diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/accessible/tests/browser/e10s/browser_events_statechange.js firefox-trunk-52.0~a1~hg20161113r322177/accessible/tests/browser/e10s/browser_events_statechange.js --- firefox-trunk-52.0~a1~hg20161110r321971/accessible/tests/browser/e10s/browser_events_statechange.js 2016-11-11 00:53:01.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/accessible/tests/browser/e10s/browser_events_statechange.js 2016-11-14 00:57:23.000000000 +0000 @@ -41,8 +41,9 @@ // Test state change let onStateChange = waitForEvent(EVENT_STATE_CHANGE, 'checkbox'); // Set checked for a checkbox. - yield ContentTask.spawn(browser, {}, () => - content.document.getElementById('checkbox').checked = true); + yield ContentTask.spawn(browser, {}, () => { + content.document.getElementById('checkbox').checked = true; + }); let event = yield onStateChange; checkStateChangeEvent(event, STATE_CHECKED, false, true); @@ -51,8 +52,9 @@ // Test extra state onStateChange = waitForEvent(EVENT_STATE_CHANGE, 'iframe'); // Set design mode on. - yield ContentTask.spawn(browser, {}, () => - content.document.getElementById('iframe').contentDocument.designMode = 'on'); + yield ContentTask.spawn(browser, {}, () => { + content.document.getElementById('iframe').contentDocument.designMode = 'on'; + }); event = yield onStateChange; checkStateChangeEvent(event, EXT_STATE_EDITABLE, true, true); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/accessible/tests/browser/e10s/browser_events_textchange.js firefox-trunk-52.0~a1~hg20161113r322177/accessible/tests/browser/e10s/browser_events_textchange.js --- firefox-trunk-52.0~a1~hg20161110r321971/accessible/tests/browser/e10s/browser_events_textchange.js 2016-11-11 00:53:01.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/accessible/tests/browser/e10s/browser_events_textchange.js 2016-11-14 00:57:23.000000000 +0000 @@ -24,8 +24,10 @@ return { id, eventType }; })); // Change text in the subtree. - yield ContentTask.spawn(browser, { id, value }, ({ id, value }) => - content.document.getElementById(id).firstChild.textContent = value); + yield ContentTask.spawn(browser, [id, value], ([contentId, contentValue]) => { + content.document.getElementById(contentId).firstChild.textContent = + contentValue; + }); let resolvedEvents = yield onEvents; events.forEach(({ isInserted, str, offset }, idx) => @@ -36,10 +38,10 @@ function* removeTextFromInput(browser, id, value, start, end) { let onTextRemoved = waitForEvent(EVENT_TEXT_REMOVED, id); // Select text and delete it. - yield ContentTask.spawn(browser, { id, start, end }, ({ id, start, end }) => { - let el = content.document.getElementById(id); + yield ContentTask.spawn(browser, [id, start, end], ([contentId, contentStart, contentEnd]) => { + let el = content.document.getElementById(contentId); el.focus(); - el.setSelectionRange(start, end); + el.setSelectionRange(contentStart, contentEnd); }); yield BrowserTestUtils.sendChar('VK_DELETE', browser); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/accessible/tests/browser/e10s/browser_treeupdate_ariadialog.js firefox-trunk-52.0~a1~hg20161113r322177/accessible/tests/browser/e10s/browser_treeupdate_ariadialog.js --- firefox-trunk-52.0~a1~hg20161110r321971/accessible/tests/browser/e10s/browser_treeupdate_ariadialog.js 2016-11-11 00:53:01.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/accessible/tests/browser/e10s/browser_treeupdate_ariadialog.js 2016-11-14 00:57:23.000000000 +0000 @@ -18,8 +18,9 @@ // Make dialog visible and update its inner content. let onShow = waitForEvent(EVENT_SHOW, 'dialog'); - yield ContentTask.spawn(browser, {}, () => - content.document.getElementById('dialog').style.display = 'block'); + yield ContentTask.spawn(browser, {}, () => { + content.document.getElementById('dialog').style.display = 'block'; + }); yield onShow; testAccessibleTree(accDoc, { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/accessible/tests/browser/e10s/browser_treeupdate_ariaowns.js firefox-trunk-52.0~a1~hg20161113r322177/accessible/tests/browser/e10s/browser_treeupdate_ariaowns.js --- firefox-trunk-52.0~a1~hg20161110r321971/accessible/tests/browser/e10s/browser_treeupdate_ariaowns.js 2016-11-11 00:53:01.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/accessible/tests/browser/e10s/browser_treeupdate_ariaowns.js 2016-11-14 00:57:23.000000000 +0000 @@ -93,11 +93,11 @@ /* ================ Append element ======================================== */ onReorder = waitForEvent(EVENT_REORDER, id); - yield ContentTask.spawn(browser, id, id => { + yield ContentTask.spawn(browser, id, contentId => { let div = content.document.createElement('div'); div.setAttribute('id', 't1_child3'); div.setAttribute('role', 'radio'); - content.document.getElementById(id).appendChild(div); + content.document.getElementById(contentId).appendChild(div); }); yield onReorder; @@ -294,9 +294,10 @@ testAccessibleTree(acc, tree); let onReorder = waitForEvent(EVENT_REORDER, id); - yield ContentTask.spawn(browser, id, id => - content.document.getElementById(id).removeChild( - content.document.getElementById('t6_span'))); + yield ContentTask.spawn(browser, id, contentId => { + content.document.getElementById(contentId).removeChild( + content.document.getElementById('t6_span')); + }); yield onReorder; tree = { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/accessible/tests/browser/e10s/browser_treeupdate_doc.js firefox-trunk-52.0~a1~hg20161113r322177/accessible/tests/browser/e10s/browser_treeupdate_doc.js --- firefox-trunk-52.0~a1~hg20161110r321971/accessible/tests/browser/e10s/browser_treeupdate_doc.js 2016-11-11 00:53:01.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/accessible/tests/browser/e10s/browser_treeupdate_doc.js 2016-11-14 00:57:23.000000000 +0000 @@ -34,12 +34,12 @@ /* ================= Write iframe document ================================ */ let reorderEventPromise = waitForEvent(EVENT_REORDER, id); - yield ContentTask.spawn(browser, id, id => { + yield ContentTask.spawn(browser, id, contentId => { let docNode = content.document.getElementById('iframe').contentDocument; let newHTMLNode = docNode.createElement('html'); let newBodyNode = docNode.createElement('body'); let newTextNode = docNode.createTextNode('New Wave'); - newBodyNode.id = id; + newBodyNode.id = contentId; newBodyNode.appendChild(newTextNode); newHTMLNode.appendChild(newBodyNode); docNode.replaceChild(newHTMLNode, docNode.documentElement); @@ -59,14 +59,14 @@ /* ================= Replace iframe HTML element ========================== */ reorderEventPromise = waitForEvent(EVENT_REORDER, id); - yield ContentTask.spawn(browser, id, id => { + yield ContentTask.spawn(browser, id, contentId => { let docNode = content.document.getElementById('iframe').contentDocument; // We can't use open/write/close outside of iframe document because of // security error. let script = docNode.createElement('script'); script.textContent = ` document.open(); - document.write('hello'); + document.write('hello'); document.close();`; docNode.body.appendChild(script); }); @@ -85,11 +85,11 @@ /* ================= Replace iframe body ================================== */ reorderEventPromise = waitForEvent(EVENT_REORDER, id); - yield ContentTask.spawn(browser, id, id => { + yield ContentTask.spawn(browser, id, contentId => { let docNode = content.document.getElementById('iframe').contentDocument; let newBodyNode = docNode.createElement('body'); let newTextNode = docNode.createTextNode('New Hello'); - newBodyNode.id = id; + newBodyNode.id = contentId; newBodyNode.appendChild(newTextNode); newBodyNode.setAttribute('role', 'button'); docNode.documentElement.replaceChild(newBodyNode, docNode.body); @@ -109,7 +109,7 @@ /* ================= Open iframe document ================================= */ reorderEventPromise = waitForEvent(EVENT_REORDER, id); - yield ContentTask.spawn(browser, id, id => { + yield ContentTask.spawn(browser, id, contentId => { // Open document. let docNode = content.document.getElementById('iframe').contentDocument; let script = docNode.createElement('script'); @@ -120,7 +120,7 @@ } window.closeMe = closeMe; document.open(); - document.write('');`; + document.write('');`; docNode.body.appendChild(script); }); yield reorderEventPromise; @@ -171,14 +171,14 @@ /* ================= Insert HTML to iframe document ======================= */ reorderEventPromise = waitForEvent(EVENT_REORDER, id); - yield ContentTask.spawn(browser, id, id => { + yield ContentTask.spawn(browser, id, contentId => { // Insert HTML element. let docNode = content.document.getElementById('iframe').contentDocument; let html = docNode.createElement('html'); let body = docNode.createElement('body'); let text = docNode.createTextNode('Haha'); body.appendChild(text); - body.id = id; + body.id = contentId; html.appendChild(body); docNode.appendChild(html); }); @@ -247,14 +247,14 @@ /* ================= Insert body to iframe document ======================= */ reorderEventPromise = waitForEvent(EVENT_REORDER, id); - yield ContentTask.spawn(browser, id, id => { + yield ContentTask.spawn(browser, id, contentId => { // Write and close document. let docNode = content.document.getElementById('iframe').contentDocument; // Insert body element. let body = docNode.createElement('body'); let text = docNode.createTextNode('Yo ho ho i butylka roma!'); body.appendChild(text); - body.id = id; + body.id = contentId; docNode.documentElement.appendChild(body); }); yield reorderEventPromise; @@ -288,13 +288,13 @@ /* ================= Replace iframe body on ARIA role body ================ */ reorderEventPromise = waitForEvent(EVENT_REORDER, id); - yield ContentTask.spawn(browser, id, id => { + yield ContentTask.spawn(browser, id, contentId => { let docNode = content.document.getElementById('iframe').contentDocument; let newBodyNode = docNode.createElement('body'); let newTextNode = docNode.createTextNode('New Hello'); newBodyNode.appendChild(newTextNode); newBodyNode.setAttribute('role', 'button'); - newBodyNode.id = id; + newBodyNode.id = contentId; docNode.documentElement.replaceChild(newBodyNode, docNode.body); }); yield reorderEventPromise; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/accessible/tests/browser/e10s/browser_treeupdate_imagemap.js firefox-trunk-52.0~a1~hg20161113r322177/accessible/tests/browser/e10s/browser_treeupdate_imagemap.js --- firefox-trunk-52.0~a1~hg20161110r321971/accessible/tests/browser/e10s/browser_treeupdate_imagemap.js 2016-11-11 00:53:01.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/accessible/tests/browser/e10s/browser_treeupdate_imagemap.js 2016-11-14 00:57:23.000000000 +0000 @@ -132,7 +132,7 @@ /* ================= Insert map =========================================== */ onReorder = waitForEvent(EVENT_REORDER, id); - yield ContentTask.spawn(browser, id, id => { + yield ContentTask.spawn(browser, id, contentId => { let map = content.document.createElement('map'); let area = content.document.createElement('area'); @@ -146,7 +146,7 @@ area.setAttribute('shape', 'rect'); map.appendChild(area); - content.document.getElementById(id).appendChild(map); + content.document.getElementById(contentId).appendChild(map); }); yield onReorder; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/accessible/tests/browser/e10s/browser_treeupdate_optgroup.js firefox-trunk-52.0~a1~hg20161113r322177/accessible/tests/browser/e10s/browser_treeupdate_optgroup.js --- firefox-trunk-52.0~a1~hg20161110r321971/accessible/tests/browser/e10s/browser_treeupdate_optgroup.js 2016-11-11 00:53:01.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/accessible/tests/browser/e10s/browser_treeupdate_optgroup.js 2016-11-14 00:57:23.000000000 +0000 @@ -15,7 +15,7 @@ // Create a combobox with grouping and 2 standalone options yield ContentTask.spawn(browser, {}, () => { let doc = content.document; - let select = doc.getElementById('select'); + let contentSelect = doc.getElementById('select'); let optGroup = doc.createElement('optgroup'); for (let i = 0; i < 2; i++) { @@ -24,13 +24,13 @@ opt.text = 'Option: Value ' + i; optGroup.appendChild(opt); } - select.add(optGroup, null); + contentSelect.add(optGroup, null); for (let i = 0; i < 2; i++) { let opt = doc.createElement('option'); - select.add(opt, null); + contentSelect.add(opt, null); } - select.firstChild.firstChild.id = 'option1Node'; + contentSelect.firstChild.firstChild.id = 'option1Node'; }); let event = yield onEvent; let option1Node = findAccessibleChildByID(event.accessible, 'option1Node'); @@ -55,8 +55,8 @@ onEvent = waitForEvent(EVENT_REORDER, 'select'); // Remove grouping from combobox yield ContentTask.spawn(browser, {}, () => { - let select = content.document.getElementById('select'); - select.removeChild(select.firstChild); + let contentSelect = content.document.getElementById('select'); + contentSelect.removeChild(contentSelect.firstChild); }); yield onEvent; @@ -75,9 +75,9 @@ onEvent = waitForEvent(EVENT_REORDER, 'select'); // Remove all options from combobox yield ContentTask.spawn(browser, {}, () => { - let select = content.document.getElementById('select'); - while (select.length) { - select.remove(0); + let contentSelect = content.document.getElementById('select'); + while (contentSelect.length) { + contentSelect.remove(0); } }); yield onEvent; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/accessible/tests/browser/e10s/browser_treeupdate_textleaf.js firefox-trunk-52.0~a1~hg20161113r322177/accessible/tests/browser/e10s/browser_treeupdate_textleaf.js --- firefox-trunk-52.0~a1~hg20161110r321971/accessible/tests/browser/e10s/browser_treeupdate_textleaf.js 2016-11-11 00:53:01.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/accessible/tests/browser/e10s/browser_treeupdate_textleaf.js 2016-11-14 00:57:23.000000000 +0000 @@ -16,8 +16,9 @@ testAccessibleTree(accessible, tree); let onReorder = waitForEvent(EVENT_REORDER, id); - yield ContentTask.spawn(browser, id, id => - content.document.getElementById(id).firstChild.textContent = ''); + yield ContentTask.spawn(browser, id, contentId => { + content.document.getElementById(contentId).firstChild.textContent = ''; + }); yield onReorder; tree = { role: role, children: [] }; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/accessible/tests/browser/.eslintrc.js firefox-trunk-52.0~a1~hg20161113r322177/accessible/tests/browser/.eslintrc.js --- firefox-trunk-52.0~a1~hg20161110r321971/accessible/tests/browser/.eslintrc.js 2016-11-11 00:53:01.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/accessible/tests/browser/.eslintrc.js 2016-11-14 00:57:23.000000000 +0000 @@ -134,11 +134,11 @@ "no-regex-spaces": "error", "no-reserved-keys": "off", "no-restricted-modules": "off", - "no-return-assign": "warn", + "no-return-assign": "error", "no-script-url": "off", "no-self-compare": "error", "no-sequences": "error", - "no-shadow": "warn", + "no-shadow": "error", "no-shadow-restricted-names": "error", "no-space-before-semi": "off", "no-spaced-func": "error", diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/accessible/tests/browser/shared-head.js firefox-trunk-52.0~a1~hg20161113r322177/accessible/tests/browser/shared-head.js --- firefox-trunk-52.0~a1~hg20161110r321971/accessible/tests/browser/shared-head.js 2016-11-11 00:53:01.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/accessible/tests/browser/shared-head.js 2016-11-14 00:57:23.000000000 +0000 @@ -114,13 +114,13 @@ } else { Logger.log(`Removing ${attr} attribute from node with id: ${id}`); } - return ContentTask.spawn(browser, { id, attr, value }, - ({ id, attr, value }) => { - let elm = content.document.getElementById(id); - if (value) { - elm.setAttribute(attr, value); + return ContentTask.spawn(browser, [id, attr, value], + ([contentId, contentAttr, contentValue]) => { + let elm = content.document.getElementById(contentId); + if (contentValue) { + elm.setAttribute(contentAttr, contentValue); } else { - elm.removeAttribute(attr); + elm.removeAttribute(contentAttr); } }); } @@ -141,13 +141,13 @@ } else { Logger.log(`Removing ${style} style from node with id: ${id}`); } - return ContentTask.spawn(browser, { id, style, value }, - ({ id, style, value }) => { - let elm = content.document.getElementById(id); - if (value) { - elm.style[style] = value; + return ContentTask.spawn(browser, [id, style, value], + ([contentId, contentStyle, contentValue]) => { + let elm = content.document.getElementById(contentId); + if (contentValue) { + elm.style[contentStyle] = contentValue; } else { - delete elm.style[style]; + delete elm.style[contentStyle]; } }); } @@ -161,8 +161,8 @@ */ function invokeFocus(browser, id) { Logger.log(`Setting focus on a node with id: ${id}`); - return ContentTask.spawn(browser, id, id => { - let elm = content.document.getElementById(id); + return ContentTask.spawn(browser, id, contentId => { + let elm = content.document.getElementById(contentId); if (elm instanceof Ci.nsIDOMNSEditableElement && elm.editor || elm instanceof Ci.nsIDOMXULTextBoxElement) { elm.selectionStart = elm.selectionEnd = elm.value.length; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/accessible/tests/mochitest/tree/test_tabbrowser.xul firefox-trunk-52.0~a1~hg20161113r322177/accessible/tests/mochitest/tree/test_tabbrowser.xul --- firefox-trunk-52.0~a1~hg20161110r321971/accessible/tests/mochitest/tree/test_tabbrowser.xul 2016-11-11 00:53:43.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/accessible/tests/mochitest/tree/test_tabbrowser.xul 2016-11-14 00:57:41.000000000 +0000 @@ -90,6 +90,15 @@ ); } else { SimpleTest.ok(true, "Testing Firefox tabbrowser UI."); + let newTabChildren = []; + if (SpecialPowers.getBoolPref("privacy.userContext.enabled")) { + newTabChildren = [ + { + role: ROLE_MENUPOPUP, + children: [] + } + ]; + } // NB: The (3) buttons are not visible, unless manually hovered, // probably due to size reduction in this test. @@ -119,7 +128,7 @@ { // xul:toolbarbutton ("Open a new tab") role: ROLE_PUSHBUTTON, - children: [] + children: newTabChildren } // "List all tabs" dropdown // XXX: This child(?) is not present in this test. diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/addon-sdk/source/test/addons/jetpack-addon.ini firefox-trunk-52.0~a1~hg20161113r322177/addon-sdk/source/test/addons/jetpack-addon.ini --- firefox-trunk-52.0~a1~hg20161110r321971/addon-sdk/source/test/addons/jetpack-addon.ini 2016-11-11 00:54:54.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/addon-sdk/source/test/addons/jetpack-addon.ini 2016-11-14 01:00:10.000000000 +0000 @@ -29,6 +29,7 @@ [page-mod-debugger-post.xpi] [page-mod-debugger-pre.xpi] [page-worker.xpi] +skip-if = true # Bug 1288619 and Bug 1288708 [places.xpi] [predefined-id-with-at.xpi] [preferences-branch.xpi] diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/browser/app/blocklist.xml firefox-trunk-52.0~a1~hg20161113r322177/browser/app/blocklist.xml --- firefox-trunk-52.0~a1~hg20161110r321971/browser/app/blocklist.xml 2016-11-11 00:58:13.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/browser/app/blocklist.xml 2016-11-14 01:02:02.000000000 +0000 @@ -1,5 +1,5 @@ - + @@ -48,10 +48,6 @@ - - - - app.update.auto @@ -61,6 +57,10 @@ + + + + @@ -137,14 +137,14 @@ - - - - + + + + @@ -351,8 +351,8 @@ - + @@ -598,10 +598,6 @@ - - - - security.csp.enable @@ -610,6 +606,10 @@ + + + + @@ -859,6 +859,10 @@ + + + + @@ -867,10 +871,6 @@ - - - - browser.startup.homepage @@ -941,10 +941,6 @@ - - - - browser.startup.homepage @@ -952,6 +948,10 @@ + + + + @@ -1160,6 +1160,10 @@ + + + + browser.startup.homepage @@ -1167,10 +1171,6 @@ - - - - @@ -1231,10 +1231,6 @@ - - - - @@ -1243,6 +1239,10 @@ + + + + @@ -1392,11 +1392,11 @@ - + - + @@ -1643,6 +1643,10 @@ + + + + browser.startup.homepage @@ -1650,10 +1654,6 @@ - - - - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/browser/app/profile/firefox.js firefox-trunk-52.0~a1~hg20161113r322177/browser/app/profile/firefox.js --- firefox-trunk-52.0~a1~hg20161110r321971/browser/app/profile/firefox.js 2016-11-11 00:58:14.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/browser/app/profile/firefox.js 2016-11-14 01:02:02.000000000 +0000 @@ -82,10 +82,16 @@ // 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. -// default=2 minutes +// 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 @@ -104,12 +110,6 @@ // the failure. pref("app.update.backgroundMaxErrors", 10); -// When |app.update.cert.requireBuiltIn| is true or not specified the -// final certificate and all certificates the connection is redirected to before -// the final certificate for the url specified in the |app.update.url| -// preference must be built-in. -pref("app.update.cert.requireBuiltIn", false); - // Whether or not app updates are enabled pref("app.update.enabled", true); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/browser/base/content/browser.css firefox-trunk-52.0~a1~hg20161113r322177/browser/base/content/browser.css --- firefox-trunk-52.0~a1~hg20161110r321971/browser/base/content/browser.css 2016-11-11 00:58:51.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/browser/base/content/browser.css 2016-11-14 01:02:25.000000000 +0000 @@ -119,6 +119,16 @@ visibility: hidden; /* temporary space to keep a tab's close button under the cursor */ } +.tabs-newtab-button > .toolbarbutton-menu-dropmarker, +#new-tab-button > .toolbarbutton-menu-dropmarker { + display: none; +} + +/* override drop marker image padding */ +.tabs-newtab-button > .toolbarbutton-icon { + margin-inline-end: 0; +} + .tabbrowser-tab { -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-tab"); } @@ -177,6 +187,7 @@ transition: transform 200ms ease-out; } +.new-tab-popup, #alltabs-popup { -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-alltabs-popup"); } @@ -472,7 +483,15 @@ list-style-image: none; } -#urlbar:not([actiontype="switchtab"]) > #urlbar-display-box { +#urlbar:not([actiontype="switchtab"]):not([actiontype="extension"]) > #urlbar-display-box { + display: none; +} + +#urlbar:not([actiontype="switchtab"]) > #urlbar-display-box > #switchtab { + display: none; +} + +#urlbar:not([actiontype="extension"]) > #urlbar-display-box > #extension { display: none; } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/browser/base/content/browser.js firefox-trunk-52.0~a1~hg20161113r322177/browser/base/content/browser.js --- firefox-trunk-52.0~a1~hg20161110r321971/browser/base/content/browser.js 2016-11-11 00:58:52.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/browser/base/content/browser.js 2016-11-14 01:02:25.000000000 +0000 @@ -268,15 +268,29 @@ * XXXmano: should this live in toolbarbutton.xml? */ function SetClickAndHoldHandlers() { - var timer; + // Bug 414797: Clone the back/forward buttons' context menu into both buttons. + let popup = document.getElementById("backForwardMenu").cloneNode(true); + popup.removeAttribute("id"); + // Prevent the back/forward buttons' context attributes from being inherited. + popup.setAttribute("context", ""); - function openMenu(aButton) { - cancelHold(aButton); - aButton.firstChild.hidden = false; - aButton.open = true; - } + let backButton = document.getElementById("back-button"); + backButton.setAttribute("type", "menu"); + backButton.appendChild(popup); + gClickAndHoldListenersOnElement.add(backButton); - function mousedownHandler(aEvent) { + let forwardButton = document.getElementById("forward-button"); + popup = popup.cloneNode(true); + forwardButton.setAttribute("type", "menu"); + forwardButton.appendChild(popup); + gClickAndHoldListenersOnElement.add(forwardButton); +} + + +const gClickAndHoldListenersOnElement = { + _timers: new Map(), + + _mousedownHandler(aEvent) { if (aEvent.button != 0 || aEvent.currentTarget.open || aEvent.currentTarget.disabled) @@ -285,32 +299,12 @@ // Prevent the menupopup from opening immediately aEvent.currentTarget.firstChild.hidden = true; - aEvent.currentTarget.addEventListener("mouseout", mouseoutHandler, false); - aEvent.currentTarget.addEventListener("mouseup", mouseupHandler, false); - timer = setTimeout(openMenu, 500, aEvent.currentTarget); - } - - function mouseoutHandler(aEvent) { - let buttonRect = aEvent.currentTarget.getBoundingClientRect(); - if (aEvent.clientX >= buttonRect.left && - aEvent.clientX <= buttonRect.right && - aEvent.clientY >= buttonRect.bottom) - openMenu(aEvent.currentTarget); - else - cancelHold(aEvent.currentTarget); - } - - function mouseupHandler(aEvent) { - cancelHold(aEvent.currentTarget); - } - - function cancelHold(aButton) { - clearTimeout(timer); - aButton.removeEventListener("mouseout", mouseoutHandler, false); - aButton.removeEventListener("mouseup", mouseupHandler, false); - } + aEvent.currentTarget.addEventListener("mouseout", this, false); + aEvent.currentTarget.addEventListener("mouseup", this, false); + this._timers.set(aEvent.currentTarget, setTimeout((b) => this._openMenu(b), 500, aEvent.currentTarget)); + }, - function clickHandler(aEvent) { + _clickHandler(aEvent) { if (aEvent.button == 0 && aEvent.target == aEvent.currentTarget && !aEvent.currentTarget.open && @@ -320,31 +314,69 @@ aEvent.ctrlKey, aEvent.altKey, aEvent.shiftKey, aEvent.metaKey, null); aEvent.currentTarget.dispatchEvent(cmdEvent); + + // This is here to cancel the XUL default event + // dom.click() triggers a command even if there is a click handler + // however this can now be prevented with preventDefault(). + aEvent.preventDefault(); } - } + }, - function _addClickAndHoldListenersOnElement(aElm) { - aElm.addEventListener("mousedown", mousedownHandler, true); - aElm.addEventListener("click", clickHandler, true); - } + _openMenu(aButton) { + this._cancelHold(aButton); + aButton.firstChild.hidden = false; + aButton.open = true; + }, - // Bug 414797: Clone the back/forward buttons' context menu into both buttons. - let popup = document.getElementById("backForwardMenu").cloneNode(true); - popup.removeAttribute("id"); - // Prevent the back/forward buttons' context attributes from being inherited. - popup.setAttribute("context", ""); + _mouseoutHandler(aEvent) { + let buttonRect = aEvent.currentTarget.getBoundingClientRect(); + if (aEvent.clientX >= buttonRect.left && + aEvent.clientX <= buttonRect.right && + aEvent.clientY >= buttonRect.bottom) + this._openMenu(aEvent.currentTarget); + else + this._cancelHold(aEvent.currentTarget); + }, - let backButton = document.getElementById("back-button"); - backButton.setAttribute("type", "menu"); - backButton.appendChild(popup); - _addClickAndHoldListenersOnElement(backButton); + _mouseupHandler(aEvent) { + this._cancelHold(aEvent.currentTarget); + }, + + _cancelHold(aButton) { + clearTimeout(this._timers.get(aButton)); + aButton.removeEventListener("mouseout", this, false); + aButton.removeEventListener("mouseup", this, false); + }, + + handleEvent(e) { + switch (e.type) { + case "mouseout": + this._mouseoutHandler(e); + break; + case "mousedown": + this._mousedownHandler(e); + break; + case "click": + this._clickHandler(e); + break; + case "mouseup": + this._mouseupHandler(e); + break; + } + }, - let forwardButton = document.getElementById("forward-button"); - popup = popup.cloneNode(true); - forwardButton.setAttribute("type", "menu"); - forwardButton.appendChild(popup); - _addClickAndHoldListenersOnElement(forwardButton); -} + remove(aButton) { + aButton.removeEventListener("mousedown", this, true); + aButton.removeEventListener("click", this, true); + }, + + add(aElm) { + this._timers.delete(aElm); + + aElm.addEventListener("mousedown", this, true); + aElm.addEventListener("click", this, true); + } +}; const gSessionHistoryObserver = { observe: function(subject, topic, data) diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/browser/base/content/browser.xul firefox-trunk-52.0~a1~hg20161113r322177/browser/base/content/browser.xul --- firefox-trunk-52.0~a1~hg20161110r321971/browser/base/content/browser.xul 2016-11-11 00:58:52.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/browser/base/content/browser.xul 2016-11-14 01:02:25.000000000 +0000 @@ -760,7 +760,8 @@ - + + + + + + + @@ -796,8 +812,10 @@ } let unifiedComplete = this.mTabBrowser._unifiedComplete; + let userContextId = this.mBrowser.getAttribute("usercontextid") || 0; if (this.mBrowser.registeredOpenURI) { - unifiedComplete.unregisterOpenPage(this.mBrowser.registeredOpenURI); + unifiedComplete.unregisterOpenPage(this.mBrowser.registeredOpenURI, + userContextId); delete this.mBrowser.registeredOpenURI; } // Tabs in private windows aren't registered as "Open" so @@ -805,7 +823,7 @@ if (!isBlankPageURL(aLocation.spec) && (!PrivateBrowsingUtils.isWindowPrivate(window) || PrivateBrowsingUtils.permanentPrivateBrowsing)) { - unifiedComplete.registerOpenPage(aLocation); + unifiedComplete.registerOpenPage(aLocation, userContextId); this.mBrowser.registeredOpenURI = aLocation; } } @@ -2575,7 +2593,8 @@ listener.destroy(); if (browser.registeredOpenURI && !aAdoptedByTab) { - this._unifiedComplete.unregisterOpenPage(browser.registeredOpenURI); + this._unifiedComplete.unregisterOpenPage(browser.registeredOpenURI, + browser.getAttribute("usercontextid") || 0); delete browser.registeredOpenURI; } @@ -2947,7 +2966,8 @@ + + + + + + @@ -5236,7 +5280,7 @@ - + + + + + document.getElementById(this.getAttribute("tabbrowser")); @@ -5283,6 +5335,53 @@ null null + + + + + + + let root = document.documentElement; @@ -6556,7 +6655,7 @@ anonid="sharing-icon" class="tab-sharing-icon-overlay" role="presentation"/> - @@ -6564,7 +6663,7 @@ xbl:inherits="value=label,crop,accesskey,fadein,pinned,selected=visuallyselected,attention" class="tab-text tab-label" role="presentation"/> - @@ -6637,6 +6736,11 @@ return this.getAttribute("muted") == "true"; + + + return this.getAttribute("blocked") == "true"; + + " /***/ }, -/* 310 */ +/* 314 */ /***/ function(module, exports) { module.exports = "" /***/ }, -/* 311 */ +/* 315 */ /***/ function(module, exports) { module.exports = "" /***/ }, -/* 312 */ +/* 316 */ /***/ function(module, exports) { module.exports = "" /***/ }, -/* 313 */ +/* 317 */ /***/ function(module, exports) { module.exports = "" /***/ }, -/* 314 */ +/* 318 */ /***/ function(module, exports) { module.exports = "" /***/ }, -/* 315 */ +/* 319 */ /***/ function(module, exports) { module.exports = "" /***/ }, -/* 316 */ +/* 320 */ /***/ function(module, exports) { module.exports = "" /***/ }, -/* 317 */ +/* 321 */ /***/ function(module, exports) { module.exports = "" /***/ }, -/* 318 */ +/* 322 */ /***/ function(module, exports) { module.exports = "" /***/ }, -/* 319 */ +/* 323 */ /***/ function(module, exports) { module.exports = "" /***/ }, -/* 320 */ +/* 324 */ /***/ function(module, exports) { module.exports = "" /***/ }, -/* 321 */ +/* 325 */ /***/ function(module, exports) { module.exports = "" /***/ }, -/* 322 */ +/* 326 */ /***/ function(module, exports) { module.exports = "" /***/ }, -/* 323 */ +/* 327 */ /***/ function(module, exports) { module.exports = "" /***/ }, -/* 324 */ +/* 328 */ /***/ function(module, exports) { module.exports = "" /***/ }, -/* 325 */ +/* 329 */ /***/ function(module, exports) { module.exports = "" /***/ }, -/* 326 */ +/* 330 */ /***/ function(module, exports) { module.exports = "" /***/ }, -/* 327 */ +/* 331 */ /***/ function(module, exports) { module.exports = "" /***/ }, -/* 328 */ +/* 332 */ /***/ function(module, exports) { module.exports = "" /***/ }, -/* 329 */ +/* 333 */ /***/ function(module, exports) { module.exports = "" /***/ }, -/* 330 */ +/* 334 */ /***/ function(module, exports) { module.exports = "" /***/ }, -/* 331 */ +/* 335 */ /***/ function(module, exports) { module.exports = "" /***/ }, -/* 332 */ +/* 336 */ /***/ function(module, exports, __webpack_require__) { var React = __webpack_require__(2); var dom = React.DOM; var PropTypes = React.PropTypes; - var Svg = __webpack_require__(306); + var Svg = __webpack_require__(310); - __webpack_require__(333); + __webpack_require__(337); function CloseButton(_ref) { var handleClick = _ref.handleClick; + var buttonClass = _ref.buttonClass; - return dom.div({ className: "close-btn", onClick: handleClick }, Svg("close")); + return dom.div({ + className: buttonClass ? "close-btn-" + buttonClass : "close-btn", + onClick: handleClick + }, Svg("close")); } CloseButton.propTypes = { @@ -34564,21 +35067,21 @@ module.exports = CloseButton; /***/ }, -/* 333 */ +/* 337 */ /***/ function(module, exports) { // removed by extract-text-webpack-plugin /***/ }, -/* 334 */, -/* 335 */ +/* 338 */, +/* 339 */ /***/ function(module, exports, __webpack_require__) { var React = __webpack_require__(2); var dom = React.DOM; var PropTypes = React.PropTypes; - var ImPropTypes = __webpack_require__(233); + var ImPropTypes = __webpack_require__(235); var _require = __webpack_require__(3); @@ -34588,20 +35091,20 @@ var connect = _require2.connect; - var _require3 = __webpack_require__(259); + var _require3 = __webpack_require__(261); var cmdString = _require3.cmdString; - var SourcesTree = React.createFactory(__webpack_require__(336)); - var actions = __webpack_require__(260); + var SourcesTree = React.createFactory(__webpack_require__(340)); + var actions = __webpack_require__(262); - var _require4 = __webpack_require__(257); + var _require4 = __webpack_require__(259); var getSelectedSource = _require4.getSelectedSource; var getSources = _require4.getSources; - __webpack_require__(394); + __webpack_require__(398); var Sources = React.createClass({ propTypes: { @@ -34625,21 +35128,21 @@ sources: getSources(state) }), dispatch => bindActionCreators(actions, dispatch))(Sources); /***/ }, -/* 336 */ +/* 340 */ /***/ function(module, exports, __webpack_require__) { var React = __webpack_require__(2); var dom = React.DOM; var PropTypes = React.PropTypes; - var classnames = __webpack_require__(209); - var ImPropTypes = __webpack_require__(233); + var classnames = __webpack_require__(211); + var ImPropTypes = __webpack_require__(235); - var _require = __webpack_require__(227); + var _require = __webpack_require__(229); var Set = _require.Set; - var _require2 = __webpack_require__(337); + var _require2 = __webpack_require__(341); var nodeHasChildren = _require2.nodeHasChildren; var createParentMap = _require2.createParentMap; @@ -34647,10 +35150,10 @@ var collapseTree = _require2.collapseTree; var createTree = _require2.createTree; - var ManagedTree = React.createFactory(__webpack_require__(390)); - var Svg = __webpack_require__(306); + var ManagedTree = React.createFactory(__webpack_require__(394)); + var Svg = __webpack_require__(310); - var _require3 = __webpack_require__(242); + var _require3 = __webpack_require__(244); var throttle = _require3.throttle; @@ -34775,7 +35278,7 @@ getRoots: () => sourceTree.contents, getKey: (item, i) => item.path, itemHeight: 30, - autoExpandDepth: 2, + autoExpandDepth: 1, onFocus: this.focusItem, renderItem: this.renderItem }); @@ -34794,38 +35297,59 @@ module.exports = SourcesTree; /***/ }, -/* 337 */ +/* 341 */ /***/ function(module, exports, __webpack_require__) { - var _require = __webpack_require__(289); + + + /** + * Utils for Sources Tree Component + * @module utils/sources-tree + */ + + var _require = __webpack_require__(293); var parse = _require.parse; - var _require2 = __webpack_require__(244); + var _require2 = __webpack_require__(246); var assert = _require2.assert; - var _require3 = __webpack_require__(275); + var _require3 = __webpack_require__(277); var isPretty = _require3.isPretty; - var merge = __webpack_require__(338); + var merge = __webpack_require__(342); var IGNORED_URLS = ["debugger eval code", "XStringBundle"]; /** * Temporary Source type to be used only within this module * TODO: Replace with real Source type definition when refactoring types + * @memberof utils/sources-tree + * @static */ - // TODO: createNode is exported so this type could be useful to other modules + /** + * TODO: createNode is exported so this type could be useful to other modules + * @memberof utils/sources-tree + * @static + */ + /** + * @memberof utils/sources-tree + * @static + */ function nodeHasChildren(item) { return Array.isArray(item.contents); } + /** + * @memberof utils/sources-tree + * @static + */ function createNode(name, path, contents) { return { name, @@ -34834,6 +35358,10 @@ }; } + /** + * @memberof utils/sources-tree + * @static + */ function createParentMap(tree) { var map = new WeakMap(); @@ -34852,6 +35380,10 @@ return map; } + /** + * @memberof utils/sources-tree + * @static + */ function getURL(source) { var url = source.get("url"); var def = { path: "", group: "" }; @@ -34911,6 +35443,10 @@ }); } + /** + * @memberof utils/sources-tree + * @static + */ function addToTree(tree, source) { var url = getURL(source); @@ -34971,6 +35507,8 @@ /** * Look at the nodes in the source tree, and determine the index of where to * insert a new node. The ordering is index -> folder -> file. + * @memberof utils/sources-tree + * @static */ function determineFileSortOrder(nodes, pathPart, isLastPart) { var partIsDir = !isLastPart || pathPart.indexOf(".") === -1; @@ -34999,6 +35537,8 @@ /** * Take an existing source tree, and return a new one with collapsed nodes. + * @memberof utils/sources-tree + * @static */ function collapseTree(node) { var depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; @@ -35020,6 +35560,10 @@ return node; } + /** + * @memberof utils/sources-tree + * @static + */ function createTree(sources) { var uncollapsedTree = createNode("root", "", []); for (var source of sources.valueSeq()) { @@ -35043,11 +35587,11 @@ }; /***/ }, -/* 338 */ +/* 342 */ /***/ function(module, exports, __webpack_require__) { - var baseMerge = __webpack_require__(339), - createAssigner = __webpack_require__(380); + var baseMerge = __webpack_require__(343), + createAssigner = __webpack_require__(384); /** * This method is like `_.assign` except that it recursively merges own and @@ -35088,15 +35632,15 @@ /***/ }, -/* 339 */ +/* 343 */ /***/ function(module, exports, __webpack_require__) { - var Stack = __webpack_require__(340), - assignMergeValue = __webpack_require__(346), - baseFor = __webpack_require__(349), - baseMergeDeep = __webpack_require__(351), - isObject = __webpack_require__(104), - keysIn = __webpack_require__(374); + var Stack = __webpack_require__(344), + assignMergeValue = __webpack_require__(350), + baseFor = __webpack_require__(353), + baseMergeDeep = __webpack_require__(355), + isObject = __webpack_require__(106), + keysIn = __webpack_require__(378); /** * The base implementation of `_.merge` without support for multiple sources. @@ -35135,15 +35679,15 @@ /***/ }, -/* 340 */ +/* 344 */ /***/ function(module, exports, __webpack_require__) { - var ListCache = __webpack_require__(115), - stackClear = __webpack_require__(341), - stackDelete = __webpack_require__(342), - stackGet = __webpack_require__(343), - stackHas = __webpack_require__(344), - stackSet = __webpack_require__(345); + var ListCache = __webpack_require__(117), + stackClear = __webpack_require__(345), + stackDelete = __webpack_require__(346), + stackGet = __webpack_require__(347), + stackHas = __webpack_require__(348), + stackSet = __webpack_require__(349); /** * Creates a stack cache object to store key-value pairs. @@ -35168,10 +35712,10 @@ /***/ }, -/* 341 */ +/* 345 */ /***/ function(module, exports, __webpack_require__) { - var ListCache = __webpack_require__(115); + var ListCache = __webpack_require__(117); /** * Removes all key-value entries from the stack. @@ -35189,7 +35733,7 @@ /***/ }, -/* 342 */ +/* 346 */ /***/ function(module, exports) { /** @@ -35213,7 +35757,7 @@ /***/ }, -/* 343 */ +/* 347 */ /***/ function(module, exports) { /** @@ -35233,7 +35777,7 @@ /***/ }, -/* 344 */ +/* 348 */ /***/ function(module, exports) { /** @@ -35253,12 +35797,12 @@ /***/ }, -/* 345 */ +/* 349 */ /***/ function(module, exports, __webpack_require__) { - var ListCache = __webpack_require__(115), - Map = __webpack_require__(123), - MapCache = __webpack_require__(96); + var ListCache = __webpack_require__(117), + Map = __webpack_require__(125), + MapCache = __webpack_require__(98); /** Used as the size to enable large array optimizations. */ var LARGE_ARRAY_SIZE = 200; @@ -35293,11 +35837,11 @@ /***/ }, -/* 346 */ +/* 350 */ /***/ function(module, exports, __webpack_require__) { - var baseAssignValue = __webpack_require__(347), - eq = __webpack_require__(119); + var baseAssignValue = __webpack_require__(351), + eq = __webpack_require__(121); /** * This function is like `assignValue` except that it doesn't assign @@ -35319,10 +35863,10 @@ /***/ }, -/* 347 */ +/* 351 */ /***/ function(module, exports, __webpack_require__) { - var defineProperty = __webpack_require__(348); + var defineProperty = __webpack_require__(352); /** * The base implementation of `assignValue` and `assignMergeValue` without @@ -35350,10 +35894,10 @@ /***/ }, -/* 348 */ +/* 352 */ /***/ function(module, exports, __webpack_require__) { - var getNative = __webpack_require__(101); + var getNative = __webpack_require__(103); var defineProperty = (function() { try { @@ -35367,10 +35911,10 @@ /***/ }, -/* 349 */ +/* 353 */ /***/ function(module, exports, __webpack_require__) { - var createBaseFor = __webpack_require__(350); + var createBaseFor = __webpack_require__(354); /** * The base implementation of `baseForOwn` which iterates over `object` @@ -35389,7 +35933,7 @@ /***/ }, -/* 350 */ +/* 354 */ /***/ function(module, exports) { /** @@ -35420,23 +35964,23 @@ /***/ }, -/* 351 */ +/* 355 */ /***/ function(module, exports, __webpack_require__) { - var assignMergeValue = __webpack_require__(346), - cloneBuffer = __webpack_require__(352), - cloneTypedArray = __webpack_require__(353), - copyArray = __webpack_require__(356), - initCloneObject = __webpack_require__(357), - isArguments = __webpack_require__(360), - isArray = __webpack_require__(92), - isArrayLikeObject = __webpack_require__(362), - isBuffer = __webpack_require__(365), - isFunction = __webpack_require__(103), - isObject = __webpack_require__(104), + var assignMergeValue = __webpack_require__(350), + cloneBuffer = __webpack_require__(356), + cloneTypedArray = __webpack_require__(357), + copyArray = __webpack_require__(360), + initCloneObject = __webpack_require__(361), + isArguments = __webpack_require__(364), + isArray = __webpack_require__(94), + isArrayLikeObject = __webpack_require__(366), + isBuffer = __webpack_require__(369), + isFunction = __webpack_require__(105), + isObject = __webpack_require__(106), isPlainObject = __webpack_require__(5), - isTypedArray = __webpack_require__(367), - toPlainObject = __webpack_require__(371); + isTypedArray = __webpack_require__(371), + toPlainObject = __webpack_require__(375); /** * A specialized version of `baseMerge` for arrays and objects which performs @@ -35519,10 +36063,10 @@ /***/ }, -/* 352 */ +/* 356 */ /***/ function(module, exports, __webpack_require__) { - /* WEBPACK VAR INJECTION */(function(module) {var root = __webpack_require__(107); + /* WEBPACK VAR INJECTION */(function(module) {var root = __webpack_require__(109); /** Detect free variable `exports`. */ var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; @@ -35561,10 +36105,10 @@ /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(77)(module))) /***/ }, -/* 353 */ +/* 357 */ /***/ function(module, exports, __webpack_require__) { - var cloneArrayBuffer = __webpack_require__(354); + var cloneArrayBuffer = __webpack_require__(358); /** * Creates a clone of `typedArray`. @@ -35583,10 +36127,10 @@ /***/ }, -/* 354 */ +/* 358 */ /***/ function(module, exports, __webpack_require__) { - var Uint8Array = __webpack_require__(355); + var Uint8Array = __webpack_require__(359); /** * Creates a clone of `arrayBuffer`. @@ -35605,10 +36149,10 @@ /***/ }, -/* 355 */ +/* 359 */ /***/ function(module, exports, __webpack_require__) { - var root = __webpack_require__(107); + var root = __webpack_require__(109); /** Built-in value references. */ var Uint8Array = root.Uint8Array; @@ -35617,7 +36161,7 @@ /***/ }, -/* 356 */ +/* 360 */ /***/ function(module, exports) { /** @@ -35643,12 +36187,12 @@ /***/ }, -/* 357 */ +/* 361 */ /***/ function(module, exports, __webpack_require__) { - var baseCreate = __webpack_require__(358), + var baseCreate = __webpack_require__(362), getPrototype = __webpack_require__(6), - isPrototype = __webpack_require__(359); + isPrototype = __webpack_require__(363); /** * Initializes an object clone. @@ -35667,10 +36211,10 @@ /***/ }, -/* 358 */ +/* 362 */ /***/ function(module, exports, __webpack_require__) { - var isObject = __webpack_require__(104); + var isObject = __webpack_require__(106); /** Built-in value references. */ var objectCreate = Object.create; @@ -35703,7 +36247,7 @@ /***/ }, -/* 359 */ +/* 363 */ /***/ function(module, exports) { /** Used for built-in method references. */ @@ -35727,10 +36271,10 @@ /***/ }, -/* 360 */ +/* 364 */ /***/ function(module, exports, __webpack_require__) { - var baseIsArguments = __webpack_require__(361), + var baseIsArguments = __webpack_require__(365), isObjectLike = __webpack_require__(8); /** Used for built-in method references. */ @@ -35769,7 +36313,7 @@ /***/ }, -/* 361 */ +/* 365 */ /***/ function(module, exports, __webpack_require__) { var isObjectLike = __webpack_require__(8); @@ -35802,10 +36346,10 @@ /***/ }, -/* 362 */ +/* 366 */ /***/ function(module, exports, __webpack_require__) { - var isArrayLike = __webpack_require__(363), + var isArrayLike = __webpack_require__(367), isObjectLike = __webpack_require__(8); /** @@ -35841,11 +36385,11 @@ /***/ }, -/* 363 */ +/* 367 */ /***/ function(module, exports, __webpack_require__) { - var isFunction = __webpack_require__(103), - isLength = __webpack_require__(364); + var isFunction = __webpack_require__(105), + isLength = __webpack_require__(368); /** * Checks if `value` is array-like. A value is considered array-like if it's @@ -35880,7 +36424,7 @@ /***/ }, -/* 364 */ +/* 368 */ /***/ function(module, exports) { /** Used as references for various `Number` constants. */ @@ -35921,11 +36465,11 @@ /***/ }, -/* 365 */ +/* 369 */ /***/ function(module, exports, __webpack_require__) { - /* WEBPACK VAR INJECTION */(function(module) {var root = __webpack_require__(107), - stubFalse = __webpack_require__(366); + /* WEBPACK VAR INJECTION */(function(module) {var root = __webpack_require__(109), + stubFalse = __webpack_require__(370); /** Detect free variable `exports`. */ var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; @@ -35966,7 +36510,7 @@ /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(77)(module))) /***/ }, -/* 366 */ +/* 370 */ /***/ function(module, exports) { /** @@ -35990,12 +36534,12 @@ /***/ }, -/* 367 */ +/* 371 */ /***/ function(module, exports, __webpack_require__) { - var baseIsTypedArray = __webpack_require__(368), - baseUnary = __webpack_require__(369), - nodeUtil = __webpack_require__(370); + var baseIsTypedArray = __webpack_require__(372), + baseUnary = __webpack_require__(373), + nodeUtil = __webpack_require__(374); /* Node.js helper references. */ var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; @@ -36023,10 +36567,10 @@ /***/ }, -/* 368 */ +/* 372 */ /***/ function(module, exports, __webpack_require__) { - var isLength = __webpack_require__(364), + var isLength = __webpack_require__(368), isObjectLike = __webpack_require__(8); /** `Object#toString` result references. */ @@ -36098,7 +36642,7 @@ /***/ }, -/* 369 */ +/* 373 */ /***/ function(module, exports) { /** @@ -36118,10 +36662,10 @@ /***/ }, -/* 370 */ +/* 374 */ /***/ function(module, exports, __webpack_require__) { - /* WEBPACK VAR INJECTION */(function(module) {var freeGlobal = __webpack_require__(108); + /* WEBPACK VAR INJECTION */(function(module) {var freeGlobal = __webpack_require__(110); /** Detect free variable `exports`. */ var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; @@ -36147,11 +36691,11 @@ /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(77)(module))) /***/ }, -/* 371 */ +/* 375 */ /***/ function(module, exports, __webpack_require__) { - var copyObject = __webpack_require__(372), - keysIn = __webpack_require__(374); + var copyObject = __webpack_require__(376), + keysIn = __webpack_require__(378); /** * Converts `value` to a plain object flattening inherited enumerable string @@ -36185,11 +36729,11 @@ /***/ }, -/* 372 */ +/* 376 */ /***/ function(module, exports, __webpack_require__) { - var assignValue = __webpack_require__(373), - baseAssignValue = __webpack_require__(347); + var assignValue = __webpack_require__(377), + baseAssignValue = __webpack_require__(351); /** * Copies properties of `source` to `object`. @@ -36231,11 +36775,11 @@ /***/ }, -/* 373 */ +/* 377 */ /***/ function(module, exports, __webpack_require__) { - var baseAssignValue = __webpack_require__(347), - eq = __webpack_require__(119); + var baseAssignValue = __webpack_require__(351), + eq = __webpack_require__(121); /** Used for built-in method references. */ var objectProto = Object.prototype; @@ -36265,12 +36809,12 @@ /***/ }, -/* 374 */ +/* 378 */ /***/ function(module, exports, __webpack_require__) { - var arrayLikeKeys = __webpack_require__(375), - baseKeysIn = __webpack_require__(378), - isArrayLike = __webpack_require__(363); + var arrayLikeKeys = __webpack_require__(379), + baseKeysIn = __webpack_require__(382), + isArrayLike = __webpack_require__(367); /** * Creates an array of the own and inherited enumerable property names of `object`. @@ -36303,15 +36847,15 @@ /***/ }, -/* 375 */ +/* 379 */ /***/ function(module, exports, __webpack_require__) { - var baseTimes = __webpack_require__(376), - isArguments = __webpack_require__(360), - isArray = __webpack_require__(92), - isBuffer = __webpack_require__(365), - isIndex = __webpack_require__(377), - isTypedArray = __webpack_require__(367); + var baseTimes = __webpack_require__(380), + isArguments = __webpack_require__(364), + isArray = __webpack_require__(94), + isBuffer = __webpack_require__(369), + isIndex = __webpack_require__(381), + isTypedArray = __webpack_require__(371); /** Used for built-in method references. */ var objectProto = Object.prototype; @@ -36358,7 +36902,7 @@ /***/ }, -/* 376 */ +/* 380 */ /***/ function(module, exports) { /** @@ -36384,7 +36928,7 @@ /***/ }, -/* 377 */ +/* 381 */ /***/ function(module, exports) { /** Used as references for various `Number` constants. */ @@ -36412,12 +36956,12 @@ /***/ }, -/* 378 */ +/* 382 */ /***/ function(module, exports, __webpack_require__) { - var isObject = __webpack_require__(104), - isPrototype = __webpack_require__(359), - nativeKeysIn = __webpack_require__(379); + var isObject = __webpack_require__(106), + isPrototype = __webpack_require__(363), + nativeKeysIn = __webpack_require__(383); /** Used for built-in method references. */ var objectProto = Object.prototype; @@ -36451,7 +36995,7 @@ /***/ }, -/* 379 */ +/* 383 */ /***/ function(module, exports) { /** @@ -36477,11 +37021,11 @@ /***/ }, -/* 380 */ +/* 384 */ /***/ function(module, exports, __webpack_require__) { - var baseRest = __webpack_require__(381), - isIterateeCall = __webpack_require__(389); + var baseRest = __webpack_require__(385), + isIterateeCall = __webpack_require__(393); /** * Creates a function like `_.assign`. @@ -36520,12 +37064,12 @@ /***/ }, -/* 381 */ +/* 385 */ /***/ function(module, exports, __webpack_require__) { - var identity = __webpack_require__(382), - overRest = __webpack_require__(383), - setToString = __webpack_require__(385); + var identity = __webpack_require__(386), + overRest = __webpack_require__(387), + setToString = __webpack_require__(389); /** * The base implementation of `_.rest` which doesn't validate or coerce arguments. @@ -36543,7 +37087,7 @@ /***/ }, -/* 382 */ +/* 386 */ /***/ function(module, exports) { /** @@ -36570,10 +37114,10 @@ /***/ }, -/* 383 */ +/* 387 */ /***/ function(module, exports, __webpack_require__) { - var apply = __webpack_require__(384); + var apply = __webpack_require__(388); /* Built-in method references for those with the same name as other `lodash` methods. */ var nativeMax = Math.max; @@ -36612,7 +37156,7 @@ /***/ }, -/* 384 */ +/* 388 */ /***/ function(module, exports) { /** @@ -36639,11 +37183,11 @@ /***/ }, -/* 385 */ +/* 389 */ /***/ function(module, exports, __webpack_require__) { - var baseSetToString = __webpack_require__(386), - shortOut = __webpack_require__(388); + var baseSetToString = __webpack_require__(390), + shortOut = __webpack_require__(392); /** * Sets the `toString` method of `func` to return `string`. @@ -36659,12 +37203,12 @@ /***/ }, -/* 386 */ +/* 390 */ /***/ function(module, exports, __webpack_require__) { - var constant = __webpack_require__(387), - defineProperty = __webpack_require__(348), - identity = __webpack_require__(382); + var constant = __webpack_require__(391), + defineProperty = __webpack_require__(352), + identity = __webpack_require__(386); /** * The base implementation of `setToString` without support for hot loop shorting. @@ -36687,7 +37231,7 @@ /***/ }, -/* 387 */ +/* 391 */ /***/ function(module, exports) { /** @@ -36719,7 +37263,7 @@ /***/ }, -/* 388 */ +/* 392 */ /***/ function(module, exports) { /** Used to detect hot functions by number of calls within a span of milliseconds. */ @@ -36762,13 +37306,13 @@ /***/ }, -/* 389 */ +/* 393 */ /***/ function(module, exports, __webpack_require__) { - var eq = __webpack_require__(119), - isArrayLike = __webpack_require__(363), - isIndex = __webpack_require__(377), - isObject = __webpack_require__(104); + var eq = __webpack_require__(121), + isArrayLike = __webpack_require__(367), + isIndex = __webpack_require__(381), + isObject = __webpack_require__(106); /** * Checks if the given arguments are from an iteratee call. @@ -36798,12 +37342,12 @@ /***/ }, -/* 390 */ +/* 394 */ /***/ function(module, exports, __webpack_require__) { var React = __webpack_require__(2); - var Tree = React.createFactory(__webpack_require__(391)); - __webpack_require__(392); + var Tree = React.createFactory(__webpack_require__(395)); + __webpack_require__(396); var ManagedTree = React.createClass({ propTypes: Tree.propTypes, @@ -36878,7 +37422,7 @@ module.exports = ManagedTree; /***/ }, -/* 391 */ +/* 395 */ /***/ function(module, exports, __webpack_require__) { /* This Source Code Form is subject to the terms of the Mozilla Public @@ -37480,21 +38024,21 @@ /***/ }, -/* 392 */ +/* 396 */ /***/ function(module, exports) { // removed by extract-text-webpack-plugin /***/ }, -/* 393 */, -/* 394 */ +/* 397 */, +/* 398 */ /***/ function(module, exports) { // removed by extract-text-webpack-plugin /***/ }, -/* 395 */, -/* 396 */ +/* 399 */, +/* 400 */ /***/ function(module, exports, __webpack_require__) { var React = __webpack_require__(2); @@ -37504,7 +38048,7 @@ var ReactDOM = __webpack_require__(16); - var ImPropTypes = __webpack_require__(233); + var ImPropTypes = __webpack_require__(235); var _require = __webpack_require__(3); @@ -37514,44 +38058,56 @@ var connect = _require2.connect; - var SourceEditor = __webpack_require__(397); - var SourceFooter = createFactory(__webpack_require__(398)); - var EditorSearchBar = createFactory(__webpack_require__(402)); + var SourceEditor = __webpack_require__(401); + var SourceFooter = createFactory(__webpack_require__(402)); + var EditorSearchBar = createFactory(__webpack_require__(406)); - var _require3 = __webpack_require__(18); + var _require3 = __webpack_require__(411); - var debugGlobal = _require3.debugGlobal; + var renderConditionalPanel = _require3.renderConditionalPanel; - var _require4 = __webpack_require__(257); + var _require4 = __webpack_require__(18); - var getSourceText = _require4.getSourceText; - var getBreakpointsForSource = _require4.getBreakpointsForSource; - var getSelectedLocation = _require4.getSelectedLocation; - var getSelectedFrame = _require4.getSelectedFrame; - var getSelectedSource = _require4.getSelectedSource; + var debugGlobal = _require4.debugGlobal; + + var _require5 = __webpack_require__(259); - var _require5 = __webpack_require__(253); + var getSourceText = _require5.getSourceText; + var getBreakpointsForSource = _require5.getBreakpointsForSource; + var getSelectedLocation = _require5.getSelectedLocation; + var getSelectedFrame = _require5.getSelectedFrame; + var getSelectedSource = _require5.getSelectedSource; - var makeLocationId = _require5.makeLocationId; + var _require6 = __webpack_require__(255); - var actions = __webpack_require__(260); - var Breakpoint = React.createFactory(__webpack_require__(406)); + var makeLocationId = _require6.makeLocationId; - var _require6 = __webpack_require__(277); + var actions = __webpack_require__(262); + var Breakpoint = React.createFactory(__webpack_require__(412)); - var getDocument = _require6.getDocument; - var setDocument = _require6.setDocument; + var _require7 = __webpack_require__(279); - var _require7 = __webpack_require__(399); + var getDocument = _require7.getDocument; + var setDocument = _require7.setDocument; - var shouldShowFooter = _require7.shouldShowFooter; + var _require8 = __webpack_require__(403); - var _require8 = __webpack_require__(87); + var shouldShowFooter = _require8.shouldShowFooter; - var isEnabled = _require8.isEnabled; + var _require9 = __webpack_require__(89); + var isFirefox = _require9.isFirefox; - __webpack_require__(407); + var _require10 = __webpack_require__(413); + + var showMenu = _require10.showMenu; + + var _require11 = __webpack_require__(89); + + var isEnabled = _require11.isEnabled; + + + __webpack_require__(414); function isTextForSource(sourceText) { return !sourceText.get("loading") && !sourceText.get("error"); @@ -37563,29 +38119,8 @@ }); } - function renderConditionalBreakpointPanel(_ref) { - var location = _ref.location; - var setBreakpointCondition = _ref.setBreakpointCondition; - var condition = _ref.condition; - var closePanel = _ref.closePanel; - - function onKey(e) { - if (e.key != "Enter") { - return; - } - - setBreakpointCondition(location, e.target.value); - closePanel(); - } - - var panel = document.createElement("div"); - ReactDOM.render(dom.div({ className: "conditional-breakpoint-panel" }, dom.input({ - defaultValue: condition, - placeholder: "This breakpoint will pause when the expression is true", - onKeyPress: onKey - })), panel); - - return panel; + function getTextForLine(codeMirror, line) { + return codeMirror.getLine(line - 1).trim(); } /** @@ -37616,37 +38151,69 @@ displayName: "Editor", onGutterClick(cm, line, gutter, ev) { + // ignore right clicks in the gutter + if (ev.which === 3) { + return; + } + + if (this.isCbPanelOpen()) { + return this.closeConditionalPanel(line); + } + + this.toggleBreakpoint(line); + }, + + onGutterContextMenu(event) { + event.preventDefault(); + var line = this.editor.codeMirror.lineAtHeight(event.clientY); var bp = breakpointAtLine(this.props.breakpoints, line); + this.showGutterMenu(event, line, bp); + }, + + showConditionalPanel(line) { + if (this.isCbPanelOpen()) { + return; + } + var _props = this.props; var sourceId = _props.selectedLocation.sourceId; var setBreakpointCondition = _props.setBreakpointCondition; + var breakpoints = _props.breakpoints; + var bp = breakpointAtLine(breakpoints, line); var location = { sourceId, line: line + 1 }; - var closePanel = () => this.cbPanels[line].clear(); + var condition = bp ? bp.condition : ""; - if (isEnabled("conditionalBreakpoints") && bp && ev.metaKey) { - if (!this.state.isCondBPOpen) { - var condition = bp.condition; + var setBreakpoint = value => { + setBreakpointCondition(location, { + condition: value, + getTextForLine: l => getTextForLine(this.editor.codeMirror, l) + }); + }; - var panel = renderConditionalBreakpointPanel({ - location, setBreakpointCondition, condition, closePanel - }); + var panel = renderConditionalPanel({ + condition, + setBreakpoint, + closePanel: this.closeConditionalPanel + }); - this.cbPanels[line] = this.editor.codeMirror.addLineWidget(line, panel); - this.setState({ isCondBPOpen: true, openPanel: this.cbPanels[line] }); - } else { - delete this.cbPanels[line]; - this.state.openPanel.clear(); - this.replaceState({ isCondBPOpen: false }); - } - return; - } + this.cbPanel = this.editor.codeMirror.addLineWidget(line, panel); + this.cbPanel.node.querySelector("input").focus(); + }, + + closeConditionalPanel() { + this.cbPanel.clear(); + this.cbPanel = null; + }, - this.toggleBreakpoint(bp, line); + isCbPanelOpen() { + return !!this.cbPanel; }, - toggleBreakpoint(bp, line) { + toggleBreakpoint(line) { + var bp = breakpointAtLine(this.props.breakpoints, line); + if (bp && bp.loading) { return; } @@ -37662,7 +38229,7 @@ // Pass in a function to get line text because the breakpoint // may slide and it needs to compute the value at the new // line. - { getTextForLine: l => this.editor.codeMirror.getLine(l - 1).trim() }); + { getTextForLine: l => getTextForLine(this.editor.codeMirror, l) }); } }, @@ -37734,13 +38301,43 @@ } }, - getInitialState() { - return { isCondBPOpen: false }; + showGutterMenu(e, line, bp) { + var bpLabel = void 0; + var cbLabel = void 0; + if (!bp) { + bpLabel = L10N.getStr("editor.addBreakpoint"); + cbLabel = L10N.getStr("editor.addConditionalBreakpoint"); + } else { + bpLabel = L10N.getStr("editor.removeBreakpoint"); + cbLabel = L10N.getStr("editor.editBreakpoint"); + } + + var toggleBreakpoint = { + id: "node-menu-breakpoint", + label: bpLabel, + accesskey: "B", + disabled: false, + click: () => { + this.toggleBreakpoint(line); + if (this.isCbPanelOpen()) { + this.closeConditionalPanel(); + } + } + }; + + var conditionalBreakpoint = { + id: "node-menu-conditional-breakpoint", + label: cbLabel, + accesskey: "C", + disabled: false, + click: () => this.showConditionalPanel(line) + }; + + showMenu(e, [toggleBreakpoint, conditionalBreakpoint]); }, componentDidMount() { - var extraKeys = isEnabled("search") ? { "Cmd-F": () => {} } : {}; - this.cbPanels = {}; + this.cbPanel = null; this.editor = new SourceEditor({ mode: "javascript", @@ -37753,12 +38350,24 @@ enableCodeFolding: false, gutters: ["breakpoints"], value: " ", - extraKeys + extraKeys: {} }); + // disables the default search shortcuts + if (isEnabled("editorSearch")) { + this.editor._initShortcuts = () => {}; + } + this.editor.appendToLocalElement(ReactDOM.findDOMNode(this).querySelector(".editor-mount")); this.editor.codeMirror.on("gutterClick", this.onGutterClick); + + if (!isFirefox()) { + this.editor.codeMirror.on("gutterContextMenu", (cm, line, eventName, event) => this.onGutterContextMenu(event)); + } else { + this.editor.codeMirror.getWrapperElement().addEventListener("contextmenu", event => this.onGutterContextMenu(event), false); + } + resizeBreakpointGutter(this.editor.codeMirror); debugGlobal("cm", this.editor.codeMirror); @@ -37905,13 +38514,13 @@ }, dispatch => bindActionCreators(actions, dispatch))(Editor); /***/ }, -/* 397 */ +/* 401 */ /***/ function(module, exports) { module.exports = devtoolsRequire("devtools/client/sourceeditor/editor"); /***/ }, -/* 398 */ +/* 402 */ /***/ function(module, exports, __webpack_require__) { var React = __webpack_require__(2); @@ -37926,29 +38535,29 @@ var bindActionCreators = _require2.bindActionCreators; - var actions = __webpack_require__(260); + var actions = __webpack_require__(262); - var _require3 = __webpack_require__(257); + var _require3 = __webpack_require__(259); var getSelectedSource = _require3.getSelectedSource; var getSourceText = _require3.getSourceText; var getPrettySource = _require3.getPrettySource; - var Svg = __webpack_require__(306); - var ImPropTypes = __webpack_require__(233); - var classnames = __webpack_require__(209); + var Svg = __webpack_require__(310); + var ImPropTypes = __webpack_require__(235); + var classnames = __webpack_require__(211); - var _require4 = __webpack_require__(275); + var _require4 = __webpack_require__(277); var isPretty = _require4.isPretty; - var _require5 = __webpack_require__(399); + var _require5 = __webpack_require__(403); var shouldShowFooter = _require5.shouldShowFooter; var shouldShowPrettyPrint = _require5.shouldShowPrettyPrint; - __webpack_require__(400); + __webpack_require__(404); function debugBtn(onClick, type) { var className = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "active"; @@ -38014,18 +38623,18 @@ }, dispatch => bindActionCreators(actions, dispatch))(SourceFooter); /***/ }, -/* 399 */ +/* 403 */ /***/ function(module, exports, __webpack_require__) { - var _require = __webpack_require__(275); + var _require = __webpack_require__(277); var isPretty = _require.isPretty; - var _require2 = __webpack_require__(87); + var _require2 = __webpack_require__(89); var isEnabled = _require2.isEnabled; - var _require3 = __webpack_require__(262); + var _require3 = __webpack_require__(264); var isOriginalId = _require3.isOriginalId; @@ -38056,14 +38665,14 @@ }; /***/ }, -/* 400 */ +/* 404 */ /***/ function(module, exports) { // removed by extract-text-webpack-plugin /***/ }, -/* 401 */, -/* 402 */ +/* 405 */, +/* 406 */ /***/ function(module, exports, __webpack_require__) { var React = __webpack_require__(2); @@ -38074,24 +38683,32 @@ var findDOMNode = _require.findDOMNode; - var Svg = __webpack_require__(306); + var Svg = __webpack_require__(310); - var _require2 = __webpack_require__(87); + var _require2 = __webpack_require__(407); - var isEnabled = _require2.isEnabled; + var find = _require2.find; + var findNext = _require2.findNext; + var findPrev = _require2.findPrev; - var _require3 = __webpack_require__(403); + var classnames = __webpack_require__(211); - var find = _require3.find; - var findNext = _require3.findNext; - var findPrev = _require3.findPrev; + var _require3 = __webpack_require__(408); - var classnames = __webpack_require__(209); + var debounce = _require3.debounce; + var escapeRegExp = _require3.escapeRegExp; - __webpack_require__(404); + var CloseButton = __webpack_require__(336); + + var _require4 = __webpack_require__(89); + + var isEnabled = _require4.isEnabled; + + + __webpack_require__(409); function countMatches(query, text) { - var re = new RegExp(query, "g"); + var re = new RegExp(escapeRegExp(query), "g"); var match = text.match(re); return match ? match.length : 0; } @@ -38120,7 +38737,7 @@ componentWillUnmount() { var shortcuts = this.context.shortcuts; - if (isEnabled("search")) { + if (isEnabled("editorSearch")) { shortcuts.off("CmdOrCtrl+F", this.toggleSearch); shortcuts.off("Escape", this.onEscape); } @@ -38128,12 +38745,18 @@ componentDidMount() { var shortcuts = this.context.shortcuts; - if (isEnabled("search")) { + if (isEnabled("editorSearch")) { shortcuts.on("CmdOrCtrl+F", this.toggleSearch); shortcuts.on("Escape", this.onEscape); } }, + componentWillReceiveProps() { + var shortcuts = this.context.shortcuts; + shortcuts.on("CmdOrCtrl+Shift+G", (_, e) => this.traverseResultsPrev(e)); + shortcuts.on("CmdOrCtrl+G", (_, e) => this.traverseResultsNext(e)); + }, + componentDidUpdate() { if (this.searchInput()) { this.searchInput().focus(); @@ -38141,8 +38764,13 @@ }, onEscape(shortcut, e) { + this.closeSearch(e); + }, + + closeSearch(e) { if (this.state.enabled) { this.setState({ enabled: false }); + e.stopPropagation(); e.preventDefault(); } }, @@ -38155,7 +38783,9 @@ if (this.state.enabled) { var node = this.searchInput(); - node.setSelectionRange(0, node.value.length); + if (node) { + node.setSelectionRange(0, node.value.length); + } } }, @@ -38165,15 +38795,17 @@ onChange(e) { var query = e.target.value; - var ed = this.props.editor; - var ctx = { ed, cm: ed.codeMirror }; - find(ctx, query); var count = countMatches(query, this.props.sourceText.get("text")); this.setState({ query, count, index: 0 }); + + this.search(query); }, - onKeyUp(e) { + traverseResultsPrev(e) { + e.stopPropagation(); + e.preventDefault(); + var ed = this.props.editor; var ctx = { ed, cm: ed.codeMirror }; var _state = this.state; @@ -38182,191 +38814,17339 @@ var count = _state.count; - if (e.key != "Enter") { - return; - } - - if (e.shiftKey) { - findPrev(ctx, query); - var nextIndex = index == 0 ? count - 1 : index - 1; - this.setState({ index: nextIndex }); - } else { - findNext(ctx, query); - var _nextIndex = index == count - 1 ? 0 : index + 1; - this.setState({ index: _nextIndex }); - } + findPrev(ctx, query); + var nextIndex = index == 0 ? count - 1 : index - 1; + this.setState({ index: nextIndex }); }, - renderSummary() { - var _state2 = this.state; - var count = _state2.count; - var index = _state2.index; - var query = _state2.query; + traverseResultsNext(e) { + e.stopPropagation(); + e.preventDefault(); + var ed = this.props.editor; + var ctx = { ed, cm: ed.codeMirror }; + var _state2 = this.state; + var query = _state2.query; + var index = _state2.index; + var count = _state2.count; + + + findNext(ctx, query); + var nextIndex = index == count - 1 ? 0 : index + 1; + this.setState({ index: nextIndex }); + }, + + onKeyUp(e) { + if (e.key != "Enter") { + return; + } + + if (e.shiftKey) { + this.traverseResultsPrev(e); + } else { + this.traverseResultsNext(e); + } + }, + + search: debounce(function (query) { + var ed = this.props.editor; + var ctx = { ed, cm: ed.codeMirror }; + + find(ctx, query); + }, 100), + + renderSummary() { + var _state3 = this.state; + var count = _state3.count; + var index = _state3.index; + var query = _state3.query; + + + if (query.trim() == "") { + return dom.div({}); + } else if (count == 0) { + return dom.div({ className: "summary" }, L10N.getStr("editor.noResults")); + } + + return dom.div({ className: "summary" }, L10N.getFormatStr("editor.searchResults", index + 1, count)); + }, + + renderSvg() { + var _state4 = this.state; + var count = _state4.count; + var query = _state4.query; + + + if (count == 0 && query.trim() != "") { + return Svg("sad-face"); + } + + return Svg("magnifying-glass"); + }, + + render() { + if (!this.state.enabled) { + return dom.div(); + } + + var _state5 = this.state; + var count = _state5.count; + var query = _state5.query; + + + return dom.div({ className: "search-bar" }, this.renderSvg(), dom.input({ + className: classnames({ + empty: count == 0 && query.trim() != "" + }), + onChange: this.onChange, + onKeyUp: this.onKeyUp, + placeholder: "Search in file...", + value: this.state.query, + spellCheck: false + }), this.renderSummary(), CloseButton({ + handleClick: this.closeSearch, + buttonClass: "big" + })); + } + }); + + module.exports = EditorSearchBar; + +/***/ }, +/* 407 */ +/***/ function(module, exports, __webpack_require__) { + + var _require = __webpack_require__(408); + + var escapeRegExp = _require.escapeRegExp; + /** + * These functions implement search within the debugger. Since + * search in the debugger is different from other components, + * we can't use search.js CodeMirror addon. This is a slightly + * modified version of that addon. Depends on searchcursor.js. + * @module utils/source-search + */ + + /** + * @memberof utils/source-search + * @static + */ + + function SearchState() { + this.posFrom = this.posTo = this.query = null; + this.overlay = null; + } + + /** + * @memberof utils/source-search + * @static + */ + function getSearchState(cm) { + return cm.state.search || (cm.state.search = new SearchState()); + } + + /** + * @memberof utils/source-search + * @static + */ + function getSearchCursor(cm, query, pos) { + // If the query string is all lowercase, do a case insensitive search. + return cm.getSearchCursor(query, pos, typeof query == "string" && query == query.toLowerCase()); + } + + /** + * Ignore doing outline matches for less than 3 whitespaces + * + * @memberof utils/source-search + * @static + */ + function ignoreWhiteSpace(str) { + return (/^\s{0,2}$/.test(str) ? "(?!\s*.*)" : str + ); + } + + /** + * This returns a mode object used by CoeMirror's addOverlay function + * to parse and style tokens in the file. + * The mode object contains a tokenizer function (token) which takes + * a character stream as input, advances it past a token, and returns + * a style for that token. For more details see + * https://codemirror.net/doc/manual.html#modeapi + * + * @memberof utils/source-search + * @static + */ + function searchOverlay(query) { + query = new RegExp(escapeRegExp(ignoreWhiteSpace(query)), "g"); + return { + token: function (stream) { + query.lastIndex = stream.pos; + var match = query.exec(stream.string); + if (match && match.index == stream.pos) { + stream.pos += match[0].length || 1; + return "selecting"; + } else if (match) { + stream.pos = match.index; + } else { + stream.skipToEnd(); + } + } + }; + } + + /** + * @memberof utils/source-search + * @static + */ + function startSearch(cm, state, query) { + cm.removeOverlay(state.overlay); + state.overlay = searchOverlay(query); + cm.addOverlay(state.overlay, { opaque: true }); + } + + /** + * If there's a saved search, selects the next results. + * Otherwise, creates a new search and selects the first + * result. + * + * @memberof utils/source-search + * @static + */ + function doSearch(ctx, rev, query) { + var cm = ctx.cm; + + var state = getSearchState(cm); + + if (state.query) { + searchNext(ctx, rev); + return; + } + + cm.operation(function () { + if (state.query) { + return; + } + startSearch(cm, state, query); + state.query = query; + state.posFrom = state.posTo = { line: 0, ch: 0 }; + searchNext(ctx, rev); + }); + } + + /** + * Selects the next result of a saved search. + * + * @memberof utils/source-search + * @static + */ + function searchNext(ctx, rev) { + var cm = ctx.cm; + var ed = ctx.ed; + + cm.operation(function () { + var state = getSearchState(cm); + var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo); + + if (!cursor.find(rev)) { + cursor = getSearchCursor(cm, state.query, rev ? { line: cm.lastLine(), ch: null } : { line: cm.firstLine(), ch: 0 }); + if (!cursor.find(rev)) { + return; + } + } + + ed.alignLine(cursor.from().line, "center"); + cm.setSelection(cursor.from(), cursor.to()); + state.posFrom = cursor.from(); + state.posTo = cursor.to(); + }); + } + + /** + * Clears the currently saved search. + * + * @memberof utils/source-search + * @static + */ + function clearSearch(cm) { + var state = getSearchState(cm); + + if (!state.query) { + return; + } + cm.removeOverlay(state.overlay); + state.query = null; + } + + /** + * Starts a new search. + * + * @memberof utils/source-search + * @static + */ + function find(ctx, query) { + clearSearch(ctx.cm); + doSearch(ctx, false, query); + } + + /** + * Finds the next item based on the currently saved search. + * + * @memberof utils/source-search + * @static + */ + function findNext(ctx, query) { + doSearch(ctx, false, query); + } + + /** + * Finds the previous item based on the currently saved search. + * + * @memberof utils/source-search + * @static + */ + function findPrev(ctx, query) { + doSearch(ctx, true, query); + } + + module.exports = { find, findNext, findPrev }; + +/***/ }, +/* 408 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(global, module) {/** + * @license + * lodash + * Copyright jQuery Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ + ;(function() { + + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + + /** Used as the semantic version number. */ + var VERSION = '4.16.4'; + + /** Used as the size to enable large array optimizations. */ + var LARGE_ARRAY_SIZE = 200; + + /** Error message constants. */ + var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://github.com/es-shims.', + FUNC_ERROR_TEXT = 'Expected a function'; + + /** Used to stand-in for `undefined` hash values. */ + var HASH_UNDEFINED = '__lodash_hash_undefined__'; + + /** Used as the maximum memoize cache size. */ + var MAX_MEMOIZE_SIZE = 500; + + /** Used as the internal argument placeholder. */ + var PLACEHOLDER = '__lodash_placeholder__'; + + /** Used to compose bitmasks for function metadata. */ + var BIND_FLAG = 1, + BIND_KEY_FLAG = 2, + CURRY_BOUND_FLAG = 4, + CURRY_FLAG = 8, + CURRY_RIGHT_FLAG = 16, + PARTIAL_FLAG = 32, + PARTIAL_RIGHT_FLAG = 64, + ARY_FLAG = 128, + REARG_FLAG = 256, + FLIP_FLAG = 512; + + /** Used to compose bitmasks for comparison styles. */ + var UNORDERED_COMPARE_FLAG = 1, + PARTIAL_COMPARE_FLAG = 2; + + /** Used as default options for `_.truncate`. */ + var DEFAULT_TRUNC_LENGTH = 30, + DEFAULT_TRUNC_OMISSION = '...'; + + /** Used to detect hot functions by number of calls within a span of milliseconds. */ + var HOT_COUNT = 500, + HOT_SPAN = 16; + + /** Used to indicate the type of lazy iteratees. */ + var LAZY_FILTER_FLAG = 1, + LAZY_MAP_FLAG = 2, + LAZY_WHILE_FLAG = 3; + + /** Used as references for various `Number` constants. */ + var INFINITY = 1 / 0, + MAX_SAFE_INTEGER = 9007199254740991, + MAX_INTEGER = 1.7976931348623157e+308, + NAN = 0 / 0; + + /** Used as references for the maximum length and index of an array. */ + var MAX_ARRAY_LENGTH = 4294967295, + MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, + HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + + /** Used to associate wrap methods with their bit flags. */ + var wrapFlags = [ + ['ary', ARY_FLAG], + ['bind', BIND_FLAG], + ['bindKey', BIND_KEY_FLAG], + ['curry', CURRY_FLAG], + ['curryRight', CURRY_RIGHT_FLAG], + ['flip', FLIP_FLAG], + ['partial', PARTIAL_FLAG], + ['partialRight', PARTIAL_RIGHT_FLAG], + ['rearg', REARG_FLAG] + ]; + + /** `Object#toString` result references. */ + var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + mapTag = '[object Map]', + numberTag = '[object Number]', + objectTag = '[object Object]', + promiseTag = '[object Promise]', + proxyTag = '[object Proxy]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + symbolTag = '[object Symbol]', + weakMapTag = '[object WeakMap]', + weakSetTag = '[object WeakSet]'; + + var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + + /** Used to match empty string literals in compiled template source. */ + var reEmptyStringLeading = /\b__p \+= '';/g, + reEmptyStringMiddle = /\b(__p \+=) '' \+/g, + reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + + /** Used to match HTML entities and HTML characters. */ + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, + reUnescapedHtml = /[&<>"']/g, + reHasEscapedHtml = RegExp(reEscapedHtml.source), + reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + + /** Used to match template delimiters. */ + var reEscape = /<%-([\s\S]+?)%>/g, + reEvaluate = /<%([\s\S]+?)%>/g, + reInterpolate = /<%=([\s\S]+?)%>/g; + + /** Used to match property names within property paths. */ + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, + reIsPlainProp = /^\w*$/, + reLeadingDot = /^\./, + rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; + + /** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ + var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, + reHasRegExpChar = RegExp(reRegExpChar.source); + + /** Used to match leading and trailing whitespace. */ + var reTrim = /^\s+|\s+$/g, + reTrimStart = /^\s+/, + reTrimEnd = /\s+$/; + + /** Used to match wrap detail comments. */ + var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/, + reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/, + reSplitDetails = /,? & /; + + /** Used to match words composed of alphanumeric characters. */ + var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; + + /** Used to match backslashes in property paths. */ + var reEscapeChar = /\\(\\)?/g; + + /** + * Used to match + * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components). + */ + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + + /** Used to match `RegExp` flags from their coerced string values. */ + var reFlags = /\w*$/; + + /** Used to detect bad signed hexadecimal string values. */ + var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; + + /** Used to detect binary string values. */ + var reIsBinary = /^0b[01]+$/i; + + /** Used to detect host constructors (Safari). */ + var reIsHostCtor = /^\[object .+?Constructor\]$/; + + /** Used to detect octal string values. */ + var reIsOctal = /^0o[0-7]+$/i; + + /** Used to detect unsigned integer values. */ + var reIsUint = /^(?:0|[1-9]\d*)$/; + + /** Used to match Latin Unicode letters (excluding mathematical operators). */ + var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g; + + /** Used to ensure capturing order of template delimiters. */ + var reNoMatch = /($^)/; + + /** Used to match unescaped characters in compiled string literals. */ + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; + + /** Used to compose unicode character classes. */ + var rsAstralRange = '\\ud800-\\udfff', + rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsComboSymbolsRange = '\\u20d0-\\u20f0', + rsDingbatRange = '\\u2700-\\u27bf', + rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff', + rsMathOpRange = '\\xac\\xb1\\xd7\\xf7', + rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf', + rsPunctuationRange = '\\u2000-\\u206f', + rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000', + rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde', + rsVarRange = '\\ufe0e\\ufe0f', + rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange; + + /** Used to compose unicode capture groups. */ + var rsApos = "['\u2019]", + rsAstral = '[' + rsAstralRange + ']', + rsBreak = '[' + rsBreakRange + ']', + rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']', + rsDigits = '\\d+', + rsDingbat = '[' + rsDingbatRange + ']', + rsLower = '[' + rsLowerRange + ']', + rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']', + rsFitz = '\\ud83c[\\udffb-\\udfff]', + rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', + rsNonAstral = '[^' + rsAstralRange + ']', + rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', + rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', + rsUpper = '[' + rsUpperRange + ']', + rsZWJ = '\\u200d'; + + /** Used to compose unicode regexes. */ + var rsLowerMisc = '(?:' + rsLower + '|' + rsMisc + ')', + rsUpperMisc = '(?:' + rsUpper + '|' + rsMisc + ')', + rsOptLowerContr = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?', + rsOptUpperContr = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?', + reOptMod = rsModifier + '?', + rsOptVar = '[' + rsVarRange + ']?', + rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', + rsSeq = rsOptVar + reOptMod + rsOptJoin, + rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq, + rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; + + /** Used to match apostrophes. */ + var reApos = RegExp(rsApos, 'g'); + + /** + * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and + * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols). + */ + var reComboMark = RegExp(rsCombo, 'g'); + + /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ + var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); + + /** Used to match complex or compound words. */ + var reUnicodeWord = RegExp([ + rsUpper + '?' + rsLower + '+' + rsOptLowerContr + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', + rsUpperMisc + '+' + rsOptUpperContr + '(?=' + [rsBreak, rsUpper + rsLowerMisc, '$'].join('|') + ')', + rsUpper + '?' + rsLowerMisc + '+' + rsOptLowerContr, + rsUpper + '+' + rsOptUpperContr, + rsDigits, + rsEmoji + ].join('|'), 'g'); + + /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ + var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboMarksRange + rsComboSymbolsRange + rsVarRange + ']'); + + /** Used to detect strings that need a more robust regexp to match words. */ + var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; + + /** Used to assign default `context` object properties. */ + var contextProps = [ + 'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array', + 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object', + 'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array', + 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', + '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout' + ]; + + /** Used to make template sourceURLs easier to identify. */ + var templateCounter = -1; + + /** Used to identify `toStringTag` values of typed arrays. */ + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = + typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = + typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = + typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = + typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = + typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = + typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = + typedArrayTags[errorTag] = typedArrayTags[funcTag] = + typedArrayTags[mapTag] = typedArrayTags[numberTag] = + typedArrayTags[objectTag] = typedArrayTags[regexpTag] = + typedArrayTags[setTag] = typedArrayTags[stringTag] = + typedArrayTags[weakMapTag] = false; + + /** Used to identify `toStringTag` values supported by `_.clone`. */ + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = + cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = + cloneableTags[boolTag] = cloneableTags[dateTag] = + cloneableTags[float32Tag] = cloneableTags[float64Tag] = + cloneableTags[int8Tag] = cloneableTags[int16Tag] = + cloneableTags[int32Tag] = cloneableTags[mapTag] = + cloneableTags[numberTag] = cloneableTags[objectTag] = + cloneableTags[regexpTag] = cloneableTags[setTag] = + cloneableTags[stringTag] = cloneableTags[symbolTag] = + cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = + cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = + cloneableTags[weakMapTag] = false; + + /** Used to map Latin Unicode letters to basic Latin letters. */ + var deburredLetters = { + // Latin-1 Supplement block. + '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', + '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a', + '\xc7': 'C', '\xe7': 'c', + '\xd0': 'D', '\xf0': 'd', + '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E', + '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e', + '\xcc': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', + '\xec': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', + '\xd1': 'N', '\xf1': 'n', + '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O', + '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o', + '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U', + '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u', + '\xdd': 'Y', '\xfd': 'y', '\xff': 'y', + '\xc6': 'Ae', '\xe6': 'ae', + '\xde': 'Th', '\xfe': 'th', + '\xdf': 'ss', + // Latin Extended-A block. + '\u0100': 'A', '\u0102': 'A', '\u0104': 'A', + '\u0101': 'a', '\u0103': 'a', '\u0105': 'a', + '\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C', + '\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c', + '\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd', + '\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E', + '\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e', + '\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G', + '\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g', + '\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h', + '\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I', + '\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i', + '\u0134': 'J', '\u0135': 'j', + '\u0136': 'K', '\u0137': 'k', '\u0138': 'k', + '\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L', + '\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l', + '\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N', + '\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n', + '\u014c': 'O', '\u014e': 'O', '\u0150': 'O', + '\u014d': 'o', '\u014f': 'o', '\u0151': 'o', + '\u0154': 'R', '\u0156': 'R', '\u0158': 'R', + '\u0155': 'r', '\u0157': 'r', '\u0159': 'r', + '\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S', + '\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's', + '\u0162': 'T', '\u0164': 'T', '\u0166': 'T', + '\u0163': 't', '\u0165': 't', '\u0167': 't', + '\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U', + '\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u', + '\u0174': 'W', '\u0175': 'w', + '\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y', + '\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z', + '\u017a': 'z', '\u017c': 'z', '\u017e': 'z', + '\u0132': 'IJ', '\u0133': 'ij', + '\u0152': 'Oe', '\u0153': 'oe', + '\u0149': "'n", '\u017f': 's' + }; + + /** Used to map characters to HTML entities. */ + var htmlEscapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + }; + + /** Used to map HTML entities to characters. */ + var htmlUnescapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + ''': "'" + }; + + /** Used to escape characters for inclusion in compiled string literals. */ + var stringEscapes = { + '\\': '\\', + "'": "'", + '\n': 'n', + '\r': 'r', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + /** Built-in method references without a dependency on `root`. */ + var freeParseFloat = parseFloat, + freeParseInt = parseInt; + + /** Detect free variable `global` from Node.js. */ + var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + + /** Detect free variable `self`. */ + var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + + /** Used as a reference to the global object. */ + var root = freeGlobal || freeSelf || Function('return this')(); + + /** Detect free variable `exports`. */ + var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; + + /** Detect free variable `module`. */ + var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; + + /** Detect the popular CommonJS extension `module.exports`. */ + var moduleExports = freeModule && freeModule.exports === freeExports; + + /** Detect free variable `process` from Node.js. */ + var freeProcess = moduleExports && freeGlobal.process; + + /** Used to access faster Node.js helpers. */ + var nodeUtil = (function() { + try { + return freeProcess && freeProcess.binding('util'); + } catch (e) {} + }()); + + /* Node.js helper references. */ + var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer, + nodeIsDate = nodeUtil && nodeUtil.isDate, + nodeIsMap = nodeUtil && nodeUtil.isMap, + nodeIsRegExp = nodeUtil && nodeUtil.isRegExp, + nodeIsSet = nodeUtil && nodeUtil.isSet, + nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; + + /*--------------------------------------------------------------------------*/ + + /** + * Adds the key-value `pair` to `map`. + * + * @private + * @param {Object} map The map to modify. + * @param {Array} pair The key-value pair to add. + * @returns {Object} Returns `map`. + */ + function addMapEntry(map, pair) { + // Don't return `map.set` because it's not chainable in IE 11. + map.set(pair[0], pair[1]); + return map; + } + + /** + * Adds `value` to `set`. + * + * @private + * @param {Object} set The set to modify. + * @param {*} value The value to add. + * @returns {Object} Returns `set`. + */ + function addSetEntry(set, value) { + // Don't return `set.add` because it's not chainable in IE 11. + set.add(value); + return set; + } + + /** + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. + * + * @private + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} args The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. + */ + function apply(func, thisArg, args) { + switch (args.length) { + case 0: return func.call(thisArg); + case 1: return func.call(thisArg, args[0]); + case 2: return func.call(thisArg, args[0], args[1]); + case 3: return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); + } + + /** + * A specialized version of `baseAggregator` for arrays. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform keys. + * @param {Object} accumulator The initial aggregated object. + * @returns {Function} Returns `accumulator`. + */ + function arrayAggregator(array, setter, iteratee, accumulator) { + var index = -1, + length = array ? array.length : 0; + + while (++index < length) { + var value = array[index]; + setter(accumulator, value, iteratee(value), array); + } + return accumulator; + } + + /** + * A specialized version of `_.forEach` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. + */ + function arrayEach(array, iteratee) { + var index = -1, + length = array ? array.length : 0; + + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; + } + + /** + * A specialized version of `_.forEachRight` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. + */ + function arrayEachRight(array, iteratee) { + var length = array ? array.length : 0; + + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; + } + } + return array; + } + + /** + * A specialized version of `_.every` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. + */ + function arrayEvery(array, predicate) { + var index = -1, + length = array ? array.length : 0; + + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; + } + } + return true; + } + + /** + * A specialized version of `_.filter` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ + function arrayFilter(array, predicate) { + var index = -1, + length = array ? array.length : 0, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[resIndex++] = value; + } + } + return result; + } + + /** + * A specialized version of `_.includes` for arrays without support for + * specifying an index to search from. + * + * @private + * @param {Array} [array] The array to inspect. + * @param {*} target The value to search for. + * @returns {boolean} Returns `true` if `target` is found, else `false`. + */ + function arrayIncludes(array, value) { + var length = array ? array.length : 0; + return !!length && baseIndexOf(array, value, 0) > -1; + } + + /** + * This function is like `arrayIncludes` except that it accepts a comparator. + * + * @private + * @param {Array} [array] The array to inspect. + * @param {*} target The value to search for. + * @param {Function} comparator The comparator invoked per element. + * @returns {boolean} Returns `true` if `target` is found, else `false`. + */ + function arrayIncludesWith(array, value, comparator) { + var index = -1, + length = array ? array.length : 0; + + while (++index < length) { + if (comparator(value, array[index])) { + return true; + } + } + return false; + } + + /** + * A specialized version of `_.map` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ + function arrayMap(array, iteratee) { + var index = -1, + length = array ? array.length : 0, + result = Array(length); + + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; + } + + /** + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. + */ + function arrayPush(array, values) { + var index = -1, + length = values.length, + offset = array.length; + + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + + /** + * A specialized version of `_.reduce` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {boolean} [initAccum] Specify using the first element of `array` as + * the initial value. + * @returns {*} Returns the accumulated value. + */ + function arrayReduce(array, iteratee, accumulator, initAccum) { + var index = -1, + length = array ? array.length : 0; + + if (initAccum && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; + } + + /** + * A specialized version of `_.reduceRight` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {boolean} [initAccum] Specify using the last element of `array` as + * the initial value. + * @returns {*} Returns the accumulated value. + */ + function arrayReduceRight(array, iteratee, accumulator, initAccum) { + var length = array ? array.length : 0; + if (initAccum && length) { + accumulator = array[--length]; + } + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); + } + return accumulator; + } + + /** + * A specialized version of `_.some` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ + function arraySome(array, predicate) { + var index = -1, + length = array ? array.length : 0; + + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; + } + + /** + * Gets the size of an ASCII `string`. + * + * @private + * @param {string} string The string inspect. + * @returns {number} Returns the string size. + */ + var asciiSize = baseProperty('length'); + + /** + * Converts an ASCII `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function asciiToArray(string) { + return string.split(''); + } + + /** + * Splits an ASCII `string` into an array of its words. + * + * @private + * @param {string} The string to inspect. + * @returns {Array} Returns the words of `string`. + */ + function asciiWords(string) { + return string.match(reAsciiWord) || []; + } + + /** + * The base implementation of methods like `_.findKey` and `_.findLastKey`, + * without support for iteratee shorthands, which iterates over `collection` + * using `eachFunc`. + * + * @private + * @param {Array|Object} collection The collection to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {Function} eachFunc The function to iterate over `collection`. + * @returns {*} Returns the found element or its key, else `undefined`. + */ + function baseFindKey(collection, predicate, eachFunc) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = key; + return false; + } + }); + return result; + } + + /** + * The base implementation of `_.findIndex` and `_.findLastIndex` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {number} fromIndex The index to search from. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseFindIndex(array, predicate, fromIndex, fromRight) { + var length = array.length, + index = fromIndex + (fromRight ? 1 : -1); + + while ((fromRight ? index-- : ++index < length)) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; + } + + /** + * The base implementation of `_.indexOf` without `fromIndex` bounds checks. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseIndexOf(array, value, fromIndex) { + return value === value + ? strictIndexOf(array, value, fromIndex) + : baseFindIndex(array, baseIsNaN, fromIndex); + } + + /** + * This function is like `baseIndexOf` except that it accepts a comparator. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @param {Function} comparator The comparator invoked per element. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseIndexOfWith(array, value, fromIndex, comparator) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (comparator(array[index], value)) { + return index; + } + } + return -1; + } + + /** + * The base implementation of `_.isNaN` without support for number objects. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + */ + function baseIsNaN(value) { + return value !== value; + } + + /** + * The base implementation of `_.mean` and `_.meanBy` without support for + * iteratee shorthands. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {number} Returns the mean. + */ + function baseMean(array, iteratee) { + var length = array ? array.length : 0; + return length ? (baseSum(array, iteratee) / length) : NAN; + } + + /** + * The base implementation of `_.property` without support for deep paths. + * + * @private + * @param {string} key The key of the property to get. + * @returns {Function} Returns the new accessor function. + */ + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + + /** + * The base implementation of `_.propertyOf` without support for deep paths. + * + * @private + * @param {Object} object The object to query. + * @returns {Function} Returns the new accessor function. + */ + function basePropertyOf(object) { + return function(key) { + return object == null ? undefined : object[key]; + }; + } + + /** + * The base implementation of `_.reduce` and `_.reduceRight`, without support + * for iteratee shorthands, which iterates over `collection` using `eachFunc`. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} accumulator The initial value. + * @param {boolean} initAccum Specify using the first or last element of + * `collection` as the initial value. + * @param {Function} eachFunc The function to iterate over `collection`. + * @returns {*} Returns the accumulated value. + */ + function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initAccum + ? (initAccum = false, value) + : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + + /** + * The base implementation of `_.sortBy` which uses `comparer` to define the + * sort order of `array` and replaces criteria objects with their corresponding + * values. + * + * @private + * @param {Array} array The array to sort. + * @param {Function} comparer The function to define sort order. + * @returns {Array} Returns `array`. + */ + function baseSortBy(array, comparer) { + var length = array.length; + + array.sort(comparer); + while (length--) { + array[length] = array[length].value; + } + return array; + } + + /** + * The base implementation of `_.sum` and `_.sumBy` without support for + * iteratee shorthands. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {number} Returns the sum. + */ + function baseSum(array, iteratee) { + var result, + index = -1, + length = array.length; + + while (++index < length) { + var current = iteratee(array[index]); + if (current !== undefined) { + result = result === undefined ? current : (result + current); + } + } + return result; + } + + /** + * The base implementation of `_.times` without support for iteratee shorthands + * or max array length checks. + * + * @private + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the array of results. + */ + function baseTimes(n, iteratee) { + var index = -1, + result = Array(n); + + while (++index < n) { + result[index] = iteratee(index); + } + return result; + } + + /** + * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array + * of key-value pairs for `object` corresponding to the property names of `props`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the key-value pairs. + */ + function baseToPairs(object, props) { + return arrayMap(props, function(key) { + return [key, object[key]]; + }); + } + + /** + * The base implementation of `_.unary` without support for storing metadata. + * + * @private + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. + */ + function baseUnary(func) { + return function(value) { + return func(value); + }; + } + + /** + * The base implementation of `_.values` and `_.valuesIn` which creates an + * array of `object` property values corresponding to the property names + * of `props`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the array of property values. + */ + function baseValues(object, props) { + return arrayMap(props, function(key) { + return object[key]; + }); + } + + /** + * Checks if a `cache` value for `key` exists. + * + * @private + * @param {Object} cache The cache to query. + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function cacheHas(cache, key) { + return cache.has(key); + } + + /** + * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the first unmatched string symbol. + */ + function charsStartIndex(strSymbols, chrSymbols) { + var index = -1, + length = strSymbols.length; + + while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} + return index; + } + + /** + * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the last unmatched string symbol. + */ + function charsEndIndex(strSymbols, chrSymbols) { + var index = strSymbols.length; + + while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} + return index; + } + + /** + * Gets the number of `placeholder` occurrences in `array`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} placeholder The placeholder to search for. + * @returns {number} Returns the placeholder count. + */ + function countHolders(array, placeholder) { + var length = array.length, + result = 0; + + while (length--) { + if (array[length] === placeholder) { + ++result; + } + } + return result; + } + + /** + * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A + * letters to basic Latin letters. + * + * @private + * @param {string} letter The matched letter to deburr. + * @returns {string} Returns the deburred letter. + */ + var deburrLetter = basePropertyOf(deburredLetters); + + /** + * Used by `_.escape` to convert characters to HTML entities. + * + * @private + * @param {string} chr The matched character to escape. + * @returns {string} Returns the escaped character. + */ + var escapeHtmlChar = basePropertyOf(htmlEscapes); + + /** + * Used by `_.template` to escape characters for inclusion in compiled string literals. + * + * @private + * @param {string} chr The matched character to escape. + * @returns {string} Returns the escaped character. + */ + function escapeStringChar(chr) { + return '\\' + stringEscapes[chr]; + } + + /** + * Gets the value at `key` of `object`. + * + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ + function getValue(object, key) { + return object == null ? undefined : object[key]; + } + + /** + * Checks if `string` contains Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a symbol is found, else `false`. + */ + function hasUnicode(string) { + return reHasUnicode.test(string); + } + + /** + * Checks if `string` contains a word composed of Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a word is found, else `false`. + */ + function hasUnicodeWord(string) { + return reHasUnicodeWord.test(string); + } + + /** + * Converts `iterator` to an array. + * + * @private + * @param {Object} iterator The iterator to convert. + * @returns {Array} Returns the converted array. + */ + function iteratorToArray(iterator) { + var data, + result = []; + + while (!(data = iterator.next()).done) { + result.push(data.value); + } + return result; + } + + /** + * Converts `map` to its key-value pairs. + * + * @private + * @param {Object} map The map to convert. + * @returns {Array} Returns the key-value pairs. + */ + function mapToArray(map) { + var index = -1, + result = Array(map.size); + + map.forEach(function(value, key) { + result[++index] = [key, value]; + }); + return result; + } + + /** + * Creates a unary function that invokes `func` with its argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ + function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; + } + + /** + * Replaces all `placeholder` elements in `array` with an internal placeholder + * and returns an array of their indexes. + * + * @private + * @param {Array} array The array to modify. + * @param {*} placeholder The placeholder to replace. + * @returns {Array} Returns the new array of placeholder indexes. + */ + function replaceHolders(array, placeholder) { + var index = -1, + length = array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (value === placeholder || value === PLACEHOLDER) { + array[index] = PLACEHOLDER; + result[resIndex++] = index; + } + } + return result; + } + + /** + * Converts `set` to an array of its values. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the values. + */ + function setToArray(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = value; + }); + return result; + } + + /** + * Converts `set` to its value-value pairs. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the value-value pairs. + */ + function setToPairs(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = [value, value]; + }); + return result; + } + + /** + * A specialized version of `_.indexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function strictIndexOf(array, value, fromIndex) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + + /** + * A specialized version of `_.lastIndexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function strictLastIndexOf(array, value, fromIndex) { + var index = fromIndex + 1; + while (index--) { + if (array[index] === value) { + return index; + } + } + return index; + } + + /** + * Gets the number of symbols in `string`. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the string size. + */ + function stringSize(string) { + return hasUnicode(string) + ? unicodeSize(string) + : asciiSize(string); + } + + /** + * Converts `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function stringToArray(string) { + return hasUnicode(string) + ? unicodeToArray(string) + : asciiToArray(string); + } + + /** + * Used by `_.unescape` to convert HTML entities to characters. + * + * @private + * @param {string} chr The matched character to unescape. + * @returns {string} Returns the unescaped character. + */ + var unescapeHtmlChar = basePropertyOf(htmlUnescapes); + + /** + * Gets the size of a Unicode `string`. + * + * @private + * @param {string} string The string inspect. + * @returns {number} Returns the string size. + */ + function unicodeSize(string) { + var result = reUnicode.lastIndex = 0; + while (reUnicode.test(string)) { + ++result; + } + return result; + } + + /** + * Converts a Unicode `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function unicodeToArray(string) { + return string.match(reUnicode) || []; + } + + /** + * Splits a Unicode `string` into an array of its words. + * + * @private + * @param {string} The string to inspect. + * @returns {Array} Returns the words of `string`. + */ + function unicodeWords(string) { + return string.match(reUnicodeWord) || []; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Create a new pristine `lodash` function using the `context` object. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Util + * @param {Object} [context=root] The context object. + * @returns {Function} Returns a new `lodash` function. + * @example + * + * _.mixin({ 'foo': _.constant('foo') }); + * + * var lodash = _.runInContext(); + * lodash.mixin({ 'bar': lodash.constant('bar') }); + * + * _.isFunction(_.foo); + * // => true + * _.isFunction(_.bar); + * // => false + * + * lodash.isFunction(lodash.foo); + * // => false + * lodash.isFunction(lodash.bar); + * // => true + * + * // Create a suped-up `defer` in Node.js. + * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer; + */ + var runInContext = (function runInContext(context) { + context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root; + + /** Built-in constructor references. */ + var Array = context.Array, + Date = context.Date, + Error = context.Error, + Function = context.Function, + Math = context.Math, + Object = context.Object, + RegExp = context.RegExp, + String = context.String, + TypeError = context.TypeError; + + /** Used for built-in method references. */ + var arrayProto = Array.prototype, + funcProto = Function.prototype, + objectProto = Object.prototype; + + /** Used to detect overreaching core-js shims. */ + var coreJsData = context['__core-js_shared__']; + + /** Used to detect methods masquerading as native. */ + var maskSrcKey = (function() { + var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); + return uid ? ('Symbol(src)_1.' + uid) : ''; + }()); + + /** Used to resolve the decompiled source of functions. */ + var funcToString = funcProto.toString; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** Used to generate unique IDs. */ + var idCounter = 0; + + /** Used to infer the `Object` constructor. */ + var objectCtorString = funcToString.call(Object); + + /** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ + var objectToString = objectProto.toString; + + /** Used to restore the original `_` reference in `_.noConflict`. */ + var oldDash = root._; + + /** Used to detect if a method is native. */ + var reIsNative = RegExp('^' + + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' + ); + + /** Built-in value references. */ + var Buffer = moduleExports ? context.Buffer : undefined, + Symbol = context.Symbol, + Uint8Array = context.Uint8Array, + allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined, + getPrototype = overArg(Object.getPrototypeOf, Object), + iteratorSymbol = Symbol ? Symbol.iterator : undefined, + objectCreate = Object.create, + propertyIsEnumerable = objectProto.propertyIsEnumerable, + splice = arrayProto.splice, + spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined; + + var defineProperty = (function() { + try { + var func = getNative(Object, 'defineProperty'); + func({}, '', {}); + return func; + } catch (e) {} + }()); + + /** Mocked built-ins. */ + var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout, + ctxNow = Date && Date.now !== root.Date.now && Date.now, + ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout; + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeCeil = Math.ceil, + nativeFloor = Math.floor, + nativeGetSymbols = Object.getOwnPropertySymbols, + nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined, + nativeIsFinite = context.isFinite, + nativeJoin = arrayProto.join, + nativeKeys = overArg(Object.keys, Object), + nativeMax = Math.max, + nativeMin = Math.min, + nativeNow = Date.now, + nativeParseInt = context.parseInt, + nativeRandom = Math.random, + nativeReverse = arrayProto.reverse; + + /* Built-in method references that are verified to be native. */ + var DataView = getNative(context, 'DataView'), + Map = getNative(context, 'Map'), + Promise = getNative(context, 'Promise'), + Set = getNative(context, 'Set'), + WeakMap = getNative(context, 'WeakMap'), + nativeCreate = getNative(Object, 'create'); + + /** Used to store function metadata. */ + var metaMap = WeakMap && new WeakMap; + + /** Used to lookup unminified function names. */ + var realNames = {}; + + /** Used to detect maps, sets, and weakmaps. */ + var dataViewCtorString = toSource(DataView), + mapCtorString = toSource(Map), + promiseCtorString = toSource(Promise), + setCtorString = toSource(Set), + weakMapCtorString = toSource(WeakMap); + + /** Used to convert symbols to primitives and strings. */ + var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolValueOf = symbolProto ? symbolProto.valueOf : undefined, + symbolToString = symbolProto ? symbolProto.toString : undefined; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a `lodash` object which wraps `value` to enable implicit method + * chain sequences. Methods that operate on and return arrays, collections, + * and functions can be chained together. Methods that retrieve a single value + * or may return a primitive value will automatically end the chain sequence + * and return the unwrapped value. Otherwise, the value must be unwrapped + * with `_#value`. + * + * Explicit chain sequences, which must be unwrapped with `_#value`, may be + * enabled using `_.chain`. + * + * The execution of chained methods is lazy, that is, it's deferred until + * `_#value` is implicitly or explicitly called. + * + * Lazy evaluation allows several methods to support shortcut fusion. + * Shortcut fusion is an optimization to merge iteratee calls; this avoids + * the creation of intermediate arrays and can greatly reduce the number of + * iteratee executions. Sections of a chain sequence qualify for shortcut + * fusion if the section is applied to an array of at least `200` elements + * and any iteratees accept only one argument. The heuristic for whether a + * section qualifies for shortcut fusion is subject to change. + * + * Chaining is supported in custom builds as long as the `_#value` method is + * directly or indirectly included in the build. + * + * In addition to lodash methods, wrappers have `Array` and `String` methods. + * + * The wrapper `Array` methods are: + * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift` + * + * The wrapper `String` methods are: + * `replace` and `split` + * + * The wrapper methods that support shortcut fusion are: + * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`, + * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`, + * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray` + * + * The chainable wrapper methods are: + * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`, + * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`, + * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`, + * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, + * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`, + * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`, + * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`, + * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, + * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`, + * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`, + * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, + * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`, + * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`, + * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`, + * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`, + * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`, + * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`, + * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`, + * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`, + * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`, + * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`, + * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`, + * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, + * `zipObject`, `zipObjectDeep`, and `zipWith` + * + * The wrapper methods that are **not** chainable by default are: + * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`, + * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`, + * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`, + * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`, + * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`, + * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`, + * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`, + * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, + * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, + * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, + * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, + * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, + * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`, + * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`, + * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`, + * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`, + * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, + * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`, + * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`, + * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`, + * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`, + * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`, + * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`, + * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`, + * `upperFirst`, `value`, and `words` + * + * @name _ + * @constructor + * @category Seq + * @param {*} value The value to wrap in a `lodash` instance. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * function square(n) { + * return n * n; + * } + * + * var wrapped = _([1, 2, 3]); + * + * // Returns an unwrapped value. + * wrapped.reduce(_.add); + * // => 6 + * + * // Returns a wrapped value. + * var squares = wrapped.map(square); + * + * _.isArray(squares); + * // => false + * + * _.isArray(squares.value()); + * // => true + */ + function lodash(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, '__wrapped__')) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); + } + + /** + * The base implementation of `_.create` without support for assigning + * properties to the created object. + * + * @private + * @param {Object} proto The object to inherit from. + * @returns {Object} Returns the new object. + */ + var baseCreate = (function() { + function object() {} + return function(proto) { + if (!isObject(proto)) { + return {}; + } + if (objectCreate) { + return objectCreate(proto); + } + object.prototype = proto; + var result = new object; + object.prototype = undefined; + return result; + }; + }()); + + /** + * The function whose prototype chain sequence wrappers inherit from. + * + * @private + */ + function baseLodash() { + // No operation performed. + } + + /** + * The base constructor for creating `lodash` wrapper objects. + * + * @private + * @param {*} value The value to wrap. + * @param {boolean} [chainAll] Enable explicit method chain sequences. + */ + function LodashWrapper(value, chainAll) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__chain__ = !!chainAll; + this.__index__ = 0; + this.__values__ = undefined; + } + + /** + * By default, the template delimiters used by lodash are like those in + * embedded Ruby (ERB). Change the following template settings to use + * alternative delimiters. + * + * @static + * @memberOf _ + * @type {Object} + */ + lodash.templateSettings = { + + /** + * Used to detect `data` property values to be HTML-escaped. + * + * @memberOf _.templateSettings + * @type {RegExp} + */ + 'escape': reEscape, + + /** + * Used to detect code to be evaluated. + * + * @memberOf _.templateSettings + * @type {RegExp} + */ + 'evaluate': reEvaluate, + + /** + * Used to detect `data` property values to inject. + * + * @memberOf _.templateSettings + * @type {RegExp} + */ + 'interpolate': reInterpolate, + + /** + * Used to reference the data object in the template text. + * + * @memberOf _.templateSettings + * @type {string} + */ + 'variable': '', + + /** + * Used to import variables into the compiled template. + * + * @memberOf _.templateSettings + * @type {Object} + */ + 'imports': { + + /** + * A reference to the `lodash` function. + * + * @memberOf _.templateSettings.imports + * @type {Function} + */ + '_': lodash + } + }; + + // Ensure wrappers are instances of `baseLodash`. + lodash.prototype = baseLodash.prototype; + lodash.prototype.constructor = lodash; + + LodashWrapper.prototype = baseCreate(baseLodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation. + * + * @private + * @constructor + * @param {*} value The value to wrap. + */ + function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = MAX_ARRAY_LENGTH; + this.__views__ = []; + } + + /** + * Creates a clone of the lazy wrapper object. + * + * @private + * @name clone + * @memberOf LazyWrapper + * @returns {Object} Returns the cloned `LazyWrapper` object. + */ + function lazyClone() { + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = copyArray(this.__actions__); + result.__dir__ = this.__dir__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = copyArray(this.__iteratees__); + result.__takeCount__ = this.__takeCount__; + result.__views__ = copyArray(this.__views__); + return result; + } + + /** + * Reverses the direction of lazy iteration. + * + * @private + * @name reverse + * @memberOf LazyWrapper + * @returns {Object} Returns the new reversed `LazyWrapper` object. + */ + function lazyReverse() { + if (this.__filtered__) { + var result = new LazyWrapper(this); + result.__dir__ = -1; + result.__filtered__ = true; + } else { + result = this.clone(); + result.__dir__ *= -1; + } + return result; + } + + /** + * Extracts the unwrapped value from its lazy wrapper. + * + * @private + * @name value + * @memberOf LazyWrapper + * @returns {*} Returns the unwrapped value. + */ + function lazyValue() { + var array = this.__wrapped__.value(), + dir = this.__dir__, + isArr = isArray(array), + isRight = dir < 0, + arrLength = isArr ? array.length : 0, + view = getView(0, arrLength, this.__views__), + start = view.start, + end = view.end, + length = end - start, + index = isRight ? end : (start - 1), + iteratees = this.__iteratees__, + iterLength = iteratees.length, + resIndex = 0, + takeCount = nativeMin(length, this.__takeCount__); + + if (!isArr || arrLength < LARGE_ARRAY_SIZE || + (arrLength == length && takeCount == length)) { + return baseWrapperValue(array, this.__actions__); + } + var result = []; + + outer: + while (length-- && resIndex < takeCount) { + index += dir; + + var iterIndex = -1, + value = array[index]; + + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], + iteratee = data.iteratee, + type = data.type, + computed = iteratee(value); + + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } + } + } + result[resIndex++] = value; + } + return result; + } + + // Ensure `LazyWrapper` is an instance of `baseLodash`. + LazyWrapper.prototype = baseCreate(baseLodash.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function Hash(entries) { + var index = -1, + length = entries ? entries.length : 0; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ + function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(null) : {}; + this.size = 0; + } + + /** + * Removes `key` and its value from the hash. + * + * @private + * @name delete + * @memberOf Hash + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function hashDelete(key) { + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; + return result; + } + + /** + * Gets the hash value for `key`. + * + * @private + * @name get + * @memberOf Hash + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function hashGet(key) { + var data = this.__data__; + if (nativeCreate) { + var result = data[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty.call(data, key) ? data[key] : undefined; + } + + /** + * Checks if a hash value for `key` exists. + * + * @private + * @name has + * @memberOf Hash + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function hashHas(key) { + var data = this.__data__; + return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key); + } + + /** + * Sets the hash `key` to `value`. + * + * @private + * @name set + * @memberOf Hash + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the hash instance. + */ + function hashSet(key, value) { + var data = this.__data__; + this.size += this.has(key) ? 0 : 1; + data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; + return this; + } + + // Add methods to `Hash`. + Hash.prototype.clear = hashClear; + Hash.prototype['delete'] = hashDelete; + Hash.prototype.get = hashGet; + Hash.prototype.has = hashHas; + Hash.prototype.set = hashSet; + + /*------------------------------------------------------------------------*/ + + /** + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function ListCache(entries) { + var index = -1, + length = entries ? entries.length : 0; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ + function listCacheClear() { + this.__data__ = []; + this.size = 0; + } + + /** + * Removes `key` and its value from the list cache. + * + * @private + * @name delete + * @memberOf ListCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function listCacheDelete(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + --this.size; + return true; + } + + /** + * Gets the list cache value for `key`. + * + * @private + * @name get + * @memberOf ListCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function listCacheGet(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + return index < 0 ? undefined : data[index][1]; + } + + /** + * Checks if a list cache value for `key` exists. + * + * @private + * @name has + * @memberOf ListCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function listCacheHas(key) { + return assocIndexOf(this.__data__, key) > -1; + } + + /** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */ + function listCacheSet(key, value) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + ++this.size; + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; + } + + // Add methods to `ListCache`. + ListCache.prototype.clear = listCacheClear; + ListCache.prototype['delete'] = listCacheDelete; + ListCache.prototype.get = listCacheGet; + ListCache.prototype.has = listCacheHas; + ListCache.prototype.set = listCacheSet; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function MapCache(entries) { + var index = -1, + length = entries ? entries.length : 0; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the map. + * + * @private + * @name clear + * @memberOf MapCache + */ + function mapCacheClear() { + this.size = 0; + this.__data__ = { + 'hash': new Hash, + 'map': new (Map || ListCache), + 'string': new Hash + }; + } + + /** + * Removes `key` and its value from the map. + * + * @private + * @name delete + * @memberOf MapCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function mapCacheDelete(key) { + var result = getMapData(this, key)['delete'](key); + this.size -= result ? 1 : 0; + return result; + } + + /** + * Gets the map value for `key`. + * + * @private + * @name get + * @memberOf MapCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function mapCacheGet(key) { + return getMapData(this, key).get(key); + } + + /** + * Checks if a map value for `key` exists. + * + * @private + * @name has + * @memberOf MapCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function mapCacheHas(key) { + return getMapData(this, key).has(key); + } + + /** + * Sets the map `key` to `value`. + * + * @private + * @name set + * @memberOf MapCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the map cache instance. + */ + function mapCacheSet(key, value) { + var data = getMapData(this, key), + size = data.size; + + data.set(key, value); + this.size += data.size == size ? 0 : 1; + return this; + } + + // Add methods to `MapCache`. + MapCache.prototype.clear = mapCacheClear; + MapCache.prototype['delete'] = mapCacheDelete; + MapCache.prototype.get = mapCacheGet; + MapCache.prototype.has = mapCacheHas; + MapCache.prototype.set = mapCacheSet; + + /*------------------------------------------------------------------------*/ + + /** + * + * Creates an array cache object to store unique values. + * + * @private + * @constructor + * @param {Array} [values] The values to cache. + */ + function SetCache(values) { + var index = -1, + length = values ? values.length : 0; + + this.__data__ = new MapCache; + while (++index < length) { + this.add(values[index]); + } + } + + /** + * Adds `value` to the array cache. + * + * @private + * @name add + * @memberOf SetCache + * @alias push + * @param {*} value The value to cache. + * @returns {Object} Returns the cache instance. + */ + function setCacheAdd(value) { + this.__data__.set(value, HASH_UNDEFINED); + return this; + } + + /** + * Checks if `value` is in the array cache. + * + * @private + * @name has + * @memberOf SetCache + * @param {*} value The value to search for. + * @returns {number} Returns `true` if `value` is found, else `false`. + */ + function setCacheHas(value) { + return this.__data__.has(value); + } + + // Add methods to `SetCache`. + SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; + SetCache.prototype.has = setCacheHas; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a stack cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function Stack(entries) { + var data = this.__data__ = new ListCache(entries); + this.size = data.size; + } + + /** + * Removes all key-value entries from the stack. + * + * @private + * @name clear + * @memberOf Stack + */ + function stackClear() { + this.__data__ = new ListCache; + this.size = 0; + } + + /** + * Removes `key` and its value from the stack. + * + * @private + * @name delete + * @memberOf Stack + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function stackDelete(key) { + var data = this.__data__, + result = data['delete'](key); + + this.size = data.size; + return result; + } + + /** + * Gets the stack value for `key`. + * + * @private + * @name get + * @memberOf Stack + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function stackGet(key) { + return this.__data__.get(key); + } + + /** + * Checks if a stack value for `key` exists. + * + * @private + * @name has + * @memberOf Stack + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function stackHas(key) { + return this.__data__.has(key); + } + + /** + * Sets the stack `key` to `value`. + * + * @private + * @name set + * @memberOf Stack + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the stack cache instance. + */ + function stackSet(key, value) { + var data = this.__data__; + if (data instanceof ListCache) { + var pairs = data.__data__; + if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) { + pairs.push([key, value]); + this.size = ++data.size; + return this; + } + data = this.__data__ = new MapCache(pairs); + } + data.set(key, value); + this.size = data.size; + return this; + } + + // Add methods to `Stack`. + Stack.prototype.clear = stackClear; + Stack.prototype['delete'] = stackDelete; + Stack.prototype.get = stackGet; + Stack.prototype.has = stackHas; + Stack.prototype.set = stackSet; + + /*------------------------------------------------------------------------*/ + + /** + * Creates an array of the enumerable property names of the array-like `value`. + * + * @private + * @param {*} value The value to query. + * @param {boolean} inherited Specify returning inherited property names. + * @returns {Array} Returns the array of property names. + */ + function arrayLikeKeys(value, inherited) { + var isArr = isArray(value), + isArg = !isArr && isArguments(value), + isBuff = !isArr && !isArg && isBuffer(value), + isType = !isArr && !isArg && !isBuff && isTypedArray(value), + skipIndexes = isArr || isArg || isBuff || isType, + result = skipIndexes ? baseTimes(value.length, String) : [], + length = result.length; + + for (var key in value) { + if ((inherited || hasOwnProperty.call(value, key)) && + !(skipIndexes && ( + // Safari 9 has enumerable `arguments.length` in strict mode. + key == 'length' || + // Node.js 0.10 has enumerable non-index properties on buffers. + (isBuff && (key == 'offset' || key == 'parent')) || + // PhantomJS 2 has enumerable non-index properties on typed arrays. + (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || + // Skip index properties. + isIndex(key, length) + ))) { + result.push(key); + } + } + return result; + } + + /** + * A specialized version of `_.sample` for arrays. + * + * @private + * @param {Array} array The array to sample. + * @returns {*} Returns the random element. + */ + function arraySample(array) { + var length = array.length; + return length ? array[baseRandom(0, length - 1)] : undefined; + } + + /** + * A specialized version of `_.sampleSize` for arrays. + * + * @private + * @param {Array} array The array to sample. + * @param {number} n The number of elements to sample. + * @returns {Array} Returns the random elements. + */ + function arraySampleSize(array, n) { + return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length)); + } + + /** + * A specialized version of `_.shuffle` for arrays. + * + * @private + * @param {Array} array The array to shuffle. + * @returns {Array} Returns the new shuffled array. + */ + function arrayShuffle(array) { + return shuffleSelf(copyArray(array)); + } + + /** + * Used by `_.defaults` to customize its `_.assignIn` use. + * + * @private + * @param {*} objValue The destination value. + * @param {*} srcValue The source value. + * @param {string} key The key of the property to assign. + * @param {Object} object The parent object of `objValue`. + * @returns {*} Returns the value to assign. + */ + function assignInDefaults(objValue, srcValue, key, object) { + if (objValue === undefined || + (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) { + return srcValue; + } + return objValue; + } + + /** + * This function is like `assignValue` except that it doesn't assign + * `undefined` values. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function assignMergeValue(object, key, value) { + if ((value !== undefined && !eq(object[key], value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } + } + + /** + * Assigns `value` to `key` of `object` if the existing value is not equivalent + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function assignValue(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } + } + + /** + * Gets the index at which the `key` is found in `array` of key-value pairs. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; + } + + /** + * Aggregates elements of `collection` on `accumulator` with keys transformed + * by `iteratee` and values set by `setter`. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform keys. + * @param {Object} accumulator The initial aggregated object. + * @returns {Function} Returns `accumulator`. + */ + function baseAggregator(collection, setter, iteratee, accumulator) { + baseEach(collection, function(value, key, collection) { + setter(accumulator, value, iteratee(value), collection); + }); + return accumulator; + } + + /** + * The base implementation of `_.assign` without support for multiple sources + * or `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ + function baseAssign(object, source) { + return object && copyObject(source, keys(source), object); + } + + /** + * The base implementation of `assignValue` and `assignMergeValue` without + * value checks. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function baseAssignValue(object, key, value) { + if (key == '__proto__' && defineProperty) { + defineProperty(object, key, { + 'configurable': true, + 'enumerable': true, + 'value': value, + 'writable': true + }); + } else { + object[key] = value; + } + } + + /** + * The base implementation of `_.at` without support for individual paths. + * + * @private + * @param {Object} object The object to iterate over. + * @param {string[]} paths The property paths of elements to pick. + * @returns {Array} Returns the picked elements. + */ + function baseAt(object, paths) { + var index = -1, + isNil = object == null, + length = paths.length, + result = Array(length); + + while (++index < length) { + result[index] = isNil ? undefined : get(object, paths[index]); + } + return result; + } + + /** + * The base implementation of `_.clamp` which doesn't coerce arguments. + * + * @private + * @param {number} number The number to clamp. + * @param {number} [lower] The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the clamped number. + */ + function baseClamp(number, lower, upper) { + if (number === number) { + if (upper !== undefined) { + number = number <= upper ? number : upper; + } + if (lower !== undefined) { + number = number >= lower ? number : lower; + } + } + return number; + } + + /** + * The base implementation of `_.clone` and `_.cloneDeep` which tracks + * traversed objects. + * + * @private + * @param {*} value The value to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @param {boolean} [isFull] Specify a clone including symbols. + * @param {Function} [customizer] The function to customize cloning. + * @param {string} [key] The key of `value`. + * @param {Object} [object] The parent object of `value`. + * @param {Object} [stack] Tracks traversed objects and their clone counterparts. + * @returns {*} Returns the cloned value. + */ + function baseClone(value, isDeep, isFull, customizer, key, object, stack) { + var result; + if (customizer) { + result = object ? customizer(value, key, object, stack) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return copyArray(value, result); + } + } else { + var tag = getTag(value), + isFunc = tag == funcTag || tag == genTag; + + if (isBuffer(value)) { + return cloneBuffer(value, isDeep); + } + if (tag == objectTag || tag == argsTag || (isFunc && !object)) { + result = initCloneObject(isFunc ? {} : value); + if (!isDeep) { + return copySymbols(value, baseAssign(result, value)); + } + } else { + if (!cloneableTags[tag]) { + return object ? value : {}; + } + result = initCloneByTag(value, tag, baseClone, isDeep); + } + } + // Check for circular references and return its corresponding clone. + stack || (stack = new Stack); + var stacked = stack.get(value); + if (stacked) { + return stacked; + } + stack.set(value, result); + + var props = isArr ? undefined : (isFull ? getAllKeys : keys)(value); + arrayEach(props || value, function(subValue, key) { + if (props) { + key = subValue; + subValue = value[key]; + } + // Recursively populate clone (susceptible to call stack limits). + assignValue(result, key, baseClone(subValue, isDeep, isFull, customizer, key, value, stack)); + }); + return result; + } + + /** + * The base implementation of `_.conforms` which doesn't clone `source`. + * + * @private + * @param {Object} source The object of property predicates to conform to. + * @returns {Function} Returns the new spec function. + */ + function baseConforms(source) { + var props = keys(source); + return function(object) { + return baseConformsTo(object, source, props); + }; + } + + /** + * The base implementation of `_.conformsTo` which accepts `props` to check. + * + * @private + * @param {Object} object The object to inspect. + * @param {Object} source The object of property predicates to conform to. + * @returns {boolean} Returns `true` if `object` conforms, else `false`. + */ + function baseConformsTo(object, source, props) { + var length = props.length; + if (object == null) { + return !length; + } + object = Object(object); + while (length--) { + var key = props[length], + predicate = source[key], + value = object[key]; + + if ((value === undefined && !(key in object)) || !predicate(value)) { + return false; + } + } + return true; + } + + /** + * The base implementation of `_.delay` and `_.defer` which accepts `args` + * to provide to `func`. + * + * @private + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {Array} args The arguments to provide to `func`. + * @returns {number|Object} Returns the timer id or timeout object. + */ + function baseDelay(func, wait, args) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { func.apply(undefined, args); }, wait); + } + + /** + * The base implementation of methods like `_.difference` without support + * for excluding multiple arrays or iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Array} values The values to exclude. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + */ + function baseDifference(array, values, iteratee, comparator) { + var index = -1, + includes = arrayIncludes, + isCommon = true, + length = array.length, + result = [], + valuesLength = values.length; + + if (!length) { + return result; + } + if (iteratee) { + values = arrayMap(values, baseUnary(iteratee)); + } + if (comparator) { + includes = arrayIncludesWith; + isCommon = false; + } + else if (values.length >= LARGE_ARRAY_SIZE) { + includes = cacheHas; + isCommon = false; + values = new SetCache(values); + } + outer: + while (++index < length) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + value = (comparator || value !== 0) ? value : 0; + if (isCommon && computed === computed) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === computed) { + continue outer; + } + } + result.push(value); + } + else if (!includes(values, computed, comparator)) { + result.push(value); + } + } + return result; + } + + /** + * The base implementation of `_.forEach` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + */ + var baseEach = createBaseEach(baseForOwn); + + /** + * The base implementation of `_.forEachRight` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + */ + var baseEachRight = createBaseEach(baseForOwnRight, true); + + /** + * The base implementation of `_.every` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false` + */ + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; + } + + /** + * The base implementation of methods like `_.max` and `_.min` which accepts a + * `comparator` to determine the extremum value. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The iteratee invoked per iteration. + * @param {Function} comparator The comparator used to compare values. + * @returns {*} Returns the extremum value. + */ + function baseExtremum(array, iteratee, comparator) { + var index = -1, + length = array.length; + + while (++index < length) { + var value = array[index], + current = iteratee(value); + + if (current != null && (computed === undefined + ? (current === current && !isSymbol(current)) + : comparator(current, computed) + )) { + var computed = current, + result = value; + } + } + return result; + } + + /** + * The base implementation of `_.fill` without an iteratee call guard. + * + * @private + * @param {Array} array The array to fill. + * @param {*} value The value to fill `array` with. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns `array`. + */ + function baseFill(array, value, start, end) { + var length = array.length; + + start = toInteger(start); + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = (end === undefined || end > length) ? length : toInteger(end); + if (end < 0) { + end += length; + } + end = start > end ? 0 : toLength(end); + while (start < end) { + array[start++] = value; + } + return array; + } + + /** + * The base implementation of `_.filter` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; + } + + /** + * The base implementation of `_.flatten` with support for restricting flattening. + * + * @private + * @param {Array} array The array to flatten. + * @param {number} depth The maximum recursion depth. + * @param {boolean} [predicate=isFlattenable] The function invoked per iteration. + * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks. + * @param {Array} [result=[]] The initial result value. + * @returns {Array} Returns the new flattened array. + */ + function baseFlatten(array, depth, predicate, isStrict, result) { + var index = -1, + length = array.length; + + predicate || (predicate = isFlattenable); + result || (result = []); + + while (++index < length) { + var value = array[index]; + if (depth > 0 && predicate(value)) { + if (depth > 1) { + // Recursively flatten arrays (susceptible to call stack limits). + baseFlatten(value, depth - 1, predicate, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; + } + + /** + * The base implementation of `baseForOwn` which iterates over `object` + * properties returned by `keysFunc` and invokes `iteratee` for each property. + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ + var baseFor = createBaseFor(); + + /** + * This function is like `baseFor` except that it iterates over properties + * in the opposite order. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ + var baseForRight = createBaseFor(true); + + /** + * The base implementation of `_.forOwn` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ + function baseForOwn(object, iteratee) { + return object && baseFor(object, iteratee, keys); + } + + /** + * The base implementation of `_.forOwnRight` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ + function baseForOwnRight(object, iteratee) { + return object && baseForRight(object, iteratee, keys); + } + + /** + * The base implementation of `_.functions` which creates an array of + * `object` function property names filtered from `props`. + * + * @private + * @param {Object} object The object to inspect. + * @param {Array} props The property names to filter. + * @returns {Array} Returns the function names. + */ + function baseFunctions(object, props) { + return arrayFilter(props, function(key) { + return isFunction(object[key]); + }); + } + + /** + * The base implementation of `_.get` without support for default values. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @returns {*} Returns the resolved value. + */ + function baseGet(object, path) { + path = isKey(path, object) ? [path] : castPath(path); + + var index = 0, + length = path.length; + + while (object != null && index < length) { + object = object[toKey(path[index++])]; + } + return (index && index == length) ? object : undefined; + } + + /** + * The base implementation of `getAllKeys` and `getAllKeysIn` which uses + * `keysFunc` and `symbolsFunc` to get the enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Function} keysFunc The function to get the keys of `object`. + * @param {Function} symbolsFunc The function to get the symbols of `object`. + * @returns {Array} Returns the array of property names and symbols. + */ + function baseGetAllKeys(object, keysFunc, symbolsFunc) { + var result = keysFunc(object); + return isArray(object) ? result : arrayPush(result, symbolsFunc(object)); + } + + /** + * The base implementation of `getTag`. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + function baseGetTag(value) { + return objectToString.call(value); + } + + /** + * The base implementation of `_.gt` which doesn't coerce arguments. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than `other`, + * else `false`. + */ + function baseGt(value, other) { + return value > other; + } + + /** + * The base implementation of `_.has` without support for deep paths. + * + * @private + * @param {Object} [object] The object to query. + * @param {Array|string} key The key to check. + * @returns {boolean} Returns `true` if `key` exists, else `false`. + */ + function baseHas(object, key) { + return object != null && hasOwnProperty.call(object, key); + } + + /** + * The base implementation of `_.hasIn` without support for deep paths. + * + * @private + * @param {Object} [object] The object to query. + * @param {Array|string} key The key to check. + * @returns {boolean} Returns `true` if `key` exists, else `false`. + */ + function baseHasIn(object, key) { + return object != null && key in Object(object); + } + + /** + * The base implementation of `_.inRange` which doesn't coerce arguments. + * + * @private + * @param {number} number The number to check. + * @param {number} start The start of the range. + * @param {number} end The end of the range. + * @returns {boolean} Returns `true` if `number` is in the range, else `false`. + */ + function baseInRange(number, start, end) { + return number >= nativeMin(start, end) && number < nativeMax(start, end); + } + + /** + * The base implementation of methods like `_.intersection`, without support + * for iteratee shorthands, that accepts an array of arrays to inspect. + * + * @private + * @param {Array} arrays The arrays to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of shared values. + */ + function baseIntersection(arrays, iteratee, comparator) { + var includes = comparator ? arrayIncludesWith : arrayIncludes, + length = arrays[0].length, + othLength = arrays.length, + othIndex = othLength, + caches = Array(othLength), + maxLength = Infinity, + result = []; + + while (othIndex--) { + var array = arrays[othIndex]; + if (othIndex && iteratee) { + array = arrayMap(array, baseUnary(iteratee)); + } + maxLength = nativeMin(array.length, maxLength); + caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120)) + ? new SetCache(othIndex && array) + : undefined; + } + array = arrays[0]; + + var index = -1, + seen = caches[0]; + + outer: + while (++index < length && result.length < maxLength) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + value = (comparator || value !== 0) ? value : 0; + if (!(seen + ? cacheHas(seen, computed) + : includes(result, computed, comparator) + )) { + othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if (!(cache + ? cacheHas(cache, computed) + : includes(arrays[othIndex], computed, comparator)) + ) { + continue outer; + } + } + if (seen) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + + /** + * The base implementation of `_.invert` and `_.invertBy` which inverts + * `object` with values transformed by `iteratee` and set by `setter`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform values. + * @param {Object} accumulator The initial inverted object. + * @returns {Function} Returns `accumulator`. + */ + function baseInverter(object, setter, iteratee, accumulator) { + baseForOwn(object, function(value, key, object) { + setter(accumulator, iteratee(value), key, object); + }); + return accumulator; + } + + /** + * The base implementation of `_.invoke` without support for individual + * method arguments. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the method to invoke. + * @param {Array} args The arguments to invoke the method with. + * @returns {*} Returns the result of the invoked method. + */ + function baseInvoke(object, path, args) { + if (!isKey(path, object)) { + path = castPath(path); + object = parent(object, path); + path = last(path); + } + var func = object == null ? object : object[toKey(path)]; + return func == null ? undefined : apply(func, object, args); + } + + /** + * The base implementation of `_.isArguments`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + */ + function baseIsArguments(value) { + return isObjectLike(value) && objectToString.call(value) == argsTag; + } + + /** + * The base implementation of `_.isArrayBuffer` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`. + */ + function baseIsArrayBuffer(value) { + return isObjectLike(value) && objectToString.call(value) == arrayBufferTag; + } + + /** + * The base implementation of `_.isDate` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a date object, else `false`. + */ + function baseIsDate(value) { + return isObjectLike(value) && objectToString.call(value) == dateTag; + } + + /** + * The base implementation of `_.isEqual` which supports partial comparisons + * and tracks traversed objects. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {Function} [customizer] The function to customize comparisons. + * @param {boolean} [bitmask] The bitmask of comparison flags. + * The bitmask may be composed of the following flags: + * 1 - Unordered comparison + * 2 - Partial comparison + * @param {Object} [stack] Tracks traversed `value` and `other` objects. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + */ + function baseIsEqual(value, other, customizer, bitmask, stack) { + if (value === other) { + return true; + } + if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, baseIsEqual, customizer, bitmask, stack); + } + + /** + * A specialized version of `baseIsEqual` for arrays and objects which performs + * deep comparisons and tracks traversed objects enabling objects with circular + * references to be compared. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Function} [customizer] The function to customize comparisons. + * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` + * for more details. + * @param {Object} [stack] Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function baseIsEqualDeep(object, other, equalFunc, customizer, bitmask, stack) { + var objIsArr = isArray(object), + othIsArr = isArray(other), + objTag = arrayTag, + othTag = arrayTag; + + if (!objIsArr) { + objTag = getTag(object); + objTag = objTag == argsTag ? objectTag : objTag; + } + if (!othIsArr) { + othTag = getTag(other); + othTag = othTag == argsTag ? objectTag : othTag; + } + var objIsObj = objTag == objectTag, + othIsObj = othTag == objectTag, + isSameTag = objTag == othTag; + + if (isSameTag && isBuffer(object)) { + if (!isBuffer(other)) { + return false; + } + objIsArr = true; + objIsObj = false; + } + if (isSameTag && !objIsObj) { + stack || (stack = new Stack); + return (objIsArr || isTypedArray(object)) + ? equalArrays(object, other, equalFunc, customizer, bitmask, stack) + : equalByTag(object, other, objTag, equalFunc, customizer, bitmask, stack); + } + if (!(bitmask & PARTIAL_COMPARE_FLAG)) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), + othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); + + if (objIsWrapped || othIsWrapped) { + var objUnwrapped = objIsWrapped ? object.value() : object, + othUnwrapped = othIsWrapped ? other.value() : other; + + stack || (stack = new Stack); + return equalFunc(objUnwrapped, othUnwrapped, customizer, bitmask, stack); + } + } + if (!isSameTag) { + return false; + } + stack || (stack = new Stack); + return equalObjects(object, other, equalFunc, customizer, bitmask, stack); + } + + /** + * The base implementation of `_.isMap` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a map, else `false`. + */ + function baseIsMap(value) { + return isObjectLike(value) && getTag(value) == mapTag; + } + + /** + * The base implementation of `_.isMatch` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @param {Array} matchData The property names, values, and compare flags to match. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + */ + function baseIsMatch(object, source, matchData, customizer) { + var index = matchData.length, + length = index, + noCustomizer = !customizer; + + if (object == null) { + return !length; + } + object = Object(object); + while (index--) { + var data = matchData[index]; + if ((noCustomizer && data[2]) + ? data[1] !== object[data[0]] + : !(data[0] in object) + ) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], + objValue = object[key], + srcValue = data[1]; + + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var stack = new Stack; + if (customizer) { + var result = customizer(objValue, srcValue, key, object, source, stack); + } + if (!(result === undefined + ? baseIsEqual(srcValue, objValue, customizer, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG, stack) + : result + )) { + return false; + } + } + } + return true; + } + + /** + * The base implementation of `_.isNative` without bad shim checks. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + */ + function baseIsNative(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = isFunction(value) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(value)); + } + + /** + * The base implementation of `_.isRegExp` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. + */ + function baseIsRegExp(value) { + return isObject(value) && objectToString.call(value) == regexpTag; + } + + /** + * The base implementation of `_.isSet` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a set, else `false`. + */ + function baseIsSet(value) { + return isObjectLike(value) && getTag(value) == setTag; + } + + /** + * The base implementation of `_.isTypedArray` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + */ + function baseIsTypedArray(value) { + return isObjectLike(value) && + isLength(value.length) && !!typedArrayTags[objectToString.call(value)]; + } + + /** + * The base implementation of `_.iteratee`. + * + * @private + * @param {*} [value=_.identity] The value to convert to an iteratee. + * @returns {Function} Returns the iteratee. + */ + function baseIteratee(value) { + // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9. + // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details. + if (typeof value == 'function') { + return value; + } + if (value == null) { + return identity; + } + if (typeof value == 'object') { + return isArray(value) + ? baseMatchesProperty(value[0], value[1]) + : baseMatches(value); + } + return property(value); + } + + /** + * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function baseKeys(object) { + if (!isPrototype(object)) { + return nativeKeys(object); + } + var result = []; + for (var key in Object(object)) { + if (hasOwnProperty.call(object, key) && key != 'constructor') { + result.push(key); + } + } + return result; + } + + /** + * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function baseKeysIn(object) { + if (!isObject(object)) { + return nativeKeysIn(object); + } + var isProto = isPrototype(object), + result = []; + + for (var key in object) { + if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; + } + + /** + * The base implementation of `_.lt` which doesn't coerce arguments. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than `other`, + * else `false`. + */ + function baseLt(value, other) { + return value < other; + } + + /** + * The base implementation of `_.map` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ + function baseMap(collection, iteratee) { + var index = -1, + result = isArrayLike(collection) ? Array(collection.length) : []; + + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; + } + + /** + * The base implementation of `_.matches` which doesn't clone `source`. + * + * @private + * @param {Object} source The object of property values to match. + * @returns {Function} Returns the new spec function. + */ + function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + return matchesStrictComparable(matchData[0][0], matchData[0][1]); + } + return function(object) { + return object === source || baseIsMatch(object, source, matchData); + }; + } + + /** + * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`. + * + * @private + * @param {string} path The path of the property to get. + * @param {*} srcValue The value to match. + * @returns {Function} Returns the new spec function. + */ + function baseMatchesProperty(path, srcValue) { + if (isKey(path) && isStrictComparable(srcValue)) { + return matchesStrictComparable(toKey(path), srcValue); + } + return function(object) { + var objValue = get(object, path); + return (objValue === undefined && objValue === srcValue) + ? hasIn(object, path) + : baseIsEqual(srcValue, objValue, undefined, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG); + }; + } + + /** + * The base implementation of `_.merge` without support for multiple sources. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {number} srcIndex The index of `source`. + * @param {Function} [customizer] The function to customize merged values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ + function baseMerge(object, source, srcIndex, customizer, stack) { + if (object === source) { + return; + } + baseFor(source, function(srcValue, key) { + if (isObject(srcValue)) { + stack || (stack = new Stack); + baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); + } + else { + var newValue = customizer + ? customizer(object[key], srcValue, (key + ''), object, source, stack) + : undefined; + + if (newValue === undefined) { + newValue = srcValue; + } + assignMergeValue(object, key, newValue); + } + }, keysIn); + } + + /** + * A specialized version of `baseMerge` for arrays and objects which performs + * deep merges and tracks traversed objects enabling objects with circular + * references to be merged. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {string} key The key of the value to merge. + * @param {number} srcIndex The index of `source`. + * @param {Function} mergeFunc The function to merge values. + * @param {Function} [customizer] The function to customize assigned values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ + function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { + var objValue = object[key], + srcValue = source[key], + stacked = stack.get(srcValue); + + if (stacked) { + assignMergeValue(object, key, stacked); + return; + } + var newValue = customizer + ? customizer(objValue, srcValue, (key + ''), object, source, stack) + : undefined; + + var isCommon = newValue === undefined; + + if (isCommon) { + var isArr = isArray(srcValue), + isBuff = !isArr && isBuffer(srcValue), + isTyped = !isArr && !isBuff && isTypedArray(srcValue); + + newValue = srcValue; + if (isArr || isBuff || isTyped) { + if (isArray(objValue)) { + newValue = objValue; + } + else if (isArrayLikeObject(objValue)) { + newValue = copyArray(objValue); + } + else if (isBuff) { + isCommon = false; + newValue = cloneBuffer(srcValue, true); + } + else if (isTyped) { + isCommon = false; + newValue = cloneTypedArray(srcValue, true); + } + else { + newValue = []; + } + } + else if (isPlainObject(srcValue) || isArguments(srcValue)) { + newValue = objValue; + if (isArguments(objValue)) { + newValue = toPlainObject(objValue); + } + else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) { + newValue = initCloneObject(srcValue); + } + } + else { + isCommon = false; + } + } + if (isCommon) { + // Recursively merge objects and arrays (susceptible to call stack limits). + stack.set(srcValue, newValue); + mergeFunc(newValue, srcValue, srcIndex, customizer, stack); + stack['delete'](srcValue); + } + assignMergeValue(object, key, newValue); + } + + /** + * The base implementation of `_.nth` which doesn't coerce arguments. + * + * @private + * @param {Array} array The array to query. + * @param {number} n The index of the element to return. + * @returns {*} Returns the nth element of `array`. + */ + function baseNth(array, n) { + var length = array.length; + if (!length) { + return; + } + n += n < 0 ? length : 0; + return isIndex(n, length) ? array[n] : undefined; + } + + /** + * The base implementation of `_.orderBy` without param guards. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by. + * @param {string[]} orders The sort orders of `iteratees`. + * @returns {Array} Returns the new sorted array. + */ + function baseOrderBy(collection, iteratees, orders) { + var index = -1; + iteratees = arrayMap(iteratees.length ? iteratees : [identity], baseUnary(getIteratee())); + + var result = baseMap(collection, function(value, key, collection) { + var criteria = arrayMap(iteratees, function(iteratee) { + return iteratee(value); + }); + return { 'criteria': criteria, 'index': ++index, 'value': value }; + }); + + return baseSortBy(result, function(object, other) { + return compareMultiple(object, other, orders); + }); + } + + /** + * The base implementation of `_.pick` without support for individual + * property identifiers. + * + * @private + * @param {Object} object The source object. + * @param {string[]} props The property identifiers to pick. + * @returns {Object} Returns the new object. + */ + function basePick(object, props) { + object = Object(object); + return basePickBy(object, props, function(value, key) { + return key in object; + }); + } + + /** + * The base implementation of `_.pickBy` without support for iteratee shorthands. + * + * @private + * @param {Object} object The source object. + * @param {string[]} props The property identifiers to pick from. + * @param {Function} predicate The function invoked per property. + * @returns {Object} Returns the new object. + */ + function basePickBy(object, props, predicate) { + var index = -1, + length = props.length, + result = {}; + + while (++index < length) { + var key = props[index], + value = object[key]; + + if (predicate(value, key)) { + baseAssignValue(result, key, value); + } + } + return result; + } + + /** + * A specialized version of `baseProperty` which supports deep paths. + * + * @private + * @param {Array|string} path The path of the property to get. + * @returns {Function} Returns the new accessor function. + */ + function basePropertyDeep(path) { + return function(object) { + return baseGet(object, path); + }; + } + + /** + * The base implementation of `_.pullAllBy` without support for iteratee + * shorthands. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns `array`. + */ + function basePullAll(array, values, iteratee, comparator) { + var indexOf = comparator ? baseIndexOfWith : baseIndexOf, + index = -1, + length = values.length, + seen = array; + + if (array === values) { + values = copyArray(values); + } + if (iteratee) { + seen = arrayMap(array, baseUnary(iteratee)); + } + while (++index < length) { + var fromIndex = 0, + value = values[index], + computed = iteratee ? iteratee(value) : value; + + while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) { + if (seen !== array) { + splice.call(seen, fromIndex, 1); + } + splice.call(array, fromIndex, 1); + } + } + return array; + } + + /** + * The base implementation of `_.pullAt` without support for individual + * indexes or capturing the removed elements. + * + * @private + * @param {Array} array The array to modify. + * @param {number[]} indexes The indexes of elements to remove. + * @returns {Array} Returns `array`. + */ + function basePullAt(array, indexes) { + var length = array ? indexes.length : 0, + lastIndex = length - 1; + + while (length--) { + var index = indexes[length]; + if (length == lastIndex || index !== previous) { + var previous = index; + if (isIndex(index)) { + splice.call(array, index, 1); + } + else if (!isKey(index, array)) { + var path = castPath(index), + object = parent(array, path); + + if (object != null) { + delete object[toKey(last(path))]; + } + } + else { + delete array[toKey(index)]; + } + } + } + return array; + } + + /** + * The base implementation of `_.random` without support for returning + * floating-point numbers. + * + * @private + * @param {number} lower The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the random number. + */ + function baseRandom(lower, upper) { + return lower + nativeFloor(nativeRandom() * (upper - lower + 1)); + } + + /** + * The base implementation of `_.range` and `_.rangeRight` which doesn't + * coerce arguments. + * + * @private + * @param {number} start The start of the range. + * @param {number} end The end of the range. + * @param {number} step The value to increment or decrement by. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Array} Returns the range of numbers. + */ + function baseRange(start, end, step, fromRight) { + var index = -1, + length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), + result = Array(length); + + while (length--) { + result[fromRight ? length : ++index] = start; + start += step; + } + return result; + } + + /** + * The base implementation of `_.repeat` which doesn't coerce arguments. + * + * @private + * @param {string} string The string to repeat. + * @param {number} n The number of times to repeat the string. + * @returns {string} Returns the repeated string. + */ + function baseRepeat(string, n) { + var result = ''; + if (!string || n < 1 || n > MAX_SAFE_INTEGER) { + return result; + } + // Leverage the exponentiation by squaring algorithm for a faster repeat. + // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details. + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + if (n) { + string += string; + } + } while (n); + + return result; + } + + /** + * The base implementation of `_.rest` which doesn't validate or coerce arguments. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + */ + function baseRest(func, start) { + return setToString(overRest(func, start, identity), func + ''); + } + + /** + * The base implementation of `_.sample`. + * + * @private + * @param {Array|Object} collection The collection to sample. + * @returns {*} Returns the random element. + */ + function baseSample(collection) { + return arraySample(values(collection)); + } + + /** + * The base implementation of `_.sampleSize` without param guards. + * + * @private + * @param {Array|Object} collection The collection to sample. + * @param {number} n The number of elements to sample. + * @returns {Array} Returns the random elements. + */ + function baseSampleSize(collection, n) { + var array = values(collection); + return shuffleSelf(array, baseClamp(n, 0, array.length)); + } + + /** + * The base implementation of `_.set`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @param {Function} [customizer] The function to customize path creation. + * @returns {Object} Returns `object`. + */ + function baseSet(object, path, value, customizer) { + if (!isObject(object)) { + return object; + } + path = isKey(path, object) ? [path] : castPath(path); + + var index = -1, + length = path.length, + lastIndex = length - 1, + nested = object; + + while (nested != null && ++index < length) { + var key = toKey(path[index]), + newValue = value; + + if (index != lastIndex) { + var objValue = nested[key]; + newValue = customizer ? customizer(objValue, key, nested) : undefined; + if (newValue === undefined) { + newValue = isObject(objValue) + ? objValue + : (isIndex(path[index + 1]) ? [] : {}); + } + } + assignValue(nested, key, newValue); + nested = nested[key]; + } + return object; + } + + /** + * The base implementation of `setData` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ + var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; + }; + + /** + * The base implementation of `setToString` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var baseSetToString = !defineProperty ? identity : function(func, string) { + return defineProperty(func, 'toString', { + 'configurable': true, + 'enumerable': false, + 'value': constant(string), + 'writable': true + }); + }; + + /** + * The base implementation of `_.shuffle`. + * + * @private + * @param {Array|Object} collection The collection to shuffle. + * @returns {Array} Returns the new shuffled array. + */ + function baseShuffle(collection) { + return shuffleSelf(values(collection)); + } + + /** + * The base implementation of `_.slice` without an iteratee call guard. + * + * @private + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ + function baseSlice(array, start, end) { + var index = -1, + length = array.length; + + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = end > length ? length : end; + if (end < 0) { + end += length; + } + length = start > end ? 0 : ((end - start) >>> 0); + start >>>= 0; + + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; + } + + /** + * The base implementation of `_.some` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ + function baseSome(collection, predicate) { + var result; + + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; + } + + /** + * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which + * performs a binary search of `array` to determine the index at which `value` + * should be inserted into `array` in order to maintain its sort order. + * + * @private + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {boolean} [retHighest] Specify returning the highest qualified index. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + */ + function baseSortedIndex(array, value, retHighest) { + var low = 0, + high = array ? array.length : low; + + if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = (low + high) >>> 1, + computed = array[mid]; + + if (computed !== null && !isSymbol(computed) && + (retHighest ? (computed <= value) : (computed < value))) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return baseSortedIndexBy(array, value, identity, retHighest); + } + + /** + * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy` + * which invokes `iteratee` for `value` and each element of `array` to compute + * their sort ranking. The iteratee is invoked with one argument; (value). + * + * @private + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} iteratee The iteratee invoked per element. + * @param {boolean} [retHighest] Specify returning the highest qualified index. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + */ + function baseSortedIndexBy(array, value, iteratee, retHighest) { + value = iteratee(value); + + var low = 0, + high = array ? array.length : 0, + valIsNaN = value !== value, + valIsNull = value === null, + valIsSymbol = isSymbol(value), + valIsUndefined = value === undefined; + + while (low < high) { + var mid = nativeFloor((low + high) / 2), + computed = iteratee(array[mid]), + othIsDefined = computed !== undefined, + othIsNull = computed === null, + othIsReflexive = computed === computed, + othIsSymbol = isSymbol(computed); + + if (valIsNaN) { + var setLow = retHighest || othIsReflexive; + } else if (valIsUndefined) { + setLow = othIsReflexive && (retHighest || othIsDefined); + } else if (valIsNull) { + setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull); + } else if (valIsSymbol) { + setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol); + } else if (othIsNull || othIsSymbol) { + setLow = false; + } else { + setLow = retHighest ? (computed <= value) : (computed < value); + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); + } + + /** + * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + */ + function baseSortedUniq(array, iteratee) { + var index = -1, + length = array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + if (!index || !eq(computed, seen)) { + var seen = computed; + result[resIndex++] = value === 0 ? 0 : value; + } + } + return result; + } + + /** + * The base implementation of `_.toNumber` which doesn't ensure correct + * conversions of binary, hexadecimal, or octal string values. + * + * @private + * @param {*} value The value to process. + * @returns {number} Returns the number. + */ + function baseToNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } + return +value; + } + + /** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ + function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isArray(value)) { + // Recursively convert values (susceptible to call stack limits). + return arrayMap(value, baseToString) + ''; + } + if (isSymbol(value)) { + return symbolToString ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + } + + /** + * The base implementation of `_.uniqBy` without support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new duplicate free array. + */ + function baseUniq(array, iteratee, comparator) { + var index = -1, + includes = arrayIncludes, + length = array.length, + isCommon = true, + result = [], + seen = result; + + if (comparator) { + isCommon = false; + includes = arrayIncludesWith; + } + else if (length >= LARGE_ARRAY_SIZE) { + var set = iteratee ? null : createSet(array); + if (set) { + return setToArray(set); + } + isCommon = false; + includes = cacheHas; + seen = new SetCache; + } + else { + seen = iteratee ? [] : result; + } + outer: + while (++index < length) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + value = (comparator || value !== 0) ? value : 0; + if (isCommon && computed === computed) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee) { + seen.push(computed); + } + result.push(value); + } + else if (!includes(seen, computed, comparator)) { + if (seen !== result) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + + /** + * The base implementation of `_.unset`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to unset. + * @returns {boolean} Returns `true` if the property is deleted, else `false`. + */ + function baseUnset(object, path) { + path = isKey(path, object) ? [path] : castPath(path); + object = parent(object, path); + + var key = toKey(last(path)); + return !(object != null && hasOwnProperty.call(object, key)) || delete object[key]; + } + + /** + * The base implementation of `_.update`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to update. + * @param {Function} updater The function to produce the updated value. + * @param {Function} [customizer] The function to customize path creation. + * @returns {Object} Returns `object`. + */ + function baseUpdate(object, path, updater, customizer) { + return baseSet(object, path, updater(baseGet(object, path)), customizer); + } + + /** + * The base implementation of methods like `_.dropWhile` and `_.takeWhile` + * without support for iteratee shorthands. + * + * @private + * @param {Array} array The array to query. + * @param {Function} predicate The function invoked per iteration. + * @param {boolean} [isDrop] Specify dropping elements instead of taking them. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Array} Returns the slice of `array`. + */ + function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, + index = fromRight ? length : -1; + + while ((fromRight ? index-- : ++index < length) && + predicate(array[index], index, array)) {} + + return isDrop + ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length)) + : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index)); + } + + /** + * The base implementation of `wrapperValue` which returns the result of + * performing a sequence of actions on the unwrapped `value`, where each + * successive action is supplied the return value of the previous. + * + * @private + * @param {*} value The unwrapped value. + * @param {Array} actions Actions to perform to resolve the unwrapped value. + * @returns {*} Returns the resolved value. + */ + function baseWrapperValue(value, actions) { + var result = value; + if (result instanceof LazyWrapper) { + result = result.value(); + } + return arrayReduce(actions, function(result, action) { + return action.func.apply(action.thisArg, arrayPush([result], action.args)); + }, result); + } + + /** + * The base implementation of methods like `_.xor`, without support for + * iteratee shorthands, that accepts an array of arrays to inspect. + * + * @private + * @param {Array} arrays The arrays to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of values. + */ + function baseXor(arrays, iteratee, comparator) { + var index = -1, + length = arrays.length; + + while (++index < length) { + var result = result + ? arrayPush( + baseDifference(result, arrays[index], iteratee, comparator), + baseDifference(arrays[index], result, iteratee, comparator) + ) + : arrays[index]; + } + return (result && result.length) ? baseUniq(result, iteratee, comparator) : []; + } + + /** + * This base implementation of `_.zipObject` which assigns values using `assignFunc`. + * + * @private + * @param {Array} props The property identifiers. + * @param {Array} values The property values. + * @param {Function} assignFunc The function to assign values. + * @returns {Object} Returns the new object. + */ + function baseZipObject(props, values, assignFunc) { + var index = -1, + length = props.length, + valsLength = values.length, + result = {}; + + while (++index < length) { + var value = index < valsLength ? values[index] : undefined; + assignFunc(result, props[index], value); + } + return result; + } + + /** + * Casts `value` to an empty array if it's not an array like object. + * + * @private + * @param {*} value The value to inspect. + * @returns {Array|Object} Returns the cast array-like object. + */ + function castArrayLikeObject(value) { + return isArrayLikeObject(value) ? value : []; + } + + /** + * Casts `value` to `identity` if it's not a function. + * + * @private + * @param {*} value The value to inspect. + * @returns {Function} Returns cast function. + */ + function castFunction(value) { + return typeof value == 'function' ? value : identity; + } + + /** + * Casts `value` to a path array if it's not one. + * + * @private + * @param {*} value The value to inspect. + * @returns {Array} Returns the cast property path array. + */ + function castPath(value) { + return isArray(value) ? value : stringToPath(value); + } + + /** + * A `baseRest` alias which can be replaced with `identity` by module + * replacement plugins. + * + * @private + * @type {Function} + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ + var castRest = baseRest; + + /** + * Casts `array` to a slice if it's needed. + * + * @private + * @param {Array} array The array to inspect. + * @param {number} start The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the cast slice. + */ + function castSlice(array, start, end) { + var length = array.length; + end = end === undefined ? length : end; + return (!start && end >= length) ? array : baseSlice(array, start, end); + } + + /** + * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout). + * + * @private + * @param {number|Object} id The timer id or timeout object of the timer to clear. + */ + var clearTimeout = ctxClearTimeout || function(id) { + return root.clearTimeout(id); + }; + + /** + * Creates a clone of `buffer`. + * + * @private + * @param {Buffer} buffer The buffer to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Buffer} Returns the cloned buffer. + */ + function cloneBuffer(buffer, isDeep) { + if (isDeep) { + return buffer.slice(); + } + var length = buffer.length, + result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); + + buffer.copy(result); + return result; + } + + /** + * Creates a clone of `arrayBuffer`. + * + * @private + * @param {ArrayBuffer} arrayBuffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ + function cloneArrayBuffer(arrayBuffer) { + var result = new arrayBuffer.constructor(arrayBuffer.byteLength); + new Uint8Array(result).set(new Uint8Array(arrayBuffer)); + return result; + } + + /** + * Creates a clone of `dataView`. + * + * @private + * @param {Object} dataView The data view to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned data view. + */ + function cloneDataView(dataView, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer; + return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength); + } + + /** + * Creates a clone of `map`. + * + * @private + * @param {Object} map The map to clone. + * @param {Function} cloneFunc The function to clone values. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned map. + */ + function cloneMap(map, isDeep, cloneFunc) { + var array = isDeep ? cloneFunc(mapToArray(map), true) : mapToArray(map); + return arrayReduce(array, addMapEntry, new map.constructor); + } + + /** + * Creates a clone of `regexp`. + * + * @private + * @param {Object} regexp The regexp to clone. + * @returns {Object} Returns the cloned regexp. + */ + function cloneRegExp(regexp) { + var result = new regexp.constructor(regexp.source, reFlags.exec(regexp)); + result.lastIndex = regexp.lastIndex; + return result; + } + + /** + * Creates a clone of `set`. + * + * @private + * @param {Object} set The set to clone. + * @param {Function} cloneFunc The function to clone values. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned set. + */ + function cloneSet(set, isDeep, cloneFunc) { + var array = isDeep ? cloneFunc(setToArray(set), true) : setToArray(set); + return arrayReduce(array, addSetEntry, new set.constructor); + } + + /** + * Creates a clone of the `symbol` object. + * + * @private + * @param {Object} symbol The symbol object to clone. + * @returns {Object} Returns the cloned symbol object. + */ + function cloneSymbol(symbol) { + return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {}; + } + + /** + * Creates a clone of `typedArray`. + * + * @private + * @param {Object} typedArray The typed array to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned typed array. + */ + function cloneTypedArray(typedArray, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; + return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); + } + + /** + * Compares values to sort them in ascending order. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {number} Returns the sort order indicator for `value`. + */ + function compareAscending(value, other) { + if (value !== other) { + var valIsDefined = value !== undefined, + valIsNull = value === null, + valIsReflexive = value === value, + valIsSymbol = isSymbol(value); + + var othIsDefined = other !== undefined, + othIsNull = other === null, + othIsReflexive = other === other, + othIsSymbol = isSymbol(other); + + if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) || + (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) || + (valIsNull && othIsDefined && othIsReflexive) || + (!valIsDefined && othIsReflexive) || + !valIsReflexive) { + return 1; + } + if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) || + (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) || + (othIsNull && valIsDefined && valIsReflexive) || + (!othIsDefined && valIsReflexive) || + !othIsReflexive) { + return -1; + } + } + return 0; + } + + /** + * Used by `_.orderBy` to compare multiple properties of a value to another + * and stable sort them. + * + * If `orders` is unspecified, all values are sorted in ascending order. Otherwise, + * specify an order of "desc" for descending or "asc" for ascending sort order + * of corresponding values. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {boolean[]|string[]} orders The order to sort by for each property. + * @returns {number} Returns the sort order indicator for `object`. + */ + function compareMultiple(object, other, orders) { + var index = -1, + objCriteria = object.criteria, + othCriteria = other.criteria, + length = objCriteria.length, + ordersLength = orders.length; + + while (++index < length) { + var result = compareAscending(objCriteria[index], othCriteria[index]); + if (result) { + if (index >= ordersLength) { + return result; + } + var order = orders[index]; + return result * (order == 'desc' ? -1 : 1); + } + } + // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications + // that causes it, under certain circumstances, to provide the same value for + // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247 + // for more details. + // + // This also ensures a stable sort in V8 and other engines. + // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details. + return object.index - other.index; + } + + /** + * Creates an array that is the composition of partially applied arguments, + * placeholders, and provided arguments into a single array of arguments. + * + * @private + * @param {Array} args The provided arguments. + * @param {Array} partials The arguments to prepend to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @params {boolean} [isCurried] Specify composing for a curried function. + * @returns {Array} Returns the new array of composed arguments. + */ + function composeArgs(args, partials, holders, isCurried) { + var argsIndex = -1, + argsLength = args.length, + holdersLength = holders.length, + leftIndex = -1, + leftLength = partials.length, + rangeLength = nativeMax(argsLength - holdersLength, 0), + result = Array(leftLength + rangeLength), + isUncurried = !isCurried; + + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + if (isUncurried || argsIndex < argsLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + } + while (rangeLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; + } + + /** + * This function is like `composeArgs` except that the arguments composition + * is tailored for `_.partialRight`. + * + * @private + * @param {Array} args The provided arguments. + * @param {Array} partials The arguments to append to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @params {boolean} [isCurried] Specify composing for a curried function. + * @returns {Array} Returns the new array of composed arguments. + */ + function composeArgsRight(args, partials, holders, isCurried) { + var argsIndex = -1, + argsLength = args.length, + holdersIndex = -1, + holdersLength = holders.length, + rightIndex = -1, + rightLength = partials.length, + rangeLength = nativeMax(argsLength - holdersLength, 0), + result = Array(rangeLength + rightLength), + isUncurried = !isCurried; + + while (++argsIndex < rangeLength) { + result[argsIndex] = args[argsIndex]; + } + var offset = argsIndex; + while (++rightIndex < rightLength) { + result[offset + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + if (isUncurried || argsIndex < argsLength) { + result[offset + holders[holdersIndex]] = args[argsIndex++]; + } + } + return result; + } + + /** + * Copies the values of `source` to `array`. + * + * @private + * @param {Array} source The array to copy values from. + * @param {Array} [array=[]] The array to copy values to. + * @returns {Array} Returns `array`. + */ + function copyArray(source, array) { + var index = -1, + length = source.length; + + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; + } + + /** + * Copies properties of `source` to `object`. + * + * @private + * @param {Object} source The object to copy properties from. + * @param {Array} props The property identifiers to copy. + * @param {Object} [object={}] The object to copy properties to. + * @param {Function} [customizer] The function to customize copied values. + * @returns {Object} Returns `object`. + */ + function copyObject(source, props, object, customizer) { + var isNew = !object; + object || (object = {}); + + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + + var newValue = customizer + ? customizer(object[key], source[key], key, object, source) + : undefined; + + if (newValue === undefined) { + newValue = source[key]; + } + if (isNew) { + baseAssignValue(object, key, newValue); + } else { + assignValue(object, key, newValue); + } + } + return object; + } + + /** + * Copies own symbol properties of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ + function copySymbols(source, object) { + return copyObject(source, getSymbols(source), object); + } + + /** + * Creates a function like `_.groupBy`. + * + * @private + * @param {Function} setter The function to set accumulator values. + * @param {Function} [initializer] The accumulator object initializer. + * @returns {Function} Returns the new aggregator function. + */ + function createAggregator(setter, initializer) { + return function(collection, iteratee) { + var func = isArray(collection) ? arrayAggregator : baseAggregator, + accumulator = initializer ? initializer() : {}; + + return func(collection, setter, getIteratee(iteratee, 2), accumulator); + }; + } + + /** + * Creates a function like `_.assign`. + * + * @private + * @param {Function} assigner The function to assign values. + * @returns {Function} Returns the new assigner function. + */ + function createAssigner(assigner) { + return baseRest(function(object, sources) { + var index = -1, + length = sources.length, + customizer = length > 1 ? sources[length - 1] : undefined, + guard = length > 2 ? sources[2] : undefined; + + customizer = (assigner.length > 3 && typeof customizer == 'function') + ? (length--, customizer) + : undefined; + + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + object = Object(object); + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, index, customizer); + } + } + return object; + }); + } + + /** + * Creates a `baseEach` or `baseEachRight` function. + * + * @private + * @param {Function} eachFunc The function to iterate over a collection. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + if (collection == null) { + return collection; + } + if (!isArrayLike(collection)) { + return eachFunc(collection, iteratee); + } + var length = collection.length, + index = fromRight ? length : -1, + iterable = Object(collection); + + while ((fromRight ? index-- : ++index < length)) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; + } + + /** + * Creates a base function for methods like `_.forIn` and `_.forOwn`. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var index = -1, + iterable = Object(object), + props = keysFunc(object), + length = props.length; + + while (length--) { + var key = props[fromRight ? length : ++index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + + /** + * Creates a function that wraps `func` to invoke it with the optional `this` + * binding of `thisArg`. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} [thisArg] The `this` binding of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createBind(func, bitmask, thisArg) { + var isBind = bitmask & BIND_FLAG, + Ctor = createCtor(func); + + function wrapper() { + var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + return fn.apply(isBind ? thisArg : this, arguments); + } + return wrapper; + } + + /** + * Creates a function like `_.lowerFirst`. + * + * @private + * @param {string} methodName The name of the `String` case method to use. + * @returns {Function} Returns the new case function. + */ + function createCaseFirst(methodName) { + return function(string) { + string = toString(string); + + var strSymbols = hasUnicode(string) + ? stringToArray(string) + : undefined; + + var chr = strSymbols + ? strSymbols[0] + : string.charAt(0); + + var trailing = strSymbols + ? castSlice(strSymbols, 1).join('') + : string.slice(1); + + return chr[methodName]() + trailing; + }; + } + + /** + * Creates a function like `_.camelCase`. + * + * @private + * @param {Function} callback The function to combine each word. + * @returns {Function} Returns the new compounder function. + */ + function createCompounder(callback) { + return function(string) { + return arrayReduce(words(deburr(string).replace(reApos, '')), callback, ''); + }; + } + + /** + * Creates a function that produces an instance of `Ctor` regardless of + * whether it was invoked as part of a `new` expression or by `call` or `apply`. + * + * @private + * @param {Function} Ctor The constructor to wrap. + * @returns {Function} Returns the new wrapped function. + */ + function createCtor(Ctor) { + return function() { + // Use a `switch` statement to work with class constructors. See + // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist + // for more details. + var args = arguments; + switch (args.length) { + case 0: return new Ctor; + case 1: return new Ctor(args[0]); + case 2: return new Ctor(args[0], args[1]); + case 3: return new Ctor(args[0], args[1], args[2]); + case 4: return new Ctor(args[0], args[1], args[2], args[3]); + case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]); + case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), + result = Ctor.apply(thisBinding, args); + + // Mimic the constructor's `return` behavior. + // See https://es5.github.io/#x13.2.2 for more details. + return isObject(result) ? result : thisBinding; + }; + } + + /** + * Creates a function that wraps `func` to enable currying. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {number} arity The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createCurry(func, bitmask, arity) { + var Ctor = createCtor(func); + + function wrapper() { + var length = arguments.length, + args = Array(length), + index = length, + placeholder = getHolder(wrapper); + + while (index--) { + args[index] = arguments[index]; + } + var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder) + ? [] + : replaceHolders(args, placeholder); + + length -= holders.length; + if (length < arity) { + return createRecurry( + func, bitmask, createHybrid, wrapper.placeholder, undefined, + args, holders, undefined, undefined, arity - length); + } + var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + return apply(fn, this, args); + } + return wrapper; + } + + /** + * Creates a `_.find` or `_.findLast` function. + * + * @private + * @param {Function} findIndexFunc The function to find the collection index. + * @returns {Function} Returns the new find function. + */ + function createFind(findIndexFunc) { + return function(collection, predicate, fromIndex) { + var iterable = Object(collection); + if (!isArrayLike(collection)) { + var iteratee = getIteratee(predicate, 3); + collection = keys(collection); + predicate = function(key) { return iteratee(iterable[key], key, iterable); }; + } + var index = findIndexFunc(collection, predicate, fromIndex); + return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined; + }; + } + + /** + * Creates a `_.flow` or `_.flowRight` function. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new flow function. + */ + function createFlow(fromRight) { + return flatRest(function(funcs) { + var length = funcs.length, + index = length, + prereq = LodashWrapper.prototype.thru; + + if (fromRight) { + funcs.reverse(); + } + while (index--) { + var func = funcs[index]; + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (prereq && !wrapper && getFuncName(func) == 'wrapper') { + var wrapper = new LodashWrapper([], true); + } + } + index = wrapper ? index : length; + while (++index < length) { + func = funcs[index]; + + var funcName = getFuncName(func), + data = funcName == 'wrapper' ? getData(func) : undefined; + + if (data && isLaziable(data[0]) && + data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && + !data[4].length && data[9] == 1 + ) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = (func.length == 1 && isLaziable(func)) + ? wrapper[funcName]() + : wrapper.thru(func); + } + } + return function() { + var args = arguments, + value = args[0]; + + if (wrapper && args.length == 1 && + isArray(value) && value.length >= LARGE_ARRAY_SIZE) { + return wrapper.plant(value).value(); + } + var index = 0, + result = length ? funcs[index].apply(this, args) : value; + + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + }); + } + + /** + * Creates a function that wraps `func` to invoke it with optional `this` + * binding of `thisArg`, partial application, and currying. + * + * @private + * @param {Function|string} func The function or method name to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to prepend to those provided to + * the new function. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [partialsRight] The arguments to append to those provided + * to the new function. + * @param {Array} [holdersRight] The `partialsRight` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & ARY_FLAG, + isBind = bitmask & BIND_FLAG, + isBindKey = bitmask & BIND_KEY_FLAG, + isCurried = bitmask & (CURRY_FLAG | CURRY_RIGHT_FLAG), + isFlip = bitmask & FLIP_FLAG, + Ctor = isBindKey ? undefined : createCtor(func); + + function wrapper() { + var length = arguments.length, + args = Array(length), + index = length; + + while (index--) { + args[index] = arguments[index]; + } + if (isCurried) { + var placeholder = getHolder(wrapper), + holdersCount = countHolders(args, placeholder); + } + if (partials) { + args = composeArgs(args, partials, holders, isCurried); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight, isCurried); + } + length -= holdersCount; + if (isCurried && length < arity) { + var newHolders = replaceHolders(args, placeholder); + return createRecurry( + func, bitmask, createHybrid, wrapper.placeholder, thisArg, + args, newHolders, argPos, ary, arity - length + ); + } + var thisBinding = isBind ? thisArg : this, + fn = isBindKey ? thisBinding[func] : func; + + length = args.length; + if (argPos) { + args = reorder(args, argPos); + } else if (isFlip && length > 1) { + args.reverse(); + } + if (isAry && ary < length) { + args.length = ary; + } + if (this && this !== root && this instanceof wrapper) { + fn = Ctor || createCtor(fn); + } + return fn.apply(thisBinding, args); + } + return wrapper; + } + + /** + * Creates a function like `_.invertBy`. + * + * @private + * @param {Function} setter The function to set accumulator values. + * @param {Function} toIteratee The function to resolve iteratees. + * @returns {Function} Returns the new inverter function. + */ + function createInverter(setter, toIteratee) { + return function(object, iteratee) { + return baseInverter(object, setter, toIteratee(iteratee), {}); + }; + } + + /** + * Creates a function that performs a mathematical operation on two values. + * + * @private + * @param {Function} operator The function to perform the operation. + * @param {number} [defaultValue] The value used for `undefined` arguments. + * @returns {Function} Returns the new mathematical operation function. + */ + function createMathOperation(operator, defaultValue) { + return function(value, other) { + var result; + if (value === undefined && other === undefined) { + return defaultValue; + } + if (value !== undefined) { + result = value; + } + if (other !== undefined) { + if (result === undefined) { + return other; + } + if (typeof value == 'string' || typeof other == 'string') { + value = baseToString(value); + other = baseToString(other); + } else { + value = baseToNumber(value); + other = baseToNumber(other); + } + result = operator(value, other); + } + return result; + }; + } + + /** + * Creates a function like `_.over`. + * + * @private + * @param {Function} arrayFunc The function to iterate over iteratees. + * @returns {Function} Returns the new over function. + */ + function createOver(arrayFunc) { + return flatRest(function(iteratees) { + iteratees = arrayMap(iteratees, baseUnary(getIteratee())); + return baseRest(function(args) { + var thisArg = this; + return arrayFunc(iteratees, function(iteratee) { + return apply(iteratee, thisArg, args); + }); + }); + }); + } + + /** + * Creates the padding for `string` based on `length`. The `chars` string + * is truncated if the number of characters exceeds `length`. + * + * @private + * @param {number} length The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padding for `string`. + */ + function createPadding(length, chars) { + chars = chars === undefined ? ' ' : baseToString(chars); + + var charsLength = chars.length; + if (charsLength < 2) { + return charsLength ? baseRepeat(chars, length) : chars; + } + var result = baseRepeat(chars, nativeCeil(length / stringSize(chars))); + return hasUnicode(chars) + ? castSlice(stringToArray(result), 0, length).join('') + : result.slice(0, length); + } + + /** + * Creates a function that wraps `func` to invoke it with the `this` binding + * of `thisArg` and `partials` prepended to the arguments it receives. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} partials The arguments to prepend to those provided to + * the new function. + * @returns {Function} Returns the new wrapped function. + */ + function createPartial(func, bitmask, thisArg, partials) { + var isBind = bitmask & BIND_FLAG, + Ctor = createCtor(func); + + function wrapper() { + var argsIndex = -1, + argsLength = arguments.length, + leftIndex = -1, + leftLength = partials.length, + args = Array(leftLength + argsLength), + fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + return apply(fn, isBind ? thisArg : this, args); + } + return wrapper; + } + + /** + * Creates a `_.range` or `_.rangeRight` function. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new range function. + */ + function createRange(fromRight) { + return function(start, end, step) { + if (step && typeof step != 'number' && isIterateeCall(start, end, step)) { + end = step = undefined; + } + // Ensure the sign of `-0` is preserved. + start = toFinite(start); + if (end === undefined) { + end = start; + start = 0; + } else { + end = toFinite(end); + } + step = step === undefined ? (start < end ? 1 : -1) : toFinite(step); + return baseRange(start, end, step, fromRight); + }; + } + + /** + * Creates a function that performs a relational operation on two values. + * + * @private + * @param {Function} operator The function to perform the operation. + * @returns {Function} Returns the new relational operation function. + */ + function createRelationalOperation(operator) { + return function(value, other) { + if (!(typeof value == 'string' && typeof other == 'string')) { + value = toNumber(value); + other = toNumber(other); + } + return operator(value, other); + }; + } + + /** + * Creates a function that wraps `func` to continue currying. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {Function} wrapFunc The function to create the `func` wrapper. + * @param {*} placeholder The placeholder value. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to prepend to those provided to + * the new function. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) { + var isCurry = bitmask & CURRY_FLAG, + newHolders = isCurry ? holders : undefined, + newHoldersRight = isCurry ? undefined : holders, + newPartials = isCurry ? partials : undefined, + newPartialsRight = isCurry ? undefined : partials; + + bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG); + bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); + + if (!(bitmask & CURRY_BOUND_FLAG)) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var newData = [ + func, bitmask, thisArg, newPartials, newHolders, newPartialsRight, + newHoldersRight, argPos, ary, arity + ]; + + var result = wrapFunc.apply(undefined, newData); + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return setWrapToString(result, func, bitmask); + } + + /** + * Creates a function like `_.round`. + * + * @private + * @param {string} methodName The name of the `Math` method to use when rounding. + * @returns {Function} Returns the new round function. + */ + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + number = toNumber(number); + precision = nativeMin(toInteger(precision), 292); + if (precision) { + // Shift with exponential notation to avoid floating-point issues. + // See [MDN](https://mdn.io/round#Examples) for more details. + var pair = (toString(number) + 'e').split('e'), + value = func(pair[0] + 'e' + (+pair[1] + precision)); + + pair = (toString(value) + 'e').split('e'); + return +(pair[0] + 'e' + (+pair[1] - precision)); + } + return func(number); + }; + } + + /** + * Creates a set object of `values`. + * + * @private + * @param {Array} values The values to add to the set. + * @returns {Object} Returns the new set. + */ + var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) { + return new Set(values); + }; + + /** + * Creates a `_.toPairs` or `_.toPairsIn` function. + * + * @private + * @param {Function} keysFunc The function to get the keys of a given object. + * @returns {Function} Returns the new pairs function. + */ + function createToPairs(keysFunc) { + return function(object) { + var tag = getTag(object); + if (tag == mapTag) { + return mapToArray(object); + } + if (tag == setTag) { + return setToPairs(object); + } + return baseToPairs(object, keysFunc(object)); + }; + } + + /** + * Creates a function that either curries or invokes `func` with optional + * `this` binding and partially applied arguments. + * + * @private + * @param {Function|string} func The function or method name to wrap. + * @param {number} bitmask The bitmask flags. + * The bitmask may be composed of the following flags: + * 1 - `_.bind` + * 2 - `_.bindKey` + * 4 - `_.curry` or `_.curryRight` of a bound function + * 8 - `_.curry` + * 16 - `_.curryRight` + * 32 - `_.partial` + * 64 - `_.partialRight` + * 128 - `_.rearg` + * 256 - `_.ary` + * 512 - `_.flip` + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to be partially applied. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & BIND_KEY_FLAG; + if (!isBindKey && typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); + partials = holders = undefined; + } + ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0); + arity = arity === undefined ? arity : toInteger(arity); + length -= holders ? holders.length : 0; + + if (bitmask & PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, + holdersRight = holders; + + partials = holders = undefined; + } + var data = isBindKey ? undefined : getData(func); + + var newData = [ + func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, + argPos, ary, arity + ]; + + if (data) { + mergeData(newData, data); + } + func = newData[0]; + bitmask = newData[1]; + thisArg = newData[2]; + partials = newData[3]; + holders = newData[4]; + arity = newData[9] = newData[9] == null + ? (isBindKey ? 0 : func.length) + : nativeMax(newData[9] - length, 0); + + if (!arity && bitmask & (CURRY_FLAG | CURRY_RIGHT_FLAG)) { + bitmask &= ~(CURRY_FLAG | CURRY_RIGHT_FLAG); + } + if (!bitmask || bitmask == BIND_FLAG) { + var result = createBind(func, bitmask, thisArg); + } else if (bitmask == CURRY_FLAG || bitmask == CURRY_RIGHT_FLAG) { + result = createCurry(func, bitmask, arity); + } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !holders.length) { + result = createPartial(func, bitmask, thisArg, partials); + } else { + result = createHybrid.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setWrapToString(setter(result, newData), func, bitmask); + } + + /** + * A specialized version of `baseIsEqualDeep` for arrays with support for + * partial deep comparisons. + * + * @private + * @param {Array} array The array to compare. + * @param {Array} other The other array to compare. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Function} customizer The function to customize comparisons. + * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual` + * for more details. + * @param {Object} stack Tracks traversed `array` and `other` objects. + * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. + */ + function equalArrays(array, other, equalFunc, customizer, bitmask, stack) { + var isPartial = bitmask & PARTIAL_COMPARE_FLAG, + arrLength = array.length, + othLength = other.length; + + if (arrLength != othLength && !(isPartial && othLength > arrLength)) { + return false; + } + // Assume cyclic values are equal. + var stacked = stack.get(array); + if (stacked && stack.get(other)) { + return stacked == other; + } + var index = -1, + result = true, + seen = (bitmask & UNORDERED_COMPARE_FLAG) ? new SetCache : undefined; + + stack.set(array, other); + stack.set(other, array); + + // Ignore non-index properties. + while (++index < arrLength) { + var arrValue = array[index], + othValue = other[index]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, arrValue, index, other, array, stack) + : customizer(arrValue, othValue, index, array, other, stack); + } + if (compared !== undefined) { + if (compared) { + continue; + } + result = false; + break; + } + // Recursively compare arrays (susceptible to call stack limits). + if (seen) { + if (!arraySome(other, function(othValue, othIndex) { + if (!cacheHas(seen, othIndex) && + (arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack))) { + return seen.push(othIndex); + } + })) { + result = false; + break; + } + } else if (!( + arrValue === othValue || + equalFunc(arrValue, othValue, customizer, bitmask, stack) + )) { + result = false; + break; + } + } + stack['delete'](array); + stack['delete'](other); + return result; + } + + /** + * A specialized version of `baseIsEqualDeep` for comparing objects of + * the same `toStringTag`. + * + * **Note:** This function only supports comparing values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {string} tag The `toStringTag` of the objects to compare. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Function} customizer The function to customize comparisons. + * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual` + * for more details. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalByTag(object, other, tag, equalFunc, customizer, bitmask, stack) { + switch (tag) { + case dataViewTag: + if ((object.byteLength != other.byteLength) || + (object.byteOffset != other.byteOffset)) { + return false; + } + object = object.buffer; + other = other.buffer; + + case arrayBufferTag: + if ((object.byteLength != other.byteLength) || + !equalFunc(new Uint8Array(object), new Uint8Array(other))) { + return false; + } + return true; + + case boolTag: + case dateTag: + case numberTag: + // Coerce booleans to `1` or `0` and dates to milliseconds. + // Invalid dates are coerced to `NaN`. + return eq(+object, +other); + + case errorTag: + return object.name == other.name && object.message == other.message; + + case regexpTag: + case stringTag: + // Coerce regexes to strings and treat strings, primitives and objects, + // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring + // for more details. + return object == (other + ''); + + case mapTag: + var convert = mapToArray; + + case setTag: + var isPartial = bitmask & PARTIAL_COMPARE_FLAG; + convert || (convert = setToArray); + + if (object.size != other.size && !isPartial) { + return false; + } + // Assume cyclic values are equal. + var stacked = stack.get(object); + if (stacked) { + return stacked == other; + } + bitmask |= UNORDERED_COMPARE_FLAG; + + // Recursively compare objects (susceptible to call stack limits). + stack.set(object, other); + var result = equalArrays(convert(object), convert(other), equalFunc, customizer, bitmask, stack); + stack['delete'](object); + return result; + + case symbolTag: + if (symbolValueOf) { + return symbolValueOf.call(object) == symbolValueOf.call(other); + } + } + return false; + } + + /** + * A specialized version of `baseIsEqualDeep` for objects with support for + * partial deep comparisons. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Function} customizer The function to customize comparisons. + * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual` + * for more details. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalObjects(object, other, equalFunc, customizer, bitmask, stack) { + var isPartial = bitmask & PARTIAL_COMPARE_FLAG, + objProps = keys(object), + objLength = objProps.length, + othProps = keys(other), + othLength = othProps.length; + + if (objLength != othLength && !isPartial) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + // Assume cyclic values are equal. + var stacked = stack.get(object); + if (stacked && stack.get(other)) { + return stacked == other; + } + var result = true; + stack.set(object, other); + stack.set(other, object); + + var skipCtor = isPartial; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], + othValue = other[key]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, objValue, key, other, object, stack) + : customizer(objValue, othValue, key, object, other, stack); + } + // Recursively compare objects (susceptible to call stack limits). + if (!(compared === undefined + ? (objValue === othValue || equalFunc(objValue, othValue, customizer, bitmask, stack)) + : compared + )) { + result = false; + break; + } + skipCtor || (skipCtor = key == 'constructor'); + } + if (result && !skipCtor) { + var objCtor = object.constructor, + othCtor = other.constructor; + + // Non `Object` object instances with different constructors are not equal. + if (objCtor != othCtor && + ('constructor' in object && 'constructor' in other) && + !(typeof objCtor == 'function' && objCtor instanceof objCtor && + typeof othCtor == 'function' && othCtor instanceof othCtor)) { + result = false; + } + } + stack['delete'](object); + stack['delete'](other); + return result; + } + + /** + * A specialized version of `baseRest` which flattens the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ + function flatRest(func) { + return setToString(overRest(func, undefined, flatten), func + ''); + } + + /** + * Creates an array of own enumerable property names and symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ + function getAllKeys(object) { + return baseGetAllKeys(object, keys, getSymbols); + } + + /** + * Creates an array of own and inherited enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ + function getAllKeysIn(object) { + return baseGetAllKeys(object, keysIn, getSymbolsIn); + } + + /** + * Gets metadata for `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {*} Returns the metadata for `func`. + */ + var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); + }; + + /** + * Gets the name of `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {string} Returns the function name. + */ + function getFuncName(func) { + var result = (func.name + ''), + array = realNames[result], + length = hasOwnProperty.call(realNames, result) ? array.length : 0; + + while (length--) { + var data = array[length], + otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; + } + + /** + * Gets the argument placeholder value for `func`. + * + * @private + * @param {Function} func The function to inspect. + * @returns {*} Returns the placeholder value. + */ + function getHolder(func) { + var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func; + return object.placeholder; + } + + /** + * Gets the appropriate "iteratee" function. If `_.iteratee` is customized, + * this function returns the custom method, otherwise it returns `baseIteratee`. + * If arguments are provided, the chosen function is invoked with them and + * its result is returned. + * + * @private + * @param {*} [value] The value to convert to an iteratee. + * @param {number} [arity] The arity of the created iteratee. + * @returns {Function} Returns the chosen function or its result. + */ + function getIteratee() { + var result = lodash.iteratee || iteratee; + result = result === iteratee ? baseIteratee : result; + return arguments.length ? result(arguments[0], arguments[1]) : result; + } + + /** + * Gets the data for `map`. + * + * @private + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. + */ + function getMapData(map, key) { + var data = map.__data__; + return isKeyable(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; + } + + /** + * Gets the property names, values, and compare flags of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the match data of `object`. + */ + function getMatchData(object) { + var result = keys(object), + length = result.length; + + while (length--) { + var key = result[length], + value = object[key]; + + result[length] = [key, value, isStrictComparable(value)]; + } + return result; + } + + /** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ + function getNative(object, key) { + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined; + } + + /** + * Creates an array of the own enumerable symbol properties of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ + var getSymbols = nativeGetSymbols ? overArg(nativeGetSymbols, Object) : stubArray; + + /** + * Creates an array of the own and inherited enumerable symbol properties + * of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ + var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) { + var result = []; + while (object) { + arrayPush(result, getSymbols(object)); + object = getPrototype(object); + } + return result; + }; + + /** + * Gets the `toStringTag` of `value`. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + var getTag = baseGetTag; + + // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. + if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || + (Map && getTag(new Map) != mapTag) || + (Promise && getTag(Promise.resolve()) != promiseTag) || + (Set && getTag(new Set) != setTag) || + (WeakMap && getTag(new WeakMap) != weakMapTag)) { + getTag = function(value) { + var result = objectToString.call(value), + Ctor = result == objectTag ? value.constructor : undefined, + ctorString = Ctor ? toSource(Ctor) : undefined; + + if (ctorString) { + switch (ctorString) { + case dataViewCtorString: return dataViewTag; + case mapCtorString: return mapTag; + case promiseCtorString: return promiseTag; + case setCtorString: return setTag; + case weakMapCtorString: return weakMapTag; + } + } + return result; + }; + } + + /** + * Gets the view, applying any `transforms` to the `start` and `end` positions. + * + * @private + * @param {number} start The start of the view. + * @param {number} end The end of the view. + * @param {Array} transforms The transformations to apply to the view. + * @returns {Object} Returns an object containing the `start` and `end` + * positions of the view. + */ + function getView(start, end, transforms) { + var index = -1, + length = transforms.length; + + while (++index < length) { + var data = transforms[index], + size = data.size; + + switch (data.type) { + case 'drop': start += size; break; + case 'dropRight': end -= size; break; + case 'take': end = nativeMin(end, start + size); break; + case 'takeRight': start = nativeMax(start, end - size); break; + } + } + return { 'start': start, 'end': end }; + } + + /** + * Extracts wrapper details from the `source` body comment. + * + * @private + * @param {string} source The source to inspect. + * @returns {Array} Returns the wrapper details. + */ + function getWrapDetails(source) { + var match = source.match(reWrapDetails); + return match ? match[1].split(reSplitDetails) : []; + } + + /** + * Checks if `path` exists on `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @param {Function} hasFunc The function to check properties. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + */ + function hasPath(object, path, hasFunc) { + path = isKey(path, object) ? [path] : castPath(path); + + var index = -1, + length = path.length, + result = false; + + while (++index < length) { + var key = toKey(path[index]); + if (!(result = object != null && hasFunc(object, key))) { + break; + } + object = object[key]; + } + if (result || ++index != length) { + return result; + } + length = object ? object.length : 0; + return !!length && isLength(length) && isIndex(key, length) && + (isArray(object) || isArguments(object)); + } + + /** + * Initializes an array clone. + * + * @private + * @param {Array} array The array to clone. + * @returns {Array} Returns the initialized clone. + */ + function initCloneArray(array) { + var length = array.length, + result = array.constructor(length); + + // Add properties assigned by `RegExp#exec`. + if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { + result.index = array.index; + result.input = array.input; + } + return result; + } + + /** + * Initializes an object clone. + * + * @private + * @param {Object} object The object to clone. + * @returns {Object} Returns the initialized clone. + */ + function initCloneObject(object) { + return (typeof object.constructor == 'function' && !isPrototype(object)) + ? baseCreate(getPrototype(object)) + : {}; + } + + /** + * Initializes an object clone based on its `toStringTag`. + * + * **Note:** This function only supports cloning values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} object The object to clone. + * @param {string} tag The `toStringTag` of the object to clone. + * @param {Function} cloneFunc The function to clone values. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the initialized clone. + */ + function initCloneByTag(object, tag, cloneFunc, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return cloneArrayBuffer(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case dataViewTag: + return cloneDataView(object, isDeep); + + case float32Tag: case float64Tag: + case int8Tag: case int16Tag: case int32Tag: + case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: + return cloneTypedArray(object, isDeep); + + case mapTag: + return cloneMap(object, isDeep, cloneFunc); + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + return cloneRegExp(object); + + case setTag: + return cloneSet(object, isDeep, cloneFunc); + + case symbolTag: + return cloneSymbol(object); + } + } + + /** + * Inserts wrapper `details` in a comment at the top of the `source` body. + * + * @private + * @param {string} source The source to modify. + * @returns {Array} details The details to insert. + * @returns {string} Returns the modified source. + */ + function insertWrapDetails(source, details) { + var length = details.length; + if (!length) { + return source; + } + var lastIndex = length - 1; + details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex]; + details = details.join(length > 2 ? ', ' : ' '); + return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n'); + } + + /** + * Checks if `value` is a flattenable `arguments` object or array. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is flattenable, else `false`. + */ + function isFlattenable(value) { + return isArray(value) || isArguments(value) || + !!(spreadableSymbol && value && value[spreadableSymbol]); + } + + /** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ + function isIndex(value, length) { + length = length == null ? MAX_SAFE_INTEGER : length; + return !!length && + (typeof value == 'number' || reIsUint.test(value)) && + (value > -1 && value % 1 == 0 && value < length); + } + + /** + * Checks if the given arguments are from an iteratee call. + * + * @private + * @param {*} value The potential iteratee value argument. + * @param {*} index The potential iteratee index or key argument. + * @param {*} object The potential iteratee object argument. + * @returns {boolean} Returns `true` if the arguments are from an iteratee call, + * else `false`. + */ + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == 'number' + ? (isArrayLike(object) && isIndex(index, object.length)) + : (type == 'string' && index in object) + ) { + return eq(object[index], value); + } + return false; + } + + /** + * Checks if `value` is a property name and not a property path. + * + * @private + * @param {*} value The value to check. + * @param {Object} [object] The object to query keys on. + * @returns {boolean} Returns `true` if `value` is a property name, else `false`. + */ + function isKey(value, object) { + if (isArray(value)) { + return false; + } + var type = typeof value; + if (type == 'number' || type == 'symbol' || type == 'boolean' || + value == null || isSymbol(value)) { + return true; + } + return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || + (object != null && value in Object(object)); + } + + /** + * Checks if `value` is suitable for use as unique object key. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is suitable, else `false`. + */ + function isKeyable(value) { + var type = typeof value; + return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') + ? (value !== '__proto__') + : (value === null); + } + + /** + * Checks if `func` has a lazy counterpart. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` has a lazy counterpart, + * else `false`. + */ + function isLaziable(func) { + var funcName = getFuncName(func), + other = lodash[funcName]; + + if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) { + return false; + } + if (func === other) { + return true; + } + var data = getData(other); + return !!data && func === data[0]; + } + + /** + * Checks if `func` has its source masked. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is masked, else `false`. + */ + function isMasked(func) { + return !!maskSrcKey && (maskSrcKey in func); + } + + /** + * Checks if `func` is capable of being masked. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `func` is maskable, else `false`. + */ + var isMaskable = coreJsData ? isFunction : stubFalse; + + /** + * Checks if `value` is likely a prototype object. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. + */ + function isPrototype(value) { + var Ctor = value && value.constructor, + proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; + + return value === proto; + } + + /** + * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` if suitable for strict + * equality comparisons, else `false`. + */ + function isStrictComparable(value) { + return value === value && !isObject(value); + } + + /** + * A specialized version of `matchesProperty` for source values suitable + * for strict equality comparisons, i.e. `===`. + * + * @private + * @param {string} key The key of the property to get. + * @param {*} srcValue The value to match. + * @returns {Function} Returns the new spec function. + */ + function matchesStrictComparable(key, srcValue) { + return function(object) { + if (object == null) { + return false; + } + return object[key] === srcValue && + (srcValue !== undefined || (key in Object(object))); + }; + } + + /** + * A specialized version of `_.memoize` which clears the memoized function's + * cache when it exceeds `MAX_MEMOIZE_SIZE`. + * + * @private + * @param {Function} func The function to have its output memoized. + * @returns {Function} Returns the new memoized function. + */ + function memoizeCapped(func) { + var result = memoize(func, function(key) { + if (cache.size === MAX_MEMOIZE_SIZE) { + cache.clear(); + } + return key; + }); + + var cache = result.cache; + return result; + } + + /** + * Merges the function metadata of `source` into `data`. + * + * Merging metadata reduces the number of wrappers used to invoke a function. + * This is possible because methods like `_.bind`, `_.curry`, and `_.partial` + * may be applied regardless of execution order. Methods like `_.ary` and + * `_.rearg` modify function arguments, making the order in which they are + * executed important, preventing the merging of metadata. However, we make + * an exception for a safe combined case where curried functions have `_.ary` + * and or `_.rearg` applied. + * + * @private + * @param {Array} data The destination metadata. + * @param {Array} source The source metadata. + * @returns {Array} Returns `data`. + */ + function mergeData(data, source) { + var bitmask = data[1], + srcBitmask = source[1], + newBitmask = bitmask | srcBitmask, + isCommon = newBitmask < (BIND_FLAG | BIND_KEY_FLAG | ARY_FLAG); + + var isCombo = + ((srcBitmask == ARY_FLAG) && (bitmask == CURRY_FLAG)) || + ((srcBitmask == ARY_FLAG) && (bitmask == REARG_FLAG) && (data[7].length <= source[8])) || + ((srcBitmask == (ARY_FLAG | REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == CURRY_FLAG)); + + // Exit early if metadata can't be merged. + if (!(isCommon || isCombo)) { + return data; + } + // Use source `thisArg` if available. + if (srcBitmask & BIND_FLAG) { + data[2] = source[2]; + // Set when currying a bound function. + newBitmask |= bitmask & BIND_FLAG ? 0 : CURRY_BOUND_FLAG; + } + // Compose partial arguments. + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : value; + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4]; + } + // Compose partial right arguments. + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : value; + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6]; + } + // Use source `argPos` if available. + value = source[7]; + if (value) { + data[7] = value; + } + // Use source `ary` if it's smaller. + if (srcBitmask & ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + // Use source `arity` if one is not provided. + if (data[9] == null) { + data[9] = source[9]; + } + // Use source `func` and merge bitmasks. + data[0] = source[0]; + data[1] = newBitmask; + + return data; + } + + /** + * Used by `_.defaultsDeep` to customize its `_.merge` use. + * + * @private + * @param {*} objValue The destination value. + * @param {*} srcValue The source value. + * @param {string} key The key of the property to merge. + * @param {Object} object The parent object of `objValue`. + * @param {Object} source The parent object of `srcValue`. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + * @returns {*} Returns the value to assign. + */ + function mergeDefaults(objValue, srcValue, key, object, source, stack) { + if (isObject(objValue) && isObject(srcValue)) { + // Recursively merge objects and arrays (susceptible to call stack limits). + stack.set(srcValue, objValue); + baseMerge(objValue, srcValue, undefined, mergeDefaults, stack); + stack['delete'](srcValue); + } + return objValue; + } + + /** + * This function is like + * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * except that it includes inherited enumerable properties. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function nativeKeysIn(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } + } + return result; + } + + /** + * A specialized version of `baseRest` which transforms the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @param {Function} transform The rest array transform. + * @returns {Function} Returns the new function. + */ + function overRest(func, start, transform) { + start = nativeMax(start === undefined ? (func.length - 1) : start, 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + array = Array(length); + + while (++index < length) { + array[index] = args[start + index]; + } + index = -1; + var otherArgs = Array(start + 1); + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = transform(array); + return apply(func, this, otherArgs); + }; + } + + /** + * Gets the parent value at `path` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} path The path to get the parent value of. + * @returns {*} Returns the parent value. + */ + function parent(object, path) { + return path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + } + + /** + * Reorder `array` according to the specified indexes where the element at + * the first index is assigned as the first element, the element at + * the second index is assigned as the second element, and so on. + * + * @private + * @param {Array} array The array to reorder. + * @param {Array} indexes The arranged array indexes. + * @returns {Array} Returns `array`. + */ + function reorder(array, indexes) { + var arrLength = array.length, + length = nativeMin(indexes.length, arrLength), + oldArray = copyArray(array); + + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; + } + + /** + * Sets metadata for `func`. + * + * **Note:** If this function becomes hot, i.e. is invoked a lot in a short + * period of time, it will trip its breaker and transition to an identity + * function to avoid garbage collection pauses in V8. See + * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070) + * for more details. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ + var setData = shortOut(baseSetData); + + /** + * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout). + * + * @private + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @returns {number|Object} Returns the timer id or timeout object. + */ + var setTimeout = ctxSetTimeout || function(func, wait) { + return root.setTimeout(func, wait); + }; + + /** + * Sets the `toString` method of `func` to return `string`. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var setToString = shortOut(baseSetToString); + + /** + * Sets the `toString` method of `wrapper` to mimic the source of `reference` + * with wrapper details in a comment at the top of the source body. + * + * @private + * @param {Function} wrapper The function to modify. + * @param {Function} reference The reference function. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @returns {Function} Returns `wrapper`. + */ + function setWrapToString(wrapper, reference, bitmask) { + var source = (reference + ''); + return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask))); + } + + /** + * Creates a function that'll short out and invoke `identity` instead + * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` + * milliseconds. + * + * @private + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new shortable function. + */ + function shortOut(func) { + var count = 0, + lastCalled = 0; + + return function() { + var stamp = nativeNow(), + remaining = HOT_SPAN - (stamp - lastCalled); + + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return arguments[0]; + } + } else { + count = 0; + } + return func.apply(undefined, arguments); + }; + } + + /** + * A specialized version of `_.shuffle` which mutates and sets the size of `array`. + * + * @private + * @param {Array} array The array to shuffle. + * @param {number} [size=array.length] The size of `array`. + * @returns {Array} Returns `array`. + */ + function shuffleSelf(array, size) { + var index = -1, + length = array.length, + lastIndex = length - 1; + + size = size === undefined ? length : size; + while (++index < size) { + var rand = baseRandom(index, lastIndex), + value = array[rand]; + + array[rand] = array[index]; + array[index] = value; + } + array.length = size; + return array; + } + + /** + * Converts `string` to a property path array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the property path array. + */ + var stringToPath = memoizeCapped(function(string) { + string = toString(string); + + var result = []; + if (reLeadingDot.test(string)) { + result.push(''); + } + string.replace(rePropName, function(match, number, quote, string) { + result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match)); + }); + return result; + }); + + /** + * Converts `value` to a string key if it's not a string or symbol. + * + * @private + * @param {*} value The value to inspect. + * @returns {string|symbol} Returns the key. + */ + function toKey(value) { + if (typeof value == 'string' || isSymbol(value)) { + return value; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + } + + /** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to process. + * @returns {string} Returns the source code. + */ + function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) {} + try { + return (func + ''); + } catch (e) {} + } + return ''; + } + + /** + * Updates wrapper `details` based on `bitmask` flags. + * + * @private + * @returns {Array} details The details to modify. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @returns {Array} Returns `details`. + */ + function updateWrapDetails(details, bitmask) { + arrayEach(wrapFlags, function(pair) { + var value = '_.' + pair[0]; + if ((bitmask & pair[1]) && !arrayIncludes(details, value)) { + details.push(value); + } + }); + return details.sort(); + } + + /** + * Creates a clone of `wrapper`. + * + * @private + * @param {Object} wrapper The wrapper to clone. + * @returns {Object} Returns the cloned wrapper. + */ + function wrapperClone(wrapper) { + if (wrapper instanceof LazyWrapper) { + return wrapper.clone(); + } + var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__); + result.__actions__ = copyArray(wrapper.__actions__); + result.__index__ = wrapper.__index__; + result.__values__ = wrapper.__values__; + return result; + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates an array of elements split into groups the length of `size`. + * If `array` can't be split evenly, the final chunk will be the remaining + * elements. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to process. + * @param {number} [size=1] The length of each chunk + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the new array of chunks. + * @example + * + * _.chunk(['a', 'b', 'c', 'd'], 2); + * // => [['a', 'b'], ['c', 'd']] + * + * _.chunk(['a', 'b', 'c', 'd'], 3); + * // => [['a', 'b', 'c'], ['d']] + */ + function chunk(array, size, guard) { + if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) { + size = 1; + } else { + size = nativeMax(toInteger(size), 0); + } + var length = array ? array.length : 0; + if (!length || size < 1) { + return []; + } + var index = 0, + resIndex = 0, + result = Array(nativeCeil(length / size)); + + while (index < length) { + result[resIndex++] = baseSlice(array, index, (index += size)); + } + return result; + } + + /** + * Creates an array with all falsey values removed. The values `false`, `null`, + * `0`, `""`, `undefined`, and `NaN` are falsey. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to compact. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.compact([0, 1, false, 2, '', 3]); + * // => [1, 2, 3] + */ + function compact(array) { + var index = -1, + length = array ? array.length : 0, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (value) { + result[resIndex++] = value; + } + } + return result; + } + + /** + * Creates a new array concatenating `array` with any additional arrays + * and/or values. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to concatenate. + * @param {...*} [values] The values to concatenate. + * @returns {Array} Returns the new concatenated array. + * @example + * + * var array = [1]; + * var other = _.concat(array, 2, [3], [[4]]); + * + * console.log(other); + * // => [1, 2, 3, [4]] + * + * console.log(array); + * // => [1] + */ + function concat() { + var length = arguments.length; + if (!length) { + return []; + } + var args = Array(length - 1), + array = arguments[0], + index = length; + + while (index--) { + args[index - 1] = arguments[index]; + } + return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)); + } + + /** + * Creates an array of `array` values not included in the other given arrays + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. The order and references of result values are + * determined by the first array. + * + * **Note:** Unlike `_.pullAll`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @returns {Array} Returns the new array of filtered values. + * @see _.without, _.xor + * @example + * + * _.difference([2, 1], [2, 3]); + * // => [1] + */ + var difference = baseRest(function(array, values) { + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true)) + : []; + }); + + /** + * This method is like `_.difference` except that it accepts `iteratee` which + * is invoked for each element of `array` and `values` to generate the criterion + * by which they're compared. The order and references of result values are + * determined by the first array. The iteratee is invoked with one argument: + * (value). + * + * **Note:** Unlike `_.pullAllBy`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [1.2] + * + * // The `_.property` iteratee shorthand. + * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x'); + * // => [{ 'x': 2 }] + */ + var differenceBy = baseRest(function(array, values) { + var iteratee = last(values); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)) + : []; + }); + + /** + * This method is like `_.difference` except that it accepts `comparator` + * which is invoked to compare elements of `array` to `values`. The order and + * references of result values are determined by the first array. The comparator + * is invoked with two arguments: (arrVal, othVal). + * + * **Note:** Unlike `_.pullAllWith`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * + * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual); + * // => [{ 'x': 2, 'y': 1 }] + */ + var differenceWith = baseRest(function(array, values) { + var comparator = last(values); + if (isArrayLikeObject(comparator)) { + comparator = undefined; + } + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator) + : []; + }); + + /** + * Creates a slice of `array` with `n` elements dropped from the beginning. + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to drop. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.drop([1, 2, 3]); + * // => [2, 3] + * + * _.drop([1, 2, 3], 2); + * // => [3] + * + * _.drop([1, 2, 3], 5); + * // => [] + * + * _.drop([1, 2, 3], 0); + * // => [1, 2, 3] + */ + function drop(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + return baseSlice(array, n < 0 ? 0 : n, length); + } + + /** + * Creates a slice of `array` with `n` elements dropped from the end. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to drop. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.dropRight([1, 2, 3]); + * // => [1, 2] + * + * _.dropRight([1, 2, 3], 2); + * // => [1] + * + * _.dropRight([1, 2, 3], 5); + * // => [] + * + * _.dropRight([1, 2, 3], 0); + * // => [1, 2, 3] + */ + function dropRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + n = length - n; + return baseSlice(array, 0, n < 0 ? 0 : n); + } + + /** + * Creates a slice of `array` excluding elements dropped from the end. + * Elements are dropped until `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.dropRightWhile(users, function(o) { return !o.active; }); + * // => objects for ['barney'] + * + * // The `_.matches` iteratee shorthand. + * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false }); + * // => objects for ['barney', 'fred'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.dropRightWhile(users, ['active', false]); + * // => objects for ['barney'] + * + * // The `_.property` iteratee shorthand. + * _.dropRightWhile(users, 'active'); + * // => objects for ['barney', 'fred', 'pebbles'] + */ + function dropRightWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3), true, true) + : []; + } + + /** + * Creates a slice of `array` excluding elements dropped from the beginning. + * Elements are dropped until `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] + * The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.dropWhile(users, function(o) { return !o.active; }); + * // => objects for ['pebbles'] + * + * // The `_.matches` iteratee shorthand. + * _.dropWhile(users, { 'user': 'barney', 'active': false }); + * // => objects for ['fred', 'pebbles'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.dropWhile(users, ['active', false]); + * // => objects for ['pebbles'] + * + * // The `_.property` iteratee shorthand. + * _.dropWhile(users, 'active'); + * // => objects for ['barney', 'fred', 'pebbles'] + */ + function dropWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3), true) + : []; + } + + /** + * Fills elements of `array` with `value` from `start` up to, but not + * including, `end`. + * + * **Note:** This method mutates `array`. + * + * @static + * @memberOf _ + * @since 3.2.0 + * @category Array + * @param {Array} array The array to fill. + * @param {*} value The value to fill `array` with. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns `array`. + * @example + * + * var array = [1, 2, 3]; + * + * _.fill(array, 'a'); + * console.log(array); + * // => ['a', 'a', 'a'] + * + * _.fill(Array(3), 2); + * // => [2, 2, 2] + * + * _.fill([4, 6, 8, 10], '*', 1, 3); + * // => [4, '*', '*', 10] + */ + function fill(array, value, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (start && typeof start != 'number' && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + + /** + * This method is like `_.find` except that it returns the index of the first + * element `predicate` returns truthy for instead of the element itself. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [predicate=_.identity] + * The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. + * @returns {number} Returns the index of the found element, else `-1`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.findIndex(users, function(o) { return o.user == 'barney'; }); + * // => 0 + * + * // The `_.matches` iteratee shorthand. + * _.findIndex(users, { 'user': 'fred', 'active': false }); + * // => 1 + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findIndex(users, ['active', false]); + * // => 0 + * + * // The `_.property` iteratee shorthand. + * _.findIndex(users, 'active'); + * // => 2 + */ + function findIndex(array, predicate, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax(length + index, 0); + } + return baseFindIndex(array, getIteratee(predicate, 3), index); + } + + /** + * This method is like `_.findIndex` except that it iterates over elements + * of `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [predicate=_.identity] + * The function invoked per iteration. + * @param {number} [fromIndex=array.length-1] The index to search from. + * @returns {number} Returns the index of the found element, else `-1`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; }); + * // => 2 + * + * // The `_.matches` iteratee shorthand. + * _.findLastIndex(users, { 'user': 'barney', 'active': true }); + * // => 0 + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findLastIndex(users, ['active', false]); + * // => 2 + * + * // The `_.property` iteratee shorthand. + * _.findLastIndex(users, 'active'); + * // => 0 + */ + function findLastIndex(array, predicate, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + var index = length - 1; + if (fromIndex !== undefined) { + index = toInteger(fromIndex); + index = fromIndex < 0 + ? nativeMax(length + index, 0) + : nativeMin(index, length - 1); + } + return baseFindIndex(array, getIteratee(predicate, 3), index, true); + } + + /** + * Flattens `array` a single level deep. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flatten([1, [2, [3, [4]], 5]]); + * // => [1, 2, [3, [4]], 5] + */ + function flatten(array) { + var length = array ? array.length : 0; + return length ? baseFlatten(array, 1) : []; + } + + /** + * Recursively flattens `array`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flattenDeep([1, [2, [3, [4]], 5]]); + * // => [1, 2, 3, 4, 5] + */ + function flattenDeep(array) { + var length = array ? array.length : 0; + return length ? baseFlatten(array, INFINITY) : []; + } + + /** + * Recursively flatten `array` up to `depth` times. + * + * @static + * @memberOf _ + * @since 4.4.0 + * @category Array + * @param {Array} array The array to flatten. + * @param {number} [depth=1] The maximum recursion depth. + * @returns {Array} Returns the new flattened array. + * @example + * + * var array = [1, [2, [3, [4]], 5]]; + * + * _.flattenDepth(array, 1); + * // => [1, 2, [3, [4]], 5] + * + * _.flattenDepth(array, 2); + * // => [1, 2, 3, [4], 5] + */ + function flattenDepth(array, depth) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + depth = depth === undefined ? 1 : toInteger(depth); + return baseFlatten(array, depth); + } + + /** + * The inverse of `_.toPairs`; this method returns an object composed + * from key-value `pairs`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} pairs The key-value pairs. + * @returns {Object} Returns the new object. + * @example + * + * _.fromPairs([['a', 1], ['b', 2]]); + * // => { 'a': 1, 'b': 2 } + */ + function fromPairs(pairs) { + var index = -1, + length = pairs ? pairs.length : 0, + result = {}; + + while (++index < length) { + var pair = pairs[index]; + result[pair[0]] = pair[1]; + } + return result; + } + + /** + * Gets the first element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @alias first + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the first element of `array`. + * @example + * + * _.head([1, 2, 3]); + * // => 1 + * + * _.head([]); + * // => undefined + */ + function head(array) { + return (array && array.length) ? array[0] : undefined; + } + + /** + * Gets the index at which the first occurrence of `value` is found in `array` + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. If `fromIndex` is negative, it's used as the + * offset from the end of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=0] The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.indexOf([1, 2, 1, 2], 2); + * // => 1 + * + * // Search from the `fromIndex`. + * _.indexOf([1, 2, 1, 2], 2, 2); + * // => 3 + */ + function indexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax(length + index, 0); + } + return baseIndexOf(array, value, index); + } + + /** + * Gets all but the last element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.initial([1, 2, 3]); + * // => [1, 2] + */ + function initial(array) { + var length = array ? array.length : 0; + return length ? baseSlice(array, 0, -1) : []; + } + + /** + * Creates an array of unique values that are included in all given arrays + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. The order and references of result values are + * determined by the first array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * _.intersection([2, 1], [2, 3]); + * // => [2] + */ + var intersection = baseRest(function(arrays) { + var mapped = arrayMap(arrays, castArrayLikeObject); + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped) + : []; + }); + + /** + * This method is like `_.intersection` except that it accepts `iteratee` + * which is invoked for each element of each `arrays` to generate the criterion + * by which they're compared. The order and references of result values are + * determined by the first array. The iteratee is invoked with one argument: + * (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [2.1] + * + * // The `_.property` iteratee shorthand. + * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }] + */ + var intersectionBy = baseRest(function(arrays) { + var iteratee = last(arrays), + mapped = arrayMap(arrays, castArrayLikeObject); + + if (iteratee === last(mapped)) { + iteratee = undefined; + } else { + mapped.pop(); + } + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped, getIteratee(iteratee, 2)) + : []; + }); + + /** + * This method is like `_.intersection` except that it accepts `comparator` + * which is invoked to compare elements of `arrays`. The order and references + * of result values are determined by the first array. The comparator is + * invoked with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.intersectionWith(objects, others, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }] + */ + var intersectionWith = baseRest(function(arrays) { + var comparator = last(arrays), + mapped = arrayMap(arrays, castArrayLikeObject); + + if (comparator === last(mapped)) { + comparator = undefined; + } else { + mapped.pop(); + } + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped, undefined, comparator) + : []; + }); + + /** + * Converts all elements in `array` into a string separated by `separator`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to convert. + * @param {string} [separator=','] The element separator. + * @returns {string} Returns the joined string. + * @example + * + * _.join(['a', 'b', 'c'], '~'); + * // => 'a~b~c' + */ + function join(array, separator) { + return array ? nativeJoin.call(array, separator) : ''; + } + + /** + * Gets the last element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the last element of `array`. + * @example + * + * _.last([1, 2, 3]); + * // => 3 + */ + function last(array) { + var length = array ? array.length : 0; + return length ? array[length - 1] : undefined; + } + + /** + * This method is like `_.indexOf` except that it iterates over elements of + * `array` from right to left. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=array.length-1] The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.lastIndexOf([1, 2, 1, 2], 2); + * // => 3 + * + * // Search from the `fromIndex`. + * _.lastIndexOf([1, 2, 1, 2], 2, 2); + * // => 1 + */ + function lastIndexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + var index = length; + if (fromIndex !== undefined) { + index = toInteger(fromIndex); + index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1); + } + return value === value + ? strictLastIndexOf(array, value, index) + : baseFindIndex(array, baseIsNaN, index, true); + } + + /** + * Gets the element at index `n` of `array`. If `n` is negative, the nth + * element from the end is returned. + * + * @static + * @memberOf _ + * @since 4.11.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=0] The index of the element to return. + * @returns {*} Returns the nth element of `array`. + * @example + * + * var array = ['a', 'b', 'c', 'd']; + * + * _.nth(array, 1); + * // => 'b' + * + * _.nth(array, -2); + * // => 'c'; + */ + function nth(array, n) { + return (array && array.length) ? baseNth(array, toInteger(n)) : undefined; + } + + /** + * Removes all given values from `array` using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove` + * to remove elements from an array by predicate. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {...*} [values] The values to remove. + * @returns {Array} Returns `array`. + * @example + * + * var array = ['a', 'b', 'c', 'a', 'b', 'c']; + * + * _.pull(array, 'a', 'c'); + * console.log(array); + * // => ['b', 'b'] + */ + var pull = baseRest(pullAll); + + /** + * This method is like `_.pull` except that it accepts an array of values to remove. + * + * **Note:** Unlike `_.difference`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @returns {Array} Returns `array`. + * @example + * + * var array = ['a', 'b', 'c', 'a', 'b', 'c']; + * + * _.pullAll(array, ['a', 'c']); + * console.log(array); + * // => ['b', 'b'] + */ + function pullAll(array, values) { + return (array && array.length && values && values.length) + ? basePullAll(array, values) + : array; + } + + /** + * This method is like `_.pullAll` except that it accepts `iteratee` which is + * invoked for each element of `array` and `values` to generate the criterion + * by which they're compared. The iteratee is invoked with one argument: (value). + * + * **Note:** Unlike `_.differenceBy`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [iteratee=_.identity] + * The iteratee invoked per element. + * @returns {Array} Returns `array`. + * @example + * + * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }]; + * + * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x'); + * console.log(array); + * // => [{ 'x': 2 }] + */ + function pullAllBy(array, values, iteratee) { + return (array && array.length && values && values.length) + ? basePullAll(array, values, getIteratee(iteratee, 2)) + : array; + } + + /** + * This method is like `_.pullAll` except that it accepts `comparator` which + * is invoked to compare elements of `array` to `values`. The comparator is + * invoked with two arguments: (arrVal, othVal). + * + * **Note:** Unlike `_.differenceWith`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns `array`. + * @example + * + * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }]; + * + * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual); + * console.log(array); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }] + */ + function pullAllWith(array, values, comparator) { + return (array && array.length && values && values.length) + ? basePullAll(array, values, undefined, comparator) + : array; + } + + /** + * Removes elements from `array` corresponding to `indexes` and returns an + * array of removed elements. + * + * **Note:** Unlike `_.at`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {...(number|number[])} [indexes] The indexes of elements to remove. + * @returns {Array} Returns the new array of removed elements. + * @example + * + * var array = ['a', 'b', 'c', 'd']; + * var pulled = _.pullAt(array, [1, 3]); + * + * console.log(array); + * // => ['a', 'c'] + * + * console.log(pulled); + * // => ['b', 'd'] + */ + var pullAt = flatRest(function(array, indexes) { + var length = array ? array.length : 0, + result = baseAt(array, indexes); + + basePullAt(array, arrayMap(indexes, function(index) { + return isIndex(index, length) ? +index : index; + }).sort(compareAscending)); + + return result; + }); + + /** + * Removes all elements from `array` that `predicate` returns truthy for + * and returns an array of the removed elements. The predicate is invoked + * with three arguments: (value, index, array). + * + * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull` + * to pull elements from an array by value. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Function} [predicate=_.identity] + * The function invoked per iteration. + * @returns {Array} Returns the new array of removed elements. + * @example + * + * var array = [1, 2, 3, 4]; + * var evens = _.remove(array, function(n) { + * return n % 2 == 0; + * }); + * + * console.log(array); + * // => [1, 3] + * + * console.log(evens); + * // => [2, 4] + */ + function remove(array, predicate) { + var result = []; + if (!(array && array.length)) { + return result; + } + var index = -1, + indexes = [], + length = array.length; + + predicate = getIteratee(predicate, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result.push(value); + indexes.push(index); + } + } + basePullAt(array, indexes); + return result; + } + + /** + * Reverses `array` so that the first element becomes the last, the second + * element becomes the second to last, and so on. + * + * **Note:** This method mutates `array` and is based on + * [`Array#reverse`](https://mdn.io/Array/reverse). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to modify. + * @returns {Array} Returns `array`. + * @example + * + * var array = [1, 2, 3]; + * + * _.reverse(array); + * // => [3, 2, 1] + * + * console.log(array); + * // => [3, 2, 1] + */ + function reverse(array) { + return array ? nativeReverse.call(array) : array; + } + + /** + * Creates a slice of `array` from `start` up to, but not including, `end`. + * + * **Note:** This method is used instead of + * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are + * returned. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ + function slice(array, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (end && typeof end != 'number' && isIterateeCall(array, start, end)) { + start = 0; + end = length; + } + else { + start = start == null ? 0 : toInteger(start); + end = end === undefined ? length : toInteger(end); + } + return baseSlice(array, start, end); + } + + /** + * Uses a binary search to determine the lowest index at which `value` + * should be inserted into `array` in order to maintain its sort order. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * _.sortedIndex([30, 50], 40); + * // => 1 + */ + function sortedIndex(array, value) { + return baseSortedIndex(array, value); + } + + /** + * This method is like `_.sortedIndex` except that it accepts `iteratee` + * which is invoked for `value` and each element of `array` to compute their + * sort ranking. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} [iteratee=_.identity] + * The iteratee invoked per element. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * var objects = [{ 'x': 4 }, { 'x': 5 }]; + * + * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; }); + * // => 0 + * + * // The `_.property` iteratee shorthand. + * _.sortedIndexBy(objects, { 'x': 4 }, 'x'); + * // => 0 + */ + function sortedIndexBy(array, value, iteratee) { + return baseSortedIndexBy(array, value, getIteratee(iteratee, 2)); + } + + /** + * This method is like `_.indexOf` except that it performs a binary + * search on a sorted `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.sortedIndexOf([4, 5, 5, 5, 6], 5); + * // => 1 + */ + function sortedIndexOf(array, value) { + var length = array ? array.length : 0; + if (length) { + var index = baseSortedIndex(array, value); + if (index < length && eq(array[index], value)) { + return index; + } + } + return -1; + } + + /** + * This method is like `_.sortedIndex` except that it returns the highest + * index at which `value` should be inserted into `array` in order to + * maintain its sort order. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * _.sortedLastIndex([4, 5, 5, 5, 6], 5); + * // => 4 + */ + function sortedLastIndex(array, value) { + return baseSortedIndex(array, value, true); + } + + /** + * This method is like `_.sortedLastIndex` except that it accepts `iteratee` + * which is invoked for `value` and each element of `array` to compute their + * sort ranking. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} [iteratee=_.identity] + * The iteratee invoked per element. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * var objects = [{ 'x': 4 }, { 'x': 5 }]; + * + * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; }); + * // => 1 + * + * // The `_.property` iteratee shorthand. + * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x'); + * // => 1 + */ + function sortedLastIndexBy(array, value, iteratee) { + return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true); + } + + /** + * This method is like `_.lastIndexOf` except that it performs a binary + * search on a sorted `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5); + * // => 3 + */ + function sortedLastIndexOf(array, value) { + var length = array ? array.length : 0; + if (length) { + var index = baseSortedIndex(array, value, true) - 1; + if (eq(array[index], value)) { + return index; + } + } + return -1; + } + + /** + * This method is like `_.uniq` except that it's designed and optimized + * for sorted arrays. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.sortedUniq([1, 1, 2]); + * // => [1, 2] + */ + function sortedUniq(array) { + return (array && array.length) + ? baseSortedUniq(array) + : []; + } + + /** + * This method is like `_.uniqBy` except that it's designed and optimized + * for sorted arrays. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor); + * // => [1.1, 2.3] + */ + function sortedUniqBy(array, iteratee) { + return (array && array.length) + ? baseSortedUniq(array, getIteratee(iteratee, 2)) + : []; + } + + /** + * Gets all but the first element of `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to query. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.tail([1, 2, 3]); + * // => [2, 3] + */ + function tail(array) { + var length = array ? array.length : 0; + return length ? baseSlice(array, 1, length) : []; + } + + /** + * Creates a slice of `array` with `n` elements taken from the beginning. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to take. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.take([1, 2, 3]); + * // => [1] + * + * _.take([1, 2, 3], 2); + * // => [1, 2] + * + * _.take([1, 2, 3], 5); + * // => [1, 2, 3] + * + * _.take([1, 2, 3], 0); + * // => [] + */ + function take(array, n, guard) { + if (!(array && array.length)) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + return baseSlice(array, 0, n < 0 ? 0 : n); + } + + /** + * Creates a slice of `array` with `n` elements taken from the end. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to take. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.takeRight([1, 2, 3]); + * // => [3] + * + * _.takeRight([1, 2, 3], 2); + * // => [2, 3] + * + * _.takeRight([1, 2, 3], 5); + * // => [1, 2, 3] + * + * _.takeRight([1, 2, 3], 0); + * // => [] + */ + function takeRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + n = length - n; + return baseSlice(array, n < 0 ? 0 : n, length); + } + + /** + * Creates a slice of `array` with elements taken from the end. Elements are + * taken until `predicate` returns falsey. The predicate is invoked with + * three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] + * The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.takeRightWhile(users, function(o) { return !o.active; }); + * // => objects for ['fred', 'pebbles'] + * + * // The `_.matches` iteratee shorthand. + * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false }); + * // => objects for ['pebbles'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.takeRightWhile(users, ['active', false]); + * // => objects for ['fred', 'pebbles'] + * + * // The `_.property` iteratee shorthand. + * _.takeRightWhile(users, 'active'); + * // => [] + */ + function takeRightWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3), false, true) + : []; + } + + /** + * Creates a slice of `array` with elements taken from the beginning. Elements + * are taken until `predicate` returns falsey. The predicate is invoked with + * three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] + * The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false}, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.takeWhile(users, function(o) { return !o.active; }); + * // => objects for ['barney', 'fred'] + * + * // The `_.matches` iteratee shorthand. + * _.takeWhile(users, { 'user': 'barney', 'active': false }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.takeWhile(users, ['active', false]); + * // => objects for ['barney', 'fred'] + * + * // The `_.property` iteratee shorthand. + * _.takeWhile(users, 'active'); + * // => [] + */ + function takeWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3)) + : []; + } + + /** + * Creates an array of unique values, in order, from all given arrays using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of combined values. + * @example + * + * _.union([2], [1, 2]); + * // => [2, 1] + */ + var union = baseRest(function(arrays) { + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true)); + }); + + /** + * This method is like `_.union` except that it accepts `iteratee` which is + * invoked for each element of each `arrays` to generate the criterion by + * which uniqueness is computed. Result values are chosen from the first + * array in which the value occurs. The iteratee is invoked with one argument: + * (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [iteratee=_.identity] + * The iteratee invoked per element. + * @returns {Array} Returns the new array of combined values. + * @example + * + * _.unionBy([2.1], [1.2, 2.3], Math.floor); + * // => [2.1, 1.2] + * + * // The `_.property` iteratee shorthand. + * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }, { 'x': 2 }] + */ + var unionBy = baseRest(function(arrays) { + var iteratee = last(arrays); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)); + }); + + /** + * This method is like `_.union` except that it accepts `comparator` which + * is invoked to compare elements of `arrays`. Result values are chosen from + * the first array in which the value occurs. The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of combined values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.unionWith(objects, others, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] + */ + var unionWith = baseRest(function(arrays) { + var comparator = last(arrays); + if (isArrayLikeObject(comparator)) { + comparator = undefined; + } + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator); + }); + + /** + * Creates a duplicate-free version of an array, using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons, in which only the first occurrence of each element + * is kept. The order of result values is determined by the order they occur + * in the array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.uniq([2, 1, 2]); + * // => [2, 1] + */ + function uniq(array) { + return (array && array.length) + ? baseUniq(array) + : []; + } + + /** + * This method is like `_.uniq` except that it accepts `iteratee` which is + * invoked for each element in `array` to generate the criterion by which + * uniqueness is computed. The order of result values is determined by the + * order they occur in the array. The iteratee is invoked with one argument: + * (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [iteratee=_.identity] + * The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.uniqBy([2.1, 1.2, 2.3], Math.floor); + * // => [2.1, 1.2] + * + * // The `_.property` iteratee shorthand. + * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }, { 'x': 2 }] + */ + function uniqBy(array, iteratee) { + return (array && array.length) + ? baseUniq(array, getIteratee(iteratee, 2)) + : []; + } + + /** + * This method is like `_.uniq` except that it accepts `comparator` which + * is invoked to compare elements of `array`. The order of result values is + * determined by the order they occur in the array.The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.uniqWith(objects, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }] + */ + function uniqWith(array, comparator) { + return (array && array.length) + ? baseUniq(array, undefined, comparator) + : []; + } + + /** + * This method is like `_.zip` except that it accepts an array of grouped + * elements and creates an array regrouping the elements to their pre-zip + * configuration. + * + * @static + * @memberOf _ + * @since 1.2.0 + * @category Array + * @param {Array} array The array of grouped elements to process. + * @returns {Array} Returns the new array of regrouped elements. + * @example + * + * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]); + * // => [['a', 1, true], ['b', 2, false]] + * + * _.unzip(zipped); + * // => [['a', 'b'], [1, 2], [true, false]] + */ + function unzip(array) { + if (!(array && array.length)) { + return []; + } + var length = 0; + array = arrayFilter(array, function(group) { + if (isArrayLikeObject(group)) { + length = nativeMax(group.length, length); + return true; + } + }); + return baseTimes(length, function(index) { + return arrayMap(array, baseProperty(index)); + }); + } + + /** + * This method is like `_.unzip` except that it accepts `iteratee` to specify + * how regrouped values should be combined. The iteratee is invoked with the + * elements of each group: (...group). + * + * @static + * @memberOf _ + * @since 3.8.0 + * @category Array + * @param {Array} array The array of grouped elements to process. + * @param {Function} [iteratee=_.identity] The function to combine + * regrouped values. + * @returns {Array} Returns the new array of regrouped elements. + * @example + * + * var zipped = _.zip([1, 2], [10, 20], [100, 200]); + * // => [[1, 10, 100], [2, 20, 200]] + * + * _.unzipWith(zipped, _.add); + * // => [3, 30, 300] + */ + function unzipWith(array, iteratee) { + if (!(array && array.length)) { + return []; + } + var result = unzip(array); + if (iteratee == null) { + return result; + } + return arrayMap(result, function(group) { + return apply(iteratee, undefined, group); + }); + } + + /** + * Creates an array excluding all given values using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * **Note:** Unlike `_.pull`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...*} [values] The values to exclude. + * @returns {Array} Returns the new array of filtered values. + * @see _.difference, _.xor + * @example + * + * _.without([2, 1, 2, 3], 1, 2); + * // => [3] + */ + var without = baseRest(function(array, values) { + return isArrayLikeObject(array) + ? baseDifference(array, values) + : []; + }); + + /** + * Creates an array of unique values that is the + * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference) + * of the given arrays. The order of result values is determined by the order + * they occur in the arrays. + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of filtered values. + * @see _.difference, _.without + * @example + * + * _.xor([2, 1], [2, 3]); + * // => [1, 3] + */ + var xor = baseRest(function(arrays) { + return baseXor(arrayFilter(arrays, isArrayLikeObject)); + }); + + /** + * This method is like `_.xor` except that it accepts `iteratee` which is + * invoked for each element of each `arrays` to generate the criterion by + * which by which they're compared. The order of result values is determined + * by the order they occur in the arrays. The iteratee is invoked with one + * argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [iteratee=_.identity] + * The iteratee invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [1.2, 3.4] + * + * // The `_.property` iteratee shorthand. + * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 2 }] + */ + var xorBy = baseRest(function(arrays) { + var iteratee = last(arrays); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2)); + }); + + /** + * This method is like `_.xor` except that it accepts `comparator` which is + * invoked to compare elements of `arrays`. The order of result values is + * determined by the order they occur in the arrays. The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.xorWith(objects, others, _.isEqual); + * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] + */ + var xorWith = baseRest(function(arrays) { + var comparator = last(arrays); + if (isArrayLikeObject(comparator)) { + comparator = undefined; + } + return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator); + }); + + /** + * Creates an array of grouped elements, the first of which contains the + * first elements of the given arrays, the second of which contains the + * second elements of the given arrays, and so on. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to process. + * @returns {Array} Returns the new array of grouped elements. + * @example + * + * _.zip(['a', 'b'], [1, 2], [true, false]); + * // => [['a', 1, true], ['b', 2, false]] + */ + var zip = baseRest(unzip); + + /** + * This method is like `_.fromPairs` except that it accepts two arrays, + * one of property identifiers and one of corresponding values. + * + * @static + * @memberOf _ + * @since 0.4.0 + * @category Array + * @param {Array} [props=[]] The property identifiers. + * @param {Array} [values=[]] The property values. + * @returns {Object} Returns the new object. + * @example + * + * _.zipObject(['a', 'b'], [1, 2]); + * // => { 'a': 1, 'b': 2 } + */ + function zipObject(props, values) { + return baseZipObject(props || [], values || [], assignValue); + } + + /** + * This method is like `_.zipObject` except that it supports property paths. + * + * @static + * @memberOf _ + * @since 4.1.0 + * @category Array + * @param {Array} [props=[]] The property identifiers. + * @param {Array} [values=[]] The property values. + * @returns {Object} Returns the new object. + * @example + * + * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]); + * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } } + */ + function zipObjectDeep(props, values) { + return baseZipObject(props || [], values || [], baseSet); + } + + /** + * This method is like `_.zip` except that it accepts `iteratee` to specify + * how grouped values should be combined. The iteratee is invoked with the + * elements of each group: (...group). + * + * @static + * @memberOf _ + * @since 3.8.0 + * @category Array + * @param {...Array} [arrays] The arrays to process. + * @param {Function} [iteratee=_.identity] The function to combine grouped values. + * @returns {Array} Returns the new array of grouped elements. + * @example + * + * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) { + * return a + b + c; + * }); + * // => [111, 222] + */ + var zipWith = baseRest(function(arrays) { + var length = arrays.length, + iteratee = length > 1 ? arrays[length - 1] : undefined; + + iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined; + return unzipWith(arrays, iteratee); + }); + + /*------------------------------------------------------------------------*/ + + /** + * Creates a `lodash` wrapper instance that wraps `value` with explicit method + * chain sequences enabled. The result of such sequences must be unwrapped + * with `_#value`. + * + * @static + * @memberOf _ + * @since 1.3.0 + * @category Seq + * @param {*} value The value to wrap. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'pebbles', 'age': 1 } + * ]; + * + * var youngest = _ + * .chain(users) + * .sortBy('age') + * .map(function(o) { + * return o.user + ' is ' + o.age; + * }) + * .head() + * .value(); + * // => 'pebbles is 1' + */ + function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; + } + + /** + * This method invokes `interceptor` and returns `value`. The interceptor + * is invoked with one argument; (value). The purpose of this method is to + * "tap into" a method chain sequence in order to modify intermediate results. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @returns {*} Returns `value`. + * @example + * + * _([1, 2, 3]) + * .tap(function(array) { + * // Mutate input array. + * array.pop(); + * }) + * .reverse() + * .value(); + * // => [2, 1] + */ + function tap(value, interceptor) { + interceptor(value); + return value; + } + + /** + * This method is like `_.tap` except that it returns the result of `interceptor`. + * The purpose of this method is to "pass thru" values replacing intermediate + * results in a method chain sequence. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Seq + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @returns {*} Returns the result of `interceptor`. + * @example + * + * _(' abc ') + * .chain() + * .trim() + * .thru(function(value) { + * return [value]; + * }) + * .value(); + * // => ['abc'] + */ + function thru(value, interceptor) { + return interceptor(value); + } + + /** + * This method is the wrapper version of `_.at`. + * + * @name at + * @memberOf _ + * @since 1.0.0 + * @category Seq + * @param {...(string|string[])} [paths] The property paths of elements to pick. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; + * + * _(object).at(['a[0].b.c', 'a[1]']).value(); + * // => [3, 4] + */ + var wrapperAt = flatRest(function(paths) { + var length = paths.length, + start = length ? paths[0] : 0, + value = this.__wrapped__, + interceptor = function(object) { return baseAt(object, paths); }; + + if (length > 1 || this.__actions__.length || + !(value instanceof LazyWrapper) || !isIndex(start)) { + return this.thru(interceptor); + } + value = value.slice(start, +start + (length ? 1 : 0)); + value.__actions__.push({ + 'func': thru, + 'args': [interceptor], + 'thisArg': undefined + }); + return new LodashWrapper(value, this.__chain__).thru(function(array) { + if (length && !array.length) { + array.push(undefined); + } + return array; + }); + }); + + /** + * Creates a `lodash` wrapper instance with explicit method chain sequences enabled. + * + * @name chain + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 } + * ]; + * + * // A sequence without explicit chaining. + * _(users).head(); + * // => { 'user': 'barney', 'age': 36 } + * + * // A sequence with explicit chaining. + * _(users) + * .chain() + * .head() + * .pick('user') + * .value(); + * // => { 'user': 'barney' } + */ + function wrapperChain() { + return chain(this); + } + + /** + * Executes the chain sequence and returns the wrapped result. + * + * @name commit + * @memberOf _ + * @since 3.2.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var array = [1, 2]; + * var wrapped = _(array).push(3); + * + * console.log(array); + * // => [1, 2] + * + * wrapped = wrapped.commit(); + * console.log(array); + * // => [1, 2, 3] + * + * wrapped.last(); + * // => 3 + * + * console.log(array); + * // => [1, 2, 3] + */ + function wrapperCommit() { + return new LodashWrapper(this.value(), this.__chain__); + } + + /** + * Gets the next value on a wrapped object following the + * [iterator protocol](https://mdn.io/iteration_protocols#iterator). + * + * @name next + * @memberOf _ + * @since 4.0.0 + * @category Seq + * @returns {Object} Returns the next iterator value. + * @example + * + * var wrapped = _([1, 2]); + * + * wrapped.next(); + * // => { 'done': false, 'value': 1 } + * + * wrapped.next(); + * // => { 'done': false, 'value': 2 } + * + * wrapped.next(); + * // => { 'done': true, 'value': undefined } + */ + function wrapperNext() { + if (this.__values__ === undefined) { + this.__values__ = toArray(this.value()); + } + var done = this.__index__ >= this.__values__.length, + value = done ? undefined : this.__values__[this.__index__++]; + + return { 'done': done, 'value': value }; + } + + /** + * Enables the wrapper to be iterable. + * + * @name Symbol.iterator + * @memberOf _ + * @since 4.0.0 + * @category Seq + * @returns {Object} Returns the wrapper object. + * @example + * + * var wrapped = _([1, 2]); + * + * wrapped[Symbol.iterator]() === wrapped; + * // => true + * + * Array.from(wrapped); + * // => [1, 2] + */ + function wrapperToIterator() { + return this; + } + + /** + * Creates a clone of the chain sequence planting `value` as the wrapped value. + * + * @name plant + * @memberOf _ + * @since 3.2.0 + * @category Seq + * @param {*} value The value to plant. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * function square(n) { + * return n * n; + * } + * + * var wrapped = _([1, 2]).map(square); + * var other = wrapped.plant([3, 4]); + * + * other.value(); + * // => [9, 16] + * + * wrapped.value(); + * // => [1, 4] + */ + function wrapperPlant(value) { + var result, + parent = this; + + while (parent instanceof baseLodash) { + var clone = wrapperClone(parent); + clone.__index__ = 0; + clone.__values__ = undefined; + if (result) { + previous.__wrapped__ = clone; + } else { + result = clone; + } + var previous = clone; + parent = parent.__wrapped__; + } + previous.__wrapped__ = value; + return result; + } + + /** + * This method is the wrapper version of `_.reverse`. + * + * **Note:** This method mutates the wrapped array. + * + * @name reverse + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var array = [1, 2, 3]; + * + * _(array).reverse().value() + * // => [3, 2, 1] + * + * console.log(array); + * // => [3, 2, 1] + */ + function wrapperReverse() { + var value = this.__wrapped__; + if (value instanceof LazyWrapper) { + var wrapped = value; + if (this.__actions__.length) { + wrapped = new LazyWrapper(this); + } + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ + 'func': thru, + 'args': [reverse], + 'thisArg': undefined + }); + return new LodashWrapper(wrapped, this.__chain__); + } + return this.thru(reverse); + } + + /** + * Executes the chain sequence to resolve the unwrapped value. + * + * @name value + * @memberOf _ + * @since 0.1.0 + * @alias toJSON, valueOf + * @category Seq + * @returns {*} Returns the resolved unwrapped value. + * @example + * + * _([1, 2, 3]).value(); + * // => [1, 2, 3] + */ + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` thru `iteratee`. The corresponding value of + * each key is the number of times the key was returned by `iteratee`. The + * iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] + * The iteratee to transform keys. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.countBy([6.1, 4.2, 6.3], Math.floor); + * // => { '4': 1, '6': 2 } + * + * // The `_.property` iteratee shorthand. + * _.countBy(['one', 'two', 'three'], 'length'); + * // => { '3': 2, '5': 1 } + */ + var countBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + ++result[key]; + } else { + baseAssignValue(result, key, 1); + } + }); + + /** + * Checks if `predicate` returns truthy for **all** elements of `collection`. + * Iteration is stopped once `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index|key, collection). + * + * **Note:** This method returns `true` for + * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because + * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of + * elements of empty collections. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] + * The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. + * @example + * + * _.every([true, 1, null, 'yes'], Boolean); + * // => false + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.every(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // The `_.matchesProperty` iteratee shorthand. + * _.every(users, ['active', false]); + * // => true + * + * // The `_.property` iteratee shorthand. + * _.every(users, 'active'); + * // => false + */ + function every(collection, predicate, guard) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (guard && isIterateeCall(collection, predicate, guard)) { + predicate = undefined; + } + return func(collection, getIteratee(predicate, 3)); + } + + /** + * Iterates over elements of `collection`, returning an array of all elements + * `predicate` returns truthy for. The predicate is invoked with three + * arguments: (value, index|key, collection). + * + * **Note:** Unlike `_.remove`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] + * The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + * @see _.reject + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * _.filter(users, function(o) { return !o.active; }); + * // => objects for ['fred'] + * + * // The `_.matches` iteratee shorthand. + * _.filter(users, { 'age': 36, 'active': true }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.filter(users, ['active', false]); + * // => objects for ['fred'] + * + * // The `_.property` iteratee shorthand. + * _.filter(users, 'active'); + * // => objects for ['barney'] + */ + function filter(collection, predicate) { + var func = isArray(collection) ? arrayFilter : baseFilter; + return func(collection, getIteratee(predicate, 3)); + } + + /** + * Iterates over elements of `collection`, returning the first element + * `predicate` returns truthy for. The predicate is invoked with three + * arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to inspect. + * @param {Function} [predicate=_.identity] + * The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false }, + * { 'user': 'pebbles', 'age': 1, 'active': true } + * ]; + * + * _.find(users, function(o) { return o.age < 40; }); + * // => object for 'barney' + * + * // The `_.matches` iteratee shorthand. + * _.find(users, { 'age': 1, 'active': true }); + * // => object for 'pebbles' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.find(users, ['active', false]); + * // => object for 'fred' + * + * // The `_.property` iteratee shorthand. + * _.find(users, 'active'); + * // => object for 'barney' + */ + var find = createFind(findIndex); + + /** + * This method is like `_.find` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Collection + * @param {Array|Object} collection The collection to inspect. + * @param {Function} [predicate=_.identity] + * The function invoked per iteration. + * @param {number} [fromIndex=collection.length-1] The index to search from. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * _.findLast([1, 2, 3, 4], function(n) { + * return n % 2 == 1; + * }); + * // => 3 + */ + var findLast = createFind(findLastIndex); + + /** + * Creates a flattened array of values by running each element in `collection` + * thru `iteratee` and flattening the mapped results. The iteratee is invoked + * with three arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] + * The function invoked per iteration. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [n, n]; + * } + * + * _.flatMap([1, 2], duplicate); + * // => [1, 1, 2, 2] + */ + function flatMap(collection, iteratee) { + return baseFlatten(map(collection, iteratee), 1); + } + + /** + * This method is like `_.flatMap` except that it recursively flattens the + * mapped results. + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] + * The function invoked per iteration. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [[[n, n]]]; + * } + * + * _.flatMapDeep([1, 2], duplicate); + * // => [1, 1, 2, 2] + */ + function flatMapDeep(collection, iteratee) { + return baseFlatten(map(collection, iteratee), INFINITY); + } + + /** + * This method is like `_.flatMap` except that it recursively flattens the + * mapped results up to `depth` times. + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] + * The function invoked per iteration. + * @param {number} [depth=1] The maximum recursion depth. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [[[n, n]]]; + * } + * + * _.flatMapDepth([1, 2], duplicate, 2); + * // => [[1, 1], [2, 2]] + */ + function flatMapDepth(collection, iteratee, depth) { + depth = depth === undefined ? 1 : toInteger(depth); + return baseFlatten(map(collection, iteratee), depth); + } + + /** + * Iterates over elements of `collection` and invokes `iteratee` for each element. + * The iteratee is invoked with three arguments: (value, index|key, collection). + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * **Note:** As with other "Collections" methods, objects with a "length" + * property are iterated like arrays. To avoid this behavior use `_.forIn` + * or `_.forOwn` for object iteration. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @alias each + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + * @see _.forEachRight + * @example + * + * _.forEach([1, 2], function(value) { + * console.log(value); + * }); + * // => Logs `1` then `2`. + * + * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a' then 'b' (iteration order is not guaranteed). + */ + function forEach(collection, iteratee) { + var func = isArray(collection) ? arrayEach : baseEach; + return func(collection, getIteratee(iteratee, 3)); + } + + /** + * This method is like `_.forEach` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @alias eachRight + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + * @see _.forEach + * @example + * + * _.forEachRight([1, 2], function(value) { + * console.log(value); + * }); + * // => Logs `2` then `1`. + */ + function forEachRight(collection, iteratee) { + var func = isArray(collection) ? arrayEachRight : baseEachRight; + return func(collection, getIteratee(iteratee, 3)); + } + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` thru `iteratee`. The order of grouped values + * is determined by the order they occur in `collection`. The corresponding + * value of each key is an array of elements responsible for generating the + * key. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] + * The iteratee to transform keys. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.groupBy([6.1, 4.2, 6.3], Math.floor); + * // => { '4': [4.2], '6': [6.1, 6.3] } + * + * // The `_.property` iteratee shorthand. + * _.groupBy(['one', 'two', 'three'], 'length'); + * // => { '3': ['one', 'two'], '5': ['three'] } + */ + var groupBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + baseAssignValue(result, key, [value]); + } + }); + + /** + * Checks if `value` is in `collection`. If `collection` is a string, it's + * checked for a substring of `value`, otherwise + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * is used for equality comparisons. If `fromIndex` is negative, it's used as + * the offset from the end of `collection`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object|string} collection The collection to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=0] The index to search from. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. + * @returns {boolean} Returns `true` if `value` is found, else `false`. + * @example + * + * _.includes([1, 2, 3], 1); + * // => true + * + * _.includes([1, 2, 3], 1, 2); + * // => false + * + * _.includes({ 'a': 1, 'b': 2 }, 1); + * // => true + * + * _.includes('abcd', 'bc'); + * // => true + */ + function includes(collection, value, fromIndex, guard) { + collection = isArrayLike(collection) ? collection : values(collection); + fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0; + + var length = collection.length; + if (fromIndex < 0) { + fromIndex = nativeMax(length + fromIndex, 0); + } + return isString(collection) + ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1) + : (!!length && baseIndexOf(collection, value, fromIndex) > -1); + } + + /** + * Invokes the method at `path` of each element in `collection`, returning + * an array of the results of each invoked method. Any additional arguments + * are provided to each invoked method. If `path` is a function, it's invoked + * for, and `this` bound to, each element in `collection`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Array|Function|string} path The path of the method to invoke or + * the function invoked per iteration. + * @param {...*} [args] The arguments to invoke each method with. + * @returns {Array} Returns the array of results. + * @example + * + * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort'); + * // => [[1, 5, 7], [1, 2, 3]] + * + * _.invokeMap([123, 456], String.prototype.split, ''); + * // => [['1', '2', '3'], ['4', '5', '6']] + */ + var invokeMap = baseRest(function(collection, path, args) { + var index = -1, + isFunc = typeof path == 'function', + isProp = isKey(path), + result = isArrayLike(collection) ? Array(collection.length) : []; + + baseEach(collection, function(value) { + var func = isFunc ? path : ((isProp && value != null) ? value[path] : undefined); + result[++index] = func ? apply(func, value, args) : baseInvoke(value, path, args); + }); + return result; + }); + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` thru `iteratee`. The corresponding value of + * each key is the last element responsible for generating the key. The + * iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] + * The iteratee to transform keys. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * var array = [ + * { 'dir': 'left', 'code': 97 }, + * { 'dir': 'right', 'code': 100 } + * ]; + * + * _.keyBy(array, function(o) { + * return String.fromCharCode(o.code); + * }); + * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } + * + * _.keyBy(array, 'dir'); + * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } + */ + var keyBy = createAggregator(function(result, value, key) { + baseAssignValue(result, key, value); + }); + + /** + * Creates an array of values by running each element in `collection` thru + * `iteratee`. The iteratee is invoked with three arguments: + * (value, index|key, collection). + * + * Many lodash methods are guarded to work as iteratees for methods like + * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. + * + * The guarded methods are: + * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`, + * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`, + * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`, + * `template`, `trim`, `trimEnd`, `trimStart`, and `words` + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + * @example + * + * function square(n) { + * return n * n; + * } + * + * _.map([4, 8], square); + * // => [16, 64] + * + * _.map({ 'a': 4, 'b': 8 }, square); + * // => [16, 64] (iteration order is not guaranteed) + * + * var users = [ + * { 'user': 'barney' }, + * { 'user': 'fred' } + * ]; + * + * // The `_.property` iteratee shorthand. + * _.map(users, 'user'); + * // => ['barney', 'fred'] + */ + function map(collection, iteratee) { + var func = isArray(collection) ? arrayMap : baseMap; + return func(collection, getIteratee(iteratee, 3)); + } + + /** + * This method is like `_.sortBy` except that it allows specifying the sort + * orders of the iteratees to sort by. If `orders` is unspecified, all values + * are sorted in ascending order. Otherwise, specify an order of "desc" for + * descending or "asc" for ascending sort order of corresponding values. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]] + * The iteratees to sort by. + * @param {string[]} [orders] The sort orders of `iteratees`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. + * @returns {Array} Returns the new sorted array. + * @example + * + * var users = [ + * { 'user': 'fred', 'age': 48 }, + * { 'user': 'barney', 'age': 34 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'barney', 'age': 36 } + * ]; + * + * // Sort by `user` in ascending order and by `age` in descending order. + * _.orderBy(users, ['user', 'age'], ['asc', 'desc']); + * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] + */ + function orderBy(collection, iteratees, orders, guard) { + if (collection == null) { + return []; + } + if (!isArray(iteratees)) { + iteratees = iteratees == null ? [] : [iteratees]; + } + orders = guard ? undefined : orders; + if (!isArray(orders)) { + orders = orders == null ? [] : [orders]; + } + return baseOrderBy(collection, iteratees, orders); + } + + /** + * Creates an array of elements split into two groups, the first of which + * contains elements `predicate` returns truthy for, the second of which + * contains elements `predicate` returns falsey for. The predicate is + * invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the array of grouped elements. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true }, + * { 'user': 'pebbles', 'age': 1, 'active': false } + * ]; + * + * _.partition(users, function(o) { return o.active; }); + * // => objects for [['fred'], ['barney', 'pebbles']] + * + * // The `_.matches` iteratee shorthand. + * _.partition(users, { 'age': 1, 'active': false }); + * // => objects for [['pebbles'], ['barney', 'fred']] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.partition(users, ['active', false]); + * // => objects for [['barney', 'pebbles'], ['fred']] + * + * // The `_.property` iteratee shorthand. + * _.partition(users, 'active'); + * // => objects for [['fred'], ['barney', 'pebbles']] + */ + var partition = createAggregator(function(result, value, key) { + result[key ? 0 : 1].push(value); + }, function() { return [[], []]; }); + + /** + * Reduces `collection` to a value which is the accumulated result of running + * each element in `collection` thru `iteratee`, where each successive + * invocation is supplied the return value of the previous. If `accumulator` + * is not given, the first element of `collection` is used as the initial + * value. The iteratee is invoked with four arguments: + * (accumulator, value, index|key, collection). + * + * Many lodash methods are guarded to work as iteratees for methods like + * `_.reduce`, `_.reduceRight`, and `_.transform`. + * + * The guarded methods are: + * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`, + * and `sortBy` + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @returns {*} Returns the accumulated value. + * @see _.reduceRight + * @example + * + * _.reduce([1, 2], function(sum, n) { + * return sum + n; + * }, 0); + * // => 3 + * + * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { + * (result[value] || (result[value] = [])).push(key); + * return result; + * }, {}); + * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed) + */ + function reduce(collection, iteratee, accumulator) { + var func = isArray(collection) ? arrayReduce : baseReduce, + initAccum = arguments.length < 3; + + return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach); + } + + /** + * This method is like `_.reduce` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @returns {*} Returns the accumulated value. + * @see _.reduce + * @example + * + * var array = [[0, 1], [2, 3], [4, 5]]; + * + * _.reduceRight(array, function(flattened, other) { + * return flattened.concat(other); + * }, []); + * // => [4, 5, 2, 3, 0, 1] + */ + function reduceRight(collection, iteratee, accumulator) { + var func = isArray(collection) ? arrayReduceRight : baseReduce, + initAccum = arguments.length < 3; + + return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight); + } + + /** + * The opposite of `_.filter`; this method returns the elements of `collection` + * that `predicate` does **not** return truthy for. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + * @see _.filter + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true } + * ]; + * + * _.reject(users, function(o) { return !o.active; }); + * // => objects for ['fred'] + * + * // The `_.matches` iteratee shorthand. + * _.reject(users, { 'age': 40, 'active': true }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.reject(users, ['active', false]); + * // => objects for ['fred'] + * + * // The `_.property` iteratee shorthand. + * _.reject(users, 'active'); + * // => objects for ['barney'] + */ + function reject(collection, predicate) { + var func = isArray(collection) ? arrayFilter : baseFilter; + return func(collection, negate(getIteratee(predicate, 3))); + } + + /** + * Gets a random element from `collection`. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Collection + * @param {Array|Object} collection The collection to sample. + * @returns {*} Returns the random element. + * @example + * + * _.sample([1, 2, 3, 4]); + * // => 2 + */ + function sample(collection) { + var func = isArray(collection) ? arraySample : baseSample; + return func(collection); + } + + /** + * Gets `n` random elements at unique keys from `collection` up to the + * size of `collection`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to sample. + * @param {number} [n=1] The number of elements to sample. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the random elements. + * @example + * + * _.sampleSize([1, 2, 3], 2); + * // => [3, 1] + * + * _.sampleSize([1, 2, 3], 4); + * // => [2, 3, 1] + */ + function sampleSize(collection, n, guard) { + if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) { + n = 1; + } else { + n = toInteger(n); + } + var func = isArray(collection) ? arraySampleSize : baseSampleSize; + return func(collection, n); + } + + /** + * Creates an array of shuffled values, using a version of the + * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to shuffle. + * @returns {Array} Returns the new shuffled array. + * @example + * + * _.shuffle([1, 2, 3, 4]); + * // => [4, 1, 3, 2] + */ + function shuffle(collection) { + var func = isArray(collection) ? arrayShuffle : baseShuffle; + return func(collection); + } + + /** + * Gets the size of `collection` by returning its length for array-like + * values or the number of own enumerable string keyed properties for objects. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object|string} collection The collection to inspect. + * @returns {number} Returns the collection size. + * @example + * + * _.size([1, 2, 3]); + * // => 3 + * + * _.size({ 'a': 1, 'b': 2 }); + * // => 2 + * + * _.size('pebbles'); + * // => 7 + */ + function size(collection) { + if (collection == null) { + return 0; + } + if (isArrayLike(collection)) { + return isString(collection) ? stringSize(collection) : collection.length; + } + var tag = getTag(collection); + if (tag == mapTag || tag == setTag) { + return collection.size; + } + return baseKeys(collection).length; + } + + /** + * Checks if `predicate` returns truthy for **any** element of `collection`. + * Iteration is stopped once `predicate` returns truthy. The predicate is + * invoked with three arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + * @example + * + * _.some([null, 0, 'yes', false], Boolean); + * // => true + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.some(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // The `_.matchesProperty` iteratee shorthand. + * _.some(users, ['active', false]); + * // => true + * + * // The `_.property` iteratee shorthand. + * _.some(users, 'active'); + * // => true + */ + function some(collection, predicate, guard) { + var func = isArray(collection) ? arraySome : baseSome; + if (guard && isIterateeCall(collection, predicate, guard)) { + predicate = undefined; + } + return func(collection, getIteratee(predicate, 3)); + } + + /** + * Creates an array of elements, sorted in ascending order by the results of + * running each element in a collection thru each iteratee. This method + * performs a stable sort, that is, it preserves the original sort order of + * equal elements. The iteratees are invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {...(Function|Function[])} [iteratees=[_.identity]] + * The iteratees to sort by. + * @returns {Array} Returns the new sorted array. + * @example + * + * var users = [ + * { 'user': 'fred', 'age': 48 }, + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'barney', 'age': 34 } + * ]; + * + * _.sortBy(users, [function(o) { return o.user; }]); + * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] + * + * _.sortBy(users, ['user', 'age']); + * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]] + */ + var sortBy = baseRest(function(collection, iteratees) { + if (collection == null) { + return []; + } + var length = iteratees.length; + if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) { + iteratees = []; + } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) { + iteratees = [iteratees[0]]; + } + return baseOrderBy(collection, baseFlatten(iteratees, 1), []); + }); + + /*------------------------------------------------------------------------*/ + + /** + * Gets the timestamp of the number of milliseconds that have elapsed since + * the Unix epoch (1 January 1970 00:00:00 UTC). + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Date + * @returns {number} Returns the timestamp. + * @example + * + * _.defer(function(stamp) { + * console.log(_.now() - stamp); + * }, _.now()); + * // => Logs the number of milliseconds it took for the deferred invocation. + */ + var now = ctxNow || function() { + return root.Date.now(); + }; + + /*------------------------------------------------------------------------*/ + + /** + * The opposite of `_.before`; this method creates a function that invokes + * `func` once it's called `n` or more times. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {number} n The number of calls before `func` is invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var saves = ['profile', 'settings']; + * + * var done = _.after(saves.length, function() { + * console.log('done saving!'); + * }); + * + * _.forEach(saves, function(type) { + * asyncSave({ 'type': type, 'complete': done }); + * }); + * // => Logs 'done saving!' after the two async saves have completed. + */ + function after(n, func) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + n = toInteger(n); + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + + /** + * Creates a function that invokes `func`, with up to `n` arguments, + * ignoring any additional arguments. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} func The function to cap arguments for. + * @param {number} [n=func.length] The arity cap. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new capped function. + * @example + * + * _.map(['6', '8', '10'], _.ary(parseInt, 1)); + * // => [6, 8, 10] + */ + function ary(func, n, guard) { + n = guard ? undefined : n; + n = (func && n == null) ? func.length : n; + return createWrap(func, ARY_FLAG, undefined, undefined, undefined, undefined, n); + } + + /** + * Creates a function that invokes `func`, with the `this` binding and arguments + * of the created function, while it's called less than `n` times. Subsequent + * calls to the created function return the result of the last `func` invocation. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {number} n The number of calls at which `func` is no longer invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * jQuery(element).on('click', _.before(5, addContactToList)); + * // => Allows adding up to 4 contacts to the list. + */ + function before(n, func) { + var result; + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + n = toInteger(n); + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; + } + + /** + * Creates a function that invokes `func` with the `this` binding of `thisArg` + * and `partials` prepended to the arguments it receives. + * + * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for partially applied arguments. + * + * **Note:** Unlike native `Function#bind`, this method doesn't set the "length" + * property of bound functions. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to bind. + * @param {*} thisArg The `this` binding of `func`. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * function greet(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * } + * + * var object = { 'user': 'fred' }; + * + * var bound = _.bind(greet, object, 'hi'); + * bound('!'); + * // => 'hi fred!' + * + * // Bound with placeholders. + * var bound = _.bind(greet, object, _, '!'); + * bound('hi'); + * // => 'hi fred!' + */ + var bind = baseRest(function(func, thisArg, partials) { + var bitmask = BIND_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, getHolder(bind)); + bitmask |= PARTIAL_FLAG; + } + return createWrap(func, bitmask, thisArg, partials, holders); + }); + + /** + * Creates a function that invokes the method at `object[key]` with `partials` + * prepended to the arguments it receives. + * + * This method differs from `_.bind` by allowing bound functions to reference + * methods that may be redefined or don't yet exist. See + * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern) + * for more details. + * + * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. + * + * @static + * @memberOf _ + * @since 0.10.0 + * @category Function + * @param {Object} object The object to invoke the method on. + * @param {string} key The key of the method. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * var object = { + * 'user': 'fred', + * 'greet': function(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * } + * }; + * + * var bound = _.bindKey(object, 'greet', 'hi'); + * bound('!'); + * // => 'hi fred!' + * + * object.greet = function(greeting, punctuation) { + * return greeting + 'ya ' + this.user + punctuation; + * }; + * + * bound('!'); + * // => 'hiya fred!' + * + * // Bound with placeholders. + * var bound = _.bindKey(object, 'greet', _, '!'); + * bound('hi'); + * // => 'hiya fred!' + */ + var bindKey = baseRest(function(object, key, partials) { + var bitmask = BIND_FLAG | BIND_KEY_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, getHolder(bindKey)); + bitmask |= PARTIAL_FLAG; + } + return createWrap(key, bitmask, object, partials, holders); + }); + + /** + * Creates a function that accepts arguments of `func` and either invokes + * `func` returning its result, if at least `arity` number of arguments have + * been provided, or returns a function that accepts the remaining `func` + * arguments, and so on. The arity of `func` may be specified if `func.length` + * is not sufficient. + * + * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for provided arguments. + * + * **Note:** This method doesn't set the "length" property of curried functions. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Function + * @param {Function} func The function to curry. + * @param {number} [arity=func.length] The arity of `func`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new curried function. + * @example + * + * var abc = function(a, b, c) { + * return [a, b, c]; + * }; + * + * var curried = _.curry(abc); + * + * curried(1)(2)(3); + * // => [1, 2, 3] + * + * curried(1, 2)(3); + * // => [1, 2, 3] + * + * curried(1, 2, 3); + * // => [1, 2, 3] + * + * // Curried with placeholders. + * curried(1)(_, 3)(2); + * // => [1, 2, 3] + */ + function curry(func, arity, guard) { + arity = guard ? undefined : arity; + var result = createWrap(func, CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curry.placeholder; + return result; + } + + /** + * This method is like `_.curry` except that arguments are applied to `func` + * in the manner of `_.partialRight` instead of `_.partial`. + * + * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for provided arguments. + * + * **Note:** This method doesn't set the "length" property of curried functions. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} func The function to curry. + * @param {number} [arity=func.length] The arity of `func`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new curried function. + * @example + * + * var abc = function(a, b, c) { + * return [a, b, c]; + * }; + * + * var curried = _.curryRight(abc); + * + * curried(3)(2)(1); + * // => [1, 2, 3] + * + * curried(2, 3)(1); + * // => [1, 2, 3] + * + * curried(1, 2, 3); + * // => [1, 2, 3] + * + * // Curried with placeholders. + * curried(3)(1, _)(2); + * // => [1, 2, 3] + */ + function curryRight(func, arity, guard) { + arity = guard ? undefined : arity; + var result = createWrap(func, CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curryRight.placeholder; + return result; + } + + /** + * Creates a debounced function that delays invoking `func` until after `wait` + * milliseconds have elapsed since the last time the debounced function was + * invoked. The debounced function comes with a `cancel` method to cancel + * delayed `func` invocations and a `flush` method to immediately invoke them. + * Provide `options` to indicate whether `func` should be invoked on the + * leading and/or trailing edge of the `wait` timeout. The `func` is invoked + * with the last arguments provided to the debounced function. Subsequent + * calls to the debounced function return the result of the last `func` + * invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the debounced function + * is invoked more than once during the `wait` timeout. + * + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until to the next tick, similar to `setTimeout` with a timeout of `0`. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) + * for details over the differences between `_.debounce` and `_.throttle`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to debounce. + * @param {number} [wait=0] The number of milliseconds to delay. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=false] + * Specify invoking on the leading edge of the timeout. + * @param {number} [options.maxWait] + * The maximum time `func` is allowed to be delayed before it's invoked. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. + * @returns {Function} Returns the new debounced function. + * @example + * + * // Avoid costly calculations while the window size is in flux. + * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); + * + * // Invoke `sendMail` when clicked, debouncing subsequent calls. + * jQuery(element).on('click', _.debounce(sendMail, 300, { + * 'leading': true, + * 'trailing': false + * })); + * + * // Ensure `batchLog` is invoked once after 1 second of debounced calls. + * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); + * var source = new EventSource('/stream'); + * jQuery(source).on('message', debounced); + * + * // Cancel the trailing debounced invocation. + * jQuery(window).on('popstate', debounced.cancel); + */ + function debounce(func, wait, options) { + var lastArgs, + lastThis, + maxWait, + result, + timerId, + lastCallTime, + lastInvokeTime = 0, + leading = false, + maxing = false, + trailing = true; + + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = toNumber(wait) || 0; + if (isObject(options)) { + leading = !!options.leading; + maxing = 'maxWait' in options; + maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + + function invokeFunc(time) { + var args = lastArgs, + thisArg = lastThis; + + lastArgs = lastThis = undefined; + lastInvokeTime = time; + result = func.apply(thisArg, args); + return result; + } + + function leadingEdge(time) { + // Reset any `maxWait` timer. + lastInvokeTime = time; + // Start the timer for the trailing edge. + timerId = setTimeout(timerExpired, wait); + // Invoke the leading edge. + return leading ? invokeFunc(time) : result; + } + + function remainingWait(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime, + result = wait - timeSinceLastCall; + + return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result; + } + + function shouldInvoke(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime; + + // Either this is the first call, activity has stopped and we're at the + // trailing edge, the system time has gone backwards and we're treating + // it as the trailing edge, or we've hit the `maxWait` limit. + return (lastCallTime === undefined || (timeSinceLastCall >= wait) || + (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); + } + + function timerExpired() { + var time = now(); + if (shouldInvoke(time)) { + return trailingEdge(time); + } + // Restart the timer. + timerId = setTimeout(timerExpired, remainingWait(time)); + } + + function trailingEdge(time) { + timerId = undefined; + + // Only invoke if we have `lastArgs` which means `func` has been + // debounced at least once. + if (trailing && lastArgs) { + return invokeFunc(time); + } + lastArgs = lastThis = undefined; + return result; + } + + function cancel() { + if (timerId !== undefined) { + clearTimeout(timerId); + } + lastInvokeTime = 0; + lastArgs = lastCallTime = lastThis = timerId = undefined; + } + + function flush() { + return timerId === undefined ? result : trailingEdge(now()); + } + + function debounced() { + var time = now(), + isInvoking = shouldInvoke(time); + + lastArgs = arguments; + lastThis = this; + lastCallTime = time; + + if (isInvoking) { + if (timerId === undefined) { + return leadingEdge(lastCallTime); + } + if (maxing) { + // Handle invocations in a tight loop. + timerId = setTimeout(timerExpired, wait); + return invokeFunc(lastCallTime); + } + } + if (timerId === undefined) { + timerId = setTimeout(timerExpired, wait); + } + return result; + } + debounced.cancel = cancel; + debounced.flush = flush; + return debounced; + } + + /** + * Defers invoking the `func` until the current call stack has cleared. Any + * additional arguments are provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to defer. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {number} Returns the timer id. + * @example + * + * _.defer(function(text) { + * console.log(text); + * }, 'deferred'); + * // => Logs 'deferred' after one millisecond. + */ + var defer = baseRest(function(func, args) { + return baseDelay(func, 1, args); + }); + + /** + * Invokes `func` after `wait` milliseconds. Any additional arguments are + * provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {number} Returns the timer id. + * @example + * + * _.delay(function(text) { + * console.log(text); + * }, 1000, 'later'); + * // => Logs 'later' after one second. + */ + var delay = baseRest(function(func, wait, args) { + return baseDelay(func, toNumber(wait) || 0, args); + }); + + /** + * Creates a function that invokes `func` with arguments reversed. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Function + * @param {Function} func The function to flip arguments for. + * @returns {Function} Returns the new flipped function. + * @example + * + * var flipped = _.flip(function() { + * return _.toArray(arguments); + * }); + * + * flipped('a', 'b', 'c', 'd'); + * // => ['d', 'c', 'b', 'a'] + */ + function flip(func) { + return createWrap(func, FLIP_FLAG); + } + + /** + * Creates a function that memoizes the result of `func`. If `resolver` is + * provided, it determines the cache key for storing the result based on the + * arguments provided to the memoized function. By default, the first argument + * provided to the memoized function is used as the map cache key. The `func` + * is invoked with the `this` binding of the memoized function. + * + * **Note:** The cache is exposed as the `cache` property on the memoized + * function. Its creation may be customized by replacing the `_.memoize.Cache` + * constructor with one whose instances implement the + * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) + * method interface of `delete`, `get`, `has`, and `set`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to have its output memoized. + * @param {Function} [resolver] The function to resolve the cache key. + * @returns {Function} Returns the new memoized function. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * var other = { 'c': 3, 'd': 4 }; + * + * var values = _.memoize(_.values); + * values(object); + * // => [1, 2] + * + * values(other); + * // => [3, 4] + * + * object.a = 2; + * values(object); + * // => [1, 2] + * + * // Modify the result cache. + * values.cache.set(object, ['a', 'b']); + * values(object); + * // => ['a', 'b'] + * + * // Replace `_.memoize.Cache`. + * _.memoize.Cache = WeakMap; + */ + function memoize(func, resolver) { + if (typeof func != 'function' || (resolver && typeof resolver != 'function')) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, + key = resolver ? resolver.apply(this, args) : args[0], + cache = memoized.cache; + + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result) || cache; + return result; + }; + memoized.cache = new (memoize.Cache || MapCache); + return memoized; + } + + // Expose `MapCache`. + memoize.Cache = MapCache; + + /** + * Creates a function that negates the result of the predicate `func`. The + * `func` predicate is invoked with the `this` binding and arguments of the + * created function. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} predicate The predicate to negate. + * @returns {Function} Returns the new negated function. + * @example + * + * function isEven(n) { + * return n % 2 == 0; + * } + * + * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); + * // => [1, 3, 5] + */ + function negate(predicate) { + if (typeof predicate != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + var args = arguments; + switch (args.length) { + case 0: return !predicate.call(this); + case 1: return !predicate.call(this, args[0]); + case 2: return !predicate.call(this, args[0], args[1]); + case 3: return !predicate.call(this, args[0], args[1], args[2]); + } + return !predicate.apply(this, args); + }; + } + + /** + * Creates a function that is restricted to invoking `func` once. Repeat calls + * to the function return the value of the first invocation. The `func` is + * invoked with the `this` binding and arguments of the created function. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var initialize = _.once(createApplication); + * initialize(); + * initialize(); + * // => `createApplication` is invoked once + */ + function once(func) { + return before(2, func); + } + + /** + * Creates a function that invokes `func` with its arguments transformed. + * + * @static + * @since 4.0.0 + * @memberOf _ + * @category Function + * @param {Function} func The function to wrap. + * @param {...(Function|Function[])} [transforms=[_.identity]] + * The argument transforms. + * @returns {Function} Returns the new function. + * @example + * + * function doubled(n) { + * return n * 2; + * } + * + * function square(n) { + * return n * n; + * } + * + * var func = _.overArgs(function(x, y) { + * return [x, y]; + * }, [square, doubled]); + * + * func(9, 3); + * // => [81, 6] + * + * func(10, 5); + * // => [100, 10] + */ + var overArgs = castRest(function(func, transforms) { + transforms = (transforms.length == 1 && isArray(transforms[0])) + ? arrayMap(transforms[0], baseUnary(getIteratee())) + : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee())); + + var funcsLength = transforms.length; + return baseRest(function(args) { + var index = -1, + length = nativeMin(args.length, funcsLength); + + while (++index < length) { + args[index] = transforms[index].call(this, args[index]); + } + return apply(func, this, args); + }); + }); + + /** + * Creates a function that invokes `func` with `partials` prepended to the + * arguments it receives. This method is like `_.bind` except it does **not** + * alter the `this` binding. + * + * The `_.partial.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. + * + * **Note:** This method doesn't set the "length" property of partially + * applied functions. + * + * @static + * @memberOf _ + * @since 0.2.0 + * @category Function + * @param {Function} func The function to partially apply arguments to. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. + * @example + * + * function greet(greeting, name) { + * return greeting + ' ' + name; + * } + * + * var sayHelloTo = _.partial(greet, 'hello'); + * sayHelloTo('fred'); + * // => 'hello fred' + * + * // Partially applied with placeholders. + * var greetFred = _.partial(greet, _, 'fred'); + * greetFred('hi'); + * // => 'hi fred' + */ + var partial = baseRest(function(func, partials) { + var holders = replaceHolders(partials, getHolder(partial)); + return createWrap(func, PARTIAL_FLAG, undefined, partials, holders); + }); + + /** + * This method is like `_.partial` except that partially applied arguments + * are appended to the arguments it receives. + * + * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. + * + * **Note:** This method doesn't set the "length" property of partially + * applied functions. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Function + * @param {Function} func The function to partially apply arguments to. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. + * @example + * + * function greet(greeting, name) { + * return greeting + ' ' + name; + * } + * + * var greetFred = _.partialRight(greet, 'fred'); + * greetFred('hi'); + * // => 'hi fred' + * + * // Partially applied with placeholders. + * var sayHelloTo = _.partialRight(greet, 'hello', _); + * sayHelloTo('fred'); + * // => 'hello fred' + */ + var partialRight = baseRest(function(func, partials) { + var holders = replaceHolders(partials, getHolder(partialRight)); + return createWrap(func, PARTIAL_RIGHT_FLAG, undefined, partials, holders); + }); + + /** + * Creates a function that invokes `func` with arguments arranged according + * to the specified `indexes` where the argument value at the first index is + * provided as the first argument, the argument value at the second index is + * provided as the second argument, and so on. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} func The function to rearrange arguments for. + * @param {...(number|number[])} indexes The arranged argument indexes. + * @returns {Function} Returns the new function. + * @example + * + * var rearged = _.rearg(function(a, b, c) { + * return [a, b, c]; + * }, [2, 0, 1]); + * + * rearged('b', 'c', 'a') + * // => ['a', 'b', 'c'] + */ + var rearg = flatRest(function(func, indexes) { + return createWrap(func, REARG_FLAG, undefined, undefined, undefined, indexes); + }); + + /** + * Creates a function that invokes `func` with the `this` binding of the + * created function and arguments from `start` and beyond provided as + * an array. + * + * **Note:** This method is based on the + * [rest parameter](https://mdn.io/rest_parameters). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Function + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + * @example + * + * var say = _.rest(function(what, names) { + * return what + ' ' + _.initial(names).join(', ') + + * (_.size(names) > 1 ? ', & ' : '') + _.last(names); + * }); + * + * say('hello', 'fred', 'barney', 'pebbles'); + * // => 'hello fred, barney, & pebbles' + */ + function rest(func, start) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = start === undefined ? start : toInteger(start); + return baseRest(func, start); + } + + /** + * Creates a function that invokes `func` with the `this` binding of the + * create function and an array of arguments much like + * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply). + * + * **Note:** This method is based on the + * [spread operator](https://mdn.io/spread_operator). + * + * @static + * @memberOf _ + * @since 3.2.0 + * @category Function + * @param {Function} func The function to spread arguments over. + * @param {number} [start=0] The start position of the spread. + * @returns {Function} Returns the new function. + * @example + * + * var say = _.spread(function(who, what) { + * return who + ' says ' + what; + * }); + * + * say(['fred', 'hello']); + * // => 'fred says hello' + * + * var numbers = Promise.all([ + * Promise.resolve(40), + * Promise.resolve(36) + * ]); + * + * numbers.then(_.spread(function(x, y) { + * return x + y; + * })); + * // => a Promise of 76 + */ + function spread(func, start) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = start === undefined ? 0 : nativeMax(toInteger(start), 0); + return baseRest(function(args) { + var array = args[start], + otherArgs = castSlice(args, 0, start); + + if (array) { + arrayPush(otherArgs, array); + } + return apply(func, this, otherArgs); + }); + } + + /** + * Creates a throttled function that only invokes `func` at most once per + * every `wait` milliseconds. The throttled function comes with a `cancel` + * method to cancel delayed `func` invocations and a `flush` method to + * immediately invoke them. Provide `options` to indicate whether `func` + * should be invoked on the leading and/or trailing edge of the `wait` + * timeout. The `func` is invoked with the last arguments provided to the + * throttled function. Subsequent calls to the throttled function return the + * result of the last `func` invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the throttled function + * is invoked more than once during the `wait` timeout. + * + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until to the next tick, similar to `setTimeout` with a timeout of `0`. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) + * for details over the differences between `_.throttle` and `_.debounce`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to throttle. + * @param {number} [wait=0] The number of milliseconds to throttle invocations to. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=true] + * Specify invoking on the leading edge of the timeout. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. + * @returns {Function} Returns the new throttled function. + * @example + * + * // Avoid excessively updating the position while scrolling. + * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); + * + * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes. + * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }); + * jQuery(element).on('click', throttled); + * + * // Cancel the trailing throttled invocation. + * jQuery(window).on('popstate', throttled.cancel); + */ + function throttle(func, wait, options) { + var leading = true, + trailing = true; + + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (isObject(options)) { + leading = 'leading' in options ? !!options.leading : leading; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + 'leading': leading, + 'maxWait': wait, + 'trailing': trailing + }); + } + + /** + * Creates a function that accepts up to one argument, ignoring any + * additional arguments. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Function + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. + * @example + * + * _.map(['6', '8', '10'], _.unary(parseInt)); + * // => [6, 8, 10] + */ + function unary(func) { + return ary(func, 1); + } + + /** + * Creates a function that provides `value` to `wrapper` as its first + * argument. Any additional arguments provided to the function are appended + * to those provided to the `wrapper`. The wrapper is invoked with the `this` + * binding of the created function. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {*} value The value to wrap. + * @param {Function} [wrapper=identity] The wrapper function. + * @returns {Function} Returns the new function. + * @example + * + * var p = _.wrap(_.escape, function(func, text) { + * return '

' + func(text) + '

'; + * }); + * + * p('fred, barney, & pebbles'); + * // => '

fred, barney, & pebbles

' + */ + function wrap(value, wrapper) { + wrapper = wrapper == null ? identity : wrapper; + return partial(wrapper, value); + } + + /*------------------------------------------------------------------------*/ + + /** + * Casts `value` as an array if it's not one. + * + * @static + * @memberOf _ + * @since 4.4.0 + * @category Lang + * @param {*} value The value to inspect. + * @returns {Array} Returns the cast array. + * @example + * + * _.castArray(1); + * // => [1] + * + * _.castArray({ 'a': 1 }); + * // => [{ 'a': 1 }] + * + * _.castArray('abc'); + * // => ['abc'] + * + * _.castArray(null); + * // => [null] + * + * _.castArray(undefined); + * // => [undefined] + * + * _.castArray(); + * // => [] + * + * var array = [1, 2, 3]; + * console.log(_.castArray(array) === array); + * // => true + */ + function castArray() { + if (!arguments.length) { + return []; + } + var value = arguments[0]; + return isArray(value) ? value : [value]; + } + + /** + * Creates a shallow clone of `value`. + * + * **Note:** This method is loosely based on the + * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm) + * and supports cloning arrays, array buffers, booleans, date objects, maps, + * numbers, `Object` objects, regexes, sets, strings, symbols, and typed + * arrays. The own enumerable properties of `arguments` objects are cloned + * as plain objects. An empty object is returned for uncloneable values such + * as error objects, functions, DOM nodes, and WeakMaps. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to clone. + * @returns {*} Returns the cloned value. + * @see _.cloneDeep + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var shallow = _.clone(objects); + * console.log(shallow[0] === objects[0]); + * // => true + */ + function clone(value) { + return baseClone(value, false, true); + } + + /** + * This method is like `_.clone` except that it accepts `customizer` which + * is invoked to produce the cloned value. If `customizer` returns `undefined`, + * cloning is handled by the method instead. The `customizer` is invoked with + * up to four arguments; (value [, index|key, object, stack]). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to clone. + * @param {Function} [customizer] The function to customize cloning. + * @returns {*} Returns the cloned value. + * @see _.cloneDeepWith + * @example + * + * function customizer(value) { + * if (_.isElement(value)) { + * return value.cloneNode(false); + * } + * } + * + * var el = _.cloneWith(document.body, customizer); + * + * console.log(el === document.body); + * // => false + * console.log(el.nodeName); + * // => 'BODY' + * console.log(el.childNodes.length); + * // => 0 + */ + function cloneWith(value, customizer) { + return baseClone(value, false, true, customizer); + } + + /** + * This method is like `_.clone` except that it recursively clones `value`. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Lang + * @param {*} value The value to recursively clone. + * @returns {*} Returns the deep cloned value. + * @see _.clone + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var deep = _.cloneDeep(objects); + * console.log(deep[0] === objects[0]); + * // => false + */ + function cloneDeep(value) { + return baseClone(value, true, true); + } + + /** + * This method is like `_.cloneWith` except that it recursively clones `value`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to recursively clone. + * @param {Function} [customizer] The function to customize cloning. + * @returns {*} Returns the deep cloned value. + * @see _.cloneWith + * @example + * + * function customizer(value) { + * if (_.isElement(value)) { + * return value.cloneNode(true); + * } + * } + * + * var el = _.cloneDeepWith(document.body, customizer); + * + * console.log(el === document.body); + * // => false + * console.log(el.nodeName); + * // => 'BODY' + * console.log(el.childNodes.length); + * // => 20 + */ + function cloneDeepWith(value, customizer) { + return baseClone(value, true, true, customizer); + } + + /** + * Checks if `object` conforms to `source` by invoking the predicate + * properties of `source` with the corresponding property values of `object`. + * + * **Note:** This method is equivalent to `_.conforms` when `source` is + * partially applied. + * + * @static + * @memberOf _ + * @since 4.14.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property predicates to conform to. + * @returns {boolean} Returns `true` if `object` conforms, else `false`. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * + * _.conformsTo(object, { 'b': function(n) { return n > 1; } }); + * // => true + * + * _.conformsTo(object, { 'b': function(n) { return n > 2; } }); + * // => false + */ + function conformsTo(object, source) { + return source == null || baseConformsTo(object, source, keys(source)); + } + + /** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ + function eq(value, other) { + return value === other || (value !== value && other !== other); + } + + /** + * Checks if `value` is greater than `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than `other`, + * else `false`. + * @see _.lt + * @example + * + * _.gt(3, 1); + * // => true + * + * _.gt(3, 3); + * // => false + * + * _.gt(1, 3); + * // => false + */ + var gt = createRelationalOperation(baseGt); + + /** + * Checks if `value` is greater than or equal to `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than or equal to + * `other`, else `false`. + * @see _.lte + * @example + * + * _.gte(3, 1); + * // => true + * + * _.gte(3, 3); + * // => true + * + * _.gte(1, 3); + * // => false + */ + var gte = createRelationalOperation(function(value, other) { + return value >= other; + }); + + /** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ + var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { + return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && + !propertyIsEnumerable.call(value, 'callee'); + }; + + /** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ + var isArray = Array.isArray; + + /** + * Checks if `value` is classified as an `ArrayBuffer` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`. + * @example + * + * _.isArrayBuffer(new ArrayBuffer(2)); + * // => true + * + * _.isArrayBuffer(new Array(2)); + * // => false + */ + var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer; + + /** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ + function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); + } + + /** + * This method is like `_.isArrayLike` except that it also checks if `value` + * is an object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array-like object, + * else `false`. + * @example + * + * _.isArrayLikeObject([1, 2, 3]); + * // => true + * + * _.isArrayLikeObject(document.body.children); + * // => true + * + * _.isArrayLikeObject('abc'); + * // => false + * + * _.isArrayLikeObject(_.noop); + * // => false + */ + function isArrayLikeObject(value) { + return isObjectLike(value) && isArrayLike(value); + } + + /** + * Checks if `value` is classified as a boolean primitive or object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a boolean, else `false`. + * @example + * + * _.isBoolean(false); + * // => true + * + * _.isBoolean(null); + * // => false + */ + function isBoolean(value) { + return value === true || value === false || + (isObjectLike(value) && objectToString.call(value) == boolTag); + } + + /** + * Checks if `value` is a buffer. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. + * @example + * + * _.isBuffer(new Buffer(2)); + * // => true + * + * _.isBuffer(new Uint8Array(2)); + * // => false + */ + var isBuffer = nativeIsBuffer || stubFalse; + + /** + * Checks if `value` is classified as a `Date` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a date object, else `false`. + * @example + * + * _.isDate(new Date); + * // => true + * + * _.isDate('Mon April 23 2012'); + * // => false + */ + var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate; + + /** + * Checks if `value` is likely a DOM element. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`. + * @example + * + * _.isElement(document.body); + * // => true + * + * _.isElement(''); + * // => false + */ + function isElement(value) { + return value != null && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); + } + + /** + * Checks if `value` is an empty object, collection, map, or set. + * + * Objects are considered empty if they have no own enumerable string keyed + * properties. + * + * Array-like values such as `arguments` objects, arrays, buffers, strings, or + * jQuery-like collections are considered empty if they have a `length` of `0`. + * Similarly, maps and sets are considered empty if they have a `size` of `0`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is empty, else `false`. + * @example + * + * _.isEmpty(null); + * // => true + * + * _.isEmpty(true); + * // => true + * + * _.isEmpty(1); + * // => true + * + * _.isEmpty([1, 2, 3]); + * // => false + * + * _.isEmpty({ 'a': 1 }); + * // => false + */ + function isEmpty(value) { + if (isArrayLike(value) && + (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' || + isBuffer(value) || isTypedArray(value) || isArguments(value))) { + return !value.length; + } + var tag = getTag(value); + if (tag == mapTag || tag == setTag) { + return !value.size; + } + if (isPrototype(value)) { + return !baseKeys(value).length; + } + for (var key in value) { + if (hasOwnProperty.call(value, key)) { + return false; + } + } + return true; + } + + /** + * Performs a deep comparison between two values to determine if they are + * equivalent. + * + * **Note:** This method supports comparing arrays, array buffers, booleans, + * date objects, error objects, maps, numbers, `Object` objects, regexes, + * sets, strings, symbols, and typed arrays. `Object` objects are compared + * by their own, not inherited, enumerable properties. Functions and DOM + * nodes are **not** supported. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.isEqual(object, other); + * // => true + * + * object === other; + * // => false + */ + function isEqual(value, other) { + return baseIsEqual(value, other); + } + + /** + * This method is like `_.isEqual` except that it accepts `customizer` which + * is invoked to compare values. If `customizer` returns `undefined`, comparisons + * are handled by the method instead. The `customizer` is invoked with up to + * six arguments: (objValue, othValue [, index|key, object, other, stack]). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * function isGreeting(value) { + * return /^h(?:i|ello)$/.test(value); + * } + * + * function customizer(objValue, othValue) { + * if (isGreeting(objValue) && isGreeting(othValue)) { + * return true; + * } + * } + * + * var array = ['hello', 'goodbye']; + * var other = ['hi', 'goodbye']; + * + * _.isEqualWith(array, other, customizer); + * // => true + */ + function isEqualWith(value, other, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + var result = customizer ? customizer(value, other) : undefined; + return result === undefined ? baseIsEqual(value, other, customizer) : !!result; + } + + /** + * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`, + * `SyntaxError`, `TypeError`, or `URIError` object. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an error object, else `false`. + * @example + * + * _.isError(new Error); + * // => true + * + * _.isError(Error); + * // => false + */ + function isError(value) { + if (!isObjectLike(value)) { + return false; + } + return (objectToString.call(value) == errorTag) || + (typeof value.message == 'string' && typeof value.name == 'string'); + } + + /** + * Checks if `value` is a finite primitive number. + * + * **Note:** This method is based on + * [`Number.isFinite`](https://mdn.io/Number/isFinite). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a finite number, else `false`. + * @example + * + * _.isFinite(3); + * // => true + * + * _.isFinite(Number.MIN_VALUE); + * // => true + * + * _.isFinite(Infinity); + * // => false + * + * _.isFinite('3'); + * // => false + */ + function isFinite(value) { + return typeof value == 'number' && nativeIsFinite(value); + } + + /** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ + function isFunction(value) { + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 9 which returns 'object' for typed array and other constructors. + var tag = isObject(value) ? objectToString.call(value) : ''; + return tag == funcTag || tag == genTag || tag == proxyTag; + } + + /** + * Checks if `value` is an integer. + * + * **Note:** This method is based on + * [`Number.isInteger`](https://mdn.io/Number/isInteger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an integer, else `false`. + * @example + * + * _.isInteger(3); + * // => true + * + * _.isInteger(Number.MIN_VALUE); + * // => false + * + * _.isInteger(Infinity); + * // => false + * + * _.isInteger('3'); + * // => false + */ + function isInteger(value) { + return typeof value == 'number' && value == toInteger(value); + } + + /** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ + function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + + /** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ + function isObject(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); + } + + /** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ + function isObjectLike(value) { + return value != null && typeof value == 'object'; + } + + /** + * Checks if `value` is classified as a `Map` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a map, else `false`. + * @example + * + * _.isMap(new Map); + * // => true + * + * _.isMap(new WeakMap); + * // => false + */ + var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap; + + /** + * Performs a partial deep comparison between `object` and `source` to + * determine if `object` contains equivalent property values. + * + * **Note:** This method is equivalent to `_.matches` when `source` is + * partially applied. + * + * Partial comparisons will match empty array and empty object `source` + * values against any array or object value, respectively. See `_.isEqual` + * for a list of supported value comparisons. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * + * _.isMatch(object, { 'b': 2 }); + * // => true + * + * _.isMatch(object, { 'b': 1 }); + * // => false + */ + function isMatch(object, source) { + return object === source || baseIsMatch(object, source, getMatchData(source)); + } + + /** + * This method is like `_.isMatch` except that it accepts `customizer` which + * is invoked to compare values. If `customizer` returns `undefined`, comparisons + * are handled by the method instead. The `customizer` is invoked with five + * arguments: (objValue, srcValue, index|key, object, source). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + * @example + * + * function isGreeting(value) { + * return /^h(?:i|ello)$/.test(value); + * } + * + * function customizer(objValue, srcValue) { + * if (isGreeting(objValue) && isGreeting(srcValue)) { + * return true; + * } + * } + * + * var object = { 'greeting': 'hello' }; + * var source = { 'greeting': 'hi' }; + * + * _.isMatchWith(object, source, customizer); + * // => true + */ + function isMatchWith(object, source, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return baseIsMatch(object, source, getMatchData(source), customizer); + } + + /** + * Checks if `value` is `NaN`. + * + * **Note:** This method is based on + * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as + * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for + * `undefined` and other non-number values. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + * @example + * + * _.isNaN(NaN); + * // => true + * + * _.isNaN(new Number(NaN)); + * // => true + * + * isNaN(undefined); + * // => true + * + * _.isNaN(undefined); + * // => false + */ + function isNaN(value) { + // An `NaN` primitive is the only value that is not equal to itself. + // Perform the `toStringTag` check first to avoid errors with some + // ActiveX objects in IE. + return isNumber(value) && value != +value; + } + + /** + * Checks if `value` is a pristine native function. + * + * **Note:** This method can't reliably detect native functions in the presence + * of the core-js package because core-js circumvents this kind of detection. + * Despite multiple requests, the core-js maintainer has made it clear: any + * attempt to fix the detection will be obstructed. As a result, we're left + * with little choice but to throw an error. Unfortunately, this also affects + * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill), + * which rely on core-js. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + * @example + * + * _.isNative(Array.prototype.push); + * // => true + * + * _.isNative(_); + * // => false + */ + function isNative(value) { + if (isMaskable(value)) { + throw new Error(CORE_ERROR_TEXT); + } + return baseIsNative(value); + } + + /** + * Checks if `value` is `null`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `null`, else `false`. + * @example + * + * _.isNull(null); + * // => true + * + * _.isNull(void 0); + * // => false + */ + function isNull(value) { + return value === null; + } + + /** + * Checks if `value` is `null` or `undefined`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is nullish, else `false`. + * @example + * + * _.isNil(null); + * // => true + * + * _.isNil(void 0); + * // => true + * + * _.isNil(NaN); + * // => false + */ + function isNil(value) { + return value == null; + } + + /** + * Checks if `value` is classified as a `Number` primitive or object. + * + * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are + * classified as numbers, use the `_.isFinite` method. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a number, else `false`. + * @example + * + * _.isNumber(3); + * // => true + * + * _.isNumber(Number.MIN_VALUE); + * // => true + * + * _.isNumber(Infinity); + * // => true + * + * _.isNumber('3'); + * // => false + */ + function isNumber(value) { + return typeof value == 'number' || + (isObjectLike(value) && objectToString.call(value) == numberTag); + } + + /** + * Checks if `value` is a plain object, that is, an object created by the + * `Object` constructor or one with a `[[Prototype]]` of `null`. + * + * @static + * @memberOf _ + * @since 0.8.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * _.isPlainObject(new Foo); + * // => false + * + * _.isPlainObject([1, 2, 3]); + * // => false + * + * _.isPlainObject({ 'x': 0, 'y': 0 }); + * // => true + * + * _.isPlainObject(Object.create(null)); + * // => true + */ + function isPlainObject(value) { + if (!isObjectLike(value) || objectToString.call(value) != objectTag) { + return false; + } + var proto = getPrototype(value); + if (proto === null) { + return true; + } + var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor; + return (typeof Ctor == 'function' && + Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString); + } + + /** + * Checks if `value` is classified as a `RegExp` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. + * @example + * + * _.isRegExp(/abc/); + * // => true + * + * _.isRegExp('/abc/'); + * // => false + */ + var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp; + + /** + * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754 + * double precision number which isn't the result of a rounded unsafe integer. + * + * **Note:** This method is based on + * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`. + * @example + * + * _.isSafeInteger(3); + * // => true + * + * _.isSafeInteger(Number.MIN_VALUE); + * // => false + * + * _.isSafeInteger(Infinity); + * // => false + * + * _.isSafeInteger('3'); + * // => false + */ + function isSafeInteger(value) { + return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER; + } + + /** + * Checks if `value` is classified as a `Set` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a set, else `false`. + * @example + * + * _.isSet(new Set); + * // => true + * + * _.isSet(new WeakSet); + * // => false + */ + var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet; + + /** + * Checks if `value` is classified as a `String` primitive or object. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a string, else `false`. + * @example + * + * _.isString('abc'); + * // => true + * + * _.isString(1); + * // => false + */ + function isString(value) { + return typeof value == 'string' || + (!isArray(value) && isObjectLike(value) && objectToString.call(value) == stringTag); + } + + /** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ + function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && objectToString.call(value) == symbolTag); + } + + /** + * Checks if `value` is classified as a typed array. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + * @example + * + * _.isTypedArray(new Uint8Array); + * // => true + * + * _.isTypedArray([]); + * // => false + */ + var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; + + /** + * Checks if `value` is `undefined`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. + * @example + * + * _.isUndefined(void 0); + * // => true + * + * _.isUndefined(null); + * // => false + */ + function isUndefined(value) { + return value === undefined; + } + + /** + * Checks if `value` is classified as a `WeakMap` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a weak map, else `false`. + * @example + * + * _.isWeakMap(new WeakMap); + * // => true + * + * _.isWeakMap(new Map); + * // => false + */ + function isWeakMap(value) { + return isObjectLike(value) && getTag(value) == weakMapTag; + } + + /** + * Checks if `value` is classified as a `WeakSet` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a weak set, else `false`. + * @example + * + * _.isWeakSet(new WeakSet); + * // => true + * + * _.isWeakSet(new Set); + * // => false + */ + function isWeakSet(value) { + return isObjectLike(value) && objectToString.call(value) == weakSetTag; + } + + /** + * Checks if `value` is less than `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than `other`, + * else `false`. + * @see _.gt + * @example + * + * _.lt(1, 3); + * // => true + * + * _.lt(3, 3); + * // => false + * + * _.lt(3, 1); + * // => false + */ + var lt = createRelationalOperation(baseLt); + + /** + * Checks if `value` is less than or equal to `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than or equal to + * `other`, else `false`. + * @see _.gte + * @example + * + * _.lte(1, 3); + * // => true + * + * _.lte(3, 3); + * // => true + * + * _.lte(3, 1); + * // => false + */ + var lte = createRelationalOperation(function(value, other) { + return value <= other; + }); + + /** + * Converts `value` to an array. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to convert. + * @returns {Array} Returns the converted array. + * @example + * + * _.toArray({ 'a': 1, 'b': 2 }); + * // => [1, 2] + * + * _.toArray('abc'); + * // => ['a', 'b', 'c'] + * + * _.toArray(1); + * // => [] + * + * _.toArray(null); + * // => [] + */ + function toArray(value) { + if (!value) { + return []; + } + if (isArrayLike(value)) { + return isString(value) ? stringToArray(value) : copyArray(value); + } + if (iteratorSymbol && value[iteratorSymbol]) { + return iteratorToArray(value[iteratorSymbol]()); + } + var tag = getTag(value), + func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values); + + return func(value); + } + + /** + * Converts `value` to a finite number. + * + * @static + * @memberOf _ + * @since 4.12.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted number. + * @example + * + * _.toFinite(3.2); + * // => 3.2 + * + * _.toFinite(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toFinite(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toFinite('3.2'); + * // => 3.2 + */ + function toFinite(value) { + if (!value) { + return value === 0 ? value : 0; + } + value = toNumber(value); + if (value === INFINITY || value === -INFINITY) { + var sign = (value < 0 ? -1 : 1); + return sign * MAX_INTEGER; + } + return value === value ? value : 0; + } + + /** + * Converts `value` to an integer. + * + * **Note:** This method is loosely based on + * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toInteger(3.2); + * // => 3 + * + * _.toInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toInteger(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toInteger('3.2'); + * // => 3 + */ + function toInteger(value) { + var result = toFinite(value), + remainder = result % 1; + + return result === result ? (remainder ? result - remainder : result) : 0; + } + + /** + * Converts `value` to an integer suitable for use as the length of an + * array-like object. + * + * **Note:** This method is based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toLength(3.2); + * // => 3 + * + * _.toLength(Number.MIN_VALUE); + * // => 0 + * + * _.toLength(Infinity); + * // => 4294967295 + * + * _.toLength('3.2'); + * // => 3 + */ + function toLength(value) { + return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0; + } + + /** + * Converts `value` to a number. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to process. + * @returns {number} Returns the number. + * @example + * + * _.toNumber(3.2); + * // => 3.2 + * + * _.toNumber(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toNumber(Infinity); + * // => Infinity + * + * _.toNumber('3.2'); + * // => 3.2 + */ + function toNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } + if (isObject(value)) { + var other = typeof value.valueOf == 'function' ? value.valueOf() : value; + value = isObject(other) ? (other + '') : other; + } + if (typeof value != 'string') { + return value === 0 ? value : +value; + } + value = value.replace(reTrim, ''); + var isBinary = reIsBinary.test(value); + return (isBinary || reIsOctal.test(value)) + ? freeParseInt(value.slice(2), isBinary ? 2 : 8) + : (reIsBadHex.test(value) ? NAN : +value); + } + + /** + * Converts `value` to a plain object flattening inherited enumerable string + * keyed properties of `value` to own properties of the plain object. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {Object} Returns the converted plain object. + * @example + * + * function Foo() { + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.assign({ 'a': 1 }, new Foo); + * // => { 'a': 1, 'b': 2 } + * + * _.assign({ 'a': 1 }, _.toPlainObject(new Foo)); + * // => { 'a': 1, 'b': 2, 'c': 3 } + */ + function toPlainObject(value) { + return copyObject(value, keysIn(value)); + } + + /** + * Converts `value` to a safe integer. A safe integer can be compared and + * represented correctly. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toSafeInteger(3.2); + * // => 3 + * + * _.toSafeInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toSafeInteger(Infinity); + * // => 9007199254740991 + * + * _.toSafeInteger('3.2'); + * // => 3 + */ + function toSafeInteger(value) { + return baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER); + } + + /** + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.toString(null); + * // => '' + * + * _.toString(-0); + * // => '-0' + * + * _.toString([1, 2, 3]); + * // => '1,2,3' + */ + function toString(value) { + return value == null ? '' : baseToString(value); + } + + /*------------------------------------------------------------------------*/ + + /** + * Assigns own enumerable string keyed properties of source objects to the + * destination object. Source objects are applied from left to right. + * Subsequent sources overwrite property assignments of previous sources. + * + * **Note:** This method mutates `object` and is loosely based on + * [`Object.assign`](https://mdn.io/Object/assign). + * + * @static + * @memberOf _ + * @since 0.10.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.assignIn + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * function Bar() { + * this.c = 3; + * } + * + * Foo.prototype.b = 2; + * Bar.prototype.d = 4; + * + * _.assign({ 'a': 0 }, new Foo, new Bar); + * // => { 'a': 1, 'c': 3 } + */ + var assign = createAssigner(function(object, source) { + if (isPrototype(source) || isArrayLike(source)) { + copyObject(source, keys(source), object); + return; + } + for (var key in source) { + if (hasOwnProperty.call(source, key)) { + assignValue(object, key, source[key]); + } + } + }); + + /** + * This method is like `_.assign` except that it iterates over own and + * inherited source properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias extend + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.assign + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * function Bar() { + * this.c = 3; + * } + * + * Foo.prototype.b = 2; + * Bar.prototype.d = 4; + * + * _.assignIn({ 'a': 0 }, new Foo, new Bar); + * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 } + */ + var assignIn = createAssigner(function(object, source) { + copyObject(source, keysIn(source), object); + }); + + /** + * This method is like `_.assignIn` except that it accepts `customizer` + * which is invoked to produce the assigned values. If `customizer` returns + * `undefined`, assignment is handled by the method instead. The `customizer` + * is invoked with five arguments: (objValue, srcValue, key, object, source). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias extendWith + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @see _.assignWith + * @example + * + * function customizer(objValue, srcValue) { + * return _.isUndefined(objValue) ? srcValue : objValue; + * } + * + * var defaults = _.partialRight(_.assignInWith, customizer); + * + * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var assignInWith = createAssigner(function(object, source, srcIndex, customizer) { + copyObject(source, keysIn(source), object, customizer); + }); + + /** + * This method is like `_.assign` except that it accepts `customizer` + * which is invoked to produce the assigned values. If `customizer` returns + * `undefined`, assignment is handled by the method instead. The `customizer` + * is invoked with five arguments: (objValue, srcValue, key, object, source). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @see _.assignInWith + * @example + * + * function customizer(objValue, srcValue) { + * return _.isUndefined(objValue) ? srcValue : objValue; + * } + * + * var defaults = _.partialRight(_.assignWith, customizer); + * + * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var assignWith = createAssigner(function(object, source, srcIndex, customizer) { + copyObject(source, keys(source), object, customizer); + }); + + /** + * Creates an array of values corresponding to `paths` of `object`. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {...(string|string[])} [paths] The property paths of elements to pick. + * @returns {Array} Returns the picked values. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; + * + * _.at(object, ['a[0].b.c', 'a[1]']); + * // => [3, 4] + */ + var at = flatRest(baseAt); + + /** + * Creates an object that inherits from the `prototype` object. If a + * `properties` object is given, its own enumerable string keyed properties + * are assigned to the created object. + * + * @static + * @memberOf _ + * @since 2.3.0 + * @category Object + * @param {Object} prototype The object to inherit from. + * @param {Object} [properties] The properties to assign to the object. + * @returns {Object} Returns the new object. + * @example + * + * function Shape() { + * this.x = 0; + * this.y = 0; + * } + * + * function Circle() { + * Shape.call(this); + * } + * + * Circle.prototype = _.create(Shape.prototype, { + * 'constructor': Circle + * }); + * + * var circle = new Circle; + * circle instanceof Circle; + * // => true + * + * circle instanceof Shape; + * // => true + */ + function create(prototype, properties) { + var result = baseCreate(prototype); + return properties ? baseAssign(result, properties) : result; + } + + /** + * Assigns own and inherited enumerable string keyed properties of source + * objects to the destination object for all destination properties that + * resolve to `undefined`. Source objects are applied from left to right. + * Once a property is set, additional values of the same property are ignored. + * + * **Note:** This method mutates `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.defaultsDeep + * @example + * + * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var defaults = baseRest(function(args) { + args.push(undefined, assignInDefaults); + return apply(assignInWith, undefined, args); + }); + + /** + * This method is like `_.defaults` except that it recursively assigns + * default properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 3.10.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.defaults + * @example + * + * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } }); + * // => { 'a': { 'b': 2, 'c': 3 } } + */ + var defaultsDeep = baseRest(function(args) { + args.push(undefined, mergeDefaults); + return apply(mergeWith, undefined, args); + }); + + /** + * This method is like `_.find` except that it returns the key of the first + * element `predicate` returns truthy for instead of the element itself. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Object + * @param {Object} object The object to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {string|undefined} Returns the key of the matched element, + * else `undefined`. + * @example + * + * var users = { + * 'barney': { 'age': 36, 'active': true }, + * 'fred': { 'age': 40, 'active': false }, + * 'pebbles': { 'age': 1, 'active': true } + * }; + * + * _.findKey(users, function(o) { return o.age < 40; }); + * // => 'barney' (iteration order is not guaranteed) + * + * // The `_.matches` iteratee shorthand. + * _.findKey(users, { 'age': 1, 'active': true }); + * // => 'pebbles' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findKey(users, ['active', false]); + * // => 'fred' + * + * // The `_.property` iteratee shorthand. + * _.findKey(users, 'active'); + * // => 'barney' + */ + function findKey(object, predicate) { + return baseFindKey(object, getIteratee(predicate, 3), baseForOwn); + } + + /** + * This method is like `_.findKey` except that it iterates over elements of + * a collection in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {string|undefined} Returns the key of the matched element, + * else `undefined`. + * @example + * + * var users = { + * 'barney': { 'age': 36, 'active': true }, + * 'fred': { 'age': 40, 'active': false }, + * 'pebbles': { 'age': 1, 'active': true } + * }; + * + * _.findLastKey(users, function(o) { return o.age < 40; }); + * // => returns 'pebbles' assuming `_.findKey` returns 'barney' + * + * // The `_.matches` iteratee shorthand. + * _.findLastKey(users, { 'age': 36, 'active': true }); + * // => 'barney' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findLastKey(users, ['active', false]); + * // => 'fred' + * + * // The `_.property` iteratee shorthand. + * _.findLastKey(users, 'active'); + * // => 'pebbles' + */ + function findLastKey(object, predicate) { + return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight); + } + + /** + * Iterates over own and inherited enumerable string keyed properties of an + * object and invokes `iteratee` for each property. The iteratee is invoked + * with three arguments: (value, key, object). Iteratee functions may exit + * iteration early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @since 0.3.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forInRight + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forIn(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed). + */ + function forIn(object, iteratee) { + return object == null + ? object + : baseFor(object, getIteratee(iteratee, 3), keysIn); + } + + /** + * This method is like `_.forIn` except that it iterates over properties of + * `object` in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forIn + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forInRight(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'. + */ + function forInRight(object, iteratee) { + return object == null + ? object + : baseForRight(object, getIteratee(iteratee, 3), keysIn); + } + + /** + * Iterates over own enumerable string keyed properties of an object and + * invokes `iteratee` for each property. The iteratee is invoked with three + * arguments: (value, key, object). Iteratee functions may exit iteration + * early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @since 0.3.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forOwnRight + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forOwn(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a' then 'b' (iteration order is not guaranteed). + */ + function forOwn(object, iteratee) { + return object && baseForOwn(object, getIteratee(iteratee, 3)); + } + + /** + * This method is like `_.forOwn` except that it iterates over properties of + * `object` in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forOwn + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forOwnRight(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'. + */ + function forOwnRight(object, iteratee) { + return object && baseForOwnRight(object, getIteratee(iteratee, 3)); + } + + /** + * Creates an array of function property names from own enumerable properties + * of `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the function names. + * @see _.functionsIn + * @example + * + * function Foo() { + * this.a = _.constant('a'); + * this.b = _.constant('b'); + * } + * + * Foo.prototype.c = _.constant('c'); + * + * _.functions(new Foo); + * // => ['a', 'b'] + */ + function functions(object) { + return object == null ? [] : baseFunctions(object, keys(object)); + } + + /** + * Creates an array of function property names from own and inherited + * enumerable properties of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the function names. + * @see _.functions + * @example + * + * function Foo() { + * this.a = _.constant('a'); + * this.b = _.constant('b'); + * } + * + * Foo.prototype.c = _.constant('c'); + * + * _.functionsIn(new Foo); + * // => ['a', 'b', 'c'] + */ + function functionsIn(object) { + return object == null ? [] : baseFunctions(object, keysIn(object)); + } + + /** + * Gets the value at `path` of `object`. If the resolved value is + * `undefined`, the `defaultValue` is returned in its place. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.get(object, 'a[0].b.c'); + * // => 3 + * + * _.get(object, ['a', '0', 'b', 'c']); + * // => 3 + * + * _.get(object, 'a.b.c', 'default'); + * // => 'default' + */ + function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, path); + return result === undefined ? defaultValue : result; + } + + /** + * Checks if `path` is a direct property of `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + * @example + * + * var object = { 'a': { 'b': 2 } }; + * var other = _.create({ 'a': _.create({ 'b': 2 }) }); + * + * _.has(object, 'a'); + * // => true + * + * _.has(object, 'a.b'); + * // => true + * + * _.has(object, ['a', 'b']); + * // => true + * + * _.has(other, 'a'); + * // => false + */ + function has(object, path) { + return object != null && hasPath(object, path, baseHas); + } + + /** + * Checks if `path` is a direct or inherited property of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + * @example + * + * var object = _.create({ 'a': _.create({ 'b': 2 }) }); + * + * _.hasIn(object, 'a'); + * // => true + * + * _.hasIn(object, 'a.b'); + * // => true + * + * _.hasIn(object, ['a', 'b']); + * // => true + * + * _.hasIn(object, 'b'); + * // => false + */ + function hasIn(object, path) { + return object != null && hasPath(object, path, baseHasIn); + } + + /** + * Creates an object composed of the inverted keys and values of `object`. + * If `object` contains duplicate values, subsequent values overwrite + * property assignments of previous values. + * + * @static + * @memberOf _ + * @since 0.7.0 + * @category Object + * @param {Object} object The object to invert. + * @returns {Object} Returns the new inverted object. + * @example + * + * var object = { 'a': 1, 'b': 2, 'c': 1 }; + * + * _.invert(object); + * // => { '1': 'c', '2': 'b' } + */ + var invert = createInverter(function(result, value, key) { + result[value] = key; + }, constant(identity)); + + /** + * This method is like `_.invert` except that the inverted object is generated + * from the results of running each element of `object` thru `iteratee`. The + * corresponding inverted value of each inverted key is an array of keys + * responsible for generating the inverted value. The iteratee is invoked + * with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.1.0 + * @category Object + * @param {Object} object The object to invert. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Object} Returns the new inverted object. + * @example + * + * var object = { 'a': 1, 'b': 2, 'c': 1 }; + * + * _.invertBy(object); + * // => { '1': ['a', 'c'], '2': ['b'] } + * + * _.invertBy(object, function(value) { + * return 'group' + value; + * }); + * // => { 'group1': ['a', 'c'], 'group2': ['b'] } + */ + var invertBy = createInverter(function(result, value, key) { + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [key]; + } + }, getIteratee); + + /** + * Invokes the method at `path` of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the method to invoke. + * @param {...*} [args] The arguments to invoke the method with. + * @returns {*} Returns the result of the invoked method. + * @example + * + * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] }; + * + * _.invoke(object, 'a[0].b.c.slice', 1, 3); + * // => [2, 3] + */ + var invoke = baseRest(baseInvoke); + + /** + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * for more details. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] + */ + function keys(object) { + return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); + } + + /** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ + function keysIn(object) { + return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); + } + + /** + * The opposite of `_.mapValues`; this method creates an object with the + * same values as `object` and keys generated by running each own enumerable + * string keyed property of `object` thru `iteratee`. The iteratee is invoked + * with three arguments: (value, key, object). + * + * @static + * @memberOf _ + * @since 3.8.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns the new mapped object. + * @see _.mapValues + * @example + * + * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) { + * return key + value; + * }); + * // => { 'a1': 1, 'b2': 2 } + */ + function mapKeys(object, iteratee) { + var result = {}; + iteratee = getIteratee(iteratee, 3); + + baseForOwn(object, function(value, key, object) { + baseAssignValue(result, iteratee(value, key, object), value); + }); + return result; + } + + /** + * Creates an object with the same keys as `object` and values generated + * by running each own enumerable string keyed property of `object` thru + * `iteratee`. The iteratee is invoked with three arguments: + * (value, key, object). + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns the new mapped object. + * @see _.mapKeys + * @example + * + * var users = { + * 'fred': { 'user': 'fred', 'age': 40 }, + * 'pebbles': { 'user': 'pebbles', 'age': 1 } + * }; + * + * _.mapValues(users, function(o) { return o.age; }); + * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) + * + * // The `_.property` iteratee shorthand. + * _.mapValues(users, 'age'); + * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) + */ + function mapValues(object, iteratee) { + var result = {}; + iteratee = getIteratee(iteratee, 3); + + baseForOwn(object, function(value, key, object) { + baseAssignValue(result, key, iteratee(value, key, object)); + }); + return result; + } + + /** + * This method is like `_.assign` except that it recursively merges own and + * inherited enumerable string keyed properties of source objects into the + * destination object. Source properties that resolve to `undefined` are + * skipped if a destination value exists. Array and plain object properties + * are merged recursively. Other objects and value types are overridden by + * assignment. Source objects are applied from left to right. Subsequent + * sources overwrite property assignments of previous sources. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @example + * + * var object = { + * 'a': [{ 'b': 2 }, { 'd': 4 }] + * }; + * + * var other = { + * 'a': [{ 'c': 3 }, { 'e': 5 }] + * }; + * + * _.merge(object, other); + * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] } + */ + var merge = createAssigner(function(object, source, srcIndex) { + baseMerge(object, source, srcIndex); + }); + + /** + * This method is like `_.merge` except that it accepts `customizer` which + * is invoked to produce the merged values of the destination and source + * properties. If `customizer` returns `undefined`, merging is handled by the + * method instead. The `customizer` is invoked with six arguments: + * (objValue, srcValue, key, object, source, stack). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} customizer The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * function customizer(objValue, srcValue) { + * if (_.isArray(objValue)) { + * return objValue.concat(srcValue); + * } + * } + * + * var object = { 'a': [1], 'b': [2] }; + * var other = { 'a': [3], 'b': [4] }; + * + * _.mergeWith(object, other, customizer); + * // => { 'a': [1, 3], 'b': [2, 4] } + */ + var mergeWith = createAssigner(function(object, source, srcIndex, customizer) { + baseMerge(object, source, srcIndex, customizer); + }); + + /** + * The opposite of `_.pick`; this method creates an object composed of the + * own and inherited enumerable string keyed properties of `object` that are + * not omitted. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The source object. + * @param {...(string|string[])} [props] The property identifiers to omit. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.omit(object, ['a', 'c']); + * // => { 'b': '2' } + */ + var omit = flatRest(function(object, props) { + if (object == null) { + return {}; + } + props = arrayMap(props, toKey); + return basePick(object, baseDifference(getAllKeysIn(object), props)); + }); + + /** + * The opposite of `_.pickBy`; this method creates an object composed of + * the own and inherited enumerable string keyed properties of `object` that + * `predicate` doesn't return truthy for. The predicate is invoked with two + * arguments: (value, key). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The source object. + * @param {Function} [predicate=_.identity] The function invoked per property. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.omitBy(object, _.isNumber); + * // => { 'b': '2' } + */ + function omitBy(object, predicate) { + return pickBy(object, negate(getIteratee(predicate))); + } + + /** + * Creates an object composed of the picked `object` properties. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The source object. + * @param {...(string|string[])} [props] The property identifiers to pick. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.pick(object, ['a', 'c']); + * // => { 'a': 1, 'c': 3 } + */ + var pick = flatRest(function(object, props) { + return object == null ? {} : basePick(object, arrayMap(props, toKey)); + }); + + /** + * Creates an object composed of the `object` properties `predicate` returns + * truthy for. The predicate is invoked with two arguments: (value, key). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The source object. + * @param {Function} [predicate=_.identity] The function invoked per property. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.pickBy(object, _.isNumber); + * // => { 'a': 1, 'c': 3 } + */ + function pickBy(object, predicate) { + return object == null ? {} : basePickBy(object, getAllKeysIn(object), getIteratee(predicate)); + } + + /** + * This method is like `_.get` except that if the resolved value is a + * function it's invoked with the `this` binding of its parent object and + * its result is returned. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to resolve. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] }; + * + * _.result(object, 'a[0].b.c1'); + * // => 3 + * + * _.result(object, 'a[0].b.c2'); + * // => 4 + * + * _.result(object, 'a[0].b.c3', 'default'); + * // => 'default' + * + * _.result(object, 'a[0].b.c3', _.constant('default')); + * // => 'default' + */ + function result(object, path, defaultValue) { + path = isKey(path, object) ? [path] : castPath(path); + + var index = -1, + length = path.length; + + // Ensure the loop is entered when path is empty. + if (!length) { + object = undefined; + length = 1; + } + while (++index < length) { + var value = object == null ? undefined : object[toKey(path[index])]; + if (value === undefined) { + index = length; + value = defaultValue; + } + object = isFunction(value) ? value.call(object) : value; + } + return object; + } + + /** + * Sets the value at `path` of `object`. If a portion of `path` doesn't exist, + * it's created. Arrays are created for missing index properties while objects + * are created for all other missing properties. Use `_.setWith` to customize + * `path` creation. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @returns {Object} Returns `object`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.set(object, 'a[0].b.c', 4); + * console.log(object.a[0].b.c); + * // => 4 + * + * _.set(object, ['x', '0', 'y', 'z'], 5); + * console.log(object.x[0].y.z); + * // => 5 + */ + function set(object, path, value) { + return object == null ? object : baseSet(object, path, value); + } + + /** + * This method is like `_.set` except that it accepts `customizer` which is + * invoked to produce the objects of `path`. If `customizer` returns `undefined` + * path creation is handled by the method instead. The `customizer` is invoked + * with three arguments: (nsValue, key, nsObject). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * var object = {}; + * + * _.setWith(object, '[0][1]', 'a', Object); + * // => { '0': { '1': 'a' } } + */ + function setWith(object, path, value, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return object == null ? object : baseSet(object, path, value, customizer); + } + + /** + * Creates an array of own enumerable string keyed-value pairs for `object` + * which can be consumed by `_.fromPairs`. If `object` is a map or set, its + * entries are returned. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias entries + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the key-value pairs. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.toPairs(new Foo); + * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed) + */ + var toPairs = createToPairs(keys); + + /** + * Creates an array of own and inherited enumerable string keyed-value pairs + * for `object` which can be consumed by `_.fromPairs`. If `object` is a map + * or set, its entries are returned. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias entriesIn + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the key-value pairs. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.toPairsIn(new Foo); + * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed) + */ + var toPairsIn = createToPairs(keysIn); + + /** + * An alternative to `_.reduce`; this method transforms `object` to a new + * `accumulator` object which is the result of running each of its own + * enumerable string keyed properties thru `iteratee`, with each invocation + * potentially mutating the `accumulator` object. If `accumulator` is not + * provided, a new object with the same `[[Prototype]]` will be used. The + * iteratee is invoked with four arguments: (accumulator, value, key, object). + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @since 1.3.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The custom accumulator value. + * @returns {*} Returns the accumulated value. + * @example + * + * _.transform([2, 3, 4], function(result, n) { + * result.push(n *= n); + * return n % 2 == 0; + * }, []); + * // => [4, 9] + * + * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { + * (result[value] || (result[value] = [])).push(key); + * }, {}); + * // => { '1': ['a', 'c'], '2': ['b'] } + */ + function transform(object, iteratee, accumulator) { + var isArr = isArray(object), + isArrLike = isArr || isBuffer(object) || isTypedArray(object); + + iteratee = getIteratee(iteratee, 4); + if (accumulator == null) { + var Ctor = object && object.constructor; + if (isArrLike) { + accumulator = isArr ? new Ctor : []; + } + else if (isObject(object)) { + accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {}; + } + else { + accumulator = {}; + } + } + (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) { + return iteratee(accumulator, value, index, object); + }); + return accumulator; + } + + /** + * Removes the property at `path` of `object`. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to unset. + * @returns {boolean} Returns `true` if the property is deleted, else `false`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 7 } }] }; + * _.unset(object, 'a[0].b.c'); + * // => true + * + * console.log(object); + * // => { 'a': [{ 'b': {} }] }; + * + * _.unset(object, ['a', '0', 'b', 'c']); + * // => true + * + * console.log(object); + * // => { 'a': [{ 'b': {} }] }; + */ + function unset(object, path) { + return object == null ? true : baseUnset(object, path); + } + + /** + * This method is like `_.set` except that accepts `updater` to produce the + * value to set. Use `_.updateWith` to customize `path` creation. The `updater` + * is invoked with one argument: (value). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {Function} updater The function to produce the updated value. + * @returns {Object} Returns `object`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.update(object, 'a[0].b.c', function(n) { return n * n; }); + * console.log(object.a[0].b.c); + * // => 9 + * + * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; }); + * console.log(object.x[0].y.z); + * // => 0 + */ + function update(object, path, updater) { + return object == null ? object : baseUpdate(object, path, castFunction(updater)); + } + + /** + * This method is like `_.update` except that it accepts `customizer` which is + * invoked to produce the objects of `path`. If `customizer` returns `undefined` + * path creation is handled by the method instead. The `customizer` is invoked + * with three arguments: (nsValue, key, nsObject). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {Function} updater The function to produce the updated value. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * var object = {}; + * + * _.updateWith(object, '[0][1]', _.constant('a'), Object); + * // => { '0': { '1': 'a' } } + */ + function updateWith(object, path, updater, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer); + } + + /** + * Creates an array of the own enumerable string keyed property values of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property values. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.values(new Foo); + * // => [1, 2] (iteration order is not guaranteed) + * + * _.values('hi'); + * // => ['h', 'i'] + */ + function values(object) { + return object ? baseValues(object, keys(object)) : []; + } + + /** + * Creates an array of the own and inherited enumerable string keyed property + * values of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property values. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.valuesIn(new Foo); + * // => [1, 2, 3] (iteration order is not guaranteed) + */ + function valuesIn(object) { + return object == null ? [] : baseValues(object, keysIn(object)); + } + + /*------------------------------------------------------------------------*/ + + /** + * Clamps `number` within the inclusive `lower` and `upper` bounds. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Number + * @param {number} number The number to clamp. + * @param {number} [lower] The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the clamped number. + * @example + * + * _.clamp(-10, -5, 5); + * // => -5 + * + * _.clamp(10, -5, 5); + * // => 5 + */ + function clamp(number, lower, upper) { + if (upper === undefined) { + upper = lower; + lower = undefined; + } + if (upper !== undefined) { + upper = toNumber(upper); + upper = upper === upper ? upper : 0; + } + if (lower !== undefined) { + lower = toNumber(lower); + lower = lower === lower ? lower : 0; + } + return baseClamp(toNumber(number), lower, upper); + } + + /** + * Checks if `n` is between `start` and up to, but not including, `end`. If + * `end` is not specified, it's set to `start` with `start` then set to `0`. + * If `start` is greater than `end` the params are swapped to support + * negative ranges. + * + * @static + * @memberOf _ + * @since 3.3.0 + * @category Number + * @param {number} number The number to check. + * @param {number} [start=0] The start of the range. + * @param {number} end The end of the range. + * @returns {boolean} Returns `true` if `number` is in the range, else `false`. + * @see _.range, _.rangeRight + * @example + * + * _.inRange(3, 2, 4); + * // => true + * + * _.inRange(4, 8); + * // => true + * + * _.inRange(4, 2); + * // => false + * + * _.inRange(2, 2); + * // => false + * + * _.inRange(1.2, 2); + * // => true + * + * _.inRange(5.2, 4); + * // => false + * + * _.inRange(-3, -2, -6); + * // => true + */ + function inRange(number, start, end) { + start = toFinite(start); + if (end === undefined) { + end = start; + start = 0; + } else { + end = toFinite(end); + } + number = toNumber(number); + return baseInRange(number, start, end); + } + + /** + * Produces a random number between the inclusive `lower` and `upper` bounds. + * If only one argument is provided a number between `0` and the given number + * is returned. If `floating` is `true`, or either `lower` or `upper` are + * floats, a floating-point number is returned instead of an integer. + * + * **Note:** JavaScript follows the IEEE-754 standard for resolving + * floating-point values which can produce unexpected results. + * + * @static + * @memberOf _ + * @since 0.7.0 + * @category Number + * @param {number} [lower=0] The lower bound. + * @param {number} [upper=1] The upper bound. + * @param {boolean} [floating] Specify returning a floating-point number. + * @returns {number} Returns the random number. + * @example + * + * _.random(0, 5); + * // => an integer between 0 and 5 + * + * _.random(5); + * // => also an integer between 0 and 5 + * + * _.random(5, true); + * // => a floating-point number between 0 and 5 + * + * _.random(1.2, 5.2); + * // => a floating-point number between 1.2 and 5.2 + */ + function random(lower, upper, floating) { + if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) { + upper = floating = undefined; + } + if (floating === undefined) { + if (typeof upper == 'boolean') { + floating = upper; + upper = undefined; + } + else if (typeof lower == 'boolean') { + floating = lower; + lower = undefined; + } + } + if (lower === undefined && upper === undefined) { + lower = 0; + upper = 1; + } + else { + lower = toFinite(lower); + if (upper === undefined) { + upper = lower; + lower = 0; + } else { + upper = toFinite(upper); + } + } + if (lower > upper) { + var temp = lower; + lower = upper; + upper = temp; + } + if (floating || lower % 1 || upper % 1) { + var rand = nativeRandom(); + return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper); + } + return baseRandom(lower, upper); + } + + /*------------------------------------------------------------------------*/ + + /** + * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the camel cased string. + * @example + * + * _.camelCase('Foo Bar'); + * // => 'fooBar' + * + * _.camelCase('--foo-bar--'); + * // => 'fooBar' + * + * _.camelCase('__FOO_BAR__'); + * // => 'fooBar' + */ + var camelCase = createCompounder(function(result, word, index) { + word = word.toLowerCase(); + return result + (index ? capitalize(word) : word); + }); + + /** + * Converts the first character of `string` to upper case and the remaining + * to lower case. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to capitalize. + * @returns {string} Returns the capitalized string. + * @example + * + * _.capitalize('FRED'); + * // => 'Fred' + */ + function capitalize(string) { + return upperFirst(toString(string).toLowerCase()); + } + + /** + * Deburrs `string` by converting + * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) + * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A) + * letters to basic Latin letters and removing + * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to deburr. + * @returns {string} Returns the deburred string. + * @example + * + * _.deburr('déjà vu'); + * // => 'deja vu' + */ + function deburr(string) { + string = toString(string); + return string && string.replace(reLatin, deburrLetter).replace(reComboMark, ''); + } + + /** + * Checks if `string` ends with the given target string. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to inspect. + * @param {string} [target] The string to search for. + * @param {number} [position=string.length] The position to search up to. + * @returns {boolean} Returns `true` if `string` ends with `target`, + * else `false`. + * @example + * + * _.endsWith('abc', 'c'); + * // => true + * + * _.endsWith('abc', 'b'); + * // => false + * + * _.endsWith('abc', 'b', 2); + * // => true + */ + function endsWith(string, target, position) { + string = toString(string); + target = baseToString(target); + + var length = string.length; + position = position === undefined + ? length + : baseClamp(toInteger(position), 0, length); + + var end = position; + position -= target.length; + return position >= 0 && string.slice(position, end) == target; + } + + /** + * Converts the characters "&", "<", ">", '"', and "'" in `string` to their + * corresponding HTML entities. + * + * **Note:** No other characters are escaped. To escape additional + * characters use a third-party library like [_he_](https://mths.be/he). + * + * Though the ">" character is escaped for symmetry, characters like + * ">" and "/" don't need escaping in HTML and have no special meaning + * unless they're part of a tag or unquoted attribute value. See + * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) + * (under "semi-related fun fact") for more details. + * + * When working with HTML you should always + * [quote attribute values](http://wonko.com/post/html-escaping) to reduce + * XSS vectors. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escape('fred, barney, & pebbles'); + * // => 'fred, barney, & pebbles' + */ + function escape(string) { + string = toString(string); + return (string && reHasUnescapedHtml.test(string)) + ? string.replace(reUnescapedHtml, escapeHtmlChar) + : string; + } + + /** + * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+", + * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escapeRegExp('[lodash](https://lodash.com/)'); + * // => '\[lodash\]\(https://lodash\.com/\)' + */ + function escapeRegExp(string) { + string = toString(string); + return (string && reHasRegExpChar.test(string)) + ? string.replace(reRegExpChar, '\\$&') + : string; + } + + /** + * Converts `string` to + * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the kebab cased string. + * @example + * + * _.kebabCase('Foo Bar'); + * // => 'foo-bar' + * + * _.kebabCase('fooBar'); + * // => 'foo-bar' + * + * _.kebabCase('__FOO_BAR__'); + * // => 'foo-bar' + */ + var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? '-' : '') + word.toLowerCase(); + }); + + /** + * Converts `string`, as space separated words, to lower case. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the lower cased string. + * @example + * + * _.lowerCase('--Foo-Bar--'); + * // => 'foo bar' + * + * _.lowerCase('fooBar'); + * // => 'foo bar' + * + * _.lowerCase('__FOO_BAR__'); + * // => 'foo bar' + */ + var lowerCase = createCompounder(function(result, word, index) { + return result + (index ? ' ' : '') + word.toLowerCase(); + }); + + /** + * Converts the first character of `string` to lower case. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.lowerFirst('Fred'); + * // => 'fred' + * + * _.lowerFirst('FRED'); + * // => 'fRED' + */ + var lowerFirst = createCaseFirst('toLowerCase'); + + /** + * Pads `string` on the left and right sides if it's shorter than `length`. + * Padding characters are truncated if they can't be evenly divided by `length`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example + * + * _.pad('abc', 8); + * // => ' abc ' + * + * _.pad('abc', 8, '_-'); + * // => '_-abc_-_' + * + * _.pad('abc', 3); + * // => 'abc' + */ + function pad(string, length, chars) { + string = toString(string); + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + if (!length || strLength >= length) { + return string; + } + var mid = (length - strLength) / 2; + return ( + createPadding(nativeFloor(mid), chars) + + string + + createPadding(nativeCeil(mid), chars) + ); + } + + /** + * Pads `string` on the right side if it's shorter than `length`. Padding + * characters are truncated if they exceed `length`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example + * + * _.padEnd('abc', 6); + * // => 'abc ' + * + * _.padEnd('abc', 6, '_-'); + * // => 'abc_-_' + * + * _.padEnd('abc', 3); + * // => 'abc' + */ + function padEnd(string, length, chars) { + string = toString(string); + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + return (length && strLength < length) + ? (string + createPadding(length - strLength, chars)) + : string; + } + + /** + * Pads `string` on the left side if it's shorter than `length`. Padding + * characters are truncated if they exceed `length`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example + * + * _.padStart('abc', 6); + * // => ' abc' + * + * _.padStart('abc', 6, '_-'); + * // => '_-_abc' + * + * _.padStart('abc', 3); + * // => 'abc' + */ + function padStart(string, length, chars) { + string = toString(string); + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + return (length && strLength < length) + ? (createPadding(length - strLength, chars) + string) + : string; + } + + /** + * Converts `string` to an integer of the specified radix. If `radix` is + * `undefined` or `0`, a `radix` of `10` is used unless `value` is a + * hexadecimal, in which case a `radix` of `16` is used. + * + * **Note:** This method aligns with the + * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category String + * @param {string} string The string to convert. + * @param {number} [radix=10] The radix to interpret `value` by. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {number} Returns the converted integer. + * @example + * + * _.parseInt('08'); + * // => 8 + * + * _.map(['6', '08', '10'], _.parseInt); + * // => [6, 8, 10] + */ + function parseInt(string, radix, guard) { + if (guard || radix == null) { + radix = 0; + } else if (radix) { + radix = +radix; + } + return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0); + } + + /** + * Repeats the given string `n` times. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to repeat. + * @param {number} [n=1] The number of times to repeat the string. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {string} Returns the repeated string. + * @example + * + * _.repeat('*', 3); + * // => '***' + * + * _.repeat('abc', 2); + * // => 'abcabc' + * + * _.repeat('abc', 0); + * // => '' + */ + function repeat(string, n, guard) { + if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) { + n = 1; + } else { + n = toInteger(n); + } + return baseRepeat(toString(string), n); + } + + /** + * Replaces matches for `pattern` in `string` with `replacement`. + * + * **Note:** This method is based on + * [`String#replace`](https://mdn.io/String/replace). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to modify. + * @param {RegExp|string} pattern The pattern to replace. + * @param {Function|string} replacement The match replacement. + * @returns {string} Returns the modified string. + * @example + * + * _.replace('Hi Fred', 'Fred', 'Barney'); + * // => 'Hi Barney' + */ + function replace() { + var args = arguments, + string = toString(args[0]); + + return args.length < 3 ? string : string.replace(args[1], args[2]); + } + + /** + * Converts `string` to + * [snake case](https://en.wikipedia.org/wiki/Snake_case). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the snake cased string. + * @example + * + * _.snakeCase('Foo Bar'); + * // => 'foo_bar' + * + * _.snakeCase('fooBar'); + * // => 'foo_bar' + * + * _.snakeCase('--FOO-BAR--'); + * // => 'foo_bar' + */ + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? '_' : '') + word.toLowerCase(); + }); + + /** + * Splits `string` by `separator`. + * + * **Note:** This method is based on + * [`String#split`](https://mdn.io/String/split). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to split. + * @param {RegExp|string} separator The separator pattern to split by. + * @param {number} [limit] The length to truncate results to. + * @returns {Array} Returns the string segments. + * @example + * + * _.split('a-b-c', '-', 2); + * // => ['a', 'b'] + */ + function split(string, separator, limit) { + if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) { + separator = limit = undefined; + } + limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0; + if (!limit) { + return []; + } + string = toString(string); + if (string && ( + typeof separator == 'string' || + (separator != null && !isRegExp(separator)) + )) { + separator = baseToString(separator); + if (!separator && hasUnicode(string)) { + return castSlice(stringToArray(string), 0, limit); + } + } + return string.split(separator, limit); + } + + /** + * Converts `string` to + * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage). + * + * @static + * @memberOf _ + * @since 3.1.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the start cased string. + * @example + * + * _.startCase('--foo-bar--'); + * // => 'Foo Bar' + * + * _.startCase('fooBar'); + * // => 'Foo Bar' + * + * _.startCase('__FOO_BAR__'); + * // => 'FOO BAR' + */ + var startCase = createCompounder(function(result, word, index) { + return result + (index ? ' ' : '') + upperFirst(word); + }); + + /** + * Checks if `string` starts with the given target string. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to inspect. + * @param {string} [target] The string to search for. + * @param {number} [position=0] The position to search from. + * @returns {boolean} Returns `true` if `string` starts with `target`, + * else `false`. + * @example + * + * _.startsWith('abc', 'a'); + * // => true + * + * _.startsWith('abc', 'b'); + * // => false + * + * _.startsWith('abc', 'b', 1); + * // => true + */ + function startsWith(string, target, position) { + string = toString(string); + position = baseClamp(toInteger(position), 0, string.length); + target = baseToString(target); + return string.slice(position, position + target.length) == target; + } + + /** + * Creates a compiled template function that can interpolate data properties + * in "interpolate" delimiters, HTML-escape interpolated data properties in + * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data + * properties may be accessed as free variables in the template. If a setting + * object is given, it takes precedence over `_.templateSettings` values. + * + * **Note:** In the development build `_.template` utilizes + * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) + * for easier debugging. + * + * For more information on precompiling templates see + * [lodash's custom builds documentation](https://lodash.com/custom-builds). + * + * For more information on Chrome extension sandboxes see + * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval). + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category String + * @param {string} [string=''] The template string. + * @param {Object} [options={}] The options object. + * @param {RegExp} [options.escape=_.templateSettings.escape] + * The HTML "escape" delimiter. + * @param {RegExp} [options.evaluate=_.templateSettings.evaluate] + * The "evaluate" delimiter. + * @param {Object} [options.imports=_.templateSettings.imports] + * An object to import into the template as free variables. + * @param {RegExp} [options.interpolate=_.templateSettings.interpolate] + * The "interpolate" delimiter. + * @param {string} [options.sourceURL='lodash.templateSources[n]'] + * The sourceURL of the compiled template. + * @param {string} [options.variable='obj'] + * The data object variable name. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the compiled template function. + * @example + * + * // Use the "interpolate" delimiter to create a compiled template. + * var compiled = _.template('hello <%= user %>!'); + * compiled({ 'user': 'fred' }); + * // => 'hello fred!' + * + * // Use the HTML "escape" delimiter to escape data property values. + * var compiled = _.template('<%- value %>'); + * compiled({ 'value': ' + + + + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/devtools/client/debugger/new/test/mochitest/examples/doc-sources.html firefox-trunk-52.0~a1~hg20161113r322177/devtools/client/debugger/new/test/mochitest/examples/doc-sources.html --- firefox-trunk-52.0~a1~hg20161110r321971/devtools/client/debugger/new/test/mochitest/examples/doc-sources.html 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/devtools/client/debugger/new/test/mochitest/examples/doc-sources.html 2016-11-14 01:23:07.000000000 +0000 @@ -0,0 +1,23 @@ + + + + + + Debugger test page + + + + + + + + + + + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/devtools/client/debugger/new/test/mochitest/examples/frames.js firefox-trunk-52.0~a1~hg20161113r322177/devtools/client/debugger/new/test/mochitest/examples/frames.js --- firefox-trunk-52.0~a1~hg20161110r321971/devtools/client/debugger/new/test/mochitest/examples/frames.js 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/devtools/client/debugger/new/test/mochitest/examples/frames.js 2016-11-14 01:23:07.000000000 +0000 @@ -0,0 +1,24 @@ +function recurseA(i) { + if (i == 20) { + debugger; + return; + } + + // down into the rabbit hole we go + return (i % 2) ? recurseA(++i) : recurseB(++i); +} + +function recurseB(i) { + if (i == 20) { + debugger; + return; + } + + // down into the rabbit hole we go + return (i % 2) ? recurseA(++i) : recurseB(++i); +} + + +window.startRecursion = function() { + return recurseA(0); +} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/devtools/client/debugger/new/test/mochitest/examples/nested/nested-source.js firefox-trunk-52.0~a1~hg20161113r322177/devtools/client/debugger/new/test/mochitest/examples/nested/nested-source.js --- firefox-trunk-52.0~a1~hg20161110r321971/devtools/client/debugger/new/test/mochitest/examples/nested/nested-source.js 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/devtools/client/debugger/new/test/mochitest/examples/nested/nested-source.js 2016-11-14 01:23:07.000000000 +0000 @@ -0,0 +1,3 @@ +function computeSomething() { + return 1; +} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/devtools/client/debugger/new/test/mochitest/head.js firefox-trunk-52.0~a1~hg20161113r322177/devtools/client/debugger/new/test/mochitest/head.js --- firefox-trunk-52.0~a1~hg20161110r321971/devtools/client/debugger/new/test/mochitest/head.js 2016-11-11 01:31:54.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/devtools/client/debugger/new/test/mochitest/head.js 2016-11-14 01:23:07.000000000 +0000 @@ -180,6 +180,10 @@ })); } +function waitForElement(dbg, selector) { + return waitUntil(() => findElementWithSelector(dbg, selector)) +} + /** * Assert that the debugger is paused at the correct location. * @@ -523,7 +527,13 @@ } const isLinux = Services.appinfo.OS === "Linux"; +const cmdOrCtrl = isLinux ? { ctrlKey: true } : { metaKey: true }; const keyMappings = { + sourceSearch: { code: "p", modifiers: cmdOrCtrl}, + fileSearch: { code: "f", modifiers: cmdOrCtrl}, + "Enter": { code: "VK_RETURN" }, + "Up": { code: "VK_UP" }, + "Down": { code: "VK_DOWN" }, pauseKey: { code: "VK_F8" }, resumeKey: { code: "VK_F8" }, stepOverKey: { code: "VK_F10" }, @@ -542,6 +552,7 @@ */ function pressKey(dbg, keyName) { let keyEvent = keyMappings[keyName]; + const { code, modifiers } = keyEvent; return EventUtils.synthesizeKey( code, @@ -550,6 +561,12 @@ ); } +function type(dbg, string) { + string.split("").forEach(char => { + EventUtils.synthesizeKey(char, {}, dbg.win); + }); +} + function isVisibleWithin(outerEl, innerEl) { const innerRect = innerEl.getBoundingClientRect(); const outerRect = outerEl.getBoundingClientRect(); @@ -559,11 +576,14 @@ const selectors = { callStackHeader: ".call-stack-pane ._header", + callStackBody: ".call-stack-pane .pane", scopesHeader: ".scopes-pane ._header", breakpointItem: i => `.breakpoints-list .breakpoint:nth-child(${i})`, scopeNode: i => `.scopes-list .tree-node:nth-child(${i}) .object-label`, - frame: index => `.frames ul li:nth-child(${index})`, + frame: i => `.frames ul li:nth-child(${i})`, + frames: ".frames ul li", gutter: i => `.CodeMirror-code *:nth-child(${i}) .CodeMirror-linenumber`, + menuitem: i => `menupopup menuitem:nth-child(${i})`, pauseOnExceptions: ".pause-exceptions", breakpoint: ".CodeMirror-code > .new-breakpoint", highlightLine: ".CodeMirror-code > .highlight-line", @@ -574,7 +594,10 @@ stepIn: ".stepIn.active", toggleBreakpoints: ".toggleBreakpoints", prettyPrintButton: ".prettyPrint", - sourceFooter: ".source-footer" + sourceFooter: ".source-footer", + sourceNode: i => `.sources-list .tree-node:nth-child(${i})`, + sourceNodes: ".sources-list .tree-node", + sourceArrow: i => `.sources-list .tree-node:nth-child(${i}) .arrow`, }; function getSelector(elementName, ...args) { @@ -592,6 +615,10 @@ function findElement(dbg, elementName, ...args) { const selector = getSelector(elementName, ...args); + return findElementWithSelector(dbg, selector); +} + +function findElementWithSelector(dbg, selector) { return dbg.win.document.querySelector(selector); } @@ -612,14 +639,34 @@ */ function clickElement(dbg, elementName, ...args) { const selector = getSelector(elementName, ...args); + return EventUtils.synthesizeMouseAtCenter( + findElementWithSelector(dbg, selector), + {}, + dbg.win + ); +} + +function rightClickElement(dbg, elementName, ...args) { + const selector = getSelector(elementName, ...args); const doc = dbg.win.document; return EventUtils.synthesizeMouseAtCenter( doc.querySelector(selector), - {}, + {type: "contextmenu"}, dbg.win ); } +function selectMenuItem(dbg, index) { + // the context menu is in the toolbox window + const doc = dbg.toolbox.win.document; + + // there are several context menus, we want the one with the menu-api + const popup = doc.querySelector("menupopup[menu-api=\"true\"]"); + + const item = popup.querySelector(`menuitem:nth-child(${index})`); + return EventUtils.synthesizeMouseAtCenter(item, {}, dbg.toolbox.win ); +} + /** * Toggles the debugger call stack accordian. * diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/devtools/client/framework/source-map.js firefox-trunk-52.0~a1~hg20161113r322177/devtools/client/framework/source-map.js --- firefox-trunk-52.0~a1~hg20161110r321971/devtools/client/framework/source-map.js 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/devtools/client/framework/source-map.js 2016-11-14 01:24:30.000000000 +0000 @@ -0,0 +1,84 @@ +// @flow + +const { + originalToGeneratedId, + generatedToOriginalId, + isGeneratedId, + isOriginalId +} = require("./source-map-util"); + +function workerTask(worker, method) { + return function(...args: any) { + return new Promise((resolve, reject) => { + const id = msgId++; + worker.postMessage({ id, method, args }); + + const listener = ({ data: result }) => { + if (result.id !== id) { + return; + } + + worker.removeEventListener("message", listener); + if (result.error) { + reject(result.error); + } else { + resolve(result.response); + } + }; + + worker.addEventListener("message", listener); + }); + }; +} + +let sourceMapWorker; +function restartWorker() { + if (sourceMapWorker) { + sourceMapWorker.terminate(); + } + sourceMapWorker = new Worker( + "resource://devtools/client/framework/source-map-worker.js" + ); + + if (Services.prefs.getBoolPref("devtools.debugger.client-source-maps-enabled")) { + sourceMapWorker.postMessage({ id: 0, method: "enableSourceMaps" }); + } +} +restartWorker(); + +function destroyWorker() { + if (sourceMapWorker) { + sourceMapWorker.terminate(); + sourceMapWorker = null; + } +} + +function shouldSourceMap() { + return Services.prefs.getBoolPref("devtools.debugger.client-source-maps-enabled"); +} + +const getOriginalURLs = workerTask(sourceMapWorker, "getOriginalURLs"); +const getGeneratedLocation = workerTask(sourceMapWorker, + "getGeneratedLocation"); +const getOriginalLocation = workerTask(sourceMapWorker, + "getOriginalLocation"); +const getOriginalSourceText = workerTask(sourceMapWorker, + "getOriginalSourceText"); +const applySourceMap = workerTask(sourceMapWorker, "applySourceMap"); +const clearSourceMaps = workerTask(sourceMapWorker, "clearSourceMaps"); + +module.exports = { + originalToGeneratedId, + generatedToOriginalId, + isGeneratedId, + isOriginalId, + + getOriginalURLs, + getGeneratedLocation, + getOriginalLocation, + getOriginalSourceText, + applySourceMap, + clearSourceMaps, + destroyWorker, + shouldSourceMap +}; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/devtools/client/framework/source-map-util.js firefox-trunk-52.0~a1~hg20161113r322177/devtools/client/framework/source-map-util.js --- firefox-trunk-52.0~a1~hg20161110r321971/devtools/client/framework/source-map-util.js 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/devtools/client/framework/source-map-util.js 2016-11-14 01:24:30.000000000 +0000 @@ -0,0 +1,20 @@ +function originalToGeneratedId(originalId) { + const match = originalId.match(/(.*)\/originalSource/); + return match ? match[1] : ""; +} + +function generatedToOriginalId(generatedId, url) { + return generatedId + "/originalSource-" + url.replace(/ \//, '-'); +} + +function isOriginalId(id) { + return !!id.match(/\/originalSource/); +} + +function isGeneratedId(id) { + return !isOriginalId(id); +} + +module.exports = { + originalToGeneratedId, generatedToOriginalId, isOriginalId, isGeneratedId +}; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/devtools/client/framework/source-map-worker.js firefox-trunk-52.0~a1~hg20161113r322177/devtools/client/framework/source-map-worker.js --- firefox-trunk-52.0~a1~hg20161110r321971/devtools/client/framework/source-map-worker.js 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/devtools/client/framework/source-map-worker.js 2016-11-14 01:24:30.000000000 +0000 @@ -0,0 +1,220 @@ +const { fetch, assert } = require("devtools/shared/DevToolsUtils"); +const { joinURI } = require("devtools/shared/path"); +const path = require("sdk/fs/path"); +const { SourceMapConsumer, SourceMapGenerator } = require("source-map"); +const { isJavaScript } = require("./source"); +const { + originalToGeneratedId, + generatedToOriginalId, + isGeneratedId, + isOriginalId +} = require("./source-map-util"); + +let sourceMapRequests = new Map(); +let sourceMapsEnabled = false; + +function clearSourceMaps() { + sourceMapRequests.clear(); +} + +function enableSourceMaps() { + sourceMapsEnabled = true; +} + +function _resolveSourceMapURL(source) { + const { url = "", sourceMapURL = "" } = source; + if (path.isURL(sourceMapURL) || url == "") { + // If it's already a full URL or the source doesn't have a URL, + // don't resolve anything. + return sourceMapURL; + } else if (path.isAbsolute(sourceMapURL)) { + // If it's an absolute path, it should be resolved relative to the + // host of the source. + const { protocol = "", host = "" } = parse(url); + return `${protocol}//${host}${sourceMapURL}`; + } + // Otherwise, it's a relative path and should be resolved relative + // to the source. + return dirname(url) + "/" + sourceMapURL; +} + +/** + * Sets the source map's sourceRoot to be relative to the source map url. + * @memberof utils/source-map-worker + * @static + */ +function _setSourceMapRoot(sourceMap, absSourceMapURL, source) { + // No need to do this fiddling if we won't be fetching any sources over the + // wire. + if (sourceMap.hasContentsOfAllSources()) { + return; + } + + const base = dirname( + (absSourceMapURL.indexOf("data:") === 0 && source.url) ? + source.url : + absSourceMapURL + ); + + if (sourceMap.sourceRoot) { + sourceMap.sourceRoot = joinURI(base, sourceMap.sourceRoot); + } else { + sourceMap.sourceRoot = base; + } + + return sourceMap; +} + +function _getSourceMap(generatedSourceId) + : ?Promise { + return sourceMapRequests.get(generatedSourceId); +} + +async function _resolveAndFetch(generatedSource) : SourceMapConsumer { + // Fetch the sourcemap over the network and create it. + const sourceMapURL = _resolveSourceMapURL(generatedSource); + const fetched = await fetch( + sourceMapURL, { loadFromCache: false } + ); + + // Create the source map and fix it up. + const map = new SourceMapConsumer(fetched.content); + _setSourceMapRoot(map, sourceMapURL, generatedSource); + return map; +} + +function _fetchSourceMap(generatedSource) { + const existingRequest = sourceMapRequests.get(generatedSource.id); + if (existingRequest) { + // If it has already been requested, return the request. Make sure + // to do this even if sourcemapping is turned off, because + // pretty-printing uses sourcemaps. + // + // An important behavior here is that if it's in the middle of + // requesting it, all subsequent calls will block on the initial + // request. + return existingRequest; + } else if (!generatedSource.sourceMapURL || !sourceMapsEnabled) { + return Promise.resolve(null); + } + + // Fire off the request, set it in the cache, and return it. + // Suppress any errors and just return null (ignores bogus + // sourcemaps). + const req = _resolveAndFetch(generatedSource).catch(() => null); + sourceMapRequests.set(generatedSource.id, req); + return req; +} + +async function getOriginalURLs(generatedSource) { + const map = await _fetchSourceMap(generatedSource); + return map && map.sources; +} + +async function getGeneratedLocation(location: Location, originalSource: Source) + : Promise { + if (!isOriginalId(location.sourceId)) { + return location; + } + + const generatedSourceId = originalToGeneratedId(location.sourceId); + const map = await _getSourceMap(generatedSourceId); + if (!map) { + return location; + } + + const { line, column } = map.generatedPositionFor({ + source: originalSource.url, + line: location.line, + column: location.column == null ? 0 : location.column + }); + + return { + sourceId: generatedSourceId, + line: line, + // Treat 0 as no column so that line breakpoints work correctly. + column: column === 0 ? undefined : column + }; +} + +async function getOriginalLocation(location) { + if (!isGeneratedId(location.sourceId)) { + return location; + } + + const map = await _getSourceMap(location.sourceId); + if (!map) { + return location; + } + + const { source: url, line, column } = map.originalPositionFor({ + line: location.line, + column: location.column == null ? Infinity : location.column + }); + + if (url == null) { + // No url means the location didn't map. + return location; + } + + return { + sourceId: generatedToOriginalId(location.sourceId, url), + line, + column + }; +} + +async function getOriginalSourceText(originalSource) { + assert(isOriginalId(originalSource.id), + "Source is not an original source"); + + const generatedSourceId = originalToGeneratedId(originalSource.id); + const map = await _getSourceMap(generatedSourceId); + if (!map) { + return null; + } + + let text = map.sourceContentFor(originalSource.url); + if (!text) { + text = (await fetch( + originalSource.url, { loadFromCache: false } + )).content; + } + + return { + text, + contentType: isJavaScript(originalSource.url || "") ? + "text/javascript" : + "text/plain" + }; +} + +function applySourceMap(generatedId, url, code, mappings) { + const generator = new SourceMapGenerator({ file: url }); + mappings.forEach(mapping => generator.addMapping(mapping)); + generator.setSourceContent(url, code); + + const map = SourceMapConsumer(generator.toJSON()); + sourceMapRequests.set(generatedId, Promise.resolve(map)); +} + +const publicInterface = { + getOriginalURLs, + getGeneratedLocation, + getOriginalLocation, + getOriginalSourceText, + enableSourceMaps, + applySourceMap, + clearSourceMaps +}; + +self.onmessage = function(msg) { + const { id, method, args } = msg.data; + const response = publicInterface[method].apply(undefined, args); + if (response instanceof Promise) { + response.then(val => self.postMessage({ id, response: val }), + err => self.postMessage({ id, error: err })); + } else { + self.postMessage({ id, response }); + } +}; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/devtools/client/inspector/computed/computed.js firefox-trunk-52.0~a1~hg20161113r322177/devtools/client/inspector/computed/computed.js --- firefox-trunk-52.0~a1~hg20161110r321971/devtools/client/inspector/computed/computed.js 2016-11-11 01:33:13.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/devtools/client/inspector/computed/computed.js 2016-11-14 01:24:32.000000000 +0000 @@ -17,9 +17,15 @@ const {createChild} = require("devtools/client/inspector/shared/utils"); const {gDevTools} = require("devtools/client/framework/devtools"); const {getCssProperties} = require("devtools/shared/fronts/css-properties"); - -const overlays = require("devtools/client/inspector/shared/style-inspector-overlays"); +const HighlightersOverlay = require("devtools/client/inspector/shared/highlighters-overlay"); +const { + VIEW_NODE_SELECTOR_TYPE, + VIEW_NODE_PROPERTY_TYPE, + VIEW_NODE_VALUE_TYPE, + VIEW_NODE_IMAGE_URL_TYPE, +} = require("devtools/client/inspector/shared/node-types"); const StyleInspectorMenu = require("devtools/client/inspector/shared/style-inspector-menu"); +const TooltipsOverlay = require("devtools/client/inspector/shared/tooltips-overlay"); const {KeyShortcuts} = require("devtools/client/shared/key-shortcuts"); const {BoxModelView} = require("devtools/client/inspector/components/box-model"); const clipboardHelper = require("devtools/shared/platform/clipboard"); @@ -207,10 +213,10 @@ this._contextmenu = new StyleInspectorMenu(this, { isRuleView: false }); // Add the tooltips and highlightersoverlay - this.tooltips = new overlays.TooltipsOverlay(this); + this.tooltips = new TooltipsOverlay(this); this.tooltips.addToView(); - this.highlighters = new overlays.HighlightersOverlay(this); + this.highlighters = new HighlightersOverlay(this); this.highlighters.addToView(); } @@ -301,7 +307,7 @@ * The node which we want information about * @return {Object} The type information object contains the following props: * - type {String} One of the VIEW_NODE_XXX_TYPE const in - * style-inspector-overlays + * client/inspector/shared/node-types * - value {Object} Depends on the type of the node * returns null if the node isn't anything we care about */ @@ -324,7 +330,7 @@ } } return { - type: overlays.VIEW_NODE_SELECTOR_TYPE, + type: VIEW_NODE_SELECTOR_TYPE, value: selectorText.trim() }; } @@ -371,12 +377,12 @@ // Get the type if (classes.contains("property-name")) { - type = overlays.VIEW_NODE_PROPERTY_TYPE; + type = VIEW_NODE_PROPERTY_TYPE; } else if (classes.contains("property-value") || classes.contains("other-property-value")) { - type = overlays.VIEW_NODE_VALUE_TYPE; + type = VIEW_NODE_VALUE_TYPE; } else if (isHref) { - type = overlays.VIEW_NODE_IMAGE_URL_TYPE; + type = VIEW_NODE_IMAGE_URL_TYPE; value.url = node.href; } else { return null; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/devtools/client/inspector/computed/test/browser_computed_getNodeInfo.js firefox-trunk-52.0~a1~hg20161113r322177/devtools/client/inspector/computed/test/browser_computed_getNodeInfo.js --- firefox-trunk-52.0~a1~hg20161110r321971/devtools/client/inspector/computed/test/browser_computed_getNodeInfo.js 2016-11-11 01:33:13.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/devtools/client/inspector/computed/test/browser_computed_getNodeInfo.js 2016-11-14 01:24:32.000000000 +0000 @@ -5,9 +5,10 @@ "use strict"; // Tests various output of the computed-view's getNodeInfo method. -// This method is used by the style-inspector-overlay on mouseover to decide -// which tooltip or highlighter to show when hovering over a -// value/name/selector if any. +// This method is used by the HighlightersOverlay and TooltipsOverlay on mouseover to +// decide which highlighter or tooltip to show when hovering over a value/name/selector +// if any. +// // For instance, browser_ruleview_selector-highlighter_01.js and // browser_ruleview_selector-highlighter_02.js test that the selector // highlighter appear when hovering over a selector in the rule-view. @@ -20,7 +21,7 @@ VIEW_NODE_PROPERTY_TYPE, VIEW_NODE_VALUE_TYPE, VIEW_NODE_IMAGE_URL_TYPE -} = require("devtools/client/inspector/shared/style-inspector-overlays"); +} = require("devtools/client/inspector/shared/node-types"); const TEST_URI = ` @@ -260,7 +255,9 @@ if not isSupportFile and not ahemFontAdded and 'ahem' in gTestFlags[test] and re.search(searchRegex, line): # First put our ahem font declation before the first - - - This page should have a light green background. - - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-conditional-3/reference/background-lime.html firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-conditional-3/reference/background-lime.html --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-conditional-3/reference/background-lime.html 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-conditional-3/reference/background-lime.html 2016-11-14 01:09:27.000000000 +0000 @@ -0,0 +1,14 @@ + + + + CSS Test Reference + + + + + + This page should have a light green background. + + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-multicol-1/multicol-basic-ref.html firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-multicol-1/multicol-basic-ref.html --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-multicol-1/multicol-basic-ref.html 2016-11-11 01:22:18.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-multicol-1/multicol-basic-ref.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ - - - - - CSS Test reference - - - - - - - - -

Test passes if there are three vertical stripes in the yellow box below: 1st purple, 2nd orange, 3rd blue.

-
- - - - - - -
XXXX XXXX XXXX XXXX XXXX XXXX XXXX
XXXX XXXX XXXX XXXX XXXX XXXX XXXX
XXXX XXXX XXXX XXXX XXXX XXXX XXXX
-
- - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-multicol-1/reference/multicol-basic-ref.html firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-multicol-1/reference/multicol-basic-ref.html --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-multicol-1/reference/multicol-basic-ref.html 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-multicol-1/reference/multicol-basic-ref.html 2016-11-14 01:09:30.000000000 +0000 @@ -0,0 +1,77 @@ + + + + + CSS Test reference + + + + + + + + +

Test passes if there are three vertical stripes in the yellow box below: 1st purple, 2nd orange, 3rd blue.

+
+ + + + + + +
XXXX XXXX XXXX XXXX XXXX XXXX XXXX
XXXX XXXX XXXX XXXX XXXX XXXX XXXX
XXXX XXXX XXXX XXXX XXXX XXXX XXXX
+
+ + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-multicol-1/ref-filled-green-100px-square.xht firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-multicol-1/ref-filled-green-100px-square.xht --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-multicol-1/ref-filled-green-100px-square.xht 2016-11-11 01:22:36.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-multicol-1/ref-filled-green-100px-square.xht 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ - - - - CSS Reftest Reference - - - - -

Test passes if there is a filled green square and no red.

-
- - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-1-block.xml firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-1-block.xml --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-1-block.xml 2016-11-11 01:22:37.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-1-block.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ - - - - - CSS Namespaces Test Suite reference - - -

This sentence should have a green background.

- - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-1-generic.xml firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-1-generic.xml --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-1-generic.xml 2016-11-11 01:22:37.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-1-generic.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ - - - - - CSS Namespaces Test Suite reference - - - This sentence should have a green background. - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-1.xml firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-1.xml --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-1.xml 2016-11-11 01:22:37.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-1.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ - - - - - CSS Namespaces Test Suite reference - - -

This sentence should have a green background.

- - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-2-generic.xml firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-2-generic.xml --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-2-generic.xml 2016-11-11 01:22:37.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-2-generic.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ - - - - - CSS Namespaces Test Suite reference - - - This sentence should have a green background. - This sentence should have a green background. - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-2.xml firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-2.xml --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-2.xml 2016-11-11 01:22:37.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-2.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ - - - - - CSS Namespaces Test Suite reference - - -

This sentence should have a green background.

-

This sentence should have a green background.

- - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-3.xml firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-3.xml --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-3.xml 2016-11-11 01:22:37.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-3.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ - - - - - CSS Namespaces Test Suite reference - - -

This sentence should have a green background.

-

This sentence should have a green background.

-

This sentence should have a green background.

- - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-5.xml firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-5.xml --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-5.xml 2016-11-11 01:22:37.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-5.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ - - - - - CSS Namespaces Test Suite reference - - -

This sentence should have a green background.

-

This sentence should have a green background.

-

This sentence should have a green background.

-

This sentence should have a green background.

-

This sentence should have a green background.

- - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-6.xml firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-6.xml --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-6.xml 2016-11-11 01:22:37.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/ref-lime-6.xml 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ - - - - - CSS Namespaces Test Suite reference - - -

This sentence should have a green background.

-

This sentence should have a green background.

-

This sentence should have a green background.

-

This sentence should have a green background.

-

This sentence should have a green background.

-

This sentence should have a green background.

- - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-1-block.xml firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-1-block.xml --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-1-block.xml 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-1-block.xml 2016-11-14 01:09:30.000000000 +0000 @@ -0,0 +1,10 @@ + + + + + CSS Namespaces Test Suite reference + + +

This sentence should have a green background.

+ + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-1-generic.xml firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-1-generic.xml --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-1-generic.xml 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-1-generic.xml 2016-11-14 01:09:30.000000000 +0000 @@ -0,0 +1,11 @@ + + + + + CSS Namespaces Test Suite reference + + + This sentence should have a green background. + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-1.xml firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-1.xml --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-1.xml 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-1.xml 2016-11-14 01:09:30.000000000 +0000 @@ -0,0 +1,10 @@ + + + + + CSS Namespaces Test Suite reference + + +

This sentence should have a green background.

+ + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-2-generic.xml firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-2-generic.xml --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-2-generic.xml 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-2-generic.xml 2016-11-14 01:09:30.000000000 +0000 @@ -0,0 +1,13 @@ + + + + + CSS Namespaces Test Suite reference + + + This sentence should have a green background. + This sentence should have a green background. + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-2.xml firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-2.xml --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-2.xml 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-2.xml 2016-11-14 01:09:30.000000000 +0000 @@ -0,0 +1,11 @@ + + + + + CSS Namespaces Test Suite reference + + +

This sentence should have a green background.

+

This sentence should have a green background.

+ + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-3.xml firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-3.xml --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-3.xml 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-3.xml 2016-11-14 01:09:30.000000000 +0000 @@ -0,0 +1,12 @@ + + + + + CSS Namespaces Test Suite reference + + +

This sentence should have a green background.

+

This sentence should have a green background.

+

This sentence should have a green background.

+ + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-5.xml firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-5.xml --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-5.xml 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-5.xml 2016-11-14 01:09:30.000000000 +0000 @@ -0,0 +1,14 @@ + + + + + CSS Namespaces Test Suite reference + + +

This sentence should have a green background.

+

This sentence should have a green background.

+

This sentence should have a green background.

+

This sentence should have a green background.

+

This sentence should have a green background.

+ + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-6.xml firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-6.xml --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-6.xml 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-namespaces-3/reftest/ref-lime-6.xml 2016-11-14 01:09:30.000000000 +0000 @@ -0,0 +1,15 @@ + + + + + CSS Namespaces Test Suite reference + + +

This sentence should have a green background.

+

This sentence should have a green background.

+

This sentence should have a green background.

+

This sentence should have a green background.

+

This sentence should have a green background.

+

This sentence should have a green background.

+ + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-values-3/200-200-green.html firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-values-3/200-200-green.html --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-values-3/200-200-green.html 2016-11-11 01:22:37.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-values-3/200-200-green.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ - - - - - - CSS Values and Units Test: - Viewport units are interpolated correctly (reference rendering) - - - - - - - - - -
- - - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-values-3/all-green.html firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-values-3/all-green.html --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-values-3/all-green.html 2016-11-11 01:22:37.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-values-3/all-green.html 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ - \ No newline at end of file diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-values-3/ch-unit-001-ref.html firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-values-3/ch-unit-001-ref.html --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-values-3/ch-unit-001-ref.html 2016-11-11 01:22:37.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-values-3/ch-unit-001-ref.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ - - -CSS Values and Units Test Reference File - - - - -

Test passes if there is a filled green square and no red.

-
- diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-values-3/reference/200-200-green.html firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-values-3/reference/200-200-green.html --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-values-3/reference/200-200-green.html 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-values-3/reference/200-200-green.html 2016-11-14 01:09:41.000000000 +0000 @@ -0,0 +1,33 @@ + + + + + + CSS Values and Units Test: + Viewport units are interpolated correctly (reference rendering) + + + + + + + + + +
+ + + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-values-3/reference/all-green.html firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-values-3/reference/all-green.html --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-values-3/reference/all-green.html 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-values-3/reference/all-green.html 2016-11-14 01:09:41.000000000 +0000 @@ -0,0 +1 @@ + \ No newline at end of file diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-values-3/reference/ch-unit-001-ref.html firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-values-3/reference/ch-unit-001-ref.html --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-values-3/reference/ch-unit-001-ref.html 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-values-3/reference/ch-unit-001-ref.html 2016-11-14 01:09:41.000000000 +0000 @@ -0,0 +1,18 @@ + + +CSS Values and Units Test Reference File + + + + +

Test passes if there is a filled green square and no red.

+
+ diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-values-3/reference/vh_not_refreshing_on_chrome-ref.html firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-values-3/reference/vh_not_refreshing_on_chrome-ref.html --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-values-3/reference/vh_not_refreshing_on_chrome-ref.html 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-values-3/reference/vh_not_refreshing_on_chrome-ref.html 2016-11-14 01:09:41.000000000 +0000 @@ -0,0 +1,50 @@ + + + + + + CSS Reference File + + + + + + + + + + + + + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-values-3/vh_not_refreshing_on_chrome-ref.html firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-values-3/vh_not_refreshing_on_chrome-ref.html --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/css-values-3/vh_not_refreshing_on_chrome-ref.html 2016-11-11 01:22:37.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/css-values-3/vh_not_refreshing_on_chrome-ref.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,50 +0,0 @@ - - - - - - CSS Reference File - - - - - - - - - - - - - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/import.log firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/import.log --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/import.log 2016-11-11 01:22:37.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/import.log 2016-11-14 01:10:22.000000000 +0000 @@ -1,7 +1,7 @@ Importing revision: d261d6def2373f64d94b113860b29d3e45a02bd1 -from repository: https://hg.csswg.org/test/ +from repository: https://hg.csswg.org/test Importing css-conditional-3/at-media-whitespace-optional-001.html to css-conditional-3/at-media-whitespace-optional-001.html -Importing css-conditional-3/reference/background-lime.html to css-conditional-3/background-lime.html +Importing css-conditional-3/reference/background-lime.html to css-conditional-3/reference/background-lime.html Importing css-conditional-3/at-media-whitespace-optional-002.html to css-conditional-3/at-media-whitespace-optional-002.html Importing css-conditional-3/at-supports-001.html to css-conditional-3/at-supports-001.html Importing css-conditional-3/at-supports-001-ref.html to css-conditional-3/at-supports-001-ref.html @@ -85,7 +85,7 @@ Importing css-multicol-1/support/test-outer.png to css-multicol-1/support/test-outer.png Importing css-multicol-1/support/test-tl.png to css-multicol-1/support/test-tl.png Importing css-multicol-1/support/test-tr.png to css-multicol-1/support/test-tr.png -Importing css-multicol-1/reference/multicol-basic-ref.html to css-multicol-1/multicol-basic-ref.html +Importing css-multicol-1/reference/multicol-basic-ref.html to css-multicol-1/reference/multicol-basic-ref.html Importing css-multicol-1/multicol-basic-002.html to css-multicol-1/multicol-basic-002.html Importing css-multicol-1/multicol-basic-003.html to css-multicol-1/multicol-basic-003.html Importing css-multicol-1/multicol-basic-004.html to css-multicol-1/multicol-basic-004.html @@ -189,7 +189,7 @@ Importing css-multicol-1/multicol-list-item-001.xht to css-multicol-1/multicol-list-item-001.xht Importing css-multicol-1/multicol-list-item-001-ref.xht to css-multicol-1/multicol-list-item-001-ref.xht Importing css-multicol-1/multicol-margin-001.xht to css-multicol-1/multicol-margin-001.xht -Importing css-multicol-1/../reference/ref-filled-green-100px-square.xht to css-multicol-1/ref-filled-green-100px-square.xht +Importing reference/ref-filled-green-100px-square.xht to reference/ref-filled-green-100px-square.xht Importing css-multicol-1/multicol-margin-002.xht to css-multicol-1/multicol-margin-002.xht Importing css-multicol-1/multicol-margin-child-001.xht to css-multicol-1/multicol-margin-child-001.xht Importing css-multicol-1/multicol-margin-child-001-ref.xht to css-multicol-1/multicol-margin-child-001-ref.xht @@ -258,7 +258,7 @@ Importing css-multicol-1/multicol-rule-samelength-001.xht to css-multicol-1/multicol-rule-samelength-001.xht Importing css-multicol-1/multicol-rule-samelength-001-ref.xht to css-multicol-1/multicol-rule-samelength-001-ref.xht Importing css-multicol-1/multicol-rule-shorthand-001.xht to css-multicol-1/multicol-rule-shorthand-001.xht -Warning: href attribute found empty in /Users/npancholi/builds/CSSWGTests/test/css-multicol-1/multicol-rule-shorthand-2.xht +Warning: href attribute found empty in ../../../../csswg-test/css-multicol-1\multicol-rule-shorthand-2.xht Importing css-multicol-1/multicol-rule-solid-000.xht to css-multicol-1/multicol-rule-solid-000.xht Importing css-multicol-1/multicol-rule-solid-000-ref.xht to css-multicol-1/multicol-rule-solid-000-ref.xht Importing css-multicol-1/multicol-rule-stacking-001.xht to css-multicol-1/multicol-rule-stacking-001.xht @@ -330,22 +330,22 @@ Importing css-namespaces-3/support/scope-002a.css to css-namespaces-3/support/scope-002a.css Importing css-namespaces-3/support/scope-002b.css to css-namespaces-3/support/scope-002b.css Importing css-namespaces-3/support/syntax-007.css to css-namespaces-3/support/syntax-007.css -Importing css-namespaces-3/reftest/ref-lime-1.xml to css-namespaces-3/ref-lime-1.xml +Importing css-namespaces-3/reftest/ref-lime-1.xml to css-namespaces-3/reftest/ref-lime-1.xml Importing css-namespaces-3/prefix-002.xml to css-namespaces-3/prefix-002.xml Importing css-namespaces-3/prefix-003.xml to css-namespaces-3/prefix-003.xml -Importing css-namespaces-3/reftest/ref-lime-1-generic.xml to css-namespaces-3/ref-lime-1-generic.xml +Importing css-namespaces-3/reftest/ref-lime-1-generic.xml to css-namespaces-3/reftest/ref-lime-1-generic.xml Importing css-namespaces-3/prefix-004.xml to css-namespaces-3/prefix-004.xml -Importing css-namespaces-3/reftest/ref-lime-2-generic.xml to css-namespaces-3/ref-lime-2-generic.xml +Importing css-namespaces-3/reftest/ref-lime-2-generic.xml to css-namespaces-3/reftest/ref-lime-2-generic.xml Importing css-namespaces-3/prefix-005.xml to css-namespaces-3/prefix-005.xml Importing css-namespaces-3/prefix-006.xml to css-namespaces-3/prefix-006.xml -Importing css-namespaces-3/reftest/ref-lime-2.xml to css-namespaces-3/ref-lime-2.xml +Importing css-namespaces-3/reftest/ref-lime-2.xml to css-namespaces-3/reftest/ref-lime-2.xml Importing css-namespaces-3/scope-001.xml to css-namespaces-3/scope-001.xml Importing css-namespaces-3/scope-002.xml to css-namespaces-3/scope-002.xml Importing css-namespaces-3/syntax-001.xml to css-namespaces-3/syntax-001.xml -Importing css-namespaces-3/reftest/ref-lime-1-block.xml to css-namespaces-3/ref-lime-1-block.xml +Importing css-namespaces-3/reftest/ref-lime-1-block.xml to css-namespaces-3/reftest/ref-lime-1-block.xml Importing css-namespaces-3/syntax-002.xml to css-namespaces-3/syntax-002.xml Importing css-namespaces-3/syntax-003.xml to css-namespaces-3/syntax-003.xml -Importing css-namespaces-3/reftest/ref-lime-5.xml to css-namespaces-3/ref-lime-5.xml +Importing css-namespaces-3/reftest/ref-lime-5.xml to css-namespaces-3/reftest/ref-lime-5.xml Importing css-namespaces-3/syntax-004.xml to css-namespaces-3/syntax-004.xml Importing css-namespaces-3/syntax-005.xml to css-namespaces-3/syntax-005.xml Importing css-namespaces-3/syntax-006.xml to css-namespaces-3/syntax-006.xml @@ -353,9 +353,9 @@ Importing css-namespaces-3/syntax-008.xml to css-namespaces-3/syntax-008.xml Importing css-namespaces-3/syntax-009.xml to css-namespaces-3/syntax-009.xml Importing css-namespaces-3/syntax-010.xml to css-namespaces-3/syntax-010.xml -Importing css-namespaces-3/reftest/ref-lime-3.xml to css-namespaces-3/ref-lime-3.xml +Importing css-namespaces-3/reftest/ref-lime-3.xml to css-namespaces-3/reftest/ref-lime-3.xml Importing css-namespaces-3/syntax-011.xml to css-namespaces-3/syntax-011.xml -Importing css-namespaces-3/reftest/ref-lime-6.xml to css-namespaces-3/ref-lime-6.xml +Importing css-namespaces-3/reftest/ref-lime-6.xml to css-namespaces-3/reftest/ref-lime-6.xml Importing css-namespaces-3/syntax-012.xml to css-namespaces-3/syntax-012.xml Importing css-namespaces-3/syntax-013.xml to css-namespaces-3/syntax-013.xml Importing css-namespaces-3/syntax-014.xml to css-namespaces-3/syntax-014.xml @@ -405,7 +405,7 @@ Importing css-values-3/support/support/README to css-values-3/support/support/README Importing css-values-3/support/support/swatch-green.png to css-values-3/support/support/swatch-green.png Importing css-values-3/support/support/swatch-red.png to css-values-3/support/support/swatch-red.png -Importing css-values-3/reference/200-200-green.html to css-values-3/200-200-green.html +Importing css-values-3/reference/200-200-green.html to css-values-3/reference/200-200-green.html Importing css-values-3/attr-color-invalid-fallback.html to css-values-3/attr-color-invalid-fallback.html Importing css-values-3/attr-color-valid.html to css-values-3/attr-color-valid.html Importing css-values-3/attr-invalid-type-001.html to css-values-3/attr-invalid-type-001.html @@ -420,13 +420,13 @@ Importing css-values-3/attr-px-invalid-fallback.html to css-values-3/attr-px-invalid-fallback.html Importing css-values-3/attr-px-valid.html to css-values-3/attr-px-valid.html Importing css-values-3/calc-in-calc.html to css-values-3/calc-in-calc.html -Importing css-values-3/reference/all-green.html to css-values-3/all-green.html +Importing css-values-3/reference/all-green.html to css-values-3/reference/all-green.html Importing css-values-3/calc-in-media-queries-001.html to css-values-3/calc-in-media-queries-001.html Importing css-values-3/calc-in-media-queries-002.html to css-values-3/calc-in-media-queries-002.html Importing css-values-3/calc-invalid-range-clamping.html to css-values-3/calc-invalid-range-clamping.html Importing css-values-3/calc-parenthesis-stack.html to css-values-3/calc-parenthesis-stack.html Importing css-values-3/ch-unit-001.html to css-values-3/ch-unit-001.html -Importing css-values-3/reference/ch-unit-001-ref.html to css-values-3/ch-unit-001-ref.html +Importing css-values-3/reference/ch-unit-001-ref.html to css-values-3/reference/ch-unit-001-ref.html Importing css-values-3/initial-background-color.html to css-values-3/initial-background-color.html Importing css-values-3/vh-calc-support-pct.html to css-values-3/vh-calc-support-pct.html Importing css-values-3/vh-calc-support.html to css-values-3/vh-calc-support.html @@ -442,7 +442,7 @@ Importing css-values-3/vh-support.html to css-values-3/vh-support.html Importing css-values-3/vh-zero-support.html to css-values-3/vh-zero-support.html Importing css-values-3/vh_not_refreshing_on_chrome.html to css-values-3/vh_not_refreshing_on_chrome.html -Importing css-values-3/reference/vh_not_refreshing_on_chrome-ref.html to css-values-3/vh_not_refreshing_on_chrome-ref.html +Importing css-values-3/reference/vh_not_refreshing_on_chrome-ref.html to css-values-3/reference/vh_not_refreshing_on_chrome-ref.html Importing css-values-3/vh_not_refreshing_on_chrome_iframe.html to css-values-3/vh_not_refreshing_on_chrome_iframe.html Importing selectors-4/focus-within-001.html to selectors-4/focus-within-001.html Importing selectors-4/focus-within-001-ref.html to selectors-4/focus-within-001-ref.html diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/reference/ref-filled-green-100px-square.xht firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/reference/ref-filled-green-100px-square.xht --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/reference/ref-filled-green-100px-square.xht 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/reference/ref-filled-green-100px-square.xht 2016-11-14 01:10:22.000000000 +0000 @@ -0,0 +1,19 @@ + + + + CSS Reftest Reference + + + + +

Test passes if there is a filled green square and no red.

+
+ + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/reftest.list firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/reftest.list --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/received/reftest.list 2016-11-11 01:22:37.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/received/reftest.list 2016-11-14 01:10:22.000000000 +0000 @@ -1,7 +1,7 @@ # THIS FILE IS AUTOGENERATED BY import-tests.py # DO NOT EDIT! -== css-conditional-3/at-media-whitespace-optional-001.html css-conditional-3/background-lime.html -== css-conditional-3/at-media-whitespace-optional-002.html css-conditional-3/background-lime.html +== css-conditional-3/at-media-whitespace-optional-001.html css-conditional-3/reference/background-lime.html +== css-conditional-3/at-media-whitespace-optional-002.html css-conditional-3/reference/background-lime.html == css-conditional-3/at-supports-001.html css-conditional-3/at-supports-001-ref.html == css-conditional-3/at-supports-002.html css-conditional-3/at-supports-001-ref.html == css-conditional-3/at-supports-003.html css-conditional-3/at-supports-001-ref.html @@ -41,10 +41,10 @@ == css-conditional-3/at-supports-037.html css-conditional-3/at-supports-001-ref.html == css-conditional-3/at-supports-038.html css-conditional-3/at-supports-001-ref.html == css-conditional-3/at-supports-039.html css-conditional-3/at-supports-001-ref.html -HTTP(../../..) == css-multicol-1/multicol-basic-001.html css-multicol-1/multicol-basic-ref.html -HTTP(../../..) == css-multicol-1/multicol-basic-002.html css-multicol-1/multicol-basic-ref.html -HTTP(../../..) == css-multicol-1/multicol-basic-003.html css-multicol-1/multicol-basic-ref.html -HTTP(../../..) == css-multicol-1/multicol-basic-004.html css-multicol-1/multicol-basic-ref.html +HTTP(../../..) == css-multicol-1/multicol-basic-001.html css-multicol-1/reference/multicol-basic-ref.html +HTTP(../../..) == css-multicol-1/multicol-basic-002.html css-multicol-1/reference/multicol-basic-ref.html +HTTP(../../..) == css-multicol-1/multicol-basic-003.html css-multicol-1/reference/multicol-basic-ref.html +HTTP(../../..) == css-multicol-1/multicol-basic-004.html css-multicol-1/reference/multicol-basic-ref.html fails HTTP(../../..) == css-multicol-1/multicol-block-clip-001.xht css-multicol-1/multicol-block-clip-001-ref.xht fails HTTP(../../..) == css-multicol-1/multicol-block-clip-002.xht css-multicol-1/multicol-block-clip-002-ref.xht fails == css-multicol-1/multicol-br-inside-avoidcolumn-001.xht css-multicol-1/multicol-br-inside-avoidcolumn-ref.xht @@ -103,8 +103,8 @@ fails HTTP(../../..) == css-multicol-1/multicol-inherit-003.xht css-multicol-1/multicol-inherit-3-ref.xht fails HTTP(../../..) == css-multicol-1/multicol-inherit-004.xht css-multicol-1/multicol-inherit-4-ref.xht fuzzy(96,264) HTTP(../../..) == css-multicol-1/multicol-list-item-001.xht css-multicol-1/multicol-list-item-001-ref.xht -fuzzy(73,1200) HTTP(../../..) == css-multicol-1/multicol-margin-001.xht css-multicol-1/ref-filled-green-100px-square.xht -fuzzy(73,1200) HTTP(../../..) == css-multicol-1/multicol-margin-002.xht css-multicol-1/ref-filled-green-100px-square.xht +fuzzy(73,1200) HTTP(../../..) == css-multicol-1/multicol-margin-001.xht reference/ref-filled-green-100px-square.xht +fuzzy(73,1200) HTTP(../../..) == css-multicol-1/multicol-margin-002.xht reference/ref-filled-green-100px-square.xht fuzzy(243,3322) fuzzy-if(skiaContent,244,3322) HTTP(../../..) == css-multicol-1/multicol-margin-child-001.xht css-multicol-1/multicol-margin-child-001-ref.xht fuzzy(255,4008) HTTP(../../..) == css-multicol-1/multicol-nested-002.xht css-multicol-1/multicol-nested-002-ref.xht fuzzy(255,4109) HTTP(../../..) == css-multicol-1/multicol-nested-005.xht css-multicol-1/multicol-nested-005-ref.xht @@ -181,65 +181,65 @@ fails HTTP(../../..) == css-multicol-1/multicol-width-negative-001.xht css-multicol-1/multicol-count-002-ref.xht fails HTTP(../../..) == css-multicol-1/multicol-width-small-001.xht css-multicol-1/multicol-width-small-001-ref.xht fails == css-multicol-1/multicol-zero-height-001.xht css-multicol-1/multicol-zero-height-001-ref.xht -== css-namespaces-3/prefix-001.xml css-namespaces-3/ref-lime-1.xml -== css-namespaces-3/prefix-002.xml css-namespaces-3/ref-lime-1.xml -== css-namespaces-3/prefix-003.xml css-namespaces-3/ref-lime-1-generic.xml -== css-namespaces-3/prefix-004.xml css-namespaces-3/ref-lime-2-generic.xml -== css-namespaces-3/prefix-005.xml css-namespaces-3/ref-lime-2-generic.xml -== css-namespaces-3/prefix-006.xml css-namespaces-3/ref-lime-2.xml -== css-namespaces-3/scope-001.xml css-namespaces-3/ref-lime-1.xml -== css-namespaces-3/scope-002.xml css-namespaces-3/ref-lime-1.xml -== css-namespaces-3/syntax-001.xml css-namespaces-3/ref-lime-1-block.xml -== css-namespaces-3/syntax-002.xml css-namespaces-3/ref-lime-1-block.xml -== css-namespaces-3/syntax-003.xml css-namespaces-3/ref-lime-5.xml -== css-namespaces-3/syntax-004.xml css-namespaces-3/ref-lime-1.xml -== css-namespaces-3/syntax-005.xml css-namespaces-3/ref-lime-5.xml -== css-namespaces-3/syntax-006.xml css-namespaces-3/ref-lime-1.xml -== css-namespaces-3/syntax-007.xml css-namespaces-3/ref-lime-1.xml -== css-namespaces-3/syntax-008.xml css-namespaces-3/ref-lime-2.xml -== css-namespaces-3/syntax-009.xml css-namespaces-3/ref-lime-1.xml -== css-namespaces-3/syntax-010.xml css-namespaces-3/ref-lime-3.xml -== css-namespaces-3/syntax-011.xml css-namespaces-3/ref-lime-6.xml -== css-namespaces-3/syntax-012.xml css-namespaces-3/ref-lime-3.xml -== css-namespaces-3/syntax-013.xml css-namespaces-3/ref-lime-5.xml -== css-namespaces-3/syntax-014.xml css-namespaces-3/ref-lime-3.xml -== css-namespaces-3/syntax-015.xml css-namespaces-3/ref-lime-1.xml -fails == css-values-3/attr-color-invalid-cast.html css-values-3/200-200-green.html -== css-values-3/attr-color-invalid-fallback.html css-values-3/200-200-green.html -fails == css-values-3/attr-color-valid.html css-values-3/200-200-green.html -== css-values-3/attr-invalid-type-001.html css-values-3/200-200-green.html -== css-values-3/attr-invalid-type-002.html css-values-3/200-200-green.html -== css-values-3/attr-invalid-type-003.html css-values-3/200-200-green.html -fails == css-values-3/attr-length-invalid-cast.html css-values-3/200-200-green.html -== css-values-3/attr-length-invalid-fallback.html css-values-3/200-200-green.html -fails == css-values-3/attr-length-valid-zero-nofallback.html css-values-3/200-200-green.html -fails == css-values-3/attr-length-valid-zero.html css-values-3/200-200-green.html -fails == css-values-3/attr-length-valid.html css-values-3/200-200-green.html -fails == css-values-3/attr-px-invalid-cast.html css-values-3/200-200-green.html -== css-values-3/attr-px-invalid-fallback.html css-values-3/200-200-green.html -fails == css-values-3/attr-px-valid.html css-values-3/200-200-green.html -== css-values-3/calc-in-calc.html css-values-3/all-green.html -fails == css-values-3/calc-in-media-queries-001.html css-values-3/all-green.html -fails == css-values-3/calc-in-media-queries-002.html css-values-3/all-green.html -== css-values-3/calc-invalid-range-clamping.html css-values-3/200-200-green.html -== css-values-3/calc-parenthesis-stack.html css-values-3/all-green.html -fuzzy-if(OSX,40,6) == css-values-3/ch-unit-001.html css-values-3/ch-unit-001-ref.html -== css-values-3/initial-background-color.html css-values-3/all-green.html -== css-values-3/vh-calc-support-pct.html css-values-3/all-green.html -== css-values-3/vh-calc-support.html css-values-3/all-green.html -== css-values-3/vh-em-inherit.html css-values-3/all-green.html -== css-values-3/vh-inherit.html css-values-3/all-green.html -== css-values-3/vh-interpolate-pct.html css-values-3/all-green.html -== css-values-3/vh-interpolate-px.html css-values-3/all-green.html -== css-values-3/vh-interpolate-vh.html css-values-3/all-green.html -== css-values-3/vh-support-atviewport.html css-values-3/all-green.html -== css-values-3/vh-support-margin.html css-values-3/all-green.html -skip == css-values-3/vh-support-transform-origin.html css-values-3/all-green.html -skip == css-values-3/vh-support-transform-translate.html css-values-3/all-green.html -== css-values-3/vh-support.html css-values-3/all-green.html -== css-values-3/vh-zero-support.html css-values-3/all-green.html -skip == css-values-3/vh_not_refreshing_on_chrome.html css-values-3/vh_not_refreshing_on_chrome-ref.html -skip == css-values-3/vh_not_refreshing_on_chrome_iframe.html css-values-3/vh_not_refreshing_on_chrome-ref.html +== css-namespaces-3/prefix-001.xml css-namespaces-3/reftest/ref-lime-1.xml +== css-namespaces-3/prefix-002.xml css-namespaces-3/reftest/ref-lime-1.xml +== css-namespaces-3/prefix-003.xml css-namespaces-3/reftest/ref-lime-1-generic.xml +== css-namespaces-3/prefix-004.xml css-namespaces-3/reftest/ref-lime-2-generic.xml +== css-namespaces-3/prefix-005.xml css-namespaces-3/reftest/ref-lime-2-generic.xml +== css-namespaces-3/prefix-006.xml css-namespaces-3/reftest/ref-lime-2.xml +== css-namespaces-3/scope-001.xml css-namespaces-3/reftest/ref-lime-1.xml +== css-namespaces-3/scope-002.xml css-namespaces-3/reftest/ref-lime-1.xml +== css-namespaces-3/syntax-001.xml css-namespaces-3/reftest/ref-lime-1-block.xml +== css-namespaces-3/syntax-002.xml css-namespaces-3/reftest/ref-lime-1-block.xml +== css-namespaces-3/syntax-003.xml css-namespaces-3/reftest/ref-lime-5.xml +== css-namespaces-3/syntax-004.xml css-namespaces-3/reftest/ref-lime-1.xml +== css-namespaces-3/syntax-005.xml css-namespaces-3/reftest/ref-lime-5.xml +== css-namespaces-3/syntax-006.xml css-namespaces-3/reftest/ref-lime-1.xml +== css-namespaces-3/syntax-007.xml css-namespaces-3/reftest/ref-lime-1.xml +== css-namespaces-3/syntax-008.xml css-namespaces-3/reftest/ref-lime-2.xml +== css-namespaces-3/syntax-009.xml css-namespaces-3/reftest/ref-lime-1.xml +== css-namespaces-3/syntax-010.xml css-namespaces-3/reftest/ref-lime-3.xml +== css-namespaces-3/syntax-011.xml css-namespaces-3/reftest/ref-lime-6.xml +== css-namespaces-3/syntax-012.xml css-namespaces-3/reftest/ref-lime-3.xml +== css-namespaces-3/syntax-013.xml css-namespaces-3/reftest/ref-lime-5.xml +== css-namespaces-3/syntax-014.xml css-namespaces-3/reftest/ref-lime-3.xml +== css-namespaces-3/syntax-015.xml css-namespaces-3/reftest/ref-lime-1.xml +fails == css-values-3/attr-color-invalid-cast.html css-values-3/reference/200-200-green.html +== css-values-3/attr-color-invalid-fallback.html css-values-3/reference/200-200-green.html +fails == css-values-3/attr-color-valid.html css-values-3/reference/200-200-green.html +== css-values-3/attr-invalid-type-001.html css-values-3/reference/200-200-green.html +== css-values-3/attr-invalid-type-002.html css-values-3/reference/200-200-green.html +== css-values-3/attr-invalid-type-003.html css-values-3/reference/200-200-green.html +fails == css-values-3/attr-length-invalid-cast.html css-values-3/reference/200-200-green.html +== css-values-3/attr-length-invalid-fallback.html css-values-3/reference/200-200-green.html +fails == css-values-3/attr-length-valid-zero-nofallback.html css-values-3/reference/200-200-green.html +fails == css-values-3/attr-length-valid-zero.html css-values-3/reference/200-200-green.html +fails == css-values-3/attr-length-valid.html css-values-3/reference/200-200-green.html +fails == css-values-3/attr-px-invalid-cast.html css-values-3/reference/200-200-green.html +== css-values-3/attr-px-invalid-fallback.html css-values-3/reference/200-200-green.html +fails == css-values-3/attr-px-valid.html css-values-3/reference/200-200-green.html +== css-values-3/calc-in-calc.html css-values-3/reference/all-green.html +fails == css-values-3/calc-in-media-queries-001.html css-values-3/reference/all-green.html +fails == css-values-3/calc-in-media-queries-002.html css-values-3/reference/all-green.html +== css-values-3/calc-invalid-range-clamping.html css-values-3/reference/200-200-green.html +== css-values-3/calc-parenthesis-stack.html css-values-3/reference/all-green.html +fuzzy-if(OSX,40,6) == css-values-3/ch-unit-001.html css-values-3/reference/ch-unit-001-ref.html +== css-values-3/initial-background-color.html css-values-3/reference/all-green.html +== css-values-3/vh-calc-support-pct.html css-values-3/reference/all-green.html +== css-values-3/vh-calc-support.html css-values-3/reference/all-green.html +== css-values-3/vh-em-inherit.html css-values-3/reference/all-green.html +== css-values-3/vh-inherit.html css-values-3/reference/all-green.html +== css-values-3/vh-interpolate-pct.html css-values-3/reference/all-green.html +== css-values-3/vh-interpolate-px.html css-values-3/reference/all-green.html +== css-values-3/vh-interpolate-vh.html css-values-3/reference/all-green.html +== css-values-3/vh-support-atviewport.html css-values-3/reference/all-green.html +== css-values-3/vh-support-margin.html css-values-3/reference/all-green.html +skip == css-values-3/vh-support-transform-origin.html css-values-3/reference/all-green.html +skip == css-values-3/vh-support-transform-translate.html css-values-3/reference/all-green.html +== css-values-3/vh-support.html css-values-3/reference/all-green.html +== css-values-3/vh-zero-support.html css-values-3/reference/all-green.html +skip == css-values-3/vh_not_refreshing_on_chrome.html css-values-3/reference/vh_not_refreshing_on_chrome-ref.html +skip == css-values-3/vh_not_refreshing_on_chrome_iframe.html css-values-3/reference/vh_not_refreshing_on_chrome-ref.html needs-focus == selectors-4/focus-within-001.html selectors-4/focus-within-001-ref.html needs-focus == selectors-4/focus-within-002.html selectors-4/focus-within-001-ref.html needs-focus == selectors-4/focus-within-003.html selectors-4/focus-within-001-ref.html diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/submitted/align3/grid-abspos-staticpos-align-self-001.html firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/submitted/align3/grid-abspos-staticpos-align-self-001.html --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/submitted/align3/grid-abspos-staticpos-align-self-001.html 2016-11-11 01:22:38.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/submitted/align3/grid-abspos-staticpos-align-self-001.html 2016-11-14 01:10:37.000000000 +0000 @@ -9,7 +9,7 @@ CSS Test: Static position of abspos children in a grid container, with various "align-self" values - + + + +
+ + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/submitted/background/border-image-repeat-1-ref.html firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/submitted/background/border-image-repeat-1-ref.html --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/submitted/background/border-image-repeat-1-ref.html 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/submitted/background/border-image-repeat-1-ref.html 2016-11-14 01:10:37.000000000 +0000 @@ -0,0 +1,20 @@ + + + + + CSS Border Image: border-image-repeat with SVG content + + + + + + + + + + + + + + + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/submitted/background/reftest.list firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/submitted/background/reftest.list --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/submitted/background/reftest.list 2016-11-11 01:22:39.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/submitted/background/reftest.list 2016-11-14 01:10:38.000000000 +0000 @@ -32,3 +32,4 @@ == border-image-repeat-space-5-ref-1.html border-image-repeat-space-5-ref-2.html == border-image-repeat-space-6.html border-image-repeat-space-6-ref.html == border-image-repeat-space-7.html border-image-repeat-space-7-ref.html +== border-image-repeat-1.html border-image-repeat-1-ref.html diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/submitted/ui3/reftest.list firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/submitted/ui3/reftest.list --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/submitted/ui3/reftest.list 2016-11-11 01:26:02.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/submitted/ui3/reftest.list 2016-11-14 01:11:49.000000000 +0000 @@ -7,4 +7,4 @@ == box-sizing-content-box-003.xht box-sizing-content-box-003-ref.xht random-if(Android) fuzzy-if(skiaContent,15,50) == box-sizing-replaced-001.xht box-sizing-replaced-001-ref.xht #bug 982547 fuzzy-if(Android,27,874) fuzzy-if(gtkWidget,14,29) == box-sizing-replaced-002.xht box-sizing-replaced-002-ref.xht # Bug 1128229, Bug 1313772 -fuzzy-if(Android,27,925) == box-sizing-replaced-003.xht box-sizing-replaced-003-ref.xht # Bug 1128229 +fuzzy-if(Android,27,925) fuzzy-if(gtkWidget,14,43) == box-sizing-replaced-003.xht box-sizing-replaced-003-ref.xht # Bug 1128229 diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/submitted/writing-modes-3/logical-physical-mapping-001.html firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/submitted/writing-modes-3/logical-physical-mapping-001.html --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/submitted/writing-modes-3/logical-physical-mapping-001.html 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/submitted/writing-modes-3/logical-physical-mapping-001.html 2016-11-14 01:11:50.000000000 +0000 @@ -0,0 +1,96 @@ + + + + + + + + + + +

+ Test passes if orange dots are opposite to the blue dots in each cell. Orange dots should be on the (physical) side specified by the text in the cell. +

+ + + + + + + + + + + +
writing modehorizontal-tbvertical-rlvertical-lrsideways-lr
directionltrrtlltrrtlltrrtlltrrtl
block-start
top
top
right
right
left
left
left
left
block-end
bottom
bottom
left
left
right
right
right
right
inline-start
left
right
top
bottom
top
bottom
bottom
top
inline-end
right
left
bottom
top
bottom
top
top
bottom
+ + + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/submitted/writing-modes-3/logical-physical-mapping-001-ref.html firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/submitted/writing-modes-3/logical-physical-mapping-001-ref.html --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/submitted/writing-modes-3/logical-physical-mapping-001-ref.html 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/submitted/writing-modes-3/logical-physical-mapping-001-ref.html 2016-11-14 01:11:50.000000000 +0000 @@ -0,0 +1,85 @@ + + + + + + + + +

+ Test passes if orange dots are opposite to the blue dots in each cell. Orange dots should be on the (physical) side specified by the text in the cell. +

+ + + + + + + + + + + +
writing modehorizontal-tbvertical-rlvertical-lrsideways-lr
directionltrrtlltrrtlltrrtlltrrtl
block-start
top
top
right
right
left
left
left
left
block-end
bottom
bottom
left
left
right
right
right
right
inline-start
left
right
top
bottom
top
bottom
bottom
top
inline-end
right
left
bottom
top
bottom
top
top
bottom
+ + + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/submitted/writing-modes-3/reftest.list firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/submitted/writing-modes-3/reftest.list --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/submitted/writing-modes-3/reftest.list 2016-11-11 01:26:05.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/submitted/writing-modes-3/reftest.list 2016-11-14 01:11:50.000000000 +0000 @@ -13,3 +13,5 @@ == text-combine-upright-compression-007.html text-combine-upright-compression-007-ref.html == text-orientation-upright-directionality-001.html text-orientation-upright-directionality-001-ref.html + +== logical-physical-mapping-001.html logical-physical-mapping-001-ref.html diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/submitted/writing-modes-3/reftest-stylo.list firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/submitted/writing-modes-3/reftest-stylo.list --- firefox-trunk-52.0~a1~hg20161110r321971/layout/reftests/w3c-css/submitted/writing-modes-3/reftest-stylo.list 2016-11-11 01:26:05.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/reftests/w3c-css/submitted/writing-modes-3/reftest-stylo.list 2016-11-14 01:11:50.000000000 +0000 @@ -14,3 +14,5 @@ == text-combine-upright-compression-007.html text-combine-upright-compression-007.html == text-orientation-upright-directionality-001.html text-orientation-upright-directionality-001.html + +== logical-physical-mapping-001.html logical-physical-mapping-001.html diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/style/nsCSSPropList.h firefox-trunk-52.0~a1~hg20161113r322177/layout/style/nsCSSPropList.h --- firefox-trunk-52.0~a1~hg20161110r321971/layout/style/nsCSSPropList.h 2016-11-11 01:28:29.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/style/nsCSSPropList.h 2016-11-14 01:15:57.000000000 +0000 @@ -469,7 +469,7 @@ VARIANT_HK, kAppearanceKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_DISPLAY( backface-visibility, backface_visibility, @@ -479,7 +479,7 @@ VARIANT_HK, kBackfaceVisibilityKTable, offsetof(nsStyleDisplay, mBackfaceVisibility), - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SHORTHAND( background, background, @@ -498,7 +498,7 @@ VARIANT_KEYWORD, // used by list parsing kImageLayerAttachmentKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_BACKGROUND( background-blend-mode, background_blend_mode, @@ -511,7 +511,7 @@ VARIANT_KEYWORD, // used by list parsing kBlendModeKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_BACKGROUND( background-clip, background_clip, @@ -524,7 +524,7 @@ VARIANT_KEYWORD, // used by list parsing kBackgroundClipKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_BACKGROUND( background-color, background_color, @@ -553,7 +553,7 @@ VARIANT_IMAGE, // used by list parsing nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_BACKGROUND( background-origin, background_origin, @@ -566,7 +566,7 @@ VARIANT_KEYWORD, // used by list parsing kImageLayerOriginKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SHORTHAND( background-position, background_position, @@ -614,7 +614,7 @@ VARIANT_KEYWORD, // used by list parsing kImageLayerRepeatKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_BACKGROUND( background-size, background_size, @@ -803,7 +803,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_BORDER( border-bottom-left-radius, border_bottom_left_radius, @@ -840,7 +840,7 @@ VARIANT_HK, kBorderStyleKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) // on/off will need reflow + eStyleAnimType_Discrete) // on/off will need reflow CSS_PROP_BORDER( border-bottom-width, border_bottom_width, @@ -864,7 +864,7 @@ VARIANT_HK, kBorderCollapseKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SHORTHAND( border-color, border_color, @@ -888,7 +888,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_BORDER( border-image-repeat, border_image_repeat, @@ -899,7 +899,7 @@ 0, kBorderImageRepeatKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_BORDER( border-image-slice, border_image_slice, @@ -910,7 +910,7 @@ 0, kBorderImageSliceKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_BORDER( border-image-source, border_image_source, @@ -922,7 +922,7 @@ VARIANT_IMAGE | VARIANT_INHERIT, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_BORDER( border-image-width, border_image_width, @@ -933,7 +933,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SHORTHAND( border-inline-end, border_inline_end, @@ -1067,7 +1067,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_BORDER( border-left-style, border_left_style, @@ -1078,7 +1078,7 @@ VARIANT_HK, kBorderStyleKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_BORDER( border-left-width, border_left_width, @@ -1129,7 +1129,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_BORDER( border-right-style, border_right_style, @@ -1140,7 +1140,7 @@ VARIANT_HK, kBorderStyleKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_BORDER( border-right-width, border_right_width, @@ -1203,7 +1203,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_BORDER( border-top-left-radius, border_top_left_radius, @@ -1240,7 +1240,7 @@ VARIANT_HK, kBorderStyleKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) // on/off will need reflow + eStyleAnimType_Discrete) // on/off will need reflow CSS_PROP_BORDER( border-top-width, border_top_width, @@ -1284,7 +1284,7 @@ VARIANT_HK, kBoxAlignKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) // XXX bug 3935 + eStyleAnimType_Discrete) // XXX bug 3935 CSS_PROP_BORDER( box-decoration-break, box_decoration_break, @@ -1294,7 +1294,7 @@ VARIANT_HK, kBoxDecorationBreakKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_XUL( -moz-box-direction, box_direction, @@ -1304,7 +1304,7 @@ VARIANT_HK, kBoxDirectionKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) // XXX bug 3935 + eStyleAnimType_Discrete) // XXX bug 3935 CSS_PROP_XUL( -moz-box-flex, box_flex, @@ -1326,7 +1326,7 @@ VARIANT_HI, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_XUL( -moz-box-orient, box_orient, @@ -1336,7 +1336,7 @@ VARIANT_HK, kBoxOrientKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) // XXX bug 3935 + eStyleAnimType_Discrete) // XXX bug 3935 CSS_PROP_XUL( -moz-box-pack, box_pack, @@ -1346,7 +1346,7 @@ VARIANT_HK, kBoxPackKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) // XXX bug 3935 + eStyleAnimType_Discrete) // XXX bug 3935 CSS_PROP_EFFECTS( box-shadow, box_shadow, @@ -1370,7 +1370,7 @@ VARIANT_HK, kBoxSizingKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_TABLEBORDER( caption-side, caption_side, @@ -1380,7 +1380,7 @@ VARIANT_HK, kCaptionSideKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_DISPLAY( clear, clear, @@ -1390,7 +1390,7 @@ VARIANT_HK, kClearKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_EFFECTS( clip, clip, @@ -1448,7 +1448,7 @@ VARIANT_HK, kColorAdjustKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SVG( color-interpolation, color_interpolation, @@ -1491,7 +1491,7 @@ VARIANT_HK, kColumnFillKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_COLUMN( column-gap, column_gap, @@ -1529,7 +1529,7 @@ VARIANT_HK, kBorderStyleKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_COLUMN( column-rule-width, column_rule_width, @@ -1570,7 +1570,7 @@ VARIANT_HK | VARIANT_NONE, kContainKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_CONTENT( content, content, @@ -1581,7 +1581,7 @@ 0, kContentKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) #ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL CSS_PROP_TEXT( -moz-control-character-visibility, @@ -1604,7 +1604,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) // XXX bug 137285 + eStyleAnimType_Discrete) // XXX bug 137285 CSS_PROP_CONTENT( counter-reset, counter_reset, @@ -1614,7 +1614,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) // XXX bug 137285 + eStyleAnimType_Discrete) // XXX bug 137285 CSS_PROP_USERINTERFACE( cursor, cursor, @@ -1627,7 +1627,7 @@ 0, kCursorKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) #ifndef CSS_PROP_LIST_ONLY_COMPONENTS_OF_ALL_SHORTHAND CSS_PROP_VISIBILITY( direction, @@ -1638,7 +1638,7 @@ VARIANT_HK, kDirectionKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) #endif // !defined(CSS_PROP_LIST_ONLY_COMPONENTS_OF_ALL_SHORTHAND) CSS_PROP_DISPLAY( display, @@ -1673,7 +1673,7 @@ VARIANT_HK, kEmptyCellsKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SVG( fill, fill, @@ -1801,7 +1801,7 @@ VARIANT_HK, kFloatKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_BORDER( -moz-float-edge, float_edge, @@ -1811,7 +1811,7 @@ VARIANT_HK, kFloatEdgeKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) // XXX bug 3935 + eStyleAnimType_Discrete) // XXX bug 3935 CSS_PROP_SVGRESET( flood-color, flood_color, @@ -1850,7 +1850,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_FONT( font-feature-settings, font_feature_settings, @@ -1863,7 +1863,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_FONT( font-kerning, font_kerning, @@ -1875,7 +1875,7 @@ VARIANT_HK, kFontKerningKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_FONT( font-language-override, font_language_override, @@ -1887,7 +1887,7 @@ VARIANT_NORMAL | VARIANT_INHERIT | VARIANT_STRING, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_FONT( font-size, font_size, @@ -1953,7 +1953,7 @@ 0, kFontSynthesisKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SHORTHAND( font-variant, font_variant, @@ -1972,7 +1972,7 @@ 0, kFontVariantAlternatesKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_FONT( font-variant-caps, font_variant_caps, @@ -1984,7 +1984,7 @@ VARIANT_HMK, kFontVariantCapsKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_FONT( font-variant-east-asian, font_variant_east_asian, @@ -1997,7 +1997,7 @@ 0, kFontVariantEastAsianKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_FONT( font-variant-ligatures, font_variant_ligatures, @@ -2010,7 +2010,7 @@ 0, kFontVariantLigaturesKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_FONT( font-variant-numeric, font_variant_numeric, @@ -2023,7 +2023,7 @@ 0, kFontVariantNumericKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_FONT( font-variant-position, font_variant_position, @@ -2035,7 +2035,7 @@ VARIANT_HMK, kFontVariantPositionKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_FONT( font-weight, font_weight, @@ -2060,7 +2060,7 @@ VARIANT_HI, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) // bug 58646 + eStyleAnimType_Discrete) // bug 58646 CSS_PROP_SHORTHAND( grid, grid, @@ -2084,7 +2084,7 @@ 0, kGridTrackBreadthKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_POSITION( grid-auto-flow, grid_auto_flow, @@ -2095,7 +2095,7 @@ 0, kGridAutoFlowKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_POSITION( grid-auto-rows, grid_auto_rows, @@ -2107,7 +2107,7 @@ 0, kGridTrackBreadthKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SHORTHAND( grid-column, grid_column, @@ -2123,7 +2123,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_POSITION( grid-column-gap, grid_column_gap, @@ -2145,7 +2145,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SHORTHAND( grid-gap, grid_gap, @@ -2167,7 +2167,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_POSITION( grid-row-gap, grid_row_gap, @@ -2189,7 +2189,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SHORTHAND( grid-template, grid_template, @@ -2206,7 +2206,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_POSITION( grid-template-columns, grid_template_columns, @@ -2219,7 +2219,7 @@ 0, kGridTrackBreadthKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_POSITION( grid-template-rows, grid_template_rows, @@ -2232,7 +2232,7 @@ 0, kGridTrackBreadthKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_POSITION( height, height, @@ -2256,7 +2256,7 @@ VARIANT_HK, kHyphensKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_TEXTRESET( initial-letter, initial_letter, @@ -2267,7 +2267,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_VISIBILITY( image-orientation, image_orientation, @@ -2278,7 +2278,7 @@ 0, kImageOrientationKTable, offsetof(nsStyleVisibility, mImageOrientation), - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_LIST( -moz-image-region, image_region, @@ -2308,7 +2308,7 @@ VARIANT_HK, kIMEModeKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_LOGICAL( inline-size, inline_size, @@ -2336,7 +2336,7 @@ VARIANT_HK, kIsolationKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_POSITION( justify-content, justify_content, @@ -2449,7 +2449,7 @@ VARIANT_HUO, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_LIST( list-style-position, list_style_position, @@ -2459,7 +2459,7 @@ VARIANT_HK, kListStylePositionKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_LIST( list-style-type, list_style_type, @@ -2470,7 +2470,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SHORTHAND( margin, margin, @@ -2624,7 +2624,7 @@ VARIANT_HUO, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SVG( marker-mid, marker_mid, @@ -2634,7 +2634,7 @@ VARIANT_HUO, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SVG( marker-start, marker_start, @@ -2644,7 +2644,7 @@ VARIANT_HUO, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) #ifndef MOZ_ENABLE_MASK_AS_SHORTHAND CSS_PROP_SVGRESET( mask, @@ -2656,7 +2656,7 @@ VARIANT_HUO, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) #else CSS_PROP_SHORTHAND( mask, @@ -2674,7 +2674,7 @@ VARIANT_KEYWORD, // used by list parsing kImageLayerOriginKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SVGRESET( mask-composite, mask_composite, @@ -2685,7 +2685,7 @@ VARIANT_KEYWORD, // used by list parsing kImageLayerCompositeKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SVGRESET( mask-image, mask_image, @@ -2698,7 +2698,7 @@ VARIANT_IMAGE, // used by list parsing nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SVGRESET( mask-mode, mask_mode, @@ -2709,7 +2709,7 @@ VARIANT_KEYWORD, // used by list parsing kImageLayerModeKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SVGRESET( mask-origin, mask_origin, @@ -2720,7 +2720,7 @@ VARIANT_KEYWORD, // used by list parsing kImageLayerOriginKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SHORTHAND( mask-position, mask_position, @@ -2762,7 +2762,7 @@ VARIANT_KEYWORD, // used by list parsing kImageLayerRepeatKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SVGRESET( mask-size, mask_size, @@ -2960,7 +2960,7 @@ VARIANT_HK, kBlendModeKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_POSITION( object-fit, object_fit, @@ -2971,7 +2971,7 @@ VARIANT_HK, kObjectFitKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_POSITION( object-position, object_position, @@ -3080,7 +3080,7 @@ VARIANT_HK, kOrientKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_FONT( -moz-osx-font-smoothing, osx_font_smoothing, @@ -3092,7 +3092,7 @@ VARIANT_HK, kFontSmoothingKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SHORTHAND( outline, outline, @@ -3183,7 +3183,7 @@ VARIANT_HK, kOutlineStyleKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_OUTLINE( outline-width, outline_width, @@ -3212,7 +3212,7 @@ VARIANT_HK, kOverflowClipBoxKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_DISPLAY( overflow-x, overflow_x, @@ -3224,7 +3224,7 @@ VARIANT_HK, kOverflowSubKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_DISPLAY( overflow-y, overflow_y, @@ -3236,7 +3236,7 @@ VARIANT_HK, kOverflowSubKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SHORTHAND( padding, padding, @@ -3401,7 +3401,7 @@ VARIANT_HK, kPageBreakKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) // temp fix for bug 24000 + eStyleAnimType_Discrete) // temp fix for bug 24000 CSS_PROP_DISPLAY( page-break-before, page_break_before, @@ -3411,7 +3411,7 @@ VARIANT_HK, kPageBreakKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) // temp fix for bug 24000 + eStyleAnimType_Discrete) // temp fix for bug 24000 CSS_PROP_DISPLAY( page-break-inside, page_break_inside, @@ -3421,7 +3421,7 @@ VARIANT_HK, kPageBreakInsideKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SVG( paint-order, paint_order, @@ -3431,7 +3431,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_DISPLAY( perspective, perspective, @@ -3480,7 +3480,7 @@ VARIANT_HK, kPositionKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_LIST( quotes, quotes, @@ -3490,7 +3490,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_DISPLAY( resize, resize, @@ -3504,7 +3504,7 @@ VARIANT_HK, kResizeKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_POSITION( right, right, @@ -3591,7 +3591,7 @@ VARIANT_HK, kScrollBehaviorKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_DISPLAY( scroll-snap-coordinate, scroll_snap_coordinate, @@ -3604,7 +3604,7 @@ 0, kImageLayerPositionKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_DISPLAY( scroll-snap-destination, scroll_snap_destination, @@ -3616,7 +3616,7 @@ 0, kImageLayerPositionKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_DISPLAY( scroll-snap-points-x, scroll_snap_points_x, @@ -3628,7 +3628,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_DISPLAY( scroll-snap-points-y, scroll_snap_points_y, @@ -3640,7 +3640,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SHORTHAND( scroll-snap-type, scroll_snap_type, @@ -3656,7 +3656,7 @@ VARIANT_HK, kScrollSnapTypeKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_DISPLAY( scroll-snap-type-y, scroll_snap_type_y, @@ -3666,7 +3666,7 @@ VARIANT_HK, kScrollSnapTypeKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_DISPLAY( shape-outside, shape_outside, @@ -3678,7 +3678,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) // FIXME: Bug 1289049 for adding animation support + eStyleAnimType_Discrete) // FIXME: Bug 1289049 for adding animation support CSS_PROP_SVG( shape-rendering, shape_rendering, @@ -3713,7 +3713,7 @@ VARIANT_HK, kStackSizingKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SVGRESET( stop-color, stop_color, @@ -3846,7 +3846,7 @@ VARIANT_HI, nullptr, offsetof(nsStyleText, mTabSize), - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_TABLE( table-layout, table_layout, @@ -3856,7 +3856,7 @@ VARIANT_HK, kTableLayoutKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_TEXT( text-align, text_align, @@ -3869,7 +3869,7 @@ VARIANT_HK /* | VARIANT_STRING */, kTextAlignKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_TEXT( text-align-last, text_align_last, @@ -3879,7 +3879,7 @@ VARIANT_HK, kTextAlignLastKTable, offsetof(nsStyleText, mTextAlignLast), - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SVG( text-anchor, text_anchor, @@ -3944,7 +3944,7 @@ VARIANT_HK, kTextDecorationStyleKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SHORTHAND( text-emphasis, text_emphasis, @@ -3972,7 +3972,7 @@ 0, kTextEmphasisPositionKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_TEXT( text-emphasis-style, text_emphasis_style, @@ -3983,7 +3983,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_TEXT( -webkit-text-fill-color, _webkit_text_fill_color, @@ -4030,7 +4030,7 @@ 0, kTextOverflowKTable, offsetof(nsStyleTextReset, mTextOverflow), - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_TEXT( text-rendering, text_rendering, @@ -4065,7 +4065,7 @@ VARIANT_AUTO | VARIANT_NONE | VARIANT_INHERIT, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SHORTHAND( -webkit-text-stroke, _webkit_text_stroke, @@ -4097,7 +4097,7 @@ VARIANT_HKL | VARIANT_CALC, kBorderWidthKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_TEXT( text-transform, text_transform, @@ -4109,7 +4109,7 @@ VARIANT_HK, kTextTransformKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) #ifndef CSS_PROP_LIST_ONLY_COMPONENTS_OF_ALL_SHORTHAND #ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL CSS_PROP_FONT( @@ -4162,7 +4162,7 @@ VARIANT_HK, kTouchActionKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_DISPLAY( transform, transform, @@ -4195,7 +4195,7 @@ VARIANT_HK, kTransformBoxKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_DISPLAY( transform-origin, transform_origin, @@ -4219,7 +4219,7 @@ VARIANT_HK, kTransformStyleKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_SHORTHAND( transition, transition, @@ -4280,7 +4280,7 @@ VARIANT_HK, kUnicodeBidiKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) #endif // CSS_PROP_LIST_ONLY_COMPONENTS_OF_ALL_SHORTHAND CSS_PROP_USERINTERFACE( -moz-user-focus, @@ -4291,7 +4291,7 @@ VARIANT_HK, kUserFocusKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) // XXX bug 3935 + eStyleAnimType_Discrete) // XXX bug 3935 CSS_PROP_USERINTERFACE( -moz-user-input, user_input, @@ -4301,7 +4301,7 @@ VARIANT_HK, kUserInputKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) // XXX ??? // XXX bug 3935 + eStyleAnimType_Discrete) // XXX ??? // XXX bug 3935 CSS_PROP_USERINTERFACE( -moz-user-modify, user_modify, @@ -4311,7 +4311,7 @@ VARIANT_HK, kUserModifyKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) // XXX bug 3935 + eStyleAnimType_Discrete) // XXX bug 3935 CSS_PROP_UIRESET( -moz-user-select, user_select, @@ -4321,7 +4321,7 @@ VARIANT_HK, kUserSelectKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) // XXX bug 3935 + eStyleAnimType_Discrete) // XXX bug 3935 CSS_PROP_SVGRESET( vector-effect, vector_effect, @@ -4370,7 +4370,7 @@ VARIANT_HK, kWhitespaceKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_POSITION( width, width, @@ -4395,7 +4395,7 @@ 0, nullptr, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_UIRESET( -moz-window-dragging, _moz_window_dragging, @@ -4405,7 +4405,7 @@ VARIANT_HK, kWindowDraggingKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) #ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL CSS_PROP_UIRESET( -moz-window-shadow, @@ -4453,7 +4453,7 @@ VARIANT_HK, kOverflowWrapKTable, CSS_PROP_NO_OFFSET, - eStyleAnimType_None) + eStyleAnimType_Discrete) CSS_PROP_VISIBILITY( writing-mode, writing_mode, diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/style/nsCSSValue.cpp firefox-trunk-52.0~a1~hg20161113r322177/layout/style/nsCSSValue.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/layout/style/nsCSSValue.cpp 2016-11-11 01:28:29.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/style/nsCSSValue.cpp 2016-11-14 01:15:58.000000000 +0000 @@ -494,6 +494,8 @@ SetIntegerColorValue(aValue, eCSSUnit_RGBAColor); } + + void nsCSSValue::SetIntegerColorValue(nscolor aValue, nsCSSUnit aUnit) { Reset(); @@ -502,6 +504,12 @@ mValue.mColor = aValue; } +void nsCSSValue::SetIntegerCoordValue(nscoord aValue) +{ + SetFloatValue(nsPresContext::AppUnitsToFloatCSSPixels(aValue), + eCSSUnit_Pixel); +} + void nsCSSValue::SetFloatColorValue(float aComponent1, float aComponent2, float aComponent3, @@ -809,6 +817,21 @@ mUnit = eCSSUnit_DummyInherit; } +void nsCSSValue::SetCalcValue(const nsStyleCoord::CalcValue* aCalc) +{ + RefPtr arr = nsCSSValue::Array::Create(1); + if (!aCalc->mHasPercent) { + arr->Item(0).SetIntegerCoordValue(aCalc->mLength); + } else { + nsCSSValue::Array *arr2 = nsCSSValue::Array::Create(2); + arr->Item(0).SetArrayValue(arr2, eCSSUnit_Calc_Plus); + arr2->Item(0).SetIntegerCoordValue(aCalc->mLength); + arr2->Item(1).SetPercentValue(aCalc->mPercent); + } + + SetArrayValue(arr, eCSSUnit_Calc); +} + void nsCSSValue::StartImageLoad(nsIDocument* aDocument) const { MOZ_ASSERT(eCSSUnit_URL == mUnit, "Not a URL value!"); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/style/nsCSSValue.h firefox-trunk-52.0~a1~hg20161113r322177/layout/style/nsCSSValue.h --- firefox-trunk-52.0~a1~hg20161110r321971/layout/style/nsCSSValue.h 2016-11-11 01:28:29.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/style/nsCSSValue.h 2016-11-14 01:15:58.000000000 +0000 @@ -30,6 +30,7 @@ #include "nsStringBuffer.h" #include "nsTArray.h" #include "nsStyleConsts.h" +#include "nsStyleCoord.h" #include "gfxFontFamilyList.h" class imgRequestProxy; @@ -910,6 +911,8 @@ void SetStringValue(const nsString& aValue, nsCSSUnit aUnit); void SetColorValue(nscolor aValue); void SetIntegerColorValue(nscolor aValue, nsCSSUnit aUnit); + // converts the nscoord to pixels + void SetIntegerCoordValue(nscoord aCoord); void SetFloatColorValue(float aComponent1, float aComponent2, float aComponent3, @@ -942,6 +945,9 @@ void SetDummyValue(); void SetDummyInheritValue(); + // Converts an nsStyleCoord::CalcValue back into a CSSValue + void SetCalcValue(const nsStyleCoord::CalcValue* aCalc); + // These are a little different - they allocate storage for you and // return a handle. nsCSSRect& SetRectValue(); @@ -1207,7 +1213,7 @@ ~nsCSSValueSharedList(); public: - NS_INLINE_DECL_REFCOUNTING(nsCSSValueSharedList) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsCSSValueSharedList) void AppendToString(nsCSSPropertyID aProperty, nsAString& aResult, nsCSSValue::Serialization aValueSerialization) const; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/style/ServoBindings.cpp firefox-trunk-52.0~a1~hg20161113r322177/layout/style/ServoBindings.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/layout/style/ServoBindings.cpp 2016-11-11 01:27:01.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/style/ServoBindings.cpp 2016-11-14 01:15:35.000000000 +0000 @@ -29,6 +29,7 @@ #include "mozilla/EventStates.h" #include "mozilla/ServoElementSnapshot.h" #include "mozilla/ServoRestyleManager.h" +#include "mozilla/StyleAnimationValue.h" #include "mozilla/DeclarationBlockInlines.h" #include "mozilla/dom/Element.h" @@ -966,6 +967,75 @@ NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsStyleQuoteValues, QuoteValues); +nsCSSValueSharedList* +Gecko_NewCSSValueSharedList(uint32_t aLen) +{ + RefPtr list = new nsCSSValueSharedList; + if (aLen == 0) { + return list.forget().take(); + } + + list->mHead = new nsCSSValueList; + nsCSSValueList* cur = list->mHead; + for (uint32_t i = 0; i < aLen - 1; i++) { + cur->mNext = new nsCSSValueList; + cur = cur->mNext; + } + + return list.forget().take(); +} + +void +Gecko_CSSValue_SetAbsoluteLength(nsCSSValueBorrowedMut aCSSValue, nscoord aLen) +{ + aCSSValue->SetIntegerCoordValue(aLen); +} + +void +Gecko_CSSValue_SetNumber(nsCSSValueBorrowedMut aCSSValue, float aNumber) +{ + aCSSValue->SetFloatValue(aNumber, eCSSUnit_Number); +} + +void +Gecko_CSSValue_SetKeyword(nsCSSValueBorrowedMut aCSSValue, nsCSSKeyword aKeyword) +{ + aCSSValue->SetIntValue(aKeyword, eCSSUnit_Enumerated); +} + +void +Gecko_CSSValue_SetPercentage(nsCSSValueBorrowedMut aCSSValue, float aPercent) +{ + aCSSValue->SetFloatValue(aPercent, eCSSUnit_Number); +} + +void +Gecko_CSSValue_SetAngle(nsCSSValueBorrowedMut aCSSValue, float aRadians) +{ + aCSSValue->SetFloatValue(aRadians, eCSSUnit_Radian); +} + +void +Gecko_CSSValue_SetCalc(nsCSSValueBorrowedMut aCSSValue, nsStyleCoord::CalcValue aCalc) +{ + aCSSValue->SetCalcValue(&aCalc); +} + +void +Gecko_CSSValue_SetFunction(nsCSSValueBorrowedMut aCSSValue, int32_t aLen) +{ + nsCSSValue::Array* arr = nsCSSValue::Array::Create(aLen); + aCSSValue->SetArrayValue(arr, eCSSUnit_Function); +} + +nsCSSValueBorrowedMut +Gecko_CSSValue_GetArrayItem(nsCSSValueBorrowedMut aCSSValue, int32_t aIndex) +{ + return &aCSSValue->GetArrayValue()->Item(aIndex); +} + +NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsCSSValueSharedList, CSSValueSharedList); + #define STYLE_STRUCT(name, checkdata_cb) \ \ void \ diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/style/ServoBindings.h firefox-trunk-52.0~a1~hg20161113r322177/layout/style/ServoBindings.h --- firefox-trunk-52.0~a1~hg20161110r321971/layout/style/ServoBindings.h 2016-11-11 01:27:01.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/style/ServoBindings.h 2016-11-14 01:15:35.000000000 +0000 @@ -256,6 +256,17 @@ nsStyleQuoteValues* Gecko_NewStyleQuoteValues(uint32_t len); NS_DECL_THREADSAFE_FFI_REFCOUNTING(nsStyleQuoteValues, QuoteValues); +nsCSSValueSharedList* Gecko_NewCSSValueSharedList(uint32_t len); +void Gecko_CSSValue_SetAbsoluteLength(nsCSSValueBorrowedMut css_value, nscoord len); +void Gecko_CSSValue_SetNumber(nsCSSValueBorrowedMut css_value, float number); +void Gecko_CSSValue_SetKeyword(nsCSSValueBorrowedMut css_value, nsCSSKeyword keyword); +void Gecko_CSSValue_SetPercentage(nsCSSValueBorrowedMut css_value, float percent); +void Gecko_CSSValue_SetAngle(nsCSSValueBorrowedMut css_value, float radians); +void Gecko_CSSValue_SetCalc(nsCSSValueBorrowedMut css_value, nsStyleCoord::CalcValue calc); +void Gecko_CSSValue_SetFunction(nsCSSValueBorrowedMut css_value, int32_t len); +nsCSSValueBorrowedMut Gecko_CSSValue_GetArrayItem(nsCSSValueBorrowedMut css_value, int32_t index); +NS_DECL_THREADSAFE_FFI_REFCOUNTING(nsCSSValueSharedList, CSSValueSharedList); + // Style-struct management. #define STYLE_STRUCT(name, checkdata_cb) \ void Gecko_Construct_nsStyle##name(nsStyle##name* ptr); \ diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/style/ServoBindingTypes.h firefox-trunk-52.0~a1~hg20161113r322177/layout/style/ServoBindingTypes.h --- firefox-trunk-52.0~a1~hg20161110r321971/layout/style/ServoBindingTypes.h 2016-11-11 01:27:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/style/ServoBindingTypes.h 2016-11-14 01:15:35.000000000 +0000 @@ -22,6 +22,7 @@ } // namespace dom } // namespace mozilla +class nsCSSValue; class nsIDocument; class nsINode; @@ -93,6 +94,8 @@ DECL_BORROWED_REF_TYPE_FOR(RawGeckoDocument) DECL_NULLABLE_BORROWED_REF_TYPE_FOR(RawGeckoDocument) DECL_BORROWED_MUT_REF_TYPE_FOR(StyleChildrenIterator) +DECL_BORROWED_REF_TYPE_FOR(nsCSSValue) +DECL_BORROWED_MUT_REF_TYPE_FOR(nsCSSValue) #undef DECL_ARC_REF_TYPE_FOR #undef DECL_OWNED_REF_TYPE_FOR diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/style/StyleAnimationValue.cpp firefox-trunk-52.0~a1~hg20161113r322177/layout/style/StyleAnimationValue.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/layout/style/StyleAnimationValue.cpp 2016-11-11 01:27:01.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/style/StyleAnimationValue.cpp 2016-11-14 01:15:35.000000000 +0000 @@ -271,13 +271,6 @@ return arr.forget(); } -inline void -nscoordToCSSValue(nscoord aCoord, nsCSSValue& aCSSValue) -{ - aCSSValue.SetFloatValue(nsPresContext::AppUnitsToFloatCSSPixels(aCoord), - eCSSUnit_Pixel); -} - static void AppendCSSShadowValue(const nsCSSShadowItem *aShadow, nsCSSValueList **&aResultTail) @@ -286,12 +279,12 @@ // X, Y, Radius, Spread, Color, Inset RefPtr arr = nsCSSValue::Array::Create(6); - nscoordToCSSValue(aShadow->mXOffset, arr->Item(0)); - nscoordToCSSValue(aShadow->mYOffset, arr->Item(1)); - nscoordToCSSValue(aShadow->mRadius, arr->Item(2)); + arr->Item(0).SetIntegerCoordValue(aShadow->mXOffset); + arr->Item(1).SetIntegerCoordValue(aShadow->mYOffset); + arr->Item(2).SetIntegerCoordValue(aShadow->mRadius); // NOTE: This code sometimes stores mSpread: 0 even when // the parser would be required to leave it null. - nscoordToCSSValue(aShadow->mSpread, arr->Item(3)); + arr->Item(3).SetIntegerCoordValue(aShadow->mSpread); if (aShadow->mHasColor) { arr->Item(4).SetColorValue(aShadow->mColor); } @@ -388,23 +381,13 @@ } static void -SetCalcValue(const nsStyleCoord::CalcValue* aCalc, nsCSSValue& aValue) +CalcValueToCSSValue(const nsStyleCoord::CalcValue* aCalc, nsCSSValue& aValue) { - RefPtr arr = nsCSSValue::Array::Create(1); - if (!aCalc->mHasPercent) { - nscoordToCSSValue(aCalc->mLength, arr->Item(0)); - } else { - nsCSSValue::Array *arr2 = nsCSSValue::Array::Create(2); - arr->Item(0).SetArrayValue(arr2, eCSSUnit_Calc_Plus); - nscoordToCSSValue(aCalc->mLength, arr2->Item(0)); - arr2->Item(1).SetPercentValue(aCalc->mPercent); - } - - aValue.SetArrayValue(arr, eCSSUnit_Calc); + aValue.SetCalcValue(aCalc); } static void -SetCalcValue(const PixelCalcValue& aCalc, nsCSSValue& aValue) +CalcValueToCSSValue(const PixelCalcValue& aCalc, nsCSSValue& aValue) { RefPtr arr = nsCSSValue::Array::Create(1); if (!aCalc.mHasPercent) { @@ -588,7 +571,7 @@ result.mHasPercent = v1.mHasPercent || v2.mHasPercent; MOZ_ASSERT(result.mHasPercent || result.mPercent == 0.0f, "can't have a nonzero percentage part without having percentages"); - SetCalcValue(result, aResult); + CalcValueToCSSValue(result, aResult); } static inline void @@ -3502,7 +3485,7 @@ SetIntValue(aComputedValue.GetIntValue(), eCSSUnit_Integer); break; case eUnit_Coord: - nscoordToCSSValue(aComputedValue.GetCoordValue(), aSpecifiedValue); + aSpecifiedValue.SetIntegerCoordValue(aComputedValue.GetCoordValue()); break; case eUnit_Percent: aSpecifiedValue.SetPercentValue(aComputedValue.GetPercentValue()); @@ -3693,7 +3676,7 @@ break; case eStyleUnit_Calc: { nsAutoPtr val(new nsCSSValue); - SetCalcValue(aCoord.GetCalcValue(), *val); + CalcValueToCSSValue(aCoord.GetCalcValue(), *val); aValue.SetAndAdoptCSSValueValue(val.forget(), StyleAnimationValue::eUnit_Calc); break; @@ -3709,7 +3692,7 @@ { switch (aCoord.GetUnit()) { case eStyleUnit_Coord: - nscoordToCSSValue(aCoord.GetCoordValue(), aCSSValue); + aCSSValue.SetIntegerCoordValue(aCoord.GetCoordValue()); break; case eStyleUnit_Factor: aCSSValue.SetFloatValue(aCoord.GetFactorValue(), eCSSUnit_Number); @@ -3718,7 +3701,7 @@ aCSSValue.SetPercentValue(aCoord.GetPercentValue()); break; case eStyleUnit_Calc: - SetCalcValue(aCoord.GetCalcValue(), aCSSValue); + CalcValueToCSSValue(aCoord.GetCalcValue(), aCSSValue); break; case eStyleUnit_Degree: aCSSValue.SetFloatValue(aCoord.GetAngleValue(), eCSSUnit_Degree); @@ -3753,8 +3736,8 @@ nsCSSValue& xValue = posArray->Item(1); nsCSSValue& yValue = posArray->Item(3); - SetCalcValue(&aPos.mXPosition, xValue); - SetCalcValue(&aPos.mYPosition, yValue); + CalcValueToCSSValue(&aPos.mXPosition, xValue); + CalcValueToCSSValue(&aPos.mYPosition, yValue); } static void @@ -3771,7 +3754,7 @@ // we'll just have a normalized "x"/"y" position, with no edge names needed. nsCSSValue& value = posArray->Item(1); - SetCalcValue(&aPosCoord, value); + CalcValueToCSSValue(&aPosCoord, value); } /* @@ -3793,7 +3776,7 @@ c2.mLength = c.mLength; c2.mPercent = c.mPercent; c2.mHasPercent = true; // doesn't matter for transform translate - SetCalcValue(&c2, aOutput); + CalcValueToCSSValue(&c2, aOutput); } else if (aInput.UnitHasArrayValue()) { const nsCSSValue::Array *inputArray = aInput.GetArrayValue(); RefPtr outputArray = @@ -3881,19 +3864,19 @@ break; case nsStyleImageLayers::Size::eLengthPercentage: // XXXbz is there a good reason we can't just - // SetCalcValue(&size.mWidth, item->mXValue) here? + // CalcValueToCSSValue(&size.mWidth, item->mXValue) here? if (!size.mWidth.mHasPercent && // negative values must have come from calc() size.mWidth.mLength >= 0) { MOZ_ASSERT(size.mWidth.mPercent == 0.0f, "Shouldn't have mPercent"); - nscoordToCSSValue(size.mWidth.mLength, item->mXValue); + item->mXValue.SetIntegerCoordValue(size.mWidth.mLength); } else if (size.mWidth.mLength == 0 && // negative values must have come from calc() size.mWidth.mPercent >= 0.0f) { item->mXValue.SetPercentValue(size.mWidth.mPercent); } else { - SetCalcValue(&size.mWidth, item->mXValue); + CalcValueToCSSValue(&size.mWidth, item->mXValue); } break; } @@ -3908,19 +3891,19 @@ break; case nsStyleImageLayers::Size::eLengthPercentage: // XXXbz is there a good reason we can't just - // SetCalcValue(&size.mHeight, item->mYValue) here? + // CalcValueToCSSValue(&size.mHeight, item->mYValue) here? if (!size.mHeight.mHasPercent && // negative values must have come from calc() size.mHeight.mLength >= 0) { MOZ_ASSERT(size.mHeight.mPercent == 0.0f, "Shouldn't have mPercent"); - nscoordToCSSValue(size.mHeight.mLength, item->mYValue); + item->mYValue.SetIntegerCoordValue(size.mHeight.mLength); } else if (size.mHeight.mLength == 0 && // negative values must have come from calc() size.mHeight.mPercent >= 0.0f) { item->mYValue.SetPercentValue(size.mHeight.mPercent); } else { - SetCalcValue(&size.mHeight, item->mYValue); + CalcValueToCSSValue(&size.mHeight, item->mYValue); } break; } @@ -4085,8 +4068,8 @@ const nsStyleTableBorder *styleTableBorder = static_cast(styleStruct); nsAutoPtr pair(new nsCSSValuePair); - nscoordToCSSValue(styleTableBorder->mBorderSpacingCol, pair->mXValue); - nscoordToCSSValue(styleTableBorder->mBorderSpacingRow, pair->mYValue); + pair->mXValue.SetIntegerCoordValue(styleTableBorder->mBorderSpacingCol); + pair->mYValue.SetIntegerCoordValue(styleTableBorder->mBorderSpacingRow); aComputedValue.SetAndAdoptCSSValuePairValue(pair.forget(), eUnit_CSSValuePair); break; @@ -4206,10 +4189,10 @@ } nsCSSRect *vrect = new nsCSSRect; - nscoordToCSSValue(srect.x, vrect->mLeft); - nscoordToCSSValue(srect.y, vrect->mTop); - nscoordToCSSValue(srect.XMost(), vrect->mRight); - nscoordToCSSValue(srect.YMost(), vrect->mBottom); + vrect->mLeft.SetIntegerCoordValue(srect.x); + vrect->mTop.SetIntegerCoordValue(srect.y); + vrect->mRight.SetIntegerCoordValue(srect.XMost()); + vrect->mBottom.SetIntegerCoordValue(srect.YMost()); aComputedValue.SetAndAdoptCSSRectValue(vrect, eUnit_CSSRect); break; } @@ -4225,22 +4208,22 @@ if (effects->mClipFlags & NS_STYLE_CLIP_TOP_AUTO) { vrect->mTop.SetAutoValue(); } else { - nscoordToCSSValue(srect.y, vrect->mTop); + vrect->mTop.SetIntegerCoordValue(srect.y); } if (effects->mClipFlags & NS_STYLE_CLIP_RIGHT_AUTO) { vrect->mRight.SetAutoValue(); } else { - nscoordToCSSValue(srect.XMost(), vrect->mRight); + vrect->mRight.SetIntegerCoordValue(srect.XMost()); } if (effects->mClipFlags & NS_STYLE_CLIP_BOTTOM_AUTO) { vrect->mBottom.SetAutoValue(); } else { - nscoordToCSSValue(srect.YMost(), vrect->mBottom); + vrect->mBottom.SetIntegerCoordValue(srect.YMost()); } if (effects->mClipFlags & NS_STYLE_CLIP_LEFT_AUTO) { vrect->mLeft.SetAutoValue(); } else { - nscoordToCSSValue(srect.x, vrect->mLeft); + vrect->mLeft.SetIntegerCoordValue(srect.x); } aComputedValue.SetAndAdoptCSSRectValue(vrect, eUnit_CSSRect); } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/style/StyleAnimationValue.h firefox-trunk-52.0~a1~hg20161113r322177/layout/style/StyleAnimationValue.h --- firefox-trunk-52.0~a1~hg20161110r321971/layout/style/StyleAnimationValue.h 2016-11-11 01:27:01.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/style/StyleAnimationValue.h 2016-11-14 01:15:35.000000000 +0000 @@ -16,6 +16,7 @@ #include "nsColor.h" #include "nsCSSProps.h" #include "nsCSSValue.h" +#include "nsStyleCoord.h" class nsIFrame; class nsStyleContext; @@ -596,7 +597,6 @@ nsCSSPropertyID mProperty; StyleAnimationValue mValue; }; - } // namespace mozilla #endif diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/style/test/test_animations.html firefox-trunk-52.0~a1~hg20161113r322177/layout/style/test/test_animations.html --- firefox-trunk-52.0~a1~hg20161110r321971/layout/style/test/test_animations.html 2016-11-11 01:28:56.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/style/test/test_animations.html 2016-11-14 01:16:58.000000000 +0000 @@ -50,7 +50,7 @@ 25% { margin-top: 100px } } @keyframes kf4 { - to, from { border-collapse: collapse; margin-top: 37px } + to, from { display: none; margin-top: 37px } } @keyframes kf_cascade1 { from { padding-top: 50px } @@ -566,23 +566,23 @@ // we still override the value when two consecutive keyframes have // the same value. new_div("animation: kf4 ease 10s"); -is(cs.borderCollapse, "separate", +is(cs.display, "block", "non-animatable properties should be ignored (linear, 0s)"); is(cs.marginTop, "37px", "animatable properties should still apply (linear, 0s)"); advance_clock(1000); -is(cs.borderCollapse, "separate", +is(cs.display, "block", "non-animatable properties should be ignored (linear, 1s)"); is(cs.marginTop, "37px", "animatable properties should still apply (linear, 1s)"); done_div(); new_div("animation: kf4 step-start 10s"); -is(cs.borderCollapse, "separate", +is(cs.display, "block", "non-animatable properties should be ignored (step-start, 0s)"); is(cs.marginTop, "37px", "animatable properties should still apply (step-start, 0s)"); advance_clock(1000); -is(cs.borderCollapse, "separate", +is(cs.display, "block", "non-animatable properties should be ignored (step-start, 1s)"); is(cs.marginTop, "37px", "animatable properties should still apply (step-start, 1s)"); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/layout/style/test/test_animations_omta.html firefox-trunk-52.0~a1~hg20161113r322177/layout/style/test/test_animations_omta.html --- firefox-trunk-52.0~a1~hg20161110r321971/layout/style/test/test_animations_omta.html 2016-11-11 01:28:57.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/layout/style/test/test_animations_omta.html 2016-11-14 01:16:58.000000000 +0000 @@ -61,7 +61,7 @@ 25% { transform: translate(100px) } } @keyframes kf4 { - to, from { border-collapse: collapse; transform: translate(37px) } + to, from { display: none; transform: translate(37px) } } @keyframes kf_cascade1 { from { transform: translate(50px) } @@ -634,12 +634,12 @@ new_div("animation: kf4 ease 10s"); yield waitForPaintsFlushed(); var cs = window.getComputedStyle(gDiv); - is(cs.borderCollapse, "separate", + is(cs.display, "block", "non-animatable properties should be ignored (linear, 0s)"); omta_is("transform", { tx: 37 }, RunningOn.Compositor, "animatable properties should still apply (linear, 0s)"); advance_clock(1000); - is(cs.borderCollapse, "separate", + is(cs.display, "block", "non-animatable properties should be ignored (linear, 1s)"); omta_is("transform", { tx: 37 }, RunningOn.Compositor, "animatable properties should still apply (linear, 1s)"); @@ -647,12 +647,12 @@ new_div("animation: kf4 step-start 10s"); yield waitForPaintsFlushed(); cs = window.getComputedStyle(gDiv); - is(cs.borderCollapse, "separate", + is(cs.display, "block", "non-animatable properties should be ignored (step-start, 0s)"); omta_is("transform", { tx: 37 }, RunningOn.Compositor, "animatable properties should still apply (step-start, 0s)"); advance_clock(1000); - is(cs.borderCollapse, "separate", + is(cs.display, "block", "non-animatable properties should be ignored (step-start, 1s)"); omta_is("transform", { tx: 37 }, RunningOn.Compositor, "animatable properties should still apply (step-start, 1s)"); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/memory/build/moz.build firefox-trunk-52.0~a1~hg20161113r322177/memory/build/moz.build --- firefox-trunk-52.0~a1~hg20161110r321971/memory/build/moz.build 2016-11-11 01:44:43.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/memory/build/moz.build 2016-11-14 01:38:02.000000000 +0000 @@ -9,7 +9,7 @@ 'mozmemory_wrap.h', ] -DEFINES['MOZ_HAS_MOZGLUE'] = True +LIBRARY_DEFINES['MOZ_HAS_MOZGLUE'] = True DEFINES['MOZ_MEMORY_IMPL'] = True if CONFIG['MOZ_REPLACE_MALLOC']: @@ -41,16 +41,6 @@ Library('memory') -if CONFIG['MOZ_JEMALLOC4']: - if not CONFIG['MOZ_SYSTEM_JEMALLOC']: - USE_LIBS += [ - 'jemalloc', - ] -else: - USE_LIBS += [ - 'mozjemalloc', - ] - if CONFIG['MOZ_GLUE_IN_PROGRAM']: SDK_LIBRARY = True DIST_INSTALL = True diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/memory/jemalloc/moz.build firefox-trunk-52.0~a1~hg20161113r322177/memory/jemalloc/moz.build --- firefox-trunk-52.0~a1~hg20161110r321971/memory/jemalloc/moz.build 2016-11-11 01:44:43.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/memory/jemalloc/moz.build 2016-11-14 01:38:02.000000000 +0000 @@ -46,9 +46,10 @@ 'src/src/zone.c', ] -Library('jemalloc') - -FORCE_STATIC_LIB = True +if CONFIG['MOZ_JEMALLOC4']: + FINAL_LIBRARY = 'memory' +else: + FINAL_LIBRARY = 'replace_jemalloc' if CONFIG['MOZ_GLUE_IN_PROGRAM']: SDK_LIBRARY = True @@ -68,7 +69,6 @@ CFLAGS += ['-std=gnu99'] DEFINES['abort'] = 'moz_abort' -DEFINES['MOZ_HAS_MOZGLUE'] = True LOCAL_INCLUDES += [ '!src/include', diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/memory/mozjemalloc/moz.build firefox-trunk-52.0~a1~hg20161113r322177/memory/mozjemalloc/moz.build --- firefox-trunk-52.0~a1~hg20161110r321971/memory/mozjemalloc/moz.build 2016-11-11 01:45:29.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/memory/mozjemalloc/moz.build 2016-11-14 01:39:58.000000000 +0000 @@ -12,9 +12,7 @@ SOURCES += [ 'jemalloc.c', ] - Library('mozjemalloc') - STATIC_LIBRARY_NAME = 'jemalloc' - FORCE_STATIC_LIB = True + FINAL_LIBRARY = 'memory' # See bug 422055. if CONFIG['OS_ARCH'] == 'SunOS' and not CONFIG['GNU_CC'] \ @@ -28,7 +26,6 @@ DEFINES['abort'] = 'moz_abort' -DEFINES['MOZ_HAS_MOZGLUE'] = True DEFINES['MOZ_JEMALLOC_IMPL'] = True #XXX: PGO on Linux causes problems here diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/memory/replace/jemalloc/moz.build firefox-trunk-52.0~a1~hg20161113r322177/memory/replace/jemalloc/moz.build --- firefox-trunk-52.0~a1~hg20161110r321971/memory/replace/jemalloc/moz.build 2016-11-11 01:45:29.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/memory/replace/jemalloc/moz.build 2016-11-14 01:39:59.000000000 +0000 @@ -19,10 +19,6 @@ SharedLibrary('replace_jemalloc') -USE_LIBS += [ - 'jemalloc', -] - DEFINES['MOZ_JEMALLOC4'] = True DEFINES['MOZ_REPLACE_JEMALLOC'] = True diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/mobile/android/base/AppConstants.java.in firefox-trunk-52.0~a1~hg20161113r322177/mobile/android/base/AppConstants.java.in --- firefox-trunk-52.0~a1~hg20161110r321971/mobile/android/base/AppConstants.java.in 2016-11-11 01:45:46.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/mobile/android/base/AppConstants.java.in 2016-11-14 01:40:50.000000000 +0000 @@ -278,13 +278,6 @@ false; //#endif - public static final boolean MOZ_LINKER_EXTRACT = -//#ifdef MOZ_LINKER_EXTRACT - true; -//#else - false; -//#endif - public static final boolean MOZ_DRAGGABLE_URLBAR = false; public static final boolean MOZ_INSTALL_TRACKING = diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/mobile/android/base/java/org/mozilla/gecko/home/activitystream/StreamItem.java firefox-trunk-52.0~a1~hg20161113r322177/mobile/android/base/java/org/mozilla/gecko/home/activitystream/StreamItem.java --- firefox-trunk-52.0~a1~hg20161110r321971/mobile/android/base/java/org/mozilla/gecko/home/activitystream/StreamItem.java 2016-11-11 01:46:47.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/mobile/android/base/java/org/mozilla/gecko/home/activitystream/StreamItem.java 2016-11-14 01:41:39.000000000 +0000 @@ -27,6 +27,7 @@ import org.mozilla.gecko.icons.IconResponse; import org.mozilla.gecko.icons.Icons; import org.mozilla.gecko.util.DrawableUtil; +import org.mozilla.gecko.util.ViewUtil; import org.mozilla.gecko.util.TouchTargetUtil; import org.mozilla.gecko.widget.FaviconView; @@ -124,6 +125,8 @@ vIconView.getWidth(), vIconView.getHeight()); } }); + + ViewUtil.enableTouchRipple(menuButton); } public void bind(Cursor cursor, int tilesWidth, int tilesHeight) { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/mobile/android/base/java/org/mozilla/gecko/home/activitystream/topsites/TopSitesCard.java firefox-trunk-52.0~a1~hg20161113r322177/mobile/android/base/java/org/mozilla/gecko/home/activitystream/topsites/TopSitesCard.java --- firefox-trunk-52.0~a1~hg20161110r321971/mobile/android/base/java/org/mozilla/gecko/home/activitystream/topsites/TopSitesCard.java 2016-11-11 01:46:47.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/mobile/android/base/java/org/mozilla/gecko/home/activitystream/topsites/TopSitesCard.java 2016-11-14 01:41:40.000000000 +0000 @@ -19,6 +19,7 @@ import org.mozilla.gecko.icons.IconResponse; import org.mozilla.gecko.icons.Icons; import org.mozilla.gecko.util.DrawableUtil; +import org.mozilla.gecko.util.ViewUtil; import org.mozilla.gecko.util.TouchTargetUtil; import org.mozilla.gecko.widget.FaviconView; @@ -53,6 +54,8 @@ TouchTargetUtil.ensureTargetHitArea(menuButton, card); menuButton.setOnClickListener(this); + + ViewUtil.enableTouchRipple(menuButton); } void bind(final TopSitesPageAdapter.TopSite topSite) { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/mobile/android/base/java/org/mozilla/gecko/home/TwoLinePageRow.java firefox-trunk-52.0~a1~hg20161113r322177/mobile/android/base/java/org/mozilla/gecko/home/TwoLinePageRow.java --- firefox-trunk-52.0~a1~hg20161110r321971/mobile/android/base/java/org/mozilla/gecko/home/TwoLinePageRow.java 2016-11-11 01:46:47.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/mobile/android/base/java/org/mozilla/gecko/home/TwoLinePageRow.java 2016-11-14 01:41:39.000000000 +0000 @@ -201,7 +201,8 @@ * selected tab. */ protected void updateDisplayedUrl() { - boolean isPrivate = Tabs.getInstance().getSelectedTab().isPrivate(); + final Tab selectedTab = Tabs.getInstance().getSelectedTab(); + final boolean isPrivate = (selectedTab != null) && (selectedTab.isPrivate()); // We always want to display the underlying page url, however for readermode pages // we navigate to the about:reader equivalent, hence we need to use that url when finding diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/mobile/android/base/java/org/mozilla/gecko/util/ViewUtil.java firefox-trunk-52.0~a1~hg20161113r322177/mobile/android/base/java/org/mozilla/gecko/util/ViewUtil.java --- firefox-trunk-52.0~a1~hg20161110r321971/mobile/android/base/java/org/mozilla/gecko/util/ViewUtil.java 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/mobile/android/base/java/org/mozilla/gecko/util/ViewUtil.java 2016-11-14 01:42:27.000000000 +0000 @@ -0,0 +1,33 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- + * 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/. */ +package org.mozilla.gecko.util; + +import android.content.res.TypedArray; +import android.view.View; + +import org.mozilla.gecko.AppConstants; +import org.mozilla.gecko.R; + +public class ViewUtil { + + /** + * Enable a circular touch ripple for a given view. This is intended for borderless views, + * such as (3-dot) menu buttons. + * + * Because of platform limitations a square ripple is used on Android 4. + */ + public static void enableTouchRipple(View view) { + final TypedArray backgroundDrawableArray; + if (AppConstants.Versions.feature21Plus) { + backgroundDrawableArray = view.getContext().obtainStyledAttributes(new int[] { R.attr.selectableItemBackgroundBorderless }); + } else { + backgroundDrawableArray = view.getContext().obtainStyledAttributes(new int[] { R.attr.selectableItemBackground }); + } + + // This call is deprecated, but the replacement setBackground(Drawable) isn't available + // until API 16. + view.setBackgroundDrawable(backgroundDrawableArray.getDrawable(0)); + } +} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/mobile/android/base/moz.build firefox-trunk-52.0~a1~hg20161113r322177/mobile/android/base/moz.build --- firefox-trunk-52.0~a1~hg20161110r321971/mobile/android/base/moz.build 2016-11-11 01:47:38.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/mobile/android/base/moz.build 2016-11-14 01:42:29.000000000 +0000 @@ -742,6 +742,7 @@ 'util/DrawableUtil.java', 'util/ResourceDrawableUtils.java', 'util/TouchTargetUtil.java', + 'util/ViewUtil.java', 'widget/ActivityChooserModel.java', 'widget/AllCapsTextView.java', 'widget/AnchoredPopup.java', @@ -1069,7 +1070,7 @@ # We do not expose MOZ_ADJUST_SDK_KEY here because that # would leak the value # to build logs. Instead we expose the token quietly where appropriate in # Makefile.in. -for var in ('MOZ_ANDROID_ANR_REPORTER', 'MOZ_LINKER_EXTRACT', 'MOZ_DEBUG', +for var in ('MOZ_ANDROID_ANR_REPORTER', 'MOZ_DEBUG', 'MOZ_ANDROID_SEARCH_ACTIVITY', 'MOZ_NATIVE_DEVICES', 'MOZ_ANDROID_MLS_STUMBLER', 'MOZ_ANDROID_DOWNLOADS_INTEGRATION', 'MOZ_INSTALL_TRACKING', 'MOZ_ANDROID_GCM', 'MOZ_ANDROID_EXCLUDE_FONTS', 'MOZ_LOCALE_SWITCHER', diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/mobile/android/base/resources/layout/activity_stream_card_history_item.xml firefox-trunk-52.0~a1~hg20161113r322177/mobile/android/base/resources/layout/activity_stream_card_history_item.xml --- firefox-trunk-52.0~a1~hg20161110r321971/mobile/android/base/resources/layout/activity_stream_card_history_item.xml 2016-11-11 01:48:26.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/mobile/android/base/resources/layout/activity_stream_card_history_item.xml 2016-11-14 01:43:54.000000000 +0000 @@ -17,14 +17,18 @@ + android:background="?android:attr/selectableItemBackground"> @@ -32,16 +36,15 @@ + android:src="@drawable/menu" + android:padding="@dimen/activity_stream_base_margin" /> @@ -84,7 +88,10 @@ android:layout_alignParentBottom="true" android:paddingLeft="@dimen/activity_stream_base_margin" android:paddingStart="@dimen/activity_stream_base_margin" + android:paddingRight="@dimen/activity_stream_base_margin" + android:paddingEnd="@dimen/activity_stream_base_margin" android:paddingTop="4dp" + android:paddingBottom="@dimen/activity_stream_base_margin" android:gravity="center_vertical" android:layout_below="@id/card_history_label"> diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/mobile/android/base/resources/layout/activity_stream_topsites_card.xml firefox-trunk-52.0~a1~hg20161113r322177/mobile/android/base/resources/layout/activity_stream_topsites_card.xml --- firefox-trunk-52.0~a1~hg20161110r321971/mobile/android/base/resources/layout/activity_stream_topsites_card.xml 2016-11-11 01:48:29.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/mobile/android/base/resources/layout/activity_stream_topsites_card.xml 2016-11-14 01:43:54.000000000 +0000 @@ -8,7 +8,8 @@ + android:layout_height="wrap_content" + android:background="?android:attr/selectableItemBackground"> OnStopRequest(this, mListenerContext, status); - mListener = 0; - mListenerContext = 0; + mListener = nullptr; + mListenerContext = nullptr; } if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, status); - mPump = 0; + mPump = nullptr; mIsPending = false; // Drop notification callbacks to prevent cycles. - mCallbacks = 0; - mProgressSink = 0; + mCallbacks = nullptr; + mProgressSink = nullptr; #if defined(XP_WIN) || defined(MOZ_WIDGET_COCOA) #else diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/modules/libpref/init/all.js firefox-trunk-52.0~a1~hg20161113r322177/modules/libpref/init/all.js --- firefox-trunk-52.0~a1~hg20161110r321971/modules/libpref/init/all.js 2016-11-11 01:57:18.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/modules/libpref/init/all.js 2016-11-14 01:55:46.000000000 +0000 @@ -203,6 +203,7 @@ #else pref("dom.gamepad.non_standard_events.enabled", true); #endif +pref("dom.gamepad.extensions.enabled", false); // Whether the KeyboardEvent.code is enabled pref("dom.keyboardevent.code.enabled", true); @@ -1964,6 +1965,18 @@ // 2 - allow the cross-origin authentication as well. pref("network.auth.subresource-http-auth-allow", 2); +// This preference controls whether to allow sending default credentials (SSO) to +// NTLM/Negotiate servers allowed in the "trusted uri" list when navigating them +// in a Private Browsing window. +// If set to false, Private Browsing windows will not use default credentials and ask +// for credentials from the user explicitly. +// If set to true, and a server URL conforms other conditions for sending default +// credentials, those will be sent automatically in Private Browsing windows. +// +// This preference has no effect when the browser is set to "Never Remember History", +// in that case default credentials will always be used. +pref("network.auth.private-browsing-sso", false); + pref("permissions.default.image", 1); // 1-Accept, 2-Deny, 3-dontAcceptForeign pref("network.proxy.type", 5); @@ -5517,6 +5530,8 @@ // mixed-content blocking pref("security.mixed_content.use_hsts", true); #endif +// Approximately 1 week default cache for HSTS priming failures +pref ("security.mixed_content.hsts_priming_cache_timeout", 10080); // Disable Storage api in release builds. #ifdef NIGHTLY_BUILD diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/mozglue/android/APKOpen.cpp firefox-trunk-52.0~a1~hg20161113r322177/mozglue/android/APKOpen.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/mozglue/android/APKOpen.cpp 2016-11-11 01:59:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/mozglue/android/APKOpen.cpp 2016-11-14 01:56:51.000000000 +0000 @@ -199,6 +199,21 @@ info->offset = offset; } +extern "C" void +delete_mapping(const char *name) +{ + for (int pos = 0; pos < mapping_count; ++pos) { + struct mapping_info *info = &lib_mapping[pos]; + if (!strcmp(info->name, name)) { + struct mapping_info *last = &lib_mapping[mapping_count - 1]; + free(info->name); + *info = *last; + --mapping_count; + break; + } + } +} + static void* dlopenAPKLibrary(const char* apkName, const char* libraryName) { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/mozglue/linker/CustomElf.cpp firefox-trunk-52.0~a1~hg20161113r322177/mozglue/linker/CustomElf.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/mozglue/linker/CustomElf.cpp 2016-11-11 01:59:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/mozglue/linker/CustomElf.cpp 2016-11-14 01:56:51.000000000 +0000 @@ -23,9 +23,11 @@ #ifdef ANDROID extern "C" { void report_mapping(char *name, void *base, uint32_t len, uint32_t offset); + void delete_mapping(const char *name); } #else #define report_mapping(...) +#define delete_mapping(...) #endif const Ehdr *Ehdr::validate(const void *buf) @@ -276,6 +278,7 @@ * calls destructors once, so call it in all cases. */ ElfLoader::__wrap_cxa_finalize(this); ElfLoader::Singleton.Forget(this); + delete_mapping(GetName()); } void * diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/mozglue/linker/tests/TestZip.cpp firefox-trunk-52.0~a1~hg20161113r322177/mozglue/linker/tests/TestZip.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/mozglue/linker/tests/TestZip.cpp 2016-11-11 01:59:01.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/mozglue/linker/tests/TestZip.cpp 2016-11-14 01:56:51.000000000 +0000 @@ -8,6 +8,7 @@ #include "mozilla/RefPtr.h" extern "C" void report_mapping() { } +extern "C" void delete_mapping() { } /** * test.zip is a basic test zip file with a central directory. It contains diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/mozglue/linker/Zip.cpp firefox-trunk-52.0~a1~hg20161113r322177/mozglue/linker/Zip.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/mozglue/linker/Zip.cpp 2016-11-11 01:59:01.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/mozglue/linker/Zip.cpp 2016-11-14 01:56:51.000000000 +0000 @@ -65,6 +65,7 @@ , nextDir(nullptr) , entries(nullptr) { + pthread_mutex_init(&mutex, nullptr); // If the first local file entry couldn't be found (which can happen // with optimized jars), check the first central directory entry. if (!nextFile) @@ -79,11 +80,14 @@ DEBUG_LOG("Unmapped %s @%p", name, mapped); free(name); } + pthread_mutex_destroy(&mutex); } bool Zip::GetStream(const char *path, Zip::Stream *out) const { + AutoLock lock(&mutex); + DEBUG_LOG("%s - GetFile %s", name, path); /* Fast path: if the Local File header on store matches, we can return the * corresponding stream right away. diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/mozglue/linker/Zip.h firefox-trunk-52.0~a1~hg20161113r322177/mozglue/linker/Zip.h --- firefox-trunk-52.0~a1~hg20161110r321971/mozglue/linker/Zip.h 2016-11-11 01:59:01.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/mozglue/linker/Zip.h 2016-11-14 01:56:51.000000000 +0000 @@ -9,6 +9,7 @@ #include #include #include +#include #include "Utils.h" #include "mozilla/Assertions.h" #include "mozilla/RefCounted.h" @@ -459,6 +460,8 @@ /* Pointer to the Directory entries */ mutable const DirectoryEntry *entries; + + mutable pthread_mutex_t mutex; }; /** diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/base/nsIClassOfService.idl firefox-trunk-52.0~a1~hg20161113r322177/netwerk/base/nsIClassOfService.idl --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/base/nsIClassOfService.idl 2016-11-11 01:59:02.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/base/nsIClassOfService.idl 2016-11-14 01:56:53.000000000 +0000 @@ -42,4 +42,6 @@ const unsigned long Speculative = 1 << 2; const unsigned long Background = 1 << 3; const unsigned long Unblocked = 1 << 4; + const unsigned long Throttleable = 1 << 5; + const unsigned long UrgentStart = 1 << 6; }; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/base/nsIncrementalStreamLoader.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/base/nsIncrementalStreamLoader.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/base/nsIncrementalStreamLoader.cpp 2016-11-11 01:59:03.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/base/nsIncrementalStreamLoader.cpp 2016-11-14 01:57:22.000000000 +0000 @@ -104,9 +104,9 @@ } // done.. cleanup ReleaseData(); - mRequest = 0; - mObserver = 0; - mContext = 0; + mRequest = nullptr; + mObserver = nullptr; + mContext = nullptr; } return NS_OK; } @@ -197,7 +197,7 @@ } uint32_t countRead; nsresult rv = inStr->ReadSegments(WriteSegmentFun, this, count, &countRead); - mRequest = 0; + mRequest = nullptr; return rv; } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/base/nsInputStreamPump.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/base/nsInputStreamPump.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/base/nsInputStreamPump.cpp 2016-11-11 01:59:03.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/base/nsInputStreamPump.cpp 2016-11-14 01:57:22.000000000 +0000 @@ -361,7 +361,7 @@ // release our reference to the original stream. from this point forward, // we only reference the "stream" via mAsyncStream. - mStream = 0; + mStream = nullptr; // mStreamOffset now holds the number of bytes currently read. we use this // to enforce the mStreamLength restriction. @@ -703,8 +703,8 @@ else if (mCloseWhenDone) mAsyncStream->Close(); - mAsyncStream = 0; - mTargetThread = 0; + mAsyncStream = nullptr; + mTargetThread = nullptr; mIsPending = false; { // Note: Must exit monitor for call to OnStartRequest to avoid @@ -714,8 +714,8 @@ mListener->OnStopRequest(this, mListenerContext, mStatus); mMonitor.Enter(); } - mListener = 0; - mListenerContext = 0; + mListener = nullptr; + mListenerContext = nullptr; if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, mStatus); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/base/nsIProtocolHandler.idl firefox-trunk-52.0~a1~hg20161113r322177/netwerk/base/nsIProtocolHandler.idl --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/base/nsIProtocolHandler.idl 2016-11-11 01:59:02.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/base/nsIProtocolHandler.idl 2016-11-14 01:57:20.000000000 +0000 @@ -300,6 +300,12 @@ * spec, not just the scheme + host + port. */ const unsigned long ORIGIN_IS_FULL_SPEC = (1 << 20); + + /** + * If this flag is set, the URI does not always allow content using the same + * protocol to link to it. + */ + const unsigned long URI_SCHEME_NOT_SELF_LINKABLE = (1 << 21); }; %{C++ diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/base/nsLoadGroup.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/base/nsLoadGroup.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/base/nsLoadGroup.cpp 2016-11-11 01:59:03.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/base/nsLoadGroup.cpp 2016-11-14 01:57:22.000000000 +0000 @@ -123,7 +123,7 @@ DebugOnly rv = Cancel(NS_BINDING_ABORTED); NS_ASSERTION(NS_SUCCEEDED(rv), "Cancel failed"); - mDefaultLoadRequest = 0; + mDefaultLoadRequest = nullptr; if (mRequestContext) { nsID rcid; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/base/nsSocketTransport2.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/base/nsSocketTransport2.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/base/nsSocketTransport2.cpp 2016-11-11 01:59:03.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/base/nsSocketTransport2.cpp 2016-11-14 01:57:22.000000000 +0000 @@ -1874,7 +1874,7 @@ SendStatus(NS_NET_STATUS_RESOLVED_HOST); SOCKET_LOG((" MSG_DNS_LOOKUP_COMPLETE\n")); - mDNSRequest = 0; + mDNSRequest = nullptr; if (param) { mDNSRecord = static_cast(param); mDNSRecord->GetNextAddr(SocketPort(), &mNetAddr); @@ -2092,7 +2092,7 @@ // make sure there isn't any pending DNS request if (mDNSRequest) { mDNSRequest->Cancel(NS_ERROR_ABORT); - mDNSRequest = 0; + mDNSRequest = nullptr; } // diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/base/nsStandardURL.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/base/nsStandardURL.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/base/nsStandardURL.cpp 2016-11-11 01:59:03.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/base/nsStandardURL.cpp 2016-11-14 01:57:22.000000000 +0000 @@ -393,7 +393,7 @@ nsStandardURL::InvalidateCache(bool invalidateCachedFile) { if (invalidateCachedFile) - mFile = 0; + mFile = nullptr; if (mHostA) { free(mHostA); mHostA = nullptr; @@ -3107,7 +3107,7 @@ if (NS_FAILED(file->Clone(getter_AddRefs(mFile)))) { NS_WARNING("nsIFile::Clone failed"); // failure to clone is not fatal (GetFile will generate mFile) - mFile = 0; + mFile = nullptr; } } return rv; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/base/nsStreamListenerTee.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/base/nsStreamListenerTee.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/base/nsStreamListenerTee.cpp 2016-11-11 01:59:03.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/base/nsStreamListenerTee.cpp 2016-11-14 01:57:22.000000000 +0000 @@ -37,7 +37,7 @@ // it is critical that we close out the input stream tee if (mInputTee) { mInputTee->SetSink(nullptr); - mInputTee = 0; + mInputTee = nullptr; } // release sink on the same thread where the data was written (bug 716293) @@ -45,13 +45,13 @@ NS_ProxyRelease(mEventTarget, mSink.forget()); } else { - mSink = 0; + mSink = nullptr; } nsresult rv = mListener->OnStopRequest(request, context, status); if (mObserver) mObserver->OnStopRequest(request, context, status); - mObserver = 0; + mObserver = nullptr; return rv; } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/base/nsStreamLoader.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/base/nsStreamLoader.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/base/nsStreamLoader.cpp 2016-11-11 01:59:03.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/base/nsStreamLoader.cpp 2016-11-14 01:57:22.000000000 +0000 @@ -111,9 +111,9 @@ } // done.. cleanup ReleaseData(); - mRequest = 0; - mObserver = 0; - mContext = 0; + mRequest = nullptr; + mObserver = nullptr; + mContext = nullptr; } if (mRequestObserver) { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/cache2/CacheEntry.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/cache2/CacheEntry.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/cache2/CacheEntry.cpp 2016-11-11 01:59:16.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/cache2/CacheEntry.cpp 2016-11-14 01:57:24.000000000 +0000 @@ -1547,6 +1547,15 @@ return NS_OK; } +NS_IMETHODIMP CacheEntry::GetDiskStorageSizeInKB(uint32_t *aDiskStorageSize) +{ + if (NS_FAILED(mFileStatus)) { + return NS_ERROR_NOT_AVAILABLE; + } + + return mFile->GetDiskStorageSizeInKB(aDiskStorageSize); +} + // nsIRunnable NS_IMETHODIMP CacheEntry::Run() diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/cache2/CacheFile.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/cache2/CacheFile.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/cache2/CacheFile.cpp 2016-11-11 01:59:20.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/cache2/CacheFile.cpp 2016-11-14 01:57:24.000000000 +0000 @@ -1231,6 +1231,17 @@ } nsresult +CacheFile::GetDiskStorageSizeInKB(uint32_t *aDiskStorageSize) +{ + if (!mHandle) { + return NS_ERROR_NOT_AVAILABLE; + } + + *aDiskStorageSize = mHandle->FileSizeInK(); + return NS_OK; +} + +nsresult CacheFile::OnFetched() { CacheFileAutoLock lock(this); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/cache2/CacheFile.h firefox-trunk-52.0~a1~hg20161113r322177/netwerk/cache2/CacheFile.h --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/cache2/CacheFile.h 2016-11-11 01:59:21.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/cache2/CacheFile.h 2016-11-14 01:57:24.000000000 +0000 @@ -105,6 +105,7 @@ nsresult GetLastModified(uint32_t *_retval); nsresult GetLastFetched(uint32_t *_retval); nsresult GetFetchCount(uint32_t *_retval); + nsresult GetDiskStorageSizeInKB(uint32_t *aDiskStorageSize); // Called by upper layers to indicated the entry has been fetched, // i.e. delivered to the consumer. nsresult OnFetched(); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/cache2/CacheIOThread.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/cache2/CacheIOThread.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/cache2/CacheIOThread.cpp 2016-11-11 02:00:24.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/cache2/CacheIOThread.cpp 2016-11-14 01:58:08.000000000 +0000 @@ -232,6 +232,10 @@ , mInsideLoop(true) #endif { + for (uint32_t i = 0; i < LAST_LEVEL; ++i) { + mQueueLength[i] = 0; + } + sSelf = this; } @@ -304,6 +308,8 @@ // Move everything from later executed OPEN level to the OPEN_PRIORITY level // where we post the (eviction) runnable. + mQueueLength[OPEN_PRIORITY] += mEventQueue[OPEN].Length(); + mQueueLength[OPEN] -= mEventQueue[OPEN].Length(); mEventQueue[OPEN_PRIORITY].AppendElements(mEventQueue[OPEN]); mEventQueue[OPEN].Clear(); @@ -320,6 +326,7 @@ mMonitor.AssertCurrentThreadOwns(); + ++mQueueLength[aLevel]; mEventQueue[aLevel].AppendElement(runnable.forget()); if (mLowestLevelWaiting > aLevel) mLowestLevelWaiting = aLevel; @@ -334,6 +341,17 @@ return mThread == PR_GetCurrentThread(); } +uint32_t CacheIOThread::QueueSize(bool highPriority) +{ + MonitorAutoLock lock(mMonitor); + if (highPriority) { + return mQueueLength[OPEN_PRIORITY] + mQueueLength[READ_PRIORITY]; + } + + return mQueueLength[OPEN_PRIORITY] + mQueueLength[READ_PRIORITY] + + mQueueLength[MANAGEMENT] + mQueueLength[OPEN] + mQueueLength[READ]; +} + bool CacheIOThread::YieldInternal() { if (!IsCurrentThread()) { @@ -543,6 +561,8 @@ break; } + --mQueueLength[aLevel]; + // Release outside the lock. events[index] = nullptr; } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/cache2/CacheIOThread.h firefox-trunk-52.0~a1~hg20161113r322177/netwerk/cache2/CacheIOThread.h --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/cache2/CacheIOThread.h 2016-11-11 02:00:24.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/cache2/CacheIOThread.h 2016-11-14 01:58:08.000000000 +0000 @@ -67,6 +67,8 @@ nsresult DispatchAfterPendingOpens(nsIRunnable* aRunnable); bool IsCurrentThread(); + uint32_t QueueSize(bool highPriority); + /** * Callable only on this thread, checks if there is an event waiting in * the event queue with a higher execution priority. If so, the result @@ -118,6 +120,10 @@ Atomic mLowestLevelWaiting; uint32_t mCurrentlyExecutingLevel; + // Keeps the length of the each event queue, since LoopOneLevel moves all + // events into a local array. + Atomic mQueueLength[LAST_LEVEL]; + EventQueue mEventQueue[LAST_LEVEL]; // Raised when nsIEventTarget.Dispatch() is called on this thread Atomic mHasXPCOMEvents; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/cache2/CacheStorageService.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/cache2/CacheStorageService.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/cache2/CacheStorageService.cpp 2016-11-11 02:00:25.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/cache2/CacheStorageService.cpp 2016-11-14 01:58:21.000000000 +0000 @@ -2010,6 +2010,14 @@ aEntry->IsPinned()); } +// static +uint32_t CacheStorageService::CacheQueueSize(bool highPriority) +{ + RefPtr thread = CacheFileIOManager::IOThread(); + MOZ_ASSERT(thread); + return thread->QueueSize(highPriority); +} + // Telementry collection namespace { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/cache2/CacheStorageService.h firefox-trunk-52.0~a1~hg20161113r322177/netwerk/cache2/CacheStorageService.h --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/cache2/CacheStorageService.h 2016-11-11 02:00:25.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/cache2/CacheStorageService.h 2016-11-14 01:58:21.000000000 +0000 @@ -111,6 +111,8 @@ // Invokes OnEntryInfo for the given aEntry, synchronously. static void GetCacheEntryInfo(CacheEntry* aEntry, EntryInfoCallback *aVisitor); + static uint32_t CacheQueueSize(bool highPriority); + // Memory reporting size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/cache2/nsICacheEntry.idl firefox-trunk-52.0~a1~hg20161113r322177/netwerk/cache2/nsICacheEntry.idl --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/cache2/nsICacheEntry.idl 2016-11-11 02:00:25.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/cache2/nsICacheEntry.idl 2016-11-14 01:58:21.000000000 +0000 @@ -174,6 +174,11 @@ void setValid(); /** + * Returns the size in kilobytes used to store the cache entry on disk. + */ + readonly attribute uint32_t diskStorageSizeInKB; + + /** * Doom this entry and open a new, empty, entry for write. Consumer has * to exchange the entry this method is called on for the newly created. * Used on 200 responses to conditional requests. diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/cache2/OldWrappers.h firefox-trunk-52.0~a1~hg20161113r322177/netwerk/cache2/OldWrappers.h --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/cache2/OldWrappers.h 2016-11-11 02:00:25.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/cache2/OldWrappers.h 2016-11-14 01:58:21.000000000 +0000 @@ -105,6 +105,11 @@ mOldDesc->SetMetaDataElement(key, value); } + NS_IMETHOD GetDiskStorageSizeInKB(uint32_t *aDiskStorageSize) override + { + return NS_ERROR_NOT_IMPLEMENTED; + } + // nsICacheEntryInfo NS_IMETHOD GetKey(nsACString & aKey) override { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/about/nsAboutCacheEntry.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/about/nsAboutCacheEntry.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/about/nsAboutCacheEntry.cpp 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/about/nsAboutCacheEntry.cpp 2016-11-14 01:58:23.000000000 +0000 @@ -386,7 +386,7 @@ buffer.AppendLiteral("\">"); buffer.Append(escapedStr); buffer.AppendLiteral(""); - uri = 0; + uri = nullptr; } else { buffer.Append(escapedStr); } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/about/nsAboutProtocolHandler.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/about/nsAboutProtocolHandler.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/about/nsAboutProtocolHandler.cpp 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/about/nsAboutProtocolHandler.cpp 2016-11-14 01:58:23.000000000 +0000 @@ -67,7 +67,7 @@ NS_IMETHODIMP nsAboutProtocolHandler::GetProtocolFlags(uint32_t *result) { - *result = URI_NORELATIVE | URI_NOAUTH | URI_DANGEROUS_TO_LOAD; + *result = URI_NORELATIVE | URI_NOAUTH | URI_DANGEROUS_TO_LOAD | URI_SCHEME_NOT_SELF_LINKABLE; return NS_OK; } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/ftp/nsFtpControlConnection.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/ftp/nsFtpControlConnection.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/ftp/nsFtpControlConnection.cpp 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/ftp/nsFtpControlConnection.cpp 2016-11-14 01:58:24.000000000 +0000 @@ -161,7 +161,7 @@ if (NS_FAILED(status)) { // break cyclic reference! mSocket->Close(status); - mSocket = 0; + mSocket = nullptr; mSocketInput->AsyncWait(nullptr, 0, 0, nullptr); // clear any observer mSocketInput = nullptr; mSocketOutput = nullptr; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/http/HttpChannelChild.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/http/HttpChannelChild.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/http/HttpChannelChild.cpp 2016-11-11 02:01:07.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/http/HttpChannelChild.cpp 2016-11-14 01:58:26.000000000 +0000 @@ -977,8 +977,8 @@ } mOnStopRequestCalled = true; - mListener = 0; - mListenerContext = 0; + mListener = nullptr; + mListenerContext = nullptr; mCacheEntryAvailable = false; if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, mStatus); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/http/HttpChannelParent.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/http/HttpChannelParent.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/http/HttpChannelParent.cpp 2016-11-11 02:01:22.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/http/HttpChannelParent.cpp 2016-11-14 01:58:26.000000000 +0000 @@ -788,7 +788,7 @@ { // From now on only using mAssociatedContentSecurity. Free everything else. mChannel = nullptr; // Reclaim some memory sooner. - mCacheEntry = 0; // Else we'll block other channels reading same URI + mCacheEntry = nullptr; // Else we'll block other channels reading same URI return true; } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/http/nsHttpChannel.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/http/nsHttpChannel.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/http/nsHttpChannel.cpp 2016-11-11 02:01:30.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/http/nsHttpChannel.cpp 2016-11-14 01:59:27.000000000 +0000 @@ -101,6 +101,7 @@ #include "CacheControlParser.h" #include "nsMixedContentBlocker.h" #include "HSTSPrimerListener.h" +#include "CacheStorageService.h" namespace mozilla { namespace net { @@ -242,6 +243,8 @@ , mOfflineCacheLastModifiedTime(0) , mInterceptCache(DO_NOT_INTERCEPT) , mInterceptionID(gNumIntercepted++) + , mCacheOpenWithPriority(false) + , mCacheQueueSizeWhenOpen(0) , mCachedContentIsValid(false) , mCachedContentIsPartial(false) , mCacheOnlyMetadata(false) @@ -3566,6 +3569,10 @@ MOZ_ASSERT(NS_SUCCEEDED(cacheStorage->Exists(openURI, extension, &exists)) && exists, "The entry must exist in the cache after we create it here"); } + + mCacheOpenWithPriority = cacheEntryOpenFlags & nsICacheStorage::OPEN_PRIORITY; + mCacheQueueSizeWhenOpen = CacheStorageService::CacheQueueSize(mCacheOpenWithPriority); + rv = cacheStorage->AsyncOpenURI(openURI, extension, cacheEntryOpenFlags, this); NS_ENSURE_SUCCESS(rv, rv); } @@ -6369,6 +6376,7 @@ "If we have both pumps, the cache content must be partial"); mAfterOnStartRequestBegun = true; + mOnStartRequestTimestamp = TimeStamp::Now(); if (!mSecurityInfo && !mCachePump && mTransaction) { // grab the security info from the connection object; the transaction @@ -6526,6 +6534,8 @@ if (mTimingEnabled && request == mCachePump) { mCacheReadEnd = TimeStamp::Now(); + + ReportNetVSCacheTelemetry(); } // allow content to be cached if it was loaded successfully (bug #482935) @@ -6606,6 +6616,20 @@ mTransferSize = mTransaction->GetTransferSize(); + // If we are using the transaction to serve content, we also save the + // time since async open in the cache entry so we can compare telemetry + // between cache and net response. + if (request == mTransactionPump && mCacheEntry && + !mAsyncOpenTime.IsNull() && !mOnStartRequestTimestamp.IsNull()) { + nsAutoCString onStartTime; + onStartTime.AppendInt( (uint64_t) (mOnStartRequestTimestamp - mAsyncOpenTime).ToMilliseconds()); + mCacheEntry->SetMetaDataElement("net-response-time-onstart", onStartTime.get()); + + nsAutoCString responseTime; + responseTime.AppendInt( (uint64_t) (TimeStamp::Now() - mAsyncOpenTime).ToMilliseconds()); + mCacheEntry->SetMetaDataElement("net-response-time-onstop", responseTime.get()); + } + // at this point, we're done with the transaction mTransactionTimings = mTransaction->Timings(); mTransaction = nullptr; @@ -7978,10 +8002,12 @@ HSTSPrimingResult::eHSTS_PRIMING_FAILED_ACCEPT); } - // Don't visit again for at least one day + // Don't visit again for at least + // security.mixed_content.hsts_priming_cache_timeout seconds. nsISiteSecurityService* sss = gHttpHandler->GetSSService(); NS_ENSURE_TRUE(sss, NS_ERROR_OUT_OF_MEMORY); - nsresult rv = sss->CacheNegativeHSTSResult(mURI, 24 * 60 * 60); + nsresult rv = sss->CacheNegativeHSTSResult(mURI, + nsMixedContentBlocker::sHSTSPrimingCacheTimeout); if (NS_FAILED(rv)) { NS_ERROR("nsISiteSecurityService::CacheNegativeHSTSResult failed"); } @@ -8153,5 +8179,134 @@ } } + +void +nsHttpChannel::ReportNetVSCacheTelemetry() +{ + nsresult rv; + if (!mCacheEntry) { + return; + } + + // We only report telemetry if the entry is persistent (on disk) + bool persistent; + rv = mCacheEntry->GetPersistent(&persistent); + if (NS_FAILED(rv) || !persistent) { + return; + } + + nsXPIDLCString tmpStr; + rv = mCacheEntry->GetMetaDataElement("net-response-time-onstart", + getter_Copies(tmpStr)); + if (NS_FAILED(rv)) { + return; + } + uint64_t onStartNetTime = tmpStr.ToInteger64(&rv); + if (NS_FAILED(rv)) { + return; + } + + tmpStr.Truncate(); + rv = mCacheEntry->GetMetaDataElement("net-response-time-onstop", + getter_Copies(tmpStr)); + if (NS_FAILED(rv)) { + return; + } + uint64_t onStopNetTime = tmpStr.ToInteger64(&rv); + if (NS_FAILED(rv)) { + return; + } + + uint64_t onStartCacheTime = (mOnStartRequestTimestamp - mAsyncOpenTime).ToMilliseconds(); + int64_t onStartDiff = onStartNetTime - onStartCacheTime; + onStartDiff += 500; // We offset the difference by 500 ms to report positive values in telemetry + + uint64_t onStopCacheTime = (mCacheReadEnd - mAsyncOpenTime).ToMilliseconds(); + int64_t onStopDiff = onStopNetTime - onStopCacheTime; + onStopDiff += 500; // We offset the difference by 500 ms + + if (mDidReval) { + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_REVALIDATED, onStartDiff); + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_REVALIDATED, onStopDiff); + } else { + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_NOTREVALIDATED, onStartDiff); + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_NOTREVALIDATED, onStopDiff); + } + + if (mDidReval) { + // We don't report revalidated probes as the data would be skewed. + return; + } + + uint32_t diskStorageSizeK = 0; + rv = mCacheEntry->GetDiskStorageSizeInKB(&diskStorageSizeK); + if (NS_FAILED(rv)) { + return; + } + + nsAutoCString contentType; + if (mResponseHead && mResponseHead->HasContentType()) { + mResponseHead->ContentType(contentType); + } + bool isImage = StringBeginsWith(contentType, NS_LITERAL_CSTRING("image/")); + if (isImage) { + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_ISIMG, onStartDiff); + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_ISIMG, onStopDiff); + } else { + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_NOTIMG, onStartDiff); + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_NOTIMG, onStopDiff); + } + + if (mCacheOpenWithPriority) { + if (mCacheQueueSizeWhenOpen < 5) { + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_QSMALL_HIGHPRI, onStartDiff); + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_QSMALL_HIGHPRI, onStopDiff); + } else if (mCacheQueueSizeWhenOpen < 10) { + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_QMED_HIGHPRI, onStartDiff); + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_QMED_HIGHPRI, onStopDiff); + } else { + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_QBIG_HIGHPRI, onStartDiff); + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_QBIG_HIGHPRI, onStopDiff); + } + } else { // The limits are higher for normal priority cache queues + if (mCacheQueueSizeWhenOpen < 10) { + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_QSMALL_NORMALPRI, onStartDiff); + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_QSMALL_NORMALPRI, onStopDiff); + } else if (mCacheQueueSizeWhenOpen < 50) { + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_QMED_NORMALPRI, onStartDiff); + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_QMED_NORMALPRI, onStopDiff); + } else { + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_QBIG_NORMALPRI, onStartDiff); + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_QBIG_NORMALPRI, onStopDiff); + } + } + + if (diskStorageSizeK < 32) { + if (mCacheOpenWithPriority) { + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_SMALL_HIGHPRI, onStartDiff); + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_SMALL_HIGHPRI, onStopDiff); + } else { + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_SMALL_NORMALPRI, onStartDiff); + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_SMALL_NORMALPRI, onStopDiff); + } + } else if (diskStorageSizeK < 256) { + if (mCacheOpenWithPriority) { + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_MED_HIGHPRI, onStartDiff); + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_MED_HIGHPRI, onStopDiff); + } else { + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_MED_NORMALPRI, onStartDiff); + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_MED_NORMALPRI, onStopDiff); + } + } else { + if (mCacheOpenWithPriority) { + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_LARGE_HIGHPRI, onStartDiff); + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_LARGE_HIGHPRI, onStopDiff); + } else { + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTART_LARGE_NORMALPRI, onStartDiff); + Telemetry::Accumulate(Telemetry::HTTP_NET_VS_CACHE_ONSTOP_LARGE_NORMALPRI, onStopDiff); + } + } +} + } // namespace net } // namespace mozilla diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/http/nsHttpChannel.h firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/http/nsHttpChannel.h --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/http/nsHttpChannel.h 2016-11-11 02:01:30.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/http/nsHttpChannel.h 2016-11-14 01:59:27.000000000 +0000 @@ -429,6 +429,9 @@ rv == NS_ERROR_MALFORMED_URI; } + // Report net vs cache time telemetry + void ReportNetVSCacheTelemetry(); + // Create a aggregate set of the current notification callbacks // and ensure the transaction is updated to use it. void UpdateAggregateCallbacks(); @@ -484,6 +487,8 @@ // auth specific data nsCOMPtr mAuthProvider; + mozilla::TimeStamp mOnStartRequestTimestamp; + // States of channel interception enum { DO_NOT_INTERCEPT, // no interception will occur @@ -513,6 +518,9 @@ static const uint32_t WAIT_FOR_CACHE_ENTRY = 1; static const uint32_t WAIT_FOR_OFFLINE_CACHE_ENTRY = 2; + bool mCacheOpenWithPriority; + uint32_t mCacheQueueSizeWhenOpen; + // state flags uint32_t mCachedContentIsValid : 1; uint32_t mCachedContentIsPartial : 1; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/http/nsHttpConnectionMgr.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/http/nsHttpConnectionMgr.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/http/nsHttpConnectionMgr.cpp 2016-11-11 02:01:32.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/http/nsHttpConnectionMgr.cpp 2016-11-14 01:59:27.000000000 +0000 @@ -178,7 +178,7 @@ // from being posted. this is how we indicate that we are // shutting down. mIsShuttingDown = true; - mSocketThreadTarget = 0; + mSocketThreadTarget = nullptr; if (NS_FAILED(rv)) { NS_WARNING("unable to post SHUTDOWN message"); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/http/nsHttpNTLMAuth.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/http/nsHttpNTLMAuth.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/http/nsHttpNTLMAuth.cpp 2016-11-11 02:01:40.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/http/nsHttpNTLMAuth.cpp 2016-11-14 01:59:28.000000000 +0000 @@ -37,6 +37,7 @@ static const char kAllowNonFqdn[] = "network.automatic-ntlm-auth.allow-non-fqdn"; static const char kTrustedURIs[] = "network.automatic-ntlm-auth.trusted-uris"; static const char kForceGeneric[] = "network.auth.force-generic-ntlm"; +static const char kSSOinPBmode[] = "network.auth.private-browsing-sso"; // XXX MatchesBaseURI and TestPref are duplicated in nsHttpNegotiateAuth.cpp, // but since that file lives in a separate library we cannot directly share it. @@ -188,35 +189,41 @@ bool isProxyAuth) { nsCOMPtr prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); + if (!prefs) { + return false; + } + + // Proxy should go all the time, it's not considered a privacy leak + // to send default credentials to a proxy. + if (isProxyAuth) { + bool val; + if (NS_FAILED(prefs->GetBoolPref(kAllowProxies, &val))) + val = false; + LOG(("Default credentials allowed for proxy: %d\n", val)); + return val; + } // Prevent using default credentials for authentication when we are in the - // private browsing mode. It would cause a privacy data leak. + // private browsing mode (but not in "never remember history" mode) and when + // not explicitely allowed. Otherwise, it would cause a privacy data leak. nsCOMPtr bareChannel = do_QueryInterface(channel); MOZ_ASSERT(bareChannel); if (NS_UsePrivateBrowsing(bareChannel)) { - // But allow when in the "Never remember history" mode. + bool ssoInPb; + if (NS_SUCCEEDED(prefs->GetBoolPref(kSSOinPBmode, &ssoInPb)) && + ssoInPb) { + return true; + } + bool dontRememberHistory; - if (prefs && - NS_SUCCEEDED(prefs->GetBoolPref("browser.privatebrowsing.autostart", + if (NS_SUCCEEDED(prefs->GetBoolPref("browser.privatebrowsing.autostart", &dontRememberHistory)) && !dontRememberHistory) { return false; } } - if (!prefs) { - return false; - } - - if (isProxyAuth) { - bool val; - if (NS_FAILED(prefs->GetBoolPref(kAllowProxies, &val))) - val = false; - LOG(("Default credentials allowed for proxy: %d\n", val)); - return val; - } - nsCOMPtr uri; channel->GetURI(getter_AddRefs(uri)); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/http/nsHttpTransaction.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/http/nsHttpTransaction.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/http/nsHttpTransaction.cpp 2016-11-11 02:01:41.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/http/nsHttpTransaction.cpp 2016-11-14 01:59:28.000000000 +0000 @@ -1298,7 +1298,7 @@ seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0); // clear old connection state... - mSecurityInfo = 0; + mSecurityInfo = nullptr; if (mConnection) { if (!mReuseOnRestart) { mConnection->DontReuse(); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp 2016-11-11 02:01:42.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp 2016-11-14 01:59:29.000000000 +0000 @@ -572,13 +572,13 @@ if (mCacheEntry) { LOG(("nsWyciwygChannel::CloseCacheEntryInternal [this=%p ]", this)); - mCacheOutputStream = 0; - mCacheInputStream = 0; + mCacheOutputStream = nullptr; + mCacheInputStream = nullptr; if (NS_FAILED(reason)) mCacheEntry->AsyncDoom(nullptr); // here we were calling Doom() ... - mCacheEntry = 0; + mCacheEntry = nullptr; } return NS_OK; } @@ -756,19 +756,19 @@ mStatus = status; mListener->OnStopRequest(this, mListenerContext, mStatus); - mListener = 0; - mListenerContext = 0; + mListener = nullptr; + mListenerContext = nullptr; if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, mStatus); CloseCacheEntry(mStatus); - mPump = 0; + mPump = nullptr; mIsPending = false; // Drop notification callbacks to prevent cycles. - mCallbacks = 0; - mProgressSink = 0; + mCallbacks = nullptr; + mProgressSink = nullptr; return NS_OK; } @@ -854,8 +854,8 @@ if (mListener) { mListener->OnStartRequest(this, mListenerContext); mListener->OnStopRequest(this, mListenerContext, mStatus); - mListener = 0; - mListenerContext = 0; + mListener = nullptr; + mListenerContext = nullptr; } mIsPending = false; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp 2016-11-11 02:01:42.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp 2016-11-14 01:59:29.000000000 +0000 @@ -291,14 +291,14 @@ mListener->OnStopRequest(this, mListenerContext, statusCode); - mListener = 0; - mListenerContext = 0; + mListener = nullptr; + mListenerContext = nullptr; if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, mStatus); - mCallbacks = 0; - mProgressSink = 0; + mCallbacks = nullptr; + mProgressSink = nullptr; } if (mIPCOpen) diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/streamconv/converters/nsBinHexDecoder.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/streamconv/converters/nsBinHexDecoder.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/streamconv/converters/nsBinHexDecoder.cpp 2016-11-11 02:01:43.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/streamconv/converters/nsBinHexDecoder.cpp 2016-11-14 01:59:30.000000000 +0000 @@ -274,7 +274,7 @@ { // when we reach the finished state...fire an on stop request on the event listener... mNextListener->OnStopRequest(aRequest, aContext, NS_OK); - mNextListener = 0; + mNextListener = nullptr; /* now We are done with everything. */ ++mState; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/streamconv/converters/nsIndexedToHTML.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/streamconv/converters/nsIndexedToHTML.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/streamconv/converters/nsIndexedToHTML.cpp 2016-11-11 02:01:44.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/streamconv/converters/nsIndexedToHTML.cpp 2016-11-14 01:59:30.000000000 +0000 @@ -665,7 +665,7 @@ } mParser->OnStopRequest(request, aContext, aStatus); - mParser = 0; + mParser = nullptr; return mListener->OnStopRequest(request, aContext, aStatus); } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/netwerk/streamconv/converters/nsUnknownDecoder.cpp firefox-trunk-52.0~a1~hg20161113r322177/netwerk/streamconv/converters/nsUnknownDecoder.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/netwerk/streamconv/converters/nsUnknownDecoder.cpp 2016-11-11 02:01:44.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/netwerk/streamconv/converters/nsUnknownDecoder.cpp 2016-11-14 01:59:30.000000000 +0000 @@ -299,7 +299,7 @@ } rv = mNextListener->OnStopRequest(request, aCtxt, aStatus); - mNextListener = 0; + mNextListener = nullptr; return rv; } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/parser/htmlparser/nsParser.cpp firefox-trunk-52.0~a1~hg20161113r322177/parser/htmlparser/nsParser.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/parser/htmlparser/nsParser.cpp 2016-11-11 02:04:40.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/parser/htmlparser/nsParser.cpp 2016-11-14 02:03:27.000000000 +0000 @@ -910,7 +910,7 @@ } //Ref. to bug 61462. - mParserContext->mRequest = 0; + mParserContext->mRequest = nullptr; } } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/parser/htmlparser/nsScanner.cpp firefox-trunk-52.0~a1~hg20161113r322177/parser/htmlparser/nsScanner.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/parser/htmlparser/nsScanner.cpp 2016-11-11 02:04:40.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/parser/htmlparser/nsScanner.cpp 2016-11-14 02:03:27.000000000 +0000 @@ -67,7 +67,7 @@ } mMarkPosition = mCurrentPosition; mIncremental = false; - mUnicodeDecoder = 0; + mUnicodeDecoder = nullptr; mCharsetSource = kCharsetUninitialized; mHasInvalidCharacter = false; mReplacementCharacter = char16_t(0x0); @@ -99,7 +99,7 @@ mFirstNonWhitespacePosition = -1; mCountRemaining = 0; - mUnicodeDecoder = 0; + mUnicodeDecoder = nullptr; mCharsetSource = kCharsetUninitialized; mHasInvalidCharacter = false; mReplacementCharacter = char16_t(0x0); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/manager/ssl/nsNSSCertHelper.cpp firefox-trunk-52.0~a1~hg20161113r322177/security/manager/ssl/nsNSSCertHelper.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/security/manager/ssl/nsNSSCertHelper.cpp 2016-11-11 02:09:20.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/manager/ssl/nsNSSCertHelper.cpp 2016-11-14 02:10:11.000000000 +0000 @@ -1884,7 +1884,7 @@ validityData->GetNotBefore(¬Before); validityData->GetNotAfter(¬After); - validityData = 0; + validityData = nullptr; rv = ProcessTime(notBefore, text.get(), validitySequence); if (NS_FAILED(rv)) return rv; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/manager/ssl/nsPKCS12Blob.cpp firefox-trunk-52.0~a1~hg20161113r322177/security/manager/ssl/nsPKCS12Blob.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/security/manager/ssl/nsPKCS12Blob.cpp 2016-11-11 02:09:20.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/manager/ssl/nsPKCS12Blob.cpp 2016-11-14 02:10:13.000000000 +0000 @@ -42,7 +42,7 @@ #define PIP_PKCS12_NSS_ERROR 7 // constructor -nsPKCS12Blob::nsPKCS12Blob():mCertArray(0), +nsPKCS12Blob::nsPKCS12Blob():mCertArray(nullptr), mTmpFile(nullptr), mTokenSet(false) { @@ -77,7 +77,7 @@ PK11SlotInfo *slot; rv = GetSlotWithMechanism(CKM_RSA_PKCS, mUIContext, &slot, locker); if (NS_FAILED(rv)) { - mToken = 0; + mToken = nullptr; } else { mToken = new nsPK11Token(slot); PK11_FreeSlot(slot); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/manager/ssl/nsSTSPreloadList.errors firefox-trunk-52.0~a1~hg20161113r322177/security/manager/ssl/nsSTSPreloadList.errors --- firefox-trunk-52.0~a1~hg20161110r321971/security/manager/ssl/nsSTSPreloadList.errors 2016-11-11 02:09:20.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/manager/ssl/nsSTSPreloadList.errors 2016-11-14 02:10:13.000000000 +0000 @@ -16,7 +16,6 @@ 1password.com: did not receive HSTS header 1whw.co.uk: could not connect to host 206rc.net: max-age too low: 2592000 -20hs.cn: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no] 24hourpaint.com: did not receive HSTS header 25daysof.io: could not connect to host 2859cc.com: could not connect to host @@ -49,7 +48,6 @@ a-plus.space: could not connect to host a9c.co: could not connect to host aapp.space: could not connect to host -aaronkimmig.de: could not connect to host abearofsoap.com: did not receive HSTS header abecodes.net: did not receive HSTS header abilitylist.org: did not receive HSTS header @@ -92,9 +90,9 @@ adquisitio.it: could not connect to host adsfund.org: could not connect to host advancedstudio.ro: did not receive HSTS header +adver.top: could not connect to host adviespuntklokkenluiders.nl: did not receive HSTS header aemoria.com: could not connect to host -aerelon.de: could not connect to host aes256.ru: did not receive HSTS header aether.pw: could not connect to host aevpn.net: could not connect to host @@ -139,6 +137,7 @@ alexismeza.com.mx: could not connect to host alexismeza.dk: could not connect to host alfredxing.com: did not receive HSTS header +alittlebitcheeky.com: did not receive HSTS header alkami.com: did not receive HSTS header all-subtitles.com: did not receive HSTS header allforyou.at: could not connect to host @@ -148,11 +147,9 @@ alphabit-secure.com: could not connect to host alphabuild.io: did not receive HSTS header alphalabs.xyz: could not connect to host -alterbaum.net: did not receive HSTS header altfire.ca: could not connect to host altmv.com: max-age too low: 7776000 amaforums.org: could not connect to host -ambiente.one: could not connect to host american-truck-simulator.de: could not connect to host american-truck-simulator.net: could not connect to host americanworkwear.nl: did not receive HSTS header @@ -164,6 +161,7 @@ amri.nl: did not receive HSTS header anakros.me: did not receive HSTS header analytic-s.ml: could not connect to host +ananke.io: could not connect to host anarchistischegroepnijmegen.nl: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no] anassiriphotography.com: could not connect to host ancientkarma.com: could not connect to host @@ -171,6 +169,7 @@ andreasbreitenlohner.de: did not receive HSTS header andreasolsson.se: could not connect to host andreigec.net: did not receive HSTS header +andrewimeson.com: could not connect to host andrewmichaud.beer: could not connect to host andreypopp.com: could not connect to host androoz.se: could not connect to host @@ -257,6 +256,7 @@ attimidesigns.com: did not receive HSTS header au.search.yahoo.com: max-age too low: 172800 aubiosales.com: did not receive HSTS header +augias.org: could not connect to host aujapan.ru: could not connect to host aurainfosec.com.au: could not connect to host ausnah.me: could not connect to host @@ -270,7 +270,7 @@ automacity.com: could not connect to host autotsum.com: could not connect to host autumnwindsagility.com: could not connect to host -auverbox.ovh: did not receive HSTS header +auverbox.ovh: could not connect to host av.de: did not receive HSTS header avec-ou-sans-ordonnance.fr: could not connect to host avinet.com: max-age too low: 0 @@ -282,7 +282,7 @@ b3orion.com: max-age too low: 0 babak.de: did not receive HSTS header babelfisch.eu: did not receive HSTS header -baby-click.de: could not connect to host +baby-click.de: did not receive HSTS header babybic.hu: did not receive HSTS header babyhouse.xyz: could not connect to host babysaying.me: could not connect to host @@ -294,6 +294,7 @@ balcan-underground.net: could not connect to host baldwinkoo.com: could not connect to host bandb.xyz: could not connect to host +bangzafran.com: could not connect to host bannisbierblog.de: could not connect to host barely.sexy: did not receive HSTS header bashcode.ninja: could not connect to host @@ -334,8 +335,8 @@ betafive.net: could not connect to host betnet.fr: could not connect to host betplanning.it: did not receive HSTS header -bets.de: did not receive HSTS header -bettween.com: did not receive HSTS header +bets.de: could not connect to host +bettween.com: could not connect to host betz.ro: did not receive HSTS header bevapehappy.com: did not receive HSTS header bezorg.ninja: could not connect to host @@ -384,7 +385,6 @@ black-armada.com.pl: could not connect to host black-armada.pl: could not connect to host blackburn.link: did not receive HSTS header -blackdragoninc.org: could not connect to host blacklane.com: did not receive HSTS header blackly.uk: could not connect to host blackpayment.ru: could not connect to host @@ -405,7 +405,6 @@ bobiji.com: did not receive HSTS header bodyblog.nl: did not receive HSTS header bodybuilding-legends.com: could not connect to host -bodyweightsolution.com: did not receive HSTS header boensou.com: did not receive HSTS header bogosity.se: could not connect to host bohan.life: could not connect to host @@ -434,18 +433,17 @@ branchtrack.com: did not receive HSTS header branchzero.com: did not receive HSTS header brandon.so: could not connect to host +brandonwalker.me: could not connect to host +brandred.net: did not receive HSTS header brianmwaters.net: could not connect to host brickoo.com: could not connect to host brideandgroomdirect.ie: did not receive HSTS header -bristebein.com: did not receive HSTS header brks.xyz: could not connect to host broken-oak.com: could not connect to host brokenhands.io: did not receive HSTS header brookechase.com: did not receive HSTS header browserid.org: did not receive HSTS header brunix.net: did not receive HSTS header -brunoramos.com: could not connect to host -brunoramos.org: could not connect to host bsagan.fr: could not connect to host bsalyzer.com: could not connect to host bsdtips.com: could not connect to host @@ -492,6 +490,7 @@ cake.care: could not connect to host calgaryconstructionjobs.com: could not connect to host calix.com: max-age too low: 0 +call.me: did not receive HSTS header calltrackingreports.com: could not connect to host calvin.me: max-age too low: 2592000 calvinallen.net: could not connect to host @@ -539,6 +538,7 @@ cerize.love: could not connect to host cert.se: max-age too low: 2628001 certmgr.org: could not connect to host +certnazionale.it: could not connect to host cesal.net: could not connect to host cesidianroot.eu: could not connect to host cevrimici.com: could not connect to host @@ -547,6 +547,7 @@ cg.search.yahoo.com: did not receive HSTS header chainmonitor.com: could not connect to host chamathellawala.com: did not receive HSTS header +chamilo.org: could not connect to host championsofregnum.com: did not receive HSTS header chandlerredding.com: did not receive HSTS header changelab.cc: max-age too low: 0 @@ -565,7 +566,6 @@ cheesetart.my: could not connect to host chejianer.cn: did not receive HSTS header cherysunzhang.com: max-age too low: 7776000 -chestnut.cf: could not connect to host chihiro.xyz: could not connect to host chijiokeindustries.co.uk: did not receive HSTS header childcaresolutionscny.org: did not receive HSTS header @@ -614,6 +614,7 @@ cloudstoragemaus.com: could not connect to host cloudwalk.io: did not receive HSTS header cloverleaf.net: max-age too low: 0 +clywedogmaths.co.uk: could not connect to host cmacacias.ch: did not receive HSTS header cmc-versand.de: did not receive HSTS header cmci.dk: did not receive HSTS header @@ -625,11 +626,12 @@ cmscafe.ru: did not receive HSTS header cn.search.yahoo.com: did not receive HSTS header co50.com: did not receive HSTS header +coam.co: did not receive HSTS header cocaine-import.agency: could not connect to host +cocolovesdaddy.com: could not connect to host codabix.com: did not receive HSTS header codabix.de: could not connect to host codabix.net: could not connect to host -code.fm: could not connect to host code.google.com: did not receive HSTS header (error ignored - included regardless) codeco.pw: could not connect to host codeforce.io: did not receive HSTS header @@ -661,7 +663,6 @@ conrad-kostecki.de: did not receive HSTS header consciousandglamorous.com: could not connect to host console.python.org: did not receive HSTS header -console.support: could not connect to host constructionjobs.com: did not receive HSTS header content-api-dev.azurewebsites.net: could not connect to host continuumgaming.com: could not connect to host @@ -688,11 +689,11 @@ coursella.com: did not receive HSTS header covenantbank.net: could not connect to host coverduck.ru: could not connect to host -cqchome.com: could not connect to host cr.search.yahoo.com: did not receive HSTS header cracking.org: did not receive HSTS header craftbeerbarn.co.uk: could not connect to host craftedge.xyz: could not connect to host +cranesafe.com: could not connect to host crate.io: did not receive HSTS header cravelyrics.com: did not receive HSTS header crazycen.com: did not receive HSTS header @@ -704,14 +705,12 @@ criena.net: could not connect to host crizk.com: could not connect to host crosssec.com: did not receive HSTS header -crow.tw: could not connect to host crowd.supply: could not connect to host crowdcurity.com: did not receive HSTS header crowdjuris.com: could not connect to host crtvmgmt.com: could not connect to host crudysql.com: could not connect to host cruzr.xyz: could not connect to host -crvv.me: could not connect to host crypt.guru: could not connect to host cryptify.eu: did not receive HSTS header cryptobin.org: could not connect to host @@ -722,7 +721,6 @@ crystalclassics.co.uk: did not receive HSTS header csapak.com: max-age too low: 0 csawctf.poly.edu: could not connect to host -cselzer.com: could not connect to host csfs.org.uk: could not connect to host csgodicegame.com: did not receive HSTS header csgoelemental.com: could not connect to host @@ -735,6 +733,7 @@ cubewano.com: could not connect to host cujanovic.com: did not receive HSTS header cumshots-video.ru: could not connect to host +cuongquach.com: could not connect to host cupidmentor.com: did not receive HSTS header curroapp.com: could not connect to host custe.rs: could not connect to host @@ -808,7 +807,6 @@ democracychronicles.com: did not receive HSTS header denh.am: did not receive HSTS header denisjean.fr: could not connect to host -dennisdoes.net: did not receive HSTS header dentaldomain.org: did not receive HSTS header dentaldomain.ph: did not receive HSTS header depijl-mz.nl: did not receive HSTS header @@ -819,6 +817,7 @@ desiccantpackets.com: did not receive HSTS header destinationbijoux.fr: could not connect to host detector.exposed: could not connect to host +detutorial.com: could not connect to host deux.solutions: could not connect to host deuxsol.com: could not connect to host deuxsolutions.com: could not connect to host @@ -838,7 +837,6 @@ digitalriver.tk: could not connect to host digitalskillswap.com: could not connect to host dinamoelektrik.com: max-age too low: 0 -dipl.io: did not receive HSTS header discoveringdocker.com: did not receive HSTS header discovery.lookout.com: did not receive HSTS header dislocated.de: did not receive HSTS header @@ -848,6 +846,7 @@ dizorg.net: could not connect to host dj4et.de: could not connect to host dl.google.com: did not receive HSTS header (error ignored - included regardless) +dmxledlights.com: could not connect to host dn42.eu: could not connect to host dns.google.com: did not receive HSTS header (error ignored - included regardless) do-do.tk: could not connect to host @@ -864,10 +863,8 @@ dolphin-cloud.com: could not connect to host dolphincorp.co.uk: could not connect to host domaris.de: did not receive HSTS header -dominikkulaga.pl: did not receive HSTS header dominique-mueller.de: did not receive HSTS header donzelot.co.uk: max-age too low: 3600 -doobydude.us: could not connect to host doomleika.com: could not connect to host dopost.it: could not connect to host doridian.com: could not connect to host @@ -879,7 +876,7 @@ dougferris.id.au: could not connect to host download.jitsi.org: did not receive HSTS header downsouthweddings.com.au: did not receive HSTS header -doyoucheck.com: did not receive HSTS header +doyoucheck.com: could not connect to host dpratt.de: could not connect to host dprd-wonogirikab.go.id: did not receive HSTS header dragonisles.net: could not connect to host @@ -901,6 +898,7 @@ dshiv.io: could not connect to host dubrovskiy.net: could not connect to host dubrovskiy.pro: could not connect to host +duch.cloud: could not connect to host duesee.org: could not connect to host duria.de: max-age too low: 3600 dustri.org: did not receive HSTS header @@ -915,7 +913,6 @@ e-deca2.org: did not receive HSTS header earga.sm: could not connect to host earlybirdsnacks.com: did not receive HSTS header -easychiller.org: could not connect to host easyhaul.com: did not receive HSTS header eatlowcarb.de: did not receive HSTS header eauclairecommerce.com: could not connect to host @@ -928,7 +925,6 @@ ecdn.cz: could not connect to host ecfs.link: could not connect to host ecg.fr: could not connect to host -echopaper.com: did not receive HSTS header echosystem.fr: did not receive HSTS header ecole-en-danger.fr: could not connect to host ecorus.eu: did not receive HSTS header @@ -949,7 +945,6 @@ ekostecki.de: did not receive HSTS header elaintehtaat.fi: did not receive HSTS header elanguest.pl: could not connect to host -eldinhadzic.com: could not connect to host electricianforum.co.uk: could not connect to host electromc.com: could not connect to host elemprendedor.com.ve: could not connect to host @@ -983,6 +978,7 @@ englishforums.com: could not connect to host enigmail.net: did not receive HSTS header enteente.club: could not connect to host +enteente.com: could not connect to host enteente.space: could not connect to host enteente.xyz: could not connect to host enterdev.co: did not receive HSTS header @@ -1019,16 +1015,16 @@ essexcosmeticdentists.co.uk: did not receive HSTS header essexghosthunters.co.uk: did not receive HSTS header estilosapeca.com: could not connect to host -et-buchholz.de: could not connect to host etdonline.co.uk: could not connect to host eternitylove.us: could not connect to host ethack.org: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no] +ethicalexploiting.com: could not connect to host etsysecure.com: could not connect to host etula.ga: could not connect to host etula.me: did not receive HSTS header euanbaines.com: could not connect to host eucl3d.com: did not receive HSTS header -euph.eu: did not receive HSTS header +euph.eu: could not connect to host euren.se: could not connect to host euroshop24.net: could not connect to host evantage.org: could not connect to host @@ -1109,6 +1105,7 @@ finanzkontor.net: could not connect to host findtutorsnearme.com: did not receive HSTS header finiteheap.com: could not connect to host +finpt.com: could not connect to host firebaseio-demo.com: could not connect to host firebaseio.com: could not connect to host (error ignored - included regardless) firefall.rocks: could not connect to host @@ -1118,8 +1115,10 @@ fit4medien.de: did not receive HSTS header fitnesswerk.de: could not connect to host fivestarsitters.com: did not receive HSTS header +fiws.net: could not connect to host fixatom.com: did not receive HSTS header fixingdns.com: did not receive HSTS header +fizz.buzz: could not connect to host fj.search.yahoo.com: did not receive HSTS header flags.ninja: could not connect to host flamewall.net: could not connect to host @@ -1133,7 +1132,6 @@ flow.su: could not connect to host flowersandclouds.com: could not connect to host flushstudios.com: did not receive HSTS header -fly.moe: could not connect to host flyaces.com: did not receive HSTS header flyss.net: did not receive HSTS header fm83.nl: did not receive HSTS header @@ -1141,7 +1139,6 @@ fnvsecurity.com: could not connect to host fonetiq.io: could not connect to host food4health.guide: could not connect to host -foodacademy.capetown: could not connect to host footballmapped.com: could not connect to host foraje-profesionale.ro: did not receive HSTS header forbook.net: could not connect to host @@ -1179,6 +1176,7 @@ friendica.ch: could not connect to host frizo.com: did not receive HSTS header froggstack.de: could not connect to host +frontisme.nl: could not connect to host frontmin.com: did not receive HSTS header frost-ci.xyz: could not connect to host fruitusers.com: could not connect to host @@ -1240,6 +1238,7 @@ getbooks.co.il: did not receive HSTS header getcarefirst.com: could not connect to host getcolor.com: did not receive HSTS header +getdigitized.net: could not connect to host getinternet.de: max-age too low: 0 getlantern.org: did not receive HSTS header getlifti.com: did not receive HSTS header @@ -1316,6 +1315,8 @@ grazetech.com: could not connect to host greenhillantiques.co.uk: did not receive HSTS header greenvines.com.tw: did not receive HSTS header +gregmilton.com: could not connect to host +gregmilton.org: could not connect to host gregorytlee.me: did not receive HSTS header gremots.com: did not receive HSTS header greplin.com: could not connect to host @@ -1329,7 +1330,8 @@ gtanda.tk: could not connect to host gtlfsonlinepay.com: did not receive HSTS header gtraxapp.com: could not connect to host -guava.studio: could not connect to host +guava.studio: did not receive HSTS header +guhenry3.tk: could not connect to host guilde-vindicta.fr: did not receive HSTS header gurusupe.com: could not connect to host gvt2.com: could not connect to host (error ignored - included regardless) @@ -1346,24 +1348,24 @@ haarkliniek.com: did not receive HSTS header habanaavenue.com: did not receive HSTS header hablemosdetecnologia.com.ve: could not connect to host +hack.cz: could not connect to host hack.li: could not connect to host hacker.one: could not connect to host hackerforever.com: did not receive HSTS header hackerone-ext-adroll.com: could not connect to host hackerpoints.com: could not connect to host +hackest.org: could not connect to host hackit.im: could not connect to host -hackmd.io: did not receive HSTS header hadzic.co: could not connect to host hahayidu.org: could not connect to host haitschi.com: could not connect to host haitschi.de: could not connect to host haitschi.net: could not connect to host haitschi.org: could not connect to host -hajnzic.at: could not connect to host haktec.de: could not connect to host haku.moe: could not connect to host hakugin.org: could not connect to host -halo.red: did not receive HSTS header +halo.red: could not connect to host hancc.net: did not receive HSTS header hannover-banditen.de: did not receive HSTS header hao2taiwan.com: max-age too low: 0 @@ -1425,7 +1427,6 @@ hiphopconvention.nl: could not connect to host hitoy.org: did not receive HSTS header hittipps.com: did not receive HSTS header -hjw-kunstwerk.de: could not connect to host hmm.nyc: could not connect to host hn.search.yahoo.com: did not receive HSTS header hoerbuecher-und-hoerspiele.de: could not connect to host @@ -1478,7 +1479,7 @@ icewoman.net: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no] ichnichtskaufmann.de: could not connect to host icreative.nl: did not receive HSTS header -ictual.com: max-age too low: 0 +ictual.com: could not connect to host icusignature.com: did not receive HSTS header id-co.in: could not connect to host id-conf.com: could not connect to host @@ -1495,6 +1496,8 @@ ies.id.lv: could not connect to host ifad.org: did not receive HSTS header ifleurs.com: could not connect to host +ifoss.me: could not connect to host +igforums.com: could not connect to host ignatisd.gr: did not receive HSTS header igule.net: could not connect to host ihrlotto.de: could not connect to host @@ -1508,7 +1511,6 @@ ilikerainbows.co.uk: could not connect to host ilmconpm.de: did not receive HSTS header ilona.graphics: max-age too low: 3600 -imanolbarba.net: could not connect to host ime.moe: could not connect to host imguoguo.com: did not receive HSTS header imim.pw: did not receive HSTS header @@ -1566,8 +1568,8 @@ intimtoy.com.ua: could not connect to host inverselink-user-content.com: could not connect to host inverselink.com: could not connect to host -invitescene.com: could not connect to host inwesttitle.com: max-age too low: 0 +ionc.ca: could not connect to host ionx.co.uk: did not receive HSTS header iop.intuit.com: max-age too low: 86400 iosmods.com: could not connect to host @@ -1598,12 +1600,12 @@ itfh.eu: could not connect to host itos.asia: did not receive HSTS header itos.pl: did not receive HSTS header -itpol.dk: could not connect to host its4living.com: could not connect to host itsadog.co.uk: did not receive HSTS header itsamurai.ru: max-age too low: 2592000 itsecurityassurance.pw: did not receive HSTS header itshost.ru: could not connect to host +ivancacic.com: could not connect to host ivi-fertility.com: max-age too low: 0 ivi.es: max-age too low: 0 ivk.website: could not connect to host @@ -1613,7 +1615,6 @@ ja-publications.com: did not receive HSTS header jaba.hosting: did not receive HSTS header jabbari.io: did not receive HSTS header -jabber.at: could not connect to host jackalworks.com: could not connect to host jacobparry.ca: did not receive HSTS header jahliveradio.com: could not connect to host @@ -1649,10 +1650,10 @@ jbbd.fr: could not connect to host jbfp.dk: could not connect to host jbn.mx: could not connect to host +jbradaric.me: could not connect to host jcch.de: could not connect to host jcor.me: could not connect to host jctf.io: could not connect to host -jdh8.org: could not connect to host jeff393.com: could not connect to host jenjoit.de: could not connect to host jensenbanden.no: could not connect to host @@ -1680,9 +1681,10 @@ joakimalgroy.com: could not connect to host jobmedic.com: did not receive HSTS header joedavison.me: could not connect to host -johnbrownphotography.ch: could not connect to host +johnbrownphotography.ch: did not receive HSTS header johners.me: could not connect to host johners.tech: did not receive HSTS header +johnhgaunt.com: did not receive HSTS header johnrom.com: did not receive HSTS header jonas-keidel.de: did not receive HSTS header jonasgroth.se: max-age too low: 2592000 @@ -1690,9 +1692,11 @@ jonathancarter.org: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no] jonn.me: could not connect to host joostbovee.nl: did not receive HSTS header +jordanhamilton.me: could not connect to host joretapo.fr: could not connect to host josahrens.me: could not connect to host joshstroup.me: could not connect to host +josip.at: could not connect to host jottit.com: could not connect to host jpbike.cz: could not connect to host jrc9.ca: did not receive HSTS header @@ -1719,12 +1723,12 @@ k-dev.de: could not connect to host ka-clan.com: could not connect to host kabuabc.com: did not receive HSTS header -kabus.org: could not connect to host kadioglumakina.com.tr: did not receive HSTS header kahopoon.net: could not connect to host kaisers.de: did not receive HSTS header kalami.nl: did not receive HSTS header kamikano.com: could not connect to host +kamitech.ch: could not connect to host kaplatz.is: could not connect to host kapucini.si: max-age too low: 0 karaoketonight.com: could not connect to host @@ -1755,14 +1759,13 @@ kickass.al: could not connect to host kid-dachau.de: did not receive HSTS header kiel-media.de: did not receive HSTS header -kilianvalkhof.com: did not receive HSTS header kimpost.org: could not connect to host kinderwagen-test24.de: could not connect to host kingmanhall.org: could not connect to host -kini24.ru: did not receive HSTS header kinnon.enterprises: could not connect to host kinogb.net: max-age too low: 0 kionetworks.com: did not receive HSTS header +kipira.com: could not connect to host kirkforcongress.com: could not connect to host kirkforsenate.com: did not receive HSTS header kirkpatrickdavis.com: could not connect to host @@ -1776,7 +1779,6 @@ kiwiirc.com: max-age too low: 5256000 kizil.net: could not connect to host kjaermaxi.me: did not receive HSTS header -kjellvn.net: did not receive HSTS header klauwd.com: did not receive HSTS header klaxn.org: could not connect to host kleertjesvoordelig.nl: could not connect to host @@ -1801,9 +1803,11 @@ kotonehoko.net: could not connect to host kotovstyle.ru: could not connect to host kr.search.yahoo.com: did not receive HSTS header +kraga.sk: could not connect to host kredite.sale: could not connect to host kriegt.es: could not connect to host krislamoureux.com: could not connect to host +kristofferkoch.com: could not connect to host krmela.com: could not connect to host kroetenfuchs.de: could not connect to host kropkait.pl: could not connect to host @@ -1819,7 +1823,7 @@ kusaka-abacus.jp: max-age too low: 0 kuschku.de: did not receive HSTS header kweddingplanning.com: did not receive HSTS header -kwok.tv: did not receive HSTS header +kwok.tv: could not connect to host kyanite.co: could not connect to host kylinj.com: could not connect to host kz.search.yahoo.com: did not receive HSTS header @@ -1834,7 +1838,6 @@ ladbroke.net: did not receive HSTS header laf.in.net: did not receive HSTS header lagalerievirtuelle.fr: did not receive HSTS header -lagarderob.ru: max-age too low: 0 lagoza.name: could not connect to host lambdafive.co.uk: could not connect to host lampl.info: did not receive HSTS header @@ -1857,7 +1860,6 @@ leardev.de: did not receive HSTS header learnfrenchfluently.com: did not receive HSTS header learningorder.com: could not connect to host -leaversmith.com: could not connect to host ledgerscope.net: could not connect to host leermotorrijden.nl: max-age too low: 300 legarage.org: did not receive HSTS header @@ -1892,6 +1894,7 @@ libertyrp.org: could not connect to host library.linode.com: did not receive HSTS header librechan.net: could not connect to host +libscode.com: did not receive HSTS header liduan.com: could not connect to host liduan.net: could not connect to host lifeguard.aecom.com: did not receive HSTS header @@ -1980,6 +1983,7 @@ macbolo.com: could not connect to host macchaberrycream.com: could not connect to host macchedil.com: did not receive HSTS header +macosxfilerecovery.com: did not receive HSTS header madars.org: did not receive HSTS header maddin.ga: could not connect to host madebymagnitude.com: did not receive HSTS header @@ -2005,9 +2009,9 @@ mannsolutions.co.uk: did not receive HSTS header mansion-note.com: could not connect to host marchagen.nl: did not receive HSTS header -marcoececilia.it: could not connect to host marcontrol.com: did not receive HSTS header marcuskoh.com: could not connect to host +mariannematthew.com: could not connect to host marie-curie.fr: could not connect to host markaconnor.com: could not connect to host markayapilandirma.com: did not receive HSTS header @@ -2027,8 +2031,6 @@ matrip.de: could not connect to host matrix.ac: did not receive HSTS header matsuz.com: could not connect to host -mattandyana.com: could not connect to host -mattcoles.io: could not connect to host mattfin.ch: could not connect to host matthewprenger.com: could not connect to host matthiassteen.be: max-age too low: 0 @@ -2049,6 +2051,8 @@ mdfnet.se: did not receive HSTS header mdscomp.net: did not receive HSTS header mea.in.ua: could not connect to host +meap.xyz: max-age too low: 0 +mebio.us: did not receive HSTS header mechanus.io: max-age too low: 2592000 medallia.io: could not connect to host media-courses.com: did not receive HSTS header @@ -2062,6 +2066,7 @@ megasslstore.com: did not receive HSTS header megaxchange.com: did not receive HSTS header meghudson.com: could not connect to host +megumico.net: did not receive HSTS header mein-gesundheitsmanager.com: did not receive HSTS header meincenter-meinemeinung.de: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no] meinebo.it: could not connect to host @@ -2094,7 +2099,6 @@ micro-rain-systems.com: did not receive HSTS header microme.ga: could not connect to host micropple.net: could not connect to host -microvb.com: did not receive HSTS header midwestwomenworkers.org: did not receive HSTS header mightydicks.io: could not connect to host mightydicks.tech: could not connect to host @@ -2213,6 +2217,7 @@ mypagella.eu: could not connect to host mypagella.it: could not connect to host myplaceonline.com: did not receive HSTS header +myresearchapp.com: could not connect to host mysecretrewards.com: did not receive HSTS header mysmelly.com: could not connect to host mystudy.me: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no] @@ -2221,6 +2226,7 @@ mziulu.me: could not connect to host n0psled.nl: could not connect to host n4l.pw: could not connect to host +nagoya-kyuyo.com: could not connect to host naiharngym.com: did not receive HSTS header najedlo.sk: did not receive HSTS header nakliyatsirketi.biz: could not connect to host @@ -2244,12 +2250,11 @@ ncc60205.info: could not connect to host nct.org.uk: max-age too low: 1 nctx.co.uk: did not receive HSTS header -ndtblog.com: could not connect to host -ndtmarket.place: could not connect to host near.st: did not receive HSTS header neel.ch: could not connect to host neftaly.com: did not receive HSTS header neilgreen.net: did not receive HSTS header +neko-life.com: did not receive HSTS header neko-system.com: did not receive HSTS header nella-project.org: could not connect to host nellacms.com: could not connect to host @@ -2264,6 +2269,7 @@ nerven.se: could not connect to host nestedquotes.ca: could not connect to host netbox.cc: could not connect to host +netbulls.io: could not connect to host netherwind.eu: could not connect to host netlilo.com: did not receive HSTS header netsight.org: could not connect to host @@ -2286,6 +2292,7 @@ ng-security.com: could not connect to host ngine.ch: did not receive HSTS header nginxnudes.com: could not connect to host +ngt-service.ru: could not connect to host ni.search.yahoo.com: did not receive HSTS header nibiisclaim.com: could not connect to host nicestresser.fr: could not connect to host @@ -2311,7 +2318,9 @@ nodetemple.com: could not connect to host noexpect.org: could not connect to host noima.com: did not receive HSTS header +nojestorget.se: could not connect to host nolatepayments.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no] +nolberg.net: could not connect to host nolte.work: could not connect to host nomorebytes.de: did not receive HSTS header nope.website: could not connect to host @@ -2368,9 +2377,9 @@ ofcourselanguages.com: could not connect to host offshore-firma.org: could not connect to host oishioffice.com: did not receive HSTS header -ojls.co: could not connect to host okane.love: could not connect to host okok.rent: could not connect to host +okonetwork.org.uk: could not connect to host okutama.in.th: could not connect to host oliver-pietsch.de: did not receive HSTS header oliverdunk.com: did not receive HSTS header @@ -2414,7 +2423,7 @@ openshift.redhat.com: did not receive HSTS header opensrd.com: could not connect to host openxmpp.com: could not connect to host -opim.ca: could not connect to host +opim.ca: did not receive HSTS header oprbox.com: could not connect to host opsbears.com: did not receive HSTS header optenhoefel.de: could not connect to host @@ -2424,7 +2433,6 @@ orbiosales.com: could not connect to host orbitcom.de: max-age too low: 0 orbograph-hrcm.com: did not receive HSTS header -orioncustompcs.com: could not connect to host orionfcu.com: did not receive HSTS header orleika.ml: could not connect to host osaiyuwu.com: could not connect to host @@ -2440,6 +2448,7 @@ otichi.com: did not receive HSTS header ottospora.nl: could not connect to host ourbank.com: did not receive HSTS header +outdoorproducts.com: could not connect to host outetc.com: could not connect to host outreachbuddy.com: could not connect to host outsider.im: could not connect to host @@ -2467,12 +2476,11 @@ panelomix.net: could not connect to host pants-off.xyz: could not connect to host pantsu.cat: did not receive HSTS header -papeda.net: did not receive HSTS header +papeda.net: could not connect to host papercard.co.uk: did not receive HSTS header papierniak.net: could not connect to host parent5446.us: could not connect to host parentmail.co.uk: did not receive HSTS header -parithy.net: could not connect to host particonpsplus.it: could not connect to host partijtjevoordevrijheid.nl: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no] partyvan.it: could not connect to host @@ -2510,7 +2518,6 @@ pepperworldhotshop.de: did not receive HSTS header perfectionis.me: could not connect to host performous.org: could not connect to host -perfumista.vn: could not connect to host perlwork.nl: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no] perplex.nl: did not receive HSTS header perroud.pro: max-age too low: 2592000 @@ -2528,7 +2535,6 @@ pgpm.io: could not connect to host phonenumberinfo.co.uk: could not connect to host phongmay24h.com: could not connect to host -phperformances.fr: could not connect to host phurl.de: could not connect to host pickr.co: could not connect to host picotronic.biz: could not connect to host @@ -2558,6 +2564,7 @@ playkh.com: did not receive HSTS header playmaker.io: could not connect to host playnation.io: did not receive HSTS header +please-deny.me: did not receive HSTS header plogable.co: could not connect to host plothost.com: did not receive HSTS header ploup.net: could not connect to host @@ -2577,16 +2584,16 @@ poolsandstuff.com: did not receive HSTS header poris.web.id: did not receive HSTS header portalplatform.net: did not receive HSTS header -portalzine.de: did not receive HSTS header postcodewise.co.uk: did not receive HSTS header +posterspy.com: did not receive HSTS header postscheduler.org: could not connect to host posylka.de: did not receive HSTS header -potatofrom.space: could not connect to host poussinooz.fr: could not connect to host povitria.net: could not connect to host -powerplannerapp.com: did not receive HSTS header +powerplannerapp.com: could not connect to host powerxequality.com: could not connect to host ppr-truby.ru: could not connect to host +ppuu.org: could not connect to host pr.search.yahoo.com: did not receive HSTS header prefontaine.name: could not connect to host prego-shop.de: did not receive HSTS header @@ -2602,7 +2609,7 @@ prnt.li: did not receive HSTS header pro-zone.com: could not connect to host prodpad.com: did not receive HSTS header -production.vn: could not connect to host +production.vn: did not receive HSTS header professionalboundaries.com: did not receive HSTS header profi-durchgangsmelder.de: did not receive HSTS header profundr.com: could not connect to host @@ -2647,6 +2654,7 @@ qrlending.com: did not receive HSTS header quail.solutions: could not connect to host quantacloud.ch: could not connect to host +quantenteranik.eu: could not connect to host quantumcourse.org: did not receive HSTS header queercoders.com: did not receive HSTS header quemmeliga.com: could not connect to host @@ -2660,7 +2668,7 @@ r3bl.me: did not receive HSTS header raajheshkannaa.com: could not connect to host radicaleducation.net: could not connect to host -radiormi.com: did not receive HSTS header +radiormi.com: could not connect to host rafaelcz.de: could not connect to host rainbowbarracuda.com: could not connect to host ramonj.nl: could not connect to host @@ -2698,6 +2706,7 @@ reisyukaku.org: did not receive HSTS header rejo.in: could not connect to host relisten.nl: did not receive HSTS header +remitatm.com: could not connect to host remodela.com.ve: could not connect to host renem.net: did not receive HSTS header renlong.org: could not connect to host @@ -2712,10 +2721,10 @@ reserve-online.net: did not receive HSTS header respice.xyz: could not connect to host restchart.com: did not receive HSTS header +reth.ch: could not connect to host revello.org: did not receive HSTS header -revensoftware.com: could not connect to host reverie.pw: could not connect to host -reviews.anime.my: could not connect to host +reviews.anime.my: max-age too low: 5184000 revtut.net: did not receive HSTS header rewardstock.com: max-age too low: 0 rewrite3.com: could not connect to host @@ -2791,7 +2800,6 @@ rxv.cc: could not connect to host ryansmithphotography.com: did not receive HSTS header ryanteck.uk: did not receive HSTS header -saba-piserver.info: could not connect to host safematix.com: could not connect to host sageth.com: max-age too low: 0 sah3.net: could not connect to host @@ -2802,6 +2810,7 @@ salserototal.com: did not receive HSTS header salud.top: did not receive HSTS header samirnassar.com: max-age too low: 60 +saml2.com: could not connect to host sampoznay.ru: did not receive HSTS header samraskauskas.com: could not connect to host samsen.club: did not receive HSTS header @@ -2837,7 +2846,7 @@ scrambl.is: could not connect to host scrambler.in: could not connect to host scrapings.net: could not connect to host -screenlight.tv: did not receive HSTS header +screencaster.io: did not receive HSTS header screenresolution.space: could not connect to host scribe.systems: could not connect to host script.google.com: did not receive HSTS header (error ignored - included regardless) @@ -2856,6 +2865,7 @@ securityinet.biz: did not receive HSTS header securityinet.net: did not receive HSTS header securityinet.org.il: did not receive HSTS header +securitymap.wiki: did not receive HSTS header securitysoapbox.com: could not connect to host securiviera.ch: did not receive HSTS header seedbox.fr: did not receive HSTS header @@ -2876,7 +2886,6 @@ semenkovich.com: did not receive HSTS header semps-servers.de: could not connect to host semps.de: did not receive HSTS header -sendash.com: did not receive HSTS header senedirect.com: did not receive HSTS header sensibus.com: did not receive HSTS header seo.consulting: did not receive HSTS header @@ -2893,14 +2902,13 @@ setuid.de: could not connect to host setuid.io: did not receive HSTS header seyahatsagliksigortalari.com: could not connect to host -sh-network.de: could not connect to host shadoom.com: did not receive HSTS header +shadowguardian507-irl.tk: could not connect to host shadowmorph.info: did not receive HSTS header shadowsocks.net: could not connect to host shakepeers.org: did not receive HSTS header shakespearesolutions.com.au: did not receive HSTS header shanesage.com: could not connect to host -shansing.net: could not connect to host shaobin.wang: could not connect to host sharescope.co.uk: max-age too low: 14400 shareworx.net: could not connect to host @@ -2926,10 +2934,10 @@ shwongacc.com: could not connect to host siammedia.co: did not receive HSTS header siddhant.me: could not connect to host -siebeve.be: could not connect to host sifls.com: could not connect to host silentcircle.org: could not connect to host silicagelpackets.ca: did not receive HSTS header +sillisalaatti.fi: could not connect to host silver-drachenkrieger.de: did not receive HSTS header silverhome.ninja: could not connect to host silverpvp.com: could not connect to host @@ -2942,9 +2950,8 @@ simplelearner.com: could not connect to host simplepractice.com: did not receive HSTS header simply-premium.com: max-age too low: 0 -simplymozzo.se: could not connect to host +simplycloud.de: could not connect to host sincron.org: could not connect to host -sinful.pw: could not connect to host siriad.com: did not receive HSTS header sirius-lee.net: could not connect to host sitehost.io: could not connect to host @@ -2961,6 +2968,7 @@ slash-dev.de: did not receive HSTS header slashem.me: did not receive HSTS header slattery.co: could not connect to host +sleep10.com: could not connect to host slicketl.com: did not receive HSTS header slightfuture.click: could not connect to host slix.io: could not connect to host @@ -2974,9 +2982,10 @@ smartofficesandsmarthomes.com: did not receive HSTS header smartrak.co.nz: did not receive HSTS header smatch.com: did not receive HSTS header +smdev.fr: could not connect to host smet.us: could not connect to host smirkingwhorefromhighgarden.pro: could not connect to host -smith.is: did not receive HSTS header +smith.is: could not connect to host smkn1lengkong.sch.id: did not receive HSTS header smksi2.com: max-age too low: 0 smusg.com: did not receive HSTS header @@ -3001,6 +3010,7 @@ socialspirit.com.br: did not receive HSTS header sockeye.cc: could not connect to host socomponents.co.uk: did not receive HSTS header +sogeek.me: did not receive HSTS header solidfuelappliancespares.co.uk: did not receive HSTS header solinter.com.br: did not receive HSTS header soll-i.ch: did not receive HSTS header @@ -3009,12 +3019,15 @@ somethingnew.xyz: did not receive HSTS header songzhuolun.com: did not receive HSTS header sonic.sk: max-age too low: 0 +sonicrainboom.rocks: did not receive HSTS header sotar.us: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no] +sotiran.com: could not connect to host sotor.de: did not receive HSTS header soulboy.io: did not receive HSTS header soulema.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no] soulfulglamour.uk: could not connect to host sourcelair.com: did not receive HSTS header +sourcitec.com: could not connect to host southside-crew.club: could not connect to host southworcestershiregpservices.co.uk: could not connect to host souyar.de: could not connect to host @@ -3074,6 +3087,7 @@ stationaryjourney.com: did not receive HSTS header stationnementdenuit.ca: did not receive HSTS header statuschecks.net: could not connect to host +stay.black: could not connect to host stefany.eu: could not connect to host stephanierxo.com: did not receive HSTS header stephenandburns.com: did not receive HSTS header @@ -3111,14 +3125,13 @@ studybay.com: did not receive HSTS header studydrive.net: did not receive HSTS header stugb.de: did not receive HSTS header -stupendous.net: could not connect to host stw-group.at: could not connect to host +styles.pm: could not connect to host subbing.work: could not connect to host subdimension.org: could not connect to host subtitle.rip: could not connect to host sudo.im: could not connect to host sudo.li: did not receive HSTS header -sufix.cz: could not connect to host suite73.org: could not connect to host suksit.com: could not connect to host sumoatm.com: did not receive HSTS header @@ -3149,7 +3162,6 @@ sylvanorder.com: could not connect to host synackr.com: could not connect to host syncer.jp: did not receive HSTS header -synchrocube.com: could not connect to host syncserve.net: did not receive HSTS header syneic.com: did not receive HSTS header syno.gq: could not connect to host @@ -3202,6 +3214,7 @@ techpointed.com: could not connect to host techvalue.gr: did not receive HSTS header tegelsensanitaironline.nl: did not receive HSTS header +teknologi.or.id: could not connect to host tekshrek.com: max-age too low: 0 telefonnummer.online: could not connect to host telefoonnummerinfo.nl: could not connect to host @@ -3215,6 +3228,7 @@ testandroid.xyz: could not connect to host testbawks.com: did not receive HSTS header testnode.xyz: could not connect to host +texter-linz.at: did not receive HSTS header textoplano.xyz: could not connect to host textracer.dk: could not connect to host tezcam.tk: could not connect to host @@ -3267,6 +3281,7 @@ tickopa.co.uk: could not connect to host tickreport.com: did not receive HSTS header tictactux.de: could not connect to host +tidmore.us: could not connect to host tiensnet.com: did not receive HSTS header tightlineproductions.com: did not receive HSTS header tikutiku.pl: max-age too low: 0 @@ -3282,7 +3297,6 @@ tirex.media: did not receive HSTS header tittelbach.at: did not receive HSTS header titties.ml: could not connect to host -tjs.me: could not connect to host tkarstens.de: could not connect to host tlo.hosting: could not connect to host tlo.network: could not connect to host @@ -3303,7 +3317,6 @@ tomharling.co.uk: max-age too low: 86400 tomharling.uk: max-age too low: 86400 tomlankhorst.nl: did not receive HSTS header -tomli.me: could not connect to host tommsy.com: did not receive HSTS header tonburi.jp: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no] tonyfantjr.com: could not connect to host @@ -3330,8 +3343,10 @@ tradingcentre.com.au: did not receive HSTS header tradinghope.com: could not connect to host traeningsprojekt.dk: did not receive HSTS header +traindb.nl: could not connect to host translate.googleapis.com: did not receive HSTS header (error ignored - included regardless) transportal.sk: did not receive HSTS header +treeby.net: could not connect to host trendberry.ru: did not receive HSTS header trinityaffirmations.com: max-age too low: 0 trinitycore.org: max-age too low: 2592000 @@ -3350,6 +3365,7 @@ tuturulianda.com: could not connect to host tuvalie.com: could not connect to host tuxcall.de: could not connect to host +tuxz.net: could not connect to host tv.search.yahoo.com: could not connect to host tvtubeflix.com: did not receive HSTS header tvz-materijali.com: could not connect to host @@ -3374,12 +3390,12 @@ tzappa.net: could not connect to host u-blox.com: did not receive HSTS header ua.search.yahoo.com: did not receive HSTS header +ubanquity.com: could not connect to host ubicloud.de: could not connect to host ublox.com: did not receive HSTS header -ubtce.com: could not connect to host ubuntuhot.com: did not receive HSTS header uega.net: did not receive HSTS header -ufotable.uk: could not connect to host +ufotable.uk: max-age too low: 0 ui8.net: did not receive HSTS header ukas.com: did not receive HSTS header ukrgadget.com: could not connect to host @@ -3393,7 +3409,6 @@ unblocked.host: could not connect to host unccdesign.club: could not connect to host undernet.uy: did not receive HSTS header -underskatten.tk: could not connect to host unfiltered.nyc: did not receive HSTS header uni-games.com: could not connect to host unicooo.com: could not connect to host @@ -3404,6 +3419,7 @@ universogay.com: did not receive HSTS header univz.com: could not connect to host unknownphenomena.net: could not connect to host +unmanaged.space: could not connect to host unravel.ie: did not receive HSTS header unsystem.net: could not connect to host unterschicht.tv: could not connect to host @@ -3423,6 +3439,7 @@ uscitizenship.info: did not receive HSTS header used-in.jp: did not receive HSTS header usercare.com: did not receive HSTS header +userify.com: did not receive HSTS header ustr.gov: max-age too low: 86400 utumno.ch: could not connect to host uy.search.yahoo.com: did not receive HSTS header @@ -3444,6 +3461,7 @@ vanitynailworkz.com: could not connect to host vansieleghem.com: could not connect to host vasanth.org: did not receive HSTS header +vazue.com: could not connect to host vbh2o.com: did not receive HSTS header vbulletin-russia.com: could not connect to host vbulletinrussia.com: could not connect to host @@ -3453,6 +3471,7 @@ vechkasov.ru: did not receive HSTS header vemokin.net: did not receive HSTS header verifikatorindonesia.com: could not connect to host +veriny.tf: did not receive HSTS header vermontcareergateway.org: could not connect to host versia.ru: did not receive HSTS header veryhax.de: could not connect to host @@ -3471,7 +3490,7 @@ vio.no: did not receive HSTS header viperdns.com: could not connect to host vipmusic.ga: could not connect to host -vipnettikasinoklubi.com: could not connect to host +visalogy.com: could not connect to host vissanum.com: did not receive HSTS header vistarait.com: did not receive HSTS header viva-french.com: did not receive HSTS header @@ -3480,6 +3499,7 @@ vmrdev.com: could not connect to host voceinveste.com: did not receive HSTS header voicesuk.co.uk: did not receive HSTS header +voidi.ca: could not connect to host volcrado.com: could not connect to host voliere-info.nl: did not receive HSTS header vortexhobbies.com: did not receive HSTS header @@ -3490,6 +3510,7 @@ vpn-byen.dk: did not receive HSTS header vratny.space: could not connect to host vrtak-cz.net: could not connect to host +vulners.com: did not receive HSTS header vvl.me: did not receive HSTS header vxstream-sandbox.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no] vyncke.org: max-age too low: 2678400 @@ -3498,6 +3519,7 @@ w4a.fr: max-age too low: 0 w4xzr.top: could not connect to host w4xzr.xyz: could not connect to host +wafa4hw.com: could not connect to host wait.jp: could not connect to host wait.moe: could not connect to host wakapp.de: could not connect to host @@ -3537,9 +3559,9 @@ webperformance.ru: max-age too low: 3600 webswitch.io: could not connect to host webtiles.co.uk: could not connect to host -webtobesocial.de: could not connect to host webwork.pw: could not connect to host weddingenvelopes.co.uk: did not receive HSTS header +wegenaer.nl: could not connect to host wellsolveit.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no] weltmeisterschaft.net: could not connect to host weme.eu: could not connect to host @@ -3547,8 +3569,8 @@ wer-kommt-her.de: could not connect to host werdeeintimo.de: did not receive HSTS header werkenbijkfc.nl: did not receive HSTS header -werkplaatsoost.nl: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no] werkruimtebottendaal.nl: did not receive HSTS header +wesecom.com: could not connect to host wesleyharris.ca: did not receive HSTS header westendzone.com: max-age too low: 0 westerhoud.nl: did not receive HSTS header @@ -3564,6 +3586,7 @@ whatsstalk.me: could not connect to host when-release.com: did not receive HSTS header whereisjason.com: could not connect to host +whisker.network: could not connect to host whiterabbitcakery.com: could not connect to host whitestagforge.com: did not receive HSTS header whoclicks.net: could not connect to host @@ -3607,11 +3630,11 @@ wolfesden.com: could not connect to host womosale.de: could not connect to host wonderfall.xyz: could not connect to host +wondershift.biz: did not receive HSTS header woording.com: could not connect to host woresite.jp: did not receive HSTS header workfone.io: did not receive HSTS header workwithgo.com: could not connect to host -wow-foederation.de: could not connect to host wowapi.org: could not connect to host wphostingspot.com: did not receive HSTS header wpmetadatastandardsproject.org: could not connect to host @@ -3621,7 +3644,6 @@ wufu.org: did not receive HSTS header wuhengmin.com: did not receive HSTS header wurzelzwerg.net: could not connect to host -wvg.myds.me: could not connect to host www.apollo-auto.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no] www.braintreepayments.com: did not receive HSTS header www.calyxinstitute.org: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no] @@ -3655,13 +3677,14 @@ xcoop.me: could not connect to host xellos.ga: could not connect to host xellos.ml: could not connect to host +xendo.net: did not receive HSTS header xenesisziarovky.sk: could not connect to host xett.com: did not receive HSTS header xf-liam.com: could not connect to host xfive.de: did not receive HSTS header xiaody.me: could not connect to host xiaolvmu.me: could not connect to host -xiaoxiao.im: did not receive HSTS header +xiaoxiao.im: could not connect to host xisa.it: could not connect to host xiyu.moe: could not connect to host xmr.my: could not connect to host @@ -3695,14 +3718,13 @@ xxbase.com: could not connect to host y-o-w.com: did not receive HSTS header y-s.pw: did not receive HSTS header -yal.sh: could not connect to host +yahvehyireh.com: did not receive HSTS header yalook.com: did not receive HSTS header yamaken.jp: did not receive HSTS header yamamo10.com: could not connect to host yaporn.tv: did not receive HSTS header yard-fu.com: did not receive HSTS header yasinaydin.net: max-age too low: 2592000 -yaucy.win: could not connect to host yello.website: could not connect to host yellowcar.website: could not connect to host yenniferallulli.de: could not connect to host @@ -3729,6 +3751,7 @@ yukontec.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 121" data: no] yunzhu.li: did not receive HSTS header yunzhu.org: could not connect to host +yux.io: did not receive HSTS header yzal.io: could not connect to host z33.ch: did not receive HSTS header z3liff.com: could not connect to host @@ -3749,7 +3772,6 @@ zeitzer-turngala.de: could not connect to host zelezny.uk: did not receive HSTS header zelfstandigemakelaars.net: did not receive HSTS header -zellari.ru: could not connect to host zenpayroll.com: did not receive HSTS header zentraler-kreditausschuss.de: did not receive HSTS header zentralwolke.de: did not receive HSTS header diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/manager/ssl/nsSTSPreloadList.inc firefox-trunk-52.0~a1~hg20161113r322177/security/manager/ssl/nsSTSPreloadList.inc --- firefox-trunk-52.0~a1~hg20161110r321971/security/manager/ssl/nsSTSPreloadList.inc 2016-11-11 02:09:21.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/manager/ssl/nsSTSPreloadList.inc 2016-11-14 02:10:13.000000000 +0000 @@ -8,7 +8,7 @@ /*****************************************************************************/ #include -const PRTime gPreloadListExpirationTime = INT64_C(1489673233711000); +const PRTime gPreloadListExpirationTime = INT64_C(1489932160224000); static const char kSTSHostTable[] = { /* "007sascha.de", true */ '0', '0', '7', 's', 'a', 's', 'c', 'h', 'a', '.', 'd', 'e', '\0', @@ -91,6 +91,7 @@ /* "2-cpu.de", true */ '2', '-', 'c', 'p', 'u', '.', 'd', 'e', '\0', /* "2.wtf", true */ '2', '.', 'w', 't', 'f', '\0', /* "2048game.co.uk", true */ '2', '0', '4', '8', 'g', 'a', 'm', 'e', '.', 'c', 'o', '.', 'u', 'k', '\0', + /* "20hs.cn", true */ '2', '0', 'h', 's', '.', 'c', 'n', '\0', /* "21.co.uk", true */ '2', '1', '.', 'c', 'o', '.', 'u', 'k', '\0', /* "247healthshop.com", true */ '2', '4', '7', 'h', 'e', 'a', 'l', 't', 'h', 's', 'h', 'o', 'p', '.', 'c', 'o', 'm', '\0', /* "247loan.com", true */ '2', '4', '7', 'l', 'o', 'a', 'n', '.', 'c', 'o', 'm', '\0', @@ -201,6 +202,7 @@ /* "aaoo.net", true */ 'a', 'a', 'o', 'o', '.', 'n', 'e', 't', '\0', /* "aapas.org.ar", true */ 'a', 'a', 'p', 'a', 's', '.', 'o', 'r', 'g', '.', 'a', 'r', '\0', /* "aaron-gustafson.com", true */ 'a', 'a', 'r', 'o', 'n', '-', 'g', 'u', 's', 't', 'a', 'f', 's', 'o', 'n', '.', 'c', 'o', 'm', '\0', + /* "aaronkimmig.de", true */ 'a', 'a', 'r', 'o', 'n', 'k', 'i', 'm', 'm', 'i', 'g', '.', 'd', 'e', '\0', /* "aaronsilber.me", true */ 'a', 'a', 'r', 'o', 'n', 's', 'i', 'l', 'b', 'e', 'r', '.', 'm', 'e', '\0', /* "aatf.us", true */ 'a', 'a', 't', 'f', '.', 'u', 's', '\0', /* "aati.info", true */ 'a', 'a', 't', 'i', '.', 'i', 'n', 'f', 'o', '\0', @@ -331,7 +333,6 @@ /* "adventureally.com", true */ 'a', 'd', 'v', 'e', 'n', 't', 'u', 'r', 'e', 'a', 'l', 'l', 'y', '.', 'c', 'o', 'm', '\0', /* "adventureforest.de", false */ 'a', 'd', 'v', 'e', 'n', 't', 'u', 'r', 'e', 'f', 'o', 'r', 'e', 's', 't', '.', 'd', 'e', '\0', /* "adventures.de", true */ 'a', 'd', 'v', 'e', 'n', 't', 'u', 'r', 'e', 's', '.', 'd', 'e', '\0', - /* "adver.top", true */ 'a', 'd', 'v', 'e', 'r', '.', 't', 'o', 'p', '\0', /* "advocatenalkmaar.org", true */ 'a', 'd', 'v', 'o', 'c', 'a', 't', 'e', 'n', 'a', 'l', 'k', 'm', 'a', 'a', 'r', '.', 'o', 'r', 'g', '\0', /* "adxperience.com", true */ 'a', 'd', 'x', 'p', 'e', 'r', 'i', 'e', 'n', 'c', 'e', '.', 'c', 'o', 'm', '\0', /* "adzuna.ca", true */ 'a', 'd', 'z', 'u', 'n', 'a', '.', 'c', 'a', '\0', @@ -347,6 +348,7 @@ /* "adzuna.ru", true */ 'a', 'd', 'z', 'u', 'n', 'a', '.', 'r', 'u', '\0', /* "aegee-utrecht.nl", true */ 'a', 'e', 'g', 'e', 'e', '-', 'u', 't', 'r', 'e', 'c', 'h', 't', '.', 'n', 'l', '\0', /* "aeon.co", false */ 'a', 'e', 'o', 'n', '.', 'c', 'o', '\0', + /* "aerelon.de", true */ 'a', 'e', 'r', 'e', 'l', 'o', 'n', '.', 'd', 'e', '\0', /* "aerialmediapro.net", true */ 'a', 'e', 'r', 'i', 'a', 'l', 'm', 'e', 'd', 'i', 'a', 'p', 'r', 'o', '.', 'n', 'e', 't', '\0', /* "aerolog.co", true */ 'a', 'e', 'r', 'o', 'l', 'o', 'g', '.', 'c', 'o', '\0', /* "aeyoun.com", true */ 'a', 'e', 'y', 'o', 'u', 'n', '.', 'c', 'o', 'm', '\0', @@ -477,7 +479,6 @@ /* "alienstat.com", true */ 'a', 'l', 'i', 'e', 'n', 's', 't', 'a', 't', '.', 'c', 'o', 'm', '\0', /* "alinasmusicstudio.com", true */ 'a', 'l', 'i', 'n', 'a', 's', 'm', 'u', 's', 'i', 'c', 's', 't', 'u', 'd', 'i', 'o', '.', 'c', 'o', 'm', '\0', /* "alisonlitchfield.com", true */ 'a', 'l', 'i', 's', 'o', 'n', 'l', 'i', 't', 'c', 'h', 'f', 'i', 'e', 'l', 'd', '.', 'c', 'o', 'm', '\0', - /* "alittlebitcheeky.com", false */ 'a', 'l', 'i', 't', 't', 'l', 'e', 'b', 'i', 't', 'c', 'h', 'e', 'e', 'k', 'y', '.', 'c', 'o', 'm', '\0', /* "aljaspod.com", true */ 'a', 'l', 'j', 'a', 's', 'p', 'o', 'd', '.', 'c', 'o', 'm', '\0', /* "aljaspod.hu", true */ 'a', 'l', 'j', 'a', 's', 'p', 'o', 'd', '.', 'h', 'u', '\0', /* "aljaspod.net", true */ 'a', 'l', 'j', 'a', 's', 'p', 'o', 'd', '.', 'n', 'e', 't', '\0', @@ -517,6 +518,7 @@ /* "alt-three.com", true */ 'a', 'l', 't', '-', 't', 'h', 'r', 'e', 'e', '.', 'c', 'o', 'm', '\0', /* "alt.org", true */ 'a', 'l', 't', '.', 'o', 'r', 'g', '\0', /* "altedirect.com", true */ 'a', 'l', 't', 'e', 'd', 'i', 'r', 'e', 'c', 't', '.', 'c', 'o', 'm', '\0', + /* "alterbaum.net", true */ 'a', 'l', 't', 'e', 'r', 'b', 'a', 'u', 'm', '.', 'n', 'e', 't', '\0', /* "alternativet.party", true */ 'a', 'l', 't', 'e', 'r', 'n', 'a', 't', 'i', 'v', 'e', 't', '.', 'p', 'a', 'r', 't', 'y', '\0', /* "altesses.eu", true */ 'a', 'l', 't', 'e', 's', 's', 'e', 's', '.', 'e', 'u', '\0', /* "altestore.com", true */ 'a', 'l', 't', 'e', 's', 't', 'o', 'r', 'e', '.', 'c', 'o', 'm', '\0', @@ -541,6 +543,7 @@ /* "amateri.com", true */ 'a', 'm', 'a', 't', 'e', 'r', 'i', '.', 'c', 'o', 'm', '\0', /* "amavis.org", true */ 'a', 'm', 'a', 'v', 'i', 's', '.', 'o', 'r', 'g', '\0', /* "amazing-gaming.fr", true */ 'a', 'm', 'a', 'z', 'i', 'n', 'g', '-', 'g', 'a', 'm', 'i', 'n', 'g', '.', 'f', 'r', '\0', + /* "ambiente.one", true */ 'a', 'm', 'b', 'i', 'e', 'n', 't', 'e', '.', 'o', 'n', 'e', '\0', /* "ambiq.nl", true */ 'a', 'm', 'b', 'i', 'q', '.', 'n', 'l', '\0', /* "amcvega.com", true */ 'a', 'm', 'c', 'v', 'e', 'g', 'a', '.', 'c', 'o', 'm', '\0', /* "amdouglas.com", true */ 'a', 'm', 'd', 'o', 'u', 'g', 'l', 'a', 's', '.', 'c', 'o', 'm', '\0', @@ -574,7 +577,6 @@ /* "analyticum.eu", true */ 'a', 'n', 'a', 'l', 'y', 't', 'i', 'c', 'u', 'm', '.', 'e', 'u', '\0', /* "analyticum.net", true */ 'a', 'n', 'a', 'l', 'y', 't', 'i', 'c', 'u', 'm', '.', 'n', 'e', 't', '\0', /* "analyzemyfriends.com", true */ 'a', 'n', 'a', 'l', 'y', 'z', 'e', 'm', 'y', 'f', 'r', 'i', 'e', 'n', 'd', 's', '.', 'c', 'o', 'm', '\0', - /* "ananke.io", true */ 'a', 'n', 'a', 'n', 'k', 'e', '.', 'i', 'o', '\0', /* "anarka.org", true */ 'a', 'n', 'a', 'r', 'k', 'a', '.', 'o', 'r', 'g', '\0', /* "anastasia-shamara.ru", true */ 'a', 'n', 'a', 's', 't', 'a', 's', 'i', 'a', '-', 's', 'h', 'a', 'm', 'a', 'r', 'a', '.', 'r', 'u', '\0', /* "anastasiafond.com", true */ 'a', 'n', 'a', 's', 't', 'a', 's', 'i', 'a', 'f', 'o', 'n', 'd', '.', 'c', 'o', 'm', '\0', @@ -593,7 +595,6 @@ /* "andrepicard.de", true */ 'a', 'n', 'd', 'r', 'e', 'p', 'i', 'c', 'a', 'r', 'd', '.', 'd', 'e', '\0', /* "andrewbroekman.com", true */ 'a', 'n', 'd', 'r', 'e', 'w', 'b', 'r', 'o', 'e', 'k', 'm', 'a', 'n', '.', 'c', 'o', 'm', '\0', /* "andrewhowden.com", true */ 'a', 'n', 'd', 'r', 'e', 'w', 'h', 'o', 'w', 'd', 'e', 'n', '.', 'c', 'o', 'm', '\0', - /* "andrewimeson.com", true */ 'a', 'n', 'd', 'r', 'e', 'w', 'i', 'm', 'e', 's', 'o', 'n', '.', 'c', 'o', 'm', '\0', /* "andrewmichaud.com", true */ 'a', 'n', 'd', 'r', 'e', 'w', 'm', 'i', 'c', 'h', 'a', 'u', 'd', '.', 'c', 'o', 'm', '\0', /* "andrewmichaud.me", true */ 'a', 'n', 'd', 'r', 'e', 'w', 'm', 'i', 'c', 'h', 'a', 'u', 'd', '.', 'm', 'e', '\0', /* "andrewregan.me", true */ 'a', 'n', 'd', 'r', 'e', 'w', 'r', 'e', 'g', 'a', 'n', '.', 'm', 'e', '\0', @@ -781,7 +782,7 @@ /* "arrow-analytics.nl", true */ 'a', 'r', 'r', 'o', 'w', '-', 'a', 'n', 'a', 'l', 'y', 't', 'i', 'c', 's', '.', 'n', 'l', '\0', /* "arrow-api.nl", true */ 'a', 'r', 'r', 'o', 'w', '-', 'a', 'p', 'i', '.', 'n', 'l', '\0', /* "arrow-cloud.nl", true */ 'a', 'r', 'r', 'o', 'w', '-', 'c', 'l', 'o', 'u', 'd', '.', 'n', 'l', '\0', - /* "arrowgrove.com", true */ 'a', 'r', 'r', 'o', 'w', 'g', 'r', 'o', 'v', 'e', '.', 'c', 'o', 'm', '\0', + /* "arrowgrove.com", false */ 'a', 'r', 'r', 'o', 'w', 'g', 'r', 'o', 'v', 'e', '.', 'c', 'o', 'm', '\0', /* "arrowwebprojects.nl", true */ 'a', 'r', 'r', 'o', 'w', 'w', 'e', 'b', 'p', 'r', 'o', 'j', 'e', 'c', 't', 's', '.', 'n', 'l', '\0', /* "arsenal.ru", true */ 'a', 'r', 's', 'e', 'n', 'a', 'l', '.', 'r', 'u', '\0', /* "art2web.net", true */ 'a', 'r', 't', '2', 'w', 'e', 'b', '.', 'n', 'e', 't', '\0', @@ -895,7 +896,6 @@ /* "auf-feindgebiet.de", true */ 'a', 'u', 'f', '-', 'f', 'e', 'i', 'n', 'd', 'g', 'e', 'b', 'i', 'e', 't', '.', 'd', 'e', '\0', /* "aufmerksamkeitsstudie.com", true */ 'a', 'u', 'f', 'm', 'e', 'r', 'k', 's', 'a', 'm', 'k', 'e', 'i', 't', 's', 's', 't', 'u', 'd', 'i', 'e', '.', 'c', 'o', 'm', '\0', /* "augaware.org", true */ 'a', 'u', 'g', 'a', 'w', 'a', 'r', 'e', '.', 'o', 'r', 'g', '\0', - /* "augias.org", true */ 'a', 'u', 'g', 'i', 'a', 's', '.', 'o', 'r', 'g', '\0', /* "augiero.it", true */ 'a', 'u', 'g', 'i', 'e', 'r', 'o', '.', 'i', 't', '\0', /* "augustian-life.cz", true */ 'a', 'u', 'g', 'u', 's', 't', 'i', 'a', 'n', '-', 'l', 'i', 'f', 'e', '.', 'c', 'z', '\0', /* "augustiner-kantorei-erfurt.de", true */ 'a', 'u', 'g', 'u', 's', 't', 'i', 'n', 'e', 'r', '-', 'k', 'a', 'n', 't', 'o', 'r', 'e', 'i', '-', 'e', 'r', 'f', 'u', 'r', 't', '.', 'd', 'e', '\0', @@ -1032,7 +1032,6 @@ /* "bancacrs.it", true */ 'b', 'a', 'n', 'c', 'a', 'c', 'r', 's', '.', 'i', 't', '\0', /* "bancoctt.pt", true */ 'b', 'a', 'n', 'c', 'o', 'c', 't', 't', '.', 'p', 't', '\0', /* "bandrcrafts.com", true */ 'b', 'a', 'n', 'd', 'r', 'c', 'r', 'a', 'f', 't', 's', '.', 'c', 'o', 'm', '\0', - /* "bangzafran.com", true */ 'b', 'a', 'n', 'g', 'z', 'a', 'f', 'r', 'a', 'n', '.', 'c', 'o', 'm', '\0', /* "bank.simple.com", false */ 'b', 'a', 'n', 'k', '.', 's', 'i', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm', '\0', /* "bankcardoffer.com", true */ 'b', 'a', 'n', 'k', 'c', 'a', 'r', 'd', 'o', 'f', 'f', 'e', 'r', '.', 'c', 'o', 'm', '\0', /* "bankcircle.co.in", true */ 'b', 'a', 'n', 'k', 'c', 'i', 'r', 'c', 'l', 'e', '.', 'c', 'o', '.', 'i', 'n', '\0', @@ -1393,6 +1392,7 @@ /* "blackcatinformatics.ca", true */ 'b', 'l', 'a', 'c', 'k', 'c', 'a', 't', 'i', 'n', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'c', 's', '.', 'c', 'a', '\0', /* "blackcatinformatics.com", true */ 'b', 'l', 'a', 'c', 'k', 'c', 'a', 't', 'i', 'n', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'c', 's', '.', 'c', 'o', 'm', '\0', /* "blackdesertsp.com", true */ 'b', 'l', 'a', 'c', 'k', 'd', 'e', 's', 'e', 'r', 't', 's', 'p', '.', 'c', 'o', 'm', '\0', + /* "blackdragoninc.org", true */ 'b', 'l', 'a', 'c', 'k', 'd', 'r', 'a', 'g', 'o', 'n', 'i', 'n', 'c', '.', 'o', 'r', 'g', '\0', /* "blackhelicopters.net", false */ 'b', 'l', 'a', 'c', 'k', 'h', 'e', 'l', 'i', 'c', 'o', 'p', 't', 'e', 'r', 's', '.', 'n', 'e', 't', '\0', /* "blacknova.io", true */ 'b', 'l', 'a', 'c', 'k', 'n', 'o', 'v', 'a', '.', 'i', 'o', '\0', /* "blackonion.com", true */ 'b', 'l', 'a', 'c', 'k', 'o', 'n', 'i', 'o', 'n', '.', 'c', 'o', 'm', '\0', @@ -1480,6 +1480,7 @@ /* "bodhi.fedoraproject.org", true */ 'b', 'o', 'd', 'h', 'i', '.', 'f', 'e', 'd', 'o', 'r', 'a', 'p', 'r', 'o', 'j', 'e', 'c', 't', '.', 'o', 'r', 'g', '\0', /* "bodo-wolff.de", false */ 'b', 'o', 'd', 'o', '-', 'w', 'o', 'l', 'f', 'f', '.', 'd', 'e', '\0', /* "bodrumfarm.com", true */ 'b', 'o', 'd', 'r', 'u', 'm', 'f', 'a', 'r', 'm', '.', 'c', 'o', 'm', '\0', + /* "bodyweightsolution.com", true */ 'b', 'o', 'd', 'y', 'w', 'e', 'i', 'g', 'h', 't', 's', 'o', 'l', 'u', 't', 'i', 'o', 'n', '.', 'c', 'o', 'm', '\0', /* "boeddhashop.nl", true */ 'b', 'o', 'e', 'd', 'd', 'h', 'a', 's', 'h', 'o', 'p', '.', 'n', 'l', '\0', /* "boernecancerfonden.dk", true */ 'b', 'o', 'e', 'r', 'n', 'e', 'c', 'a', 'n', 'c', 'e', 'r', 'f', 'o', 'n', 'd', 'e', 'n', '.', 'd', 'k', '\0', /* "bohramt.de", true */ 'b', 'o', 'h', 'r', 'a', 'm', 't', '.', 'd', 'e', '\0', @@ -1555,8 +1556,6 @@ /* "bran.land", true */ 'b', 'r', 'a', 'n', '.', 'l', 'a', 'n', 'd', '\0', /* "brandbuilderwebsites.com", true */ 'b', 'r', 'a', 'n', 'd', 'b', 'u', 'i', 'l', 'd', 'e', 'r', 'w', 'e', 'b', 's', 'i', 't', 'e', 's', '.', 'c', 'o', 'm', '\0', /* "brandnewdays.nl", true */ 'b', 'r', 'a', 'n', 'd', 'n', 'e', 'w', 'd', 'a', 'y', 's', '.', 'n', 'l', '\0', - /* "brandonwalker.me", true */ 'b', 'r', 'a', 'n', 'd', 'o', 'n', 'w', 'a', 'l', 'k', 'e', 'r', '.', 'm', 'e', '\0', - /* "brandred.net", true */ 'b', 'r', 'a', 'n', 'd', 'r', 'e', 'd', '.', 'n', 'e', 't', '\0', /* "brandspray.com", true */ 'b', 'r', 'a', 'n', 'd', 's', 'p', 'r', 'a', 'y', '.', 'c', 'o', 'm', '\0', /* "brasalcosmetics.com", true */ 'b', 'r', 'a', 's', 'a', 'l', 'c', 'o', 's', 'm', 'e', 't', 'i', 'c', 's', '.', 'c', 'o', 'm', '\0', /* "brashear.me", true */ 'b', 'r', 'a', 's', 'h', 'e', 'a', 'r', '.', 'm', 'e', '\0', @@ -1592,6 +1591,7 @@ /* "brilliantbuilders.co.uk", true */ 'b', 'r', 'i', 'l', 'l', 'i', 'a', 'n', 't', 'b', 'u', 'i', 'l', 'd', 'e', 'r', 's', '.', 'c', 'o', '.', 'u', 'k', '\0', /* "brilliantdecisionmaking.com", true */ 'b', 'r', 'i', 'l', 'l', 'i', 'a', 'n', 't', 'd', 'e', 'c', 'i', 's', 'i', 'o', 'n', 'm', 'a', 'k', 'i', 'n', 'g', '.', 'c', 'o', 'm', '\0', /* "brinkhu.is", true */ 'b', 'r', 'i', 'n', 'k', 'h', 'u', '.', 'i', 's', '\0', + /* "bristebein.com", true */ 'b', 'r', 'i', 's', 't', 'e', 'b', 'e', 'i', 'n', '.', 'c', 'o', 'm', '\0', /* "britishgroupsg.com", true */ 'b', 'r', 'i', 't', 'i', 's', 'h', 'g', 'r', 'o', 'u', 'p', 's', 'g', '.', 'c', 'o', 'm', '\0', /* "britishscienceweek.org", true */ 'b', 'r', 'i', 't', 'i', 's', 'h', 's', 'c', 'i', 'e', 'n', 'c', 'e', 'w', 'e', 'e', 'k', '.', 'o', 'r', 'g', '\0', /* "britzer-toner.de", true */ 'b', 'r', 'i', 't', 'z', 'e', 'r', '-', 't', 'o', 'n', 'e', 'r', '.', 'd', 'e', '\0', @@ -1610,6 +1610,8 @@ /* "bru6.de", true */ 'b', 'r', 'u', '6', '.', 'd', 'e', '\0', /* "brunn.email", true */ 'b', 'r', 'u', 'n', 'n', '.', 'e', 'm', 'a', 'i', 'l', '\0', /* "brunoonline.co.uk", true */ 'b', 'r', 'u', 'n', 'o', 'o', 'n', 'l', 'i', 'n', 'e', '.', 'c', 'o', '.', 'u', 'k', '\0', + /* "brunoramos.com", true */ 'b', 'r', 'u', 'n', 'o', 'r', 'a', 'm', 'o', 's', '.', 'c', 'o', 'm', '\0', + /* "brunoramos.org", true */ 'b', 'r', 'u', 'n', 'o', 'r', 'a', 'm', 'o', 's', '.', 'o', 'r', 'g', '\0', /* "brunosouza.org", true */ 'b', 'r', 'u', 'n', 'o', 's', 'o', 'u', 'z', 'a', '.', 'o', 'r', 'g', '\0', /* "bryanquigley.com", true */ 'b', 'r', 'y', 'a', 'n', 'q', 'u', 'i', 'g', 'l', 'e', 'y', '.', 'c', 'o', 'm', '\0', /* "bryn.xyz", false */ 'b', 'r', 'y', 'n', '.', 'x', 'y', 'z', '\0', @@ -1769,7 +1771,6 @@ /* "calgoty.com", true */ 'c', 'a', 'l', 'g', 'o', 't', 'y', '.', 'c', 'o', 'm', '\0', /* "calibreapp.com", false */ 'c', 'a', 'l', 'i', 'b', 'r', 'e', 'a', 'p', 'p', '.', 'c', 'o', 'm', '\0', /* "calibso.net", true */ 'c', 'a', 'l', 'i', 'b', 's', 'o', '.', 'n', 'e', 't', '\0', - /* "call.me", false */ 'c', 'a', 'l', 'l', '.', 'm', 'e', '\0', /* "callcap.com", false */ 'c', 'a', 'l', 'l', 'c', 'a', 'p', '.', 'c', 'o', 'm', '\0', /* "callear.org", true */ 'c', 'a', 'l', 'l', 'e', 'a', 'r', '.', 'o', 'r', 'g', '\0', /* "callhub.io", true */ 'c', 'a', 'l', 'l', 'h', 'u', 'b', '.', 'i', 'o', '\0', @@ -1932,7 +1933,6 @@ /* "certible.com", true */ 'c', 'e', 'r', 't', 'i', 'b', 'l', 'e', '.', 'c', 'o', 'm', '\0', /* "certifi.io", true */ 'c', 'e', 'r', 't', 'i', 'f', 'i', '.', 'i', 'o', '\0', /* "certly.io", true */ 'c', 'e', 'r', 't', 'l', 'y', '.', 'i', 'o', '\0', - /* "certnazionale.it", true */ 'c', 'e', 'r', 't', 'n', 'a', 'z', 'i', 'o', 'n', 'a', 'l', 'e', '.', 'i', 't', '\0', /* "certspotter.com", true */ 'c', 'e', 'r', 't', 's', 'p', 'o', 't', 't', 'e', 'r', '.', 'c', 'o', 'm', '\0', /* "certspotter.org", true */ 'c', 'e', 'r', 't', 's', 'p', 'o', 't', 't', 'e', 'r', '.', 'o', 'r', 'g', '\0', /* "cervejista.com", true */ 'c', 'e', 'r', 'v', 'e', 'j', 'i', 's', 't', 'a', '.', 'c', 'o', 'm', '\0', @@ -1958,7 +1958,6 @@ /* "chaletmanager.com", true */ 'c', 'h', 'a', 'l', 'e', 't', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'c', 'o', 'm', '\0', /* "chalkfestival.org", true */ 'c', 'h', 'a', 'l', 'k', 'f', 'e', 's', 't', 'i', 'v', 'a', 'l', '.', 'o', 'r', 'g', '\0', /* "chameth.com", true */ 'c', 'h', 'a', 'm', 'e', 't', 'h', '.', 'c', 'o', 'm', '\0', - /* "chamilo.org", true */ 'c', 'h', 'a', 'm', 'i', 'l', 'o', '.', 'o', 'r', 'g', '\0', /* "changetip.com", true */ 'c', 'h', 'a', 'n', 'g', 'e', 't', 'i', 'p', '.', 'c', 'o', 'm', '\0', /* "chaos-inc.de", true */ 'c', 'h', 'a', 'o', 's', '-', 'i', 'n', 'c', '.', 'd', 'e', '\0', /* "chaoschemnitz.de", true */ 'c', 'h', 'a', 'o', 's', 'c', 'h', 'e', 'm', 'n', 'i', 't', 'z', '.', 'd', 'e', '\0', @@ -2008,6 +2007,7 @@ /* "chepaofen.com", true */ 'c', 'h', 'e', 'p', 'a', 'o', 'f', 'e', 'n', '.', 'c', 'o', 'm', '\0', /* "cherryonit.com", true */ 'c', 'h', 'e', 'r', 'r', 'y', 'o', 'n', 'i', 't', '.', 'c', 'o', 'm', '\0', /* "cherrywoodtech.com", true */ 'c', 'h', 'e', 'r', 'r', 'y', 'w', 'o', 'o', 'd', 't', 'e', 'c', 'h', '.', 'c', 'o', 'm', '\0', + /* "chestnut.cf", true */ 'c', 'h', 'e', 's', 't', 'n', 'u', 't', '.', 'c', 'f', '\0', /* "chfr.search.yahoo.com", false */ 'c', 'h', 'f', 'r', '.', 's', 'e', 'a', 'r', 'c', 'h', '.', 'y', 'a', 'h', 'o', 'o', '.', 'c', 'o', 'm', '\0', /* "chhy.at", true */ 'c', 'h', 'h', 'y', '.', 'a', 't', '\0', /* "chiaramail.com", true */ 'c', 'h', 'i', 'a', 'r', 'a', 'm', 'a', 'i', 'l', '.', 'c', 'o', 'm', '\0', @@ -2204,7 +2204,6 @@ /* "clvrwebdesign.com", true */ 'c', 'l', 'v', 'r', 'w', 'e', 'b', 'd', 'e', 's', 'i', 'g', 'n', '.', 'c', 'o', 'm', '\0', /* "clvs7.com", true */ 'c', 'l', 'v', 's', '7', '.', 'c', 'o', 'm', '\0', /* "clycat.ru", true */ 'c', 'l', 'y', 'c', 'a', 't', '.', 'r', 'u', '\0', - /* "clywedogmaths.co.uk", true */ 'c', 'l', 'y', 'w', 'e', 'd', 'o', 'g', 'm', 'a', 't', 'h', 's', '.', 'c', 'o', '.', 'u', 'k', '\0', /* "cmahy.be", true */ 'c', 'm', 'a', 'h', 'y', '.', 'b', 'e', '\0', /* "cmdline.org", true */ 'c', 'm', 'd', 'l', 'i', 'n', 'e', '.', 'o', 'r', 'g', '\0', /* "cmylife.nl", true */ 'c', 'm', 'y', 'l', 'i', 'f', 'e', '.', 'n', 'l', '\0', @@ -2215,16 +2214,15 @@ /* "co.search.yahoo.com", false */ 'c', 'o', '.', 's', 'e', 'a', 'r', 'c', 'h', '.', 'y', 'a', 'h', 'o', 'o', '.', 'c', 'o', 'm', '\0', /* "coachingconsultancy.com", true */ 'c', 'o', 'a', 'c', 'h', 'i', 'n', 'g', 'c', 'o', 'n', 's', 'u', 'l', 't', 'a', 'n', 'c', 'y', '.', 'c', 'o', 'm', '\0', /* "coalpointcottage.com", true */ 'c', 'o', 'a', 'l', 'p', 'o', 'i', 'n', 't', 'c', 'o', 't', 't', 'a', 'g', 'e', '.', 'c', 'o', 'm', '\0', - /* "coam.co", true */ 'c', 'o', 'a', 'm', '.', 'c', 'o', '\0', /* "cobalt.io", true */ 'c', 'o', 'b', 'a', 'l', 't', '.', 'i', 'o', '\0', /* "cocaine.ninja", true */ 'c', 'o', 'c', 'a', 'i', 'n', 'e', '.', 'n', 'i', 'n', 'j', 'a', '\0', /* "cocker.cc", false */ 'c', 'o', 'c', 'k', 'e', 'r', '.', 'c', 'c', '\0', /* "cocktailfuture.fr", true */ 'c', 'o', 'c', 'k', 't', 'a', 'i', 'l', 'f', 'u', 't', 'u', 'r', 'e', '.', 'f', 'r', '\0', /* "cocoaheads.at", false */ 'c', 'o', 'c', 'o', 'a', 'h', 'e', 'a', 'd', 's', '.', 'a', 't', '\0', - /* "cocolovesdaddy.com", true */ 'c', 'o', 'c', 'o', 'l', 'o', 'v', 'e', 's', 'd', 'a', 'd', 'd', 'y', '.', 'c', 'o', 'm', '\0', /* "code-poets.co.uk", true */ 'c', 'o', 'd', 'e', '-', 'p', 'o', 'e', 't', 's', '.', 'c', 'o', '.', 'u', 'k', '\0', /* "code-well.com", true */ 'c', 'o', 'd', 'e', '-', 'w', 'e', 'l', 'l', '.', 'c', 'o', 'm', '\0', /* "code.facebook.com", false */ 'c', 'o', 'd', 'e', '.', 'f', 'a', 'c', 'e', 'b', 'o', 'o', 'k', '.', 'c', 'o', 'm', '\0', + /* "code.fm", true */ 'c', 'o', 'd', 'e', '.', 'f', 'm', '\0', /* "code.google.com", true */ 'c', 'o', 'd', 'e', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm', '\0', /* "code67.com", true */ 'c', 'o', 'd', 'e', '6', '7', '.', 'c', 'o', 'm', '\0', /* "codeferm.com", true */ 'c', 'o', 'd', 'e', 'f', 'e', 'r', 'm', '.', 'c', 'o', 'm', '\0', @@ -2352,6 +2350,7 @@ /* "consciousbranding.org.au", true */ 'c', 'o', 'n', 's', 'c', 'i', 'o', 'u', 's', 'b', 'r', 'a', 'n', 'd', 'i', 'n', 'g', '.', 'o', 'r', 'g', '.', 'a', 'u', '\0', /* "consciousbrands.net.au", true */ 'c', 'o', 'n', 's', 'c', 'i', 'o', 'u', 's', 'b', 'r', 'a', 'n', 'd', 's', '.', 'n', 'e', 't', '.', 'a', 'u', '\0', /* "console.ninja", true */ 'c', 'o', 'n', 's', 'o', 'l', 'e', '.', 'n', 'i', 'n', 'j', 'a', '\0', + /* "console.support", true */ 'c', 'o', 'n', 's', 'o', 'l', 'e', '.', 's', 'u', 'p', 'p', 'o', 'r', 't', '\0', /* "consonare.de", true */ 'c', 'o', 'n', 's', 'o', 'n', 'a', 'r', 'e', '.', 'd', 'e', '\0', /* "constant-rough.de", true */ 'c', 'o', 'n', 's', 't', 'a', 'n', 't', '-', 'r', 'o', 'u', 'g', 'h', '.', 'd', 'e', '\0', /* "consul.io", true */ 'c', 'o', 'n', 's', 'u', 'l', '.', 'i', 'o', '\0', @@ -2424,6 +2423,7 @@ /* "cprnearme.com", true */ 'c', 'p', 'r', 'n', 'e', 'a', 'r', 'm', 'e', '.', 'c', 'o', 'm', '\0', /* "cpuvinf.eu.org", true */ 'c', 'p', 'u', 'v', 'i', 'n', 'f', '.', 'e', 'u', '.', 'o', 'r', 'g', '\0', /* "cpvmatch.eu", true */ 'c', 'p', 'v', 'm', 'a', 't', 'c', 'h', '.', 'e', 'u', '\0', + /* "cqchome.com", true */ 'c', 'q', 'c', 'h', 'o', 'm', 'e', '.', 'c', 'o', 'm', '\0', /* "cracker.in.th", true */ 'c', 'r', 'a', 'c', 'k', 'e', 'r', '.', 'i', 'n', '.', 't', 'h', '\0', /* "crackingking.com", false */ 'c', 'r', 'a', 'c', 'k', 'i', 'n', 'g', 'k', 'i', 'n', 'g', '.', 'c', 'o', 'm', '\0', /* "crackle.io", true */ 'c', 'r', 'a', 'c', 'k', 'l', 'e', '.', 'i', 'o', '\0', @@ -2435,7 +2435,6 @@ /* "craftmine.cz", true */ 'c', 'r', 'a', 'f', 't', 'm', 'i', 'n', 'e', '.', 'c', 'z', '\0', /* "craigfrancis.co.uk", true */ 'c', 'r', 'a', 'i', 'g', 'f', 'r', 'a', 'n', 'c', 'i', 's', '.', 'c', 'o', '.', 'u', 'k', '\0', /* "craigrouse.com", true */ 'c', 'r', 'a', 'i', 'g', 'r', 'o', 'u', 's', 'e', '.', 'c', 'o', 'm', '\0', - /* "cranesafe.com", true */ 'c', 'r', 'a', 'n', 'e', 's', 'a', 'f', 'e', '.', 'c', 'o', 'm', '\0', /* "crazifyngers.com", true */ 'c', 'r', 'a', 'z', 'i', 'f', 'y', 'n', 'g', 'e', 'r', 's', '.', 'c', 'o', 'm', '\0', /* "crazy-crawler.de", true */ 'c', 'r', 'a', 'z', 'y', '-', 'c', 'r', 'a', 'w', 'l', 'e', 'r', '.', 'd', 'e', '\0', /* "crazydomains.ae", true */ 'c', 'r', 'a', 'z', 'y', 'd', 'o', 'm', 'a', 'i', 'n', 's', '.', 'a', 'e', '\0', @@ -2470,6 +2469,7 @@ /* "crosscom.ch", true */ 'c', 'r', 'o', 's', 's', 'c', 'o', 'm', '.', 'c', 'h', '\0', /* "crossfitblackwater.com", true */ 'c', 'r', 'o', 's', 's', 'f', 'i', 't', 'b', 'l', 'a', 'c', 'k', 'w', 'a', 't', 'e', 'r', '.', 'c', 'o', 'm', '\0', /* "crosssellguide.com", true */ 'c', 'r', 'o', 's', 's', 's', 'e', 'l', 'l', 'g', 'u', 'i', 'd', 'e', '.', 'c', 'o', 'm', '\0', + /* "crow.tw", true */ 'c', 'r', 'o', 'w', '.', 't', 'w', '\0', /* "crowdsupply.com", true */ 'c', 'r', 'o', 'w', 'd', 's', 'u', 'p', 'p', 'l', 'y', '.', 'c', 'o', 'm', '\0', /* "crownruler.com", true */ 'c', 'r', 'o', 'w', 'n', 'r', 'u', 'l', 'e', 'r', '.', 'c', 'o', 'm', '\0', /* "crstat.ru", true */ 'c', 'r', 's', 't', 'a', 't', '.', 'r', 'u', '\0', @@ -2478,6 +2478,7 @@ /* "crumbcontrol.com", true */ 'c', 'r', 'u', 'm', 'b', 'c', 'o', 'n', 't', 'r', 'o', 'l', '.', 'c', 'o', 'm', '\0', /* "crushroom.com", true */ 'c', 'r', 'u', 's', 'h', 'r', 'o', 'o', 'm', '.', 'c', 'o', 'm', '\0', /* "crute.me", true */ 'c', 'r', 'u', 't', 'e', '.', 'm', 'e', '\0', + /* "crvv.me", true */ 'c', 'r', 'v', 'v', '.', 'm', 'e', '\0', /* "cryptearth.de", true */ 'c', 'r', 'y', 'p', 't', 'e', 'a', 'r', 't', 'h', '.', 'd', 'e', '\0', /* "crypticshell.co.uk", true */ 'c', 'r', 'y', 'p', 't', 'i', 'c', 's', 'h', 'e', 'l', 'l', '.', 'c', 'o', '.', 'u', 'k', '\0', /* "crypto.cat", false */ 'c', 'r', 'y', 'p', 't', 'o', '.', 'c', 'a', 't', '\0', @@ -2505,6 +2506,7 @@ /* "cs-ubladego.pl", true */ 'c', 's', '-', 'u', 'b', 'l', 'a', 'd', 'e', 'g', 'o', '.', 'p', 'l', '\0', /* "csacongress.org", true */ 'c', 's', 'a', 'c', 'o', 'n', 'g', 'r', 'e', 's', 's', '.', 'o', 'r', 'g', '\0', /* "csbs.fr", true */ 'c', 's', 'b', 's', '.', 'f', 'r', '\0', + /* "cselzer.com", false */ 'c', 's', 'e', 'l', 'z', 'e', 'r', '.', 'c', 'o', 'm', '\0', /* "csengle.de", true */ 'c', 's', 'e', 'n', 'g', 'l', 'e', '.', 'd', 'e', '\0', /* "csfm.com", true */ 'c', 's', 'f', 'm', '.', 'c', 'o', 'm', '\0', /* "csgohandouts.com", true */ 'c', 's', 'g', 'o', 'h', 'a', 'n', 'd', 'o', 'u', 't', 's', '.', 'c', 'o', 'm', '\0', @@ -2538,7 +2540,6 @@ /* "culinae.nl", true */ 'c', 'u', 'l', 'i', 'n', 'a', 'e', '.', 'n', 'l', '\0', /* "cultiv.nl", true */ 'c', 'u', 'l', 't', 'i', 'v', '.', 'n', 'l', '\0', /* "culturedcode.com", true */ 'c', 'u', 'l', 't', 'u', 'r', 'e', 'd', 'c', 'o', 'd', 'e', '.', 'c', 'o', 'm', '\0', - /* "cuongquach.com", true */ 'c', 'u', 'o', 'n', 'g', 'q', 'u', 'a', 'c', 'h', '.', 'c', 'o', 'm', '\0', /* "cuonic.com", true */ 'c', 'u', 'o', 'n', 'i', 'c', '.', 'c', 'o', 'm', '\0', /* "cup.al", true */ 'c', 'u', 'p', '.', 'a', 'l', '\0', /* "cupcake.io", true */ 'c', 'u', 'p', 'c', 'a', 'k', 'e', '.', 'i', 'o', '\0', @@ -2844,6 +2845,7 @@ /* "denardbrewing.com", true */ 'd', 'e', 'n', 'a', 'r', 'd', 'b', 'r', 'e', 'w', 'i', 'n', 'g', '.', 'c', 'o', 'm', '\0', /* "dengchangdong.com", true */ 'd', 'e', 'n', 'g', 'c', 'h', 'a', 'n', 'g', 'd', 'o', 'n', 'g', '.', 'c', 'o', 'm', '\0', /* "denimio.com", true */ 'd', 'e', 'n', 'i', 'm', 'i', 'o', '.', 'c', 'o', 'm', '\0', + /* "dennisdoes.net", true */ 'd', 'e', 'n', 'n', 'i', 's', 'd', 'o', 'e', 's', '.', 'n', 'e', 't', '\0', /* "denniskoot.nl", true */ 'd', 'e', 'n', 'n', 'i', 's', 'k', 'o', 'o', 't', '.', 'n', 'l', '\0', /* "dennogumi.org", true */ 'd', 'e', 'n', 'n', 'o', 'g', 'u', 'm', 'i', '.', 'o', 'r', 'g', '\0', /* "dentallaborgeraeteservice.de", true */ 'd', 'e', 'n', 't', 'a', 'l', 'l', 'a', 'b', 'o', 'r', 'g', 'e', 'r', 'a', 'e', 't', 'e', 's', 'e', 'r', 'v', 'i', 'c', 'e', '.', 'd', 'e', '\0', @@ -2884,7 +2886,6 @@ /* "dethemium.com", true */ 'd', 'e', 't', 'h', 'e', 'm', 'i', 'u', 'm', '.', 'c', 'o', 'm', '\0', /* "detoxsinutritie.ro", true */ 'd', 'e', 't', 'o', 'x', 's', 'i', 'n', 'u', 't', 'r', 'i', 't', 'i', 'e', '.', 'r', 'o', '\0', /* "detteflies.com", true */ 'd', 'e', 't', 't', 'e', 'f', 'l', 'i', 'e', 's', '.', 'c', 'o', 'm', '\0', - /* "detutorial.com", true */ 'd', 'e', 't', 'u', 't', 'o', 'r', 'i', 'a', 'l', '.', 'c', 'o', 'm', '\0', /* "deusu.de", true */ 'd', 'e', 'u', 's', 'u', '.', 'd', 'e', '\0', /* "deusu.org", true */ 'd', 'e', 'u', 's', 'u', '.', 'o', 'r', 'g', '\0', /* "dev-tek.de", true */ 'd', 'e', 'v', '-', 't', 'e', 'k', '.', 'd', 'e', '\0', @@ -2996,6 +2997,7 @@ /* "dinube.com", true */ 'd', 'i', 'n', 'u', 'b', 'e', '.', 'c', 'o', 'm', '\0', /* "diodeled.com", true */ 'd', 'i', 'o', 'd', 'e', 'l', 'e', 'd', '.', 'c', 'o', 'm', '\0', /* "dipconsultants.com", true */ 'd', 'i', 'p', 'c', 'o', 'n', 's', 'u', 'l', 't', 'a', 'n', 't', 's', '.', 'c', 'o', 'm', '\0', + /* "dipl.io", false */ 'd', 'i', 'p', 'l', '.', 'i', 'o', '\0', /* "dipulse.it", true */ 'd', 'i', 'p', 'u', 'l', 's', 'e', '.', 'i', 't', '\0', /* "dir2epub.com", true */ 'd', 'i', 'r', '2', 'e', 'p', 'u', 'b', '.', 'c', 'o', 'm', '\0', /* "dir2epub.org", true */ 'd', 'i', 'r', '2', 'e', 'p', 'u', 'b', '.', 'o', 'r', 'g', '\0', @@ -3059,7 +3061,6 @@ /* "dmlogic.com", true */ 'd', 'm', 'l', 'o', 'g', 'i', 'c', '.', 'c', 'o', 'm', '\0', /* "dmtry.me", true */ 'd', 'm', 't', 'r', 'y', '.', 'm', 'e', '\0', /* "dmwall.cn", true */ 'd', 'm', 'w', 'a', 'l', 'l', '.', 'c', 'n', '\0', - /* "dmxledlights.com", true */ 'd', 'm', 'x', 'l', 'e', 'd', 'l', 'i', 'g', 'h', 't', 's', '.', 'c', 'o', 'm', '\0', /* "dmz.ninja", true */ 'd', 'm', 'z', '.', 'n', 'i', 'n', 'j', 'a', '\0', /* "dn3s.me", true */ 'd', 'n', '3', 's', '.', 'm', 'e', '\0', /* "dn42.us", true */ 'd', 'n', '4', '2', '.', 'u', 's', '\0', @@ -3119,6 +3120,7 @@ /* "domhaase.me", true */ 'd', 'o', 'm', 'h', 'a', 'a', 's', 'e', '.', 'm', 'e', '\0', /* "dominationgame.co.uk", true */ 'd', 'o', 'm', 'i', 'n', 'a', 't', 'i', 'o', 'n', 'g', 'a', 'm', 'e', '.', 'c', 'o', '.', 'u', 'k', '\0', /* "dominicpratt.de", false */ 'd', 'o', 'm', 'i', 'n', 'i', 'c', 'p', 'r', 'a', 't', 't', '.', 'd', 'e', '\0', + /* "dominikkulaga.pl", true */ 'd', 'o', 'm', 'i', 'n', 'i', 'k', 'k', 'u', 'l', 'a', 'g', 'a', '.', 'p', 'l', '\0', /* "domodedovo.travel", true */ 'd', 'o', 'm', 'o', 'd', 'e', 'd', 'o', 'v', 'o', '.', 't', 'r', 'a', 'v', 'e', 'l', '\0', /* "donateaday.net", true */ 'd', 'o', 'n', 'a', 't', 'e', 'a', 'd', 'a', 'y', '.', 'n', 'e', 't', '\0', /* "donkeytrekkingkefalonia.com", true */ 'd', 'o', 'n', 'k', 'e', 'y', 't', 'r', 'e', 'k', 'k', 'i', 'n', 'g', 'k', 'e', 'f', 'a', 'l', 'o', 'n', 'i', 'a', '.', 'c', 'o', 'm', '\0', @@ -3133,6 +3135,7 @@ /* "dontcageus.org", true */ 'd', 'o', 'n', 't', 'c', 'a', 'g', 'e', 'u', 's', '.', 'o', 'r', 'g', '\0', /* "donthedragonwilson.com", true */ 'd', 'o', 'n', 't', 'h', 'e', 'd', 'r', 'a', 'g', 'o', 'n', 'w', 'i', 'l', 's', 'o', 'n', '.', 'c', 'o', 'm', '\0', /* "donttrustrobots.nl", true */ 'd', 'o', 'n', 't', 't', 'r', 'u', 's', 't', 'r', 'o', 'b', 'o', 't', 's', '.', 'n', 'l', '\0', + /* "doobydude.us", true */ 'd', 'o', 'o', 'b', 'y', 'd', 'u', 'd', 'e', '.', 'u', 's', '\0', /* "doodledraw.ninja", true */ 'd', 'o', 'o', 'd', 'l', 'e', 'd', 'r', 'a', 'w', '.', 'n', 'i', 'n', 'j', 'a', '\0', /* "dooku.cz", true */ 'd', 'o', 'o', 'k', 'u', '.', 'c', 'z', '\0', /* "dooleytackaberry.com", true */ 'd', 'o', 'o', 'l', 'e', 'y', 't', 'a', 'c', 'k', 'a', 'b', 'e', 'r', 'r', 'y', '.', 'c', 'o', 'm', '\0', @@ -3225,7 +3228,6 @@ /* "dsol.hu", true */ 'd', 's', 'o', 'l', '.', 'h', 'u', '\0', /* "dt27.org", true */ 'd', 't', '2', '7', '.', 'o', 'r', 'g', '\0', /* "dubaieveningsafari.com", true */ 'd', 'u', 'b', 'a', 'i', 'e', 'v', 'e', 'n', 'i', 'n', 'g', 's', 'a', 'f', 'a', 'r', 'i', '.', 'c', 'o', 'm', '\0', - /* "duch.cloud", true */ 'd', 'u', 'c', 'h', '.', 'c', 'l', 'o', 'u', 'd', '\0', /* "duckasylum.com", true */ 'd', 'u', 'c', 'k', 'a', 's', 'y', 'l', 'u', 'm', '.', 'c', 'o', 'm', '\0', /* "duckduckstart.com", true */ 'd', 'u', 'c', 'k', 'd', 'u', 'c', 'k', 's', 't', 'a', 'r', 't', '.', 'c', 'o', 'm', '\0', /* "duckinc.net", true */ 'd', 'u', 'c', 'k', 'i', 'n', 'c', '.', 'n', 'e', 't', '\0', @@ -3299,6 +3301,7 @@ /* "easez.net", true */ 'e', 'a', 's', 'e', 'z', '.', 'n', 'e', 't', '\0', /* "eastmontgroup.com", true */ 'e', 'a', 's', 't', 'm', 'o', 'n', 't', 'g', 'r', 'o', 'u', 'p', '.', 'c', 'o', 'm', '\0', /* "easy-rpg.org", false */ 'e', 'a', 's', 'y', '-', 'r', 'p', 'g', '.', 'o', 'r', 'g', '\0', + /* "easychiller.org", true */ 'e', 'a', 's', 'y', 'c', 'h', 'i', 'l', 'l', 'e', 'r', '.', 'o', 'r', 'g', '\0', /* "easyconstat.com", true */ 'e', 'a', 's', 'y', 'c', 'o', 'n', 's', 't', 'a', 't', '.', 'c', 'o', 'm', '\0', /* "easycosmetic.ch", true */ 'e', 'a', 's', 'y', 'c', 'o', 's', 'm', 'e', 't', 'i', 'c', '.', 'c', 'h', '\0', /* "easykonto.de", true */ 'e', 'a', 's', 'y', 'k', 'o', 'n', 't', 'o', '.', 'd', 'e', '\0', @@ -3326,6 +3329,7 @@ /* "ecco-verde.com", false */ 'e', 'c', 'c', 'o', '-', 'v', 'e', 'r', 'd', 'e', '.', 'c', 'o', 'm', '\0', /* "echipstore.com", true */ 'e', 'c', 'h', 'i', 'p', 's', 't', 'o', 'r', 'e', '.', 'c', 'o', 'm', '\0', /* "echomanchester.net", true */ 'e', 'c', 'h', 'o', 'm', 'a', 'n', 'c', 'h', 'e', 's', 't', 'e', 'r', '.', 'n', 'e', 't', '\0', + /* "echopaper.com", true */ 'e', 'c', 'h', 'o', 'p', 'a', 'p', 'e', 'r', '.', 'c', 'o', 'm', '\0', /* "echosixmonkey.com", true */ 'e', 'c', 'h', 'o', 's', 'i', 'x', 'm', 'o', 'n', 'k', 'e', 'y', '.', 'c', 'o', 'm', '\0', /* "eckel.co", true */ 'e', 'c', 'k', 'e', 'l', '.', 'c', 'o', '\0', /* "eckro.com", true */ 'e', 'c', 'k', 'r', 'o', '.', 'c', 'o', 'm', '\0', @@ -3428,6 +3432,7 @@ /* "elaxy-online.de", true */ 'e', 'l', 'a', 'x', 'y', '-', 'o', 'n', 'l', 'i', 'n', 'e', '.', 'd', 'e', '\0', /* "elbetech.net", true */ 'e', 'l', 'b', 'e', 't', 'e', 'c', 'h', '.', 'n', 'e', 't', '\0', /* "elblein.de", true */ 'e', 'l', 'b', 'l', 'e', 'i', 'n', '.', 'd', 'e', '\0', + /* "eldinhadzic.com", true */ 'e', 'l', 'd', 'i', 'n', 'h', 'a', 'd', 'z', 'i', 'c', '.', 'c', 'o', 'm', '\0', /* "elearningpilot.com", true */ 'e', 'l', 'e', 'a', 'r', 'n', 'i', 'n', 'g', 'p', 'i', 'l', 'o', 't', '.', 'c', 'o', 'm', '\0', /* "electricant.com", true */ 'e', 'l', 'e', 'c', 't', 'r', 'i', 'c', 'a', 'n', 't', '.', 'c', 'o', 'm', '\0', /* "electricant.nl", true */ 'e', 'l', 'e', 'c', 't', 'r', 'i', 'c', 'a', 'n', 't', '.', 'n', 'l', '\0', @@ -3554,7 +3559,6 @@ /* "enskatson-sippe.de", true */ 'e', 'n', 's', 'k', 'a', 't', 's', 'o', 'n', '-', 's', 'i', 'p', 'p', 'e', '.', 'd', 'e', '\0', /* "ensured.com", true */ 'e', 'n', 's', 'u', 'r', 'e', 'd', '.', 'c', 'o', 'm', '\0', /* "ensured.nl", true */ 'e', 'n', 's', 'u', 'r', 'e', 'd', '.', 'n', 'l', '\0', - /* "enteente.com", true */ 'e', 'n', 't', 'e', 'e', 'n', 't', 'e', '.', 'c', 'o', 'm', '\0', /* "enterprisecarclub.co.uk", true */ 'e', 'n', 't', 'e', 'r', 'p', 'r', 'i', 's', 'e', 'c', 'a', 'r', 'c', 'l', 'u', 'b', '.', 'c', 'o', '.', 'u', 'k', '\0', /* "entourneebeetle.com", true */ 'e', 'n', 't', 'o', 'u', 'r', 'n', 'e', 'e', 'b', 'e', 'e', 't', 'l', 'e', '.', 'c', 'o', 'm', '\0', /* "entrainr.com", true */ 'e', 'n', 't', 'r', 'a', 'i', 'n', 'r', '.', 'c', 'o', 'm', '\0', @@ -3649,6 +3653,7 @@ /* "estebanborges.com", true */ 'e', 's', 't', 'e', 'b', 'a', 'n', 'b', 'o', 'r', 'g', 'e', 's', '.', 'c', 'o', 'm', '\0', /* "estoic.net", true */ 'e', 's', 't', 'o', 'i', 'c', '.', 'n', 'e', 't', '\0', /* "estrietoit.com", false */ 'e', 's', 't', 'r', 'i', 'e', 't', 'o', 'i', 't', '.', 'c', 'o', 'm', '\0', + /* "et-buchholz.de", true */ 'e', 't', '-', 'b', 'u', 'c', 'h', 'h', 'o', 'l', 'z', '.', 'd', 'e', '\0', /* "etaes.eu", true */ 'e', 't', 'a', 'e', 's', '.', 'e', 'u', '\0', /* "etaxi.tn", true */ 'e', 't', 'a', 'x', 'i', '.', 't', 'n', '\0', /* "eteesheet.com", true */ 'e', 't', 'e', 'e', 's', 'h', 'e', 'e', 't', '.', 'c', 'o', 'm', '\0', @@ -3662,7 +3667,6 @@ /* "ethercalc.org", true */ 'e', 't', 'h', 'e', 'r', 'c', 'a', 'l', 'c', '.', 'o', 'r', 'g', '\0', /* "etherpad.fr", true */ 'e', 't', 'h', 'e', 'r', 'p', 'a', 'd', '.', 'f', 'r', '\0', /* "ethicaldata.co.uk", true */ 'e', 't', 'h', 'i', 'c', 'a', 'l', 'd', 'a', 't', 'a', '.', 'c', 'o', '.', 'u', 'k', '\0', - /* "ethicalexploiting.com", true */ 'e', 't', 'h', 'i', 'c', 'a', 'l', 'e', 'x', 'p', 'l', 'o', 'i', 't', 'i', 'n', 'g', '.', 'c', 'o', 'm', '\0', /* "ethicall.org.uk", true */ 'e', 't', 'h', 'i', 'c', 'a', 'l', 'l', '.', 'o', 'r', 'g', '.', 'u', 'k', '\0', /* "ethil-faer.fr", true */ 'e', 't', 'h', 'i', 'l', '-', 'f', 'a', 'e', 'r', '.', 'f', 'r', '\0', /* "ethiopian.dating", true */ 'e', 't', 'h', 'i', 'o', 'p', 'i', 'a', 'n', '.', 'd', 'a', 't', 'i', 'n', 'g', '\0', @@ -3950,7 +3954,6 @@ /* "finkelstein.fr", true */ 'f', 'i', 'n', 'k', 'e', 'l', 's', 't', 'e', 'i', 'n', '.', 'f', 'r', '\0', /* "finn.io", true */ 'f', 'i', 'n', 'n', '.', 'i', 'o', '\0', /* "finneas.net", true */ 'f', 'i', 'n', 'n', 'e', 'a', 's', '.', 'n', 'e', 't', '\0', - /* "finpt.com", true */ 'f', 'i', 'n', 'p', 't', '.', 'c', 'o', 'm', '\0', /* "finstererlebnis.de", true */ 'f', 'i', 'n', 's', 't', 'e', 'r', 'e', 'r', 'l', 'e', 'b', 'n', 'i', 's', '.', 'd', 'e', '\0', /* "finsterlebnis.de", true */ 'f', 'i', 'n', 's', 't', 'e', 'r', 'l', 'e', 'b', 'n', 'i', 's', '.', 'd', 'e', '\0', /* "fionamcbride.com", true */ 'f', 'i', 'o', 'n', 'a', 'm', 'c', 'b', 'r', 'i', 'd', 'e', '.', 'c', 'o', 'm', '\0', @@ -3982,12 +3985,10 @@ /* "fitkram.cz", true */ 'f', 'i', 't', 'k', 'r', 'a', 'm', '.', 'c', 'z', '\0', /* "fittelo.cz", true */ 'f', 'i', 't', 't', 'e', 'l', 'o', '.', 'c', 'z', '\0', /* "fitzsim.org", true */ 'f', 'i', 't', 'z', 's', 'i', 'm', '.', 'o', 'r', 'g', '\0', - /* "fiws.net", true */ 'f', 'i', 'w', 's', '.', 'n', 'e', 't', '\0', /* "fixel.express", true */ 'f', 'i', 'x', 'e', 'l', '.', 'e', 'x', 'p', 'r', 'e', 's', 's', '\0', /* "fixforce.nl", true */ 'f', 'i', 'x', 'f', 'o', 'r', 'c', 'e', '.', 'n', 'l', '\0', /* "fixhotsauce.com", true */ 'f', 'i', 'x', 'h', 'o', 't', 's', 'a', 'u', 'c', 'e', '.', 'c', 'o', 'm', '\0', /* "fixmycomputerdude.com", true */ 'f', 'i', 'x', 'm', 'y', 'c', 'o', 'm', 'p', 'u', 't', 'e', 'r', 'd', 'u', 'd', 'e', '.', 'c', 'o', 'm', '\0', - /* "fizz.buzz", true */ 'f', 'i', 'z', 'z', '.', 'b', 'u', 'z', 'z', '\0', /* "fj.simple.com", false */ 'f', 'j', '.', 's', 'i', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm', '\0', /* "fjruiz.es", true */ 'f', 'j', 'r', 'u', 'i', 'z', '.', 'e', 's', '\0', /* "flaemig42.de", true */ 'f', 'l', 'a', 'e', 'm', 'i', 'g', '4', '2', '.', 'd', 'e', '\0', @@ -4047,6 +4048,7 @@ /* "fluxent.de", false */ 'f', 'l', 'u', 'x', 'e', 'n', 't', '.', 'd', 'e', '\0', /* "fluxfingers.net", true */ 'f', 'l', 'u', 'x', 'f', 'i', 'n', 'g', 'e', 'r', 's', '.', 'n', 'e', 't', '\0', /* "fluxforge.com", true */ 'f', 'l', 'u', 'x', 'f', 'o', 'r', 'g', 'e', '.', 'c', 'o', 'm', '\0', + /* "fly.moe", true */ 'f', 'l', 'y', '.', 'm', 'o', 'e', '\0', /* "flynn.io", true */ 'f', 'l', 'y', 'n', 'n', '.', 'i', 'o', '\0', /* "flyserver.co.il", true */ 'f', 'l', 'y', 's', 'e', 'r', 'v', 'e', 'r', '.', 'c', 'o', '.', 'i', 'l', '\0', /* "fm.ie", true */ 'f', 'm', '.', 'i', 'e', '\0', @@ -4066,6 +4068,7 @@ /* "font-converter.net", true */ 'f', 'o', 'n', 't', '-', 'c', 'o', 'n', 'v', 'e', 'r', 't', 'e', 'r', '.', 'n', 'e', 't', '\0', /* "fontein.de", true */ 'f', 'o', 'n', 't', 'e', 'i', 'n', '.', 'd', 'e', '\0', /* "fontlibrary.org", true */ 'f', 'o', 'n', 't', 'l', 'i', 'b', 'r', 'a', 'r', 'y', '.', 'o', 'r', 'g', '\0', + /* "foodacademy.capetown", true */ 'f', 'o', 'o', 'd', 'a', 'c', 'a', 'd', 'e', 'm', 'y', '.', 'c', 'a', 'p', 'e', 't', 'o', 'w', 'n', '\0', /* "foodblogger.club", true */ 'f', 'o', 'o', 'd', 'b', 'l', 'o', 'g', 'g', 'e', 'r', '.', 'c', 'l', 'u', 'b', '\0', /* "foodiebox.no", true */ 'f', 'o', 'o', 'd', 'i', 'e', 'b', 'o', 'x', '.', 'n', 'o', '\0', /* "foodies.my", true */ 'f', 'o', 'o', 'd', 'i', 'e', 's', '.', 'm', 'y', '\0', @@ -4192,7 +4195,6 @@ /* "fromlemaytoz.com", true */ 'f', 'r', 'o', 'm', 'l', 'e', 'm', 'a', 'y', 't', 'o', 'z', '.', 'c', 'o', 'm', '\0', /* "fromscratch.rocks", true */ 'f', 'r', 'o', 'm', 's', 'c', 'r', 'a', 't', 'c', 'h', '.', 'r', 'o', 'c', 'k', 's', '\0', /* "fronteers.nl", true */ 'f', 'r', 'o', 'n', 't', 'e', 'e', 'r', 's', '.', 'n', 'l', '\0', - /* "frontisme.nl", true */ 'f', 'r', 'o', 'n', 't', 'i', 's', 'm', 'e', '.', 'n', 'l', '\0', /* "froot.se", true */ 'f', 'r', 'o', 'o', 't', '.', 's', 'e', '\0', /* "frosty-gaming.xyz", true */ 'f', 'r', 'o', 's', 't', 'y', '-', 'g', 'a', 'm', 'i', 'n', 'g', '.', 'x', 'y', 'z', '\0', /* "frothy.coffee", true */ 'f', 'r', 'o', 't', 'h', 'y', '.', 'c', 'o', 'f', 'f', 'e', 'e', '\0', @@ -4423,7 +4425,6 @@ /* "getcloak.com", false */ 'g', 'e', 't', 'c', 'l', 'o', 'a', 'k', '.', 'c', 'o', 'm', '\0', /* "getcolq.com", true */ 'g', 'e', 't', 'c', 'o', 'l', 'q', '.', 'c', 'o', 'm', '\0', /* "getdash.io", true */ 'g', 'e', 't', 'd', 'a', 's', 'h', '.', 'i', 'o', '\0', - /* "getdigitized.net", true */ 'g', 'e', 't', 'd', 'i', 'g', 'i', 't', 'i', 'z', 'e', 'd', '.', 'n', 'e', 't', '\0', /* "geterp.ru", true */ 'g', 'e', 't', 'e', 'r', 'p', '.', 'r', 'u', '\0', /* "getfedora.org", true */ 'g', 'e', 't', 'f', 'e', 'd', 'o', 'r', 'a', '.', 'o', 'r', 'g', '\0', /* "getfittedstore.com", true */ 'g', 'e', 't', 'f', 'i', 't', 't', 'e', 'd', 's', 't', 'o', 'r', 'e', '.', 'c', 'o', 'm', '\0', @@ -4663,8 +4664,6 @@ /* "greensolid.biz", true */ 'g', 'r', 'e', 'e', 'n', 's', 'o', 'l', 'i', 'd', '.', 'b', 'i', 'z', '\0', /* "greenteamtwente.nl", true */ 'g', 'r', 'e', 'e', 'n', 't', 'e', 'a', 'm', 't', 'w', 'e', 'n', 't', 'e', '.', 'n', 'l', '\0', /* "greg.red", true */ 'g', 'r', 'e', 'g', '.', 'r', 'e', 'd', '\0', - /* "gregmilton.com", true */ 'g', 'r', 'e', 'g', 'm', 'i', 'l', 't', 'o', 'n', '.', 'c', 'o', 'm', '\0', - /* "gregmilton.org", true */ 'g', 'r', 'e', 'g', 'm', 'i', 'l', 't', 'o', 'n', '.', 'o', 'r', 'g', '\0', /* "gregorians.org", true */ 'g', 'r', 'e', 'g', 'o', 'r', 'i', 'a', 'n', 's', '.', 'o', 'r', 'g', '\0', /* "gregorywiest.com", true */ 'g', 'r', 'e', 'g', 'o', 'r', 'y', 'w', 'i', 'e', 's', 't', '.', 'c', 'o', 'm', '\0', /* "greiners.net", true */ 'g', 'r', 'e', 'i', 'n', 'e', 'r', 's', '.', 'n', 'e', 't', '\0', @@ -4734,7 +4733,6 @@ /* "gugaltika-ipb.org", true */ 'g', 'u', 'g', 'a', 'l', 't', 'i', 'k', 'a', '-', 'i', 'p', 'b', '.', 'o', 'r', 'g', '\0', /* "gugga.dk", true */ 'g', 'u', 'g', 'g', 'a', '.', 'd', 'k', '\0', /* "guguke.net", true */ 'g', 'u', 'g', 'u', 'k', 'e', '.', 'n', 'e', 't', '\0', - /* "guhenry3.tk", true */ 'g', 'u', 'h', 'e', 'n', 'r', 'y', '3', '.', 't', 'k', '\0', /* "guidetoiceland.is", false */ 'g', 'u', 'i', 'd', 'e', 't', 'o', 'i', 'c', 'e', 'l', 'a', 'n', 'd', '.', 'i', 's', '\0', /* "guillaume-leduc.fr", true */ 'g', 'u', 'i', 'l', 'l', 'a', 'u', 'm', 'e', '-', 'l', 'e', 'd', 'u', 'c', '.', 'f', 'r', '\0', /* "guillaumeperrin.io", true */ 'g', 'u', 'i', 'l', 'l', 'a', 'u', 'm', 'e', 'p', 'e', 'r', 'r', 'i', 'n', '.', 'i', 'o', '\0', @@ -4785,7 +4783,6 @@ /* "habbo.life", true */ 'h', 'a', 'b', 'b', 'o', '.', 'l', 'i', 'f', 'e', '\0', /* "habbotalk.nl", true */ 'h', 'a', 'b', 'b', 'o', 't', 'a', 'l', 'k', '.', 'n', 'l', '\0', /* "hachre.de", false */ 'h', 'a', 'c', 'h', 'r', 'e', '.', 'd', 'e', '\0', - /* "hack.cz", true */ 'h', 'a', 'c', 'k', '.', 'c', 'z', '\0', /* "hackcraft.net", true */ 'h', 'a', 'c', 'k', 'c', 'r', 'a', 'f', 't', '.', 'n', 'e', 't', '\0', /* "hackenkunjeleren.nl", true */ 'h', 'a', 'c', 'k', 'e', 'n', 'k', 'u', 'n', 'j', 'e', 'l', 'e', 'r', 'e', 'n', '.', 'n', 'l', '\0', /* "hackenturet.dk", true */ 'h', 'a', 'c', 'k', 'e', 'n', 't', 'u', 'r', 'e', 't', '.', 'd', 'k', '\0', @@ -4796,7 +4793,7 @@ /* "hackerone-user-content.com", true */ 'h', 'a', 'c', 'k', 'e', 'r', 'o', 'n', 'e', '-', 'u', 's', 'e', 'r', '-', 'c', 'o', 'n', 't', 'e', 'n', 't', '.', 'c', 'o', 'm', '\0', /* "hackerone.com", true */ 'h', 'a', 'c', 'k', 'e', 'r', 'o', 'n', 'e', '.', 'c', 'o', 'm', '\0', /* "hackerstxt.org", true */ 'h', 'a', 'c', 'k', 'e', 'r', 's', 't', 'x', 't', '.', 'o', 'r', 'g', '\0', - /* "hackest.org", true */ 'h', 'a', 'c', 'k', 'e', 's', 't', '.', 'o', 'r', 'g', '\0', + /* "hackmd.io", true */ 'h', 'a', 'c', 'k', 'm', 'd', '.', 'i', 'o', '\0', /* "hacksnack.io", true */ 'h', 'a', 'c', 'k', 's', 'n', 'a', 'c', 'k', '.', 'i', 'o', '\0', /* "hackthissite.org", true */ 'h', 'a', 'c', 'k', 't', 'h', 'i', 's', 's', 'i', 't', 'e', '.', 'o', 'r', 'g', '\0', /* "hacktivis.me", true */ 'h', 'a', 'c', 'k', 't', 'i', 'v', 'i', 's', '.', 'm', 'e', '\0', @@ -4808,6 +4805,7 @@ /* "hail2u.net", true */ 'h', 'a', 'i', 'l', '2', 'u', '.', 'n', 'e', 't', '\0', /* "hailer.com", true */ 'h', 'a', 'i', 'l', 'e', 'r', '.', 'c', 'o', 'm', '\0', /* "haircrazy.com", true */ 'h', 'a', 'i', 'r', 'c', 'r', 'a', 'z', 'y', '.', 'c', 'o', 'm', '\0', + /* "hajnzic.at", true */ 'h', 'a', 'j', 'n', 'z', 'i', 'c', '.', 'a', 't', '\0', /* "hakase.kr", true */ 'h', 'a', 'k', 'a', 's', 'e', '.', 'k', 'r', '\0', /* "hakatabijin-mind.com", true */ 'h', 'a', 'k', 'a', 't', 'a', 'b', 'i', 'j', 'i', 'n', '-', 'm', 'i', 'n', 'd', '.', 'c', 'o', 'm', '\0', /* "hake.me", true */ 'h', 'a', 'k', 'e', '.', 'm', 'e', '\0', @@ -5022,6 +5020,7 @@ /* "hititgunesi-tr.com", true */ 'h', 'i', 't', 'i', 't', 'g', 'u', 'n', 'e', 's', 'i', '-', 't', 'r', '.', 'c', 'o', 'm', '\0', /* "hiv.gov", true */ 'h', 'i', 'v', '.', 'g', 'o', 'v', '\0', /* "hiverlune.net", true */ 'h', 'i', 'v', 'e', 'r', 'l', 'u', 'n', 'e', '.', 'n', 'e', 't', '\0', + /* "hjw-kunstwerk.de", true */ 'h', 'j', 'w', '-', 'k', 'u', 'n', 's', 't', 'w', 'e', 'r', 'k', '.', 'd', 'e', '\0', /* "hk.search.yahoo.com", false */ 'h', 'k', '.', 's', 'e', 'a', 'r', 'c', 'h', '.', 'y', 'a', 'h', 'o', 'o', '.', 'c', 'o', 'm', '\0', /* "hlavacek.us", true */ 'h', 'l', 'a', 'v', 'a', 'c', 'e', 'k', '.', 'u', 's', '\0', /* "hledejlevne.cz", true */ 'h', 'l', 'e', 'd', 'e', 'j', 'l', 'e', 'v', 'n', 'e', '.', 'c', 'z', '\0', @@ -5269,12 +5268,10 @@ /* "ifconfig.co", true */ 'i', 'f', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', '\0', /* "iflare.de", true */ 'i', 'f', 'l', 'a', 'r', 'e', '.', 'd', 'e', '\0', /* "iformbuilder.com", false */ 'i', 'f', 'o', 'r', 'm', 'b', 'u', 'i', 'l', 'd', 'e', 'r', '.', 'c', 'o', 'm', '\0', - /* "ifoss.me", true */ 'i', 'f', 'o', 's', 's', '.', 'm', 'e', '\0', /* "ifsac.org", true */ 'i', 'f', 's', 'a', 'c', '.', 'o', 'r', 'g', '\0', /* "ifsr.de", true */ 'i', 'f', 's', 'r', '.', 'd', 'e', '\0', /* "iftrue.de", true */ 'i', 'f', 't', 'r', 'u', 'e', '.', 'd', 'e', '\0', /* "ifxor.com", true */ 'i', 'f', 'x', 'o', 'r', '.', 'c', 'o', 'm', '\0', - /* "igforums.com", true */ 'i', 'g', 'f', 'o', 'r', 'u', 'm', 's', '.', 'c', 'o', 'm', '\0', /* "iggprivate.com", true */ 'i', 'g', 'g', 'p', 'r', 'i', 'v', 'a', 't', 'e', '.', 'c', 'o', 'm', '\0', /* "iggsoft.com", true */ 'i', 'g', 'g', 's', 'o', 'f', 't', '.', 'c', 'o', 'm', '\0', /* "iggsoftware.com", true */ 'i', 'g', 'g', 's', 'o', 'f', 't', 'w', 'a', 'r', 'e', '.', 'c', 'o', 'm', '\0', @@ -5318,6 +5315,7 @@ /* "imaginary.ca", true */ 'i', 'm', 'a', 'g', 'i', 'n', 'a', 'r', 'y', '.', 'c', 'a', '\0', /* "imagr.io", true */ 'i', 'm', 'a', 'g', 'r', '.', 'i', 'o', '\0', /* "imakepoems.net", true */ 'i', 'm', 'a', 'k', 'e', 'p', 'o', 'e', 'm', 's', '.', 'n', 'e', 't', '\0', + /* "imanolbarba.net", true */ 'i', 'm', 'a', 'n', 'o', 'l', 'b', 'a', 'r', 'b', 'a', '.', 'n', 'e', 't', '\0', /* "imanudin.net", true */ 'i', 'm', 'a', 'n', 'u', 'd', 'i', 'n', '.', 'n', 'e', 't', '\0', /* "imbrian.org", true */ 'i', 'm', 'b', 'r', 'i', 'a', 'n', '.', 'o', 'r', 'g', '\0', /* "imbushuo.net", true */ 'i', 'm', 'b', 'u', 's', 'h', 'u', 'o', '.', 'n', 'e', 't', '\0', @@ -5485,6 +5483,7 @@ /* "investpay.ru", true */ 'i', 'n', 'v', 'e', 's', 't', 'p', 'a', 'y', '.', 'r', 'u', '\0', /* "invictusmc.uk", true */ 'i', 'n', 'v', 'i', 'c', 't', 'u', 's', 'm', 'c', '.', 'u', 'k', '\0', /* "invite24.pro", true */ 'i', 'n', 'v', 'i', 't', 'e', '2', '4', '.', 'p', 'r', 'o', '\0', + /* "invitescene.com", true */ 'i', 'n', 'v', 'i', 't', 'e', 's', 'c', 'e', 'n', 'e', '.', 'c', 'o', 'm', '\0', /* "invoiced.com", true */ 'i', 'n', 'v', 'o', 'i', 'c', 'e', 'd', '.', 'c', 'o', 'm', '\0', /* "invoicefinance.com", true */ 'i', 'n', 'v', 'o', 'i', 'c', 'e', 'f', 'i', 'n', 'a', 'n', 'c', 'e', '.', 'c', 'o', 'm', '\0', /* "invoicefinance.nl", true */ 'i', 'n', 'v', 'o', 'i', 'c', 'e', 'f', 'i', 'n', 'a', 'n', 'c', 'e', '.', 'n', 'l', '\0', @@ -5497,7 +5496,6 @@ /* "iompost.com", true */ 'i', 'o', 'm', 'p', 'o', 's', 't', '.', 'c', 'o', 'm', '\0', /* "iomstamps.com", true */ 'i', 'o', 'm', 's', 't', 'a', 'm', 'p', 's', '.', 'c', 'o', 'm', '\0', /* "ionas-law.ro", false */ 'i', 'o', 'n', 'a', 's', '-', 'l', 'a', 'w', '.', 'r', 'o', '\0', - /* "ionc.ca", true */ 'i', 'o', 'n', 'c', '.', 'c', 'a', '\0', /* "ionlabs.kr", true */ 'i', 'o', 'n', 'l', 'a', 'b', 's', '.', 'k', 'r', '\0', /* "iossifovlab.com", true */ 'i', 'o', 's', 's', 'i', 'f', 'o', 'v', 'l', 'a', 'b', '.', 'c', 'o', 'm', '\0', /* "ip-life.net", true */ 'i', 'p', '-', 'l', 'i', 'f', 'e', '.', 'n', 'e', 't', '\0', @@ -5604,6 +5602,7 @@ /* "itludens.com", true */ 'i', 't', 'l', 'u', 'd', 'e', 'n', 's', '.', 'c', 'o', 'm', '\0', /* "itnota.com", true */ 'i', 't', 'n', 'o', 't', 'a', '.', 'c', 'o', 'm', '\0', /* "itochan.jp", true */ 'i', 't', 'o', 'c', 'h', 'a', 'n', '.', 'j', 'p', '\0', + /* "itpol.dk", true */ 'i', 't', 'p', 'o', 'l', '.', 'd', 'k', '\0', /* "itriskltd.com", true */ 'i', 't', 'r', 'i', 's', 'k', 'l', 't', 'd', '.', 'c', 'o', 'm', '\0', /* "its-gutachten.de", true */ 'i', 't', 's', '-', 'g', 'u', 't', 'a', 'c', 'h', 't', 'e', 'n', '.', 'd', 'e', '\0', /* "its-schindler.de", true */ 'i', 't', 's', '-', 's', 'c', 'h', 'i', 'n', 'd', 'l', 'e', 'r', '.', 'd', 'e', '\0', @@ -5619,7 +5618,6 @@ /* "itsryan.com", true */ 'i', 't', 's', 'r', 'y', 'a', 'n', '.', 'c', 'o', 'm', '\0', /* "itu2015.de", true */ 'i', 't', 'u', '2', '0', '1', '5', '.', 'd', 'e', '\0', /* "iuscommunity.org", true */ 'i', 'u', 's', 'c', 'o', 'm', 'm', 'u', 'n', 'i', 't', 'y', '.', 'o', 'r', 'g', '\0', - /* "ivancacic.com", true */ 'i', 'v', 'a', 'n', 'c', 'a', 'c', 'i', 'c', '.', 'c', 'o', 'm', '\0', /* "ivi-fertilite.fr", true */ 'i', 'v', 'i', '-', 'f', 'e', 'r', 't', 'i', 'l', 'i', 't', 'e', '.', 'f', 'r', '\0', /* "ivi-fruchtbarkeit.de", true */ 'i', 'v', 'i', '-', 'f', 'r', 'u', 'c', 'h', 't', 'b', 'a', 'r', 'k', 'e', 'i', 't', '.', 'd', 'e', '\0', /* "ivi.com.ar", true */ 'i', 'v', 'i', '.', 'c', 'o', 'm', '.', 'a', 'r', '\0', @@ -5659,6 +5657,7 @@ /* "j2ee.cz", true */ 'j', '2', 'e', 'e', '.', 'c', 'z', '\0', /* "j3e.de", true */ 'j', '3', 'e', '.', 'd', 'e', '\0', /* "ja-dyck.de", true */ 'j', 'a', '-', 'd', 'y', 'c', 'k', '.', 'd', 'e', '\0', + /* "jabber.at", true */ 'j', 'a', 'b', 'b', 'e', 'r', '.', 'a', 't', '\0', /* "jabberfr.org", true */ 'j', 'a', 'b', 'b', 'e', 'r', 'f', 'r', '.', 'o', 'r', 'g', '\0', /* "jacekowski.org", true */ 'j', 'a', 'c', 'e', 'k', 'o', 'w', 's', 'k', 'i', '.', 'o', 'r', 'g', '\0', /* "jackdelik.de", true */ 'j', 'a', 'c', 'k', 'd', 'e', 'l', 'i', 'k', '.', 'd', 'e', '\0', @@ -5739,7 +5738,6 @@ /* "jazz-alliance.org", true */ 'j', 'a', 'z', 'z', '-', 'a', 'l', 'l', 'i', 'a', 'n', 'c', 'e', '.', 'o', 'r', 'g', '\0', /* "jazzanet.com", true */ 'j', 'a', 'z', 'z', 'a', 'n', 'e', 't', '.', 'c', 'o', 'm', '\0', /* "jazzncheese.com", true */ 'j', 'a', 'z', 'z', 'n', 'c', 'h', 'e', 'e', 's', 'e', '.', 'c', 'o', 'm', '\0', - /* "jbradaric.me", true */ 'j', 'b', 'r', 'a', 'd', 'a', 'r', 'i', 'c', '.', 'm', 'e', '\0', /* "jcaicedo.tk", true */ 'j', 'c', 'a', 'i', 'c', 'e', 'd', 'o', '.', 't', 'k', '\0', /* "jccrew.org", true */ 'j', 'c', 'c', 'r', 'e', 'w', '.', 'o', 'r', 'g', '\0', /* "jcoscia.com", true */ 'j', 'c', 'o', 's', 'c', 'i', 'a', '.', 'c', 'o', 'm', '\0', @@ -5747,6 +5745,7 @@ /* "jcyz.cf", true */ 'j', 'c', 'y', 'z', '.', 'c', 'f', '\0', /* "jdav-leipzig.de", true */ 'j', 'd', 'a', 'v', '-', 'l', 'e', 'i', 'p', 'z', 'i', 'g', '.', 'd', 'e', '\0', /* "jdcgroup.com.ph", true */ 'j', 'd', 'c', 'g', 'r', 'o', 'u', 'p', '.', 'c', 'o', 'm', '.', 'p', 'h', '\0', + /* "jdh8.org", true */ 'j', 'd', 'h', '8', '.', 'o', 'r', 'g', '\0', /* "jdubya.info", true */ 'j', 'd', 'u', 'b', 'y', 'a', '.', 'i', 'n', 'f', 'o', '\0', /* "jean-remy.ch", true */ 'j', 'e', 'a', 'n', '-', 'r', 'e', 'm', 'y', '.', 'c', 'h', '\0', /* "jedipedia.net", true */ 'j', 'e', 'd', 'i', 'p', 'e', 'd', 'i', 'a', '.', 'n', 'e', 't', '\0', @@ -5838,7 +5837,6 @@ /* "johndong.net", true */ 'j', 'o', 'h', 'n', 'd', 'o', 'n', 'g', '.', 'n', 'e', 't', '\0', /* "johngallias.com", true */ 'j', 'o', 'h', 'n', 'g', 'a', 'l', 'l', 'i', 'a', 's', '.', 'c', 'o', 'm', '\0', /* "johnguant.com", true */ 'j', 'o', 'h', 'n', 'g', 'u', 'a', 'n', 't', '.', 'c', 'o', 'm', '\0', - /* "johnhgaunt.com", true */ 'j', 'o', 'h', 'n', 'h', 'g', 'a', 'u', 'n', 't', '.', 'c', 'o', 'm', '\0', /* "johnmcgovern.com", true */ 'j', 'o', 'h', 'n', 'm', 'c', 'g', 'o', 'v', 'e', 'r', 'n', '.', 'c', 'o', 'm', '\0', /* "johnmcintosh.pro", true */ 'j', 'o', 'h', 'n', 'm', 'c', 'i', 'n', 't', 'o', 's', 'h', '.', 'p', 'r', 'o', '\0', /* "johnmh.me", true */ 'j', 'o', 'h', 'n', 'm', 'h', '.', 'm', 'e', '\0', @@ -5872,7 +5870,6 @@ /* "jooto.com", true */ 'j', 'o', 'o', 't', 'o', '.', 'c', 'o', 'm', '\0', /* "jopsens.de", true */ 'j', 'o', 'p', 's', 'e', 'n', 's', '.', 'd', 'e', '\0', /* "joran.org", true */ 'j', 'o', 'r', 'a', 'n', '.', 'o', 'r', 'g', '\0', - /* "jordanhamilton.me", true */ 'j', 'o', 'r', 'd', 'a', 'n', 'h', 'a', 'm', 'i', 'l', 't', 'o', 'n', '.', 'm', 'e', '\0', /* "jorgemesa.me", true */ 'j', 'o', 'r', 'g', 'e', 'm', 'e', 's', 'a', '.', 'm', 'e', '\0', /* "jornadasciberdefensa2016.es", true */ 'j', 'o', 'r', 'n', 'a', 'd', 'a', 's', 'c', 'i', 'b', 'e', 'r', 'd', 'e', 'f', 'e', 'n', 's', 'a', '2', '0', '1', '6', '.', 'e', 's', '\0', /* "jornane.me", true */ 'j', 'o', 'r', 'n', 'a', 'n', 'e', '.', 'm', 'e', '\0', @@ -5884,7 +5881,6 @@ /* "joshi.su", true */ 'j', 'o', 's', 'h', 'i', '.', 's', 'u', '\0', /* "joshtriplett.org", true */ 'j', 'o', 's', 'h', 't', 'r', 'i', 'p', 'l', 'e', 't', 't', '.', 'o', 'r', 'g', '\0', /* "joshuarogers.net", true */ 'j', 'o', 's', 'h', 'u', 'a', 'r', 'o', 'g', 'e', 'r', 's', '.', 'n', 'e', 't', '\0', - /* "josip.at", true */ 'j', 'o', 's', 'i', 'p', '.', 'a', 't', '\0', /* "jotpics.com", true */ 'j', 'o', 't', 'p', 'i', 'c', 's', '.', 'c', 'o', 'm', '\0', /* "jovic.hamburg", true */ 'j', 'o', 'v', 'i', 'c', '.', 'h', 'a', 'm', 'b', 'u', 'r', 'g', '\0', /* "joworld.net", true */ 'j', 'o', 'w', 'o', 'r', 'l', 'd', '.', 'n', 'e', 't', '\0', @@ -5961,6 +5957,7 @@ /* "kab-s.de", true */ 'k', 'a', 'b', '-', 's', '.', 'd', 'e', '\0', /* "kabat-fans.cz", true */ 'k', 'a', 'b', 'a', 't', '-', 'f', 'a', 'n', 's', '.', 'c', 'z', '\0', /* "kabeuchi.com", true */ 'k', 'a', 'b', 'e', 'u', 'c', 'h', 'i', '.', 'c', 'o', 'm', '\0', + /* "kabus.org", true */ 'k', 'a', 'b', 'u', 's', '.', 'o', 'r', 'g', '\0', /* "kachlikova2.cz", true */ 'k', 'a', 'c', 'h', 'l', 'i', 'k', 'o', 'v', 'a', '2', '.', 'c', 'z', '\0', /* "kackscharf.de", true */ 'k', 'a', 'c', 'k', 's', 'c', 'h', 'a', 'r', 'f', '.', 'd', 'e', '\0', /* "kadmec.com", true */ 'k', 'a', 'd', 'm', 'e', 'c', '.', 'c', 'o', 'm', '\0', @@ -5986,7 +5983,6 @@ /* "kaloix.de", true */ 'k', 'a', 'l', 'o', 'i', 'x', '.', 'd', 'e', '\0', /* "kamcvicit.sk", true */ 'k', 'a', 'm', 'c', 'v', 'i', 'c', 'i', 't', '.', 's', 'k', '\0', /* "kamikatse.net", true */ 'k', 'a', 'm', 'i', 'k', 'a', 't', 's', 'e', '.', 'n', 'e', 't', '\0', - /* "kamitech.ch", true */ 'k', 'a', 'm', 'i', 't', 'e', 'c', 'h', '.', 'c', 'h', '\0', /* "kamixa.se", true */ 'k', 'a', 'm', 'i', 'x', 'a', '.', 's', 'e', '\0', /* "kana.me", true */ 'k', 'a', 'n', 'a', '.', 'm', 'e', '\0', /* "kanar.nl", true */ 'k', 'a', 'n', 'a', 'r', '.', 'n', 'l', '\0', @@ -6140,6 +6136,7 @@ /* "kigmbh.com", true */ 'k', 'i', 'g', 'm', 'b', 'h', '.', 'c', 'o', 'm', '\0', /* "kikuzuki.org", false */ 'k', 'i', 'k', 'u', 'z', 'u', 'k', 'i', '.', 'o', 'r', 'g', '\0', /* "kilerd.me", true */ 'k', 'i', 'l', 'e', 'r', 'd', '.', 'm', 'e', '\0', + /* "kilianvalkhof.com", true */ 'k', 'i', 'l', 'i', 'a', 'n', 'v', 'a', 'l', 'k', 'h', 'o', 'f', '.', 'c', 'o', 'm', '\0', /* "killerrobots.com", true */ 'k', 'i', 'l', 'l', 'e', 'r', 'r', 'o', 'b', 'o', 't', 's', '.', 'c', 'o', 'm', '\0', /* "kilobyte22.de", true */ 'k', 'i', 'l', 'o', 'b', 'y', 't', 'e', '2', '2', '.', 'd', 'e', '\0', /* "kilogram.nl", true */ 'k', 'i', 'l', 'o', 'g', 'r', 'a', 'm', '.', 'n', 'l', '\0', @@ -6157,6 +6154,7 @@ /* "kinganywhere.eu", true */ 'k', 'i', 'n', 'g', 'a', 'n', 'y', 'w', 'h', 'e', 'r', 'e', '.', 'e', 'u', '\0', /* "kingbird.me", true */ 'k', 'i', 'n', 'g', 'b', 'i', 'r', 'd', '.', 'm', 'e', '\0', /* "kingqueen.org.uk", true */ 'k', 'i', 'n', 'g', 'q', 'u', 'e', 'e', 'n', '.', 'o', 'r', 'g', '.', 'u', 'k', '\0', + /* "kini24.ru", true */ 'k', 'i', 'n', 'i', '2', '4', '.', 'r', 'u', '\0', /* "kinkdr.com", true */ 'k', 'i', 'n', 'k', 'd', 'r', '.', 'c', 'o', 'm', '\0', /* "kinkenonline.com", true */ 'k', 'i', 'n', 'k', 'e', 'n', 'o', 'n', 'l', 'i', 'n', 'e', '.', 'c', 'o', 'm', '\0', /* "kinomoto.me", true */ 'k', 'i', 'n', 'o', 'm', 'o', 't', 'o', '.', 'm', 'e', '\0', @@ -6169,7 +6167,6 @@ /* "kintzingerfilm.de", true */ 'k', 'i', 'n', 't', 'z', 'i', 'n', 'g', 'e', 'r', 'f', 'i', 'l', 'm', '.', 'd', 'e', '\0', /* "kiocloud.com", true */ 'k', 'i', 'o', 'c', 'l', 'o', 'u', 'd', '.', 'c', 'o', 'm', '\0', /* "kionetworks.es", true */ 'k', 'i', 'o', 'n', 'e', 't', 'w', 'o', 'r', 'k', 's', '.', 'e', 's', '\0', - /* "kipira.com", true */ 'k', 'i', 'p', 'i', 'r', 'a', '.', 'c', 'o', 'm', '\0', /* "kirara.eu", true */ 'k', 'i', 'r', 'a', 'r', 'a', '.', 'e', 'u', '\0', /* "kirbear.com", true */ 'k', 'i', 'r', 'b', 'e', 'a', 'r', '.', 'c', 'o', 'm', '\0', /* "kircp.com", true */ 'k', 'i', 'r', 'c', 'p', '.', 'c', 'o', 'm', '\0', @@ -6193,6 +6190,7 @@ /* "kjarni.cc", true */ 'k', 'j', 'a', 'r', 'n', 'i', '.', 'c', 'c', '\0', /* "kjarrval.is", true */ 'k', 'j', 'a', 'r', 'r', 'v', 'a', 'l', '.', 'i', 's', '\0', /* "kjchernov.info", true */ 'k', 'j', 'c', 'h', 'e', 'r', 'n', 'o', 'v', '.', 'i', 'n', 'f', 'o', '\0', + /* "kjellvn.net", true */ 'k', 'j', 'e', 'l', 'l', 'v', 'n', '.', 'n', 'e', 't', '\0', /* "kk-neudorf-duissern.de", true */ 'k', 'k', '-', 'n', 'e', 'u', 'd', 'o', 'r', 'f', '-', 'd', 'u', 'i', 's', 's', 'e', 'r', 'n', '.', 'd', 'e', '\0', /* "kkaufmann.de", true */ 'k', 'k', 'a', 'u', 'f', 'm', 'a', 'n', 'n', '.', 'd', 'e', '\0', /* "kki.org", true */ 'k', 'k', 'i', '.', 'o', 'r', 'g', '\0', @@ -6307,7 +6305,6 @@ /* "krachtinverbinding.nl", true */ 'k', 'r', 'a', 'c', 'h', 't', 'i', 'n', 'v', 'e', 'r', 'b', 'i', 'n', 'd', 'i', 'n', 'g', '.', 'n', 'l', '\0', /* "kradalby.no", true */ 'k', 'r', 'a', 'd', 'a', 'l', 'b', 'y', '.', 'n', 'o', '\0', /* "kraft.im", true */ 'k', 'r', 'a', 'f', 't', '.', 'i', 'm', '\0', - /* "kraga.sk", true */ 'k', 'r', 'a', 'g', 'a', '.', 's', 'k', '\0', /* "kraiwan.com", true */ 'k', 'r', 'a', 'i', 'w', 'a', 'n', '.', 'c', 'o', 'm', '\0', /* "kraiwon.com", true */ 'k', 'r', 'a', 'i', 'w', 'o', 'n', '.', 'c', 'o', 'm', '\0', /* "kraken.io", true */ 'k', 'r', 'a', 'k', 'e', 'n', '.', 'i', 'o', '\0', @@ -6334,7 +6331,6 @@ /* "krisstarkey.co.uk", true */ 'k', 'r', 'i', 's', 's', 't', 'a', 'r', 'k', 'e', 'y', '.', 'c', 'o', '.', 'u', 'k', '\0', /* "kristikala.nl", true */ 'k', 'r', 'i', 's', 't', 'i', 'k', 'a', 'l', 'a', '.', 'n', 'l', '\0', /* "kristinbailey.com", true */ 'k', 'r', 'i', 's', 't', 'i', 'n', 'b', 'a', 'i', 'l', 'e', 'y', '.', 'c', 'o', 'm', '\0', - /* "kristofferkoch.com", true */ 'k', 'r', 'i', 's', 't', 'o', 'f', 'f', 'e', 'r', 'k', 'o', 'c', 'h', '.', 'c', 'o', 'm', '\0', /* "krizek.cc", true */ 'k', 'r', 'i', 'z', 'e', 'k', '.', 'c', 'c', '\0', /* "krk-media.pl", true */ 'k', 'r', 'k', '-', 'm', 'e', 'd', 'i', 'a', '.', 'p', 'l', '\0', /* "krmeni.cz", true */ 'k', 'r', 'm', 'e', 'n', 'i', '.', 'c', 'z', '\0', @@ -6422,6 +6418,7 @@ /* "lafillepolyvalente.com", true */ 'l', 'a', 'f', 'i', 'l', 'l', 'e', 'p', 'o', 'l', 'y', 'v', 'a', 'l', 'e', 'n', 't', 'e', '.', 'c', 'o', 'm', '\0', /* "lafka.org", true */ 'l', 'a', 'f', 'k', 'a', '.', 'o', 'r', 'g', '\0', /* "lafkor.de", true */ 'l', 'a', 'f', 'k', 'o', 'r', '.', 'd', 'e', '\0', + /* "lagarderob.ru", false */ 'l', 'a', 'g', 'a', 'r', 'd', 'e', 'r', 'o', 'b', '.', 'r', 'u', '\0', /* "lagerauftrag.info", true */ 'l', 'a', 'g', 'e', 'r', 'a', 'u', 'f', 't', 'r', 'a', 'g', '.', 'i', 'n', 'f', 'o', '\0', /* "lagier.xyz", true */ 'l', 'a', 'g', 'i', 'e', 'r', '.', 'x', 'y', 'z', '\0', /* "laglab.org", true */ 'l', 'a', 'g', 'l', 'a', 'b', '.', 'o', 'r', 'g', '\0', @@ -6527,6 +6524,7 @@ /* "learnflakes.net", true */ 'l', 'e', 'a', 'r', 'n', 'f', 'l', 'a', 'k', 'e', 's', '.', 'n', 'e', 't', '\0', /* "learntube.cz", true */ 'l', 'e', 'a', 'r', 'n', 't', 'u', 'b', 'e', '.', 'c', 'z', '\0', /* "leatherfurnitureexpo.com", true */ 'l', 'e', 'a', 't', 'h', 'e', 'r', 'f', 'u', 'r', 'n', 'i', 't', 'u', 'r', 'e', 'e', 'x', 'p', 'o', '.', 'c', 'o', 'm', '\0', + /* "leaversmith.com", true */ 'l', 'e', 'a', 'v', 'e', 'r', 's', 'm', 'i', 't', 'h', '.', 'c', 'o', 'm', '\0', /* "lebanesearmy.gov.lb", true */ 'l', 'e', 'b', 'a', 'n', 'e', 's', 'e', 'a', 'r', 'm', 'y', '.', 'g', 'o', 'v', '.', 'l', 'b', '\0', /* "lebarmy.gov.lb", true */ 'l', 'e', 'b', 'a', 'r', 'm', 'y', '.', 'g', 'o', 'v', '.', 'l', 'b', '\0', /* "leblanc.io", true */ 'l', 'e', 'b', 'l', 'a', 'n', 'c', '.', 'i', 'o', '\0', @@ -6608,7 +6606,6 @@ /* "libreboot.org", true */ 'l', 'i', 'b', 'r', 'e', 'b', 'o', 'o', 't', '.', 'o', 'r', 'g', '\0', /* "librelamp.com", true */ 'l', 'i', 'b', 'r', 'e', 'l', 'a', 'm', 'p', '.', 'c', 'o', 'm', '\0', /* "librends.org", true */ 'l', 'i', 'b', 'r', 'e', 'n', 'd', 's', '.', 'o', 'r', 'g', '\0', - /* "libscode.com", true */ 'l', 'i', 'b', 's', 'c', 'o', 'd', 'e', '.', 'c', 'o', 'm', '\0', /* "libskia.so", true */ 'l', 'i', 'b', 's', 'k', 'i', 'a', '.', 's', 'o', '\0', /* "libsodium.org", true */ 'l', 'i', 'b', 's', 'o', 'd', 'i', 'u', 'm', '.', 'o', 'r', 'g', '\0', /* "liceserv.com", true */ 'l', 'i', 'c', 'e', 's', 'e', 'r', 'v', '.', 'c', 'o', 'm', '\0', @@ -6689,7 +6686,7 @@ /* "litchidova.nl", true */ 'l', 'i', 't', 'c', 'h', 'i', 'd', 'o', 'v', 'a', '.', 'n', 'l', '\0', /* "litevault.net", true */ 'l', 'i', 't', 'e', 'v', 'a', 'u', 'l', 't', '.', 'n', 'e', 't', '\0', /* "litfin.name", true */ 'l', 'i', 't', 'f', 'i', 'n', '.', 'n', 'a', 'm', 'e', '\0', - /* "lithesalar.se", true */ 'l', 'i', 't', 'h', 'e', 's', 'a', 'l', 'a', 'r', '.', 's', 'e', '\0', + /* "lithesalar.se", false */ 'l', 'i', 't', 'h', 'e', 's', 'a', 'l', 'a', 'r', '.', 's', 'e', '\0', /* "little.pw", true */ 'l', 'i', 't', 't', 'l', 'e', '.', 'p', 'w', '\0', /* "littlefreelibrary.org", true */ 'l', 'i', 't', 't', 'l', 'e', 'f', 'r', 'e', 'e', 'l', 'i', 'b', 'r', 'a', 'r', 'y', '.', 'o', 'r', 'g', '\0', /* "litvideoserver.de", true */ 'l', 'i', 't', 'v', 'i', 'd', 'e', 'o', 's', 'e', 'r', 'v', 'e', 'r', '.', 'd', 'e', '\0', @@ -6919,7 +6916,6 @@ /* "macleod.io", true */ 'm', 'a', 'c', 'l', 'e', 'o', 'd', '.', 'i', 'o', '\0', /* "macnemo.de", true */ 'm', 'a', 'c', 'n', 'e', 'm', 'o', '.', 'd', 'e', '\0', /* "maco.org.uk", true */ 'm', 'a', 'c', 'o', '.', 'o', 'r', 'g', '.', 'u', 'k', '\0', - /* "macosxfilerecovery.com", true */ 'm', 'a', 'c', 'o', 's', 'x', 'f', 'i', 'l', 'e', 'r', 'e', 'c', 'o', 'v', 'e', 'r', 'y', '.', 'c', 'o', 'm', '\0', /* "maddi.biz", true */ 'm', 'a', 'd', 'd', 'i', '.', 'b', 'i', 'z', '\0', /* "madebyshore.com", true */ 'm', 'a', 'd', 'e', 'b', 'y', 's', 'h', 'o', 'r', 'e', '.', 'c', 'o', 'm', '\0', /* "madeglobal.com", true */ 'm', 'a', 'd', 'e', 'g', 'l', 'o', 'b', 'a', 'l', '.', 'c', 'o', 'm', '\0', @@ -7040,11 +7036,11 @@ /* "marcel-preuss.de", true */ 'm', 'a', 'r', 'c', 'e', 'l', '-', 'p', 'r', 'e', 'u', 's', 's', '.', 'd', 'e', '\0', /* "marcelpreuss.de", true */ 'm', 'a', 'r', 'c', 'e', 'l', 'p', 'r', 'e', 'u', 's', 's', '.', 'd', 'e', '\0', /* "marcelsiegert.com", true */ 'm', 'a', 'r', 'c', 'e', 'l', 's', 'i', 'e', 'g', 'e', 'r', 't', '.', 'c', 'o', 'm', '\0', + /* "marcoececilia.it", true */ 'm', 'a', 'r', 'c', 'o', 'e', 'c', 'e', 'c', 'i', 'l', 'i', 'a', '.', 'i', 't', '\0', /* "marcofinke.de", true */ 'm', 'a', 'r', 'c', 'o', 'f', 'i', 'n', 'k', 'e', '.', 'd', 'e', '\0', /* "marcohager.de", true */ 'm', 'a', 'r', 'c', 'o', 'h', 'a', 'g', 'e', 'r', '.', 'd', 'e', '\0', /* "marcoslater.com", true */ 'm', 'a', 'r', 'c', 'o', 's', 'l', 'a', 't', 'e', 'r', '.', 'c', 'o', 'm', '\0', /* "mareklecian.cz", true */ 'm', 'a', 'r', 'e', 'k', 'l', 'e', 'c', 'i', 'a', 'n', '.', 'c', 'z', '\0', - /* "mariannematthew.com", true */ 'm', 'a', 'r', 'i', 'a', 'n', 'n', 'e', 'm', 'a', 't', 't', 'h', 'e', 'w', '.', 'c', 'o', 'm', '\0', /* "mariaolesen.dk", true */ 'm', 'a', 'r', 'i', 'a', 'o', 'l', 'e', 's', 'e', 'n', '.', 'd', 'k', '\0', /* "marie-elisabeth.dk", true */ 'm', 'a', 'r', 'i', 'e', '-', 'e', 'l', 'i', 's', 'a', 'b', 'e', 't', 'h', '.', 'd', 'k', '\0', /* "marie.club", true */ 'm', 'a', 'r', 'i', 'e', '.', 'c', 'l', 'u', 'b', '\0', @@ -7113,7 +7109,9 @@ /* "matrixcheats.net", true */ 'm', 'a', 't', 'r', 'i', 'x', 'c', 'h', 'e', 'a', 't', 's', '.', 'n', 'e', 't', '\0', /* "matt.tf", true */ 'm', 'a', 't', 't', '.', 't', 'f', '\0', /* "mattandreko.com", true */ 'm', 'a', 't', 't', 'a', 'n', 'd', 'r', 'e', 'k', 'o', '.', 'c', 'o', 'm', '\0', + /* "mattandyana.com", true */ 'm', 'a', 't', 't', 'a', 'n', 'd', 'y', 'a', 'n', 'a', '.', 'c', 'o', 'm', '\0', /* "mattberryman.com", false */ 'm', 'a', 't', 't', 'b', 'e', 'r', 'r', 'y', 'm', 'a', 'n', '.', 'c', 'o', 'm', '\0', + /* "mattcoles.io", true */ 'm', 'a', 't', 't', 'c', 'o', 'l', 'e', 's', '.', 'i', 'o', '\0', /* "matteomarescotti.it", true */ 'm', 'a', 't', 't', 'e', 'o', 'm', 'a', 'r', 'e', 's', 'c', 'o', 't', 't', 'i', '.', 'i', 't', '\0', /* "matthecat.com", true */ 'm', 'a', 't', 't', 'h', 'e', 'c', 'a', 't', '.', 'c', 'o', 'm', '\0', /* "matthewgrill.com", true */ 'm', 'a', 't', 't', 'h', 'e', 'w', 'g', 'r', 'i', 'l', 'l', '.', 'c', 'o', 'm', '\0', @@ -7201,8 +7199,6 @@ /* "meadowviewfarms.org", true */ 'm', 'e', 'a', 'd', 'o', 'w', 'v', 'i', 'e', 'w', 'f', 'a', 'r', 'm', 's', '.', 'o', 'r', 'g', '\0', /* "mealgoo.com", true */ 'm', 'e', 'a', 'l', 'g', 'o', 'o', '.', 'c', 'o', 'm', '\0', /* "meamod.com", true */ 'm', 'e', 'a', 'm', 'o', 'd', '.', 'c', 'o', 'm', '\0', - /* "meap.xyz", true */ 'm', 'e', 'a', 'p', '.', 'x', 'y', 'z', '\0', - /* "mebio.us", false */ 'm', 'e', 'b', 'i', 'o', '.', 'u', 's', '\0', /* "mechanixdirect.co.uk", false */ 'm', 'e', 'c', 'h', 'a', 'n', 'i', 'x', 'd', 'i', 'r', 'e', 'c', 't', '.', 'c', 'o', '.', 'u', 'k', '\0', /* "mechmk1.me", true */ 'm', 'e', 'c', 'h', 'm', 'k', '1', '.', 'm', 'e', '\0', /* "medba.se", true */ 'm', 'e', 'd', 'b', 'a', '.', 's', 'e', '\0', @@ -7246,7 +7242,6 @@ /* "meganreel.com", true */ 'm', 'e', 'g', 'a', 'n', 'r', 'e', 'e', 'l', '.', 'c', 'o', 'm', '\0', /* "megaplan.cz", true */ 'm', 'e', 'g', 'a', 'p', 'l', 'a', 'n', '.', 'c', 'z', '\0', /* "megaplan.ru", true */ 'm', 'e', 'g', 'a', 'p', 'l', 'a', 'n', '.', 'r', 'u', '\0', - /* "megumico.net", true */ 'm', 'e', 'g', 'u', 'm', 'i', 'c', 'o', '.', 'n', 'e', 't', '\0', /* "mehmetince.net", true */ 'm', 'e', 'h', 'm', 'e', 't', 'i', 'n', 'c', 'e', '.', 'n', 'e', 't', '\0', /* "mehostdd.com", true */ 'm', 'e', 'h', 'o', 's', 't', 'd', 'd', '.', 'c', 'o', 'm', '\0', /* "mehrwert.de", true */ 'm', 'e', 'h', 'r', 'w', 'e', 'r', 't', '.', 'd', 'e', '\0', @@ -7350,6 +7345,7 @@ /* "microdots.de", true */ 'm', 'i', 'c', 'r', 'o', 'd', 'o', 't', 's', '.', 'd', 'e', '\0', /* "microlog.org", true */ 'm', 'i', 'c', 'r', 'o', 'l', 'o', 'g', '.', 'o', 'r', 'g', '\0', /* "microtalk.org", true */ 'm', 'i', 'c', 'r', 'o', 't', 'a', 'l', 'k', '.', 'o', 'r', 'g', '\0', + /* "microvb.com", true */ 'm', 'i', 'c', 'r', 'o', 'v', 'b', '.', 'c', 'o', 'm', '\0', /* "midair.io", true */ 'm', 'i', 'd', 'a', 'i', 'r', '.', 'i', 'o', '\0', /* "midirs.org", true */ 'm', 'i', 'd', 'i', 'r', 's', '.', 'o', 'r', 'g', '\0', /* "midlgx.com", true */ 'm', 'i', 'd', 'l', 'g', 'x', '.', 'c', 'o', 'm', '\0', @@ -7752,7 +7748,6 @@ /* "myraytech.net", false */ 'm', 'y', 'r', 'a', 'y', 't', 'e', 'c', 'h', '.', 'n', 'e', 't', '\0', /* "myrealestatemate.com.au", true */ 'm', 'y', 'r', 'e', 'a', 'l', 'e', 's', 't', 'a', 't', 'e', 'm', 'a', 't', 'e', '.', 'c', 'o', 'm', '.', 'a', 'u', '\0', /* "myrepublic.co.id", true */ 'm', 'y', 'r', 'e', 'p', 'u', 'b', 'l', 'i', 'c', '.', 'c', 'o', '.', 'i', 'd', '\0', - /* "myresearchapp.com", true */ 'm', 'y', 'r', 'e', 's', 'e', 'a', 'r', 'c', 'h', 'a', 'p', 'p', '.', 'c', 'o', 'm', '\0', /* "myruststats.com", true */ 'm', 'y', 'r', 'u', 's', 't', 's', 't', 'a', 't', 's', '.', 'c', 'o', 'm', '\0', /* "myschoolphoto.org", true */ 'm', 'y', 's', 'c', 'h', 'o', 'o', 'l', 'p', 'h', 'o', 't', 'o', '.', 'o', 'r', 'g', '\0', /* "mysecretcase.com", true */ 'm', 'y', 's', 'e', 'c', 'r', 'e', 't', 'c', 'a', 's', 'e', '.', 'c', 'o', 'm', '\0', @@ -7791,7 +7786,6 @@ /* "nagb.gov", true */ 'n', 'a', 'g', 'b', '.', 'g', 'o', 'v', '\0', /* "nagb.org", true */ 'n', 'a', 'g', 'b', '.', 'o', 'r', 'g', '\0', /* "nagelfam.com", true */ 'n', 'a', 'g', 'e', 'l', 'f', 'a', 'm', '.', 'c', 'o', 'm', '\0', - /* "nagoya-kyuyo.com", true */ 'n', 'a', 'g', 'o', 'y', 'a', '-', 'k', 'y', 'u', 'y', 'o', '.', 'c', 'o', 'm', '\0', /* "nakamastreamingcommunity.com", true */ 'n', 'a', 'k', 'a', 'm', 'a', 's', 't', 'r', 'e', 'a', 'm', 'i', 'n', 'g', 'c', 'o', 'm', 'm', 'u', 'n', 'i', 't', 'y', '.', 'c', 'o', 'm', '\0', /* "nakedalarmclock.me", true */ 'n', 'a', 'k', 'e', 'd', 'a', 'l', 'a', 'r', 'm', 'c', 'l', 'o', 'c', 'k', '.', 'm', 'e', '\0', /* "nakedfacts.co.uk", true */ 'n', 'a', 'k', 'e', 'd', 'f', 'a', 'c', 't', 's', '.', 'c', 'o', '.', 'u', 'k', '\0', @@ -7865,6 +7859,8 @@ /* "ndbt.com", true */ 'n', 'd', 'b', 't', '.', 'c', 'o', 'm', '\0', /* "nder.be", true */ 'n', 'd', 'e', 'r', '.', 'b', 'e', '\0', /* "ndmath.club", true */ 'n', 'd', 'm', 'a', 't', 'h', '.', 'c', 'l', 'u', 'b', '\0', + /* "ndtblog.com", true */ 'n', 'd', 't', 'b', 'l', 'o', 'g', '.', 'c', 'o', 'm', '\0', + /* "ndtmarket.place", true */ 'n', 'd', 't', 'm', 'a', 'r', 'k', 'e', 't', '.', 'p', 'l', 'a', 'c', 'e', '\0', /* "ne-on.org", true */ 'n', 'e', '-', 'o', 'n', '.', 'o', 'r', 'g', '\0', /* "ne1home.dyndns.org", true */ 'n', 'e', '1', 'h', 'o', 'm', 'e', '.', 'd', 'y', 'n', 'd', 'n', 's', '.', 'o', 'r', 'g', '\0', /* "neap.io", true */ 'n', 'e', 'a', 'p', '.', 'i', 'o', '\0', @@ -7886,7 +7882,6 @@ /* "neillans.co.uk", true */ 'n', 'e', 'i', 'l', 'l', 'a', 'n', 's', '.', 'c', 'o', '.', 'u', 'k', '\0', /* "neillans.com", true */ 'n', 'e', 'i', 'l', 'l', 'a', 'n', 's', '.', 'c', 'o', 'm', '\0', /* "neilwynne.com", false */ 'n', 'e', 'i', 'l', 'w', 'y', 'n', 'n', 'e', '.', 'c', 'o', 'm', '\0', - /* "neko-life.com", true */ 'n', 'e', 'k', 'o', '-', 'l', 'i', 'f', 'e', '.', 'c', 'o', 'm', '\0', /* "neko.li", true */ 'n', 'e', 'k', 'o', '.', 'l', 'i', '\0', /* "nekomimi.pl", true */ 'n', 'e', 'k', 'o', 'm', 'i', 'm', 'i', '.', 'p', 'l', '\0', /* "nekosc.com", true */ 'n', 'e', 'k', 'o', 's', 'c', '.', 'c', 'o', 'm', '\0', @@ -7914,7 +7909,6 @@ /* "net2o.net", true */ 'n', 'e', 't', '2', 'o', '.', 'n', 'e', 't', '\0', /* "netbank.com.au", true */ 'n', 'e', 't', 'b', 'a', 'n', 'k', '.', 'c', 'o', 'm', '.', 'a', 'u', '\0', /* "netbrief.ml", true */ 'n', 'e', 't', 'b', 'r', 'i', 'e', 'f', '.', 'm', 'l', '\0', - /* "netbulls.io", true */ 'n', 'e', 't', 'b', 'u', 'l', 'l', 's', '.', 'i', 'o', '\0', /* "netconnect.at", true */ 'n', 'e', 't', 'c', 'o', 'n', 'n', 'e', 'c', 't', '.', 'a', 't', '\0', /* "netcoolusers.org", true */ 'n', 'e', 't', 'c', 'o', 'o', 'l', 'u', 's', 'e', 'r', 's', '.', 'o', 'r', 'g', '\0', /* "netera.se", true */ 'n', 'e', 't', 'e', 'r', 'a', '.', 's', 'e', '\0', @@ -7999,7 +7993,6 @@ /* "ng-firewall.com", true */ 'n', 'g', '-', 'f', 'i', 'r', 'e', 'w', 'a', 'l', 'l', '.', 'c', 'o', 'm', '\0', /* "nghe.net", true */ 'n', 'g', 'h', 'e', '.', 'n', 'e', 't', '\0', /* "nglr.org", true */ 'n', 'g', 'l', 'r', '.', 'o', 'r', 'g', '\0', - /* "ngt-service.ru", true */ 'n', 'g', 't', '-', 's', 'e', 'r', 'v', 'i', 'c', 'e', '.', 'r', 'u', '\0', /* "nhome.ba", true */ 'n', 'h', 'o', 'm', 'e', '.', 'b', 'a', '\0', /* "ni-mate.com", true */ 'n', 'i', '-', 'm', 'a', 't', 'e', '.', 'c', 'o', 'm', '\0', /* "niagarafalls.ca", true */ 'n', 'i', 'a', 'g', 'a', 'r', 'a', 'f', 'a', 'l', 'l', 's', '.', 'c', 'a', '\0', @@ -8096,9 +8089,7 @@ /* "nohats.ca", true */ 'n', 'o', 'h', 'a', 't', 's', '.', 'c', 'a', '\0', /* "nohup.se", true */ 'n', 'o', 'h', 'u', 'p', '.', 's', 'e', '\0', /* "noisetrap.cz", true */ 'n', 'o', 'i', 's', 'e', 't', 'r', 'a', 'p', '.', 'c', 'z', '\0', - /* "nojestorget.se", true */ 'n', 'o', 'j', 'e', 's', 't', 'o', 'r', 'g', 'e', 't', '.', 's', 'e', '\0', /* "nolaviz.org", true */ 'n', 'o', 'l', 'a', 'v', 'i', 'z', '.', 'o', 'r', 'g', '\0', - /* "nolberg.net", true */ 'n', 'o', 'l', 'b', 'e', 'r', 'g', '.', 'n', 'e', 't', '\0', /* "noma-film.com", true */ 'n', 'o', 'm', 'a', '-', 'f', 'i', 'l', 'm', '.', 'c', 'o', 'm', '\0', /* "nomadproject.io", true */ 'n', 'o', 'm', 'a', 'd', 'p', 'r', 'o', 'j', 'e', 'c', 't', '.', 'i', 'o', '\0', /* "nomesbiblicos.com", true */ 'n', 'o', 'm', 'e', 's', 'b', 'i', 'b', 'l', 'i', 'c', 'o', 's', '.', 'c', 'o', 'm', '\0', @@ -8257,13 +8248,13 @@ /* "ohnemusik.com", true */ 'o', 'h', 'n', 'e', 'm', 'u', 's', 'i', 'k', '.', 'c', 'o', 'm', '\0', /* "ohsocool.org", true */ 'o', 'h', 's', 'o', 'c', 'o', 'o', 'l', '.', 'o', 'r', 'g', '\0', /* "oiepoie.nl", false */ 'o', 'i', 'e', 'p', 'o', 'i', 'e', '.', 'n', 'l', '\0', + /* "ojls.co", true */ 'o', 'j', 'l', 's', '.', 'c', 'o', '\0', /* "okay.coffee", true */ 'o', 'k', 'a', 'y', '.', 'c', 'o', 'f', 'f', 'e', 'e', '\0', /* "oke.com.tw", true */ 'o', 'k', 'e', '.', 'c', 'o', 'm', '.', 't', 'w', '\0', /* "okhrana.agency", true */ 'o', 'k', 'h', 'r', 'a', 'n', 'a', '.', 'a', 'g', 'e', 'n', 'c', 'y', '\0', /* "oklahomatickets.com", true */ 'o', 'k', 'l', 'a', 'h', 'o', 'm', 'a', 't', 'i', 'c', 'k', 'e', 't', 's', '.', 'c', 'o', 'm', '\0', /* "okmx.de", true */ 'o', 'k', 'm', 'x', '.', 'd', 'e', '\0', /* "okok-rent.com", true */ 'o', 'k', 'o', 'k', '-', 'r', 'e', 'n', 't', '.', 'c', 'o', 'm', '\0', - /* "okonetwork.org.uk", true */ 'o', 'k', 'o', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'o', 'r', 'g', '.', 'u', 'k', '\0', /* "olafnorge.de", false */ 'o', 'l', 'a', 'f', 'n', 'o', 'r', 'g', 'e', '.', 'd', 'e', '\0', /* "olcso-vps-szerver.hu", true */ 'o', 'l', 'c', 's', 'o', '-', 'v', 'p', 's', '-', 's', 'z', 'e', 'r', 'v', 'e', 'r', '.', 'h', 'u', '\0', /* "olegon.ru", true */ 'o', 'l', 'e', 'g', 'o', 'n', '.', 'r', 'u', '\0', @@ -8398,6 +8389,7 @@ /* "orientalart.nl", true */ 'o', 'r', 'i', 'e', 'n', 't', 'a', 'l', 'a', 'r', 't', '.', 'n', 'l', '\0', /* "origami.to", true */ 'o', 'r', 'i', 'g', 'a', 'm', 'i', '.', 't', 'o', '\0', /* "originalmockups.com", true */ 'o', 'r', 'i', 'g', 'i', 'n', 'a', 'l', 'm', 'o', 'c', 'k', 'u', 'p', 's', '.', 'c', 'o', 'm', '\0', + /* "orioncustompcs.com", false */ 'o', 'r', 'i', 'o', 'n', 'c', 'u', 's', 't', 'o', 'm', 'p', 'c', 's', '.', 'c', 'o', 'm', '\0', /* "orlives.de", true */ 'o', 'r', 'l', 'i', 'v', 'e', 's', '.', 'd', 'e', '\0', /* "oroweatorganic.com", true */ 'o', 'r', 'o', 'w', 'e', 'a', 't', 'o', 'r', 'g', 'a', 'n', 'i', 'c', '.', 'c', 'o', 'm', '\0', /* "orrs.de", true */ 'o', 'r', 'r', 's', '.', 'd', 'e', '\0', @@ -8433,7 +8425,6 @@ /* "ourcloud.at", true */ 'o', 'u', 'r', 'c', 'l', 'o', 'u', 'd', '.', 'a', 't', '\0', /* "ourcodinglives.com", true */ 'o', 'u', 'r', 'c', 'o', 'd', 'i', 'n', 'g', 'l', 'i', 'v', 'e', 's', '.', 'c', 'o', 'm', '\0', /* "ourevents.net", true */ 'o', 'u', 'r', 'e', 'v', 'e', 'n', 't', 's', '.', 'n', 'e', 't', '\0', - /* "outdoorproducts.com", true */ 'o', 'u', 't', 'd', 'o', 'o', 'r', 'p', 'r', 'o', 'd', 'u', 'c', 't', 's', '.', 'c', 'o', 'm', '\0', /* "outgress.com", true */ 'o', 'u', 't', 'g', 'r', 'e', 's', 's', '.', 'c', 'o', 'm', '\0', /* "outlookonthedesktop.com", true */ 'o', 'u', 't', 'l', 'o', 'o', 'k', 'o', 'n', 't', 'h', 'e', 'd', 'e', 's', 'k', 't', 'o', 'p', '.', 'c', 'o', 'm', '\0', /* "outofcontrol.ca", true */ 'o', 'u', 't', 'o', 'f', 'c', 'o', 'n', 't', 'r', 'o', 'l', '.', 'c', 'a', '\0', @@ -8516,6 +8507,7 @@ /* "parcon.it", true */ 'p', 'a', 'r', 'c', 'o', 'n', '.', 'i', 't', '\0', /* "parentinterview.com", true */ 'p', 'a', 'r', 'e', 'n', 't', 'i', 'n', 't', 'e', 'r', 'v', 'i', 'e', 'w', '.', 'c', 'o', 'm', '\0', /* "pariga.co.uk", true */ 'p', 'a', 'r', 'i', 'g', 'a', '.', 'c', 'o', '.', 'u', 'k', '\0', + /* "parithy.net", true */ 'p', 'a', 'r', 'i', 't', 'h', 'y', '.', 'n', 'e', 't', '\0', /* "parkingplus.co.il", true */ 'p', 'a', 'r', 'k', 'i', 'n', 'g', 'p', 'l', 'u', 's', '.', 'c', 'o', '.', 'i', 'l', '\0', /* "parkingpoint.co.uk", true */ 'p', 'a', 'r', 'k', 'i', 'n', 'g', 'p', 'o', 'i', 'n', 't', '.', 'c', 'o', '.', 'u', 'k', '\0', /* "parlamento.gub.uy", true */ 'p', 'a', 'r', 'l', 'a', 'm', 'e', 'n', 't', 'o', '.', 'g', 'u', 'b', '.', 'u', 'y', '\0', @@ -8669,6 +8661,7 @@ /* "performaterm.ro", true */ 'p', 'e', 'r', 'f', 'o', 'r', 'm', 'a', 't', 'e', 'r', 'm', '.', 'r', 'o', '\0', /* "perfumeaz.com", true */ 'p', 'e', 'r', 'f', 'u', 'm', 'e', 'a', 'z', '.', 'c', 'o', 'm', '\0', /* "perfumes.com.br", true */ 'p', 'e', 'r', 'f', 'u', 'm', 'e', 's', '.', 'c', 'o', 'm', '.', 'b', 'r', '\0', + /* "perfumista.vn", true */ 'p', 'e', 'r', 'f', 'u', 'm', 'i', 's', 't', 'a', '.', 'v', 'n', '\0', /* "periscope.tv", true */ 'p', 'e', 'r', 'i', 's', 'c', 'o', 'p', 'e', '.', 't', 'v', '\0', /* "periscopeliveweb.com", true */ 'p', 'e', 'r', 'i', 's', 'c', 'o', 'p', 'e', 'l', 'i', 'v', 'e', 'w', 'e', 'b', '.', 'c', 'o', 'm', '\0', /* "perishablepress.com", true */ 'p', 'e', 'r', 'i', 's', 'h', 'a', 'b', 'l', 'e', 'p', 'r', 'e', 's', 's', '.', 'c', 'o', 'm', '\0', @@ -8752,6 +8745,7 @@ /* "phpbbchinese.com", true */ 'p', 'h', 'p', 'b', 'b', 'c', 'h', 'i', 'n', 'e', 's', 'e', '.', 'c', 'o', 'm', '\0', /* "phpdistribution.com", true */ 'p', 'h', 'p', 'd', 'i', 's', 't', 'r', 'i', 'b', 'u', 't', 'i', 'o', 'n', '.', 'c', 'o', 'm', '\0', /* "phpdorset.co.uk", true */ 'p', 'h', 'p', 'd', 'o', 'r', 's', 'e', 't', '.', 'c', 'o', '.', 'u', 'k', '\0', + /* "phperformances.fr", true */ 'p', 'h', 'p', 'e', 'r', 'f', 'o', 'r', 'm', 'a', 'n', 'c', 'e', 's', '.', 'f', 'r', '\0', /* "phpfashion.com", true */ 'p', 'h', 'p', 'f', 'a', 's', 'h', 'i', 'o', 'n', '.', 'c', 'o', 'm', '\0', /* "phpmyadmin.net", true */ 'p', 'h', 'p', 'm', 'y', 'a', 'd', 'm', 'i', 'n', '.', 'n', 'e', 't', '\0', /* "phpprime.com", true */ 'p', 'h', 'p', 'p', 'r', 'i', 'm', 'e', '.', 'c', 'o', 'm', '\0', @@ -8861,7 +8855,6 @@ /* "playsharp.com", true */ 'p', 'l', 'a', 'y', 's', 'h', 'a', 'r', 'p', '.', 'c', 'o', 'm', '\0', /* "playsoundevents.be", true */ 'p', 'l', 'a', 'y', 's', 'o', 'u', 'n', 'd', 'e', 'v', 'e', 'n', 't', 's', '.', 'b', 'e', '\0', /* "playsprout.industries", true */ 'p', 'l', 'a', 'y', 's', 'p', 'r', 'o', 'u', 't', '.', 'i', 'n', 'd', 'u', 's', 't', 'r', 'i', 'e', 's', '\0', - /* "please-deny.me", true */ 'p', 'l', 'e', 'a', 's', 'e', '-', 'd', 'e', 'n', 'y', '.', 'm', 'e', '\0', /* "pleier-it.de", true */ 'p', 'l', 'e', 'i', 'e', 'r', '-', 'i', 't', '.', 'd', 'e', '\0', /* "pleier.it", true */ 'p', 'l', 'e', 'i', 'e', 'r', '.', 'i', 't', '\0', /* "plen.io", true */ 'p', 'l', 'e', 'n', '.', 'i', 'o', '\0', @@ -8942,6 +8935,7 @@ /* "port443.hamburg", true */ 'p', 'o', 'r', 't', '4', '4', '3', '.', 'h', 'a', 'm', 'b', 'u', 'r', 'g', '\0', /* "port80.hamburg", true */ 'p', 'o', 'r', 't', '8', '0', '.', 'h', 'a', 'm', 'b', 'u', 'r', 'g', '\0', /* "portal.tirol.gv.at", true */ 'p', 'o', 'r', 't', 'a', 'l', '.', 't', 'i', 'r', 'o', 'l', '.', 'g', 'v', '.', 'a', 't', '\0', + /* "portalzine.de", true */ 'p', 'o', 'r', 't', 'a', 'l', 'z', 'i', 'n', 'e', '.', 'd', 'e', '\0', /* "portercup.com", true */ 'p', 'o', 'r', 't', 'e', 'r', 'c', 'u', 'p', '.', 'c', 'o', 'm', '\0', /* "portofrotterdam.com", true */ 'p', 'o', 'r', 't', 'o', 'f', 'r', 'o', 't', 't', 'e', 'r', 'd', 'a', 'm', '.', 'c', 'o', 'm', '\0', /* "portosonline.pl", true */ 'p', 'o', 'r', 't', 'o', 's', 'o', 'n', 'l', 'i', 'n', 'e', '.', 'p', 'l', '\0', @@ -8957,10 +8951,10 @@ /* "postbox.life", true */ 'p', 'o', 's', 't', 'b', 'o', 'x', '.', 'l', 'i', 'f', 'e', '\0', /* "postcodegarant.nl", true */ 'p', 'o', 's', 't', 'c', 'o', 'd', 'e', 'g', 'a', 'r', 'a', 'n', 't', '.', 'n', 'l', '\0', /* "posteo.de", false */ 'p', 'o', 's', 't', 'e', 'o', '.', 'd', 'e', '\0', - /* "posterspy.com", true */ 'p', 'o', 's', 't', 'e', 'r', 's', 'p', 'y', '.', 'c', 'o', 'm', '\0', /* "postfinance.ch", true */ 'p', 'o', 's', 't', 'f', 'i', 'n', 'a', 'n', 'c', 'e', '.', 'c', 'h', '\0', /* "postn.eu", true */ 'p', 'o', 's', 't', 'n', '.', 'e', 'u', '\0', /* "posttigo.com", true */ 'p', 'o', 's', 't', 't', 'i', 'g', 'o', '.', 'c', 'o', 'm', '\0', + /* "potatofrom.space", false */ 'p', 'o', 't', 'a', 't', 'o', 'f', 'r', 'o', 'm', '.', 's', 'p', 'a', 'c', 'e', '\0', /* "potatoheads.net", true */ 'p', 'o', 't', 'a', 't', 'o', 'h', 'e', 'a', 'd', 's', '.', 'n', 'e', 't', '\0', /* "potbar.com", true */ 'p', 'o', 't', 'b', 'a', 'r', '.', 'c', 'o', 'm', '\0', /* "potbox.com", true */ 'p', 'o', 't', 'b', 'o', 'x', '.', 'c', 'o', 'm', '\0', @@ -8984,7 +8978,6 @@ /* "ppipe.net", true */ 'p', 'p', 'i', 'p', 'e', '.', 'n', 'e', 't', '\0', /* "ppmoon.com", true */ 'p', 'p', 'm', 'o', 'o', 'n', '.', 'c', 'o', 'm', '\0', /* "ppro.com", true */ 'p', 'p', 'r', 'o', '.', 'c', 'o', 'm', '\0', - /* "ppuu.org", false */ 'p', 'p', 'u', 'u', '.', 'o', 'r', 'g', '\0', /* "ppy3.com", true */ 'p', 'p', 'y', '3', '.', 'c', 'o', 'm', '\0', /* "pr1sm.com", true */ 'p', 'r', '1', 's', 'm', '.', 'c', 'o', 'm', '\0', /* "pr2studio.com", true */ 'p', 'r', '2', 's', 't', 'u', 'd', 'i', 'o', '.', 'c', 'o', 'm', '\0', @@ -9202,14 +9195,14 @@ /* "qbiju.com.br", true */ 'q', 'b', 'i', 'j', 'u', '.', 'c', 'o', 'm', '.', 'b', 'r', '\0', /* "qbin.io", true */ 'q', 'b', 'i', 'n', '.', 'i', 'o', '\0', /* "qc.search.yahoo.com", false */ 'q', 'c', '.', 's', 'e', 'a', 'r', 'c', 'h', '.', 'y', 'a', 'h', 'o', 'o', '.', 'c', 'o', 'm', '\0', - /* "qccareerschool.com", true */ 'q', 'c', 'c', 'a', 'r', 'e', 'e', 'r', 's', 'c', 'h', 'o', 'o', 'l', '.', 'c', 'o', 'm', '\0', + /* "qccareerschool.com", false */ 'q', 'c', 'c', 'a', 'r', 'e', 'e', 'r', 's', 'c', 'h', 'o', 'o', 'l', '.', 'c', 'o', 'm', '\0', /* "qccqld.org.au", true */ 'q', 'c', 'c', 'q', 'l', 'd', '.', 'o', 'r', 'g', '.', 'a', 'u', '\0', - /* "qcdesignschool.com", true */ 'q', 'c', 'd', 'e', 's', 'i', 'g', 'n', 's', 'c', 'h', 'o', 'o', 'l', '.', 'c', 'o', 'm', '\0', - /* "qceventplanning.com", true */ 'q', 'c', 'e', 'v', 'e', 'n', 't', 'p', 'l', 'a', 'n', 'n', 'i', 'n', 'g', '.', 'c', 'o', 'm', '\0', - /* "qcmakeupacademy.com", true */ 'q', 'c', 'm', 'a', 'k', 'e', 'u', 'p', 'a', 'c', 'a', 'd', 'e', 'm', 'y', '.', 'c', 'o', 'm', '\0', - /* "qcstudentcenter.com", true */ 'q', 'c', 's', 't', 'u', 'd', 'e', 'n', 't', 'c', 'e', 'n', 't', 'e', 'r', '.', 'c', 'o', 'm', '\0', - /* "qcstyleacademy.com", true */ 'q', 'c', 's', 't', 'y', 'l', 'e', 'a', 'c', 'a', 'd', 'e', 'm', 'y', '.', 'c', 'o', 'm', '\0', - /* "qctravelschool.com", true */ 'q', 'c', 't', 'r', 'a', 'v', 'e', 'l', 's', 'c', 'h', 'o', 'o', 'l', '.', 'c', 'o', 'm', '\0', + /* "qcdesignschool.com", false */ 'q', 'c', 'd', 'e', 's', 'i', 'g', 'n', 's', 'c', 'h', 'o', 'o', 'l', '.', 'c', 'o', 'm', '\0', + /* "qceventplanning.com", false */ 'q', 'c', 'e', 'v', 'e', 'n', 't', 'p', 'l', 'a', 'n', 'n', 'i', 'n', 'g', '.', 'c', 'o', 'm', '\0', + /* "qcmakeupacademy.com", false */ 'q', 'c', 'm', 'a', 'k', 'e', 'u', 'p', 'a', 'c', 'a', 'd', 'e', 'm', 'y', '.', 'c', 'o', 'm', '\0', + /* "qcstudentcenter.com", false */ 'q', 'c', 's', 't', 'u', 'd', 'e', 'n', 't', 'c', 'e', 'n', 't', 'e', 'r', '.', 'c', 'o', 'm', '\0', + /* "qcstyleacademy.com", false */ 'q', 'c', 's', 't', 'y', 'l', 'e', 'a', 'c', 'a', 'd', 'e', 'm', 'y', '.', 'c', 'o', 'm', '\0', + /* "qctravelschool.com", false */ 'q', 'c', 't', 'r', 'a', 'v', 'e', 'l', 's', 'c', 'h', 'o', 'o', 'l', '.', 'c', 'o', 'm', '\0', /* "qedcon.org", true */ 'q', 'e', 'd', 'c', 'o', 'n', '.', 'o', 'r', 'g', '\0', /* "qetesh.de", true */ 'q', 'e', 't', 'e', 's', 'h', '.', 'd', 'e', '\0', /* "qewc.com", true */ 'q', 'e', 'w', 'c', '.', 'c', 'o', 'm', '\0', @@ -9246,10 +9239,9 @@ /* "quakelive.dk", true */ 'q', 'u', 'a', 'k', 'e', 'l', 'i', 'v', 'e', '.', 'd', 'k', '\0', /* "qualityedgarsolutions.com", true */ 'q', 'u', 'a', 'l', 'i', 't', 'y', 'e', 'd', 'g', 'a', 'r', 's', 'o', 'l', 'u', 't', 'i', 'o', 'n', 's', '.', 'c', 'o', 'm', '\0', /* "qualityhomesystems.com", true */ 'q', 'u', 'a', 'l', 'i', 't', 'y', 'h', 'o', 'm', 'e', 's', 'y', 's', 't', 'e', 'm', 's', '.', 'c', 'o', 'm', '\0', - /* "qualityofcourse.com", true */ 'q', 'u', 'a', 'l', 'i', 't', 'y', 'o', 'f', 'c', 'o', 'u', 'r', 's', 'e', '.', 'c', 'o', 'm', '\0', + /* "qualityofcourse.com", false */ 'q', 'u', 'a', 'l', 'i', 't', 'y', 'o', 'f', 'c', 'o', 'u', 'r', 's', 'e', '.', 'c', 'o', 'm', '\0', /* "qualityology.com", true */ 'q', 'u', 'a', 'l', 'i', 't', 'y', 'o', 'l', 'o', 'g', 'y', '.', 'c', 'o', 'm', '\0', /* "quanglepro.com", true */ 'q', 'u', 'a', 'n', 'g', 'l', 'e', 'p', 'r', 'o', '.', 'c', 'o', 'm', '\0', - /* "quantenteranik.eu", true */ 'q', 'u', 'a', 'n', 't', 'e', 'n', 't', 'e', 'r', 'a', 'n', 'i', 'k', '.', 'e', 'u', '\0', /* "quantoras.com", true */ 'q', 'u', 'a', 'n', 't', 'o', 'r', 'a', 's', '.', 'c', 'o', 'm', '\0', /* "quantum-cloud.xyz", true */ 'q', 'u', 'a', 'n', 't', 'u', 'm', '-', 'c', 'l', 'o', 'u', 'd', '.', 'x', 'y', 'z', '\0', /* "quantumfurball.net", true */ 'q', 'u', 'a', 'n', 't', 'u', 'm', 'f', 'u', 'r', 'b', 'a', 'l', 'l', '.', 'n', 'e', 't', '\0', @@ -9478,7 +9470,6 @@ /* "remaimodern.org", true */ 'r', 'e', 'm', 'a', 'i', 'm', 'o', 'd', 'e', 'r', 'n', '.', 'o', 'r', 'g', '\0', /* "remambo.jp", true */ 'r', 'e', 'm', 'a', 'm', 'b', 'o', '.', 'j', 'p', '\0', /* "rememberthemilk.com", false */ 'r', 'e', 'm', 'e', 'm', 'b', 'e', 'r', 't', 'h', 'e', 'm', 'i', 'l', 'k', '.', 'c', 'o', 'm', '\0', - /* "remitatm.com", true */ 'r', 'e', 'm', 'i', 't', 'a', 't', 'm', '.', 'c', 'o', 'm', '\0', /* "remonti.info", true */ 'r', 'e', 'm', 'o', 'n', 't', 'i', '.', 'i', 'n', 'f', 'o', '\0', /* "remote.so", true */ 'r', 'e', 'm', 'o', 't', 'e', '.', 's', 'o', '\0', /* "remotestance.com", true */ 'r', 'e', 'm', 'o', 't', 'e', 's', 't', 'a', 'n', 'c', 'e', '.', 'c', 'o', 'm', '\0', @@ -9519,7 +9510,6 @@ /* "restrealitaet.de", true */ 'r', 'e', 's', 't', 'r', 'e', 'a', 'l', 'i', 't', 'a', 'e', 't', '.', 'd', 'e', '\0', /* "restrito.org", true */ 'r', 'e', 's', 't', 'r', 'i', 't', 'o', '.', 'o', 'r', 'g', '\0', /* "retcor.net", true */ 'r', 'e', 't', 'c', 'o', 'r', '.', 'n', 'e', 't', '\0', - /* "reth.ch", true */ 'r', 'e', 't', 'h', '.', 'c', 'h', '\0', /* "reto.com", true */ 'r', 'e', 't', 'o', '.', 'c', 'o', 'm', '\0', /* "retroarms.com", true */ 'r', 'e', 't', 'r', 'o', 'a', 'r', 'm', 's', '.', 'c', 'o', 'm', '\0', /* "retroarms.cz", true */ 'r', 'e', 't', 'r', 'o', 'a', 'r', 'm', 's', '.', 'c', 'z', '\0', @@ -9532,6 +9522,7 @@ /* "revamed.com", false */ 'r', 'e', 'v', 'a', 'm', 'e', 'd', '.', 'c', 'o', 'm', '\0', /* "revapost.ch", true */ 'r', 'e', 'v', 'a', 'p', 'o', 's', 't', '.', 'c', 'h', '\0', /* "revealdata.com", true */ 'r', 'e', 'v', 'e', 'a', 'l', 'd', 'a', 't', 'a', '.', 'c', 'o', 'm', '\0', + /* "revensoftware.com", true */ 'r', 'e', 'v', 'e', 'n', 's', 'o', 'f', 't', 'w', 'a', 'r', 'e', '.', 'c', 'o', 'm', '\0', /* "revlect.com", true */ 'r', 'e', 'v', 'l', 'e', 'c', 't', '.', 'c', 'o', 'm', '\0', /* "revolt.tv", true */ 'r', 'e', 'v', 'o', 'l', 't', '.', 't', 'v', '\0', /* "revthefox.co.uk", true */ 'r', 'e', 'v', 't', 'h', 'e', 'f', 'o', 'x', '.', 'c', 'o', '.', 'u', 'k', '\0', @@ -9779,6 +9770,7 @@ /* "s13d.fr", true */ 's', '1', '3', 'd', '.', 'f', 'r', '\0', /* "s16e.no", true */ 's', '1', '6', 'e', '.', 'n', 'o', '\0', /* "saamhorigheidsfonds.nl", false */ 's', 'a', 'a', 'm', 'h', 'o', 'r', 'i', 'g', 'h', 'e', 'i', 'd', 's', 'f', 'o', 'n', 'd', 's', '.', 'n', 'l', '\0', + /* "saba-piserver.info", true */ 's', 'a', 'b', 'a', '-', 'p', 'i', 's', 'e', 'r', 'v', 'e', 'r', '.', 'i', 'n', 'f', 'o', '\0', /* "sabahattin-gucukoglu.com", true */ 's', 'a', 'b', 'a', 'h', 'a', 't', 't', 'i', 'n', '-', 'g', 'u', 'c', 'u', 'k', 'o', 'g', 'l', 'u', '.', 'c', 'o', 'm', '\0', /* "sacaentradas.com", true */ 's', 'a', 'c', 'a', 'e', 'n', 't', 'r', 'a', 'd', 'a', 's', '.', 'c', 'o', 'm', '\0', /* "saccani.net", true */ 's', 'a', 'c', 'c', 'a', 'n', 'i', '.', 'n', 'e', 't', '\0', @@ -9835,7 +9827,6 @@ /* "samizdat.cz", true */ 's', 'a', 'm', 'i', 'z', 'd', 'a', 't', '.', 'c', 'z', '\0', /* "samkelleher.com", true */ 's', 'a', 'm', 'k', 'e', 'l', 'l', 'e', 'h', 'e', 'r', '.', 'c', 'o', 'm', '\0', /* "saml-gateway.org", true */ 's', 'a', 'm', 'l', '-', 'g', 'a', 't', 'e', 'w', 'a', 'y', '.', 'o', 'r', 'g', '\0', - /* "saml2.com", true */ 's', 'a', 'm', 'l', '2', '.', 'c', 'o', 'm', '\0', /* "samuelkeeley.com", true */ 's', 'a', 'm', 'u', 'e', 'l', 'k', 'e', 'e', 'l', 'e', 'y', '.', 'c', 'o', 'm', '\0', /* "samwilberforce.com", true */ 's', 'a', 'm', 'w', 'i', 'l', 'b', 'e', 'r', 'f', 'o', 'r', 'c', 'e', '.', 'c', 'o', 'm', '\0', /* "samwu.tw", false */ 's', 'a', 'm', 'w', 'u', '.', 't', 'w', '\0', @@ -9992,7 +9983,7 @@ /* "scp-trens.notaires.fr", true */ 's', 'c', 'p', '-', 't', 'r', 'e', 'n', 's', '.', 'n', 'o', 't', 'a', 'i', 'r', 'e', 's', '.', 'f', 'r', '\0', /* "scrap.tf", true */ 's', 'c', 'r', 'a', 'p', '.', 't', 'f', '\0', /* "scrayos.net", true */ 's', 'c', 'r', 'a', 'y', 'o', 's', '.', 'n', 'e', 't', '\0', - /* "screencaster.io", true */ 's', 'c', 'r', 'e', 'e', 'n', 'c', 'a', 's', 't', 'e', 'r', '.', 'i', 'o', '\0', + /* "screenlight.tv", true */ 's', 'c', 'r', 'e', 'e', 'n', 'l', 'i', 'g', 'h', 't', '.', 't', 'v', '\0', /* "screensaversplanet.com", true */ 's', 'c', 'r', 'e', 'e', 'n', 's', 'a', 'v', 'e', 'r', 's', 'p', 'l', 'a', 'n', 'e', 't', '.', 'c', 'o', 'm', '\0', /* "scrion.com", true */ 's', 'c', 'r', 'i', 'o', 'n', '.', 'c', 'o', 'm', '\0', /* "script.google.com", true */ 's', 'c', 'r', 'i', 'p', 't', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm', '\0', @@ -10061,7 +10052,6 @@ /* "securityglance.com", true */ 's', 'e', 'c', 'u', 'r', 'i', 't', 'y', 'g', 'l', 'a', 'n', 'c', 'e', '.', 'c', 'o', 'm', '\0', /* "securityheaders.com", true */ 's', 'e', 'c', 'u', 'r', 'i', 't', 'y', 'h', 'e', 'a', 'd', 'e', 'r', 's', '.', 'c', 'o', 'm', '\0', /* "securityheaders.io", true */ 's', 'e', 'c', 'u', 'r', 'i', 't', 'y', 'h', 'e', 'a', 'd', 'e', 'r', 's', '.', 'i', 'o', '\0', - /* "securitymap.wiki", true */ 's', 'e', 'c', 'u', 'r', 'i', 't', 'y', 'm', 'a', 'p', '.', 'w', 'i', 'k', 'i', '\0', /* "securityprimes.in", true */ 's', 'e', 'c', 'u', 'r', 'i', 't', 'y', 'p', 'r', 'i', 'm', 'e', 's', '.', 'i', 'n', '\0', /* "securitysnobs.com", false */ 's', 'e', 'c', 'u', 'r', 'i', 't', 'y', 's', 'n', 'o', 'b', 's', '.', 'c', 'o', 'm', '\0', /* "securitystreak.com", true */ 's', 'e', 'c', 'u', 'r', 'i', 't', 'y', 's', 't', 'r', 'e', 'a', 'k', '.', 'c', 'o', 'm', '\0', @@ -10097,6 +10087,7 @@ /* "semps-threema.de", true */ 's', 'e', 'm', 'p', 's', '-', 't', 'h', 'r', 'e', 'e', 'm', 'a', '.', 'd', 'e', '\0', /* "semyonov.su", true */ 's', 'e', 'm', 'y', 'o', 'n', 'o', 'v', '.', 's', 'u', '\0', /* "semyonov.us", true */ 's', 'e', 'm', 'y', 'o', 'n', 'o', 'v', '.', 'u', 's', '\0', + /* "sendash.com", true */ 's', 'e', 'n', 'd', 'a', 's', 'h', '.', 'c', 'o', 'm', '\0', /* "sendc.at", true */ 's', 'e', 'n', 'd', 'c', '.', 'a', 't', '\0', /* "sendcat.com", true */ 's', 'e', 'n', 'd', 'c', 'a', 't', '.', 'c', 'o', 'm', '\0', /* "sendinvoice.nl", true */ 's', 'e', 'n', 'd', 'i', 'n', 'v', 'o', 'i', 'c', 'e', '.', 'n', 'l', '\0', @@ -10171,9 +10162,9 @@ /* "sg.search.yahoo.com", false */ 's', 'g', '.', 's', 'e', 'a', 'r', 'c', 'h', '.', 'y', 'a', 'h', 'o', 'o', '.', 'c', 'o', 'm', '\0', /* "sgcaccounts.co.uk", true */ 's', 'g', 'c', 'a', 'c', 'c', 'o', 'u', 'n', 't', 's', '.', 'c', 'o', '.', 'u', 'k', '\0', /* "sgtcodfish.com", true */ 's', 'g', 't', 'c', 'o', 'd', 'f', 'i', 's', 'h', '.', 'c', 'o', 'm', '\0', + /* "sh-network.de", false */ 's', 'h', '-', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'd', 'e', '\0', /* "shaaaaaaaaaaaaa.com", true */ 's', 'h', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', '.', 'c', 'o', 'm', '\0', /* "shadex.net", true */ 's', 'h', 'a', 'd', 'e', 'x', '.', 'n', 'e', 't', '\0', - /* "shadowguardian507-irl.tk", true */ 's', 'h', 'a', 'd', 'o', 'w', 'g', 'u', 'a', 'r', 'd', 'i', 'a', 'n', '5', '0', '7', '-', 'i', 'r', 'l', '.', 't', 'k', '\0', /* "shadowkitsune.net", true */ 's', 'h', 'a', 'd', 'o', 'w', 'k', 'i', 't', 's', 'u', 'n', 'e', '.', 'n', 'e', 't', '\0', /* "shadowplus.net", true */ 's', 'h', 'a', 'd', 'o', 'w', 'p', 'l', 'u', 's', '.', 'n', 'e', 't', '\0', /* "shadowrocket.net", true */ 's', 'h', 'a', 'd', 'o', 'w', 'r', 'o', 'c', 'k', 'e', 't', '.', 'n', 'e', 't', '\0', @@ -10190,6 +10181,7 @@ /* "shanewadleigh.com", true */ 's', 'h', 'a', 'n', 'e', 'w', 'a', 'd', 'l', 'e', 'i', 'g', 'h', '.', 'c', 'o', 'm', '\0', /* "shannoneichorn.com", true */ 's', 'h', 'a', 'n', 'n', 'o', 'n', 'e', 'i', 'c', 'h', 'o', 'r', 'n', '.', 'c', 'o', 'm', '\0', /* "shansing.com", true */ 's', 'h', 'a', 'n', 's', 'i', 'n', 'g', '.', 'c', 'o', 'm', '\0', + /* "shansing.net", true */ 's', 'h', 'a', 'n', 's', 'i', 'n', 'g', '.', 'n', 'e', 't', '\0', /* "shansing.space", true */ 's', 'h', 'a', 'n', 's', 'i', 'n', 'g', '.', 's', 'p', 'a', 'c', 'e', '\0', /* "shareimg.xyz", true */ 's', 'h', 'a', 'r', 'e', 'i', 'm', 'g', '.', 'x', 'y', 'z', '\0', /* "sharepass.pw", true */ 's', 'h', 'a', 'r', 'e', 'p', 'a', 's', 's', '.', 'p', 'w', '\0', @@ -10261,6 +10253,7 @@ /* "sidium.de", true */ 's', 'i', 'd', 'i', 'u', 'm', '.', 'd', 'e', '\0', /* "sidnicio.us", true */ 's', 'i', 'd', 'n', 'i', 'c', 'i', 'o', '.', 'u', 's', '\0', /* "siebens.net", true */ 's', 'i', 'e', 'b', 'e', 'n', 's', '.', 'n', 'e', 't', '\0', + /* "siebeve.be", true */ 's', 'i', 'e', 'b', 'e', 'v', 'e', '.', 'b', 'e', '\0', /* "sieh.es", false */ 's', 'i', 'e', 'h', '.', 'e', 's', '\0', /* "siewert-kau.de", true */ 's', 'i', 'e', 'w', 'e', 'r', 't', '-', 'k', 'a', 'u', '.', 'd', 'e', '\0', /* "sift-tool.org", true */ 's', 'i', 'f', 't', '-', 't', 'o', 'o', 'l', '.', 'o', 'r', 'g', '\0', @@ -10290,7 +10283,6 @@ /* "silentundo.org", true */ 's', 'i', 'l', 'e', 'n', 't', 'u', 'n', 'd', 'o', '.', 'o', 'r', 'g', '\0', /* "siliconchip.me", true */ 's', 'i', 'l', 'i', 'c', 'o', 'n', 'c', 'h', 'i', 'p', '.', 'm', 'e', '\0', /* "silkebaekken.no", true */ 's', 'i', 'l', 'k', 'e', 'b', 'a', 'e', 'k', 'k', 'e', 'n', '.', 'n', 'o', '\0', - /* "sillisalaatti.fi", true */ 's', 'i', 'l', 'l', 'i', 's', 'a', 'l', 'a', 'a', 't', 't', 'i', '.', 'f', 'i', '\0', /* "silqueskineyeserum.com", true */ 's', 'i', 'l', 'q', 'u', 'e', 's', 'k', 'i', 'n', 'e', 'y', 'e', 's', 'e', 'r', 'u', 'm', '.', 'c', 'o', 'm', '\0', /* "silver-heart.co.uk", true */ 's', 'i', 'l', 'v', 'e', 'r', '-', 'h', 'e', 'a', 'r', 't', '.', 'c', 'o', '.', 'u', 'k', '\0', /* "silverbowflyshop.com", true */ 's', 'i', 'l', 'v', 'e', 'r', 'b', 'o', 'w', 'f', 'l', 'y', 's', 'h', 'o', 'p', '.', 'c', 'o', 'm', '\0', @@ -10327,14 +10319,15 @@ /* "simplicitypvp.net", true */ 's', 'i', 'm', 'p', 'l', 'i', 'c', 'i', 't', 'y', 'p', 'v', 'p', '.', 'n', 'e', 't', '\0', /* "simplixos.org", true */ 's', 'i', 'm', 'p', 'l', 'i', 'x', 'o', 's', '.', 'o', 'r', 'g', '\0', /* "simplycharlottemason.com", true */ 's', 'i', 'm', 'p', 'l', 'y', 'c', 'h', 'a', 'r', 'l', 'o', 't', 't', 'e', 'm', 'a', 's', 'o', 'n', '.', 'c', 'o', 'm', '\0', - /* "simplycloud.de", true */ 's', 'i', 'm', 'p', 'l', 'y', 'c', 'l', 'o', 'u', 'd', '.', 'd', 'e', '\0', /* "simplyfixit.co.uk", true */ 's', 'i', 'm', 'p', 'l', 'y', 'f', 'i', 'x', 'i', 't', '.', 'c', 'o', '.', 'u', 'k', '\0', + /* "simplymozzo.se", true */ 's', 'i', 'm', 'p', 'l', 'y', 'm', 'o', 'z', 'z', 'o', '.', 's', 'e', '\0', /* "simplystudio.com", true */ 's', 'i', 'm', 'p', 'l', 'y', 's', 't', 'u', 'd', 'i', 'o', '.', 'c', 'o', 'm', '\0', /* "simpte.com", true */ 's', 'i', 'm', 'p', 't', 'e', '.', 'c', 'o', 'm', '\0', /* "simpul.nl", true */ 's', 'i', 'm', 'p', 'u', 'l', '.', 'n', 'l', '\0', /* "simumiehet.com", true */ 's', 'i', 'm', 'u', 'm', 'i', 'e', 'h', 'e', 't', '.', 'c', 'o', 'm', '\0', /* "simus.fr", true */ 's', 'i', 'm', 'u', 's', '.', 'f', 'r', '\0', /* "sin30.net", true */ 's', 'i', 'n', '3', '0', '.', 'n', 'e', 't', '\0', + /* "sinful.pw", true */ 's', 'i', 'n', 'f', 'u', 'l', '.', 'p', 'w', '\0', /* "singleuse.link", true */ 's', 'i', 'n', 'g', 'l', 'e', 'u', 's', 'e', '.', 'l', 'i', 'n', 'k', '\0', /* "singlu10.org", false */ 's', 'i', 'n', 'g', 'l', 'u', '1', '0', '.', 'o', 'r', 'g', '\0', /* "singul4rity.com", true */ 's', 'i', 'n', 'g', 'u', 'l', '4', 'r', 'i', 't', 'y', '.', 'c', 'o', 'm', '\0', @@ -10411,7 +10404,6 @@ /* "slaps.be", true */ 's', 'l', 'a', 'p', 's', '.', 'b', 'e', '\0', /* "slashdesign.it", true */ 's', 'l', 'a', 's', 'h', 'd', 'e', 's', 'i', 'g', 'n', '.', 'i', 't', '\0', /* "slauber.de", true */ 's', 'l', 'a', 'u', 'b', 'e', 'r', '.', 'd', 'e', '\0', - /* "sleep10.com", true */ 's', 'l', 'e', 'e', 'p', '1', '0', '.', 'c', 'o', 'm', '\0', /* "sleeplessbeastie.eu", true */ 's', 'l', 'e', 'e', 'p', 'l', 'e', 's', 's', 'b', 'e', 'a', 's', 't', 'i', 'e', '.', 'e', 'u', '\0', /* "sleepstar.co.uk", true */ 's', 'l', 'e', 'e', 'p', 's', 't', 'a', 'r', '.', 'c', 'o', '.', 'u', 'k', '\0', /* "sleepstar.com.mt", true */ 's', 'l', 'e', 'e', 'p', 's', 't', 'a', 'r', '.', 'c', 'o', 'm', '.', 'm', 't', '\0', @@ -10464,7 +10456,6 @@ /* "smb445.com", true */ 's', 'm', 'b', '4', '4', '5', '.', 'c', 'o', 'm', '\0', /* "smdavis.us", true */ 's', 'm', 'd', 'a', 'v', 'i', 's', '.', 'u', 's', '\0', /* "smdcn.net", true */ 's', 'm', 'd', 'c', 'n', '.', 'n', 'e', 't', '\0', - /* "smdev.fr", true */ 's', 'm', 'd', 'e', 'v', '.', 'f', 'r', '\0', /* "sme-gmbh.net", true */ 's', 'm', 'e', '-', 'g', 'm', 'b', 'h', '.', 'n', 'e', 't', '\0', /* "smiatek.name", true */ 's', 'm', 'i', 'a', 't', 'e', 'k', '.', 'n', 'a', 'm', 'e', '\0', /* "smipty.cn", true */ 's', 'm', 'i', 'p', 't', 'y', '.', 'c', 'n', '\0', @@ -10537,7 +10528,6 @@ /* "softwarebetrieb.de", true */ 's', 'o', 'f', 't', 'w', 'a', 'r', 'e', 'b', 'e', 't', 'r', 'i', 'e', 'b', '.', 'd', 'e', '\0', /* "softwaredesign.foundation", true */ 's', 'o', 'f', 't', 'w', 'a', 'r', 'e', 'd', 'e', 's', 'i', 'g', 'n', '.', 'f', 'o', 'u', 'n', 'd', 'a', 't', 'i', 'o', 'n', '\0', /* "softwerk-edv.de", true */ 's', 'o', 'f', 't', 'w', 'e', 'r', 'k', '-', 'e', 'd', 'v', '.', 'd', 'e', '\0', - /* "sogeek.me", false */ 's', 'o', 'g', 'e', 'e', 'k', '.', 'm', 'e', '\0', /* "sogravatas.com.br", true */ 's', 'o', 'g', 'r', 'a', 'v', 'a', 't', 'a', 's', '.', 'c', 'o', 'm', '.', 'b', 'r', '\0', /* "sogravatas.net.br", true */ 's', 'o', 'g', 'r', 'a', 'v', 'a', 't', 'a', 's', '.', 'n', 'e', 't', '.', 'b', 'r', '\0', /* "sogutma.com.tr", true */ 's', 'o', 'g', 'u', 't', 'm', 'a', '.', 'c', 'o', 'm', '.', 't', 'r', '\0', @@ -10575,7 +10565,6 @@ /* "sonarqube.com", true */ 's', 'o', 'n', 'a', 'r', 'q', 'u', 'b', 'e', '.', 'c', 'o', 'm', '\0', /* "sondergaard.de", true */ 's', 'o', 'n', 'd', 'e', 'r', 'g', 'a', 'a', 'r', 'd', '.', 'd', 'e', '\0', /* "sonerezh.bzh", true */ 's', 'o', 'n', 'e', 'r', 'e', 'z', 'h', '.', 'b', 'z', 'h', '\0', - /* "sonicrainboom.rocks", true */ 's', 'o', 'n', 'i', 'c', 'r', 'a', 'i', 'n', 'b', 'o', 'o', 'm', '.', 'r', 'o', 'c', 'k', 's', '\0', /* "soobi.org", true */ 's', 'o', 'o', 'b', 'i', '.', 'o', 'r', 'g', '\0', /* "soondy.com", false */ 's', 'o', 'o', 'n', 'd', 'y', '.', 'c', 'o', 'm', '\0', /* "soph.us", true */ 's', 'o', 'p', 'h', '.', 'u', 's', '\0', @@ -10591,7 +10580,6 @@ /* "sos.sk", true */ 's', 'o', 's', '.', 's', 'k', '\0', /* "sosaka.ml", true */ 's', 'o', 's', 'a', 'k', 'a', '.', 'm', 'l', '\0', /* "sosecu.red", true */ 's', 'o', 's', 'e', 'c', 'u', '.', 'r', 'e', 'd', '\0', - /* "sotiran.com", true */ 's', 'o', 't', 'i', 'r', 'a', 'n', '.', 'c', 'o', 'm', '\0', /* "sou-co.jp", true */ 's', 'o', 'u', '-', 'c', 'o', '.', 'j', 'p', '\0', /* "soucorneteiro.com.br", true */ 's', 'o', 'u', 'c', 'o', 'r', 'n', 'e', 't', 'e', 'i', 'r', 'o', '.', 'c', 'o', 'm', '.', 'b', 'r', '\0', /* "souki.cz", true */ 's', 'o', 'u', 'k', 'i', '.', 'c', 'z', '\0', @@ -10607,7 +10595,6 @@ /* "sourcecode.love", true */ 's', 'o', 'u', 'r', 'c', 'e', 'c', 'o', 'd', 'e', '.', 'l', 'o', 'v', 'e', '\0', /* "sourcely.net", true */ 's', 'o', 'u', 'r', 'c', 'e', 'l', 'y', '.', 'n', 'e', 't', '\0', /* "sourceway.de", true */ 's', 'o', 'u', 'r', 'c', 'e', 'w', 'a', 'y', '.', 'd', 'e', '\0', - /* "sourcitec.com", true */ 's', 'o', 'u', 'r', 'c', 'i', 't', 'e', 'c', '.', 'c', 'o', 'm', '\0', /* "sous-surveillance.net", true */ 's', 'o', 'u', 's', '-', 's', 'u', 'r', 'v', 'e', 'i', 'l', 'l', 'a', 'n', 'c', 'e', '.', 'n', 'e', 't', '\0', /* "southamerican.dating", true */ 's', 'o', 'u', 't', 'h', 'a', 'm', 'e', 'r', 'i', 'c', 'a', 'n', '.', 'd', 'a', 't', 'i', 'n', 'g', '\0', /* "southernjamusa.com", true */ 's', 'o', 'u', 't', 'h', 'e', 'r', 'n', 'j', 'a', 'm', 'u', 's', 'a', '.', 'c', 'o', 'm', '\0', @@ -10793,7 +10780,6 @@ /* "stationary-traveller.eu", true */ 's', 't', 'a', 't', 'i', 'o', 'n', 'a', 'r', 'y', '-', 't', 'r', 'a', 'v', 'e', 'l', 'l', 'e', 'r', '.', 'e', 'u', '\0', /* "stats.g.doubleclick.net", true */ 's', 't', 'a', 't', 's', '.', 'g', '.', 'd', 'o', 'u', 'b', 'l', 'e', 'c', 'l', 'i', 'c', 'k', '.', 'n', 'e', 't', '\0', /* "statuscode.ch", true */ 's', 't', 'a', 't', 'u', 's', 'c', 'o', 'd', 'e', '.', 'c', 'h', '\0', - /* "stay.black", true */ 's', 't', 'a', 'y', '.', 'b', 'l', 'a', 'c', 'k', '\0', /* "stayokhotelscdc-mailing.com", true */ 's', 't', 'a', 'y', 'o', 'k', 'h', 'o', 't', 'e', 'l', 's', 'c', 'd', 'c', '-', 'm', 'a', 'i', 'l', 'i', 'n', 'g', '.', 'c', 'o', 'm', '\0', /* "stbennett.org", true */ 's', 't', 'b', 'e', 'n', 'n', 'e', 't', 't', '.', 'o', 'r', 'g', '\0', /* "stcu.org", true */ 's', 't', 'c', 'u', '.', 'o', 'r', 'g', '\0', @@ -10910,6 +10896,7 @@ /* "stulda.cz", true */ 's', 't', 'u', 'l', 'd', 'a', '.', 'c', 'z', '\0', /* "stumf.si", true */ 's', 't', 'u', 'm', 'f', '.', 's', 'i', '\0', /* "stuntmen.xyz", true */ 's', 't', 'u', 'n', 't', 'm', 'e', 'n', '.', 'x', 'y', 'z', '\0', + /* "stupendous.net", true */ 's', 't', 'u', 'p', 'e', 'n', 'd', 'o', 'u', 's', '.', 'n', 'e', 't', '\0', /* "sturbi.de", true */ 's', 't', 'u', 'r', 'b', 'i', '.', 'd', 'e', '\0', /* "sturbock.me", true */ 's', 't', 'u', 'r', 'b', 'o', 'c', 'k', '.', 'm', 'e', '\0', /* "stutelage.com", true */ 's', 't', 'u', 't', 'e', 'l', 'a', 'g', 'e', '.', 'c', 'o', 'm', '\0', @@ -10917,7 +10904,6 @@ /* "stygium.net", true */ 's', 't', 'y', 'g', 'i', 'u', 'm', '.', 'n', 'e', 't', '\0', /* "styleci.io", true */ 's', 't', 'y', 'l', 'e', 'c', 'i', '.', 'i', 'o', '\0', /* "stylenda.com", true */ 's', 't', 'y', 'l', 'e', 'n', 'd', 'a', '.', 'c', 'o', 'm', '\0', - /* "styles.pm", true */ 's', 't', 'y', 'l', 'e', 's', '.', 'p', 'm', '\0', /* "stylle.me", true */ 's', 't', 'y', 'l', 'l', 'e', '.', 'm', 'e', '\0', /* "su1ph3r.io", true */ 's', 'u', '1', 'p', 'h', '3', 'r', '.', 'i', 'o', '\0', /* "suave.io", true */ 's', 'u', 'a', 'v', 'e', '.', 'i', 'o', '\0', @@ -10934,6 +10920,7 @@ /* "sudaraka.org", true */ 's', 'u', 'd', 'a', 'r', 'a', 'k', 'a', '.', 'o', 'r', 'g', '\0', /* "sudo.ws", true */ 's', 'u', 'd', 'o', '.', 'w', 's', '\0', /* "sudoschool.com", true */ 's', 'u', 'd', 'o', 's', 'c', 'h', 'o', 'o', 'l', '.', 'c', 'o', 'm', '\0', + /* "sufix.cz", true */ 's', 'u', 'f', 'i', 'x', '.', 'c', 'z', '\0', /* "suian.or.jp", true */ 's', 'u', 'i', 'a', 'n', '.', 'o', 'r', '.', 'j', 'p', '\0', /* "suitocracy.com", true */ 's', 'u', 'i', 't', 'o', 'c', 'r', 'a', 'c', 'y', '.', 'c', 'o', 'm', '\0', /* "sulek.eu", true */ 's', 'u', 'l', 'e', 'k', '.', 'e', 'u', '\0', @@ -11025,6 +11012,7 @@ /* "synatra.co", true */ 's', 'y', 'n', 'a', 't', 'r', 'a', '.', 'c', 'o', '\0', /* "sync-it.no", true */ 's', 'y', 'n', 'c', '-', 'i', 't', '.', 'n', 'o', '\0', /* "syncappate.com", true */ 's', 'y', 'n', 'c', 'a', 'p', 'p', 'a', 't', 'e', '.', 'c', 'o', 'm', '\0', + /* "synchrocube.com", true */ 's', 'y', 'n', 'c', 'h', 'r', 'o', 'c', 'u', 'b', 'e', '.', 'c', 'o', 'm', '\0', /* "synchtu.be", false */ 's', 'y', 'n', 'c', 'h', 't', 'u', '.', 'b', 'e', '\0', /* "syncmylife.net", true */ 's', 'y', 'n', 'c', 'm', 'y', 'l', 'i', 'f', 'e', '.', 'n', 'e', 't', '\0', /* "syndic-discount.fr", false */ 's', 'y', 'n', 'd', 'i', 'c', '-', 'd', 'i', 's', 'c', 'o', 'u', 'n', 't', '.', 'f', 'r', '\0', @@ -11202,7 +11190,6 @@ /* "tege-elektronik.hu", true */ 't', 'e', 'g', 'e', '-', 'e', 'l', 'e', 'k', 't', 'r', 'o', 'n', 'i', 'k', '.', 'h', 'u', '\0', /* "tehotuotanto.net", true */ 't', 'e', 'h', 'o', 't', 'u', 'o', 't', 'a', 'n', 't', 'o', '.', 'n', 'e', 't', '\0', /* "tehrabbitt.com", false */ 't', 'e', 'h', 'r', 'a', 'b', 'b', 'i', 't', 't', '.', 'c', 'o', 'm', '\0', - /* "teknologi.or.id", true */ 't', 'e', 'k', 'n', 'o', 'l', 'o', 'g', 'i', '.', 'o', 'r', '.', 'i', 'd', '\0', /* "tektoria.de", false */ 't', 'e', 'k', 't', 'o', 'r', 'i', 'a', '.', 'd', 'e', '\0', /* "tel-dithmarschen.de", true */ 't', 'e', 'l', '-', 'd', 'i', 't', 'h', 'm', 'a', 'r', 's', 'c', 'h', 'e', 'n', '.', 'd', 'e', '\0', /* "telefisk.org", true */ 't', 'e', 'l', 'e', 'f', 'i', 's', 'k', '.', 'o', 'r', 'g', '\0', @@ -11259,7 +11246,6 @@ /* "teunstuinposters.nl", false */ 't', 'e', 'u', 'n', 's', 't', 'u', 'i', 'n', 'p', 'o', 's', 't', 'e', 'r', 's', '.', 'n', 'l', '\0', /* "textburst.com", true */ 't', 'e', 'x', 't', 'b', 'u', 'r', 's', 't', '.', 'c', 'o', 'm', '\0', /* "texte-zur-taufe.de", true */ 't', 'e', 'x', 't', 'e', '-', 'z', 'u', 'r', '-', 't', 'a', 'u', 'f', 'e', '.', 'd', 'e', '\0', - /* "texter-linz.at", true */ 't', 'e', 'x', 't', 'e', 'r', '-', 'l', 'i', 'n', 'z', '.', 'a', 't', '\0', /* "texterseo.at", true */ 't', 'e', 'x', 't', 'e', 'r', 's', 'e', 'o', '.', 'a', 't', '\0', /* "textualapp.com", true */ 't', 'e', 'x', 't', 'u', 'a', 'l', 'a', 'p', 'p', '.', 'c', 'o', 'm', '\0', /* "texy.info", true */ 't', 'e', 'x', 'y', '.', 'i', 'n', 'f', 'o', '\0', @@ -11451,7 +11437,6 @@ /* "ticketoplichting.nl", true */ 't', 'i', 'c', 'k', 'e', 't', 'o', 'p', 'l', 'i', 'c', 'h', 't', 'i', 'n', 'g', '.', 'n', 'l', '\0', /* "tickettoaster.de", true */ 't', 'i', 'c', 'k', 'e', 't', 't', 'o', 'a', 's', 't', 'e', 'r', '.', 'd', 'e', '\0', /* "tid.jp", true */ 't', 'i', 'd', '.', 'j', 'p', '\0', - /* "tidmore.us", true */ 't', 'i', 'd', 'm', 'o', 'r', 'e', '.', 'u', 's', '\0', /* "tidycustoms.net", true */ 't', 'i', 'd', 'y', 'c', 'u', 's', 't', 'o', 'm', 's', '.', 'n', 'e', 't', '\0', /* "tiendavertigo.com", true */ 't', 'i', 'e', 'n', 'd', 'a', 'v', 'e', 'r', 't', 'i', 'g', 'o', '.', 'c', 'o', 'm', '\0', /* "tiendschuurstraat.nl", true */ 't', 'i', 'e', 'n', 'd', 's', 'c', 'h', 'u', 'u', 'r', 's', 't', 'r', 'a', 'a', 't', '.', 'n', 'l', '\0', @@ -11505,6 +11490,7 @@ /* "titiansgirlphotography.com", true */ 't', 'i', 't', 'i', 'a', 'n', 's', 'g', 'i', 'r', 'l', 'p', 'h', 'o', 't', 'o', 'g', 'r', 'a', 'p', 'h', 'y', '.', 'c', 'o', 'm', '\0', /* "titouan.co", false */ 't', 'i', 't', 'o', 'u', 'a', 'n', '.', 'c', 'o', '\0', /* "tjenestetorvet.dk", true */ 't', 'j', 'e', 'n', 'e', 's', 't', 'e', 't', 'o', 'r', 'v', 'e', 't', '.', 'd', 'k', '\0', + /* "tjs.me", true */ 't', 'j', 's', '.', 'm', 'e', '\0', /* "tkat.ch", true */ 't', 'k', 'a', 't', '.', 'c', 'h', '\0', /* "tlach.cz", true */ 't', 'l', 'a', 'c', 'h', '.', 'c', 'z', '\0', /* "tlo.link", true */ 't', 'l', 'o', '.', 'l', 'i', 'n', 'k', '\0', @@ -11564,10 +11550,11 @@ /* "tomcort.com", true */ 't', 'o', 'm', 'c', 'o', 'r', 't', '.', 'c', 'o', 'm', '\0', /* "tomend.es", true */ 't', 'o', 'm', 'e', 'n', 'd', '.', 'e', 's', '\0', /* "tomfisher.eu", true */ 't', 'o', 'm', 'f', 'i', 's', 'h', 'e', 'r', '.', 'e', 'u', '\0', + /* "tomli.me", true */ 't', 'o', 'm', 'l', 'i', '.', 'm', 'e', '\0', /* "tommyads.com", true */ 't', 'o', 'm', 'm', 'y', 'a', 'd', 's', '.', 'c', 'o', 'm', '\0', /* "tomo.gr", false */ 't', 'o', 'm', 'o', '.', 'g', 'r', '\0', /* "tomrei.com", true */ 't', 'o', 'm', 'r', 'e', 'i', '.', 'c', 'o', 'm', '\0', - /* "tomrichards.net", false */ 't', 'o', 'm', 'r', 'i', 'c', 'h', 'a', 'r', 'd', 's', '.', 'n', 'e', 't', '\0', + /* "tomrichards.net", true */ 't', 'o', 'm', 'r', 'i', 'c', 'h', 'a', 'r', 'd', 's', '.', 'n', 'e', 't', '\0', /* "tomssl.com", true */ 't', 'o', 'm', 's', 's', 'l', '.', 'c', 'o', 'm', '\0', /* "tomudding.nl", true */ 't', 'o', 'm', 'u', 'd', 'd', 'i', 'n', 'g', '.', 'n', 'l', '\0', /* "tomvote.com", true */ 't', 'o', 'm', 'v', 'o', 't', 'e', '.', 'c', 'o', 'm', '\0', @@ -11675,7 +11662,6 @@ /* "tradiz.org", true */ 't', 'r', 'a', 'd', 'i', 'z', '.', 'o', 'r', 'g', '\0', /* "trafficquality.org", true */ 't', 'r', 'a', 'f', 'f', 'i', 'c', 'q', 'u', 'a', 'l', 'i', 't', 'y', '.', 'o', 'r', 'g', '\0', /* "traffixdevices.com", true */ 't', 'r', 'a', 'f', 'f', 'i', 'x', 'd', 'e', 'v', 'i', 'c', 'e', 's', '.', 'c', 'o', 'm', '\0', - /* "traindb.nl", true */ 't', 'r', 'a', 'i', 'n', 'd', 'b', '.', 'n', 'l', '\0', /* "trainex.org", true */ 't', 'r', 'a', 'i', 'n', 'e', 'x', '.', 'o', 'r', 'g', '\0', /* "trainline.de", true */ 't', 'r', 'a', 'i', 'n', 'l', 'i', 'n', 'e', '.', 'd', 'e', '\0', /* "trainline.es", true */ 't', 'r', 'a', 'i', 'n', 'l', 'i', 'n', 'e', '.', 'e', 's', '\0', @@ -11714,7 +11700,6 @@ /* "travisfranck.com", true */ 't', 'r', 'a', 'v', 'i', 's', 'f', 'r', 'a', 'n', 'c', 'k', '.', 'c', 'o', 'm', '\0', /* "travler.net", true */ 't', 'r', 'a', 'v', 'l', 'e', 'r', '.', 'n', 'e', 't', '\0', /* "treebaglia.xyz", true */ 't', 'r', 'e', 'e', 'b', 'a', 'g', 'l', 'i', 'a', '.', 'x', 'y', 'z', '\0', - /* "treeby.net", true */ 't', 'r', 'e', 'e', 'b', 'y', '.', 'n', 'e', 't', '\0', /* "treeschat.com", true */ 't', 'r', 'e', 'e', 's', 'c', 'h', 'a', 't', '.', 'c', 'o', 'm', '\0', /* "trefpuntdemeent.nl", true */ 't', 'r', 'e', 'f', 'p', 'u', 'n', 't', 'd', 'e', 'm', 'e', 'e', 'n', 't', '.', 'n', 'l', '\0', /* "treinaweb.com.br", true */ 't', 'r', 'e', 'i', 'n', 'a', 'w', 'e', 'b', '.', 'c', 'o', 'm', '.', 'b', 'r', '\0', @@ -11815,7 +11800,6 @@ /* "tuxgeo.com", false */ 't', 'u', 'x', 'g', 'e', 'o', '.', 'c', 'o', 'm', '\0', /* "tuxie.com", true */ 't', 'u', 'x', 'i', 'e', '.', 'c', 'o', 'm', '\0', /* "tuxplace.nl", true */ 't', 'u', 'x', 'p', 'l', 'a', 'c', 'e', '.', 'n', 'l', '\0', - /* "tuxz.net", true */ 't', 'u', 'x', 'z', '.', 'n', 'e', 't', '\0', /* "tuzaijidi.com", true */ 't', 'u', 'z', 'a', 'i', 'j', 'i', 'd', 'i', '.', 'c', 'o', 'm', '\0', /* "tv2vie.org", true */ 't', 'v', '2', 'v', 'i', 'e', '.', 'o', 'r', 'g', '\0', /* "tvbeugels.nl", false */ 't', 'v', 'b', 'e', 'u', 'g', 'e', 'l', 's', '.', 'n', 'l', '\0', @@ -11862,7 +11846,6 @@ /* "uasmi.com", true */ 'u', 'a', 's', 'm', 'i', '.', 'c', 'o', 'm', '\0', /* "uat-activesg.com", true */ 'u', 'a', 't', '-', 'a', 'c', 't', 'i', 'v', 'e', 's', 'g', '.', 'c', 'o', 'm', '\0', /* "ub3rk1tten.com", false */ 'u', 'b', '3', 'r', 'k', '1', 't', 't', 'e', 'n', '.', 'c', 'o', 'm', '\0', - /* "ubanquity.com", true */ 'u', 'b', 'a', 'n', 'q', 'u', 'i', 't', 'y', '.', 'c', 'o', 'm', '\0', /* "uber.com.au", true */ 'u', 'b', 'e', 'r', '.', 'c', 'o', 'm', '.', 'a', 'u', '\0', /* "uberboxen.net", true */ 'u', 'b', 'e', 'r', 'b', 'o', 'x', 'e', 'n', '.', 'n', 'e', 't', '\0', /* "uberfunction.com", true */ 'u', 'b', 'e', 'r', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', '.', 'c', 'o', 'm', '\0', @@ -11870,6 +11853,7 @@ /* "uberwald.de", true */ 'u', 'b', 'e', 'r', 'w', 'a', 'l', 'd', '.', 'd', 'e', '\0', /* "uberwald.ws", true */ 'u', 'b', 'e', 'r', 'w', 'a', 'l', 'd', '.', 'w', 's', '\0', /* "ubicv.com", true */ 'u', 'b', 'i', 'c', 'v', '.', 'c', 'o', 'm', '\0', + /* "ubtce.com", true */ 'u', 'b', 't', 'c', 'e', '.', 'c', 'o', 'm', '\0', /* "ucfirst.nl", true */ 'u', 'c', 'f', 'i', 'r', 's', 't', '.', 'n', 'l', '\0', /* "udbhav.me", true */ 'u', 'd', 'b', 'h', 'a', 'v', '.', 'm', 'e', '\0', /* "udo-luetkemeier.de", true */ 'u', 'd', 'o', '-', 'l', 'u', 'e', 't', 'k', 'e', 'm', 'e', 'i', 'e', 'r', '.', 'd', 'e', '\0', @@ -11926,6 +11910,7 @@ /* "unblockthe.top", true */ 'u', 'n', 'b', 'l', 'o', 'c', 'k', 't', 'h', 'e', '.', 't', 'o', 'p', '\0', /* "unblockweb.co", true */ 'u', 'n', 'b', 'l', 'o', 'c', 'k', 'w', 'e', 'b', '.', 'c', 'o', '\0', /* "under30stravelinsurance.com.au", true */ 'u', 'n', 'd', 'e', 'r', '3', '0', 's', 't', 'r', 'a', 'v', 'e', 'l', 'i', 'n', 's', 'u', 'r', 'a', 'n', 'c', 'e', '.', 'c', 'o', 'm', '.', 'a', 'u', '\0', + /* "underskatten.tk", true */ 'u', 'n', 'd', 'e', 'r', 's', 'k', 'a', 't', 't', 'e', 'n', '.', 't', 'k', '\0', /* "undo.co.il", true */ 'u', 'n', 'd', 'o', '.', 'c', 'o', '.', 'i', 'l', '\0', /* "undone.me", true */ 'u', 'n', 'd', 'o', 'n', 'e', '.', 'm', 'e', '\0', /* "unearaigneeauplafond.fr", false */ 'u', 'n', 'e', 'a', 'r', 'a', 'i', 'g', 'n', 'e', 'e', 'a', 'u', 'p', 'l', 'a', 'f', 'o', 'n', 'd', '.', 'f', 'r', '\0', @@ -11959,7 +11944,6 @@ /* "unixattic.com", true */ 'u', 'n', 'i', 'x', 'a', 't', 't', 'i', 'c', '.', 'c', 'o', 'm', '\0', /* "unixcorn.org", true */ 'u', 'n', 'i', 'x', 'c', 'o', 'r', 'n', '.', 'o', 'r', 'g', '\0', /* "unlocken.nl", true */ 'u', 'n', 'l', 'o', 'c', 'k', 'e', 'n', '.', 'n', 'l', '\0', - /* "unmanaged.space", true */ 'u', 'n', 'm', 'a', 'n', 'a', 'g', 'e', 'd', '.', 's', 'p', 'a', 'c', 'e', '\0', /* "uno-pizza.ru", true */ 'u', 'n', 'o', '-', 'p', 'i', 'z', 'z', 'a', '.', 'r', 'u', '\0', /* "unoccupyabq.org", true */ 'u', 'n', 'o', 'c', 'c', 'u', 'p', 'y', 'a', 'b', 'q', '.', 'o', 'r', 'g', '\0', /* "unpkg.com", true */ 'u', 'n', 'p', 'k', 'g', '.', 'c', 'o', 'm', '\0', @@ -12016,7 +12000,6 @@ /* "use.be", true */ 'u', 's', 'e', '.', 'b', 'e', '\0', /* "usedesk.ru", true */ 'u', 's', 'e', 'd', 'e', 's', 'k', '.', 'r', 'u', '\0', /* "useresponse.com", true */ 'u', 's', 'e', 'r', 'e', 's', 'p', 'o', 'n', 's', 'e', '.', 'c', 'o', 'm', '\0', - /* "userify.com", true */ 'u', 's', 'e', 'r', 'i', 'f', 'y', '.', 'c', 'o', 'm', '\0', /* "usetypo3.com", true */ 'u', 's', 'e', 't', 'y', 'p', 'o', '3', '.', 'c', 'o', 'm', '\0', /* "usgande.com", true */ 'u', 's', 'g', 'a', 'n', 'd', 'e', '.', 'c', 'o', 'm', '\0', /* "ushare.ch", true */ 'u', 's', 'h', 'a', 'r', 'e', '.', 'c', 'h', '\0', @@ -12090,7 +12073,6 @@ /* "vaultproject.io", true */ 'v', 'a', 'u', 'l', 't', 'p', 'r', 'o', 'j', 'e', 'c', 't', '.', 'i', 'o', '\0', /* "vaur.fr", true */ 'v', 'a', 'u', 'r', '.', 'f', 'r', '\0', /* "vavai.net", true */ 'v', 'a', 'v', 'a', 'i', '.', 'n', 'e', 't', '\0', - /* "vazue.com", true */ 'v', 'a', 'z', 'u', 'e', '.', 'c', 'o', 'm', '\0', /* "vbest.net", true */ 'v', 'b', 'e', 's', 't', '.', 'n', 'e', 't', '\0', /* "vbhelp.org", true */ 'v', 'b', 'h', 'e', 'l', 'p', '.', 'o', 'r', 'g', '\0', /* "vcelin-na-doliku.cz", true */ 'v', 'c', 'e', 'l', 'i', 'n', '-', 'n', 'a', '-', 'd', 'o', 'l', 'i', 'k', 'u', '.', 'c', 'z', '\0', @@ -12124,7 +12106,6 @@ /* "verfassungsklage.at", true */ 'v', 'e', 'r', 'f', 'a', 's', 's', 'u', 'n', 'g', 's', 'k', 'l', 'a', 'g', 'e', '.', 'a', 't', '\0', /* "verifiedinvesting.com", true */ 'v', 'e', 'r', 'i', 'f', 'i', 'e', 'd', 'i', 'n', 'v', 'e', 's', 't', 'i', 'n', 'g', '.', 'c', 'o', 'm', '\0', /* "verifyos.com", true */ 'v', 'e', 'r', 'i', 'f', 'y', 'o', 's', '.', 'c', 'o', 'm', '\0', - /* "veriny.tf", true */ 'v', 'e', 'r', 'i', 'n', 'y', '.', 't', 'f', '\0', /* "verizonguidelines.com", true */ 'v', 'e', 'r', 'i', 'z', 'o', 'n', 'g', 'u', 'i', 'd', 'e', 'l', 'i', 'n', 'e', 's', '.', 'c', 'o', 'm', '\0', /* "veronique-schmitz.de", true */ 'v', 'e', 'r', 'o', 'n', 'i', 'q', 'u', 'e', '-', 's', 'c', 'h', 'm', 'i', 't', 'z', '.', 'd', 'e', '\0', /* "versbeton.nl", true */ 'v', 'e', 'r', 's', 'b', 'e', 't', 'o', 'n', '.', 'n', 'l', '\0', @@ -12189,12 +12170,12 @@ /* "vinner.com.au", true */ 'v', 'i', 'n', 'n', 'e', 'r', '.', 'c', 'o', 'm', '.', 'a', 'u', '\0', /* "vinyculture.com", true */ 'v', 'i', 'n', 'y', 'c', 'u', 'l', 't', 'u', 'r', 'e', '.', 'c', 'o', 'm', '\0', /* "viphospitality.se", true */ 'v', 'i', 'p', 'h', 'o', 's', 'p', 'i', 't', 'a', 'l', 'i', 't', 'y', '.', 's', 'e', '\0', + /* "vipnettikasinoklubi.com", true */ 'v', 'i', 'p', 'n', 'e', 't', 't', 'i', 'k', 'a', 's', 'i', 'n', 'o', 'k', 'l', 'u', 'b', 'i', '.', 'c', 'o', 'm', '\0', /* "virginiacrimeanalysisnetwork.org", true */ 'v', 'i', 'r', 'g', 'i', 'n', 'i', 'a', 'c', 'r', 'i', 'm', 'e', 'a', 'n', 'a', 'l', 'y', 's', 'i', 's', 'n', 'e', 't', 'w', 'o', 'r', 'k', '.', 'o', 'r', 'g', '\0', /* "virtualdesignmedia.com", false */ 'v', 'i', 'r', 't', 'u', 'a', 'l', 'd', 'e', 's', 'i', 'g', 'n', 'm', 'e', 'd', 'i', 'a', '.', 'c', 'o', 'm', '\0', /* "virtuallifestyle.nl", true */ 'v', 'i', 'r', 't', 'u', 'a', 'l', 'l', 'i', 'f', 'e', 's', 't', 'y', 'l', 'e', '.', 'n', 'l', '\0', /* "virtualperez.com", true */ 'v', 'i', 'r', 't', 'u', 'a', 'l', 'p', 'e', 'r', 'e', 'z', '.', 'c', 'o', 'm', '\0', /* "virtualsanity.com", true */ 'v', 'i', 'r', 't', 'u', 'a', 'l', 's', 'a', 'n', 'i', 't', 'y', '.', 'c', 'o', 'm', '\0', - /* "visalogy.com", true */ 'v', 'i', 's', 'a', 'l', 'o', 'g', 'y', '.', 'c', 'o', 'm', '\0', /* "viscopic.com", true */ 'v', 'i', 's', 'c', 'o', 'p', 'i', 'c', '.', 'c', 'o', 'm', '\0', /* "viserproject.com", true */ 'v', 'i', 's', 'e', 'r', 'p', 'r', 'o', 'j', 'e', 'c', 't', '.', 'c', 'o', 'm', '\0', /* "visibox.nl", true */ 'v', 'i', 's', 'i', 'b', 'o', 'x', '.', 'n', 'l', '\0', @@ -12242,7 +12223,6 @@ /* "vocaloid.my", true */ 'v', 'o', 'c', 'a', 'l', 'o', 'i', 'd', '.', 'm', 'y', '\0', /* "vogler.name", true */ 'v', 'o', 'g', 'l', 'e', 'r', '.', 'n', 'a', 'm', 'e', '\0', /* "vogt.tech", true */ 'v', 'o', 'g', 't', '.', 't', 'e', 'c', 'h', '\0', - /* "voidi.ca", true */ 'v', 'o', 'i', 'd', 'i', '.', 'c', 'a', '\0', /* "vokeapp.com", true */ 'v', 'o', 'k', 'e', 'a', 'p', 'p', '.', 'c', 'o', 'm', '\0', /* "volcain.io", true */ 'v', 'o', 'l', 'c', 'a', 'i', 'n', '.', 'i', 'o', '\0', /* "volkden.com", true */ 'v', 'o', 'l', 'k', 'd', 'e', 'n', '.', 'c', 'o', 'm', '\0', @@ -12275,7 +12255,6 @@ /* "vsund.de", true */ 'v', 's', 'u', 'n', 'd', '.', 'd', 'e', '\0', /* "vubey.yt", true */ 'v', 'u', 'b', 'e', 'y', '.', 'y', 't', '\0', /* "vulnerability.ch", true */ 'v', 'u', 'l', 'n', 'e', 'r', 'a', 'b', 'i', 'l', 'i', 't', 'y', '.', 'c', 'h', '\0', - /* "vulners.com", true */ 'v', 'u', 'l', 'n', 'e', 'r', 's', '.', 'c', 'o', 'm', '\0', /* "vumetric.com", true */ 'v', 'u', 'm', 'e', 't', 'r', 'i', 'c', '.', 'c', 'o', 'm', '\0', /* "vuosaarenmontessoritalo.fi", true */ 'v', 'u', 'o', 's', 'a', 'a', 'r', 'e', 'n', 'm', 'o', 'n', 't', 'e', 's', 's', 'o', 'r', 'i', 't', 'a', 'l', 'o', '.', 'f', 'i', '\0', /* "vux.li", true */ 'v', 'u', 'x', '.', 'l', 'i', '\0', @@ -12292,7 +12271,6 @@ /* "wachter.biz", true */ 'w', 'a', 'c', 'h', 't', 'e', 'r', '.', 'b', 'i', 'z', '\0', /* "wachtwoordencheck.nl", true */ 'w', 'a', 'c', 'h', 't', 'w', 'o', 'o', 'r', 'd', 'e', 'n', 'c', 'h', 'e', 'c', 'k', '.', 'n', 'l', '\0', /* "waelti.xxx", true */ 'w', 'a', 'e', 'l', 't', 'i', '.', 'x', 'x', 'x', '\0', - /* "wafa4hw.com", true */ 'w', 'a', 'f', 'a', '4', 'h', 'w', '.', 'c', 'o', 'm', '\0', /* "waffle.at", true */ 'w', 'a', 'f', 'f', 'l', 'e', '.', 'a', 't', '\0', /* "wail.net", true */ 'w', 'a', 'i', 'l', '.', 'n', 'e', 't', '\0', /* "waits.io", true */ 'w', 'a', 'i', 't', 's', '.', 'i', 'o', '\0', @@ -12419,6 +12397,7 @@ /* "webtasarim.pw", true */ 'w', 'e', 'b', 't', 'a', 's', 'a', 'r', 'i', 'm', '.', 'p', 'w', '\0', /* "webtheapp.com", true */ 'w', 'e', 'b', 't', 'h', 'e', 'a', 'p', 'p', '.', 'c', 'o', 'm', '\0', /* "webthings.com.br", true */ 'w', 'e', 'b', 't', 'h', 'i', 'n', 'g', 's', '.', 'c', 'o', 'm', '.', 'b', 'r', '\0', + /* "webtobesocial.de", true */ 'w', 'e', 'b', 't', 'o', 'b', 'e', 's', 'o', 'c', 'i', 'a', 'l', '.', 'd', 'e', '\0', /* "webtorrent.io", true */ 'w', 'e', 'b', 't', 'o', 'r', 'r', 'e', 'n', 't', '.', 'i', 'o', '\0', /* "webtrh.cz", true */ 'w', 'e', 'b', 't', 'r', 'h', '.', 'c', 'z', '\0', /* "webtropia.com", false */ 'w', 'e', 'b', 't', 'r', 'o', 'p', 'i', 'a', '.', 'c', 'o', 'm', '\0', @@ -12432,7 +12411,6 @@ /* "weekly-residence.com", true */ 'w', 'e', 'e', 'k', 'l', 'y', '-', 'r', 'e', 's', 'i', 'd', 'e', 'n', 'c', 'e', '.', 'c', 'o', 'm', '\0', /* "weerstatistieken.nl", true */ 'w', 'e', 'e', 'r', 's', 't', 'a', 't', 'i', 's', 't', 'i', 'e', 'k', 'e', 'n', '.', 'n', 'l', '\0', /* "wefinanceinc.com", true */ 'w', 'e', 'f', 'i', 'n', 'a', 'n', 'c', 'e', 'i', 'n', 'c', '.', 'c', 'o', 'm', '\0', - /* "wegenaer.nl", true */ 'w', 'e', 'g', 'e', 'n', 'a', 'e', 'r', '.', 'n', 'l', '\0', /* "weggeweest.nl", true */ 'w', 'e', 'g', 'g', 'e', 'w', 'e', 'e', 's', 't', '.', 'n', 'l', '\0', /* "wegner.no", true */ 'w', 'e', 'g', 'n', 'e', 'r', '.', 'n', 'o', '\0', /* "weicn.org", true */ 'w', 'e', 'i', 'c', 'n', '.', 'o', 'r', 'g', '\0', @@ -12465,9 +12443,9 @@ /* "werbewelt-tv.de", true */ 'w', 'e', 'r', 'b', 'e', 'w', 'e', 'l', 't', '-', 't', 'v', '.', 'd', 'e', '\0', /* "wereldkoffie.eu", true */ 'w', 'e', 'r', 'e', 'l', 'd', 'k', 'o', 'f', 'f', 'i', 'e', '.', 'e', 'u', '\0', /* "werken-bij-inwork.nl", true */ 'w', 'e', 'r', 'k', 'e', 'n', '-', 'b', 'i', 'j', '-', 'i', 'n', 'w', 'o', 'r', 'k', '.', 'n', 'l', '\0', + /* "werkplaatsoost.nl", false */ 'w', 'e', 'r', 'k', 'p', 'l', 'a', 'a', 't', 's', 'o', 'o', 's', 't', '.', 'n', 'l', '\0', /* "werktor.net", true */ 'w', 'e', 'r', 'k', 't', 'o', 'r', '.', 'n', 'e', 't', '\0', /* "wernerschaeffer.de", true */ 'w', 'e', 'r', 'n', 'e', 'r', 's', 'c', 'h', 'a', 'e', 'f', 'f', 'e', 'r', '.', 'd', 'e', '\0', - /* "wesecom.com", false */ 'w', 'e', 's', 'e', 'c', 'o', 'm', '.', 'c', 'o', 'm', '\0', /* "weserv.nl", true */ 'w', 'e', 's', 'e', 'r', 'v', '.', 'n', 'l', '\0', /* "wesleycabus.be", true */ 'w', 'e', 's', 'l', 'e', 'y', 'c', 'a', 'b', 'u', 's', '.', 'b', 'e', '\0', /* "wessner.org", true */ 'w', 'e', 's', 's', 'n', 'e', 'r', '.', 'o', 'r', 'g', '\0', @@ -12511,7 +12489,6 @@ /* "wherephoto.com", false */ 'w', 'h', 'e', 'r', 'e', 'p', 'h', 'o', 't', 'o', '.', 'c', 'o', 'm', '\0', /* "whey-protein.ch", true */ 'w', 'h', 'e', 'y', '-', 'p', 'r', 'o', 't', 'e', 'i', 'n', '.', 'c', 'h', '\0', /* "whing.org", true */ 'w', 'h', 'i', 'n', 'g', '.', 'o', 'r', 'g', '\0', - /* "whisker.network", true */ 'w', 'h', 'i', 's', 'k', 'e', 'r', '.', 'n', 'e', 't', 'w', 'o', 'r', 'k', '\0', /* "whiskeyriver.co.uk", true */ 'w', 'h', 'i', 's', 'k', 'e', 'y', 'r', 'i', 'v', 'e', 'r', '.', 'c', 'o', '.', 'u', 'k', '\0', /* "whiskynerd.ca", true */ 'w', 'h', 'i', 's', 'k', 'y', 'n', 'e', 'r', 'd', '.', 'c', 'a', '\0', /* "whisp.ly", true */ 'w', 'h', 'i', 's', 'p', '.', 'l', 'y', '\0', @@ -12635,7 +12612,6 @@ /* "wonderhost.info", true */ 'w', 'o', 'n', 'd', 'e', 'r', 'h', 'o', 's', 't', '.', 'i', 'n', 'f', 'o', '\0', /* "wonderlandmovies.de", true */ 'w', 'o', 'n', 'd', 'e', 'r', 'l', 'a', 'n', 'd', 'm', 'o', 'v', 'i', 'e', 's', '.', 'd', 'e', '\0', /* "wondermags.com", true */ 'w', 'o', 'n', 'd', 'e', 'r', 'm', 'a', 'g', 's', '.', 'c', 'o', 'm', '\0', - /* "wondershift.biz", true */ 'w', 'o', 'n', 'd', 'e', 'r', 's', 'h', 'i', 'f', 't', '.', 'b', 'i', 'z', '\0', /* "wondy.com", true */ 'w', 'o', 'n', 'd', 'y', '.', 'c', 'o', 'm', '\0', /* "woodbury.io", true */ 'w', 'o', 'o', 'd', 'b', 'u', 'r', 'y', '.', 'i', 'o', '\0', /* "woodlandschurch.net", true */ 'w', 'o', 'o', 'd', 'l', 'a', 'n', 'd', 's', 'c', 'h', 'u', 'r', 'c', 'h', '.', 'n', 'e', 't', '\0', @@ -12661,6 +12637,7 @@ /* "worshapp.com", true */ 'w', 'o', 'r', 's', 'h', 'a', 'p', 'p', '.', 'c', 'o', 'm', '\0', /* "woutergeraedts.nl", true */ 'w', 'o', 'u', 't', 'e', 'r', 'g', 'e', 'r', 'a', 'e', 'd', 't', 's', '.', 'n', 'l', '\0', /* "woutervdb.com", true */ 'w', 'o', 'u', 't', 'e', 'r', 'v', 'd', 'b', '.', 'c', 'o', 'm', '\0', + /* "wow-foederation.de", true */ 'w', 'o', 'w', '-', 'f', 'o', 'e', 'd', 'e', 'r', 'a', 't', 'i', 'o', 'n', '.', 'd', 'e', '\0', /* "wowhelp.it", true */ 'w', 'o', 'w', 'h', 'e', 'l', 'p', '.', 'i', 't', '\0', /* "wowjs.co.uk", true */ 'w', 'o', 'w', 'j', 's', '.', 'c', 'o', '.', 'u', 'k', '\0', /* "wowjs.org", true */ 'w', 'o', 'w', 'j', 's', '.', 'o', 'r', 'g', '\0', @@ -12701,6 +12678,7 @@ /* "wunderkarten.de", true */ 'w', 'u', 'n', 'd', 'e', 'r', 'k', 'a', 'r', 't', 'e', 'n', '.', 'd', 'e', '\0', /* "wunderlist.com", true */ 'w', 'u', 'n', 'd', 'e', 'r', 'l', 'i', 's', 't', '.', 'c', 'o', 'm', '\0', /* "wundi.net", true */ 'w', 'u', 'n', 'd', 'i', '.', 'n', 'e', 't', '\0', + /* "wvg.myds.me", true */ 'w', 'v', 'g', '.', 'm', 'y', 'd', 's', '.', 'm', 'e', '\0', /* "wvr-law.de", false */ 'w', 'v', 'r', '-', 'l', 'a', 'w', '.', 'd', 'e', '\0', /* "ww2onlineshop.com", false */ 'w', 'w', '2', 'o', 'n', 'l', 'i', 'n', 'e', 's', 'h', 'o', 'p', '.', 'c', 'o', 'm', '\0', /* "www.aclu.org", false */ 'w', 'w', 'w', '.', 'a', 'c', 'l', 'u', '.', 'o', 'r', 'g', '\0', @@ -12783,7 +12761,6 @@ /* "xdd.io", true */ 'x', 'd', 'd', '.', 'i', 'o', '\0', /* "xdeftor.com", true */ 'x', 'd', 'e', 'f', 't', 'o', 'r', '.', 'c', 'o', 'm', '\0', /* "xecureit.com", true */ 'x', 'e', 'c', 'u', 'r', 'e', 'i', 't', '.', 'c', 'o', 'm', '\0', - /* "xendo.net", true */ 'x', 'e', 'n', 'd', 'o', '.', 'n', 'e', 't', '\0', /* "xenophile.name", true */ 'x', 'e', 'n', 'o', 'p', 'h', 'i', 'l', 'e', '.', 'n', 'a', 'm', 'e', '\0', /* "xerhost.de", false */ 'x', 'e', 'r', 'h', 'o', 's', 't', '.', 'd', 'e', '\0', /* "xetown.com", true */ 'x', 'e', 't', 'o', 'w', 'n', '.', 'c', 'o', 'm', '\0', @@ -12877,10 +12854,10 @@ /* "yacobo.com", true */ 'y', 'a', 'c', 'o', 'b', 'o', '.', 'c', 'o', 'm', '\0', /* "yafuoku.ru", true */ 'y', 'a', 'f', 'u', 'o', 'k', 'u', '.', 'r', 'u', '\0', /* "yagihiro.tech", true */ 'y', 'a', 'g', 'i', 'h', 'i', 'r', 'o', '.', 't', 'e', 'c', 'h', '\0', - /* "yahvehyireh.com", true */ 'y', 'a', 'h', 'v', 'e', 'h', 'y', 'i', 'r', 'e', 'h', '.', 'c', 'o', 'm', '\0', /* "yak.is", true */ 'y', 'a', 'k', '.', 'i', 's', '\0', /* "yakmade.com", true */ 'y', 'a', 'k', 'm', 'a', 'd', 'e', '.', 'c', 'o', 'm', '\0', /* "yakmoo.se", true */ 'y', 'a', 'k', 'm', 'o', 'o', '.', 's', 'e', '\0', + /* "yal.sh", true */ 'y', 'a', 'l', '.', 's', 'h', '\0', /* "yamadaya.tv", true */ 'y', 'a', 'm', 'a', 'd', 'a', 'y', 'a', '.', 't', 'v', '\0', /* "yameveo.com", false */ 'y', 'a', 'm', 'e', 'v', 'e', 'o', '.', 'c', 'o', 'm', '\0', /* "yanaduday.com", true */ 'y', 'a', 'n', 'a', 'd', 'u', 'd', 'a', 'y', '.', 'c', 'o', 'm', '\0', @@ -12891,6 +12868,7 @@ /* "yarcom.ru", true */ 'y', 'a', 'r', 'c', 'o', 'm', '.', 'r', 'u', '\0', /* "yarogneva.ru", true */ 'y', 'a', 'r', 'o', 'g', 'n', 'e', 'v', 'a', '.', 'r', 'u', '\0', /* "yatesun.com", true */ 'y', 'a', 't', 'e', 's', 'u', 'n', '.', 'c', 'o', 'm', '\0', + /* "yaucy.win", true */ 'y', 'a', 'u', 'c', 'y', '.', 'w', 'i', 'n', '\0', /* "yaup.tk", true */ 'y', 'a', 'u', 'p', '.', 't', 'k', '\0', /* "yawnbox.com", true */ 'y', 'a', 'w', 'n', 'b', 'o', 'x', '.', 'c', 'o', 'm', '\0', /* "yaxim.org", true */ 'y', 'a', 'x', 'i', 'm', '.', 'o', 'r', 'g', '\0', @@ -12972,7 +12950,6 @@ /* "yutabon.com", false */ 'y', 'u', 't', 'a', 'b', 'o', 'n', '.', 'c', 'o', 'm', '\0', /* "yutangyun.com", true */ 'y', 'u', 't', 'a', 'n', 'g', 'y', 'u', 'n', '.', 'c', 'o', 'm', '\0', /* "yuushou.com", true */ 'y', 'u', 'u', 's', 'h', 'o', 'u', '.', 'c', 'o', 'm', '\0', - /* "yux.io", true */ 'y', 'u', 'x', '.', 'i', 'o', '\0', /* "yuyu.io", true */ 'y', 'u', 'y', 'u', '.', 'i', 'o', '\0', /* "yvesx.com", true */ 'y', 'v', 'e', 's', 'x', '.', 'c', 'o', 'm', '\0', /* "yyyy.xyz", true */ 'y', 'y', 'y', 'y', '.', 'x', 'y', 'z', '\0', @@ -13014,8 +12991,9 @@ /* "zehdenick-bleibt-bunt.de", true */ 'z', 'e', 'h', 'd', 'e', 'n', 'i', 'c', 'k', '-', 'b', 'l', 'e', 'i', 'b', 't', '-', 'b', 'u', 'n', 't', '.', 'd', 'e', '\0', /* "zehntner.ch", true */ 'z', 'e', 'h', 'n', 't', 'n', 'e', 'r', '.', 'c', 'h', '\0', /* "zelfrijdendeautos.com", true */ 'z', 'e', 'l', 'f', 'r', 'i', 'j', 'd', 'e', 'n', 'd', 'e', 'a', 'u', 't', 'o', 's', '.', 'c', 'o', 'm', '\0', + /* "zellari.ru", true */ 'z', 'e', 'l', 'l', 'a', 'r', 'i', '.', 'r', 'u', '\0', /* "zemlova.cz", true */ 'z', 'e', 'm', 'l', 'o', 'v', 'a', '.', 'c', 'z', '\0', - /* "zenithmedia.ca", false */ 'z', 'e', 'n', 'i', 't', 'h', 'm', 'e', 'd', 'i', 'a', '.', 'c', 'a', '\0', + /* "zenithmedia.ca", true */ 'z', 'e', 'n', 'i', 't', 'h', 'm', 'e', 'd', 'i', 'a', '.', 'c', 'a', '\0', /* "zenk-security.com", true */ 'z', 'e', 'n', 'k', '-', 's', 'e', 'c', 'u', 'r', 'i', 't', 'y', '.', 'c', 'o', 'm', '\0', /* "zenlogic.com", true */ 'z', 'e', 'n', 'l', 'o', 'g', 'i', 'c', '.', 'c', 'o', 'm', '\0', /* "zeno-system.com", true */ 'z', 'e', 'n', 'o', '-', 's', 'y', 's', 't', 'e', 'm', '.', 'c', 'o', 'm', '\0', @@ -13202,2392 +13180,2393 @@ { 937, true }, { 943, true }, { 958, true }, - { 967, true }, - { 985, true }, - { 997, true }, - { 1006, true }, + { 966, true }, + { 975, true }, + { 993, true }, + { 1005, true }, { 1014, true }, { 1022, true }, - { 1033, true }, - { 1045, true }, + { 1030, true }, + { 1041, true }, { 1053, true }, - { 1063, true }, - { 1079, false }, - { 1092, true }, - { 1101, true }, - { 1115, true }, - { 1124, true }, - { 1145, true }, - { 1154, true }, - { 1164, true }, - { 1179, true }, - { 1196, true }, - { 1203, true }, - { 1216, true }, - { 1225, true }, - { 1237, false }, - { 1249, true }, + { 1061, true }, + { 1071, true }, + { 1087, false }, + { 1100, true }, + { 1109, true }, + { 1123, true }, + { 1132, true }, + { 1153, true }, + { 1162, true }, + { 1172, true }, + { 1187, true }, + { 1204, true }, + { 1211, true }, + { 1224, true }, + { 1233, true }, + { 1245, false }, { 1257, true }, - { 1268, true }, - { 1277, true }, - { 1286, false }, - { 1302, true }, - { 1315, true }, - { 1324, true }, - { 1343, true }, - { 1362, true }, - { 1374, true }, - { 1387, true }, - { 1403, true }, - { 1418, true }, - { 1431, true }, - { 1441, true }, - { 1455, true }, - { 1471, true }, - { 1485, true }, - { 1500, true }, + { 1265, true }, + { 1276, true }, + { 1285, true }, + { 1294, false }, + { 1310, true }, + { 1323, true }, + { 1332, true }, + { 1351, true }, + { 1370, true }, + { 1382, true }, + { 1395, true }, + { 1411, true }, + { 1426, true }, + { 1439, true }, + { 1449, true }, + { 1463, true }, + { 1479, true }, + { 1493, true }, { 1508, true }, - { 1515, true }, - { 1522, true }, - { 1534, true }, - { 1545, true }, - { 1554, true }, - { 1565, true }, - { 1580, true }, - { 1588, false }, - { 1601, true }, + { 1516, true }, + { 1523, true }, + { 1530, true }, + { 1542, true }, + { 1553, true }, + { 1562, true }, + { 1573, true }, + { 1588, true }, + { 1596, false }, { 1609, true }, - { 1621, true }, - { 1636, true }, - { 1655, true }, - { 1662, false }, - { 1681, true }, - { 1691, true }, - { 1697, true }, - { 1706, true }, - { 1719, false }, - { 1726, true }, - { 1738, true }, - { 1747, true }, - { 1760, true }, - { 1770, true }, - { 1778, false }, - { 1785, true }, - { 1796, true }, - { 1808, true }, + { 1617, true }, + { 1629, true }, + { 1644, true }, + { 1663, true }, + { 1670, false }, + { 1689, true }, + { 1699, true }, + { 1705, true }, + { 1714, true }, + { 1727, false }, + { 1734, true }, + { 1746, true }, + { 1755, true }, + { 1768, true }, + { 1778, true }, + { 1786, false }, + { 1793, true }, + { 1804, true }, { 1816, true }, - { 1829, true }, - { 1836, true }, - { 1845, true }, - { 1857, true }, - { 1866, true }, - { 1887, true }, - { 1911, true }, - { 1922, true }, - { 1928, true }, - { 1941, true }, - { 1953, true }, - { 1965, true }, - { 1975, true }, - { 1992, true }, - { 1999, true }, - { 2008, true }, - { 2029, false }, - { 2042, true }, - { 2052, true }, - { 2063, true }, - { 2075, true }, - { 2084, true }, - { 2094, true }, - { 2105, true }, + { 1824, true }, + { 1837, true }, + { 1844, true }, + { 1853, true }, + { 1865, true }, + { 1874, true }, + { 1895, true }, + { 1919, true }, + { 1930, true }, + { 1936, true }, + { 1949, true }, + { 1961, true }, + { 1973, true }, + { 1983, true }, + { 2000, true }, + { 2007, true }, + { 2016, true }, + { 2037, false }, + { 2050, true }, + { 2060, true }, + { 2071, true }, + { 2083, true }, + { 2092, true }, + { 2102, true }, { 2113, true }, - { 2125, true }, - { 2135, true }, - { 2154, true }, - { 2165, true }, - { 2177, true }, - { 2189, true }, - { 2201, true }, - { 2212, true }, - { 2221, true }, - { 2234, true }, - { 2254, true }, - { 2269, true }, + { 2121, true }, + { 2133, true }, + { 2143, true }, + { 2162, true }, + { 2173, true }, + { 2185, true }, + { 2197, true }, + { 2209, true }, + { 2220, true }, + { 2229, true }, + { 2242, true }, + { 2262, true }, { 2277, true }, - { 2287, true }, - { 2304, true }, - { 2319, true }, - { 2326, false }, - { 2337, true }, - { 2352, false }, - { 2367, true }, - { 2386, true }, - { 2396, true }, - { 2407, true }, - { 2425, true }, - { 2439, true }, - { 2451, true }, - { 2467, true }, - { 2478, false }, - { 2494, false }, - { 2506, true }, - { 2519, true }, - { 2532, false }, - { 2540, true }, - { 2564, true }, - { 2579, true }, - { 2598, true }, - { 2611, true }, - { 2623, true }, + { 2292, true }, + { 2300, true }, + { 2310, true }, + { 2327, true }, + { 2342, true }, + { 2349, false }, + { 2360, true }, + { 2375, false }, + { 2390, true }, + { 2409, true }, + { 2419, true }, + { 2430, true }, + { 2448, true }, + { 2462, true }, + { 2474, true }, + { 2490, true }, + { 2501, false }, + { 2517, false }, + { 2529, true }, + { 2542, true }, + { 2555, false }, + { 2563, true }, + { 2587, true }, + { 2602, true }, + { 2621, true }, { 2634, true }, - { 2658, true }, - { 2671, true }, - { 2680, true }, - { 2697, true }, - { 2709, true }, - { 2728, true }, + { 2646, true }, + { 2657, true }, + { 2681, true }, + { 2694, true }, + { 2703, true }, + { 2720, true }, + { 2732, true }, { 2751, true }, - { 2767, true }, - { 2784, true }, - { 2804, true }, - { 2819, true }, - { 2840, true }, - { 2860, true }, - { 2872, true }, + { 2774, true }, + { 2790, true }, + { 2807, true }, + { 2827, true }, + { 2842, true }, + { 2863, true }, { 2883, true }, { 2895, true }, - { 2916, true }, - { 2928, true }, - { 2945, true }, - { 2958, true }, - { 2974, true }, - { 2986, true }, - { 2999, false }, - { 3008, true }, - { 3023, true }, - { 3040, true }, - { 3054, true }, - { 3070, true }, - { 3081, true }, + { 2906, true }, + { 2918, true }, + { 2939, true }, + { 2951, true }, + { 2968, true }, + { 2981, true }, + { 2997, true }, + { 3009, true }, + { 3022, false }, + { 3031, true }, + { 3046, true }, + { 3063, true }, + { 3077, true }, { 3093, true }, - { 3114, true }, - { 3131, false }, - { 3141, true }, - { 3156, true }, - { 3170, false }, - { 3183, true }, - { 3192, true }, + { 3104, true }, + { 3116, true }, + { 3137, true }, + { 3154, false }, + { 3164, true }, + { 3179, true }, + { 3193, false }, { 3206, true }, - { 3218, true }, - { 3233, true }, - { 3246, true }, - { 3258, true }, - { 3270, true }, - { 3282, true }, - { 3294, true }, - { 3306, true }, + { 3215, true }, + { 3229, true }, + { 3241, true }, + { 3256, true }, + { 3269, true }, + { 3281, true }, + { 3293, true }, + { 3305, true }, { 3317, true }, - { 3331, true }, - { 3347, true }, - { 3360, true }, - { 3377, true }, - { 3392, true }, - { 3407, true }, - { 3425, true }, - { 3434, true }, - { 3447, true }, - { 3468, true }, - { 3477, true }, - { 3487, true }, - { 3512, true }, - { 3523, true }, - { 3542, true }, - { 3554, true }, - { 3573, true }, - { 3592, true }, - { 3611, true }, - { 3630, true }, - { 3645, true }, - { 3656, true }, - { 3669, true }, - { 3681, true }, - { 3694, true }, - { 3708, true }, - { 3719, true }, - { 3728, true }, + { 3329, true }, + { 3340, true }, + { 3354, true }, + { 3370, true }, + { 3383, true }, + { 3400, true }, + { 3415, true }, + { 3430, true }, + { 3448, true }, + { 3457, true }, + { 3470, true }, + { 3491, true }, + { 3500, true }, + { 3510, true }, + { 3535, true }, + { 3546, true }, + { 3565, true }, + { 3577, true }, + { 3596, true }, + { 3615, true }, + { 3634, true }, + { 3653, true }, + { 3668, true }, + { 3679, true }, + { 3692, true }, + { 3704, true }, + { 3717, true }, + { 3731, true }, { 3742, true }, - { 3754, true }, - { 3781, true }, - { 3807, true }, - { 3820, true }, - { 3831, true }, - { 3855, true }, - { 3872, true }, - { 3900, true }, - { 3916, true }, - { 3925, true }, - { 3935, true }, - { 3949, true }, - { 3959, true }, - { 3973, false }, - { 3994, true }, - { 4012, true }, - { 4020, true }, - { 4029, true }, - { 4048, true }, - { 4067, true }, - { 4080, true }, - { 4091, true }, - { 4111, true }, - { 4129, false }, - { 4148, true }, - { 4162, true }, - { 4172, true }, - { 4193, true }, - { 4209, true }, - { 4219, true }, + { 3751, true }, + { 3765, true }, + { 3777, true }, + { 3804, true }, + { 3830, true }, + { 3843, true }, + { 3854, true }, + { 3878, true }, + { 3895, true }, + { 3923, true }, + { 3939, true }, + { 3948, true }, + { 3958, true }, + { 3972, true }, + { 3982, true }, + { 3996, false }, + { 4017, true }, + { 4035, true }, + { 4043, true }, + { 4052, true }, + { 4071, true }, + { 4090, true }, + { 4103, true }, + { 4114, true }, + { 4134, true }, + { 4152, false }, + { 4171, true }, + { 4185, true }, + { 4206, true }, + { 4222, true }, { 4232, true }, { 4245, true }, - { 4259, true }, - { 4273, true }, - { 4283, true }, - { 4293, true }, - { 4303, true }, - { 4313, true }, - { 4323, true }, - { 4333, true }, - { 4350, false }, - { 4358, true }, - { 4377, true }, - { 4388, true }, - { 4399, true }, - { 4408, true }, - { 4428, true }, - { 4439, true }, + { 4258, true }, + { 4272, true }, + { 4286, true }, + { 4296, true }, + { 4306, true }, + { 4316, true }, + { 4326, true }, + { 4336, true }, + { 4346, true }, + { 4363, false }, + { 4371, true }, + { 4382, true }, + { 4401, true }, + { 4412, true }, + { 4423, true }, + { 4432, true }, + { 4452, true }, { 4463, true }, - { 4477, true }, - { 4493, true }, - { 4505, true }, - { 4521, true }, - { 4532, true }, - { 4546, true }, - { 4562, true }, + { 4487, true }, + { 4501, true }, + { 4517, true }, + { 4529, true }, + { 4545, true }, + { 4556, true }, { 4570, true }, - { 4587, false }, - { 4611, true }, - { 4628, true }, - { 4636, false }, + { 4586, true }, + { 4594, true }, + { 4611, false }, + { 4635, true }, { 4652, true }, - { 4660, true }, - { 4674, true }, - { 4686, false }, - { 4699, true }, - { 4711, true }, + { 4660, false }, + { 4676, true }, + { 4684, true }, + { 4698, true }, + { 4710, false }, { 4723, true }, { 4735, true }, - { 4745, true }, - { 4753, true }, - { 4767, true }, - { 4780, true }, - { 4792, true }, - { 4811, true }, - { 4830, true }, - { 4863, true }, - { 4873, true }, - { 4880, true }, + { 4747, true }, + { 4759, true }, + { 4769, true }, + { 4777, true }, + { 4791, true }, + { 4804, true }, + { 4816, true }, + { 4835, true }, + { 4854, true }, + { 4887, true }, { 4897, true }, - { 4912, true }, + { 4904, true }, { 4921, true }, - { 4928, true }, - { 4942, true }, - { 4950, true }, - { 4961, true }, - { 4976, true }, - { 4991, true }, - { 5001, true }, - { 5012, true }, - { 5027, true }, - { 5039, true }, - { 5050, true }, - { 5070, true }, - { 5081, true }, + { 4936, true }, + { 4945, true }, + { 4952, true }, + { 4966, true }, + { 4974, true }, + { 4985, true }, + { 5000, true }, + { 5015, true }, + { 5025, true }, + { 5036, true }, + { 5051, true }, + { 5063, true }, + { 5074, true }, { 5094, true }, { 5105, true }, - { 5116, true }, + { 5118, true }, { 5129, true }, - { 5147, true }, - { 5159, true }, - { 5168, true }, - { 5182, true }, - { 5193, true }, - { 5210, true }, - { 5221, true }, - { 5229, true }, - { 5238, false }, - { 5264, true }, - { 5275, true }, - { 5285, false }, - { 5302, true }, - { 5312, true }, + { 5140, true }, + { 5153, true }, + { 5171, true }, + { 5183, true }, + { 5192, true }, + { 5206, true }, + { 5217, true }, + { 5234, true }, + { 5245, true }, + { 5253, true }, + { 5262, false }, + { 5288, true }, + { 5299, true }, + { 5309, false }, { 5326, true }, - { 5338, true }, - { 5347, true }, - { 5364, true }, + { 5336, true }, + { 5350, true }, + { 5362, true }, + { 5371, true }, { 5388, true }, - { 5404, true }, - { 5424, true }, - { 5449, true }, - { 5474, true }, - { 5499, true }, - { 5511, true }, + { 5412, true }, + { 5428, true }, + { 5448, true }, + { 5473, true }, + { 5498, true }, { 5523, true }, - { 5532, true }, - { 5559, true }, - { 5572, false }, - { 5581, true }, - { 5597, true }, - { 5613, true }, - { 5625, true }, - { 5639, true }, - { 5659, true }, - { 5674, true }, - { 5695, true }, - { 5707, true }, - { 5717, true }, - { 5729, true }, + { 5535, true }, + { 5547, true }, + { 5556, true }, + { 5583, true }, + { 5596, false }, + { 5605, true }, + { 5621, true }, + { 5637, true }, + { 5649, true }, + { 5663, true }, + { 5683, true }, + { 5698, true }, + { 5719, true }, + { 5731, true }, { 5741, true }, - { 5750, true }, - { 5762, true }, - { 5781, true }, - { 5794, true }, + { 5753, true }, + { 5765, true }, + { 5774, true }, + { 5786, true }, { 5805, true }, - { 5814, true }, - { 5825, true }, - { 5839, true }, - { 5855, true }, - { 5875, true }, - { 5896, true }, - { 5910, true }, - { 5923, true }, - { 5933, true }, - { 5948, true }, - { 5958, true }, - { 5973, true }, - { 5987, true }, - { 6002, true }, - { 6012, true }, + { 5818, true }, + { 5829, true }, + { 5838, true }, + { 5849, true }, + { 5863, true }, + { 5879, true }, + { 5899, true }, + { 5920, true }, + { 5934, true }, + { 5947, true }, + { 5957, true }, + { 5972, true }, + { 5982, true }, + { 5997, true }, + { 6011, true }, { 6026, true }, - { 6043, true }, - { 6058, true }, - { 6072, true }, - { 6086, true }, - { 6102, true }, - { 6114, true }, + { 6036, true }, + { 6050, true }, + { 6067, true }, + { 6082, true }, + { 6096, true }, + { 6110, true }, { 6126, true }, - { 6141, true }, - { 6155, true }, - { 6177, true }, - { 6198, false }, - { 6219, true }, - { 6232, true }, - { 6244, true }, - { 6257, true }, - { 6272, true }, - { 6283, true }, - { 6299, false }, - { 6306, true }, - { 6317, true }, - { 6329, true }, - { 6342, true }, - { 6362, true }, - { 6383, true }, - { 6396, true }, - { 6414, true }, - { 6431, true }, - { 6455, true }, - { 6474, true }, - { 6485, true }, - { 6499, true }, - { 6515, true }, - { 6534, true }, - { 6555, true }, - { 6575, true }, - { 6595, true }, - { 6608, false }, - { 6621, true }, - { 6633, true }, - { 6643, true }, - { 6656, true }, - { 6670, true }, - { 6686, true }, - { 6700, true }, - { 6716, true }, - { 6728, true }, - { 6742, true }, - { 6755, true }, - { 6769, true }, - { 6777, true }, - { 6792, true }, - { 6811, true }, - { 6823, true }, - { 6837, true }, - { 6851, true }, - { 6863, true }, - { 6874, true }, - { 6885, true }, - { 6899, true }, - { 6907, true }, - { 6918, true }, - { 6926, true }, - { 6934, true }, - { 6942, true }, - { 6950, true }, - { 6963, true }, - { 6970, true }, + { 6138, true }, + { 6150, true }, + { 6165, true }, + { 6179, true }, + { 6201, true }, + { 6222, true }, + { 6235, true }, + { 6247, true }, + { 6260, true }, + { 6275, true }, + { 6286, true }, + { 6302, false }, + { 6309, true }, + { 6320, true }, + { 6332, true }, + { 6345, true }, + { 6365, true }, + { 6386, true }, + { 6399, true }, + { 6417, true }, + { 6434, true }, + { 6458, true }, + { 6477, true }, + { 6488, true }, + { 6502, true }, + { 6518, true }, + { 6537, true }, + { 6558, true }, + { 6578, true }, + { 6598, true }, + { 6611, false }, + { 6624, true }, + { 6636, true }, + { 6646, true }, + { 6659, true }, + { 6673, true }, + { 6689, true }, + { 6703, true }, + { 6719, true }, + { 6731, true }, + { 6745, true }, + { 6758, true }, + { 6772, true }, + { 6780, true }, + { 6795, true }, + { 6809, true }, + { 6828, true }, + { 6840, true }, + { 6854, true }, + { 6868, true }, + { 6880, true }, + { 6891, true }, + { 6902, true }, + { 6916, true }, + { 6924, true }, + { 6935, true }, + { 6943, true }, + { 6951, true }, + { 6959, true }, + { 6967, true }, { 6980, true }, - { 6993, true }, - { 7005, true }, - { 7018, true }, - { 7038, true }, - { 7050, true }, - { 7061, true }, - { 7079, true }, - { 7088, true }, - { 7100, true }, - { 7114, true }, - { 7127, true }, - { 7136, true }, - { 7152, true }, - { 7180, true }, - { 7199, true }, - { 7214, true }, - { 7234, true }, - { 7246, true }, - { 7257, true }, - { 7268, true }, - { 7288, true }, - { 7306, true }, - { 7316, false }, - { 7327, true }, - { 7337, true }, - { 7348, true }, + { 6987, true }, + { 6997, true }, + { 7010, true }, + { 7022, true }, + { 7035, true }, + { 7055, true }, + { 7067, true }, + { 7078, true }, + { 7096, true }, + { 7109, true }, + { 7118, true }, + { 7130, true }, + { 7144, true }, + { 7157, true }, + { 7166, true }, + { 7182, true }, + { 7210, true }, + { 7229, true }, + { 7244, true }, + { 7264, true }, + { 7276, true }, + { 7287, true }, + { 7298, true }, + { 7318, true }, + { 7336, true }, + { 7346, false }, { 7357, true }, - { 7368, true }, + { 7367, true }, + { 7378, true }, { 7387, true }, { 7398, true }, - { 7416, true }, - { 7442, true }, - { 7452, true }, - { 7474, true }, - { 7488, true }, - { 7503, true }, - { 7517, true }, - { 7531, true }, - { 7546, true }, - { 7567, true }, - { 7577, true }, - { 7588, true }, - { 7609, true }, - { 7627, true }, - { 7640, true }, - { 7648, true }, - { 7662, true }, - { 7678, true }, - { 7696, true }, - { 7718, true }, - { 7733, true }, - { 7750, true }, - { 7766, true }, - { 7782, true }, - { 7799, true }, - { 7818, true }, - { 7833, true }, - { 7852, true }, - { 7869, true }, - { 7886, true }, - { 7904, true }, - { 7921, true }, - { 7936, true }, - { 7950, true }, - { 7967, true }, - { 7985, true }, - { 8000, true }, - { 8012, true }, - { 8025, true }, - { 8045, true }, - { 8056, true }, - { 8067, true }, - { 8078, true }, - { 8089, true }, - { 8100, true }, - { 8111, true }, - { 8123, true }, - { 8136, true }, - { 8155, true }, - { 8166, true }, - { 8179, true }, - { 8193, false }, - { 8206, false }, - { 8215, true }, - { 8232, true }, - { 8252, true }, - { 8263, true }, - { 8281, false }, - { 8314, true }, - { 8346, true }, - { 8373, true }, - { 8383, true }, - { 8401, true }, - { 8416, true }, - { 8428, true }, - { 8440, true }, - { 8460, true }, - { 8479, true }, - { 8499, true }, - { 8522, true }, - { 8546, true }, - { 8558, true }, - { 8569, true }, - { 8581, true }, - { 8593, true }, - { 8609, true }, - { 8626, true }, - { 8645, true }, - { 8659, true }, - { 8670, true }, - { 8703, true }, - { 8714, true }, - { 8727, true }, - { 8739, false }, - { 8763, true }, - { 8779, true }, - { 8795, true }, - { 8807, true }, - { 8823, true }, - { 8840, true }, - { 8858, true }, - { 8874, true }, - { 8895, true }, - { 8905, true }, - { 8922, true }, - { 8935, true }, - { 8948, true }, - { 8964, true }, - { 8975, true }, - { 8987, true }, - { 8998, true }, - { 9005, true }, - { 9013, true }, - { 9026, false }, - { 9034, true }, - { 9044, true }, - { 9058, false }, - { 9072, true }, - { 9088, true }, - { 9118, true }, - { 9141, true }, - { 9154, true }, - { 9173, true }, - { 9186, false }, - { 9205, true }, - { 9221, true }, - { 9237, false }, - { 9252, false }, - { 9265, true }, - { 9281, true }, - { 9292, true }, - { 9304, true }, - { 9323, true }, - { 9342, true }, - { 9357, true }, - { 9378, false }, - { 9393, true }, - { 9406, true }, - { 9416, true }, - { 9427, true }, - { 9438, true }, - { 9452, true }, - { 9468, true }, - { 9485, false }, - { 9502, true }, - { 9528, true }, - { 9541, true }, - { 9555, true }, - { 9574, true }, - { 9595, true }, - { 9607, true }, - { 9621, true }, - { 9645, true }, - { 9658, true }, - { 9671, true }, - { 9685, true }, - { 9696, true }, - { 9705, true }, - { 9718, true }, - { 9731, true }, - { 9743, false }, - { 9761, true }, - { 9784, true }, - { 9811, true }, - { 9830, true }, - { 9842, true }, - { 9855, true }, - { 9875, true }, - { 9886, true }, - { 9898, true }, - { 9912, true }, - { 9920, true }, - { 9937, true }, - { 9949, true }, - { 9967, true }, - { 9990, false }, - { 10006, true }, - { 10012, true }, - { 10024, true }, - { 10035, false }, - { 10052, true }, - { 10071, true }, - { 10083, true }, - { 10112, true }, - { 10128, true }, - { 10141, true }, - { 10155, true }, - { 10171, true }, - { 10184, true }, - { 10195, true }, - { 10207, true }, - { 10223, true }, - { 10237, true }, - { 10253, true }, - { 10267, true }, - { 10275, true }, - { 10289, true }, - { 10309, true }, - { 10321, true }, - { 10337, true }, - { 10351, false }, - { 10364, true }, - { 10379, true }, - { 10393, true }, - { 10402, true }, - { 10414, true }, - { 10432, true }, - { 10447, true }, - { 10457, true }, - { 10471, true }, - { 10497, true }, - { 10507, true }, - { 10521, true }, - { 10535, true }, - { 10553, true }, - { 10571, true }, - { 10581, true }, - { 10592, true }, - { 10608, true }, - { 10616, true }, - { 10624, true }, - { 10635, true }, - { 10645, true }, - { 10660, true }, - { 10679, true }, - { 10692, true }, - { 10707, true }, - { 10722, true }, - { 10742, true }, - { 10753, true }, - { 10765, true }, - { 10778, true }, - { 10798, false }, - { 10812, true }, - { 10825, true }, - { 10843, true }, - { 10857, true }, - { 10870, true }, - { 10884, true }, - { 10898, true }, - { 10910, true }, - { 10921, true }, - { 10932, true }, - { 10945, true }, - { 10960, true }, - { 10971, true }, - { 10982, true }, - { 10993, true }, - { 11003, true }, - { 11024, true }, - { 11035, true }, - { 11044, true }, - { 11051, true }, - { 11065, false }, - { 11078, true }, - { 11088, true }, - { 11094, true }, - { 11107, true }, - { 11120, true }, - { 11131, true }, - { 11143, true }, - { 11157, true }, - { 11167, true }, - { 11185, true }, - { 11195, true }, - { 11207, true }, - { 11221, true }, - { 11231, true }, - { 11247, true }, - { 11258, true }, - { 11275, true }, - { 11294, true }, - { 11308, true }, - { 11330, true }, - { 11356, true }, - { 11366, true }, - { 11384, true }, - { 11395, true }, - { 11405, true }, - { 11415, true }, - { 11425, true }, - { 11444, true }, - { 11464, true }, - { 11478, true }, - { 11485, true }, - { 11495, true }, - { 11513, true }, - { 11535, true }, - { 11548, true }, - { 11564, true }, - { 11572, true }, - { 11584, false }, - { 11604, true }, - { 11611, true }, - { 11627, true }, - { 11643, true }, - { 11658, true }, - { 11668, true }, - { 11686, true }, - { 11713, true }, - { 11730, true }, - { 11748, true }, - { 11756, true }, - { 11770, true }, - { 11781, true }, - { 11790, true }, - { 11817, true }, - { 11827, true }, - { 11843, true }, - { 11855, true }, - { 11870, true }, - { 11882, true }, - { 11897, true }, - { 11912, true }, - { 11924, true }, - { 11945, true }, - { 11962, true }, - { 11976, true }, - { 11988, true }, - { 11998, true }, - { 12008, true }, - { 12023, true }, - { 12038, true }, - { 12050, true }, - { 12058, true }, - { 12071, true }, - { 12089, true }, - { 12110, true }, - { 12124, true }, - { 12140, true }, - { 12150, true }, - { 12162, true }, - { 12175, true }, - { 12194, true }, - { 12220, true }, - { 12232, true }, - { 12248, true }, - { 12260, true }, - { 12279, true }, - { 12305, true }, - { 12318, true }, - { 12329, true }, - { 12340, true }, - { 12358, true }, - { 12388, true }, - { 12411, true }, - { 12424, false }, - { 12432, true }, - { 12444, true }, - { 12460, true }, - { 12475, true }, - { 12493, true }, - { 12503, true }, - { 12519, true }, - { 12548, true }, - { 12564, true }, - { 12580, true }, - { 12591, true }, - { 12603, true }, - { 12615, true }, - { 12638, true }, - { 12656, true }, - { 12674, true }, - { 12695, true }, - { 12720, true }, - { 12734, true }, - { 12747, true }, - { 12758, true }, - { 12784, true }, - { 12800, true }, - { 12810, true }, - { 12822, true }, - { 12839, true }, - { 12851, true }, + { 7417, true }, + { 7428, true }, + { 7446, true }, + { 7472, true }, + { 7482, true }, + { 7504, true }, + { 7518, true }, + { 7533, true }, + { 7547, true }, + { 7561, true }, + { 7576, true }, + { 7597, true }, + { 7608, true }, + { 7629, true }, + { 7647, true }, + { 7660, true }, + { 7668, true }, + { 7682, true }, + { 7698, true }, + { 7716, true }, + { 7738, true }, + { 7753, true }, + { 7770, true }, + { 7786, true }, + { 7802, true }, + { 7819, true }, + { 7838, true }, + { 7853, true }, + { 7872, true }, + { 7889, true }, + { 7907, true }, + { 7924, true }, + { 7939, true }, + { 7953, true }, + { 7970, true }, + { 7988, true }, + { 8003, true }, + { 8015, true }, + { 8028, true }, + { 8048, true }, + { 8059, true }, + { 8070, true }, + { 8081, true }, + { 8092, true }, + { 8103, true }, + { 8114, true }, + { 8126, true }, + { 8139, true }, + { 8158, true }, + { 8169, true }, + { 8182, true }, + { 8196, false }, + { 8209, false }, + { 8218, true }, + { 8235, true }, + { 8255, true }, + { 8266, true }, + { 8284, false }, + { 8317, true }, + { 8349, true }, + { 8376, true }, + { 8386, true }, + { 8404, true }, + { 8419, true }, + { 8431, true }, + { 8443, true }, + { 8463, true }, + { 8482, true }, + { 8502, true }, + { 8525, true }, + { 8549, true }, + { 8561, true }, + { 8572, true }, + { 8584, true }, + { 8596, true }, + { 8612, true }, + { 8629, true }, + { 8648, true }, + { 8662, true }, + { 8673, true }, + { 8706, true }, + { 8717, true }, + { 8730, true }, + { 8742, false }, + { 8766, true }, + { 8782, true }, + { 8798, true }, + { 8810, true }, + { 8826, true }, + { 8843, true }, + { 8861, true }, + { 8877, true }, + { 8898, true }, + { 8908, true }, + { 8925, true }, + { 8938, true }, + { 8951, true }, + { 8967, true }, + { 8978, true }, + { 8990, true }, + { 9001, true }, + { 9008, true }, + { 9016, true }, + { 9029, false }, + { 9037, true }, + { 9047, true }, + { 9061, false }, + { 9075, true }, + { 9091, true }, + { 9121, true }, + { 9144, true }, + { 9157, true }, + { 9176, true }, + { 9189, false }, + { 9208, true }, + { 9224, true }, + { 9240, false }, + { 9255, false }, + { 9268, true }, + { 9284, true }, + { 9295, true }, + { 9307, true }, + { 9326, true }, + { 9345, true }, + { 9360, true }, + { 9381, false }, + { 9396, true }, + { 9409, true }, + { 9419, true }, + { 9430, true }, + { 9441, true }, + { 9455, true }, + { 9471, true }, + { 9488, false }, + { 9505, true }, + { 9531, true }, + { 9544, true }, + { 9558, true }, + { 9577, true }, + { 9598, true }, + { 9610, true }, + { 9624, true }, + { 9648, true }, + { 9661, true }, + { 9674, true }, + { 9688, true }, + { 9699, true }, + { 9708, true }, + { 9721, true }, + { 9734, true }, + { 9746, false }, + { 9764, true }, + { 9787, true }, + { 9814, true }, + { 9833, true }, + { 9845, true }, + { 9858, true }, + { 9878, true }, + { 9889, true }, + { 9901, true }, + { 9915, true }, + { 9923, true }, + { 9940, true }, + { 9952, true }, + { 9970, true }, + { 9993, false }, + { 10009, true }, + { 10015, true }, + { 10027, true }, + { 10038, false }, + { 10055, true }, + { 10074, true }, + { 10086, true }, + { 10115, true }, + { 10131, true }, + { 10144, true }, + { 10158, true }, + { 10174, true }, + { 10187, true }, + { 10198, true }, + { 10210, true }, + { 10226, true }, + { 10240, true }, + { 10256, true }, + { 10270, true }, + { 10278, true }, + { 10292, true }, + { 10312, true }, + { 10324, true }, + { 10340, true }, + { 10354, false }, + { 10367, true }, + { 10382, true }, + { 10396, true }, + { 10405, true }, + { 10417, true }, + { 10435, true }, + { 10450, true }, + { 10460, true }, + { 10474, true }, + { 10500, true }, + { 10510, true }, + { 10524, true }, + { 10538, true }, + { 10556, true }, + { 10574, true }, + { 10584, true }, + { 10595, true }, + { 10611, true }, + { 10619, true }, + { 10627, true }, + { 10638, true }, + { 10648, true }, + { 10663, true }, + { 10682, true }, + { 10695, true }, + { 10710, false }, + { 10725, true }, + { 10745, true }, + { 10756, true }, + { 10768, true }, + { 10781, true }, + { 10801, false }, + { 10815, true }, + { 10828, true }, + { 10846, true }, + { 10860, true }, + { 10873, true }, + { 10887, true }, + { 10901, true }, + { 10913, true }, + { 10924, true }, + { 10935, true }, + { 10948, true }, + { 10963, true }, + { 10974, true }, + { 10985, true }, + { 10996, true }, + { 11006, true }, + { 11027, true }, + { 11038, true }, + { 11047, true }, + { 11054, true }, + { 11068, false }, + { 11081, true }, + { 11091, true }, + { 11097, true }, + { 11110, true }, + { 11123, true }, + { 11134, true }, + { 11146, true }, + { 11160, true }, + { 11170, true }, + { 11188, true }, + { 11198, true }, + { 11210, true }, + { 11224, true }, + { 11234, true }, + { 11250, true }, + { 11261, true }, + { 11278, true }, + { 11297, true }, + { 11311, true }, + { 11333, true }, + { 11359, true }, + { 11369, true }, + { 11387, true }, + { 11398, true }, + { 11408, true }, + { 11418, true }, + { 11428, true }, + { 11447, true }, + { 11467, true }, + { 11481, true }, + { 11488, true }, + { 11498, true }, + { 11516, true }, + { 11538, true }, + { 11551, true }, + { 11567, true }, + { 11575, true }, + { 11587, false }, + { 11607, true }, + { 11614, true }, + { 11630, true }, + { 11646, true }, + { 11661, true }, + { 11671, true }, + { 11689, true }, + { 11716, true }, + { 11733, true }, + { 11751, true }, + { 11759, true }, + { 11773, true }, + { 11784, true }, + { 11793, true }, + { 11820, true }, + { 11830, true }, + { 11846, true }, + { 11858, true }, + { 11873, true }, + { 11885, true }, + { 11900, true }, + { 11915, true }, + { 11927, true }, + { 11948, true }, + { 11965, true }, + { 11979, true }, + { 11991, true }, + { 12001, true }, + { 12011, true }, + { 12026, true }, + { 12041, true }, + { 12053, true }, + { 12061, true }, + { 12074, true }, + { 12092, true }, + { 12113, true }, + { 12127, true }, + { 12143, true }, + { 12153, true }, + { 12165, true }, + { 12178, true }, + { 12197, true }, + { 12223, true }, + { 12235, true }, + { 12251, true }, + { 12263, true }, + { 12282, true }, + { 12308, true }, + { 12321, true }, + { 12332, true }, + { 12350, true }, + { 12380, true }, + { 12403, true }, + { 12416, false }, + { 12424, true }, + { 12436, true }, + { 12452, true }, + { 12467, true }, + { 12485, true }, + { 12495, true }, + { 12511, true }, + { 12540, true }, + { 12556, true }, + { 12572, true }, + { 12583, true }, + { 12595, true }, + { 12607, true }, + { 12630, true }, + { 12648, true }, + { 12666, true }, + { 12687, true }, + { 12712, true }, + { 12726, true }, + { 12739, true }, + { 12750, true }, + { 12776, true }, + { 12792, true }, + { 12802, true }, + { 12814, true }, + { 12831, true }, + { 12843, true }, + { 12856, true }, { 12864, true }, - { 12872, true }, - { 12883, true }, - { 12894, true }, - { 12912, true }, - { 12927, true }, - { 12945, true }, - { 12954, true }, - { 12965, true }, - { 12979, true }, + { 12875, true }, + { 12886, true }, + { 12904, true }, + { 12919, true }, + { 12937, true }, + { 12946, true }, + { 12957, true }, + { 12971, true }, + { 12982, true }, { 12990, true }, - { 12998, true }, - { 13008, true }, + { 13000, true }, + { 13011, true }, { 13019, true }, - { 13027, true }, - { 13037, true }, + { 13029, true }, + { 13044, true }, { 13052, true }, - { 13060, true }, - { 13085, true }, - { 13101, true }, + { 13077, true }, + { 13093, true }, + { 13100, true }, { 13108, true }, - { 13116, true }, - { 13125, false }, - { 13134, true }, - { 13150, true }, - { 13163, true }, - { 13172, true }, - { 13181, true }, - { 13191, true }, - { 13203, true }, - { 13221, false }, - { 13237, true }, - { 13249, true }, - { 13259, true }, - { 13269, true }, - { 13281, true }, - { 13294, true }, - { 13307, true }, - { 13317, true }, - { 13327, true }, - { 13337, true }, - { 13349, false }, - { 13361, true }, - { 13377, true }, - { 13388, false }, + { 13117, false }, + { 13126, true }, + { 13142, true }, + { 13155, true }, + { 13164, true }, + { 13173, true }, + { 13183, true }, + { 13195, true }, + { 13213, false }, + { 13229, true }, + { 13241, true }, + { 13251, true }, + { 13261, true }, + { 13273, true }, + { 13286, true }, + { 13299, true }, + { 13309, true }, + { 13319, true }, + { 13329, true }, + { 13341, false }, + { 13353, true }, + { 13369, true }, + { 13380, false }, + { 13390, true }, { 13398, true }, - { 13406, true }, - { 13415, true }, - { 13429, true }, - { 13444, true }, - { 13458, true }, - { 13469, true }, - { 13493, true }, - { 13506, true }, - { 13518, true }, - { 13535, true }, - { 13546, true }, - { 13566, true }, - { 13584, true }, - { 13599, true }, - { 13620, true }, - { 13644, true }, - { 13654, true }, - { 13664, true }, - { 13674, true }, - { 13685, true }, - { 13710, true }, - { 13739, true }, - { 13752, true }, - { 13771, true }, - { 13783, true }, + { 13407, true }, + { 13421, true }, + { 13436, true }, + { 13450, true }, + { 13461, true }, + { 13485, true }, + { 13498, true }, + { 13510, true }, + { 13527, true }, + { 13538, true }, + { 13558, true }, + { 13576, true }, + { 13591, true }, + { 13612, true }, + { 13636, true }, + { 13646, true }, + { 13656, true }, + { 13666, true }, + { 13677, true }, + { 13702, true }, + { 13731, true }, + { 13744, true }, + { 13763, true }, + { 13775, true }, + { 13785, true }, { 13793, true }, - { 13801, true }, - { 13810, true }, - { 13824, true }, - { 13841, true }, - { 13853, true }, - { 13868, true }, - { 13875, true }, - { 13888, true }, + { 13802, true }, + { 13816, true }, + { 13833, true }, + { 13845, true }, + { 13860, true }, + { 13867, true }, + { 13880, true }, + { 13892, true }, { 13900, true }, - { 13908, true }, - { 13923, true }, - { 13932, true }, - { 13944, true }, - { 13955, true }, - { 13965, true }, - { 13980, true }, - { 13993, true }, - { 14003, true }, - { 14016, true }, - { 14030, true }, - { 14044, true }, - { 14056, true }, - { 14071, true }, - { 14087, true }, - { 14102, true }, - { 14116, true }, - { 14132, true }, - { 14144, true }, - { 14158, true }, - { 14170, true }, - { 14182, true }, - { 14198, true }, - { 14213, false }, - { 14229, true }, - { 14247, true }, - { 14264, true }, - { 14282, true }, - { 14293, true }, - { 14306, true }, - { 14323, false }, - { 14339, true }, - { 14355, true }, - { 14375, true }, - { 14390, true }, + { 13915, true }, + { 13924, true }, + { 13936, true }, + { 13947, true }, + { 13957, true }, + { 13972, true }, + { 13985, true }, + { 13995, true }, + { 14008, true }, + { 14022, true }, + { 14036, true }, + { 14048, true }, + { 14063, true }, + { 14079, true }, + { 14094, true }, + { 14108, true }, + { 14124, true }, + { 14136, true }, + { 14150, true }, + { 14162, true }, + { 14174, true }, + { 14190, false }, + { 14206, true }, + { 14224, true }, + { 14241, true }, + { 14259, true }, + { 14270, true }, + { 14283, true }, + { 14300, false }, + { 14316, true }, + { 14332, true }, + { 14352, true }, + { 14367, true }, + { 14381, true }, + { 14392, true }, { 14404, true }, - { 14415, true }, - { 14427, true }, - { 14440, true }, - { 14453, true }, - { 14471, true }, - { 14489, true }, - { 14507, true }, - { 14524, true }, - { 14534, true }, - { 14543, true }, - { 14558, true }, - { 14569, false }, - { 14579, true }, - { 14590, true }, + { 14417, true }, + { 14430, true }, + { 14448, true }, + { 14466, true }, + { 14484, true }, + { 14501, true }, + { 14511, true }, + { 14520, true }, + { 14535, true }, + { 14546, false }, + { 14556, true }, + { 14567, true }, + { 14581, true }, + { 14594, true }, { 14604, true }, { 14617, true }, - { 14627, true }, - { 14640, true }, - { 14654, true }, - { 14665, true }, - { 14675, true }, - { 14693, true }, - { 14702, true }, - { 14714, true }, - { 14731, true }, - { 14751, true }, - { 14770, true }, - { 14785, true }, - { 14803, true }, - { 14818, true }, - { 14829, true }, - { 14843, true }, - { 14854, true }, - { 14865, true }, - { 14876, true }, - { 14903, true }, - { 14913, true }, - { 14925, true }, - { 14937, true }, - { 14946, true }, - { 14955, true }, - { 14964, true }, - { 14979, true }, - { 14990, true }, - { 14999, true }, - { 15011, true }, - { 15020, true }, - { 15030, true }, - { 15041, true }, - { 15051, true }, - { 15063, true }, - { 15077, true }, - { 15087, true }, - { 15097, true }, - { 15107, false }, - { 15118, true }, - { 15136, true }, - { 15146, true }, - { 15165, true }, - { 15177, true }, - { 15198, true }, - { 15211, true }, - { 15225, true }, - { 15238, false }, - { 15252, false }, - { 15267, true }, - { 15279, true }, - { 15293, true }, - { 15311, true }, - { 15324, true }, - { 15333, true }, + { 14631, true }, + { 14642, true }, + { 14652, true }, + { 14670, true }, + { 14679, true }, + { 14691, true }, + { 14708, true }, + { 14728, true }, + { 14747, true }, + { 14762, true }, + { 14780, true }, + { 14795, true }, + { 14806, true }, + { 14820, true }, + { 14831, true }, + { 14842, true }, + { 14853, true }, + { 14880, true }, + { 14890, true }, + { 14902, true }, + { 14914, true }, + { 14923, true }, + { 14932, true }, + { 14941, true }, + { 14956, true }, + { 14967, true }, + { 14976, true }, + { 14988, true }, + { 14997, true }, + { 15007, true }, + { 15018, true }, + { 15028, true }, + { 15040, true }, + { 15054, true }, + { 15064, true }, + { 15074, true }, + { 15084, false }, + { 15095, true }, + { 15113, true }, + { 15123, true }, + { 15142, true }, + { 15154, true }, + { 15175, true }, + { 15188, true }, + { 15202, true }, + { 15215, false }, + { 15229, false }, + { 15244, true }, + { 15256, true }, + { 15270, true }, + { 15288, true }, + { 15301, true }, + { 15310, true }, + { 15328, true }, + { 15339, true }, { 15351, true }, - { 15362, true }, - { 15374, true }, - { 15388, true }, - { 15401, true }, - { 15415, true }, - { 15428, true }, - { 15442, true }, - { 15458, true }, - { 15469, true }, - { 15484, true }, - { 15497, true }, - { 15510, true }, - { 15526, true }, - { 15538, true }, - { 15551, true }, - { 15563, true }, + { 15365, true }, + { 15378, true }, + { 15392, true }, + { 15405, true }, + { 15419, true }, + { 15435, true }, + { 15446, true }, + { 15461, true }, + { 15474, true }, + { 15487, true }, + { 15503, true }, + { 15515, true }, + { 15528, true }, + { 15540, true }, + { 15556, true }, + { 15569, true }, { 15579, true }, - { 15592, true }, - { 15602, true }, - { 15630, true }, - { 15645, true }, - { 15661, true }, - { 15672, true }, - { 15683, true }, - { 15693, true }, - { 15703, false }, - { 15717, true }, - { 15729, false }, - { 15748, true }, - { 15775, true }, - { 15796, true }, - { 15812, true }, - { 15823, true }, - { 15841, true }, - { 15856, true }, - { 15867, true }, - { 15882, false }, - { 15897, true }, - { 15907, true }, - { 15921, true }, - { 15943, true }, - { 15958, true }, - { 15973, true }, - { 15994, true }, - { 16004, true }, - { 16018, true }, - { 16033, true }, - { 16045, true }, - { 16063, true }, - { 16077, true }, - { 16096, true }, - { 16110, true }, + { 15607, true }, + { 15622, true }, + { 15638, true }, + { 15649, true }, + { 15660, true }, + { 15670, true }, + { 15680, false }, + { 15694, true }, + { 15706, false }, + { 15725, true }, + { 15752, true }, + { 15773, true }, + { 15789, true }, + { 15800, true }, + { 15818, true }, + { 15833, true }, + { 15844, true }, + { 15859, false }, + { 15874, true }, + { 15884, true }, + { 15898, true }, + { 15920, true }, + { 15935, true }, + { 15950, true }, + { 15971, true }, + { 15981, true }, + { 15995, true }, + { 16010, true }, + { 16022, true }, + { 16040, true }, + { 16054, true }, + { 16073, true }, + { 16087, true }, + { 16097, true }, + { 16107, true }, { 16120, true }, - { 16130, true }, - { 16143, true }, - { 16158, true }, - { 16172, true }, - { 16185, true }, - { 16198, true }, - { 16215, true }, - { 16231, true }, - { 16244, true }, - { 16261, true }, - { 16273, true }, - { 16291, true }, - { 16304, true }, - { 16324, true }, - { 16340, true }, - { 16356, true }, - { 16365, true }, - { 16373, true }, - { 16382, true }, - { 16391, true }, + { 16135, true }, + { 16149, true }, + { 16162, true }, + { 16175, true }, + { 16192, true }, + { 16208, true }, + { 16221, true }, + { 16238, true }, + { 16250, true }, + { 16268, true }, + { 16281, true }, + { 16301, true }, + { 16317, true }, + { 16333, true }, + { 16342, true }, + { 16350, true }, + { 16359, true }, + { 16368, true }, + { 16385, true }, + { 16398, true }, { 16408, true }, - { 16421, true }, - { 16431, true }, - { 16441, true }, - { 16451, true }, - { 16469, true }, - { 16493, true }, - { 16507, true }, - { 16522, true }, - { 16540, true }, + { 16418, true }, + { 16428, true }, + { 16446, true }, + { 16470, true }, + { 16484, true }, + { 16499, true }, + { 16517, true }, + { 16529, true }, { 16552, true }, - { 16575, true }, - { 16597, true }, - { 16623, true }, - { 16641, true }, - { 16663, true }, - { 16676, true }, - { 16688, true }, - { 16700, false }, - { 16716, true }, - { 16730, true }, - { 16745, true }, - { 16757, true }, - { 16779, true }, - { 16796, true }, - { 16811, true }, - { 16832, true }, - { 16846, true }, - { 16865, true }, - { 16882, true }, - { 16896, true }, - { 16917, true }, - { 16933, true }, - { 16946, true }, - { 16965, true }, - { 16982, true }, - { 17000, true }, - { 17018, true }, - { 17027, true }, - { 17043, true }, - { 17059, true }, - { 17078, true }, - { 17096, true }, - { 17112, true }, - { 17126, true }, + { 16574, true }, + { 16600, true }, + { 16618, true }, + { 16640, true }, + { 16653, true }, + { 16665, true }, + { 16677, false }, + { 16693, true }, + { 16707, true }, + { 16722, true }, + { 16734, true }, + { 16756, true }, + { 16773, true }, + { 16788, true }, + { 16809, true }, + { 16823, true }, + { 16842, true }, + { 16859, true }, + { 16873, true }, + { 16894, true }, + { 16910, true }, + { 16923, true }, + { 16942, true }, + { 16959, true }, + { 16977, true }, + { 16995, true }, + { 17004, true }, + { 17020, true }, + { 17036, true }, + { 17055, true }, + { 17073, true }, + { 17089, true }, + { 17103, true }, + { 17115, true }, + { 17128, true }, { 17138, true }, - { 17151, true }, - { 17161, true }, - { 17171, true }, - { 17185, true }, - { 17195, true }, - { 17206, true }, - { 17215, false }, - { 17224, true }, - { 17238, true }, - { 17252, true }, - { 17264, true }, + { 17148, true }, + { 17162, true }, + { 17172, true }, + { 17183, true }, + { 17192, false }, + { 17201, true }, + { 17215, true }, + { 17229, true }, + { 17241, true }, + { 17256, true }, + { 17266, true }, { 17279, true }, - { 17289, true }, + { 17290, true }, { 17302, true }, - { 17313, true }, - { 17325, true }, - { 17340, true }, - { 17356, true }, - { 17365, true }, - { 17380, true }, - { 17396, true }, - { 17411, true }, - { 17424, true }, - { 17437, true }, - { 17456, true }, - { 17466, true }, - { 17476, true }, - { 17488, true }, - { 17503, true }, - { 17518, true }, - { 17533, true }, - { 17549, true }, - { 17568, true }, - { 17577, true }, - { 17590, true }, - { 17605, false }, - { 17620, true }, - { 17635, true }, - { 17650, true }, - { 17660, true }, - { 17670, true }, - { 17685, true }, - { 17707, true }, - { 17722, true }, - { 17735, true }, - { 17762, true }, - { 17776, true }, - { 17788, true }, - { 17803, true }, - { 17813, true }, - { 17834, true }, - { 17856, true }, - { 17874, false }, - { 17893, true }, - { 17907, true }, - { 17919, true }, - { 17936, true }, - { 17951, true }, - { 17962, true }, - { 17978, true }, - { 17996, true }, - { 18008, true }, - { 18018, true }, - { 18030, true }, - { 18044, false }, - { 18057, true }, - { 18074, true }, - { 18087, true }, + { 17317, true }, + { 17333, true }, + { 17342, true }, + { 17357, true }, + { 17373, true }, + { 17388, true }, + { 17401, true }, + { 17414, true }, + { 17433, true }, + { 17443, true }, + { 17453, true }, + { 17465, true }, + { 17480, true }, + { 17495, true }, + { 17510, true }, + { 17526, true }, + { 17545, true }, + { 17554, true }, + { 17567, true }, + { 17582, false }, + { 17597, true }, + { 17612, true }, + { 17627, true }, + { 17637, true }, + { 17647, true }, + { 17662, true }, + { 17684, true }, + { 17699, true }, + { 17712, true }, + { 17739, true }, + { 17753, true }, + { 17765, true }, + { 17780, true }, + { 17790, true }, + { 17811, true }, + { 17833, true }, + { 17851, false }, + { 17870, true }, + { 17884, true }, + { 17896, true }, + { 17913, true }, + { 17928, true }, + { 17939, true }, + { 17955, true }, + { 17973, true }, + { 17985, true }, + { 17995, true }, + { 18007, true }, + { 18021, false }, + { 18034, true }, + { 18051, true }, + { 18064, true }, + { 18076, true }, { 18099, true }, - { 18122, true }, - { 18135, true }, - { 18143, false }, - { 18154, true }, - { 18172, true }, - { 18193, true }, - { 18207, true }, - { 18224, true }, - { 18235, true }, + { 18112, true }, + { 18120, false }, + { 18131, true }, + { 18149, true }, + { 18170, true }, + { 18184, true }, + { 18201, true }, + { 18212, true }, + { 18221, true }, + { 18233, true }, { 18244, true }, - { 18256, true }, - { 18267, true }, - { 18277, false }, - { 18291, true }, - { 18309, true }, - { 18322, true }, - { 18333, true }, + { 18254, false }, + { 18268, true }, + { 18286, true }, + { 18299, true }, + { 18310, true }, + { 18324, true }, + { 18336, true }, { 18347, true }, - { 18359, true }, - { 18370, true }, - { 18381, true }, + { 18358, true }, + { 18371, true }, + { 18383, true }, { 18394, true }, - { 18406, true }, - { 18417, true }, - { 18436, true }, - { 18452, true }, - { 18466, true }, - { 18485, true }, - { 18497, true }, - { 18512, true }, - { 18521, true }, - { 18536, true }, - { 18550, true }, - { 18563, true }, - { 18575, true }, - { 18587, true }, - { 18601, true }, - { 18612, true }, - { 18626, true }, - { 18637, true }, - { 18648, true }, - { 18658, true }, - { 18668, true }, - { 18679, true }, - { 18690, true }, - { 18701, true }, - { 18714, true }, - { 18728, true }, - { 18740, true }, - { 18754, true }, - { 18779, true }, - { 18791, true }, - { 18808, true }, - { 18819, true }, - { 18830, true }, - { 18849, true }, + { 18413, true }, + { 18429, true }, + { 18443, true }, + { 18462, true }, + { 18474, true }, + { 18489, true }, + { 18498, true }, + { 18513, true }, + { 18527, true }, + { 18540, true }, + { 18552, true }, + { 18564, true }, + { 18578, true }, + { 18589, true }, + { 18603, true }, + { 18614, true }, + { 18625, true }, + { 18635, true }, + { 18645, true }, + { 18656, true }, + { 18667, true }, + { 18678, true }, + { 18691, true }, + { 18705, true }, + { 18717, true }, + { 18731, true }, + { 18756, true }, + { 18768, true }, + { 18785, true }, + { 18796, true }, + { 18807, true }, + { 18826, true }, + { 18842, true }, + { 18853, true }, { 18865, true }, - { 18876, true }, - { 18888, true }, - { 18903, true }, - { 18922, true }, - { 18939, true }, - { 18947, true }, - { 18963, true }, - { 18977, true }, - { 18994, true }, - { 19011, true }, - { 19024, true }, - { 19037, true }, - { 19050, true }, - { 19063, true }, - { 19076, true }, - { 19089, true }, - { 19102, true }, - { 19115, true }, - { 19128, true }, - { 19141, true }, - { 19154, true }, - { 19167, true }, - { 19180, true }, - { 19193, true }, - { 19210, true }, - { 19222, true }, - { 19244, true }, + { 18880, true }, + { 18899, true }, + { 18916, true }, + { 18924, true }, + { 18940, true }, + { 18954, true }, + { 18971, true }, + { 18988, true }, + { 19001, true }, + { 19014, true }, + { 19027, true }, + { 19040, true }, + { 19053, true }, + { 19066, true }, + { 19079, true }, + { 19092, true }, + { 19105, true }, + { 19118, true }, + { 19131, true }, + { 19144, true }, + { 19157, true }, + { 19170, true }, + { 19187, true }, + { 19199, true }, + { 19221, true }, + { 19233, true }, { 19256, true }, - { 19279, true }, - { 19303, true }, - { 19321, false }, - { 19342, true }, - { 19355, true }, - { 19370, true }, - { 19386, true }, - { 19412, true }, - { 19422, true }, - { 19439, true }, - { 19454, true }, - { 19473, true }, - { 19490, true }, - { 19506, true }, - { 19518, true }, - { 19528, true }, - { 19538, true }, - { 19559, true }, - { 19581, true }, - { 19593, true }, - { 19604, true }, - { 19619, true }, - { 19630, true }, - { 19645, true }, - { 19660, true }, - { 19672, true }, - { 19691, true }, - { 19704, true }, - { 19718, true }, - { 19740, true }, - { 19759, true }, - { 19779, true }, - { 19787, true }, - { 19800, true }, - { 19814, true }, - { 19828, true }, - { 19839, true }, - { 19852, true }, - { 19868, true }, - { 19888, true }, - { 19902, true }, - { 19914, true }, - { 19931, false }, - { 19947, false }, - { 19967, true }, - { 19980, true }, - { 19996, true }, - { 20012, true }, - { 20025, true }, - { 20038, true }, - { 20049, true }, - { 20065, true }, - { 20079, true }, - { 20095, true }, - { 20106, true }, - { 20119, true }, - { 20134, true }, - { 20148, true }, - { 20160, true }, - { 20180, true }, - { 20192, true }, - { 20205, true }, - { 20218, true }, - { 20239, true }, - { 20259, true }, - { 20273, true }, - { 20288, true }, - { 20297, true }, - { 20308, true }, - { 20318, true }, - { 20328, true }, - { 20346, true }, - { 20371, true }, - { 20382, true }, - { 20404, true }, - { 20416, true }, - { 20429, true }, - { 20442, true }, - { 20450, true }, - { 20469, true }, - { 20479, true }, - { 20494, true }, - { 20511, true }, - { 20527, true }, - { 20539, true }, - { 20550, true }, - { 20564, true }, - { 20588, false }, - { 20602, true }, - { 20617, true }, - { 20632, true }, - { 20654, true }, - { 20665, true }, - { 20678, true }, - { 20698, true }, - { 20709, true }, + { 19280, true }, + { 19298, true }, + { 19317, false }, + { 19338, true }, + { 19351, true }, + { 19366, true }, + { 19382, true }, + { 19408, true }, + { 19418, true }, + { 19435, true }, + { 19450, true }, + { 19469, true }, + { 19486, true }, + { 19502, true }, + { 19514, true }, + { 19524, true }, + { 19534, true }, + { 19555, true }, + { 19577, true }, + { 19589, true }, + { 19600, true }, + { 19615, true }, + { 19626, true }, + { 19641, true }, + { 19656, true }, + { 19668, true }, + { 19687, true }, + { 19700, true }, + { 19714, true }, + { 19736, true }, + { 19755, true }, + { 19775, true }, + { 19783, true }, + { 19796, true }, + { 19810, true }, + { 19824, true }, + { 19835, true }, + { 19848, true }, + { 19864, true }, + { 19884, true }, + { 19898, true }, + { 19910, true }, + { 19927, false }, + { 19943, false }, + { 19963, true }, + { 19976, true }, + { 19992, true }, + { 20008, true }, + { 20021, true }, + { 20034, true }, + { 20045, true }, + { 20061, true }, + { 20075, true }, + { 20091, true }, + { 20102, true }, + { 20115, true }, + { 20130, true }, + { 20144, true }, + { 20156, true }, + { 20176, true }, + { 20188, true }, + { 20201, true }, + { 20214, true }, + { 20235, true }, + { 20255, true }, + { 20269, true }, + { 20284, true }, + { 20293, true }, + { 20304, true }, + { 20314, true }, + { 20324, true }, + { 20342, true }, + { 20367, true }, + { 20378, true }, + { 20400, true }, + { 20412, true }, + { 20425, true }, + { 20438, true }, + { 20446, true }, + { 20465, true }, + { 20475, true }, + { 20490, true }, + { 20507, true }, + { 20523, true }, + { 20535, true }, + { 20546, true }, + { 20560, true }, + { 20584, false }, + { 20598, true }, + { 20613, true }, + { 20636, true }, + { 20651, true }, + { 20673, true }, + { 20684, true }, + { 20697, true }, { 20717, true }, - { 20734, true }, + { 20728, true }, + { 20736, true }, { 20753, true }, - { 20767, true }, - { 20782, true }, - { 20797, true }, - { 20807, true }, + { 20772, true }, + { 20786, true }, + { 20801, true }, { 20816, true }, - { 20831, true }, - { 20845, true }, - { 20857, true }, - { 20883, true }, - { 20898, true }, - { 20913, true }, - { 20925, true }, - { 20943, true }, - { 20963, true }, - { 20979, true }, - { 20991, true }, - { 21008, true }, - { 21022, true }, - { 21034, true }, - { 21051, true }, - { 21060, true }, - { 21072, true }, - { 21094, true }, - { 21108, true }, - { 21124, true }, - { 21141, true }, - { 21153, false }, - { 21175, false }, - { 21200, false }, - { 21224, true }, - { 21236, true }, - { 21246, true }, - { 21259, true }, - { 21269, true }, - { 21279, true }, - { 21289, true }, - { 21299, true }, - { 21309, true }, - { 21319, true }, - { 21329, true }, - { 21343, true }, - { 21361, true }, - { 21376, true }, - { 21390, true }, - { 21402, true }, - { 21414, true }, - { 21425, true }, - { 21439, true }, - { 21454, true }, - { 21468, true }, - { 21482, false }, - { 21502, true }, + { 20826, true }, + { 20835, true }, + { 20850, true }, + { 20864, true }, + { 20876, true }, + { 20902, true }, + { 20917, true }, + { 20932, true }, + { 20944, true }, + { 20962, true }, + { 20982, true }, + { 20998, true }, + { 21010, true }, + { 21027, true }, + { 21041, true }, + { 21053, true }, + { 21070, true }, + { 21079, true }, + { 21091, true }, + { 21113, true }, + { 21127, true }, + { 21143, true }, + { 21160, true }, + { 21172, false }, + { 21194, false }, + { 21219, false }, + { 21243, true }, + { 21255, true }, + { 21265, true }, + { 21278, true }, + { 21288, true }, + { 21298, true }, + { 21308, true }, + { 21318, true }, + { 21328, true }, + { 21338, true }, + { 21348, true }, + { 21362, true }, + { 21380, true }, + { 21395, true }, + { 21409, true }, + { 21421, true }, + { 21433, true }, + { 21444, true }, + { 21458, true }, + { 21473, true }, + { 21487, true }, + { 21501, false }, { 21521, true }, - { 21536, true }, - { 21547, true }, - { 21558, true }, - { 21570, true }, - { 21583, false }, - { 21596, true }, - { 21612, true }, - { 21625, true }, - { 21637, true }, - { 21652, true }, - { 21662, true }, - { 21687, true }, - { 21703, true }, - { 21720, true }, - { 21733, true }, - { 21748, true }, - { 21768, true }, - { 21780, true }, - { 21796, true }, - { 21824, false }, - { 21836, true }, - { 21849, true }, - { 21858, true }, - { 21868, true }, - { 21877, true }, - { 21886, true }, - { 21893, false }, - { 21909, true }, - { 21923, true }, - { 21933, true }, - { 21953, true }, + { 21540, true }, + { 21555, true }, + { 21566, true }, + { 21577, true }, + { 21589, true }, + { 21602, false }, + { 21615, true }, + { 21631, true }, + { 21644, true }, + { 21656, true }, + { 21671, true }, + { 21681, true }, + { 21706, true }, + { 21722, true }, + { 21737, true }, + { 21757, true }, + { 21769, true }, + { 21785, true }, + { 21813, false }, + { 21825, true }, + { 21838, true }, + { 21847, true }, + { 21857, true }, + { 21866, true }, + { 21875, true }, + { 21882, false }, + { 21898, true }, + { 21912, true }, + { 21922, true }, + { 21942, true }, + { 21962, true }, { 21973, true }, - { 21984, true }, - { 21998, true }, - { 22013, true }, - { 22026, true }, - { 22041, true }, - { 22058, true }, - { 22066, true }, - { 22080, true }, - { 22092, true }, - { 22109, false }, - { 22130, false }, - { 22152, false }, - { 22171, false }, - { 22189, true }, - { 22205, true }, - { 22229, true }, + { 21987, true }, + { 22002, true }, + { 22015, true }, + { 22030, true }, + { 22047, true }, + { 22055, true }, + { 22069, true }, + { 22081, true }, + { 22098, false }, + { 22119, false }, + { 22141, false }, + { 22160, false }, + { 22178, true }, + { 22194, true }, + { 22218, true }, + { 22246, true }, { 22257, true }, - { 22268, true }, - { 22287, true }, - { 22310, true }, - { 22327, true }, - { 22341, true }, - { 22352, true }, - { 22370, true }, - { 22385, true }, - { 22398, true }, - { 22411, true }, - { 22426, true }, - { 22438, true }, - { 22453, true }, - { 22472, true }, - { 22490, true }, - { 22498, true }, - { 22506, true }, - { 22518, true }, - { 22536, true }, - { 22551, true }, - { 22568, false }, - { 22577, true }, - { 22587, true }, - { 22600, false }, - { 22614, true }, - { 22627, true }, - { 22643, false }, - { 22650, true }, - { 22660, true }, - { 22674, true }, - { 22689, true }, - { 22697, true }, - { 22707, true }, - { 22725, true }, - { 22738, true }, - { 22751, true }, - { 22760, true }, - { 22770, true }, + { 22272, true }, + { 22291, true }, + { 22314, true }, + { 22331, true }, + { 22345, true }, + { 22356, true }, + { 22374, true }, + { 22389, true }, + { 22402, true }, + { 22415, true }, + { 22430, true }, + { 22442, true }, + { 22457, true }, + { 22476, true }, + { 22494, true }, + { 22502, true }, + { 22510, true }, + { 22522, true }, + { 22540, true }, + { 22555, true }, + { 22570, true }, + { 22585, true }, + { 22602, false }, + { 22611, true }, + { 22621, true }, + { 22634, false }, + { 22648, true }, + { 22661, true }, + { 22677, false }, + { 22684, true }, + { 22694, true }, + { 22708, true }, + { 22723, true }, + { 22731, true }, + { 22741, true }, + { 22759, true }, + { 22772, true }, { 22785, true }, - { 22814, true }, - { 22831, true }, - { 22841, true }, - { 22855, true }, - { 22866, true }, - { 22880, true }, - { 22902, true }, - { 22927, true }, - { 22940, true }, - { 22953, true }, - { 22970, true }, - { 22988, true }, - { 23003, true }, - { 23013, true }, - { 23034, true }, - { 23044, false }, - { 23063, true }, - { 23075, true }, - { 23104, true }, - { 23125, true }, - { 23139, true }, - { 23165, true }, + { 22794, true }, + { 22804, true }, + { 22819, true }, + { 22848, true }, + { 22865, true }, + { 22875, true }, + { 22889, true }, + { 22900, true }, + { 22914, true }, + { 22936, true }, + { 22961, true }, + { 22974, true }, + { 22987, true }, + { 23004, true }, + { 23022, true }, + { 23037, true }, + { 23047, true }, + { 23068, true }, + { 23078, false }, + { 23097, true }, + { 23109, true }, + { 23138, true }, + { 23159, true }, { 23173, true }, - { 23186, true }, - { 23198, true }, - { 23214, true }, - { 23233, true }, - { 23246, true }, - { 23259, true }, - { 23278, true }, - { 23291, false }, - { 23301, true }, - { 23323, true }, - { 23337, true }, - { 23353, true }, - { 23368, true }, - { 23385, false }, - { 23393, true }, - { 23409, true }, - { 23429, true }, + { 23199, true }, + { 23207, true }, + { 23220, true }, + { 23232, true }, + { 23248, true }, + { 23267, true }, + { 23280, true }, + { 23293, true }, + { 23312, true }, + { 23325, false }, + { 23335, true }, + { 23357, true }, + { 23371, true }, + { 23387, true }, + { 23402, true }, + { 23419, false }, + { 23427, true }, { 23443, true }, - { 23458, true }, - { 23469, true }, - { 23482, true }, - { 23494, true }, - { 23506, true }, - { 23519, true }, - { 23532, false }, - { 23554, true }, - { 23578, true }, - { 23601, true }, - { 23619, true }, - { 23645, true }, - { 23672, true }, - { 23695, true }, - { 23711, true }, - { 23740, true }, - { 23752, true }, - { 23765, true }, + { 23463, true }, + { 23477, true }, + { 23492, true }, + { 23503, true }, + { 23516, true }, + { 23528, true }, + { 23540, true }, + { 23553, true }, + { 23566, false }, + { 23588, true }, + { 23612, true }, + { 23635, true }, + { 23653, true }, + { 23679, true }, + { 23706, true }, + { 23729, true }, + { 23745, true }, { 23774, true }, - { 23783, true }, - { 23800, true }, - { 23813, true }, - { 23822, true }, - { 23839, true }, - { 23848, true }, + { 23786, true }, + { 23799, true }, + { 23808, true }, + { 23817, true }, + { 23834, true }, + { 23847, true }, { 23856, true }, - { 23880, true }, + { 23873, true }, + { 23882, true }, { 23890, true }, - { 23899, true }, - { 23912, true }, + { 23914, true }, { 23924, true }, - { 23938, true }, - { 23952, true }, - { 23970, true }, - { 23985, true }, - { 23999, true }, - { 24011, true }, - { 24027, true }, - { 24040, true }, - { 24055, true }, - { 24067, true }, - { 24082, true }, - { 24096, true }, - { 24105, true }, - { 24114, true }, - { 24128, true }, - { 24137, true }, - { 24151, true }, - { 24160, true }, - { 24173, true }, - { 24183, true }, - { 24198, true }, - { 24213, true }, - { 24227, true }, - { 24242, true }, - { 24255, true }, - { 24274, true }, - { 24290, true }, - { 24304, true }, - { 24315, true }, - { 24329, true }, - { 24339, true }, - { 24351, true }, - { 24367, true }, - { 24381, true }, - { 24386, true }, - { 24394, true }, + { 23933, true }, + { 23946, true }, + { 23958, true }, + { 23972, true }, + { 23986, true }, + { 24004, true }, + { 24019, true }, + { 24033, true }, + { 24045, true }, + { 24061, true }, + { 24074, true }, + { 24089, true }, + { 24101, true }, + { 24116, true }, + { 24130, true }, + { 24139, true }, + { 24148, true }, + { 24162, true }, + { 24171, true }, + { 24185, true }, + { 24194, true }, + { 24207, true }, + { 24217, true }, + { 24232, true }, + { 24247, true }, + { 24261, true }, + { 24276, true }, + { 24289, true }, + { 24308, true }, + { 24324, true }, + { 24338, true }, + { 24349, true }, + { 24363, true }, + { 24373, true }, + { 24385, true }, { 24401, true }, - { 24410, true }, - { 24425, false }, - { 24445, true }, - { 24455, true }, - { 24468, true }, - { 24486, true }, - { 24499, true }, - { 24515, true }, - { 24527, true }, - { 24540, true }, - { 24551, true }, - { 24562, true }, - { 24580, true }, - { 24593, true }, - { 24606, true }, - { 24626, true }, - { 24642, true }, - { 24650, true }, - { 24661, false }, - { 24671, true }, - { 24683, true }, - { 24697, true }, - { 24716, true }, - { 24724, true }, - { 24743, true }, - { 24757, false }, - { 24773, true }, - { 24785, false }, - { 24800, true }, - { 24812, false }, - { 24820, false }, - { 24832, true }, - { 24844, true }, - { 24855, true }, - { 24869, true }, - { 24882, true }, - { 24894, true }, - { 24907, true }, - { 24927, true }, - { 24937, true }, - { 24956, true }, - { 24967, true }, - { 24979, true }, - { 25002, true }, - { 25025, true }, - { 25036, true }, + { 24415, true }, + { 24420, true }, + { 24428, true }, + { 24435, true }, + { 24444, true }, + { 24459, false }, + { 24479, true }, + { 24489, true }, + { 24502, true }, + { 24520, true }, + { 24533, true }, + { 24549, true }, + { 24561, true }, + { 24574, true }, + { 24585, true }, + { 24596, true }, + { 24614, true }, + { 24627, true }, + { 24640, true }, + { 24660, true }, + { 24676, true }, + { 24684, true }, + { 24695, false }, + { 24705, true }, + { 24717, true }, + { 24731, true }, + { 24750, true }, + { 24758, true }, + { 24777, true }, + { 24791, false }, + { 24807, true }, + { 24819, false }, + { 24834, true }, + { 24846, false }, + { 24858, true }, + { 24870, true }, + { 24881, true }, + { 24895, true }, + { 24908, true }, + { 24920, true }, + { 24933, true }, + { 24953, true }, + { 24963, true }, + { 24982, true }, + { 24993, true }, + { 25005, true }, + { 25028, true }, { 25051, true }, - { 25064, true }, - { 25080, true }, - { 25096, true }, - { 25114, true }, - { 25134, true }, - { 25148, true }, - { 25171, true }, - { 25190, true }, - { 25208, true }, - { 25225, true }, + { 25062, true }, + { 25077, true }, + { 25090, true }, + { 25106, true }, + { 25122, true }, + { 25140, true }, + { 25160, true }, + { 25174, true }, + { 25197, true }, + { 25216, true }, + { 25234, true }, { 25251, true }, - { 25270, true }, - { 25286, true }, - { 25300, true }, - { 25321, true }, - { 25337, true }, - { 25362, true }, - { 25376, true }, - { 25385, true }, - { 25397, true }, - { 25410, true }, + { 25277, true }, + { 25296, true }, + { 25312, true }, + { 25326, true }, + { 25347, true }, + { 25363, true }, + { 25388, true }, + { 25402, true }, + { 25411, true }, { 25423, true }, - { 25435, true }, - { 25448, true }, - { 25462, true }, - { 25472, true }, - { 25485, true }, - { 25493, true }, - { 25500, true }, - { 25512, true }, - { 25524, true }, - { 25539, true }, + { 25436, true }, + { 25449, true }, + { 25461, true }, + { 25474, true }, + { 25488, true }, + { 25498, true }, + { 25511, true }, + { 25519, true }, + { 25526, true }, + { 25538, true }, + { 25550, true }, { 25565, true }, - { 25587, true }, - { 25601, true }, + { 25591, true }, { 25613, true }, - { 25623, true }, - { 25636, true }, - { 25644, true }, - { 25658, true }, - { 25682, true }, - { 25696, true }, - { 25720, true }, - { 25740, true }, - { 25751, true }, - { 25760, true }, - { 25782, true }, - { 25805, true }, - { 25829, true }, - { 25852, false }, - { 25883, false }, - { 25898, true }, - { 25910, true }, - { 25930, true }, - { 25945, true }, - { 25961, true }, - { 25972, true }, - { 25984, true }, - { 26000, true }, - { 26011, true }, - { 26025, true }, - { 26035, true }, - { 26044, false }, - { 26057, true }, - { 26074, true }, - { 26086, true }, - { 26105, true }, - { 26122, true }, - { 26135, true }, - { 26155, true }, - { 26177, true }, - { 26190, true }, - { 26201, true }, - { 26212, true }, - { 26228, true }, - { 26243, true }, - { 26257, true }, - { 26273, true }, - { 26286, true }, + { 25627, true }, + { 25639, true }, + { 25649, true }, + { 25662, true }, + { 25670, true }, + { 25684, true }, + { 25708, true }, + { 25722, true }, + { 25746, true }, + { 25766, true }, + { 25777, true }, + { 25786, true }, + { 25808, true }, + { 25831, true }, + { 25855, true }, + { 25878, false }, + { 25909, false }, + { 25924, true }, + { 25936, true }, + { 25956, true }, + { 25971, true }, + { 25987, true }, + { 25998, true }, + { 26010, true }, + { 26026, true }, + { 26037, true }, + { 26051, true }, + { 26061, true }, + { 26070, false }, + { 26083, true }, + { 26100, true }, + { 26112, true }, + { 26131, true }, + { 26148, true }, + { 26161, true }, + { 26181, true }, + { 26203, true }, + { 26216, true }, + { 26227, true }, + { 26238, true }, + { 26254, true }, + { 26269, true }, + { 26283, true }, { 26299, true }, - { 26311, true }, - { 26324, true }, + { 26312, true }, + { 26325, true }, { 26337, true }, - { 26349, true }, - { 26362, true }, - { 26374, true }, - { 26393, true }, - { 26408, true }, - { 26424, true }, - { 26442, true }, - { 26453, true }, - { 26461, false }, - { 26484, true }, - { 26499, true }, - { 26512, true }, - { 26523, true }, - { 26535, false }, - { 26545, true }, - { 26561, true }, - { 26572, true }, - { 26581, true }, - { 26592, true }, - { 26602, true }, - { 26613, true }, - { 26625, true }, - { 26642, true }, - { 26658, true }, + { 26350, true }, + { 26363, true }, + { 26375, true }, + { 26388, true }, + { 26400, true }, + { 26419, true }, + { 26434, true }, + { 26450, true }, + { 26468, true }, + { 26479, true }, + { 26487, false }, + { 26510, true }, + { 26525, true }, + { 26538, true }, + { 26549, true }, + { 26561, false }, + { 26571, true }, + { 26587, true }, + { 26598, true }, + { 26607, true }, + { 26618, true }, + { 26628, true }, + { 26639, true }, + { 26651, true }, { 26668, true }, - { 26676, false }, { 26684, true }, - { 26699, true }, - { 26713, true }, - { 26727, true }, - { 26737, true }, - { 26745, true }, - { 26759, true }, - { 26775, true }, - { 26790, false }, - { 26803, true }, - { 26816, true }, - { 26834, true }, - { 26850, true }, - { 26861, true }, - { 26879, true }, - { 26901, false }, - { 26918, true }, - { 26933, true }, - { 26949, true }, - { 26965, true }, - { 26984, true }, - { 27001, true }, - { 27016, true }, - { 27031, true }, - { 27046, true }, - { 27067, true }, - { 27085, true }, - { 27097, true }, - { 27110, true }, + { 26694, true }, + { 26702, false }, + { 26710, true }, + { 26725, true }, + { 26739, true }, + { 26753, true }, + { 26763, true }, + { 26771, true }, + { 26785, true }, + { 26801, true }, + { 26816, false }, + { 26829, true }, + { 26842, true }, + { 26860, true }, + { 26876, true }, + { 26887, true }, + { 26905, true }, + { 26927, false }, + { 26944, true }, + { 26959, true }, + { 26975, true }, + { 26991, true }, + { 27010, true }, + { 27027, true }, + { 27042, true }, + { 27057, true }, + { 27072, true }, + { 27093, true }, + { 27111, true }, { 27123, true }, - { 27137, false }, - { 27153, true }, - { 27168, true }, - { 27182, true }, - { 27195, true }, - { 27206, true }, - { 27216, true }, - { 27233, true }, - { 27249, true }, - { 27265, true }, - { 27280, true }, - { 27292, true }, - { 27303, false }, - { 27311, true }, - { 27332, true }, - { 27340, true }, - { 27353, true }, - { 27361, true }, - { 27369, true }, - { 27387, true }, - { 27401, true }, - { 27415, true }, - { 27423, true }, - { 27437, true }, - { 27457, true }, - { 27465, true }, - { 27474, false }, - { 27494, true }, - { 27512, true }, - { 27523, true }, - { 27541, true }, - { 27559, true }, - { 27571, true }, - { 27583, true }, - { 27597, true }, - { 27610, true }, - { 27627, true }, - { 27640, true }, - { 27654, true }, - { 27667, true }, - { 27681, true }, - { 27691, true }, - { 27708, true }, - { 27728, true }, - { 27737, true }, - { 27754, true }, - { 27774, true }, - { 27792, true }, - { 27806, true }, - { 27824, true }, - { 27839, true }, - { 27852, true }, - { 27866, true }, - { 27881, true }, - { 27901, false }, - { 27911, true }, - { 27928, true }, - { 27938, true }, - { 27949, true }, - { 27964, true }, - { 27972, true }, - { 27993, true }, - { 28014, true }, - { 28035, false }, - { 28051, true }, - { 28064, true }, - { 28079, true }, - { 28091, false }, - { 28112, true }, - { 28132, true }, - { 28146, true }, - { 28164, true }, - { 28184, true }, - { 28197, true }, - { 28211, true }, - { 28227, true }, - { 28245, true }, - { 28256, true }, - { 28269, true }, - { 28281, true }, - { 28295, true }, - { 28310, true }, - { 28329, false }, - { 28351, true }, - { 28359, true }, - { 28374, true }, - { 28391, true }, - { 28405, true }, - { 28422, true }, - { 28440, true }, - { 28451, true }, - { 28475, true }, - { 28491, true }, - { 28507, true }, - { 28522, true }, + { 27136, true }, + { 27149, true }, + { 27163, false }, + { 27179, true }, + { 27194, true }, + { 27208, true }, + { 27221, true }, + { 27232, true }, + { 27242, true }, + { 27258, true }, + { 27274, true }, + { 27289, true }, + { 27301, true }, + { 27312, false }, + { 27320, true }, + { 27341, true }, + { 27349, true }, + { 27362, true }, + { 27370, true }, + { 27378, true }, + { 27396, true }, + { 27410, true }, + { 27424, true }, + { 27432, true }, + { 27446, true }, + { 27466, true }, + { 27474, true }, + { 27483, false }, + { 27503, true }, + { 27521, true }, + { 27532, true }, + { 27550, true }, + { 27568, true }, + { 27580, true }, + { 27594, true }, + { 27607, true }, + { 27624, true }, + { 27637, true }, + { 27651, true }, + { 27664, true }, + { 27678, true }, + { 27688, true }, + { 27705, true }, + { 27725, true }, + { 27734, true }, + { 27751, true }, + { 27771, true }, + { 27789, true }, + { 27803, true }, + { 27821, true }, + { 27836, true }, + { 27849, true }, + { 27863, true }, + { 27878, true }, + { 27898, false }, + { 27908, true }, + { 27925, true }, + { 27935, true }, + { 27946, true }, + { 27961, true }, + { 27969, true }, + { 27990, true }, + { 28011, true }, + { 28032, false }, + { 28048, true }, + { 28061, true }, + { 28076, true }, + { 28088, false }, + { 28109, true }, + { 28129, true }, + { 28143, true }, + { 28161, true }, + { 28181, true }, + { 28194, true }, + { 28208, true }, + { 28224, true }, + { 28242, true }, + { 28253, true }, + { 28266, true }, + { 28278, true }, + { 28292, true }, + { 28307, true }, + { 28326, true }, + { 28338, false }, + { 28360, true }, + { 28368, true }, + { 28383, true }, + { 28400, true }, + { 28414, true }, + { 28431, true }, + { 28449, true }, + { 28460, true }, + { 28484, true }, + { 28500, true }, + { 28516, true }, { 28531, true }, - { 28546, true }, - { 28559, false }, - { 28569, true }, - { 28588, true }, - { 28602, true }, - { 28622, true }, + { 28540, true }, + { 28555, true }, + { 28568, false }, + { 28578, true }, + { 28597, true }, + { 28611, true }, { 28631, true }, - { 28649, false }, - { 28671, true }, + { 28640, true }, + { 28658, false }, { 28680, true }, - { 28699, false }, - { 28715, false }, - { 28729, true }, - { 28745, true }, - { 28760, true }, - { 28778, true }, - { 28800, true }, - { 28818, true }, - { 28842, true }, - { 28859, true }, - { 28874, true }, - { 28891, false }, - { 28907, true }, - { 28921, true }, - { 28935, true }, - { 28954, true }, - { 28971, true }, - { 28986, true }, - { 29013, true }, - { 29035, true }, - { 29058, true }, - { 29078, true }, - { 29096, true }, - { 29118, true }, - { 29137, true }, - { 29157, true }, - { 29180, true }, - { 29197, true }, - { 29211, true }, - { 29248, false }, - { 29259, true }, - { 29277, true }, - { 29297, true }, - { 29320, true }, - { 29345, false }, - { 29376, true }, - { 29390, true }, + { 28689, true }, + { 28708, false }, + { 28724, false }, + { 28738, true }, + { 28754, true }, + { 28769, true }, + { 28787, true }, + { 28809, true }, + { 28827, true }, + { 28851, true }, + { 28868, true }, + { 28883, true }, + { 28900, false }, + { 28916, true }, + { 28930, true }, + { 28944, true }, + { 28963, true }, + { 28980, true }, + { 28995, true }, + { 29022, true }, + { 29044, true }, + { 29067, true }, + { 29087, true }, + { 29105, true }, + { 29127, true }, + { 29146, true }, + { 29166, true }, + { 29189, true }, + { 29206, true }, + { 29220, true }, + { 29257, false }, + { 29268, true }, + { 29286, true }, + { 29306, true }, + { 29329, true }, + { 29354, false }, + { 29385, true }, { 29399, true }, - { 29410, true }, - { 29422, true }, - { 29434, true }, + { 29408, true }, + { 29419, true }, + { 29431, true }, { 29443, true }, - { 29455, true }, - { 29472, true }, - { 29490, false }, - { 29498, true }, - { 29509, true }, - { 29528, true }, - { 29540, false }, - { 29558, true }, - { 29568, true }, - { 29581, true }, - { 29590, false }, - { 29603, true }, - { 29616, true }, - { 29633, true }, - { 29649, true }, - { 29660, true }, - { 29674, true }, - { 29686, true }, - { 29701, true }, - { 29709, true }, - { 29723, true }, - { 29735, true }, - { 29747, true }, - { 29759, true }, - { 29769, true }, - { 29780, true }, - { 29791, true }, - { 29805, true }, - { 29828, true }, - { 29844, true }, - { 29852, true }, - { 29867, true }, - { 29886, true }, - { 29902, true }, - { 29912, true }, - { 29931, true }, - { 29944, true }, - { 29952, true }, - { 29967, true }, - { 29979, true }, - { 29987, true }, - { 29993, true }, - { 30006, true }, + { 29452, true }, + { 29464, true }, + { 29481, true }, + { 29499, false }, + { 29507, true }, + { 29518, true }, + { 29537, true }, + { 29549, false }, + { 29567, true }, + { 29577, true }, + { 29590, true }, + { 29599, false }, + { 29612, true }, + { 29625, true }, + { 29642, true }, + { 29658, true }, + { 29669, true }, + { 29683, true }, + { 29695, true }, + { 29710, true }, + { 29718, true }, + { 29732, true }, + { 29744, true }, + { 29756, true }, + { 29768, true }, + { 29778, true }, + { 29789, true }, + { 29800, true }, + { 29814, true }, + { 29837, true }, + { 29853, true }, + { 29861, true }, + { 29876, true }, + { 29895, true }, + { 29911, true }, + { 29921, true }, + { 29940, true }, + { 29953, true }, + { 29961, true }, + { 29976, true }, + { 29988, true }, + { 29996, true }, + { 30002, true }, { 30015, true }, - { 30029, true }, - { 30043, true }, - { 30056, false }, - { 30076, true }, - { 30092, true }, - { 30104, true }, - { 30120, true }, - { 30133, true }, - { 30153, true }, - { 30167, true }, - { 30183, true }, - { 30197, true }, - { 30217, true }, - { 30231, true }, - { 30254, true }, - { 30269, true }, - { 30283, true }, - { 30296, true }, + { 30024, true }, + { 30038, true }, + { 30052, true }, + { 30065, false }, + { 30085, true }, + { 30101, true }, + { 30113, true }, + { 30129, true }, + { 30142, true }, + { 30162, true }, + { 30176, true }, + { 30192, true }, + { 30206, true }, + { 30226, true }, + { 30240, true }, + { 30263, true }, + { 30278, true }, + { 30292, true }, { 30305, true }, - { 30315, false }, - { 30325, true }, - { 30341, true }, - { 30363, true }, - { 30395, true }, - { 30411, true }, - { 30432, true }, - { 30452, true }, - { 30465, true }, - { 30482, true }, - { 30502, true }, - { 30521, true }, - { 30540, true }, - { 30553, true }, - { 30568, true }, - { 30584, true }, - { 30596, true }, - { 30611, true }, - { 30634, true }, - { 30650, true }, - { 30662, false }, - { 30683, true }, - { 30691, true }, + { 30314, true }, + { 30324, false }, + { 30334, true }, + { 30350, true }, + { 30372, true }, + { 30404, true }, + { 30420, true }, + { 30441, true }, + { 30461, true }, + { 30474, true }, + { 30491, true }, + { 30511, true }, + { 30530, true }, + { 30549, true }, + { 30562, true }, + { 30577, true }, + { 30593, true }, + { 30605, true }, + { 30620, true }, + { 30643, true }, + { 30659, true }, + { 30671, false }, + { 30692, true }, { 30700, true }, - { 30714, true }, + { 30709, true }, { 30723, true }, - { 30735, true }, - { 30751, true }, - { 30768, false }, - { 30778, true }, - { 30789, true }, - { 30801, true }, - { 30814, true }, - { 30832, true }, - { 30849, true }, - { 30866, false }, - { 30876, true }, - { 30894, true }, - { 30908, true }, - { 30930, true }, - { 30943, true }, - { 30958, true }, - { 30979, true }, - { 31001, true }, - { 31017, true }, - { 31032, true }, - { 31046, true }, - { 31072, true }, - { 31097, true }, - { 31117, true }, - { 31131, true }, - { 31146, true }, - { 31159, true }, - { 31171, true }, - { 31181, true }, - { 31196, true }, - { 31206, true }, - { 31220, true }, - { 31231, true }, - { 31242, true }, - { 31257, true }, - { 31269, true }, - { 31283, true }, - { 31296, true }, - { 31312, true }, - { 31330, true }, - { 31340, true }, - { 31350, true }, - { 31370, true }, - { 31379, true }, + { 30732, true }, + { 30744, true }, + { 30760, true }, + { 30777, false }, + { 30787, true }, + { 30798, true }, + { 30810, true }, + { 30823, true }, + { 30841, true }, + { 30858, true }, + { 30875, false }, + { 30885, true }, + { 30903, true }, + { 30917, true }, + { 30939, true }, + { 30952, true }, + { 30967, true }, + { 30988, true }, + { 31010, true }, + { 31026, true }, + { 31041, true }, + { 31055, true }, + { 31081, true }, + { 31106, true }, + { 31126, true }, + { 31140, true }, + { 31155, true }, + { 31168, true }, + { 31180, true }, + { 31190, true }, + { 31205, true }, + { 31215, true }, + { 31229, true }, + { 31240, true }, + { 31251, true }, + { 31266, true }, + { 31278, true }, + { 31292, true }, + { 31305, true }, + { 31321, true }, + { 31339, true }, + { 31349, true }, + { 31359, true }, + { 31368, true }, + { 31380, true }, { 31391, true }, - { 31402, true }, - { 31411, true }, - { 31427, true }, - { 31442, true }, - { 31452, false }, - { 31472, true }, - { 31496, true }, - { 31517, true }, - { 31525, true }, - { 31535, true }, - { 31549, false }, - { 31559, true }, - { 31577, false }, - { 31591, true }, - { 31610, true }, - { 31627, true }, - { 31641, false }, - { 31659, true }, - { 31675, true }, - { 31686, true }, - { 31699, true }, - { 31714, true }, - { 31734, false }, - { 31749, true }, - { 31761, true }, - { 31774, true }, - { 31786, true }, - { 31799, true }, - { 31811, true }, - { 31826, true }, - { 31839, true }, - { 31852, false }, - { 31875, false }, + { 31400, true }, + { 31416, true }, + { 31431, true }, + { 31441, false }, + { 31461, true }, + { 31485, true }, + { 31506, true }, + { 31516, true }, + { 31530, false }, + { 31540, true }, + { 31558, false }, + { 31572, true }, + { 31589, true }, + { 31603, false }, + { 31621, true }, + { 31629, true }, + { 31645, true }, + { 31656, true }, + { 31669, true }, + { 31684, true }, + { 31704, false }, + { 31719, true }, + { 31731, true }, + { 31744, true }, + { 31756, true }, + { 31769, true }, + { 31781, true }, + { 31796, true }, + { 31809, true }, + { 31822, false }, + { 31845, false }, + { 31869, true }, + { 31886, true }, { 31899, true }, - { 31916, true }, - { 31929, true }, - { 31940, true }, - { 31952, true }, + { 31910, true }, + { 31922, true }, + { 31936, true }, + { 31947, true }, { 31966, true }, - { 31977, true }, - { 31996, true }, - { 32013, true }, - { 32035, true }, - { 32049, true }, - { 32068, true }, - { 32078, true }, - { 32092, true }, - { 32113, true }, - { 32128, true }, - { 32142, true }, - { 32153, true }, - { 32167, true }, - { 32180, true }, - { 32193, true }, - { 32213, true }, - { 32221, true }, - { 32233, false }, - { 32245, true }, - { 32256, true }, - { 32273, true }, - { 32295, true }, + { 31983, true }, + { 32005, true }, + { 32019, true }, + { 32038, true }, + { 32048, true }, + { 32062, true }, + { 32083, true }, + { 32098, true }, + { 32112, true }, + { 32123, true }, + { 32137, true }, + { 32150, true }, + { 32163, true }, + { 32183, true }, + { 32191, true }, + { 32203, false }, + { 32215, true }, + { 32226, true }, + { 32243, true }, + { 32265, true }, + { 32277, true }, + { 32289, true }, { 32307, true }, - { 32319, true }, - { 32337, true }, - { 32351, true }, - { 32366, true }, - { 32385, true }, - { 32400, true }, - { 32414, true }, - { 32426, true }, - { 32442, true }, - { 32463, true }, - { 32482, true }, - { 32499, true }, - { 32526, false }, - { 32545, true }, - { 32559, true }, - { 32579, true }, - { 32599, true }, - { 32612, true }, - { 32633, true }, - { 32654, true }, - { 32667, true }, - { 32674, true }, - { 32686, true }, - { 32708, true }, - { 32724, true }, - { 32739, true }, - { 32752, true }, - { 32772, true }, - { 32787, true }, - { 32797, true }, + { 32321, true }, + { 32336, true }, + { 32355, true }, + { 32370, true }, + { 32384, true }, + { 32396, true }, + { 32412, true }, + { 32433, true }, + { 32452, true }, + { 32469, true }, + { 32496, false }, + { 32515, true }, + { 32529, true }, + { 32549, true }, + { 32569, true }, + { 32582, true }, + { 32603, true }, + { 32624, true }, + { 32637, true }, + { 32644, true }, + { 32656, true }, + { 32678, true }, + { 32694, true }, + { 32709, true }, + { 32722, true }, + { 32742, true }, + { 32757, true }, + { 32767, true }, + { 32779, true }, + { 32791, true }, { 32809, true }, - { 32821, true }, - { 32839, true }, - { 32858, true }, - { 32873, true }, - { 32894, false }, - { 32915, true }, - { 32935, true }, - { 32967, true }, - { 32977, true }, - { 32990, true }, - { 33009, true }, - { 33026, false }, - { 33050, false }, - { 33072, true }, + { 32828, true }, + { 32843, true }, + { 32864, false }, + { 32885, true }, + { 32905, true }, + { 32937, true }, + { 32947, true }, + { 32960, true }, + { 32979, true }, + { 32996, false }, + { 33020, false }, + { 33042, true }, + { 33066, true }, { 33096, true }, - { 33126, true }, - { 33150, true }, - { 33167, true }, - { 33185, true }, - { 33200, true }, - { 33217, true }, - { 33231, true }, - { 33253, true }, - { 33278, true }, - { 33291, true }, - { 33310, true }, - { 33325, true }, - { 33349, true }, - { 33370, true }, - { 33384, true }, - { 33399, true }, - { 33415, true }, - { 33432, true }, - { 33450, true }, - { 33474, false }, - { 33496, true }, - { 33509, true }, - { 33520, true }, - { 33532, true }, - { 33547, false }, - { 33558, true }, - { 33586, true }, - { 33601, true }, - { 33624, true }, - { 33637, true }, - { 33648, true }, - { 33661, true }, - { 33679, true }, - { 33701, true }, - { 33726, true }, + { 33120, true }, + { 33137, true }, + { 33155, true }, + { 33170, true }, + { 33187, true }, + { 33201, true }, + { 33223, true }, + { 33248, true }, + { 33261, true }, + { 33280, true }, + { 33295, true }, + { 33319, true }, + { 33340, true }, + { 33354, true }, + { 33369, true }, + { 33385, true }, + { 33402, true }, + { 33420, true }, + { 33444, false }, + { 33466, true }, + { 33479, true }, + { 33490, true }, + { 33502, true }, + { 33517, false }, + { 33528, true }, + { 33556, true }, + { 33571, true }, + { 33594, true }, + { 33607, true }, + { 33618, true }, + { 33631, true }, + { 33649, true }, + { 33671, true }, + { 33696, true }, + { 33719, true }, + { 33733, true }, { 33749, true }, - { 33763, true }, - { 33776, true }, - { 33794, true }, - { 33804, true }, - { 33817, true }, - { 33838, true }, - { 33853, true }, + { 33762, true }, + { 33780, true }, + { 33790, true }, + { 33803, true }, + { 33824, true }, + { 33839, true }, + { 33863, true }, { 33877, true }, - { 33891, true }, - { 33916, true }, - { 33931, true }, - { 33954, true }, - { 33963, true }, - { 33984, true }, - { 34001, true }, - { 34012, true }, - { 34025, false }, - { 34064, true }, - { 34077, true }, - { 34093, true }, - { 34107, false }, - { 34122, true }, - { 34142, false }, - { 34158, true }, - { 34177, true }, - { 34188, true }, - { 34201, true }, - { 34224, true }, - { 34236, true }, - { 34245, true }, + { 33902, true }, + { 33917, true }, + { 33940, true }, + { 33949, true }, + { 33970, true }, + { 33987, true }, + { 33998, true }, + { 34011, false }, + { 34050, true }, + { 34063, true }, + { 34079, true }, + { 34093, false }, + { 34108, true }, + { 34128, false }, + { 34144, true }, + { 34163, true }, + { 34174, true }, + { 34187, true }, + { 34210, true }, + { 34222, true }, + { 34231, true }, + { 34241, true }, { 34255, true }, - { 34269, true }, + { 34270, true }, { 34284, true }, - { 34298, true }, - { 34309, true }, - { 34325, true }, - { 34342, true }, - { 34354, true }, - { 34377, true }, - { 34402, true }, - { 34422, true }, - { 34441, true }, - { 34454, true }, - { 34476, true }, - { 34488, true }, - { 34512, true }, - { 34535, true }, - { 34548, true }, - { 34571, true }, - { 34590, true }, + { 34295, true }, + { 34311, true }, + { 34328, true }, + { 34340, true }, + { 34363, true }, + { 34388, true }, + { 34408, true }, + { 34427, true }, + { 34440, true }, + { 34462, true }, + { 34474, true }, + { 34498, true }, + { 34521, true }, + { 34534, true }, + { 34557, true }, + { 34576, true }, + { 34587, true }, { 34601, true }, - { 34615, true }, - { 34627, true }, - { 34645, true }, - { 34661, true }, - { 34679, true }, - { 34696, true }, - { 34709, true }, - { 34720, true }, - { 34738, true }, - { 34756, true }, - { 34779, true }, - { 34796, false }, - { 34811, true }, - { 34823, true }, - { 34835, true }, - { 34848, true }, - { 34857, true }, - { 34872, true }, + { 34613, true }, + { 34631, true }, + { 34647, true }, + { 34665, true }, + { 34682, true }, + { 34695, true }, + { 34706, true }, + { 34724, true }, + { 34742, true }, + { 34765, true }, + { 34782, false }, + { 34797, true }, + { 34809, true }, + { 34821, true }, + { 34834, true }, + { 34843, true }, + { 34858, true }, + { 34877, true }, { 34891, true }, - { 34905, true }, - { 34920, true }, - { 34932, true }, - { 34946, false }, - { 34963, true }, - { 34974, true }, - { 34987, true }, - { 35006, true }, - { 35019, true }, - { 35037, true }, - { 35063, true }, - { 35076, true }, - { 35095, true }, - { 35110, true }, - { 35124, true }, - { 35141, true }, + { 34906, true }, + { 34918, true }, + { 34930, true }, + { 34944, false }, + { 34961, true }, + { 34972, true }, + { 34985, true }, + { 35004, true }, + { 35017, true }, + { 35035, true }, + { 35061, true }, + { 35074, true }, + { 35093, true }, + { 35108, true }, + { 35125, true }, + { 35142, true }, { 35158, true }, - { 35174, true }, - { 35193, true }, - { 35212, true }, + { 35177, true }, + { 35196, true }, + { 35216, true }, { 35232, true }, { 35248, true }, - { 35264, true }, - { 35278, false }, - { 35288, true }, - { 35296, true }, - { 35322, true }, - { 35339, true }, - { 35360, true }, - { 35378, true }, - { 35394, false }, - { 35413, true }, - { 35422, true }, - { 35436, true }, - { 35451, true }, - { 35468, true }, - { 35479, true }, - { 35498, true }, - { 35511, true }, + { 35262, false }, + { 35272, true }, + { 35280, true }, + { 35306, true }, + { 35323, true }, + { 35344, true }, + { 35362, true }, + { 35378, false }, + { 35397, true }, + { 35406, true }, + { 35420, true }, + { 35435, true }, + { 35452, true }, + { 35463, true }, + { 35482, true }, + { 35495, true }, + { 35510, true }, { 35526, true }, - { 35542, true }, - { 35564, true }, - { 35578, false }, - { 35592, true }, - { 35607, true }, - { 35619, true }, - { 35631, true }, - { 35654, true }, - { 35673, true }, - { 35689, true }, - { 35704, true }, - { 35714, true }, - { 35721, true }, - { 35732, true }, - { 35749, true }, - { 35763, true }, + { 35548, true }, + { 35562, false }, + { 35576, true }, + { 35591, true }, + { 35603, true }, + { 35615, true }, + { 35638, true }, + { 35657, true }, + { 35665, true }, + { 35681, true }, + { 35696, true }, + { 35706, true }, + { 35713, true }, + { 35724, true }, + { 35741, true }, + { 35755, true }, + { 35764, true }, { 35772, true }, { 35786, true }, { 35805, false }, @@ -15615,10611 +15594,10588 @@ { 36143, true }, { 36158, true }, { 36174, true }, - { 36182, true }, - { 36193, true }, - { 36202, true }, - { 36219, true }, - { 36235, true }, - { 36248, true }, - { 36265, true }, - { 36273, true }, - { 36284, true }, - { 36293, true }, - { 36304, true }, - { 36318, true }, - { 36331, true }, - { 36339, true }, - { 36357, true }, - { 36366, true }, - { 36375, true }, - { 36383, true }, - { 36391, true }, - { 36410, true }, - { 36429, true }, - { 36438, true }, - { 36458, true }, - { 36481, true }, - { 36491, true }, - { 36501, true }, - { 36519, true }, - { 36539, true }, - { 36553, true }, - { 36569, true }, - { 36579, true }, - { 36590, true }, - { 36600, true }, - { 36617, true }, - { 36632, true }, - { 36643, true }, - { 36650, true }, - { 36661, true }, - { 36672, true }, - { 36680, true }, - { 36700, true }, - { 36721, true }, - { 36740, true }, - { 36755, true }, - { 36777, true }, - { 36789, false }, - { 36811, true }, - { 36830, true }, - { 36845, true }, - { 36864, true }, - { 36876, true }, - { 36890, true }, - { 36899, true }, - { 36911, true }, - { 36921, true }, - { 36930, true }, - { 36939, true }, - { 36948, true }, - { 36957, true }, - { 36967, true }, - { 36977, true }, - { 36986, true }, - { 36995, true }, - { 37013, true }, - { 37029, true }, - { 37037, true }, - { 37044, true }, - { 37057, true }, - { 37074, true }, - { 37088, true }, - { 37099, true }, - { 37116, true }, - { 37136, true }, - { 37155, true }, - { 37169, true }, - { 37187, true }, - { 37200, true }, - { 37217, true }, - { 37231, true }, - { 37244, true }, - { 37270, true }, - { 37285, true }, - { 37299, true }, - { 37310, true }, - { 37323, true }, - { 37333, true }, - { 37344, true }, - { 37363, true }, - { 37378, true }, - { 37393, true }, - { 37420, true }, - { 37430, true }, - { 37442, true }, - { 37454, true }, - { 37462, true }, - { 37473, true }, - { 37482, true }, - { 37490, true }, - { 37501, true }, - { 37528, true }, - { 37538, true }, - { 37549, true }, - { 37559, true }, - { 37573, true }, - { 37587, true }, - { 37598, true }, - { 37605, true }, - { 37613, true }, - { 37621, true }, - { 37637, true }, - { 37651, true }, - { 37665, true }, - { 37674, true }, - { 37686, true }, - { 37693, true }, - { 37700, true }, - { 37716, true }, - { 37728, true }, - { 37742, true }, - { 37764, true }, - { 37782, true }, - { 37793, true }, - { 37804, true }, - { 37815, true }, - { 37831, true }, - { 37848, true }, - { 37874, false }, - { 37897, true }, - { 37913, true }, - { 37923, true }, - { 37936, true }, - { 37947, true }, - { 37962, true }, - { 37980, false }, - { 37992, true }, - { 38006, true }, - { 38020, true }, - { 38037, true }, - { 38055, true }, - { 38068, true }, - { 38087, true }, - { 38097, true }, - { 38110, true }, - { 38126, true }, - { 38135, true }, - { 38153, true }, - { 38167, true }, - { 38185, true }, - { 38200, true }, - { 38215, true }, - { 38236, true }, - { 38252, true }, - { 38273, true }, - { 38289, true }, - { 38308, true }, - { 38329, true }, - { 38349, true }, - { 38369, true }, - { 38389, true }, - { 38405, true }, - { 38422, true }, - { 38441, true }, - { 38459, true }, - { 38479, true }, - { 38495, true }, - { 38506, false }, - { 38516, true }, - { 38525, true }, - { 38543, true }, - { 38557, true }, - { 38575, true }, - { 38588, true }, - { 38603, true }, - { 38618, true }, - { 38626, true }, - { 38660, true }, - { 38671, false }, - { 38685, true }, - { 38703, true }, - { 38721, true }, - { 38732, true }, - { 38746, true }, - { 38761, true }, - { 38778, true }, - { 38793, true }, - { 38822, true }, - { 38855, true }, - { 38867, true }, - { 38879, true }, - { 38893, true }, - { 38910, true }, - { 38922, true }, - { 38937, false }, - { 38949, true }, - { 38958, true }, - { 38974, true }, - { 38986, true }, - { 39003, true }, - { 39018, false }, - { 39032, true }, - { 39052, false }, - { 39066, true }, - { 39077, true }, - { 39090, true }, - { 39100, false }, - { 39116, true }, - { 39130, true }, - { 39144, true }, - { 39158, true }, - { 39169, true }, - { 39185, true }, - { 39196, true }, - { 39213, true }, - { 39239, true }, - { 39259, true }, - { 39273, true }, - { 39290, true }, - { 39304, true }, - { 39318, false }, - { 39336, false }, - { 39353, true }, - { 39364, true }, - { 39379, true }, - { 39391, true }, - { 39406, true }, - { 39428, true }, - { 39446, true }, - { 39462, true }, - { 39476, true }, - { 39492, true }, - { 39510, true }, - { 39523, true }, - { 39540, true }, - { 39553, true }, - { 39568, true }, - { 39583, true }, - { 39599, true }, - { 39618, true }, - { 39639, true }, - { 39654, true }, - { 39666, true }, - { 39679, true }, - { 39705, true }, - { 39725, true }, - { 39736, true }, - { 39754, true }, - { 39773, true }, - { 39787, true }, - { 39796, true }, - { 39813, true }, - { 39824, true }, - { 39836, true }, - { 39846, true }, - { 39867, true }, - { 39879, true }, - { 39887, true }, - { 39895, true }, - { 39906, true }, - { 39922, true }, - { 39932, true }, - { 39941, true }, - { 39954, true }, - { 39969, true }, - { 39986, true }, - { 40008, true }, - { 40029, true }, - { 40042, true }, - { 40053, false }, - { 40073, true }, - { 40088, true }, - { 40101, true }, - { 40113, true }, - { 40134, true }, - { 40148, true }, - { 40162, true }, - { 40179, true }, - { 40194, true }, - { 40208, true }, - { 40222, true }, - { 40236, true }, - { 40250, true }, - { 40264, true }, - { 40279, true }, - { 40291, true }, - { 40305, true }, - { 40320, true }, - { 40330, true }, - { 40346, true }, - { 40367, true }, - { 40382, true }, - { 40395, true }, - { 40410, true }, - { 40422, true }, - { 40437, true }, - { 40454, true }, - { 40471, true }, - { 40483, true }, - { 40492, true }, - { 40512, true }, - { 40523, true }, - { 40538, true }, - { 40554, true }, - { 40561, true }, - { 40584, true }, - { 40598, true }, - { 40613, true }, - { 40628, true }, - { 40643, true }, - { 40654, true }, - { 40664, true }, - { 40675, true }, - { 40686, true }, - { 40697, true }, - { 40710, true }, - { 40723, true }, - { 40735, true }, - { 40763, true }, - { 40775, true }, - { 40789, true }, - { 40805, true }, - { 40824, true }, - { 40835, true }, - { 40855, true }, - { 40876, true }, - { 40891, true }, - { 40905, true }, - { 40924, true }, - { 40941, true }, - { 40954, true }, - { 40968, false }, - { 40981, true }, - { 40993, true }, - { 41006, true }, - { 41018, true }, - { 41031, true }, - { 41044, true }, - { 41055, true }, - { 41073, true }, - { 41091, true }, - { 41103, true }, - { 41117, true }, - { 41131, true }, - { 41160, true }, - { 41179, true }, - { 41192, true }, - { 41217, true }, - { 41234, true }, - { 41254, true }, - { 41275, true }, + { 36182, false }, + { 36194, true }, + { 36205, true }, + { 36214, true }, + { 36231, true }, + { 36247, true }, + { 36260, true }, + { 36277, true }, + { 36285, true }, + { 36296, true }, + { 36305, true }, + { 36316, true }, + { 36330, true }, + { 36343, true }, + { 36351, true }, + { 36369, true }, + { 36378, true }, + { 36387, true }, + { 36395, true }, + { 36403, true }, + { 36422, true }, + { 36441, true }, + { 36450, true }, + { 36470, true }, + { 36493, true }, + { 36503, true }, + { 36513, true }, + { 36531, true }, + { 36551, true }, + { 36565, true }, + { 36581, true }, + { 36591, true }, + { 36602, true }, + { 36612, true }, + { 36629, true }, + { 36640, true }, + { 36647, true }, + { 36658, true }, + { 36669, true }, + { 36677, true }, + { 36697, true }, + { 36718, true }, + { 36737, true }, + { 36752, true }, + { 36774, true }, + { 36786, false }, + { 36808, true }, + { 36827, true }, + { 36842, true }, + { 36861, true }, + { 36873, true }, + { 36887, true }, + { 36896, true }, + { 36908, true }, + { 36918, true }, + { 36927, true }, + { 36936, true }, + { 36945, true }, + { 36954, true }, + { 36964, true }, + { 36974, true }, + { 36983, true }, + { 36992, true }, + { 37010, true }, + { 37026, true }, + { 37034, true }, + { 37041, true }, + { 37054, true }, + { 37071, true }, + { 37085, true }, + { 37096, true }, + { 37113, true }, + { 37133, true }, + { 37152, true }, + { 37166, true }, + { 37184, true }, + { 37197, true }, + { 37214, true }, + { 37228, true }, + { 37241, true }, + { 37267, true }, + { 37282, true }, + { 37296, true }, + { 37307, true }, + { 37320, true }, + { 37330, true }, + { 37341, true }, + { 37360, true }, + { 37375, true }, + { 37390, true }, + { 37417, true }, + { 37427, true }, + { 37439, true }, + { 37451, true }, + { 37459, true }, + { 37470, true }, + { 37479, true }, + { 37487, true }, + { 37498, true }, + { 37525, true }, + { 37535, true }, + { 37546, true }, + { 37556, true }, + { 37570, true }, + { 37584, true }, + { 37595, true }, + { 37602, true }, + { 37610, true }, + { 37618, true }, + { 37634, true }, + { 37648, true }, + { 37662, true }, + { 37671, true }, + { 37683, true }, + { 37690, true }, + { 37697, true }, + { 37713, true }, + { 37725, true }, + { 37739, true }, + { 37761, true }, + { 37779, true }, + { 37790, true }, + { 37801, true }, + { 37812, true }, + { 37828, true }, + { 37845, true }, + { 37871, false }, + { 37894, true }, + { 37910, true }, + { 37920, true }, + { 37933, true }, + { 37944, true }, + { 37959, true }, + { 37977, false }, + { 37989, true }, + { 38003, true }, + { 38017, true }, + { 38034, true }, + { 38052, true }, + { 38065, true }, + { 38084, true }, + { 38094, true }, + { 38107, true }, + { 38123, true }, + { 38132, true }, + { 38150, true }, + { 38164, true }, + { 38182, true }, + { 38197, true }, + { 38212, true }, + { 38233, true }, + { 38249, true }, + { 38270, true }, + { 38286, true }, + { 38305, true }, + { 38326, true }, + { 38346, true }, + { 38366, true }, + { 38386, true }, + { 38402, true }, + { 38419, true }, + { 38438, true }, + { 38456, true }, + { 38476, true }, + { 38492, true }, + { 38503, false }, + { 38513, true }, + { 38522, true }, + { 38540, true }, + { 38554, true }, + { 38572, true }, + { 38585, true }, + { 38600, true }, + { 38615, true }, + { 38623, true }, + { 38657, true }, + { 38668, false }, + { 38682, true }, + { 38700, true }, + { 38718, true }, + { 38729, true }, + { 38743, true }, + { 38758, true }, + { 38775, true }, + { 38790, true }, + { 38819, true }, + { 38852, true }, + { 38864, true }, + { 38876, true }, + { 38890, true }, + { 38907, true }, + { 38919, true }, + { 38934, false }, + { 38946, true }, + { 38955, true }, + { 38971, true }, + { 38983, true }, + { 39000, true }, + { 39015, false }, + { 39029, true }, + { 39049, false }, + { 39063, true }, + { 39074, true }, + { 39087, true }, + { 39097, false }, + { 39113, true }, + { 39127, true }, + { 39141, true }, + { 39155, true }, + { 39166, true }, + { 39182, true }, + { 39193, true }, + { 39210, true }, + { 39236, true }, + { 39256, true }, + { 39270, true }, + { 39287, true }, + { 39301, true }, + { 39315, false }, + { 39333, false }, + { 39350, true }, + { 39361, true }, + { 39376, true }, + { 39388, true }, + { 39403, true }, + { 39425, true }, + { 39443, true }, + { 39459, true }, + { 39473, true }, + { 39489, true }, + { 39507, true }, + { 39520, true }, + { 39537, true }, + { 39550, true }, + { 39565, true }, + { 39580, true }, + { 39596, true }, + { 39615, true }, + { 39636, true }, + { 39651, true }, + { 39663, true }, + { 39676, true }, + { 39702, true }, + { 39722, true }, + { 39733, true }, + { 39751, true }, + { 39770, true }, + { 39784, true }, + { 39793, true }, + { 39810, true }, + { 39821, true }, + { 39833, true }, + { 39843, true }, + { 39864, true }, + { 39876, true }, + { 39884, true }, + { 39892, true }, + { 39903, true }, + { 39919, true }, + { 39929, true }, + { 39938, true }, + { 39951, true }, + { 39966, true }, + { 39983, true }, + { 40005, true }, + { 40026, true }, + { 40039, true }, + { 40050, false }, + { 40070, true }, + { 40085, true }, + { 40098, true }, + { 40110, true }, + { 40131, true }, + { 40145, true }, + { 40159, true }, + { 40176, true }, + { 40191, true }, + { 40205, true }, + { 40219, true }, + { 40233, true }, + { 40247, true }, + { 40261, true }, + { 40276, true }, + { 40288, true }, + { 40302, true }, + { 40317, true }, + { 40327, true }, + { 40343, true }, + { 40364, true }, + { 40379, true }, + { 40392, true }, + { 40407, true }, + { 40419, true }, + { 40434, true }, + { 40451, true }, + { 40468, true }, + { 40480, true }, + { 40489, true }, + { 40509, true }, + { 40520, true }, + { 40535, true }, + { 40551, true }, + { 40558, true }, + { 40581, true }, + { 40595, true }, + { 40610, true }, + { 40625, true }, + { 40640, true }, + { 40651, true }, + { 40661, true }, + { 40672, true }, + { 40683, true }, + { 40694, true }, + { 40707, true }, + { 40720, true }, + { 40732, true }, + { 40760, true }, + { 40772, true }, + { 40786, true }, + { 40802, true }, + { 40821, true }, + { 40832, true }, + { 40852, true }, + { 40873, true }, + { 40888, true }, + { 40902, true }, + { 40921, true }, + { 40938, true }, + { 40951, true }, + { 40965, false }, + { 40978, true }, + { 40990, true }, + { 41003, true }, + { 41015, true }, + { 41028, true }, + { 41041, true }, + { 41052, true }, + { 41070, true }, + { 41088, true }, + { 41100, true }, + { 41115, true }, + { 41129, true }, + { 41143, true }, + { 41172, true }, + { 41191, true }, + { 41204, true }, + { 41229, true }, + { 41246, true }, + { 41266, true }, { 41287, true }, - { 41311, true }, - { 41344, true }, + { 41299, true }, + { 41323, true }, { 41356, true }, - { 41373, true }, - { 41388, true }, - { 41402, true }, - { 41428, true }, - { 41438, true }, - { 41451, true }, - { 41461, true }, - { 41471, true }, - { 41489, true }, - { 41507, true }, - { 41534, true }, - { 41550, true }, - { 41575, true }, - { 41595, false }, - { 41616, true }, - { 41631, true }, - { 41646, true }, - { 41667, true }, - { 41678, true }, - { 41702, true }, - { 41715, true }, - { 41725, false }, - { 41739, true }, - { 41750, true }, - { 41764, true }, - { 41783, true }, - { 41798, true }, - { 41813, true }, - { 41822, true }, - { 41832, true }, - { 41843, true }, - { 41851, true }, - { 41861, true }, - { 41871, true }, - { 41885, false }, - { 41910, true }, - { 41928, false }, - { 41952, true }, - { 41966, true }, - { 41985, true }, - { 42012, true }, - { 42021, true }, - { 42035, true }, - { 42052, true }, - { 42068, true }, - { 42083, true }, - { 42100, true }, - { 42112, true }, - { 42124, true }, - { 42134, true }, - { 42146, true }, - { 42159, true }, - { 42173, true }, - { 42190, true }, - { 42201, true }, - { 42219, false }, - { 42239, true }, - { 42251, true }, - { 42263, true }, - { 42276, true }, - { 42298, true }, - { 42312, true }, - { 42321, true }, - { 42333, true }, - { 42345, true }, - { 42354, true }, - { 42364, true }, - { 42378, true }, - { 42395, true }, - { 42406, true }, - { 42420, true }, - { 42429, true }, - { 42438, true }, - { 42453, true }, - { 42465, true }, - { 42481, true }, - { 42498, true }, - { 42520, true }, - { 42529, true }, - { 42541, true }, - { 42555, true }, - { 42588, true }, - { 42613, true }, - { 42622, true }, - { 42638, true }, - { 42650, true }, - { 42661, true }, - { 42686, true }, - { 42701, true }, - { 42723, true }, - { 42748, true }, - { 42779, true }, - { 42790, true }, - { 42806, true }, - { 42820, true }, - { 42838, true }, - { 42852, true }, - { 42867, false }, - { 42884, true }, - { 42902, true }, - { 42915, true }, - { 42925, true }, - { 42937, true }, - { 42952, true }, - { 42963, true }, - { 42977, true }, - { 42990, true }, - { 43002, true }, - { 43014, true }, - { 43027, true }, - { 43043, true }, - { 43056, true }, - { 43068, false }, - { 43085, true }, - { 43105, true }, - { 43122, true }, - { 43137, true }, - { 43160, true }, - { 43186, true }, - { 43206, false }, - { 43224, true }, - { 43243, true }, - { 43260, true }, - { 43273, true }, - { 43290, true }, - { 43300, false }, - { 43317, true }, - { 43336, true }, - { 43353, true }, - { 43367, true }, - { 43384, true }, - { 43392, true }, - { 43404, true }, - { 43414, true }, - { 43425, true }, - { 43439, true }, - { 43450, true }, - { 43463, true }, - { 43482, true }, - { 43493, true }, - { 43506, true }, - { 43519, true }, - { 43538, true }, - { 43554, true }, - { 43566, true }, - { 43580, true }, - { 43594, true }, - { 43606, true }, - { 43618, true }, - { 43633, true }, - { 43651, true }, - { 43666, true }, - { 43681, true }, - { 43697, true }, - { 43711, true }, - { 43732, true }, - { 43745, true }, - { 43761, true }, - { 43780, true }, - { 43799, true }, - { 43816, false }, - { 43836, true }, - { 43866, true }, - { 43892, true }, - { 43909, true }, - { 43921, true }, - { 43941, true }, - { 43955, true }, - { 43974, true }, - { 43992, true }, - { 44007, true }, - { 44018, true }, - { 44029, true }, - { 44039, true }, - { 44057, true }, - { 44076, true }, - { 44086, true }, - { 44104, true }, - { 44113, false }, - { 44124, false }, - { 44138, false }, - { 44158, true }, - { 44166, true }, - { 44180, true }, - { 44193, true }, - { 44209, true }, - { 44220, true }, - { 44229, true }, - { 44242, true }, - { 44262, false }, - { 44277, false }, - { 44294, true }, - { 44303, true }, - { 44312, true }, - { 44328, true }, - { 44345, true }, - { 44354, true }, - { 44361, true }, - { 44369, true }, - { 44381, true }, - { 44390, true }, - { 44400, true }, - { 44417, true }, - { 44427, true }, - { 44435, true }, - { 44443, true }, - { 44450, true }, - { 44461, true }, - { 44474, true }, - { 44481, true }, - { 44491, true }, - { 44506, true }, - { 44521, true }, + { 41368, true }, + { 41385, true }, + { 41400, true }, + { 41414, true }, + { 41440, true }, + { 41450, true }, + { 41463, true }, + { 41473, true }, + { 41483, true }, + { 41501, true }, + { 41519, true }, + { 41546, true }, + { 41562, true }, + { 41587, true }, + { 41607, false }, + { 41628, true }, + { 41643, true }, + { 41658, true }, + { 41679, true }, + { 41690, true }, + { 41714, true }, + { 41727, true }, + { 41737, false }, + { 41751, true }, + { 41762, true }, + { 41776, true }, + { 41795, true }, + { 41810, true }, + { 41819, true }, + { 41829, true }, + { 41840, true }, + { 41848, true }, + { 41858, true }, + { 41868, true }, + { 41882, false }, + { 41907, true }, + { 41925, false }, + { 41949, true }, + { 41963, true }, + { 41982, true }, + { 42009, true }, + { 42018, true }, + { 42032, true }, + { 42049, true }, + { 42065, true }, + { 42080, true }, + { 42097, true }, + { 42109, true }, + { 42121, true }, + { 42131, true }, + { 42143, true }, + { 42156, true }, + { 42170, true }, + { 42187, true }, + { 42198, true }, + { 42216, false }, + { 42236, true }, + { 42248, true }, + { 42260, true }, + { 42273, true }, + { 42295, true }, + { 42309, true }, + { 42318, true }, + { 42330, true }, + { 42342, true }, + { 42351, true }, + { 42361, true }, + { 42375, true }, + { 42392, true }, + { 42403, true }, + { 42417, true }, + { 42426, true }, + { 42435, true }, + { 42450, true }, + { 42462, true }, + { 42478, true }, + { 42495, true }, + { 42517, true }, + { 42526, true }, + { 42538, true }, + { 42552, true }, + { 42585, true }, + { 42610, true }, + { 42619, true }, + { 42635, true }, + { 42647, true }, + { 42658, true }, + { 42683, true }, + { 42698, true }, + { 42720, true }, + { 42745, true }, + { 42776, true }, + { 42787, true }, + { 42803, true }, + { 42817, true }, + { 42835, true }, + { 42849, true }, + { 42864, false }, + { 42881, true }, + { 42899, true }, + { 42912, true }, + { 42922, true }, + { 42934, true }, + { 42949, true }, + { 42960, true }, + { 42974, true }, + { 42987, true }, + { 42999, true }, + { 43011, true }, + { 43024, true }, + { 43040, true }, + { 43053, true }, + { 43065, false }, + { 43082, true }, + { 43102, true }, + { 43119, true }, + { 43134, true }, + { 43157, true }, + { 43183, true }, + { 43203, false }, + { 43221, true }, + { 43240, true }, + { 43257, true }, + { 43270, true }, + { 43287, true }, + { 43297, false }, + { 43314, true }, + { 43333, true }, + { 43350, true }, + { 43364, true }, + { 43381, true }, + { 43389, true }, + { 43401, true }, + { 43411, true }, + { 43422, true }, + { 43436, true }, + { 43447, true }, + { 43460, true }, + { 43479, false }, + { 43487, true }, + { 43498, true }, + { 43511, true }, + { 43524, true }, + { 43543, true }, + { 43559, true }, + { 43571, true }, + { 43585, true }, + { 43599, true }, + { 43611, true }, + { 43623, true }, + { 43638, true }, + { 43656, true }, + { 43671, true }, + { 43686, true }, + { 43702, true }, + { 43716, true }, + { 43737, true }, + { 43750, true }, + { 43766, true }, + { 43785, true }, + { 43804, true }, + { 43821, false }, + { 43841, true }, + { 43871, true }, + { 43897, true }, + { 43914, true }, + { 43926, true }, + { 43946, true }, + { 43960, true }, + { 43979, true }, + { 43997, true }, + { 44012, true }, + { 44023, true }, + { 44034, true }, + { 44044, true }, + { 44062, true }, + { 44081, true }, + { 44091, true }, + { 44109, true }, + { 44118, false }, + { 44129, false }, + { 44143, false }, + { 44163, true }, + { 44171, true }, + { 44185, true }, + { 44198, true }, + { 44214, true }, + { 44225, true }, + { 44234, true }, + { 44247, true }, + { 44267, false }, + { 44282, false }, + { 44299, true }, + { 44308, true }, + { 44317, true }, + { 44333, true }, + { 44350, true }, + { 44359, true }, + { 44366, true }, + { 44374, true }, + { 44386, true }, + { 44395, true }, + { 44405, true }, + { 44415, true }, + { 44423, true }, + { 44431, true }, + { 44438, true }, + { 44449, true }, + { 44462, true }, + { 44469, true }, + { 44479, true }, + { 44494, true }, + { 44509, true }, + { 44522, true }, { 44534, true }, - { 44546, true }, - { 44561, true }, - { 44572, true }, - { 44582, true }, - { 44590, true }, + { 44549, true }, + { 44560, true }, + { 44570, true }, + { 44578, true }, + { 44587, true }, { 44599, true }, - { 44611, true }, - { 44626, true }, - { 44636, true }, - { 44653, true }, - { 44662, true }, - { 44672, true }, - { 44688, true }, - { 44704, true }, - { 44723, true }, - { 44737, true }, - { 44753, true }, - { 44766, true }, - { 44781, true }, + { 44614, true }, + { 44624, true }, + { 44641, true }, + { 44650, true }, + { 44660, true }, + { 44676, true }, + { 44692, true }, + { 44711, true }, + { 44725, true }, + { 44741, true }, + { 44754, true }, + { 44769, true }, + { 44782, true }, { 44794, true }, - { 44806, true }, - { 44831, false }, - { 44840, true }, - { 44853, true }, - { 44862, true }, - { 44878, true }, - { 44899, true }, - { 44913, true }, + { 44819, false }, + { 44828, true }, + { 44841, true }, + { 44850, true }, + { 44866, true }, + { 44887, true }, + { 44901, true }, + { 44915, true }, { 44927, true }, - { 44939, true }, - { 44961, false }, + { 44949, false }, + { 44960, true }, { 44972, true }, - { 44984, true }, - { 44995, true }, - { 45009, true }, - { 45029, true }, - { 45043, true }, - { 45066, true }, - { 45080, true }, - { 45097, true }, - { 45111, true }, - { 45130, true }, - { 45146, true }, - { 45157, true }, + { 44983, true }, + { 44997, true }, + { 45017, true }, + { 45031, true }, + { 45054, true }, + { 45068, true }, + { 45085, true }, + { 45099, true }, + { 45118, true }, + { 45134, true }, + { 45145, true }, + { 45156, true }, { 45168, true }, - { 45180, true }, - { 45201, false }, - { 45217, true }, - { 45235, true }, - { 45250, true }, - { 45278, false }, - { 45288, false }, - { 45298, true }, - { 45317, false }, - { 45329, true }, - { 45343, true }, - { 45356, true }, - { 45375, true }, - { 45391, true }, - { 45406, true }, - { 45429, true }, - { 45448, true }, - { 45465, true }, - { 45474, true }, - { 45495, true }, - { 45510, true }, - { 45526, true }, - { 45539, true }, - { 45552, true }, - { 45564, true }, - { 45578, true }, - { 45595, true }, - { 45612, true }, - { 45619, true }, - { 45628, true }, - { 45643, true }, - { 45654, true }, - { 45678, true }, - { 45689, true }, - { 45699, true }, - { 45710, true }, - { 45722, true }, - { 45743, true }, - { 45757, true }, - { 45772, true }, - { 45787, true }, - { 45799, true }, - { 45816, true }, - { 45832, true }, - { 45848, true }, - { 45865, true }, - { 45894, true }, - { 45905, false }, - { 45919, true }, - { 45928, true }, - { 45943, true }, - { 45960, true }, - { 45977, true }, - { 45988, true }, + { 45189, false }, + { 45205, true }, + { 45222, true }, + { 45240, true }, + { 45255, true }, + { 45283, false }, + { 45293, false }, + { 45303, true }, + { 45322, false }, + { 45334, true }, + { 45348, true }, + { 45361, true }, + { 45380, true }, + { 45396, true }, + { 45411, true }, + { 45434, true }, + { 45453, true }, + { 45466, true }, + { 45483, true }, + { 45492, true }, + { 45513, true }, + { 45528, true }, + { 45544, true }, + { 45557, true }, + { 45570, true }, + { 45582, true }, + { 45596, true }, + { 45613, true }, + { 45630, true }, + { 45637, true }, + { 45646, true }, + { 45661, true }, + { 45672, true }, + { 45696, true }, + { 45707, true }, + { 45717, true }, + { 45728, true }, + { 45740, true }, + { 45761, true }, + { 45775, true }, + { 45790, true }, + { 45805, true }, + { 45817, true }, + { 45834, true }, + { 45850, true }, + { 45866, true }, + { 45883, true }, + { 45912, true }, + { 45923, false }, + { 45937, true }, + { 45946, true }, + { 45961, true }, + { 45978, true }, + { 45995, true }, { 46006, true }, - { 46029, true }, - { 46043, true }, - { 46062, true }, - { 46081, true }, - { 46095, true }, - { 46106, true }, - { 46116, true }, - { 46129, true }, - { 46145, true }, - { 46165, true }, - { 46184, true }, - { 46213, true }, - { 46229, true }, - { 46245, true }, - { 46255, true }, - { 46271, true }, - { 46280, true }, - { 46295, true }, - { 46307, true }, - { 46321, true }, - { 46336, true }, - { 46349, false }, - { 46359, true }, - { 46376, true }, - { 46389, true }, + { 46024, true }, + { 46047, true }, + { 46061, true }, + { 46080, true }, + { 46099, true }, + { 46113, true }, + { 46124, true }, + { 46134, true }, + { 46147, true }, + { 46163, true }, + { 46183, true }, + { 46202, true }, + { 46231, true }, + { 46247, true }, + { 46263, true }, + { 46273, true }, + { 46289, true }, + { 46298, true }, + { 46313, true }, + { 46325, true }, + { 46339, true }, + { 46354, true }, + { 46367, false }, + { 46377, true }, + { 46394, true }, { 46407, true }, - { 46429, true }, - { 46440, true }, - { 46449, true }, - { 46461, false }, - { 46474, true }, - { 46486, true }, - { 46499, true }, - { 46514, true }, - { 46526, true }, - { 46541, true }, - { 46573, true }, - { 46585, true }, - { 46599, true }, - { 46615, true }, - { 46625, true }, - { 46635, true }, - { 46650, true }, - { 46664, true }, - { 46674, true }, - { 46685, true }, - { 46701, true }, + { 46425, true }, + { 46447, true }, + { 46458, true }, + { 46467, true }, + { 46479, false }, + { 46492, true }, + { 46504, true }, + { 46517, true }, + { 46532, true }, + { 46544, true }, + { 46559, true }, + { 46591, true }, + { 46603, true }, + { 46617, true }, + { 46633, true }, + { 46643, true }, + { 46653, true }, + { 46668, true }, + { 46682, true }, + { 46692, true }, + { 46703, true }, { 46719, true }, - { 46738, true }, - { 46752, true }, - { 46767, true }, - { 46775, true }, - { 46784, true }, - { 46807, true }, - { 46818, true }, - { 46833, true }, - { 46851, true }, - { 46863, true }, - { 46879, true }, - { 46894, true }, - { 46907, true }, - { 46918, true }, - { 46933, true }, - { 46950, true }, - { 46961, true }, - { 46970, true }, - { 46982, true }, - { 46998, true }, - { 47008, true }, - { 47022, true }, - { 47030, true }, - { 47039, true }, - { 47049, true }, - { 47070, true }, - { 47079, true }, - { 47095, true }, - { 47105, true }, - { 47124, true }, - { 47138, true }, - { 47151, true }, - { 47169, true }, - { 47189, true }, - { 47209, true }, - { 47217, true }, - { 47230, true }, - { 47241, true }, - { 47259, true }, - { 47269, true }, - { 47278, true }, - { 47287, true }, - { 47298, true }, + { 46737, true }, + { 46756, true }, + { 46770, true }, + { 46785, true }, + { 46793, true }, + { 46802, true }, + { 46825, true }, + { 46840, true }, + { 46858, true }, + { 46870, true }, + { 46886, true }, + { 46901, true }, + { 46914, true }, + { 46925, true }, + { 46940, true }, + { 46957, true }, + { 46968, true }, + { 46977, true }, + { 46989, true }, + { 47005, true }, + { 47015, true }, + { 47029, true }, + { 47037, true }, + { 47046, true }, + { 47056, true }, + { 47077, true }, + { 47086, true }, + { 47102, true }, + { 47112, true }, + { 47131, true }, + { 47145, true }, + { 47158, true }, + { 47176, true }, + { 47196, true }, + { 47216, true }, + { 47224, true }, + { 47237, true }, + { 47248, true }, + { 47266, true }, + { 47276, true }, + { 47285, true }, + { 47294, true }, { 47305, true }, - { 47315, true }, - { 47327, true }, - { 47337, true }, - { 47352, true }, + { 47312, true }, + { 47322, true }, + { 47334, true }, + { 47344, true }, { 47359, true }, - { 47372, false }, - { 47387, true }, - { 47407, true }, - { 47424, true }, - { 47439, true }, - { 47455, true }, - { 47469, true }, - { 47490, true }, - { 47499, true }, - { 47508, true }, - { 47521, true }, - { 47531, true }, - { 47543, true }, - { 47552, true }, - { 47562, true }, - { 47574, true }, - { 47585, true }, - { 47593, true }, + { 47366, true }, + { 47379, false }, + { 47394, true }, + { 47414, true }, + { 47431, true }, + { 47446, true }, + { 47462, true }, + { 47476, true }, + { 47497, true }, + { 47506, true }, + { 47515, true }, + { 47528, true }, + { 47538, true }, + { 47550, true }, + { 47559, true }, + { 47569, true }, + { 47581, true }, + { 47592, true }, { 47600, true }, - { 47625, true }, - { 47643, true }, - { 47661, true }, - { 47675, true }, - { 47684, true }, - { 47697, true }, - { 47714, true }, - { 47727, true }, - { 47743, true }, - { 47753, true }, - { 47771, false }, - { 47784, true }, - { 47800, true }, - { 47816, true }, - { 47829, true }, - { 47842, true }, - { 47852, false }, - { 47870, true }, - { 47883, true }, - { 47896, true }, - { 47912, true }, - { 47931, true }, - { 47946, true }, - { 47953, true }, - { 47966, true }, - { 47995, true }, - { 48017, true }, - { 48038, true }, - { 48065, true }, - { 48085, true }, - { 48093, true }, - { 48104, true }, - { 48124, true }, - { 48143, true }, - { 48159, true }, - { 48175, false }, - { 48190, true }, - { 48205, true }, - { 48224, true }, - { 48242, true }, - { 48251, true }, + { 47607, true }, + { 47632, true }, + { 47650, true }, + { 47668, true }, + { 47682, true }, + { 47691, true }, + { 47704, true }, + { 47721, true }, + { 47734, true }, + { 47750, true }, + { 47760, true }, + { 47778, false }, + { 47791, true }, + { 47807, true }, + { 47823, true }, + { 47839, true }, + { 47852, true }, + { 47865, true }, + { 47875, false }, + { 47893, true }, + { 47906, true }, + { 47919, true }, + { 47935, true }, + { 47954, true }, + { 47969, true }, + { 47976, true }, + { 47989, true }, + { 48018, true }, + { 48040, true }, + { 48061, true }, + { 48088, true }, + { 48108, true }, + { 48116, true }, + { 48127, true }, + { 48147, true }, + { 48166, true }, + { 48182, true }, + { 48198, false }, + { 48213, true }, + { 48228, true }, + { 48247, true }, { 48261, true }, - { 48277, true }, - { 48291, true }, - { 48305, true }, - { 48338, true }, - { 48352, true }, - { 48366, true }, + { 48279, true }, + { 48288, true }, + { 48298, true }, + { 48314, true }, + { 48328, true }, + { 48342, true }, { 48375, true }, - { 48386, true }, - { 48410, true }, - { 48422, true }, - { 48433, false }, - { 48446, true }, - { 48452, true }, - { 48462, true }, - { 48471, true }, - { 48485, true }, - { 48495, true }, - { 48511, true }, - { 48524, true }, - { 48536, true }, - { 48552, true }, - { 48563, true }, - { 48575, true }, - { 48590, true }, - { 48607, true }, - { 48618, true }, - { 48630, true }, - { 48646, false }, - { 48661, true }, - { 48671, true }, - { 48687, true }, - { 48699, true }, - { 48721, true }, - { 48732, true }, - { 48751, true }, - { 48774, true }, - { 48791, true }, - { 48800, false }, - { 48809, true }, - { 48820, true }, - { 48837, true }, - { 48853, true }, - { 48867, true }, - { 48881, true }, - { 48899, false }, - { 48907, true }, - { 48916, true }, - { 48929, true }, - { 48941, true }, - { 48951, true }, - { 48960, true }, - { 48968, true }, + { 48389, true }, + { 48403, true }, + { 48412, true }, + { 48423, true }, + { 48447, true }, + { 48459, true }, + { 48470, false }, + { 48483, true }, + { 48489, true }, + { 48499, true }, + { 48508, true }, + { 48522, true }, + { 48532, true }, + { 48548, true }, + { 48561, true }, + { 48573, true }, + { 48589, true }, + { 48600, true }, + { 48612, true }, + { 48627, true }, + { 48644, true }, + { 48655, true }, + { 48667, true }, + { 48683, false }, + { 48698, true }, + { 48708, true }, + { 48724, true }, + { 48736, true }, + { 48758, true }, + { 48769, true }, + { 48788, true }, + { 48811, true }, + { 48828, true }, + { 48837, false }, + { 48846, true }, + { 48857, true }, + { 48874, true }, + { 48890, true }, + { 48904, true }, + { 48918, true }, + { 48936, false }, + { 48944, true }, + { 48953, true }, + { 48966, true }, { 48978, true }, - { 48984, true }, - { 48992, true }, - { 49009, true }, + { 48988, true }, + { 48997, true }, + { 49005, true }, + { 49015, true }, { 49021, true }, - { 49030, true }, - { 49045, true }, - { 49055, true }, - { 49064, true }, - { 49076, true }, - { 49097, true }, - { 49108, true }, - { 49122, true }, - { 49139, true }, - { 49151, true }, - { 49174, true }, - { 49188, false }, - { 49204, true }, - { 49219, true }, - { 49230, true }, - { 49246, true }, - { 49257, true }, - { 49273, true }, - { 49301, true }, - { 49317, true }, - { 49329, false }, - { 49347, true }, - { 49358, true }, - { 49368, true }, - { 49389, true }, - { 49399, false }, - { 49411, true }, + { 49029, true }, + { 49046, true }, + { 49058, true }, + { 49067, true }, + { 49082, true }, + { 49092, true }, + { 49101, true }, + { 49113, true }, + { 49134, true }, + { 49145, true }, + { 49159, true }, + { 49176, true }, + { 49188, true }, + { 49211, true }, + { 49225, false }, + { 49241, true }, + { 49256, true }, + { 49267, true }, + { 49283, true }, + { 49294, true }, + { 49310, true }, + { 49338, true }, + { 49354, true }, + { 49366, false }, + { 49384, true }, + { 49395, true }, + { 49405, true }, { 49426, true }, - { 49440, true }, - { 49450, true }, - { 49465, true }, - { 49476, true }, - { 49488, true }, - { 49506, true }, - { 49519, true }, - { 49532, true }, - { 49541, true }, - { 49550, true }, - { 49562, true }, + { 49436, false }, + { 49448, true }, + { 49463, true }, + { 49477, true }, + { 49487, true }, + { 49502, true }, + { 49513, true }, + { 49525, true }, + { 49543, true }, + { 49556, true }, + { 49569, true }, { 49578, true }, - { 49591, true }, - { 49602, true }, - { 49621, true }, - { 49637, true }, - { 49652, true }, - { 49683, true }, - { 49707, true }, - { 49726, true }, - { 49746, true }, - { 49763, true }, + { 49587, true }, + { 49599, true }, + { 49615, true }, + { 49628, true }, + { 49639, true }, + { 49655, true }, + { 49674, true }, + { 49690, true }, + { 49705, true }, + { 49736, true }, + { 49760, true }, { 49779, true }, - { 49794, true }, - { 49813, true }, - { 49835, true }, + { 49799, true }, + { 49816, true }, + { 49832, true }, { 49847, true }, - { 49864, true }, - { 49879, true }, - { 49898, true }, - { 49911, true }, - { 49926, true }, - { 49941, true }, - { 49954, true }, - { 49970, true }, - { 49982, true }, - { 49995, true }, - { 50005, false }, - { 50014, true }, - { 50034, true }, - { 50049, true }, - { 50060, true }, - { 50081, true }, - { 50097, true }, - { 50121, false }, - { 50138, true }, - { 50151, true }, - { 50164, true }, - { 50177, true }, - { 50190, true }, - { 50201, true }, - { 50210, true }, - { 50228, true }, - { 50237, true }, - { 50250, true }, - { 50259, true }, - { 50275, true }, - { 50302, true }, - { 50313, true }, - { 50330, true }, - { 50343, true }, - { 50357, true }, - { 50374, true }, - { 50389, true }, - { 50412, true }, - { 50422, true }, - { 50440, true }, - { 50455, true }, - { 50480, true }, - { 50504, true }, - { 50513, true }, - { 50534, true }, - { 50554, true }, + { 49866, true }, + { 49888, true }, + { 49900, true }, + { 49917, true }, + { 49932, true }, + { 49951, true }, + { 49964, true }, + { 49979, true }, + { 49994, true }, + { 50007, true }, + { 50023, true }, + { 50035, true }, + { 50048, true }, + { 50058, false }, + { 50067, true }, + { 50087, true }, + { 50102, true }, + { 50113, true }, + { 50134, true }, + { 50150, true }, + { 50174, false }, + { 50191, true }, + { 50204, true }, + { 50217, true }, + { 50230, true }, + { 50243, true }, + { 50254, true }, + { 50263, true }, + { 50281, true }, + { 50290, true }, + { 50303, true }, + { 50312, true }, + { 50328, true }, + { 50355, true }, + { 50366, true }, + { 50383, true }, + { 50396, true }, + { 50410, true }, + { 50427, true }, + { 50442, true }, + { 50465, true }, + { 50475, true }, + { 50493, true }, + { 50508, true }, + { 50533, true }, + { 50557, true }, { 50566, true }, - { 50579, true }, - { 50593, true }, - { 50610, true }, - { 50627, false }, - { 50639, false }, - { 50652, true }, - { 50666, true }, - { 50675, true }, - { 50686, true }, - { 50706, true }, - { 50720, true }, - { 50731, true }, - { 50745, true }, - { 50762, false }, - { 50790, true }, - { 50799, true }, - { 50808, true }, - { 50818, true }, - { 50834, true }, - { 50844, true }, - { 50858, false }, - { 50872, false }, + { 50587, true }, + { 50607, true }, + { 50619, true }, + { 50632, true }, + { 50646, true }, + { 50663, true }, + { 50680, false }, + { 50692, false }, + { 50705, true }, + { 50719, true }, + { 50728, true }, + { 50739, true }, + { 50759, true }, + { 50773, true }, + { 50784, true }, + { 50798, true }, + { 50815, false }, + { 50843, true }, + { 50852, true }, + { 50861, true }, + { 50871, true }, { 50887, true }, - { 50911, true }, - { 50932, true }, - { 50954, true }, - { 50968, true }, - { 50978, true }, - { 50988, true }, - { 51000, true }, - { 51016, true }, - { 51030, true }, - { 51049, true }, - { 51065, true }, - { 51078, true }, - { 51091, true }, - { 51101, true }, - { 51120, true }, + { 50897, true }, + { 50911, false }, + { 50925, false }, + { 50940, true }, + { 50964, true }, + { 50985, true }, + { 51007, true }, + { 51021, true }, + { 51031, true }, + { 51041, true }, + { 51053, true }, + { 51069, true }, + { 51083, true }, + { 51102, true }, + { 51118, true }, + { 51131, true }, { 51144, true }, - { 51160, true }, - { 51170, true }, - { 51186, true }, - { 51205, true }, + { 51154, true }, + { 51173, true }, + { 51197, true }, + { 51213, true }, { 51223, true }, - { 51240, true }, - { 51266, true }, - { 51278, true }, - { 51298, true }, - { 51314, true }, - { 51328, true }, - { 51338, true }, - { 51353, true }, - { 51365, true }, - { 51380, true }, - { 51398, true }, - { 51417, true }, - { 51431, true }, - { 51441, true }, - { 51452, true }, - { 51471, true }, - { 51487, true }, - { 51506, true }, - { 51516, true }, - { 51535, true }, - { 51547, true }, - { 51558, true }, - { 51571, true }, - { 51595, true }, - { 51615, true }, - { 51628, false }, - { 51640, true }, - { 51652, true }, - { 51667, true }, - { 51687, true }, - { 51697, true }, - { 51707, false }, - { 51724, true }, - { 51732, true }, - { 51748, true }, - { 51763, true }, - { 51779, true }, - { 51795, true }, - { 51809, true }, - { 51821, true }, - { 51841, true }, - { 51857, true }, - { 51874, true }, - { 51884, true }, + { 51239, true }, + { 51258, true }, + { 51276, true }, + { 51293, true }, + { 51319, true }, + { 51331, true }, + { 51351, true }, + { 51367, true }, + { 51381, true }, + { 51391, true }, + { 51406, true }, + { 51418, true }, + { 51433, true }, + { 51451, true }, + { 51470, true }, + { 51484, true }, + { 51494, true }, + { 51505, true }, + { 51524, true }, + { 51540, true }, + { 51559, true }, + { 51569, true }, + { 51588, true }, + { 51600, true }, + { 51611, true }, + { 51635, true }, + { 51655, true }, + { 51668, false }, + { 51680, true }, + { 51692, true }, + { 51707, true }, + { 51727, true }, + { 51737, true }, + { 51747, false }, + { 51764, true }, + { 51772, true }, + { 51788, true }, + { 51803, true }, + { 51819, true }, + { 51835, true }, + { 51849, true }, + { 51861, true }, + { 51881, true }, { 51897, true }, - { 51911, true }, + { 51914, true }, { 51924, true }, - { 51934, true }, - { 51948, true }, - { 51960, true }, - { 51976, true }, + { 51937, true }, + { 51951, true }, + { 51964, true }, + { 51974, true }, + { 51988, true }, { 52000, true }, - { 52025, true }, - { 52038, true }, - { 52051, true }, - { 52063, true }, - { 52082, true }, - { 52095, true }, - { 52108, true }, - { 52121, true }, - { 52141, true }, - { 52156, true }, - { 52174, true }, - { 52183, true }, - { 52194, true }, - { 52205, true }, - { 52215, true }, - { 52229, true }, - { 52241, true }, - { 52251, true }, - { 52265, true }, - { 52275, true }, - { 52286, true }, - { 52298, true }, - { 52307, true }, - { 52318, false }, - { 52331, true }, + { 52016, true }, + { 52040, true }, + { 52065, true }, + { 52078, true }, + { 52091, true }, + { 52103, true }, + { 52122, true }, + { 52135, true }, + { 52148, true }, + { 52161, true }, + { 52181, true }, + { 52196, true }, + { 52214, true }, + { 52223, true }, + { 52234, true }, + { 52245, true }, + { 52255, true }, + { 52269, true }, + { 52281, true }, + { 52291, true }, + { 52305, true }, + { 52315, true }, + { 52326, true }, { 52338, true }, - { 52350, true }, - { 52366, true }, - { 52383, true }, - { 52396, false }, - { 52416, true }, - { 52428, true }, - { 52441, true }, - { 52460, true }, + { 52347, true }, + { 52358, false }, + { 52371, true }, + { 52378, true }, + { 52390, true }, + { 52406, true }, + { 52423, true }, + { 52436, false }, + { 52456, true }, + { 52468, true }, { 52481, true }, - { 52490, true }, - { 52505, true }, - { 52518, true }, - { 52529, true }, - { 52538, true }, - { 52551, true }, - { 52564, true }, - { 52573, true }, - { 52585, true }, - { 52594, true }, - { 52603, true }, - { 52622, true }, - { 52636, true }, - { 52654, true }, - { 52676, false }, - { 52701, true }, - { 52710, true }, - { 52720, true }, - { 52733, true }, - { 52745, true }, - { 52770, true }, - { 52786, true }, - { 52799, true }, - { 52813, true }, - { 52822, true }, - { 52840, true }, - { 52850, true }, - { 52868, true }, - { 52879, false }, - { 52894, true }, - { 52903, true }, - { 52912, true }, - { 52926, false }, - { 52937, true }, - { 52945, true }, - { 52953, true }, - { 52962, true }, - { 52977, true }, - { 52989, true }, - { 53003, true }, + { 52500, true }, + { 52521, true }, + { 52530, true }, + { 52545, true }, + { 52558, true }, + { 52569, true }, + { 52578, true }, + { 52591, true }, + { 52604, true }, + { 52613, true }, + { 52625, true }, + { 52634, true }, + { 52643, true }, + { 52662, true }, + { 52676, true }, + { 52694, true }, + { 52716, false }, + { 52741, true }, + { 52750, true }, + { 52760, true }, + { 52773, true }, + { 52785, true }, + { 52810, true }, + { 52826, true }, + { 52839, true }, + { 52853, true }, + { 52862, true }, + { 52880, true }, + { 52890, true }, + { 52908, true }, + { 52919, false }, + { 52934, true }, + { 52949, true }, + { 52958, true }, + { 52967, true }, + { 52981, false }, + { 52992, true }, + { 53000, true }, + { 53008, true }, { 53017, true }, - { 53029, true }, - { 53047, true }, - { 53069, true }, - { 53085, true }, - { 53099, true }, - { 53116, true }, - { 53129, true }, - { 53139, true }, - { 53153, true }, - { 53167, true }, - { 53180, true }, - { 53193, true }, - { 53206, true }, - { 53217, true }, - { 53227, true }, - { 53234, true }, - { 53243, true }, - { 53262, true }, + { 53032, true }, + { 53044, true }, + { 53058, true }, + { 53072, true }, + { 53084, true }, + { 53102, true }, + { 53118, true }, + { 53132, true }, + { 53149, true }, + { 53162, true }, + { 53172, true }, + { 53186, true }, + { 53200, true }, + { 53213, true }, + { 53226, true }, + { 53239, true }, + { 53250, true }, + { 53260, true }, + { 53267, true }, { 53276, true }, - { 53290, true }, - { 53301, true }, - { 53314, true }, - { 53330, true }, - { 53353, true }, - { 53373, true }, - { 53385, true }, - { 53400, true }, - { 53419, true }, + { 53295, true }, + { 53309, true }, + { 53323, true }, + { 53334, true }, + { 53347, true }, + { 53363, true }, + { 53386, true }, + { 53406, true }, + { 53418, true }, { 53433, true }, - { 53451, true }, - { 53469, true }, - { 53476, true }, - { 53488, true }, - { 53505, true }, - { 53524, true }, - { 53534, true }, - { 53554, true }, + { 53452, true }, + { 53466, true }, + { 53484, true }, + { 53502, true }, + { 53509, true }, + { 53521, true }, + { 53538, true }, + { 53557, true }, { 53567, true }, - { 53581, true }, - { 53598, true }, - { 53611, true }, - { 53623, true }, - { 53635, false }, - { 53650, true }, - { 53664, true }, - { 53681, true }, - { 53693, true }, - { 53712, true }, - { 53724, true }, - { 53736, true }, - { 53746, true }, + { 53587, true }, + { 53600, true }, + { 53614, true }, + { 53631, true }, + { 53644, true }, + { 53656, true }, + { 53668, false }, + { 53683, true }, + { 53697, true }, + { 53714, true }, + { 53726, true }, + { 53745, true }, { 53757, true }, - { 53771, true }, - { 53794, false }, + { 53769, true }, + { 53779, true }, + { 53790, true }, { 53804, true }, - { 53815, true }, - { 53828, true }, - { 53839, true }, + { 53827, false }, + { 53837, true }, { 53848, true }, - { 53858, true }, - { 53869, true }, + { 53861, true }, + { 53872, true }, { 53881, true }, - { 53899, true }, - { 53916, true }, - { 53930, true }, - { 53953, true }, + { 53891, true }, + { 53902, true }, + { 53914, true }, + { 53932, true }, + { 53949, true }, { 53963, true }, - { 53978, true }, - { 53991, true }, - { 53999, true }, + { 53986, true }, + { 53996, true }, { 54011, true }, - { 54025, true }, - { 54047, true }, - { 54054, true }, - { 54067, true }, + { 54024, true }, + { 54032, true }, + { 54044, true }, + { 54058, true }, + { 54080, true }, { 54087, true }, - { 54105, true }, - { 54127, true }, - { 54140, true }, - { 54151, true }, - { 54165, true }, - { 54178, true }, - { 54197, true }, - { 54213, true }, - { 54232, true }, - { 54251, true }, - { 54266, true }, - { 54278, true }, - { 54294, true }, - { 54313, true }, - { 54334, true }, - { 54353, true }, - { 54371, true }, - { 54389, true }, - { 54398, true }, - { 54421, true }, - { 54435, true }, - { 54448, true }, - { 54460, true }, - { 54471, false }, + { 54100, true }, + { 54120, true }, + { 54138, true }, + { 54160, true }, + { 54173, true }, + { 54184, true }, + { 54198, true }, + { 54211, true }, + { 54230, true }, + { 54246, true }, + { 54265, true }, + { 54284, true }, + { 54299, true }, + { 54311, true }, + { 54327, true }, + { 54346, true }, + { 54367, true }, + { 54386, true }, + { 54404, true }, + { 54422, true }, + { 54431, true }, + { 54454, true }, + { 54468, true }, { 54481, true }, - { 54501, true }, + { 54493, true }, + { 54504, false }, { 54514, true }, - { 54529, true }, - { 54538, true }, - { 54550, true }, - { 54560, true }, - { 54567, true }, - { 54576, true }, - { 54589, true }, - { 54602, true }, + { 54534, true }, + { 54547, true }, + { 54562, true }, + { 54571, true }, + { 54583, true }, + { 54593, true }, + { 54600, true }, + { 54609, true }, { 54622, true }, - { 54638, true }, - { 54654, true }, - { 54668, true }, - { 54685, true }, - { 54695, true }, - { 54722, true }, - { 54757, true }, - { 54783, false }, - { 54796, true }, - { 54809, true }, - { 54828, true }, - { 54853, true }, - { 54868, false }, - { 54878, true }, - { 54895, true }, - { 54912, true }, - { 54922, true }, - { 54932, true }, + { 54635, true }, + { 54655, true }, + { 54671, true }, + { 54687, true }, + { 54701, true }, + { 54718, true }, + { 54728, true }, + { 54755, true }, + { 54790, true }, + { 54816, false }, + { 54829, true }, + { 54842, true }, + { 54861, true }, + { 54886, true }, + { 54901, false }, + { 54911, true }, + { 54928, true }, { 54945, true }, - { 54960, true }, - { 54973, true }, - { 54988, true }, - { 55004, true }, - { 55017, true }, - { 55030, true }, - { 55044, true }, - { 55055, true }, - { 55067, true }, - { 55080, true }, - { 55099, true }, - { 55123, true }, - { 55145, true }, - { 55166, true }, - { 55191, true }, - { 55214, true }, - { 55236, true }, - { 55256, true }, - { 55267, true }, - { 55287, true }, - { 55304, true }, - { 55322, true }, - { 55345, true }, - { 55361, true }, - { 55381, true }, + { 54955, true }, + { 54965, true }, + { 54978, true }, + { 54993, true }, + { 55006, true }, + { 55021, true }, + { 55037, true }, + { 55050, true }, + { 55063, true }, + { 55077, true }, + { 55088, true }, + { 55100, true }, + { 55113, true }, + { 55132, true }, + { 55156, true }, + { 55178, true }, + { 55199, true }, + { 55224, true }, + { 55247, true }, + { 55269, true }, + { 55289, true }, + { 55300, true }, + { 55320, true }, + { 55337, true }, + { 55355, true }, + { 55378, true }, { 55394, true }, - { 55404, true }, - { 55415, true }, - { 55434, true }, - { 55444, true }, - { 55454, true }, - { 55462, true }, - { 55475, true }, - { 55488, true }, - { 55497, true }, - { 55504, false }, - { 55520, true }, - { 55537, true }, - { 55551, true }, + { 55414, true }, + { 55427, true }, + { 55437, true }, + { 55448, true }, + { 55467, true }, + { 55477, true }, + { 55487, true }, + { 55495, true }, + { 55508, true }, + { 55521, true }, + { 55530, true }, + { 55537, false }, + { 55553, true }, { 55570, true }, - { 55582, true }, - { 55605, true }, - { 55621, true }, - { 55633, true }, - { 55649, true }, + { 55584, true }, + { 55603, true }, + { 55615, true }, + { 55638, true }, + { 55654, true }, { 55666, true }, - { 55684, true }, - { 55705, true }, - { 55722, true }, - { 55739, true }, - { 55756, true }, - { 55773, true }, - { 55790, true }, - { 55807, true }, + { 55682, true }, + { 55699, true }, + { 55717, true }, + { 55738, true }, + { 55755, true }, + { 55772, true }, + { 55789, true }, + { 55806, true }, { 55823, true }, - { 55837, true }, - { 55862, true }, - { 55873, true }, - { 55889, true }, - { 55905, false }, - { 55918, true }, - { 55935, false }, + { 55840, true }, + { 55856, true }, + { 55870, true }, + { 55895, true }, + { 55906, true }, + { 55922, true }, + { 55938, false }, { 55951, true }, - { 55965, true }, - { 55975, true }, - { 55986, true }, - { 56000, true }, - { 56014, true }, - { 56024, false }, - { 56034, false }, - { 56043, true }, - { 56062, true }, - { 56072, true }, - { 56081, false }, - { 56101, true }, - { 56124, true }, - { 56141, true }, - { 56160, true }, - { 56177, true }, - { 56188, false }, - { 56200, true }, - { 56211, true }, - { 56226, true }, - { 56236, true }, + { 55968, false }, + { 55984, true }, + { 55998, true }, + { 56008, true }, + { 56019, true }, + { 56033, true }, + { 56047, true }, + { 56057, false }, + { 56067, false }, + { 56076, true }, + { 56095, true }, + { 56105, true }, + { 56114, false }, + { 56134, true }, + { 56157, true }, + { 56174, true }, + { 56193, true }, + { 56210, true }, + { 56221, false }, + { 56233, true }, { 56244, true }, - { 56258, true }, - { 56271, false }, - { 56284, true }, - { 56299, true }, - { 56313, true }, - { 56325, true }, - { 56339, true }, - { 56349, true }, - { 56365, true }, - { 56381, true }, - { 56400, false }, - { 56429, true }, - { 56443, true }, - { 56457, true }, - { 56478, true }, - { 56496, true }, + { 56259, true }, + { 56269, true }, + { 56277, true }, + { 56291, true }, + { 56304, false }, + { 56317, true }, + { 56332, true }, + { 56346, true }, + { 56358, true }, + { 56372, true }, + { 56382, true }, + { 56398, true }, + { 56414, true }, + { 56433, false }, + { 56462, true }, + { 56476, true }, + { 56490, true }, { 56511, true }, - { 56527, true }, - { 56540, true }, + { 56529, true }, + { 56544, true }, { 56560, true }, - { 56572, true }, - { 56584, true }, - { 56599, true }, - { 56623, true }, - { 56647, true }, - { 56657, true }, - { 56679, true }, - { 56711, true }, - { 56722, true }, - { 56732, true }, - { 56747, true }, - { 56761, false }, - { 56781, true }, - { 56799, true }, - { 56808, true }, - { 56815, true }, - { 56826, true }, - { 56835, true }, + { 56573, true }, + { 56593, true }, + { 56605, true }, + { 56617, true }, + { 56632, true }, + { 56656, true }, + { 56680, true }, + { 56690, true }, + { 56712, true }, + { 56744, true }, + { 56755, true }, + { 56765, true }, + { 56780, true }, + { 56794, false }, + { 56814, true }, + { 56832, true }, + { 56841, true }, { 56848, true }, - { 56871, true }, - { 56886, false }, - { 56897, false }, - { 56909, false }, - { 56920, true }, - { 56946, false }, - { 56962, true }, - { 56972, true }, - { 56980, true }, - { 56989, true }, - { 57001, true }, - { 57012, true }, - { 57024, false }, - { 57036, true }, - { 57049, true }, - { 57061, true }, - { 57078, true }, - { 57098, true }, - { 57109, true }, - { 57125, true }, - { 57137, true }, - { 57146, true }, + { 56859, true }, + { 56868, true }, + { 56881, true }, + { 56904, true }, + { 56919, false }, + { 56930, false }, + { 56942, false }, + { 56953, true }, + { 56979, false }, + { 56995, true }, + { 57005, true }, + { 57013, true }, + { 57022, true }, + { 57034, true }, + { 57045, true }, + { 57057, false }, + { 57069, true }, + { 57082, true }, + { 57094, true }, + { 57111, true }, + { 57131, true }, + { 57142, true }, + { 57158, true }, { 57170, true }, - { 57183, true }, - { 57196, true }, - { 57220, true }, - { 57234, true }, - { 57251, true }, - { 57266, true }, - { 57276, true }, - { 57288, true }, - { 57300, true }, - { 57315, true }, - { 57323, true }, - { 57335, true }, - { 57345, true }, - { 57364, true }, - { 57381, true }, - { 57398, true }, - { 57413, true }, - { 57425, true }, - { 57450, false }, - { 57463, false }, - { 57475, true }, - { 57495, true }, - { 57508, true }, - { 57521, true }, - { 57533, true }, - { 57557, true }, - { 57570, true }, - { 57589, true }, - { 57601, true }, - { 57613, true }, - { 57637, true }, - { 57658, true }, - { 57672, true }, - { 57697, true }, - { 57711, true }, - { 57724, false }, - { 57740, true }, - { 57752, true }, - { 57765, true }, - { 57777, true }, - { 57789, true }, + { 57179, true }, + { 57203, true }, + { 57216, true }, + { 57229, true }, + { 57253, true }, + { 57267, true }, + { 57284, true }, + { 57299, true }, + { 57309, true }, + { 57321, true }, + { 57333, true }, + { 57348, true }, + { 57356, true }, + { 57368, true }, + { 57387, true }, + { 57404, true }, + { 57421, true }, + { 57436, true }, + { 57448, true }, + { 57473, false }, + { 57486, false }, + { 57498, true }, + { 57518, true }, + { 57531, true }, + { 57544, true }, + { 57556, true }, + { 57580, true }, + { 57593, true }, + { 57612, true }, + { 57624, true }, + { 57636, true }, + { 57660, true }, + { 57681, true }, + { 57695, true }, + { 57720, true }, + { 57734, true }, + { 57747, false }, + { 57763, true }, + { 57775, true }, + { 57788, true }, { 57800, true }, - { 57811, true }, + { 57812, true }, { 57823, true }, - { 57832, true }, + { 57834, true }, { 57846, true }, - { 57858, true }, - { 57874, true }, - { 57896, true }, - { 57906, false }, - { 57920, true }, - { 57930, true }, - { 57943, true }, - { 57956, true }, - { 57969, true }, - { 57977, false }, - { 57994, true }, - { 58008, true }, - { 58024, false }, - { 58043, true }, - { 58062, true }, - { 58072, true }, - { 58084, true }, - { 58098, true }, - { 58106, true }, - { 58125, false }, - { 58143, true }, - { 58152, true }, - { 58165, true }, - { 58180, true }, - { 58200, false }, - { 58213, true }, - { 58230, true }, - { 58243, true }, - { 58256, true }, - { 58280, true }, - { 58307, true }, - { 58320, false }, - { 58334, true }, - { 58346, true }, - { 58359, false }, - { 58371, true }, - { 58383, true }, - { 58398, true }, - { 58416, true }, - { 58429, true }, - { 58452, false }, - { 58463, true }, - { 58479, true }, - { 58497, true }, - { 58519, true }, - { 58535, true }, - { 58552, true }, - { 58569, true }, - { 58587, true }, - { 58600, true }, - { 58617, true }, - { 58631, true }, - { 58647, true }, - { 58655, true }, - { 58674, true }, - { 58684, true }, - { 58692, true }, - { 58701, true }, - { 58716, true }, - { 58734, false }, - { 58745, true }, - { 58761, true }, - { 58775, true }, - { 58784, true }, - { 58800, true }, - { 58806, true }, + { 57860, true }, + { 57872, true }, + { 57888, true }, + { 57910, false }, + { 57924, true }, + { 57934, true }, + { 57947, true }, + { 57960, true }, + { 57973, true }, + { 57981, false }, + { 57998, true }, + { 58012, true }, + { 58028, false }, + { 58047, true }, + { 58066, true }, + { 58076, true }, + { 58088, true }, + { 58102, true }, + { 58110, true }, + { 58129, false }, + { 58147, true }, + { 58156, true }, + { 58169, true }, + { 58184, true }, + { 58204, false }, + { 58217, true }, + { 58234, true }, + { 58247, true }, + { 58260, true }, + { 58284, true }, + { 58311, true }, + { 58324, false }, + { 58338, true }, + { 58350, true }, + { 58363, false }, + { 58375, true }, + { 58387, true }, + { 58402, true }, + { 58420, true }, + { 58433, true }, + { 58456, false }, + { 58467, true }, + { 58483, true }, + { 58501, true }, + { 58523, true }, + { 58539, true }, + { 58556, true }, + { 58573, true }, + { 58591, true }, + { 58604, true }, + { 58621, true }, + { 58635, true }, + { 58651, true }, + { 58659, true }, + { 58678, true }, + { 58688, true }, + { 58696, true }, + { 58705, true }, + { 58720, true }, + { 58738, false }, + { 58749, true }, + { 58765, true }, + { 58779, true }, + { 58787, true }, + { 58796, true }, + { 58812, true }, { 58818, true }, - { 58840, true }, - { 58854, true }, - { 58869, true }, - { 58880, true }, - { 58893, true }, - { 58909, false }, - { 58922, true }, - { 58933, true }, - { 58941, true }, - { 58958, true }, - { 58967, true }, - { 58976, true }, - { 58995, true }, - { 59006, true }, - { 59022, true }, - { 59039, true }, - { 59052, true }, - { 59063, true }, - { 59080, true }, - { 59105, true }, - { 59124, true }, - { 59139, true }, - { 59151, true }, - { 59162, true }, - { 59176, true }, - { 59193, true }, - { 59213, true }, - { 59222, true }, - { 59236, true }, - { 59247, true }, - { 59267, false }, - { 59291, true }, - { 59309, false }, - { 59317, true }, - { 59335, true }, - { 59357, true }, - { 59379, true }, - { 59395, true }, - { 59407, true }, - { 59419, true }, - { 59433, true }, - { 59446, false }, - { 59463, true }, - { 59485, true }, - { 59505, true }, - { 59532, true }, - { 59551, true }, - { 59571, true }, - { 59580, false }, - { 59595, true }, - { 59610, true }, - { 59639, true }, - { 59661, true }, - { 59679, true }, - { 59693, true }, - { 59706, true }, - { 59716, true }, - { 59734, true }, - { 59753, true }, - { 59771, true }, - { 59778, false }, - { 59798, true }, - { 59807, true }, - { 59822, true }, + { 58830, true }, + { 58852, true }, + { 58866, true }, + { 58881, true }, + { 58892, true }, + { 58905, true }, + { 58921, false }, + { 58934, true }, + { 58945, true }, + { 58953, true }, + { 58970, true }, + { 58979, true }, + { 58988, true }, + { 59007, true }, + { 59018, true }, + { 59034, true }, + { 59055, true }, + { 59072, true }, + { 59085, true }, + { 59096, true }, + { 59113, true }, + { 59138, true }, + { 59157, true }, + { 59172, true }, + { 59184, true }, + { 59195, true }, + { 59209, true }, + { 59226, true }, + { 59246, true }, + { 59255, true }, + { 59269, true }, + { 59280, true }, + { 59300, false }, + { 59324, true }, + { 59342, false }, + { 59350, true }, + { 59368, true }, + { 59390, true }, + { 59412, true }, + { 59428, true }, + { 59440, true }, + { 59452, true }, + { 59466, true }, + { 59479, false }, + { 59496, true }, + { 59518, true }, + { 59538, true }, + { 59565, true }, + { 59584, true }, + { 59604, true }, + { 59613, false }, + { 59628, true }, + { 59643, true }, + { 59672, true }, + { 59694, true }, + { 59712, true }, + { 59726, true }, + { 59739, true }, + { 59749, true }, + { 59767, true }, + { 59786, true }, + { 59804, true }, + { 59811, false }, + { 59831, true }, { 59840, true }, - { 59852, true }, - { 59861, false }, - { 59871, true }, - { 59879, true }, - { 59900, true }, - { 59917, true }, - { 59928, true }, - { 59938, true }, - { 59955, true }, - { 59977, true }, - { 59992, true }, - { 60009, true }, - { 60019, true }, - { 60032, false }, - { 60047, true }, - { 60058, true }, - { 60071, true }, - { 60087, true }, - { 60098, true }, - { 60110, true }, - { 60132, true }, - { 60145, true }, - { 60156, true }, - { 60172, true }, - { 60188, true }, - { 60198, true }, - { 60210, true }, - { 60218, true }, - { 60237, true }, - { 60256, true }, - { 60269, true }, - { 60283, true }, - { 60300, true }, - { 60312, true }, - { 60326, true }, - { 60338, false }, - { 60352, true }, - { 60366, true }, - { 60388, true }, - { 60407, true }, - { 60420, true }, - { 60435, true }, - { 60450, true }, - { 60469, true }, - { 60482, true }, - { 60507, true }, - { 60530, true }, - { 60543, true }, - { 60555, true }, - { 60566, true }, - { 60580, true }, - { 60598, true }, - { 60617, true }, + { 59855, true }, + { 59873, true }, + { 59885, true }, + { 59894, false }, + { 59904, true }, + { 59912, true }, + { 59933, true }, + { 59950, true }, + { 59961, true }, + { 59971, true }, + { 59988, true }, + { 60010, true }, + { 60025, true }, + { 60042, true }, + { 60052, true }, + { 60065, false }, + { 60080, true }, + { 60091, true }, + { 60104, true }, + { 60120, true }, + { 60131, true }, + { 60143, true }, + { 60165, true }, + { 60178, true }, + { 60189, true }, + { 60205, true }, + { 60221, true }, + { 60231, true }, + { 60243, true }, + { 60251, true }, + { 60270, true }, + { 60289, true }, + { 60302, true }, + { 60316, true }, + { 60333, true }, + { 60345, true }, + { 60359, true }, + { 60371, false }, + { 60385, true }, + { 60399, true }, + { 60421, true }, + { 60440, true }, + { 60453, true }, + { 60468, true }, + { 60483, true }, + { 60502, true }, + { 60515, true }, + { 60540, true }, + { 60563, true }, + { 60576, true }, + { 60588, true }, + { 60599, true }, + { 60613, true }, { 60631, true }, - { 60644, true }, - { 60660, true }, - { 60672, true }, - { 60688, true }, - { 60701, true }, - { 60717, true }, - { 60729, true }, - { 60744, true }, - { 60759, true }, - { 60773, true }, - { 60786, true }, - { 60798, true }, - { 60808, true }, - { 60824, true }, - { 60832, true }, - { 60840, true }, - { 60853, true }, - { 60864, true }, - { 60874, true }, - { 60891, true }, - { 60909, true }, - { 60922, true }, - { 60935, true }, - { 60944, true }, - { 60962, true }, - { 60976, true }, - { 60994, true }, - { 61010, true }, - { 61019, true }, - { 61028, true }, - { 61043, true }, - { 61053, true }, + { 60650, true }, + { 60664, true }, + { 60677, true }, + { 60693, true }, + { 60705, true }, + { 60721, true }, + { 60734, true }, + { 60750, true }, + { 60762, true }, + { 60777, true }, + { 60792, true }, + { 60806, true }, + { 60819, true }, + { 60831, true }, + { 60841, true }, + { 60857, true }, + { 60865, true }, + { 60873, true }, + { 60886, true }, + { 60897, true }, + { 60907, true }, + { 60924, true }, + { 60942, true }, + { 60955, true }, + { 60964, true }, + { 60982, true }, + { 60996, true }, + { 61014, true }, + { 61030, true }, + { 61039, true }, + { 61048, true }, { 61063, true }, - { 61077, true }, - { 61089, true }, - { 61106, true }, - { 61120, true }, - { 61128, true }, - { 61136, true }, - { 61145, true }, - { 61157, true }, - { 61170, false }, - { 61178, true }, - { 61204, true }, - { 61217, true }, - { 61231, true }, - { 61241, true }, - { 61256, true }, - { 61265, true }, + { 61073, true }, + { 61083, true }, + { 61097, true }, + { 61109, true }, + { 61126, true }, + { 61140, true }, + { 61148, true }, + { 61156, true }, + { 61165, true }, + { 61177, true }, + { 61190, false }, + { 61198, true }, + { 61224, true }, + { 61237, true }, + { 61251, true }, + { 61261, true }, { 61276, true }, - { 61288, true }, - { 61301, true }, - { 61309, false }, - { 61323, true }, - { 61344, true }, - { 61369, true }, - { 61380, true }, - { 61394, true }, - { 61412, true }, - { 61423, true }, - { 61437, true }, - { 61450, true }, - { 61461, true }, - { 61480, true }, - { 61494, true }, - { 61503, true }, - { 61517, true }, - { 61528, true }, + { 61285, true }, + { 61296, true }, + { 61308, true }, + { 61321, true }, + { 61329, false }, + { 61343, true }, + { 61364, true }, + { 61389, true }, + { 61400, true }, + { 61414, true }, + { 61432, true }, + { 61443, true }, + { 61457, true }, + { 61470, true }, + { 61481, true }, + { 61500, true }, + { 61514, true }, + { 61523, true }, { 61537, true }, - { 61555, true }, - { 61574, true }, - { 61584, true }, - { 61597, true }, - { 61608, true }, + { 61548, true }, + { 61557, true }, + { 61575, true }, + { 61594, true }, + { 61604, true }, { 61617, true }, + { 61628, true }, { 61637, true }, - { 61651, true }, - { 61659, true }, - { 61666, true }, + { 61657, true }, + { 61671, true }, { 61679, true }, - { 61690, true }, - { 61704, true }, - { 61718, true }, - { 61732, true }, - { 61742, true }, + { 61686, true }, + { 61699, true }, + { 61710, true }, + { 61724, true }, + { 61738, true }, { 61752, true }, - { 61759, true }, - { 61769, true }, - { 61778, true }, - { 61793, true }, - { 61800, true }, - { 61810, true }, - { 61822, true }, - { 61833, true }, - { 61840, true }, - { 61849, true }, - { 61861, true }, - { 61870, true }, - { 61884, true }, - { 61897, true }, - { 61906, true }, - { 61918, false }, - { 61931, true }, - { 61953, true }, - { 61976, true }, - { 61990, true }, - { 62005, true }, - { 62020, true }, - { 62036, true }, - { 62054, true }, - { 62064, true }, + { 61762, true }, + { 61772, true }, + { 61779, true }, + { 61789, true }, + { 61798, true }, + { 61813, true }, + { 61820, true }, + { 61830, true }, + { 61842, true }, + { 61853, true }, + { 61860, true }, + { 61869, true }, + { 61881, true }, + { 61890, true }, + { 61904, true }, + { 61917, true }, + { 61926, true }, + { 61938, false }, + { 61951, true }, + { 61973, true }, + { 61996, true }, + { 62010, true }, + { 62025, true }, + { 62040, true }, + { 62056, true }, { 62074, true }, - { 62085, true }, - { 62103, true }, - { 62115, true }, - { 62126, true }, - { 62142, true }, - { 62159, true }, - { 62174, true }, - { 62190, true }, - { 62205, true }, - { 62221, true }, - { 62230, true }, - { 62247, true }, - { 62264, true }, - { 62282, true }, - { 62294, true }, - { 62311, true }, - { 62325, true }, - { 62339, true }, - { 62354, true }, - { 62365, true }, - { 62379, true }, - { 62393, true }, - { 62408, true }, - { 62423, true }, - { 62438, true }, - { 62460, true }, - { 62478, true }, - { 62499, true }, - { 62521, true }, - { 62533, true }, - { 62546, true }, - { 62561, true }, - { 62577, true }, - { 62591, true }, - { 62604, true }, - { 62622, false }, - { 62643, true }, - { 62661, true }, - { 62677, true }, - { 62693, true }, - { 62706, true }, - { 62721, true }, - { 62735, true }, - { 62746, true }, - { 62771, true }, - { 62787, true }, - { 62804, true }, - { 62816, true }, - { 62828, true }, - { 62841, true }, - { 62852, true }, - { 62867, true }, - { 62879, true }, - { 62890, true }, - { 62904, true }, - { 62914, true }, - { 62923, true }, - { 62930, true }, - { 62939, true }, - { 62956, true }, - { 62968, true }, - { 62977, true }, + { 62084, true }, + { 62094, true }, + { 62105, true }, + { 62123, true }, + { 62135, true }, + { 62146, true }, + { 62162, true }, + { 62179, true }, + { 62194, true }, + { 62210, true }, + { 62225, true }, + { 62241, true }, + { 62250, true }, + { 62267, true }, + { 62284, true }, + { 62302, true }, + { 62314, true }, + { 62331, true }, + { 62345, true }, + { 62359, true }, + { 62374, true }, + { 62385, true }, + { 62399, true }, + { 62413, true }, + { 62428, true }, + { 62443, true }, + { 62458, true }, + { 62480, true }, + { 62498, true }, + { 62519, true }, + { 62541, true }, + { 62553, true }, + { 62566, true }, + { 62581, true }, + { 62597, true }, + { 62611, true }, + { 62624, true }, + { 62642, false }, + { 62663, true }, + { 62681, true }, + { 62697, true }, + { 62713, true }, + { 62726, true }, + { 62741, true }, + { 62755, true }, + { 62766, true }, + { 62791, true }, + { 62807, true }, + { 62824, true }, + { 62836, true }, + { 62848, true }, + { 62861, true }, + { 62872, true }, + { 62887, true }, + { 62899, true }, + { 62910, true }, + { 62924, true }, + { 62934, true }, + { 62943, true }, + { 62950, true }, + { 62959, true }, + { 62976, true }, { 62988, true }, - { 63000, true }, - { 63007, false }, - { 63014, false }, - { 63023, true }, - { 63035, true }, - { 63047, true }, - { 63057, true }, - { 63066, true }, - { 63075, true }, - { 63082, true }, - { 63094, true }, - { 63106, true }, + { 62997, true }, + { 63008, true }, + { 63020, true }, + { 63027, false }, + { 63034, false }, + { 63043, true }, + { 63055, true }, + { 63067, true }, + { 63077, true }, + { 63086, true }, + { 63095, true }, + { 63102, true }, { 63114, true }, { 63126, true }, - { 63139, true }, - { 63153, true }, - { 63166, true }, - { 63178, true }, - { 63189, true }, - { 63204, true }, - { 63214, true }, - { 63222, true }, + { 63134, true }, + { 63146, true }, + { 63159, true }, + { 63173, true }, + { 63186, true }, + { 63198, true }, + { 63209, true }, + { 63224, true }, { 63234, true }, - { 63245, true }, - { 63257, false }, - { 63275, true }, - { 63293, true }, - { 63315, true }, - { 63337, true }, - { 63348, true }, - { 63360, true }, - { 63371, true }, - { 63387, true }, - { 63410, true }, - { 63428, true }, - { 63439, true }, - { 63457, true }, - { 63484, true }, - { 63496, true }, - { 63514, true }, - { 63528, true }, - { 63544, true }, - { 63560, true }, - { 63573, true }, - { 63587, true }, - { 63601, true }, - { 63615, true }, - { 63639, true }, - { 63667, false }, - { 63678, true }, - { 63696, true }, - { 63714, true }, - { 63738, true }, - { 63759, true }, - { 63780, true }, - { 63801, true }, - { 63815, true }, - { 63828, true }, - { 63847, true }, - { 63865, true }, - { 63875, true }, - { 63893, true }, - { 63911, true }, - { 63932, true }, - { 63945, true }, + { 63242, true }, + { 63254, true }, + { 63265, true }, + { 63277, false }, + { 63295, true }, + { 63313, true }, + { 63335, true }, + { 63357, true }, + { 63368, true }, + { 63380, true }, + { 63391, true }, + { 63407, true }, + { 63430, true }, + { 63448, true }, + { 63459, true }, + { 63477, true }, + { 63504, true }, + { 63516, true }, + { 63534, true }, + { 63548, true }, + { 63564, true }, + { 63580, true }, + { 63593, true }, + { 63607, true }, + { 63621, true }, + { 63635, true }, + { 63659, true }, + { 63687, false }, + { 63698, true }, + { 63716, true }, + { 63734, true }, + { 63758, true }, + { 63779, true }, + { 63800, true }, + { 63821, true }, + { 63835, true }, + { 63848, true }, + { 63867, true }, + { 63885, true }, + { 63895, true }, + { 63913, true }, + { 63931, true }, + { 63952, true }, { 63965, true }, - { 63975, true }, - { 63991, true }, - { 64005, true }, - { 64021, true }, - { 64032, true }, - { 64042, true }, + { 63985, true }, + { 63995, true }, + { 64011, true }, + { 64025, true }, + { 64041, true }, { 64052, true }, - { 64069, true }, - { 64083, false }, - { 64096, true }, - { 64108, true }, - { 64119, true }, - { 64136, true }, - { 64146, true }, - { 64160, true }, - { 64179, true }, - { 64197, true }, - { 64208, true }, - { 64219, true }, - { 64230, true }, - { 64241, true }, - { 64252, true }, - { 64263, true }, - { 64283, true }, - { 64296, true }, - { 64314, true }, - { 64327, true }, - { 64337, true }, - { 64352, true }, - { 64366, true }, - { 64384, true }, - { 64401, true }, - { 64418, true }, - { 64431, true }, - { 64445, true }, - { 64454, true }, - { 64473, true }, - { 64484, true }, - { 64501, true }, - { 64510, true }, - { 64524, true }, - { 64532, true }, - { 64540, true }, - { 64547, true }, - { 64559, true }, - { 64566, true }, - { 64575, true }, - { 64594, true }, - { 64609, true }, - { 64630, true }, - { 64650, true }, - { 64667, true }, - { 64683, true }, - { 64703, true }, - { 64722, true }, - { 64743, true }, - { 64756, true }, - { 64771, true }, - { 64787, false }, - { 64801, false }, - { 64814, false }, - { 64821, true }, - { 64829, true }, - { 64841, true }, - { 64851, true }, - { 64866, true }, - { 64879, true }, - { 64894, true }, - { 64916, true }, - { 64928, true }, - { 64939, true }, - { 64955, true }, - { 64971, true }, - { 64982, true }, - { 64996, true }, - { 65006, true }, - { 65013, true }, - { 65024, true }, - { 65036, false }, - { 65056, false }, - { 65072, true }, - { 65083, true }, - { 65098, true }, - { 65111, true }, - { 65124, true }, - { 65136, true }, - { 65153, false }, - { 65163, true }, - { 65174, true }, - { 65189, true }, - { 65205, true }, - { 65224, true }, - { 65238, true }, - { 65255, true }, - { 65281, true }, - { 65296, true }, - { 65311, true }, - { 65326, true }, - { 65340, true }, - { 65359, true }, - { 65384, true }, - { 65398, true }, - { 65414, true }, - { 65435, true }, - { 65469, true }, - { 65493, true }, - { 65522, false }, - { 65537, true }, - { 65553, true }, - { 65578, true }, - { 65590, true }, - { 65604, true }, - { 65613, true }, - { 65633, false }, - { 65643, true }, - { 65658, true }, - { 65666, true }, - { 65675, true }, - { 65683, true }, - { 65699, true }, - { 65721, true }, - { 65733, true }, - { 65745, true }, - { 65756, true }, - { 65766, false }, - { 65778, true }, - { 65787, true }, - { 65803, true }, - { 65819, true }, - { 65833, true }, - { 65848, true }, - { 65862, true }, - { 65877, true }, - { 65892, true }, - { 65903, false }, - { 65915, true }, - { 65924, true }, - { 65938, true }, - { 65949, true }, - { 65959, true }, - { 65976, true }, - { 65994, true }, - { 66004, true }, - { 66027, true }, - { 66041, true }, - { 66057, true }, - { 66070, true }, - { 66089, true }, - { 66102, true }, - { 66119, true }, - { 66137, true }, - { 66150, true }, - { 66164, true }, - { 66174, true }, - { 66183, true }, - { 66199, true }, - { 66206, true }, - { 66227, false }, - { 66242, true }, - { 66257, true }, - { 66274, true }, - { 66285, true }, - { 66294, true }, - { 66303, true }, - { 66315, true }, - { 66333, true }, - { 66343, true }, - { 66356, true }, - { 66367, true }, - { 66382, true }, - { 66393, true }, - { 66409, true }, - { 66419, true }, - { 66435, true }, - { 66457, true }, - { 66469, true }, - { 66482, true }, - { 66496, true }, - { 66509, true }, - { 66524, true }, - { 66540, true }, - { 66551, false }, - { 66564, true }, - { 66576, false }, - { 66589, true }, - { 66601, true }, - { 66618, true }, - { 66625, true }, - { 66641, true }, - { 66653, true }, - { 66666, true }, - { 66677, true }, - { 66697, false }, - { 66705, true }, - { 66717, true }, - { 66728, true }, - { 66747, false }, - { 66767, true }, - { 66776, true }, - { 66787, true }, - { 66818, true }, - { 66832, true }, - { 66846, true }, - { 66866, true }, - { 66885, true }, - { 66901, true }, - { 66916, true }, - { 66930, true }, - { 66952, true }, - { 66964, true }, - { 66976, true }, - { 66992, true }, - { 67003, true }, - { 67028, true }, - { 67044, true }, - { 67060, true }, - { 67076, true }, - { 67095, true }, - { 67119, true }, - { 67135, true }, - { 67151, false }, - { 67164, true }, - { 67174, true }, - { 67186, true }, - { 67198, true }, - { 67213, true }, - { 67233, true }, - { 67253, true }, - { 67274, false }, - { 67290, true }, - { 67308, true }, - { 67319, true }, - { 67334, true }, - { 67346, false }, - { 67354, true }, - { 67368, true }, - { 67382, true }, - { 67394, true }, - { 67408, true }, - { 67420, true }, - { 67434, true }, - { 67450, true }, - { 67470, true }, - { 67501, true }, - { 67532, true }, - { 67554, true }, - { 67572, true }, - { 67586, true }, - { 67608, true }, - { 67623, true }, - { 67642, true }, - { 67651, true }, - { 67666, true }, - { 67681, true }, - { 67696, true }, - { 67713, true }, - { 67726, true }, - { 67739, true }, - { 67749, true }, - { 67759, true }, - { 67782, true }, - { 67793, true }, - { 67810, true }, - { 67825, true }, - { 67832, true }, - { 67844, true }, + { 64062, true }, + { 64072, true }, + { 64089, true }, + { 64103, false }, + { 64116, true }, + { 64128, true }, + { 64139, true }, + { 64149, true }, + { 64163, true }, + { 64182, true }, + { 64200, true }, + { 64211, true }, + { 64222, true }, + { 64233, true }, + { 64244, true }, + { 64255, true }, + { 64266, true }, + { 64286, true }, + { 64299, true }, + { 64317, true }, + { 64330, true }, + { 64340, true }, + { 64355, true }, + { 64369, true }, + { 64387, true }, + { 64404, true }, + { 64421, true }, + { 64434, true }, + { 64448, true }, + { 64457, true }, + { 64476, true }, + { 64487, true }, + { 64504, true }, + { 64513, true }, + { 64527, true }, + { 64535, true }, + { 64543, true }, + { 64550, true }, + { 64562, true }, + { 64569, true }, + { 64578, true }, + { 64597, true }, + { 64612, true }, + { 64633, true }, + { 64653, true }, + { 64670, true }, + { 64686, true }, + { 64706, true }, + { 64725, true }, + { 64746, true }, + { 64759, true }, + { 64774, true }, + { 64790, false }, + { 64804, false }, + { 64817, false }, + { 64824, true }, + { 64832, true }, + { 64844, true }, + { 64854, true }, + { 64869, true }, + { 64882, true }, + { 64897, true }, + { 64919, true }, + { 64931, true }, + { 64942, true }, + { 64958, true }, + { 64974, true }, + { 64985, true }, + { 64999, true }, + { 65009, true }, + { 65016, true }, + { 65027, true }, + { 65039, false }, + { 65059, false }, + { 65075, true }, + { 65086, true }, + { 65101, true }, + { 65114, true }, + { 65127, true }, + { 65139, true }, + { 65156, false }, + { 65166, true }, + { 65177, true }, + { 65192, true }, + { 65208, true }, + { 65227, true }, + { 65241, true }, + { 65258, true }, + { 65284, true }, + { 65299, true }, + { 65314, true }, + { 65329, true }, + { 65343, true }, + { 65362, true }, + { 65387, true }, + { 65401, true }, + { 65417, true }, + { 65438, true }, + { 65472, true }, + { 65496, true }, + { 65525, false }, + { 65540, true }, + { 65556, true }, + { 65581, true }, + { 65593, true }, + { 65607, true }, + { 65616, true }, + { 65636, false }, + { 65646, true }, + { 65661, true }, + { 65669, true }, + { 65678, true }, + { 65686, true }, + { 65702, true }, + { 65724, true }, + { 65736, true }, + { 65748, true }, + { 65759, true }, + { 65769, false }, + { 65781, true }, + { 65790, true }, + { 65806, true }, + { 65822, true }, + { 65836, true }, + { 65851, true }, + { 65865, true }, + { 65880, true }, + { 65895, true }, + { 65906, false }, + { 65918, true }, + { 65927, true }, + { 65941, true }, + { 65952, true }, + { 65962, true }, + { 65979, true }, + { 65997, true }, + { 66007, true }, + { 66030, true }, + { 66044, true }, + { 66060, true }, + { 66073, true }, + { 66092, true }, + { 66105, true }, + { 66122, true }, + { 66140, true }, + { 66153, true }, + { 66167, true }, + { 66177, true }, + { 66186, true }, + { 66202, true }, + { 66209, true }, + { 66230, false }, + { 66245, true }, + { 66260, true }, + { 66277, true }, + { 66288, true }, + { 66297, true }, + { 66306, true }, + { 66318, true }, + { 66336, true }, + { 66346, true }, + { 66359, true }, + { 66370, true }, + { 66385, true }, + { 66396, true }, + { 66412, true }, + { 66422, true }, + { 66438, true }, + { 66460, true }, + { 66472, true }, + { 66485, true }, + { 66499, true }, + { 66512, true }, + { 66527, true }, + { 66543, true }, + { 66554, false }, + { 66567, true }, + { 66579, false }, + { 66592, true }, + { 66604, true }, + { 66621, true }, + { 66628, true }, + { 66644, true }, + { 66656, true }, + { 66669, true }, + { 66680, true }, + { 66700, false }, + { 66708, true }, + { 66720, true }, + { 66731, true }, + { 66750, false }, + { 66770, true }, + { 66779, true }, + { 66790, true }, + { 66821, true }, + { 66835, true }, + { 66849, true }, + { 66869, true }, + { 66888, true }, + { 66904, true }, + { 66919, true }, + { 66933, true }, + { 66955, true }, + { 66967, true }, + { 66979, true }, + { 66995, true }, + { 67006, true }, + { 67031, true }, + { 67047, true }, + { 67063, true }, + { 67079, true }, + { 67098, true }, + { 67122, true }, + { 67138, true }, + { 67154, false }, + { 67167, true }, + { 67177, true }, + { 67189, true }, + { 67201, true }, + { 67216, true }, + { 67236, true }, + { 67256, true }, + { 67277, false }, + { 67293, true }, + { 67311, true }, + { 67322, true }, + { 67337, true }, + { 67349, false }, + { 67357, true }, + { 67371, true }, + { 67385, true }, + { 67397, true }, + { 67411, true }, + { 67423, true }, + { 67437, true }, + { 67453, true }, + { 67473, true }, + { 67504, true }, + { 67535, true }, + { 67557, true }, + { 67575, true }, + { 67589, true }, + { 67611, true }, + { 67626, true }, + { 67645, true }, + { 67654, true }, + { 67669, true }, + { 67686, true }, + { 67699, true }, + { 67712, true }, + { 67722, true }, + { 67732, true }, + { 67755, true }, + { 67766, true }, + { 67783, true }, + { 67798, true }, + { 67805, true }, + { 67817, true }, + { 67830, true }, + { 67847, true }, { 67857, true }, - { 67874, true }, - { 67884, true }, - { 67893, true }, - { 67912, true }, - { 67930, true }, - { 67951, true }, - { 67971, true }, - { 67984, true }, - { 68006, true }, - { 68018, true }, - { 68034, true }, + { 67866, true }, + { 67885, true }, + { 67903, true }, + { 67924, true }, + { 67944, true }, + { 67957, true }, + { 67979, true }, + { 67991, true }, + { 68007, true }, + { 68017, true }, + { 68030, true }, { 68044, true }, - { 68057, true }, - { 68071, true }, - { 68093, true }, - { 68110, true }, - { 68124, true }, + { 68066, true }, + { 68083, true }, + { 68097, true }, + { 68105, true }, + { 68117, true }, { 68132, true }, - { 68144, true }, - { 68159, true }, - { 68169, true }, - { 68180, true }, - { 68192, true }, - { 68205, true }, - { 68216, true }, - { 68225, true }, - { 68235, true }, - { 68257, true }, - { 68275, true }, - { 68286, true }, + { 68142, true }, + { 68153, true }, + { 68165, true }, + { 68178, true }, + { 68189, true }, + { 68198, true }, + { 68208, true }, + { 68230, true }, + { 68248, true }, + { 68259, true }, + { 68274, true }, + { 68287, true }, { 68301, true }, - { 68314, true }, + { 68316, true }, { 68328, true }, - { 68343, true }, - { 68355, true }, - { 68365, true }, - { 68383, true }, - { 68394, true }, - { 68402, true }, - { 68416, true }, - { 68431, true }, - { 68444, true }, + { 68338, true }, + { 68356, true }, + { 68367, true }, + { 68375, true }, + { 68389, true }, + { 68404, true }, + { 68417, true }, + { 68428, true }, + { 68439, false }, { 68455, true }, - { 68466, false }, - { 68482, true }, - { 68495, true }, - { 68516, true }, + { 68468, true }, + { 68489, true }, + { 68504, true }, + { 68515, true }, { 68531, true }, - { 68542, true }, - { 68558, true }, - { 68579, true }, + { 68552, true }, + { 68564, true }, + { 68573, true }, { 68591, true }, { 68600, true }, - { 68618, true }, - { 68627, true }, - { 68638, true }, - { 68650, false }, - { 68668, true }, - { 68687, true }, - { 68706, true }, - { 68720, true }, - { 68740, true }, - { 68753, true }, - { 68765, true }, - { 68784, true }, - { 68801, true }, - { 68813, true }, + { 68611, false }, + { 68629, true }, + { 68648, true }, + { 68667, true }, + { 68681, true }, + { 68701, true }, + { 68714, true }, + { 68726, true }, + { 68745, true }, + { 68762, true }, + { 68774, true }, + { 68787, true }, + { 68802, true }, + { 68816, true }, { 68826, true }, - { 68841, true }, - { 68855, true }, - { 68865, true }, - { 68875, true }, - { 68885, true }, + { 68836, true }, + { 68846, true }, + { 68858, true }, + { 68867, true }, + { 68882, true }, { 68897, true }, - { 68906, true }, - { 68921, true }, - { 68936, true }, - { 68949, true }, - { 68958, true }, - { 68985, true }, - { 68993, true }, - { 69014, true }, - { 69028, true }, + { 68910, true }, + { 68919, true }, + { 68946, true }, + { 68954, true }, + { 68975, true }, + { 68989, true }, + { 68999, true }, + { 69007, true }, + { 69016, true }, + { 69025, true }, { 69038, true }, - { 69046, true }, { 69055, true }, - { 69064, true }, - { 69077, true }, - { 69094, true }, - { 69102, true }, - { 69123, true }, - { 69142, true }, - { 69154, true }, - { 69172, true }, - { 69184, true }, - { 69195, true }, - { 69204, true }, - { 69213, true }, - { 69220, true }, - { 69228, true }, - { 69242, true }, - { 69253, true }, - { 69264, true }, - { 69279, true }, - { 69290, true }, - { 69303, false }, - { 69313, true }, - { 69321, true }, - { 69335, true }, - { 69355, true }, - { 69370, true }, - { 69383, true }, - { 69395, true }, - { 69410, true }, - { 69423, true }, - { 69450, true }, - { 69464, true }, - { 69479, true }, - { 69491, true }, - { 69504, true }, - { 69521, true }, - { 69534, true }, - { 69544, true }, - { 69571, true }, - { 69587, true }, - { 69597, true }, - { 69613, true }, - { 69624, true }, - { 69635, true }, - { 69649, true }, - { 69659, true }, - { 69680, true }, - { 69688, true }, - { 69700, true }, - { 69723, true }, - { 69742, true }, - { 69750, true }, - { 69760, true }, - { 69769, true }, - { 69787, true }, - { 69819, true }, - { 69835, true }, - { 69856, true }, - { 69876, true }, - { 69889, true }, - { 69903, true }, - { 69913, true }, - { 69932, true }, - { 69950, true }, - { 69961, true }, - { 69969, true }, - { 69983, true }, - { 69995, true }, - { 70008, true }, - { 70017, true }, + { 69063, true }, + { 69084, true }, + { 69103, true }, + { 69115, true }, + { 69133, true }, + { 69145, true }, + { 69156, true }, + { 69165, true }, + { 69174, true }, + { 69181, true }, + { 69189, true }, + { 69203, true }, + { 69214, true }, + { 69225, true }, + { 69240, true }, + { 69251, true }, + { 69264, false }, + { 69274, true }, + { 69288, true }, + { 69308, true }, + { 69323, true }, + { 69336, true }, + { 69348, true }, + { 69363, true }, + { 69376, true }, + { 69403, true }, + { 69417, true }, + { 69432, true }, + { 69442, true }, + { 69455, true }, + { 69472, true }, + { 69485, true }, + { 69495, true }, + { 69522, true }, + { 69538, true }, + { 69548, true }, + { 69564, true }, + { 69575, true }, + { 69586, true }, + { 69600, true }, + { 69611, true }, + { 69621, true }, + { 69642, true }, + { 69650, true }, + { 69662, true }, + { 69685, true }, + { 69704, true }, + { 69712, true }, + { 69722, true }, + { 69731, true }, + { 69749, true }, + { 69781, true }, + { 69797, true }, + { 69818, true }, + { 69838, true }, + { 69851, true }, + { 69865, true }, + { 69875, true }, + { 69894, true }, + { 69912, true }, + { 69923, true }, + { 69931, true }, + { 69945, true }, + { 69957, true }, + { 69970, true }, + { 69979, true }, + { 69989, true }, + { 70012, true }, { 70027, true }, - { 70050, true }, - { 70065, true }, - { 70081, true }, - { 70100, true }, - { 70118, true }, - { 70132, true }, - { 70146, true }, - { 70159, true }, - { 70171, true }, - { 70185, true }, - { 70201, true }, - { 70216, true }, - { 70225, true }, - { 70238, true }, - { 70257, true }, - { 70272, true }, - { 70285, true }, - { 70301, true }, - { 70318, false }, - { 70335, true }, - { 70357, true }, - { 70379, true }, - { 70391, true }, - { 70405, false }, - { 70418, true }, - { 70427, true }, - { 70443, true }, - { 70460, true }, - { 70474, true }, + { 70043, true }, + { 70062, true }, + { 70080, true }, + { 70094, true }, + { 70108, true }, + { 70121, true }, + { 70133, true }, + { 70147, true }, + { 70163, true }, + { 70178, true }, + { 70187, true }, + { 70200, true }, + { 70219, true }, + { 70234, true }, + { 70247, true }, + { 70263, true }, + { 70280, false }, + { 70297, true }, + { 70319, true }, + { 70341, true }, + { 70353, true }, + { 70367, false }, + { 70380, true }, + { 70389, true }, + { 70405, true }, + { 70422, true }, + { 70436, true }, + { 70450, true }, + { 70462, true }, + { 70475, true }, { 70488, true }, - { 70500, true }, - { 70513, true }, - { 70526, true }, - { 70536, true }, - { 70550, true }, - { 70563, true }, - { 70585, true }, - { 70607, true }, - { 70618, true }, - { 70633, true }, - { 70644, true }, - { 70664, true }, - { 70687, true }, - { 70704, true }, - { 70723, true }, - { 70750, true }, - { 70769, true }, - { 70790, true }, - { 70809, true }, - { 70824, true }, - { 70844, false }, - { 70852, true }, - { 70863, true }, - { 70873, true }, - { 70886, true }, - { 70904, true }, - { 70920, true }, - { 70935, true }, - { 70949, true }, + { 70498, true }, + { 70512, true }, + { 70525, true }, + { 70547, true }, + { 70569, true }, + { 70580, true }, + { 70595, true }, + { 70606, true }, + { 70626, true }, + { 70649, true }, + { 70666, true }, + { 70685, true }, + { 70712, true }, + { 70731, true }, + { 70752, true }, + { 70771, true }, + { 70786, true }, + { 70806, false }, + { 70814, true }, + { 70825, true }, + { 70835, true }, + { 70848, true }, + { 70866, true }, + { 70882, true }, + { 70897, true }, + { 70911, true }, + { 70927, true }, + { 70934, true }, + { 70941, true }, + { 70952, true }, { 70965, true }, - { 70972, true }, { 70979, true }, - { 70990, true }, - { 71003, true }, - { 71017, true }, - { 71034, true }, - { 71048, true }, - { 71064, true }, - { 71075, true }, - { 71082, true }, - { 71091, false }, - { 71106, true }, - { 71134, true }, - { 71149, true }, - { 71170, true }, - { 71184, true }, - { 71205, true }, - { 71221, true }, - { 71231, true }, - { 71241, true }, - { 71254, true }, - { 71267, true }, + { 70996, true }, + { 71010, true }, + { 71026, true }, + { 71037, true }, + { 71044, true }, + { 71053, false }, + { 71068, true }, + { 71096, true }, + { 71111, true }, + { 71132, true }, + { 71146, true }, + { 71167, true }, + { 71183, true }, + { 71193, true }, + { 71203, true }, + { 71216, true }, + { 71229, true }, + { 71246, true }, + { 71265, true }, { 71284, true }, - { 71303, true }, - { 71322, true }, - { 71340, true }, - { 71351, true }, + { 71302, true }, + { 71313, true }, + { 71325, true }, + { 71337, true }, + { 71348, true }, { 71363, true }, - { 71375, true }, - { 71386, true }, - { 71401, true }, - { 71414, true }, - { 71423, true }, + { 71376, true }, + { 71385, true }, + { 71398, true }, + { 71405, false }, + { 71413, true }, + { 71421, true }, { 71436, true }, - { 71443, false }, - { 71451, true }, - { 71459, true }, - { 71474, true }, - { 71487, true }, - { 71498, false }, - { 71510, true }, - { 71534, true }, - { 71549, true }, - { 71562, true }, - { 71576, true }, - { 71584, true }, - { 71609, true }, - { 71621, true }, - { 71637, true }, - { 71646, true }, - { 71661, true }, - { 71681, true }, - { 71694, true }, - { 71710, true }, - { 71724, true }, + { 71449, true }, + { 71460, false }, + { 71472, true }, + { 71496, true }, + { 71511, true }, + { 71524, true }, + { 71538, true }, + { 71546, true }, + { 71571, true }, + { 71583, true }, + { 71599, true }, + { 71608, true }, + { 71623, true }, + { 71643, true }, + { 71656, true }, + { 71672, true }, + { 71686, true }, + { 71702, true }, + { 71722, true }, { 71740, true }, - { 71760, true }, - { 71778, true }, - { 71797, true }, - { 71814, true }, - { 71843, true }, - { 71863, true }, + { 71759, true }, + { 71776, true }, + { 71805, true }, + { 71825, true }, + { 71842, true }, + { 71858, true }, + { 71867, true }, { 71880, true }, - { 71896, true }, - { 71905, true }, - { 71918, true }, - { 71930, false }, - { 71944, true }, - { 71961, true }, - { 71981, true }, - { 71993, true }, - { 72006, true }, - { 72021, true }, - { 72032, true }, - { 72049, true }, - { 72058, true }, - { 72079, true }, - { 72094, true }, - { 72112, true }, - { 72128, true }, - { 72149, true }, - { 72163, true }, + { 71892, false }, + { 71906, true }, + { 71923, true }, + { 71943, true }, + { 71955, true }, + { 71968, true }, + { 71983, true }, + { 71994, true }, + { 72011, true }, + { 72020, true }, + { 72041, true }, + { 72056, true }, + { 72074, true }, + { 72090, true }, + { 72111, true }, + { 72125, true }, + { 72139, true }, + { 72150, true }, + { 72161, true }, { 72177, true }, - { 72188, true }, - { 72199, true }, - { 72215, true }, - { 72227, true }, + { 72189, true }, + { 72200, true }, + { 72214, true }, + { 72223, true }, { 72238, true }, - { 72252, true }, - { 72261, true }, - { 72276, true }, - { 72285, true }, - { 72293, true }, - { 72304, true }, - { 72315, true }, - { 72329, true }, - { 72344, true }, - { 72362, true }, - { 72376, true }, - { 72386, true }, - { 72396, true }, - { 72405, true }, - { 72417, true }, + { 72247, true }, + { 72255, true }, + { 72266, true }, + { 72277, true }, + { 72291, true }, + { 72306, true }, + { 72324, true }, + { 72338, true }, + { 72348, true }, + { 72358, true }, + { 72367, true }, + { 72379, true }, + { 72399, true }, + { 72422, true }, { 72437, true }, { 72460, true }, - { 72475, true }, - { 72498, true }, - { 72506, true }, - { 72519, true }, - { 72531, true }, - { 72543, true }, - { 72553, false }, - { 72562, false }, - { 72571, false }, - { 72580, true }, + { 72468, true }, + { 72481, true }, + { 72493, true }, + { 72505, true }, + { 72515, false }, + { 72524, false }, + { 72533, false }, + { 72542, true }, + { 72561, true }, + { 72584, true }, { 72599, true }, - { 72622, true }, - { 72637, true }, - { 72651, true }, - { 72664, true }, - { 72680, true }, - { 72693, true }, - { 72708, true }, - { 72724, false }, - { 72743, true }, - { 72762, true }, - { 72770, true }, - { 72784, false }, - { 72804, true }, - { 72816, true }, - { 72831, true }, + { 72613, true }, + { 72626, true }, + { 72642, true }, + { 72655, true }, + { 72670, true }, + { 72686, false }, + { 72705, true }, + { 72724, true }, + { 72732, true }, + { 72746, true }, + { 72763, false }, + { 72783, true }, + { 72795, true }, + { 72810, true }, + { 72828, true }, + { 72839, true }, { 72849, true }, - { 72860, true }, - { 72870, true }, - { 72884, true }, - { 72897, true }, - { 72912, true }, - { 72938, true }, - { 72953, true }, - { 72965, true }, - { 72990, false }, - { 72999, true }, - { 73006, true }, - { 73023, true }, - { 73037, true }, - { 73051, true }, - { 73067, true }, - { 73094, true }, - { 73108, true }, - { 73117, true }, - { 73130, true }, - { 73153, true }, - { 73173, true }, - { 73192, true }, - { 73214, false }, - { 73225, true }, - { 73239, true }, - { 73259, true }, - { 73284, true }, - { 73296, true }, - { 73318, true }, - { 73333, true }, - { 73348, true }, - { 73365, true }, - { 73380, true }, - { 73397, true }, - { 73412, true }, - { 73427, true }, - { 73439, true }, - { 73453, false }, - { 73463, true }, - { 73480, true }, - { 73491, false }, - { 73506, true }, - { 73523, true }, - { 73537, true }, - { 73550, true }, - { 73562, true }, - { 73572, true }, - { 73584, true }, - { 73599, true }, - { 73610, true }, - { 73630, true }, - { 73642, true }, - { 73654, true }, - { 73665, true }, - { 73690, true }, - { 73699, true }, - { 73707, true }, - { 73718, true }, - { 73734, false }, - { 73746, true }, - { 73761, true }, - { 73769, true }, - { 73779, true }, - { 73794, true }, - { 73808, true }, - { 73818, true }, - { 73836, true }, - { 73848, true }, - { 73876, true }, - { 73888, true }, - { 73902, true }, - { 73930, true }, - { 73944, true }, - { 73960, true }, - { 73977, true }, - { 73991, true }, - { 74008, true }, - { 74030, true }, - { 74040, true }, - { 74058, true }, - { 74077, true }, - { 74096, true }, - { 74121, true }, - { 74140, true }, - { 74154, true }, - { 74167, true }, - { 74196, true }, + { 72863, true }, + { 72876, true }, + { 72891, true }, + { 72917, true }, + { 72932, true }, + { 72944, true }, + { 72969, false }, + { 72978, true }, + { 72985, true }, + { 73002, true }, + { 73016, true }, + { 73030, true }, + { 73046, true }, + { 73073, true }, + { 73087, true }, + { 73096, true }, + { 73109, true }, + { 73132, true }, + { 73152, true }, + { 73171, true }, + { 73193, false }, + { 73204, true }, + { 73218, true }, + { 73238, true }, + { 73263, true }, + { 73275, true }, + { 73297, true }, + { 73312, true }, + { 73327, true }, + { 73344, true }, + { 73359, true }, + { 73376, true }, + { 73391, true }, + { 73406, true }, + { 73418, true }, + { 73432, false }, + { 73442, true }, + { 73459, true }, + { 73470, false }, + { 73485, true }, + { 73502, true }, + { 73516, true }, + { 73529, true }, + { 73541, true }, + { 73551, true }, + { 73563, true }, + { 73578, true }, + { 73589, true }, + { 73609, true }, + { 73621, true }, + { 73633, true }, + { 73644, true }, + { 73669, true }, + { 73678, true }, + { 73686, true }, + { 73697, true }, + { 73713, false }, + { 73725, true }, + { 73740, true }, + { 73748, true }, + { 73758, true }, + { 73773, true }, + { 73787, true }, + { 73797, true }, + { 73815, true }, + { 73827, true }, + { 73855, true }, + { 73867, true }, + { 73881, true }, + { 73909, true }, + { 73923, true }, + { 73939, true }, + { 73956, true }, + { 73970, true }, + { 73987, true }, + { 74009, true }, + { 74019, true }, + { 74037, true }, + { 74056, true }, + { 74075, true }, + { 74100, true }, + { 74119, true }, + { 74133, true }, + { 74146, true }, + { 74175, true }, + { 74205, true }, + { 74217, true }, { 74226, true }, - { 74238, true }, - { 74247, true }, + { 74239, true }, + { 74250, true }, { 74260, true }, - { 74271, true }, - { 74281, true }, - { 74298, true }, - { 74321, true }, - { 74335, true }, - { 74349, true }, - { 74373, false }, - { 74383, true }, - { 74399, true }, - { 74407, true }, - { 74426, true }, - { 74438, true }, - { 74449, true }, - { 74465, true }, - { 74479, true }, - { 74491, true }, - { 74504, true }, - { 74523, true }, - { 74534, true }, - { 74546, true }, - { 74559, true }, - { 74569, true }, - { 74582, true }, - { 74594, true }, - { 74610, true }, - { 74618, false }, - { 74626, true }, + { 74277, true }, + { 74300, true }, + { 74314, true }, + { 74328, true }, + { 74352, false }, + { 74362, true }, + { 74378, true }, + { 74386, true }, + { 74405, true }, + { 74417, true }, + { 74428, true }, + { 74444, true }, + { 74458, true }, + { 74470, true }, + { 74483, true }, + { 74502, true }, + { 74513, true }, + { 74525, true }, + { 74538, true }, + { 74548, true }, + { 74561, true }, + { 74573, true }, + { 74589, true }, + { 74597, false }, + { 74605, true }, + { 74627, true }, { 74648, true }, - { 74669, true }, - { 74693, true }, - { 74709, true }, - { 74723, true }, - { 74740, true }, - { 74752, true }, - { 74762, true }, - { 74777, true }, - { 74787, true }, - { 74810, true }, - { 74824, true }, + { 74672, true }, + { 74688, true }, + { 74702, true }, + { 74719, true }, + { 74731, true }, + { 74741, true }, + { 74756, true }, + { 74766, true }, + { 74789, true }, + { 74803, true }, + { 74818, true }, + { 74830, true }, { 74839, true }, - { 74851, true }, - { 74860, true }, - { 74873, true }, - { 74888, true }, - { 74902, true }, - { 74914, true }, - { 74929, false }, - { 74946, true }, + { 74852, true }, + { 74867, true }, + { 74881, true }, + { 74893, true }, + { 74908, false }, + { 74925, true }, + { 74936, true }, + { 74947, true }, { 74957, true }, - { 74968, true }, - { 74978, true }, - { 74992, false }, - { 75001, true }, - { 75009, true }, - { 75034, true }, - { 75043, true }, - { 75051, true }, + { 74971, false }, + { 74980, true }, + { 74988, true }, + { 75013, true }, + { 75022, true }, + { 75030, true }, + { 75038, true }, + { 75047, true }, { 75059, true }, - { 75068, true }, - { 75080, true }, - { 75092, true }, - { 75102, true }, - { 75112, true }, - { 75126, true }, - { 75138, true }, - { 75152, true }, - { 75167, true }, - { 75178, true }, - { 75186, true }, - { 75197, true }, - { 75212, true }, - { 75225, true }, - { 75232, true }, - { 75252, true }, - { 75261, true }, - { 75274, true }, - { 75291, true }, - { 75306, true }, - { 75326, true }, - { 75335, true }, + { 75071, true }, + { 75081, true }, + { 75091, true }, + { 75105, true }, + { 75117, true }, + { 75131, true }, + { 75146, true }, + { 75157, true }, + { 75165, true }, + { 75176, true }, + { 75191, true }, + { 75204, true }, + { 75211, true }, + { 75231, true }, + { 75240, true }, + { 75253, true }, + { 75270, true }, + { 75285, true }, + { 75305, true }, + { 75314, true }, + { 75323, true }, + { 75335, false }, { 75344, true }, - { 75356, false }, - { 75365, true }, - { 75375, true }, - { 75385, false }, - { 75392, true }, - { 75403, true }, - { 75416, true }, + { 75354, true }, + { 75364, false }, + { 75371, true }, + { 75382, true }, + { 75395, true }, + { 75410, true }, { 75431, true }, - { 75452, true }, - { 75459, true }, + { 75438, true }, + { 75458, true }, + { 75468, true }, { 75479, true }, - { 75489, true }, - { 75500, true }, - { 75513, true }, - { 75527, true }, - { 75536, true }, - { 75552, true }, - { 75561, false }, - { 75570, true }, - { 75578, true }, - { 75590, true }, - { 75597, true }, - { 75615, true }, - { 75627, true }, - { 75640, true }, - { 75656, true }, - { 75669, false }, - { 75678, true }, - { 75687, true }, - { 75698, true }, - { 75718, true }, - { 75733, true }, - { 75749, false }, - { 75764, true }, - { 75783, true }, - { 75794, true }, + { 75492, true }, + { 75506, true }, + { 75515, true }, + { 75531, true }, + { 75540, false }, + { 75549, true }, + { 75557, true }, + { 75569, true }, + { 75576, true }, + { 75594, true }, + { 75606, true }, + { 75619, true }, + { 75635, true }, + { 75648, false }, + { 75657, true }, + { 75666, true }, + { 75677, true }, + { 75697, true }, + { 75712, true }, + { 75728, false }, + { 75743, true }, + { 75762, true }, + { 75773, true }, + { 75790, false }, { 75811, false }, - { 75832, false }, - { 75848, false }, - { 75868, true }, - { 75880, true }, - { 75903, true }, - { 75915, true }, - { 75928, true }, + { 75827, false }, + { 75847, true }, + { 75859, true }, + { 75882, true }, + { 75894, true }, + { 75907, true }, + { 75919, true }, + { 75930, true }, { 75940, true }, - { 75951, true }, - { 75961, true }, - { 75970, true }, - { 75981, true }, - { 75999, true }, - { 76026, true }, - { 76036, true }, - { 76050, true }, + { 75949, true }, + { 75960, true }, + { 75978, true }, + { 76005, true }, + { 76015, true }, + { 76029, true }, + { 76044, true }, + { 76054, true }, { 76065, true }, - { 76075, true }, - { 76086, true }, - { 76095, true }, - { 76109, true }, - { 76128, true }, - { 76141, true }, - { 76151, true }, - { 76159, true }, - { 76166, true }, - { 76179, true }, - { 76189, true }, - { 76198, false }, + { 76074, true }, + { 76088, true }, + { 76107, true }, + { 76120, true }, + { 76130, true }, + { 76138, true }, + { 76145, true }, + { 76158, true }, + { 76168, true }, + { 76177, false }, + { 76187, true }, + { 76196, true }, { 76208, true }, - { 76217, true }, - { 76229, true }, - { 76239, false }, - { 76256, true }, - { 76265, true }, - { 76275, true }, - { 76283, true }, - { 76293, true }, - { 76303, true }, + { 76218, false }, + { 76235, true }, + { 76245, true }, + { 76253, true }, + { 76263, true }, + { 76273, true }, + { 76288, true }, + { 76300, true }, { 76316, true }, - { 76331, true }, - { 76343, true }, - { 76359, true }, - { 76373, true }, - { 76380, true }, - { 76392, true }, - { 76408, true }, - { 76422, true }, + { 76330, true }, + { 76337, true }, + { 76349, true }, + { 76365, true }, + { 76379, true }, + { 76390, true }, + { 76399, true }, + { 76411, true }, + { 76421, true }, { 76433, true }, - { 76442, true }, - { 76454, true }, - { 76464, true }, + { 76443, true }, + { 76461, true }, { 76476, true }, - { 76486, true }, - { 76504, true }, - { 76519, true }, - { 76532, true }, - { 76539, true }, - { 76556, true }, - { 76567, true }, - { 76577, true }, - { 76587, true }, - { 76596, true }, - { 76618, true }, - { 76637, true }, - { 76651, true }, - { 76666, true }, - { 76690, true }, - { 76712, true }, - { 76726, true }, - { 76739, true }, - { 76753, true }, - { 76764, true }, - { 76773, true }, - { 76784, true }, - { 76803, true }, - { 76817, true }, - { 76828, true }, - { 76840, true }, - { 76859, true }, - { 76872, true }, - { 76881, true }, - { 76896, true }, - { 76909, true }, - { 76921, true }, - { 76934, true }, - { 76942, true }, - { 76954, true }, - { 76963, true }, - { 76978, true }, - { 76987, true }, - { 76999, true }, - { 77009, true }, - { 77024, true }, - { 77032, true }, - { 77047, true }, - { 77058, true }, - { 77069, true }, - { 77078, true }, - { 77092, true }, - { 77106, true }, - { 77129, true }, - { 77154, true }, - { 77173, true }, - { 77187, true }, - { 77203, true }, - { 77217, true }, - { 77233, true }, - { 77251, true }, - { 77268, true }, - { 77283, true }, - { 77292, true }, - { 77305, true }, - { 77322, true }, - { 77335, true }, - { 77345, true }, - { 77356, true }, - { 77367, true }, - { 77377, true }, - { 77389, true }, - { 77410, true }, - { 77424, false }, - { 77444, false }, - { 77456, true }, - { 77469, true }, - { 77479, true }, - { 77492, true }, - { 77505, true }, - { 77521, true }, - { 77538, true }, - { 77550, true }, - { 77570, true }, - { 77584, true }, - { 77598, true }, - { 77614, true }, - { 77626, true }, - { 77647, false }, - { 77661, true }, - { 77679, true }, - { 77691, true }, - { 77711, true }, - { 77727, true }, - { 77749, true }, - { 77771, true }, - { 77790, true }, - { 77807, true }, - { 77819, true }, - { 77832, true }, - { 77857, true }, - { 77870, false }, + { 76489, true }, + { 76496, true }, + { 76513, true }, + { 76524, true }, + { 76534, true }, + { 76544, true }, + { 76553, true }, + { 76575, true }, + { 76594, true }, + { 76608, true }, + { 76623, true }, + { 76647, true }, + { 76669, true }, + { 76683, true }, + { 76696, true }, + { 76710, true }, + { 76721, true }, + { 76730, true }, + { 76741, true }, + { 76760, true }, + { 76774, true }, + { 76785, true }, + { 76797, true }, + { 76816, true }, + { 76829, true }, + { 76838, true }, + { 76853, true }, + { 76869, true }, + { 76882, true }, + { 76894, true }, + { 76907, true }, + { 76915, true }, + { 76927, true }, + { 76936, true }, + { 76951, true }, + { 76960, true }, + { 76972, true }, + { 76982, true }, + { 76997, true }, + { 77005, true }, + { 77020, true }, + { 77031, true }, + { 77042, true }, + { 77051, true }, + { 77065, true }, + { 77079, true }, + { 77102, true }, + { 77127, true }, + { 77146, true }, + { 77160, true }, + { 77176, true }, + { 77190, true }, + { 77206, true }, + { 77224, true }, + { 77241, true }, + { 77256, true }, + { 77265, true }, + { 77278, true }, + { 77295, true }, + { 77308, true }, + { 77318, true }, + { 77329, true }, + { 77340, true }, + { 77350, true }, + { 77362, true }, + { 77383, true }, + { 77397, false }, + { 77417, false }, + { 77429, true }, + { 77442, true }, + { 77452, true }, + { 77465, true }, + { 77478, true }, + { 77494, true }, + { 77511, true }, + { 77523, true }, + { 77543, true }, + { 77557, true }, + { 77571, true }, + { 77587, true }, + { 77599, true }, + { 77620, false }, + { 77634, true }, + { 77652, true }, + { 77664, true }, + { 77684, true }, + { 77700, true }, + { 77722, true }, + { 77744, true }, + { 77763, true }, + { 77780, true }, + { 77792, true }, + { 77805, true }, + { 77830, true }, + { 77843, false }, + { 77856, true }, + { 77867, true }, { 77883, true }, - { 77894, true }, - { 77910, true }, - { 77925, true }, - { 77945, true }, - { 77970, true }, - { 77986, true }, - { 78003, true }, + { 77898, true }, + { 77918, true }, + { 77943, true }, + { 77959, true }, + { 77976, true }, + { 77987, true }, + { 78001, true }, { 78014, true }, - { 78028, true }, - { 78041, true }, - { 78054, true }, - { 78066, true }, - { 78083, true }, - { 78095, false }, - { 78104, false }, - { 78114, true }, - { 78125, true }, - { 78138, false }, - { 78151, true }, - { 78162, true }, - { 78176, true }, - { 78199, true }, - { 78213, true }, - { 78228, true }, - { 78241, true }, - { 78260, true }, - { 78272, true }, - { 78288, true }, - { 78304, true }, - { 78321, true }, - { 78334, true }, - { 78346, true }, + { 78027, true }, + { 78039, true }, + { 78056, true }, + { 78068, false }, + { 78077, false }, + { 78087, true }, + { 78098, true }, + { 78111, false }, + { 78124, true }, + { 78135, true }, + { 78149, true }, + { 78172, true }, + { 78186, true }, + { 78201, true }, + { 78214, true }, + { 78233, true }, + { 78245, true }, + { 78261, true }, + { 78277, true }, + { 78294, true }, + { 78307, true }, + { 78319, true }, + { 78332, true }, + { 78344, true }, { 78359, true }, - { 78371, true }, - { 78386, true }, - { 78403, true }, + { 78376, true }, + { 78385, true }, { 78412, true }, - { 78439, true }, - { 78460, true }, - { 78477, true }, - { 78488, false }, - { 78506, true }, - { 78518, true }, - { 78530, true }, - { 78542, true }, - { 78561, true }, - { 78587, true }, - { 78610, true }, - { 78627, true }, - { 78640, true }, - { 78652, true }, - { 78669, false }, - { 78688, true }, - { 78706, true }, - { 78737, true }, - { 78752, true }, - { 78771, true }, - { 78793, true }, - { 78805, true }, - { 78822, true }, - { 78839, true }, + { 78433, true }, + { 78450, true }, + { 78461, false }, + { 78479, true }, + { 78491, true }, + { 78503, true }, + { 78515, true }, + { 78534, true }, + { 78560, true }, + { 78583, true }, + { 78600, true }, + { 78613, true }, + { 78625, true }, + { 78642, false }, + { 78661, true }, + { 78679, true }, + { 78710, true }, + { 78725, true }, + { 78744, true }, + { 78766, true }, + { 78778, true }, + { 78795, true }, + { 78812, true }, + { 78831, true }, + { 78843, true }, { 78858, true }, - { 78870, true }, - { 78885, true }, - { 78902, true }, - { 78919, true }, - { 78935, true }, - { 78951, true }, - { 78975, true }, - { 79000, true }, + { 78875, true }, + { 78892, true }, + { 78908, true }, + { 78924, true }, + { 78948, true }, + { 78973, true }, + { 78995, true }, { 79022, true }, - { 79049, true }, - { 79067, true }, - { 79084, true }, - { 79099, true }, - { 79117, true }, - { 79138, true }, - { 79166, true }, - { 79190, true }, - { 79214, true }, - { 79227, true }, - { 79240, true }, - { 79257, true }, - { 79272, true }, - { 79297, false }, - { 79311, true }, - { 79321, true }, - { 79340, true }, - { 79356, true }, - { 79380, true }, + { 79040, true }, + { 79057, true }, + { 79072, true }, + { 79090, true }, + { 79111, true }, + { 79139, true }, + { 79163, true }, + { 79187, true }, + { 79200, true }, + { 79213, true }, + { 79230, true }, + { 79245, true }, + { 79270, false }, + { 79284, true }, + { 79294, true }, + { 79313, true }, + { 79329, true }, + { 79353, true }, + { 79368, true }, + { 79385, true }, { 79395, true }, - { 79412, true }, - { 79422, true }, - { 79434, true }, - { 79447, true }, + { 79407, true }, + { 79420, true }, + { 79438, true }, + { 79451, true }, { 79465, true }, { 79478, true }, - { 79492, true }, - { 79505, true }, - { 79518, true }, - { 79537, true }, - { 79555, true }, - { 79569, true }, - { 79579, false }, - { 79591, true }, - { 79599, true }, - { 79609, true }, - { 79619, true }, - { 79631, true }, - { 79645, false }, + { 79494, true }, + { 79507, true }, + { 79526, true }, + { 79544, true }, + { 79558, true }, + { 79568, false }, + { 79580, true }, + { 79588, true }, + { 79598, true }, + { 79608, true }, + { 79620, true }, + { 79634, false }, + { 79647, true }, { 79658, true }, - { 79666, true }, - { 79677, true }, - { 79693, true }, - { 79705, true }, - { 79721, true }, - { 79728, true }, - { 79736, true }, - { 79746, true }, - { 79758, true }, - { 79772, true }, - { 79781, true }, - { 79797, true }, - { 79807, false }, - { 79825, true }, - { 79837, true }, - { 79849, false }, - { 79860, true }, - { 79873, true }, - { 79883, true }, - { 79893, true }, - { 79903, true }, - { 79913, true }, + { 79674, true }, + { 79686, true }, + { 79702, true }, + { 79709, true }, + { 79717, true }, + { 79727, true }, + { 79739, true }, + { 79753, true }, + { 79762, true }, + { 79778, true }, + { 79788, false }, + { 79806, true }, + { 79818, true }, + { 79830, false }, + { 79841, true }, + { 79854, true }, + { 79864, true }, + { 79874, true }, + { 79884, true }, + { 79894, true }, + { 79904, true }, { 79923, true }, - { 79942, true }, - { 79951, true }, - { 79962, true }, - { 79971, true }, - { 79987, true }, - { 80003, true }, - { 80020, true }, - { 80031, true }, + { 79932, true }, + { 79943, true }, + { 79952, true }, + { 79968, true }, + { 79984, true }, + { 80001, true }, + { 80012, true }, + { 80027, true }, + { 80037, true }, { 80046, true }, - { 80056, true }, - { 80065, true }, - { 80082, true }, - { 80091, true }, - { 80109, true }, - { 80125, true }, - { 80153, true }, - { 80162, true }, - { 80177, true }, - { 80194, true }, + { 80063, true }, + { 80072, true }, + { 80090, true }, + { 80106, true }, + { 80134, true }, + { 80143, true }, + { 80158, true }, + { 80175, true }, + { 80198, true }, { 80217, true }, - { 80236, true }, - { 80254, true }, - { 80269, true }, - { 80283, true }, - { 80306, true }, - { 80322, true }, - { 80338, true }, - { 80346, true }, - { 80358, true }, - { 80375, true }, - { 80392, true }, - { 80410, true }, - { 80424, true }, - { 80438, true }, - { 80450, true }, + { 80235, true }, + { 80250, true }, + { 80264, true }, + { 80287, true }, + { 80303, true }, + { 80319, true }, + { 80327, true }, + { 80339, true }, + { 80356, true }, + { 80373, true }, + { 80391, true }, + { 80405, true }, + { 80419, true }, + { 80431, true }, + { 80449, true }, { 80468, true }, - { 80487, true }, - { 80498, true }, - { 80509, true }, - { 80527, true }, - { 80540, true }, - { 80551, true }, - { 80563, true }, - { 80574, true }, + { 80479, true }, + { 80490, true }, + { 80508, true }, + { 80521, true }, + { 80532, true }, + { 80544, true }, + { 80555, true }, + { 80566, true }, + { 80576, true }, { 80585, true }, - { 80595, true }, { 80604, true }, - { 80623, true }, - { 80636, true }, + { 80617, true }, + { 80630, true }, { 80649, true }, - { 80668, true }, - { 80685, true }, - { 80710, true }, - { 80742, true }, - { 80756, true }, - { 80768, true }, - { 80792, true }, - { 80815, true }, - { 80840, true }, + { 80666, true }, + { 80691, true }, + { 80723, true }, + { 80737, true }, + { 80749, true }, + { 80773, true }, + { 80796, true }, + { 80821, true }, + { 80834, true }, { 80853, true }, - { 80872, true }, - { 80886, true }, - { 80899, true }, - { 80914, false }, - { 80934, true }, - { 80947, true }, - { 80964, true }, - { 80979, true }, - { 80996, true }, - { 81005, true }, - { 81021, true }, + { 80867, true }, + { 80880, true }, + { 80895, false }, + { 80915, true }, + { 80928, true }, + { 80945, true }, + { 80960, true }, + { 80977, true }, + { 80986, true }, + { 81002, true }, + { 81022, true }, { 81041, true }, - { 81060, true }, - { 81069, true }, - { 81080, true }, - { 81089, true }, - { 81100, true }, - { 81113, true }, - { 81122, true }, - { 81135, true }, - { 81145, true }, - { 81158, true }, - { 81169, true }, - { 81180, true }, - { 81194, true }, - { 81211, true }, - { 81228, true }, - { 81237, true }, - { 81252, true }, - { 81264, true }, - { 81277, true }, - { 81289, true }, - { 81302, true }, - { 81311, true }, - { 81325, true }, - { 81348, true }, - { 81360, true }, - { 81371, true }, - { 81388, true }, - { 81402, true }, - { 81419, true }, - { 81440, true }, - { 81451, true }, - { 81462, true }, - { 81469, true }, - { 81480, true }, - { 81487, true }, - { 81497, true }, - { 81509, true }, - { 81518, true }, - { 81531, true }, - { 81543, true }, - { 81560, true }, - { 81574, true }, - { 81588, true }, + { 81050, true }, + { 81061, true }, + { 81070, true }, + { 81081, true }, + { 81094, true }, + { 81103, true }, + { 81116, true }, + { 81126, true }, + { 81139, true }, + { 81150, true }, + { 81161, true }, + { 81170, true }, + { 81184, true }, + { 81201, true }, + { 81218, true }, + { 81227, true }, + { 81242, true }, + { 81254, true }, + { 81267, true }, + { 81279, true }, + { 81292, true }, + { 81301, true }, + { 81315, true }, + { 81338, true }, + { 81350, true }, + { 81361, true }, + { 81378, true }, + { 81395, true }, + { 81416, true }, + { 81427, true }, + { 81438, true }, + { 81445, true }, + { 81456, true }, + { 81463, true }, + { 81473, true }, + { 81485, true }, + { 81494, true }, + { 81507, true }, + { 81519, true }, + { 81536, true }, + { 81550, true }, + { 81564, true }, + { 81571, true }, + { 81578, true }, + { 81587, true }, { 81595, true }, - { 81602, true }, - { 81611, true }, - { 81619, true }, - { 81629, true }, - { 81647, true }, - { 81661, true }, - { 81673, true }, - { 81684, true }, + { 81605, true }, + { 81623, true }, + { 81637, true }, + { 81649, true }, + { 81660, true }, + { 81671, true }, + { 81682, true }, { 81695, true }, { 81706, true }, - { 81719, true }, - { 81730, true }, - { 81739, false }, - { 81751, true }, - { 81761, true }, - { 81778, true }, - { 81789, true }, - { 81796, true }, - { 81803, true }, - { 81817, true }, - { 81825, true }, - { 81832, true }, - { 81843, true }, - { 81856, true }, - { 81871, true }, - { 81884, true }, - { 81893, true }, - { 81912, false }, + { 81715, false }, + { 81727, true }, + { 81737, true }, + { 81754, true }, + { 81765, true }, + { 81772, true }, + { 81779, true }, + { 81793, true }, + { 81801, true }, + { 81808, true }, + { 81819, true }, + { 81829, true }, + { 81842, true }, + { 81857, true }, + { 81870, true }, + { 81879, true }, + { 81898, false }, + { 81910, true }, { 81924, true }, - { 81938, true }, - { 81951, true }, - { 81966, true }, - { 81985, true }, - { 81998, true }, - { 82013, true }, - { 82026, true }, - { 82036, true }, - { 82049, true }, - { 82066, true }, - { 82080, false }, + { 81937, true }, + { 81952, true }, + { 81971, true }, + { 81984, true }, + { 81999, true }, + { 82012, true }, + { 82022, true }, + { 82035, true }, + { 82052, true }, + { 82066, false }, + { 82085, true }, { 82099, true }, - { 82113, true }, - { 82129, true }, - { 82145, true }, - { 82165, true }, - { 82181, true }, - { 82196, true }, - { 82205, true }, - { 82224, true }, - { 82241, false }, - { 82257, true }, - { 82268, true }, - { 82288, true }, - { 82301, true }, - { 82315, false }, - { 82328, true }, - { 82344, true }, - { 82361, true }, - { 82376, true }, - { 82399, true }, - { 82412, true }, - { 82429, true }, - { 82444, true }, + { 82115, true }, + { 82131, true }, + { 82151, true }, + { 82167, true }, + { 82182, true }, + { 82191, true }, + { 82210, true }, + { 82227, false }, + { 82243, true }, + { 82254, true }, + { 82274, true }, + { 82287, true }, + { 82301, false }, + { 82314, true }, + { 82330, true }, + { 82347, true }, + { 82362, true }, + { 82385, true }, + { 82398, true }, + { 82415, true }, + { 82430, true }, + { 82447, true }, { 82461, true }, - { 82475, true }, - { 82490, true }, - { 82499, true }, - { 82514, true }, + { 82476, true }, + { 82485, true }, + { 82500, true }, + { 82518, true }, { 82532, true }, - { 82546, true }, - { 82556, true }, + { 82542, true }, + { 82557, true }, { 82571, true }, - { 82585, true }, - { 82598, true }, + { 82584, true }, + { 82595, true }, { 82609, true }, - { 82623, true }, - { 82633, true }, + { 82619, true }, + { 82637, true }, { 82651, true }, - { 82665, true }, - { 82677, true }, - { 82696, false }, - { 82711, true }, - { 82730, true }, - { 82743, true }, - { 82760, true }, - { 82777, true }, - { 82794, true }, - { 82812, true }, - { 82834, true }, - { 82853, true }, - { 82869, true }, - { 82884, true }, - { 82892, true }, + { 82663, true }, + { 82682, false }, + { 82697, true }, + { 82716, true }, + { 82729, true }, + { 82746, true }, + { 82763, true }, + { 82780, true }, + { 82798, true }, + { 82820, true }, + { 82839, true }, + { 82855, true }, + { 82870, true }, + { 82878, true }, + { 82891, true }, { 82905, true }, { 82919, true }, - { 82933, true }, - { 82949, true }, - { 82960, true }, - { 82970, true }, - { 82988, true }, - { 83006, true }, - { 83019, true }, - { 83035, true }, - { 83048, true }, - { 83060, true }, - { 83071, true }, - { 83083, true }, - { 83093, true }, - { 83101, true }, - { 83117, true }, - { 83133, true }, - { 83145, true }, - { 83158, true }, - { 83172, true }, - { 83191, true }, - { 83205, true }, - { 83218, true }, - { 83234, false }, - { 83251, true }, - { 83272, true }, - { 83291, true }, - { 83310, true }, - { 83329, false }, - { 83345, true }, - { 83360, true }, - { 83370, true }, - { 83380, true }, - { 83389, true }, - { 83402, true }, - { 83412, false }, - { 83430, true }, - { 83452, true }, - { 83469, true }, - { 83485, false }, - { 83503, true }, + { 82935, true }, + { 82946, true }, + { 82956, true }, + { 82974, true }, + { 82992, true }, + { 83005, true }, + { 83021, true }, + { 83033, true }, + { 83044, true }, + { 83056, true }, + { 83066, true }, + { 83074, true }, + { 83090, true }, + { 83106, true }, + { 83115, true }, + { 83127, true }, + { 83140, true }, + { 83154, true }, + { 83173, true }, + { 83187, true }, + { 83200, true }, + { 83216, false }, + { 83233, true }, + { 83254, true }, + { 83273, true }, + { 83292, true }, + { 83311, false }, + { 83327, true }, + { 83342, true }, + { 83352, true }, + { 83362, true }, + { 83371, true }, + { 83384, true }, + { 83394, false }, + { 83412, true }, + { 83434, true }, + { 83451, true }, + { 83467, false }, + { 83485, true }, + { 83496, true }, { 83514, true }, - { 83532, true }, - { 83547, true }, - { 83561, true }, + { 83529, true }, + { 83543, true }, + { 83560, true }, { 83578, true }, - { 83596, true }, - { 83612, true }, - { 83629, true }, + { 83594, true }, + { 83611, true }, + { 83627, true }, { 83645, true }, - { 83663, true }, - { 83680, true }, - { 83702, true }, - { 83719, true }, - { 83735, true }, - { 83747, true }, + { 83662, true }, + { 83684, true }, + { 83701, true }, + { 83717, true }, + { 83729, true }, + { 83741, true }, + { 83751, true }, { 83759, true }, - { 83769, true }, - { 83777, true }, - { 83790, true }, - { 83805, true }, - { 83820, true }, - { 83832, true }, - { 83841, true }, - { 83851, true }, - { 83861, true }, - { 83875, true }, - { 83883, true }, - { 83892, true }, - { 83902, true }, - { 83911, false }, - { 83921, true }, - { 83937, true }, - { 83950, true }, - { 83957, true }, - { 83970, true }, - { 83983, true }, - { 83996, true }, - { 84011, true }, - { 84023, true }, - { 84030, true }, + { 83772, true }, + { 83787, true }, + { 83802, true }, + { 83814, true }, + { 83823, true }, + { 83833, true }, + { 83843, true }, + { 83857, true }, + { 83865, true }, + { 83874, true }, + { 83884, true }, + { 83893, false }, + { 83903, true }, + { 83919, true }, + { 83932, true }, + { 83939, true }, + { 83952, true }, + { 83965, true }, + { 83978, true }, + { 83993, true }, + { 84005, true }, + { 84012, true }, + { 84019, true }, + { 84028, true }, { 84037, true }, { 84046, true }, - { 84055, true }, - { 84064, true }, - { 84075, true }, - { 84089, true }, - { 84102, true }, - { 84110, true }, - { 84122, true }, - { 84136, true }, - { 84147, true }, - { 84163, true }, - { 84177, true }, - { 84192, true }, - { 84202, false }, - { 84216, true }, - { 84226, true }, - { 84241, true }, - { 84256, false }, - { 84272, true }, - { 84291, true }, - { 84303, true }, - { 84316, true }, - { 84335, true }, - { 84348, true }, - { 84364, true }, - { 84378, true }, - { 84393, true }, - { 84410, true }, - { 84427, true }, - { 84437, true }, - { 84452, true }, - { 84466, true }, - { 84479, true }, - { 84495, true }, - { 84509, true }, - { 84524, true }, - { 84538, true }, - { 84553, true }, - { 84572, true }, + { 84057, true }, + { 84071, true }, + { 84084, true }, + { 84092, true }, + { 84104, true }, + { 84118, true }, + { 84129, true }, + { 84145, true }, + { 84159, true }, + { 84174, true }, + { 84184, false }, + { 84198, true }, + { 84208, true }, + { 84223, true }, + { 84238, false }, + { 84254, true }, + { 84273, true }, + { 84285, true }, + { 84298, true }, + { 84317, true }, + { 84330, true }, + { 84346, true }, + { 84360, true }, + { 84377, true }, + { 84394, true }, + { 84404, true }, + { 84419, true }, + { 84433, true }, + { 84446, true }, + { 84462, true }, + { 84476, true }, + { 84491, true }, + { 84505, true }, + { 84520, true }, + { 84539, true }, + { 84554, true }, + { 84569, true }, { 84587, true }, - { 84602, true }, - { 84620, true }, - { 84639, true }, - { 84652, true }, - { 84665, true }, - { 84688, true }, - { 84704, true }, - { 84715, true }, - { 84730, true }, - { 84745, true }, - { 84761, true }, + { 84606, true }, + { 84619, true }, + { 84632, true }, + { 84655, true }, + { 84671, true }, + { 84682, true }, + { 84697, true }, + { 84712, true }, + { 84728, true }, + { 84743, true }, + { 84759, true }, { 84776, true }, - { 84792, true }, - { 84809, true }, - { 84821, true }, - { 84831, true }, - { 84849, true }, - { 84859, true }, - { 84870, true }, - { 84880, true }, - { 84898, true }, - { 84911, true }, - { 84939, true }, - { 84950, true }, - { 84961, true }, - { 84972, true }, - { 84989, true }, - { 85003, false }, - { 85020, true }, - { 85029, true }, - { 85046, true }, - { 85063, true }, - { 85072, true }, - { 85084, true }, - { 85098, true }, - { 85110, true }, - { 85126, true }, - { 85152, true }, - { 85162, true }, - { 85175, true }, - { 85185, true }, - { 85198, true }, + { 84788, true }, + { 84798, true }, + { 84816, true }, + { 84826, true }, + { 84837, true }, + { 84847, true }, + { 84860, true }, + { 84888, true }, + { 84899, true }, + { 84910, true }, + { 84921, true }, + { 84938, true }, + { 84952, false }, + { 84969, true }, + { 84978, true }, + { 84995, true }, + { 85012, true }, + { 85024, true }, + { 85038, true }, + { 85050, true }, + { 85066, true }, + { 85092, true }, + { 85102, true }, + { 85115, true }, + { 85125, true }, + { 85138, true }, + { 85146, true }, + { 85157, true }, + { 85172, true }, + { 85190, true }, { 85206, true }, - { 85217, true }, - { 85232, true }, - { 85250, true }, - { 85266, true }, - { 85274, true }, - { 85288, true }, - { 85305, true }, - { 85325, true }, - { 85335, true }, - { 85351, true }, - { 85364, true }, - { 85374, false }, - { 85388, true }, - { 85399, true }, - { 85415, true }, - { 85423, true }, - { 85438, true }, - { 85454, true }, - { 85473, true }, - { 85486, true }, - { 85506, true }, - { 85521, true }, - { 85539, true }, - { 85552, true }, - { 85562, true }, - { 85579, true }, - { 85594, true }, - { 85605, true }, - { 85616, true }, - { 85629, true }, - { 85637, true }, - { 85646, true }, - { 85657, true }, - { 85671, true }, - { 85694, true }, - { 85707, true }, - { 85719, true }, - { 85730, true }, - { 85744, true }, - { 85772, true }, - { 85787, true }, - { 85802, true }, - { 85822, true }, - { 85835, true }, - { 85851, true }, - { 85866, true }, - { 85879, true }, - { 85893, true }, - { 85904, true }, - { 85915, true }, - { 85927, true }, - { 85944, true }, - { 85957, true }, - { 85972, true }, - { 85980, true }, - { 86000, true }, - { 86011, true }, - { 86021, true }, - { 86031, true }, + { 85214, true }, + { 85228, true }, + { 85245, true }, + { 85265, true }, + { 85275, true }, + { 85291, true }, + { 85304, true }, + { 85314, false }, + { 85328, true }, + { 85339, true }, + { 85355, true }, + { 85363, true }, + { 85378, true }, + { 85394, true }, + { 85413, true }, + { 85426, true }, + { 85446, true }, + { 85461, true }, + { 85479, true }, + { 85492, true }, + { 85502, true }, + { 85519, true }, + { 85534, true }, + { 85545, true }, + { 85556, true }, + { 85569, true }, + { 85577, true }, + { 85586, true }, + { 85597, true }, + { 85611, true }, + { 85634, true }, + { 85647, true }, + { 85659, true }, + { 85670, true }, + { 85684, true }, + { 85712, true }, + { 85727, true }, + { 85742, true }, + { 85762, true }, + { 85775, true }, + { 85791, true }, + { 85806, true }, + { 85819, true }, + { 85833, true }, + { 85844, true }, + { 85855, true }, + { 85867, true }, + { 85884, true }, + { 85897, true }, + { 85912, true }, + { 85920, true }, + { 85940, true }, + { 85951, true }, + { 85961, true }, + { 85971, true }, + { 85982, true }, + { 85992, true }, + { 86004, true }, + { 86019, true }, + { 86028, true }, { 86042, true }, - { 86052, true }, - { 86064, true }, - { 86079, true }, - { 86088, true }, - { 86102, true }, - { 86115, true }, - { 86130, true }, - { 86144, true }, - { 86155, true }, - { 86168, false }, - { 86178, true }, - { 86197, true }, - { 86210, true }, - { 86219, true }, + { 86055, true }, + { 86065, true }, + { 86080, true }, + { 86094, true }, + { 86105, true }, + { 86118, false }, + { 86128, true }, + { 86147, true }, + { 86160, true }, + { 86169, true }, + { 86180, true }, + { 86194, true }, + { 86214, true }, { 86230, true }, - { 86244, true }, - { 86264, true }, - { 86280, true }, - { 86291, true }, - { 86307, true }, - { 86324, true }, + { 86241, true }, + { 86257, true }, + { 86274, true }, + { 86289, true }, + { 86302, true }, + { 86319, true }, + { 86329, true }, { 86339, true }, - { 86352, true }, - { 86369, true }, - { 86379, true }, - { 86389, true }, - { 86397, true }, - { 86408, true }, - { 86418, true }, - { 86431, true }, - { 86445, true }, - { 86457, true }, - { 86467, true }, - { 86475, true }, - { 86484, true }, - { 86498, true }, - { 86512, true }, - { 86526, true }, + { 86347, true }, + { 86358, true }, + { 86368, true }, + { 86381, true }, + { 86395, true }, + { 86405, true }, + { 86413, true }, + { 86422, true }, + { 86436, true }, + { 86450, true }, + { 86464, true }, + { 86506, true }, + { 86522, true }, + { 86531, true }, + { 86543, true }, + { 86555, true }, { 86568, true }, - { 86584, true }, - { 86593, true }, - { 86605, true }, - { 86617, true }, + { 86581, true }, + { 86599, true }, + { 86607, true }, + { 86620, true }, { 86630, true }, - { 86643, true }, - { 86661, true }, - { 86669, true }, - { 86682, true }, - { 86692, true }, - { 86704, true }, - { 86715, true }, - { 86730, true }, - { 86742, true }, - { 86755, true }, - { 86767, true }, - { 86782, true }, - { 86795, true }, - { 86807, true }, - { 86823, true }, - { 86841, true }, + { 86642, true }, + { 86653, true }, + { 86668, true }, + { 86680, true }, + { 86693, true }, + { 86705, true }, + { 86720, true }, + { 86733, true }, + { 86745, true }, + { 86761, true }, + { 86779, true }, + { 86794, true }, + { 86808, true }, + { 86826, true }, + { 86844, true }, { 86856, true }, - { 86870, true }, - { 86888, true }, - { 86906, true }, - { 86918, true }, - { 86936, true }, - { 86947, true }, - { 86961, true }, - { 86981, true }, - { 86994, true }, - { 87006, true }, - { 87026, true }, - { 87037, true }, - { 87046, true }, - { 87055, true }, - { 87062, true }, - { 87077, true }, - { 87092, true }, - { 87106, true }, - { 87125, true }, - { 87136, true }, + { 86874, true }, + { 86885, true }, + { 86899, true }, + { 86919, true }, + { 86932, true }, + { 86944, true }, + { 86964, true }, + { 86975, true }, + { 86984, true }, + { 86993, true }, + { 87000, true }, + { 87015, true }, + { 87030, true }, + { 87044, true }, + { 87063, true }, + { 87074, true }, + { 87088, true }, + { 87100, true }, + { 87113, true }, + { 87126, true }, + { 87137, true }, { 87150, true }, { 87162, true }, - { 87175, true }, - { 87188, true }, - { 87199, true }, - { 87212, true }, - { 87224, true }, - { 87247, true }, - { 87256, true }, - { 87273, true }, - { 87288, true }, - { 87302, true }, - { 87310, true }, - { 87324, true }, - { 87338, true }, - { 87346, true }, - { 87359, true }, - { 87370, true }, - { 87382, false }, - { 87395, true }, - { 87409, true }, - { 87417, true }, - { 87427, true }, - { 87437, true }, - { 87454, true }, - { 87472, true }, + { 87185, true }, + { 87194, true }, + { 87211, true }, + { 87226, true }, + { 87240, true }, + { 87248, true }, + { 87262, true }, + { 87276, true }, + { 87284, true }, + { 87297, true }, + { 87308, true }, + { 87320, false }, + { 87333, true }, + { 87347, true }, + { 87355, true }, + { 87365, true }, + { 87375, true }, + { 87392, true }, + { 87410, true }, + { 87428, true }, + { 87442, true }, + { 87452, true }, + { 87476, true }, { 87490, true }, - { 87504, true }, - { 87514, true }, - { 87538, true }, - { 87552, true }, - { 87571, true }, - { 87583, true }, - { 87602, true }, + { 87509, true }, + { 87521, true }, + { 87540, true }, + { 87557, true }, + { 87567, true }, + { 87582, true }, + { 87594, true }, + { 87606, true }, { 87619, true }, - { 87629, true }, - { 87644, true }, + { 87628, true }, + { 87637, true }, { 87656, true }, { 87668, true }, - { 87681, true }, - { 87690, true }, - { 87699, true }, - { 87718, true }, - { 87730, true }, - { 87737, true }, - { 87747, true }, - { 87756, true }, - { 87771, true }, - { 87786, true }, - { 87804, true }, - { 87815, true }, - { 87827, true }, - { 87843, true }, - { 87857, true }, - { 87873, true }, - { 87899, true }, - { 87910, true }, - { 87925, true }, - { 87940, true }, - { 87955, true }, - { 87970, true }, - { 87983, true }, + { 87675, true }, + { 87685, true }, + { 87694, true }, + { 87709, true }, + { 87724, true }, + { 87742, true }, + { 87753, true }, + { 87765, true }, + { 87781, true }, + { 87795, true }, + { 87811, true }, + { 87837, true }, + { 87848, true }, + { 87863, true }, + { 87878, true }, + { 87893, true }, + { 87908, true }, + { 87921, true }, + { 87937, true }, + { 87960, true }, + { 87973, true }, + { 87986, true }, { 87999, true }, - { 88022, true }, - { 88035, true }, - { 88048, true }, - { 88061, true }, - { 88080, true }, - { 88095, true }, - { 88109, true }, - { 88121, false }, - { 88140, true }, - { 88151, true }, - { 88163, true }, - { 88174, true }, - { 88187, true }, - { 88210, true }, - { 88224, true }, - { 88235, true }, - { 88251, true }, - { 88264, true }, - { 88274, true }, - { 88285, true }, + { 88018, true }, + { 88033, true }, + { 88047, true }, + { 88059, false }, + { 88078, true }, + { 88089, true }, + { 88101, true }, + { 88112, true }, + { 88125, true }, + { 88148, true }, + { 88162, true }, + { 88173, true }, + { 88189, true }, + { 88202, true }, + { 88212, true }, + { 88223, true }, + { 88231, true }, + { 88241, true }, + { 88258, true }, + { 88273, true }, + { 88283, true }, { 88293, true }, - { 88303, true }, - { 88320, true }, + { 88304, true }, + { 88315, true }, { 88335, true }, - { 88345, true }, - { 88355, true }, - { 88366, true }, - { 88377, true }, - { 88397, true }, - { 88412, true }, - { 88429, true }, - { 88443, true }, - { 88453, true }, - { 88464, true }, - { 88475, true }, - { 88497, true }, - { 88509, true }, - { 88523, true }, - { 88534, false }, - { 88547, true }, - { 88557, true }, - { 88574, true }, - { 88588, true }, - { 88600, true }, - { 88616, true }, - { 88630, true }, - { 88641, true }, - { 88651, true }, - { 88671, true }, - { 88698, true }, + { 88350, true }, + { 88367, true }, + { 88381, true }, + { 88391, true }, + { 88402, true }, + { 88413, true }, + { 88435, true }, + { 88447, true }, + { 88461, true }, + { 88472, false }, + { 88485, true }, + { 88495, true }, + { 88513, true }, + { 88530, true }, + { 88544, true }, + { 88556, true }, + { 88572, true }, + { 88586, true }, + { 88597, true }, + { 88607, true }, + { 88627, true }, + { 88654, true }, + { 88669, true }, + { 88685, true }, + { 88700, true }, { 88713, true }, - { 88729, true }, - { 88744, true }, - { 88757, true }, - { 88769, true }, - { 88785, true }, - { 88797, true }, - { 88814, true }, - { 88825, true }, - { 88842, true }, - { 88854, true }, - { 88867, false }, - { 88881, true }, - { 88895, true }, - { 88907, true }, - { 88918, true }, - { 88930, true }, - { 88948, true }, - { 88961, true }, - { 88976, true }, - { 88987, true }, - { 88997, true }, + { 88725, true }, + { 88741, true }, + { 88753, true }, + { 88770, true }, + { 88780, true }, + { 88791, true }, + { 88808, true }, + { 88820, true }, + { 88833, false }, + { 88847, true }, + { 88861, true }, + { 88873, true }, + { 88884, true }, + { 88896, true }, + { 88914, true }, + { 88927, true }, + { 88942, true }, + { 88952, true }, + { 88964, true }, + { 88974, true }, + { 88983, true }, + { 88995, true }, { 89009, true }, - { 89019, true }, - { 89028, true }, - { 89040, true }, - { 89054, true }, - { 89075, true }, - { 89089, true }, - { 89103, true }, - { 89121, true }, - { 89139, true }, - { 89147, true }, - { 89159, true }, - { 89171, true }, - { 89183, true }, - { 89191, true }, - { 89205, true }, + { 89030, true }, + { 89044, true }, + { 89058, true }, + { 89076, true }, + { 89094, true }, + { 89102, true }, + { 89114, true }, + { 89126, true }, + { 89138, true }, + { 89146, true }, + { 89160, true }, + { 89175, true }, + { 89189, true }, + { 89198, true }, + { 89208, true }, { 89220, true }, - { 89234, true }, - { 89243, true }, - { 89253, true }, - { 89265, true }, - { 89280, true }, - { 89303, true }, - { 89316, true }, - { 89324, true }, - { 89335, true }, - { 89344, true }, - { 89352, true }, - { 89365, true }, - { 89388, true }, - { 89400, true }, - { 89416, true }, - { 89439, true }, - { 89450, true }, - { 89466, true }, - { 89482, true }, - { 89497, true }, - { 89510, true }, - { 89520, true }, - { 89527, true }, - { 89540, true }, - { 89563, true }, - { 89580, true }, - { 89609, true }, - { 89626, true }, - { 89640, true }, - { 89652, true }, - { 89661, true }, + { 89235, true }, + { 89247, true }, + { 89270, true }, + { 89283, true }, + { 89291, true }, + { 89302, true }, + { 89311, true }, + { 89319, true }, + { 89332, true }, + { 89355, true }, + { 89367, true }, + { 89383, true }, + { 89406, true }, + { 89417, true }, + { 89433, true }, + { 89449, true }, + { 89464, true }, + { 89477, true }, + { 89487, true }, + { 89494, true }, + { 89507, true }, + { 89530, true }, + { 89547, true }, + { 89576, true }, + { 89593, true }, + { 89607, true }, + { 89619, true }, + { 89628, true }, + { 89644, true }, + { 89659, true }, { 89677, true }, - { 89692, true }, - { 89710, true }, - { 89728, true }, - { 89738, true }, - { 89746, true }, - { 89756, true }, - { 89766, true }, - { 89774, true }, - { 89788, true }, - { 89797, true }, - { 89808, true }, - { 89823, true }, + { 89695, true }, + { 89705, true }, + { 89713, true }, + { 89723, true }, + { 89733, true }, + { 89741, true }, + { 89755, true }, + { 89764, true }, + { 89775, true }, + { 89790, true }, + { 89798, true }, + { 89813, true }, { 89831, true }, - { 89846, true }, - { 89864, true }, + { 89849, true }, + { 89861, true }, + { 89871, true }, { 89882, true }, { 89894, true }, - { 89904, true }, - { 89915, true }, - { 89927, true }, - { 89938, true }, - { 89946, true }, - { 89963, false }, - { 89979, false }, - { 90000, true }, - { 90017, true }, - { 90035, true }, - { 90052, true }, - { 90069, true }, - { 90083, true }, - { 90091, true }, - { 90104, true }, - { 90122, true }, - { 90149, true }, - { 90173, true }, - { 90190, true }, - { 90205, true }, - { 90219, true }, - { 90231, true }, - { 90242, true }, - { 90253, true }, - { 90263, true }, - { 90274, false }, - { 90295, true }, - { 90306, true }, - { 90320, true }, - { 90332, true }, - { 90346, true }, - { 90364, true }, - { 90378, true }, - { 90389, true }, - { 90406, true }, - { 90417, true }, - { 90427, true }, - { 90441, true }, - { 90455, true }, - { 90468, true }, - { 90479, true }, - { 90498, true }, - { 90511, true }, - { 90528, true }, - { 90542, true }, - { 90550, true }, - { 90564, true }, - { 90577, true }, - { 90589, true }, - { 90602, true }, - { 90614, true }, - { 90626, true }, - { 90641, true }, - { 90651, true }, - { 90666, true }, - { 90680, true }, - { 90693, true }, - { 90703, false }, - { 90714, true }, + { 89905, true }, + { 89913, true }, + { 89930, false }, + { 89946, false }, + { 89967, true }, + { 89984, true }, + { 90002, true }, + { 90019, true }, + { 90036, true }, + { 90050, true }, + { 90058, true }, + { 90071, true }, + { 90089, true }, + { 90116, true }, + { 90140, true }, + { 90157, true }, + { 90172, true }, + { 90186, true }, + { 90198, true }, + { 90209, true }, + { 90220, true }, + { 90230, true }, + { 90241, false }, + { 90262, true }, + { 90273, true }, + { 90287, true }, + { 90299, true }, + { 90313, true }, + { 90331, true }, + { 90345, true }, + { 90356, true }, + { 90373, true }, + { 90384, true }, + { 90394, true }, + { 90408, true }, + { 90422, true }, + { 90435, true }, + { 90446, true }, + { 90465, true }, + { 90478, true }, + { 90495, true }, + { 90509, true }, + { 90517, true }, + { 90531, true }, + { 90544, true }, + { 90556, true }, + { 90569, true }, + { 90581, true }, + { 90593, true }, + { 90608, true }, + { 90618, true }, + { 90633, true }, + { 90647, true }, + { 90660, true }, + { 90670, false }, + { 90681, true }, + { 90691, true }, + { 90702, true }, + { 90713, true }, { 90724, true }, - { 90735, true }, - { 90746, true }, - { 90757, true }, - { 90770, true }, - { 90782, true }, - { 90794, true }, - { 90804, true }, + { 90737, true }, + { 90749, true }, + { 90761, true }, + { 90771, true }, + { 90793, true }, + { 90805, true }, + { 90814, true }, { 90826, true }, { 90838, true }, - { 90847, true }, - { 90856, true }, - { 90868, true }, - { 90880, true }, - { 90890, true }, - { 90901, true }, - { 90911, true }, - { 90924, false }, - { 90935, true }, - { 90948, true }, - { 90973, true }, - { 90985, true }, - { 90995, true }, - { 91004, true }, - { 91021, true }, - { 91039, true }, - { 91051, true }, - { 91059, true }, - { 91078, true }, - { 91091, true }, - { 91105, true }, - { 91115, true }, - { 91127, true }, - { 91151, true }, - { 91165, true }, + { 90848, true }, + { 90859, true }, + { 90869, true }, + { 90882, false }, + { 90893, true }, + { 90906, true }, + { 90931, true }, + { 90943, true }, + { 90953, true }, + { 90962, true }, + { 90979, true }, + { 90997, true }, + { 91009, true }, + { 91017, true }, + { 91036, true }, + { 91049, true }, + { 91063, true }, + { 91073, true }, + { 91085, true }, + { 91109, true }, + { 91123, true }, + { 91141, true }, + { 91155, true }, + { 91173, true }, { 91183, true }, - { 91197, true }, - { 91215, true }, - { 91234, true }, - { 91244, true }, - { 91257, true }, - { 91267, true }, - { 91280, true }, - { 91289, true }, - { 91300, true }, - { 91312, true }, - { 91323, true }, - { 91336, true }, - { 91344, true }, - { 91356, true }, - { 91369, true }, - { 91381, true }, - { 91396, true }, - { 91404, true }, - { 91416, true }, - { 91431, true }, - { 91440, true }, - { 91453, true }, - { 91459, false }, - { 91474, true }, - { 91483, true }, - { 91496, true }, - { 91510, true }, - { 91522, true }, - { 91536, true }, - { 91549, true }, - { 91560, true }, - { 91569, true }, - { 91579, true }, - { 91587, true }, - { 91600, true }, - { 91612, true }, - { 91625, true }, - { 91645, true }, - { 91664, true }, - { 91681, true }, - { 91699, true }, + { 91196, true }, + { 91206, true }, + { 91219, true }, + { 91228, true }, + { 91239, true }, + { 91251, true }, + { 91262, true }, + { 91275, true }, + { 91283, true }, + { 91295, true }, + { 91308, true }, + { 91320, true }, + { 91335, true }, + { 91343, true }, + { 91355, true }, + { 91370, true }, + { 91379, true }, + { 91392, true }, + { 91398, false }, + { 91413, true }, + { 91422, true }, + { 91435, true }, + { 91449, true }, + { 91461, true }, + { 91475, true }, + { 91488, true }, + { 91499, true }, + { 91508, true }, + { 91518, true }, + { 91526, true }, + { 91539, true }, + { 91551, true }, + { 91564, true }, + { 91584, true }, + { 91603, true }, + { 91620, true }, + { 91638, true }, + { 91653, true }, + { 91666, true }, + { 91678, true }, + { 91697, true }, { 91714, true }, - { 91727, true }, - { 91739, true }, + { 91733, true }, + { 91748, true }, { 91758, true }, - { 91775, true }, - { 91794, true }, - { 91809, true }, + { 91772, true }, + { 91791, true }, + { 91800, false }, + { 91811, true }, { 91819, true }, - { 91833, true }, - { 91852, true }, - { 91861, false }, - { 91872, true }, - { 91880, true }, - { 91888, true }, - { 91896, true }, - { 91908, true }, - { 91920, true }, - { 91934, true }, - { 91948, true }, + { 91827, true }, + { 91835, true }, + { 91847, true }, + { 91859, true }, + { 91873, true }, + { 91887, true }, + { 91898, true }, + { 91914, true }, + { 91936, true }, + { 91947, true }, { 91959, true }, - { 91975, true }, - { 91997, true }, - { 92008, true }, - { 92020, true }, - { 92027, true }, - { 92038, true }, - { 92050, true }, - { 92060, true }, - { 92070, true }, - { 92082, true }, - { 92100, true }, - { 92123, true }, - { 92178, true }, - { 92193, true }, - { 92203, true }, - { 92221, true }, + { 91966, true }, + { 91977, true }, + { 91989, true }, + { 91999, true }, + { 92009, true }, + { 92021, true }, + { 92039, true }, + { 92062, true }, + { 92117, true }, + { 92132, true }, + { 92142, true }, + { 92160, true }, + { 92175, true }, + { 92188, false }, + { 92202, false }, + { 92218, true }, { 92236, true }, - { 92249, false }, - { 92263, false }, - { 92279, true }, - { 92297, true }, - { 92322, true }, - { 92341, true }, - { 92351, true }, - { 92362, true }, - { 92384, true }, - { 92407, true }, - { 92417, true }, - { 92427, true }, - { 92445, true }, - { 92456, true }, - { 92467, true }, - { 92483, true }, - { 92496, true }, - { 92510, true }, - { 92523, true }, + { 92261, true }, + { 92280, true }, + { 92290, true }, + { 92301, true }, + { 92323, true }, + { 92346, true }, + { 92356, true }, + { 92366, false }, + { 92380, true }, + { 92398, true }, + { 92409, true }, + { 92420, true }, + { 92436, true }, + { 92449, true }, + { 92463, true }, + { 92476, true }, + { 92505, true }, + { 92518, true }, + { 92528, true }, + { 92540, true }, { 92552, true }, - { 92565, true }, - { 92575, true }, - { 92587, true }, - { 92599, true }, - { 92618, true }, - { 92628, true }, - { 92642, true }, - { 92652, true }, - { 92669, true }, - { 92680, true }, - { 92696, true }, - { 92715, true }, - { 92730, true }, - { 92742, true }, - { 92751, true }, - { 92767, true }, - { 92781, true }, - { 92794, true }, - { 92809, true }, - { 92821, true }, + { 92571, true }, + { 92581, true }, + { 92595, true }, + { 92605, true }, + { 92622, true }, + { 92633, true }, + { 92649, true }, + { 92668, true }, + { 92683, true }, + { 92695, true }, + { 92704, true }, + { 92720, true }, + { 92734, true }, + { 92747, true }, + { 92762, true }, + { 92774, true }, + { 92784, true }, + { 92798, true }, + { 92813, true }, { 92831, true }, - { 92845, true }, - { 92860, true }, - { 92878, true }, - { 92888, true }, - { 92900, true }, - { 92914, true }, - { 92926, true }, - { 92938, true }, - { 92959, true }, - { 92975, true }, - { 92988, true }, - { 93005, true }, - { 93020, true }, - { 93033, true }, - { 93047, true }, - { 93060, true }, - { 93079, true }, - { 93102, false }, - { 93115, false }, - { 93133, true }, - { 93153, true }, - { 93166, true }, - { 93181, true }, - { 93196, true }, - { 93211, true }, - { 93225, true }, - { 93240, true }, - { 93265, true }, - { 93276, true }, - { 93292, true }, - { 93306, true }, - { 93331, true }, - { 93345, true }, - { 93359, true }, - { 93373, true }, - { 93397, true }, - { 93408, true }, - { 93419, true }, - { 93431, true }, - { 93459, true }, - { 93469, false }, - { 93481, true }, - { 93491, true }, + { 92841, true }, + { 92853, true }, + { 92867, true }, + { 92879, true }, + { 92891, true }, + { 92912, true }, + { 92928, true }, + { 92941, true }, + { 92958, true }, + { 92973, true }, + { 92986, true }, + { 93000, true }, + { 93013, true }, + { 93032, true }, + { 93055, false }, + { 93068, false }, + { 93086, true }, + { 93106, true }, + { 93119, true }, + { 93134, true }, + { 93149, true }, + { 93164, true }, + { 93178, true }, + { 93193, true }, + { 93218, true }, + { 93229, true }, + { 93245, true }, + { 93259, true }, + { 93284, true }, + { 93298, true }, + { 93312, true }, + { 93326, true }, + { 93350, true }, + { 93361, true }, + { 93372, true }, + { 93384, true }, + { 93412, true }, + { 93422, false }, + { 93434, true }, + { 93444, true }, + { 93454, true }, + { 93471, true }, + { 93488, true }, { 93501, true }, - { 93518, true }, - { 93535, true }, - { 93548, true }, - { 93558, true }, - { 93581, true }, - { 93591, true }, + { 93511, true }, + { 93534, true }, + { 93544, true }, + { 93553, true }, + { 93565, true }, + { 93577, true }, + { 93589, true }, { 93600, true }, - { 93612, true }, - { 93624, true }, - { 93636, true }, - { 93647, true }, - { 93662, true }, - { 93672, true }, + { 93615, true }, + { 93625, true }, + { 93634, true }, + { 93652, false }, + { 93663, true }, + { 93673, true }, { 93681, true }, - { 93699, false }, - { 93710, true }, - { 93720, true }, - { 93728, true }, - { 93742, true }, - { 93754, true }, - { 93766, true }, - { 93784, true }, - { 93804, true }, - { 93819, true }, - { 93836, true }, - { 93849, true }, - { 93860, true }, - { 93875, true }, - { 93890, true }, - { 93906, true }, - { 93919, true }, - { 93944, true }, - { 93964, true }, - { 93979, true }, - { 93990, true }, - { 94006, true }, - { 94018, true }, + { 93695, true }, + { 93707, true }, + { 93719, true }, + { 93737, true }, + { 93757, true }, + { 93772, true }, + { 93789, true }, + { 93802, true }, + { 93813, true }, + { 93828, true }, + { 93843, true }, + { 93859, true }, + { 93872, true }, + { 93897, true }, + { 93913, true }, + { 93933, true }, + { 93948, true }, + { 93959, true }, + { 93975, true }, + { 93987, true }, + { 94004, true }, + { 94015, true }, + { 94023, true }, { 94035, true }, - { 94046, true }, - { 94054, true }, - { 94066, true }, + { 94047, true }, + { 94061, true }, { 94078, true }, - { 94092, true }, - { 94109, true }, - { 94125, true }, - { 94141, true }, - { 94153, true }, - { 94170, false }, - { 94190, true }, - { 94210, true }, - { 94231, true }, - { 94252, false }, - { 94269, true }, - { 94288, true }, - { 94303, true }, - { 94320, true }, - { 94347, true }, - { 94358, true }, - { 94368, true }, - { 94383, true }, - { 94395, true }, - { 94416, true }, - { 94425, true }, - { 94434, true }, - { 94442, false }, - { 94459, true }, - { 94470, true }, - { 94488, true }, - { 94499, true }, - { 94515, true }, - { 94537, true }, - { 94547, true }, - { 94560, true }, - { 94572, true }, - { 94589, true }, - { 94599, true }, - { 94617, true }, - { 94634, true }, - { 94651, true }, - { 94659, true }, - { 94683, true }, + { 94094, true }, + { 94110, true }, + { 94122, true }, + { 94139, false }, + { 94159, true }, + { 94179, true }, + { 94200, true }, + { 94221, false }, + { 94238, true }, + { 94257, true }, + { 94272, true }, + { 94289, true }, + { 94316, true }, + { 94327, true }, + { 94337, true }, + { 94352, true }, + { 94364, true }, + { 94385, true }, + { 94394, true }, + { 94403, true }, + { 94411, false }, + { 94428, true }, + { 94439, true }, + { 94457, true }, + { 94468, true }, + { 94484, true }, + { 94506, true }, + { 94516, true }, + { 94529, true }, + { 94541, true }, + { 94558, true }, + { 94568, true }, + { 94586, true }, + { 94603, true }, + { 94620, true }, + { 94628, true }, + { 94652, true }, + { 94666, true }, + { 94679, true }, { 94697, true }, - { 94710, true }, - { 94728, true }, - { 94742, true }, - { 94761, true }, - { 94771, true }, - { 94783, true }, - { 94807, true }, - { 94819, true }, - { 94832, true }, - { 94839, true }, - { 94859, true }, - { 94875, true }, - { 94885, true }, - { 94896, true }, - { 94903, true }, - { 94912, true }, - { 94931, true }, - { 94944, true }, - { 94954, true }, - { 94964, true }, - { 94977, true }, - { 94989, true }, - { 95001, true }, - { 95016, true }, - { 95034, true }, - { 95045, true }, - { 95057, false }, - { 95083, true }, - { 95097, true }, - { 95111, true }, - { 95124, true }, - { 95137, true }, - { 95148, true }, - { 95162, true }, - { 95175, true }, - { 95187, true }, - { 95200, false }, - { 95214, true }, - { 95224, true }, - { 95235, true }, - { 95248, true }, - { 95260, true }, - { 95281, true }, - { 95294, true }, - { 95302, true }, - { 95316, true }, - { 95331, true }, - { 95354, true }, - { 95365, false }, - { 95380, true }, - { 95393, true }, - { 95409, true }, - { 95421, true }, - { 95435, true }, - { 95449, true }, - { 95462, true }, - { 95476, true }, - { 95489, true }, - { 95507, true }, - { 95535, true }, - { 95563, true }, + { 94711, true }, + { 94730, true }, + { 94740, true }, + { 94752, true }, + { 94776, true }, + { 94788, true }, + { 94801, true }, + { 94808, true }, + { 94828, true }, + { 94844, true }, + { 94854, true }, + { 94865, true }, + { 94872, true }, + { 94881, true }, + { 94900, true }, + { 94913, true }, + { 94923, true }, + { 94933, true }, + { 94946, true }, + { 94958, true }, + { 94970, true }, + { 94985, true }, + { 95003, true }, + { 95014, true }, + { 95026, false }, + { 95052, true }, + { 95066, true }, + { 95080, true }, + { 95093, true }, + { 95104, true }, + { 95118, true }, + { 95131, true }, + { 95143, true }, + { 95156, false }, + { 95170, true }, + { 95180, true }, + { 95191, true }, + { 95204, true }, + { 95216, true }, + { 95237, true }, + { 95250, true }, + { 95258, true }, + { 95272, true }, + { 95287, true }, + { 95310, true }, + { 95321, false }, + { 95336, true }, + { 95349, true }, + { 95365, true }, + { 95377, true }, + { 95391, true }, + { 95405, true }, + { 95418, true }, + { 95432, true }, + { 95445, true }, + { 95463, true }, + { 95491, true }, + { 95519, true }, + { 95529, true }, + { 95545, true }, + { 95558, false }, { 95573, true }, - { 95589, true }, - { 95602, false }, - { 95617, true }, - { 95635, true }, - { 95643, true }, + { 95591, true }, + { 95599, true }, + { 95614, true }, + { 95627, true }, + { 95642, true }, { 95658, true }, - { 95671, true }, - { 95686, true }, + { 95672, true }, + { 95682, true }, + { 95691, false }, { 95702, true }, - { 95716, true }, - { 95726, true }, - { 95735, false }, + { 95713, true }, + { 95723, true }, + { 95735, true }, { 95746, true }, - { 95757, true }, - { 95767, true }, - { 95779, true }, - { 95790, true }, - { 95817, true }, - { 95828, true }, - { 95837, true }, - { 95846, true }, - { 95863, true }, - { 95877, true }, - { 95900, true }, - { 95916, true }, - { 95937, true }, - { 95953, true }, - { 95973, true }, - { 95995, true }, - { 96005, true }, + { 95773, true }, + { 95784, true }, + { 95793, true }, + { 95802, true }, + { 95819, true }, + { 95833, true }, + { 95856, true }, + { 95872, true }, + { 95893, true }, + { 95909, true }, + { 95929, true }, + { 95951, true }, + { 95961, true }, + { 95969, true }, + { 95978, true }, + { 95989, true }, + { 96003, true }, { 96013, true }, - { 96022, true }, - { 96033, true }, - { 96047, true }, - { 96057, true }, - { 96072, true }, + { 96028, true }, + { 96038, true }, + { 96058, true }, + { 96068, true }, { 96082, true }, - { 96102, true }, - { 96112, true }, + { 96095, true }, + { 96107, true }, { 96126, true }, { 96139, true }, - { 96151, true }, - { 96170, true }, - { 96183, true }, - { 96207, false }, - { 96226, true }, - { 96254, true }, - { 96268, true }, - { 96282, true }, - { 96294, true }, - { 96308, true }, - { 96318, true }, - { 96340, true }, - { 96358, true }, - { 96366, true }, - { 96377, true }, - { 96393, true }, - { 96407, true }, - { 96423, true }, - { 96438, true }, - { 96453, true }, - { 96465, true }, - { 96477, true }, - { 96496, true }, - { 96512, false }, - { 96537, true }, - { 96554, true }, + { 96163, false }, + { 96182, true }, + { 96210, true }, + { 96224, true }, + { 96238, true }, + { 96250, false }, + { 96264, true }, + { 96274, true }, + { 96296, true }, + { 96314, true }, + { 96322, true }, + { 96333, true }, + { 96349, true }, + { 96363, true }, + { 96379, true }, + { 96394, true }, + { 96409, true }, + { 96421, true }, + { 96433, true }, + { 96452, true }, + { 96468, false }, + { 96493, true }, + { 96510, true }, + { 96520, true }, + { 96531, true }, + { 96546, true }, + { 96553, true }, { 96564, true }, - { 96575, true }, - { 96590, true }, - { 96597, true }, - { 96608, true }, - { 96622, true }, - { 96635, true }, - { 96648, true }, + { 96578, true }, + { 96591, true }, + { 96604, true }, + { 96617, true }, + { 96628, true }, + { 96641, true }, + { 96651, true }, { 96661, true }, - { 96672, true }, + { 96673, true }, { 96685, true }, - { 96695, true }, - { 96705, true }, - { 96717, true }, - { 96729, true }, + { 96694, true }, + { 96701, true }, + { 96711, false }, + { 96727, true }, { 96738, true }, - { 96745, true }, - { 96755, false }, - { 96771, true }, - { 96782, true }, - { 96792, true }, - { 96810, true }, - { 96828, true }, - { 96842, true }, - { 96856, true }, - { 96879, true }, - { 96889, true }, - { 96904, true }, - { 96922, true }, - { 96939, true }, - { 96953, true }, - { 96967, true }, - { 96979, true }, - { 96991, true }, - { 97004, false }, - { 97015, true }, - { 97029, true }, - { 97042, true }, - { 97057, true }, - { 97076, true }, - { 97091, true }, - { 97115, false }, - { 97130, true }, - { 97141, true }, - { 97164, true }, - { 97175, true }, - { 97186, true }, - { 97198, true }, - { 97212, true }, - { 97225, true }, - { 97238, true }, - { 97251, true }, - { 97273, true }, - { 97283, true }, - { 97303, true }, - { 97321, true }, - { 97335, true }, - { 97352, false }, - { 97367, false }, - { 97383, true }, - { 97400, true }, - { 97411, true }, + { 96748, true }, + { 96766, true }, + { 96784, true }, + { 96798, true }, + { 96812, true }, + { 96835, true }, + { 96845, true }, + { 96860, true }, + { 96878, true }, + { 96895, true }, + { 96909, true }, + { 96923, true }, + { 96935, true }, + { 96947, true }, + { 96960, false }, + { 96971, true }, + { 96985, true }, + { 96998, true }, + { 97013, true }, + { 97032, true }, + { 97047, true }, + { 97071, false }, + { 97086, true }, + { 97097, true }, + { 97120, true }, + { 97131, true }, + { 97142, true }, + { 97154, true }, + { 97168, true }, + { 97181, true }, + { 97194, true }, + { 97207, true }, + { 97229, true }, + { 97239, true }, + { 97259, true }, + { 97277, true }, + { 97291, true }, + { 97308, false }, + { 97323, false }, + { 97339, true }, + { 97356, true }, + { 97367, true }, + { 97389, true }, + { 97403, true }, + { 97423, true }, { 97433, true }, - { 97447, true }, - { 97467, true }, - { 97477, true }, - { 97488, true }, - { 97497, true }, - { 97508, true }, - { 97520, true }, - { 97530, true }, - { 97543, true }, - { 97560, true }, - { 97581, true }, - { 97595, true }, - { 97622, true }, - { 97637, true }, - { 97657, true }, - { 97672, true }, - { 97683, true }, - { 97695, true }, - { 97708, true }, - { 97719, true }, - { 97732, true }, - { 97746, true }, - { 97759, true }, - { 97782, true }, - { 97792, true }, - { 97802, true }, - { 97815, true }, - { 97825, true }, - { 97842, true }, - { 97858, true }, + { 97444, true }, + { 97453, true }, + { 97464, true }, + { 97476, true }, + { 97486, true }, + { 97499, true }, + { 97516, true }, + { 97537, true }, + { 97551, true }, + { 97578, true }, + { 97593, true }, + { 97613, true }, + { 97628, true }, + { 97639, true }, + { 97651, true }, + { 97664, true }, + { 97675, true }, + { 97688, true }, + { 97702, true }, + { 97715, true }, + { 97738, true }, + { 97748, true }, + { 97758, true }, + { 97771, true }, + { 97781, true }, + { 97798, true }, + { 97814, true }, + { 97829, true }, + { 97849, true }, + { 97859, true }, { 97873, true }, - { 97893, true }, - { 97903, true }, - { 97917, true }, - { 97929, true }, - { 97954, true }, - { 97968, true }, - { 97982, true }, - { 97996, true }, - { 98010, true }, - { 98024, true }, - { 98039, true }, - { 98053, true }, - { 98067, true }, - { 98081, true }, + { 97885, true }, + { 97910, true }, + { 97924, true }, + { 97938, true }, + { 97952, true }, + { 97966, true }, + { 97980, true }, + { 97995, true }, + { 98009, true }, + { 98023, true }, + { 98037, true }, + { 98057, true }, + { 98069, true }, + { 98086, true }, { 98101, true }, - { 98113, true }, - { 98130, true }, - { 98145, true }, - { 98158, true }, - { 98176, true }, - { 98191, true }, + { 98114, true }, + { 98132, true }, + { 98147, true }, + { 98163, true }, + { 98175, true }, + { 98192, true }, { 98207, true }, - { 98219, true }, - { 98236, true }, - { 98251, true }, - { 98260, false }, - { 98275, true }, - { 98286, true }, - { 98298, true }, - { 98307, true }, - { 98324, false }, - { 98334, true }, - { 98350, true }, - { 98360, true }, - { 98376, true }, - { 98396, true }, - { 98410, true }, - { 98424, true }, - { 98443, true }, - { 98463, true }, - { 98473, true }, - { 98488, true }, - { 98498, true }, - { 98512, true }, - { 98533, true }, - { 98543, true }, - { 98558, true }, - { 98572, true }, - { 98586, true }, + { 98216, false }, + { 98231, true }, + { 98242, true }, + { 98254, true }, + { 98263, true }, + { 98280, false }, + { 98290, true }, + { 98306, true }, + { 98316, true }, + { 98332, true }, + { 98352, true }, + { 98366, true }, + { 98380, true }, + { 98399, true }, + { 98419, true }, + { 98429, true }, + { 98444, true }, + { 98454, true }, + { 98468, true }, + { 98489, true }, + { 98499, true }, + { 98514, true }, + { 98528, true }, + { 98542, true }, + { 98557, true }, + { 98573, true }, + { 98589, true }, { 98601, true }, - { 98617, true }, - { 98633, true }, - { 98645, true }, - { 98657, true }, - { 98669, true }, - { 98682, true }, - { 98695, true }, - { 98709, true }, - { 98724, true }, - { 98738, false }, - { 98764, true }, - { 98775, true }, - { 98783, true }, - { 98791, true }, - { 98799, true }, - { 98807, true }, + { 98613, true }, + { 98625, true }, + { 98638, true }, + { 98651, true }, + { 98665, true }, + { 98680, true }, + { 98694, false }, + { 98720, true }, + { 98731, true }, + { 98739, true }, + { 98747, true }, + { 98755, true }, + { 98763, true }, + { 98773, true }, + { 98782, true }, + { 98794, true }, + { 98806, true }, { 98817, true }, - { 98826, true }, - { 98838, true }, - { 98850, true }, - { 98861, true }, - { 98871, true }, - { 98888, true }, - { 98901, true }, - { 98911, true }, - { 98922, true }, - { 98936, true }, + { 98827, true }, + { 98844, true }, + { 98857, true }, + { 98867, true }, + { 98878, true }, + { 98892, true }, + { 98902, true }, + { 98909, true }, + { 98924, true }, { 98946, true }, - { 98953, true }, - { 98968, true }, - { 98990, true }, - { 98998, true }, - { 99008, true }, - { 99020, true }, + { 98954, true }, + { 98964, true }, + { 98976, true }, + { 98986, true }, + { 98996, true }, + { 99006, true }, + { 99017, true }, { 99030, true }, - { 99040, true }, - { 99050, true }, - { 99061, true }, - { 99074, true }, - { 99082, true }, - { 99096, true }, + { 99038, true }, + { 99052, true }, + { 99062, true }, + { 99073, true }, + { 99080, true }, + { 99088, true }, { 99106, true }, - { 99117, true }, - { 99124, true }, + { 99117, false }, { 99132, true }, - { 99150, true }, - { 99161, false }, - { 99176, true }, - { 99186, true }, - { 99195, true }, - { 99206, true }, - { 99214, true }, - { 99223, true }, - { 99243, true }, - { 99259, true }, - { 99268, false }, - { 99279, true }, - { 99288, true }, - { 99302, true }, - { 99318, true }, - { 99331, false }, - { 99342, true }, - { 99354, true }, + { 99142, true }, + { 99151, true }, + { 99162, true }, + { 99170, true }, + { 99179, true }, + { 99199, true }, + { 99215, true }, + { 99224, false }, + { 99235, true }, + { 99244, true }, + { 99258, true }, + { 99274, true }, + { 99287, false }, + { 99298, true }, + { 99310, true }, + { 99325, true }, + { 99335, true }, + { 99347, true }, + { 99358, true }, { 99369, true }, - { 99379, true }, + { 99381, true }, { 99391, true }, - { 99402, true }, - { 99413, true }, - { 99425, true }, - { 99448, true }, - { 99458, true }, - { 99474, true }, - { 99489, true }, - { 99502, true }, - { 99511, true }, - { 99526, true }, - { 99539, true }, - { 99552, true }, - { 99567, true }, - { 99577, true }, - { 99593, false }, - { 99603, true }, - { 99617, true }, - { 99628, true }, - { 99638, true }, + { 99407, true }, + { 99422, true }, + { 99435, true }, + { 99444, true }, + { 99459, true }, + { 99472, true }, + { 99485, true }, + { 99500, true }, + { 99510, true }, + { 99526, false }, + { 99536, true }, + { 99550, true }, + { 99561, true }, + { 99571, true }, + { 99585, true }, + { 99596, true }, + { 99609, true }, + { 99622, true }, + { 99634, true }, { 99652, true }, { 99663, true }, { 99676, true }, - { 99689, true }, - { 99701, true }, - { 99719, true }, - { 99730, true }, - { 99743, true }, - { 99754, true }, - { 99778, true }, - { 99793, true }, - { 99818, true }, - { 99826, true }, - { 99842, false }, - { 99857, true }, - { 99869, true }, - { 99881, true }, - { 99895, true }, - { 99909, true }, - { 99923, true }, - { 99937, true }, - { 99949, true }, - { 99966, true }, - { 99983, true }, - { 99995, true }, - { 100009, true }, - { 100031, true }, + { 99687, true }, + { 99711, true }, + { 99726, true }, + { 99751, true }, + { 99759, true }, + { 99775, false }, + { 99790, true }, + { 99802, true }, + { 99814, true }, + { 99828, true }, + { 99842, true }, + { 99856, true }, + { 99870, true }, + { 99882, true }, + { 99899, true }, + { 99916, true }, + { 99928, true }, + { 99942, true }, + { 99964, true }, + { 99978, true }, + { 99996, true }, + { 100017, true }, + { 100034, true }, { 100045, true }, - { 100063, true }, - { 100084, true }, - { 100101, true }, - { 100112, true }, - { 100125, true }, - { 100141, true }, - { 100153, true }, - { 100167, true }, - { 100183, true }, - { 100200, true }, - { 100214, true }, - { 100226, false }, - { 100251, true }, - { 100261, false }, - { 100287, true }, - { 100304, true }, - { 100315, true }, - { 100345, false }, - { 100359, true }, - { 100376, true }, - { 100390, true }, - { 100405, true }, - { 100413, true }, - { 100421, true }, - { 100429, true }, - { 100437, true }, - { 100445, true }, - { 100456, true }, - { 100466, true }, - { 100481, true }, - { 100495, true }, - { 100511, true }, - { 100522, true }, - { 100547, true }, - { 100556, false }, - { 100572, true }, - { 100582, false }, - { 100604, true }, - { 100619, true }, - { 100633, true }, - { 100646, true }, - { 100663, true }, - { 100679, true }, - { 100702, true }, - { 100724, true }, - { 100743, false }, - { 100762, true }, + { 100058, true }, + { 100074, true }, + { 100086, true }, + { 100100, true }, + { 100116, true }, + { 100133, true }, + { 100147, true }, + { 100159, false }, + { 100184, true }, + { 100194, false }, + { 100220, true }, + { 100237, true }, + { 100248, true }, + { 100278, false }, + { 100292, true }, + { 100309, true }, + { 100323, true }, + { 100338, true }, + { 100346, true }, + { 100354, true }, + { 100362, true }, + { 100370, true }, + { 100378, true }, + { 100389, true }, + { 100399, true }, + { 100414, true }, + { 100428, true }, + { 100444, true }, + { 100455, true }, + { 100480, true }, + { 100489, false }, + { 100505, true }, + { 100515, false }, + { 100537, true }, + { 100552, true }, + { 100566, true }, + { 100579, true }, + { 100596, true }, + { 100612, true }, + { 100635, true }, + { 100657, true }, + { 100676, false }, + { 100695, true }, + { 100708, true }, + { 100721, true }, + { 100745, true }, + { 100756, true }, { 100775, true }, - { 100788, true }, - { 100812, true }, - { 100823, true }, - { 100842, true }, - { 100870, true }, - { 100891, true }, - { 100904, true }, - { 100920, true }, - { 100940, true }, - { 100960, true }, - { 100974, true }, - { 100995, false }, - { 101006, true }, - { 101025, true }, - { 101036, true }, + { 100803, true }, + { 100824, true }, + { 100837, true }, + { 100853, true }, + { 100873, true }, + { 100893, true }, + { 100907, true }, + { 100928, false }, + { 100939, true }, + { 100958, true }, + { 100969, true }, + { 100981, true }, + { 100992, true }, + { 101007, true }, + { 101037, true }, { 101048, true }, - { 101059, true }, + { 101062, true }, { 101074, true }, - { 101104, true }, - { 101115, true }, - { 101129, true }, - { 101141, true }, - { 101152, true }, + { 101085, true }, + { 101109, true }, + { 101130, true }, + { 101143, true }, + { 101160, true }, { 101176, true }, - { 101197, true }, - { 101210, true }, - { 101227, true }, - { 101243, true }, - { 101261, true }, - { 101275, true }, - { 101289, true }, - { 101305, true }, - { 101320, true }, - { 101340, true }, - { 101355, true }, - { 101374, true }, - { 101385, true }, - { 101402, true }, - { 101418, true }, - { 101435, true }, - { 101450, true }, - { 101466, true }, - { 101483, true }, - { 101498, true }, - { 101517, true }, - { 101533, true }, - { 101543, true }, - { 101556, true }, - { 101575, true }, - { 101595, true }, - { 101607, true }, - { 101624, false }, - { 101639, true }, - { 101651, true }, - { 101664, true }, - { 101674, true }, - { 101691, true }, - { 101703, true }, - { 101713, true }, - { 101736, true }, - { 101750, true }, - { 101767, true }, - { 101782, true }, - { 101801, true }, - { 101834, true }, - { 101844, true }, - { 101860, false }, - { 101883, true }, - { 101895, true }, - { 101910, true }, + { 101194, true }, + { 101211, true }, + { 101225, true }, + { 101239, true }, + { 101255, true }, + { 101270, true }, + { 101285, true }, + { 101304, true }, + { 101315, true }, + { 101332, true }, + { 101348, true }, + { 101365, true }, + { 101380, true }, + { 101396, true }, + { 101413, true }, + { 101428, true }, + { 101447, true }, + { 101463, true }, + { 101473, true }, + { 101486, true }, + { 101505, true }, + { 101525, true }, + { 101537, true }, + { 101554, false }, + { 101569, true }, + { 101581, true }, + { 101594, true }, + { 101604, true }, + { 101621, true }, + { 101633, true }, + { 101643, true }, + { 101666, true }, + { 101680, true }, + { 101697, true }, + { 101712, true }, + { 101731, true }, + { 101764, true }, + { 101774, true }, + { 101790, false }, + { 101813, true }, + { 101825, true }, + { 101840, true }, + { 101860, true }, + { 101872, true }, + { 101890, true }, + { 101904, true }, + { 101917, true }, { 101930, true }, - { 101942, true }, - { 101960, true }, - { 101974, true }, - { 101987, true }, - { 102000, true }, - { 102013, true }, + { 101943, true }, + { 101954, true }, + { 101969, true }, + { 101983, true }, + { 101997, true }, + { 102005, true }, { 102024, true }, - { 102039, true }, - { 102053, true }, - { 102067, true }, - { 102075, true }, - { 102094, true }, - { 102116, true }, + { 102046, true }, + { 102059, true }, + { 102069, false }, + { 102081, true }, + { 102095, true }, + { 102110, true }, { 102129, true }, - { 102139, false }, - { 102151, true }, - { 102165, true }, - { 102180, true }, - { 102199, true }, - { 102213, true }, - { 102238, true }, - { 102252, true }, - { 102271, true }, - { 102288, true }, - { 102301, true }, - { 102318, true }, - { 102334, true }, - { 102353, true }, + { 102143, true }, + { 102168, true }, + { 102182, true }, + { 102201, true }, + { 102218, true }, + { 102231, true }, + { 102248, true }, + { 102264, true }, + { 102283, true }, + { 102300, true }, + { 102308, true }, + { 102324, true }, + { 102340, false }, + { 102357, true }, { 102370, true }, - { 102378, true }, - { 102394, false }, - { 102411, true }, - { 102431, true }, - { 102445, true }, - { 102462, true }, - { 102479, true }, - { 102498, true }, - { 102516, true }, + { 102390, true }, + { 102404, true }, + { 102421, true }, + { 102438, true }, + { 102457, true }, + { 102475, true }, + { 102488, true }, + { 102506, true }, + { 102515, true }, { 102529, true }, - { 102547, true }, - { 102556, true }, - { 102570, true }, - { 102587, true }, - { 102610, true }, - { 102619, true }, - { 102635, true }, - { 102653, true }, - { 102665, true }, - { 102674, true }, - { 102687, true }, - { 102700, true }, - { 102716, true }, - { 102724, false }, - { 102736, true }, - { 102746, true }, - { 102765, true }, - { 102780, true }, + { 102546, true }, + { 102569, true }, + { 102578, true }, + { 102594, true }, + { 102612, true }, + { 102624, true }, + { 102633, true }, + { 102646, true }, + { 102659, true }, + { 102675, true }, + { 102683, false }, + { 102695, true }, + { 102705, true }, + { 102724, true }, + { 102739, true }, + { 102754, true }, + { 102776, true }, { 102795, true }, - { 102817, true }, - { 102836, true }, - { 102850, true }, - { 102862, true }, - { 102876, true }, - { 102889, false }, - { 102911, true }, - { 102924, true }, - { 102938, true }, - { 102949, true }, - { 102963, false }, - { 102983, true }, - { 102994, false }, - { 103003, true }, - { 103018, false }, - { 103036, true }, - { 103046, true }, - { 103057, false }, - { 103072, true }, - { 103081, true }, - { 103093, true }, - { 103102, true }, - { 103115, true }, - { 103128, true }, - { 103139, true }, - { 103153, true }, + { 102809, true }, + { 102821, true }, + { 102835, true }, + { 102848, false }, + { 102870, true }, + { 102883, true }, + { 102897, true }, + { 102908, true }, + { 102922, false }, + { 102942, true }, + { 102953, false }, + { 102962, true }, + { 102977, false }, + { 102995, true }, + { 103005, true }, + { 103016, false }, + { 103031, true }, + { 103040, true }, + { 103052, true }, + { 103061, true }, + { 103074, true }, + { 103087, true }, + { 103098, true }, + { 103112, true }, + { 103125, true }, + { 103142, false }, + { 103159, true }, { 103166, true }, - { 103183, false }, - { 103200, true }, - { 103207, true }, - { 103215, true }, - { 103224, true }, - { 103236, true }, - { 103259, true }, - { 103273, true }, - { 103287, true }, - { 103304, true }, - { 103320, true }, - { 103334, true }, - { 103341, true }, - { 103352, true }, - { 103367, true }, - { 103379, true }, - { 103387, false }, - { 103397, true }, + { 103174, true }, + { 103183, true }, + { 103195, true }, + { 103218, true }, + { 103232, true }, + { 103246, true }, + { 103263, true }, + { 103279, true }, + { 103293, true }, + { 103300, true }, + { 103311, true }, + { 103326, true }, + { 103338, true }, + { 103346, false }, + { 103356, true }, + { 103368, true }, + { 103380, true }, + { 103395, true }, { 103409, true }, - { 103421, true }, - { 103436, true }, - { 103450, true }, - { 103458, true }, - { 103466, true }, - { 103479, true }, - { 103487, true }, - { 103498, true }, - { 103509, true }, - { 103516, true }, - { 103525, true }, - { 103535, true }, - { 103555, true }, - { 103567, true }, + { 103417, true }, + { 103425, true }, + { 103438, true }, + { 103446, true }, + { 103457, true }, + { 103468, true }, + { 103475, true }, + { 103484, true }, + { 103494, true }, + { 103514, true }, + { 103526, true }, + { 103537, false }, + { 103558, true }, + { 103569, true }, { 103578, true }, - { 103587, false }, - { 103596, false }, - { 103617, true }, - { 103628, true }, - { 103637, true }, - { 103651, true }, + { 103592, true }, + { 103609, true }, + { 103625, true }, + { 103642, true }, + { 103654, true }, { 103668, true }, - { 103684, true }, - { 103701, true }, - { 103713, true }, - { 103727, true }, - { 103745, true }, - { 103759, true }, - { 103775, false }, - { 103793, true }, + { 103686, true }, + { 103700, true }, + { 103716, false }, + { 103734, true }, + { 103751, true }, + { 103773, true }, + { 103784, true }, + { 103796, true }, { 103810, true }, - { 103832, true }, - { 103843, true }, - { 103855, true }, - { 103869, true }, - { 103880, true }, - { 103894, true }, - { 103905, true }, - { 103916, true }, + { 103821, true }, + { 103835, true }, + { 103846, true }, + { 103857, true }, + { 103871, true }, + { 103882, true }, + { 103911, true }, { 103930, true }, - { 103941, true }, - { 103970, true }, - { 103989, true }, - { 104008, true }, - { 104024, true }, - { 104050, true }, - { 104064, true }, - { 104081, true }, - { 104100, true }, + { 103949, true }, + { 103965, true }, + { 103991, true }, + { 104005, true }, + { 104022, true }, + { 104041, true }, + { 104058, true }, + { 104069, true }, + { 104077, true }, + { 104089, true }, + { 104102, true }, { 104117, true }, - { 104128, true }, - { 104136, true }, - { 104148, true }, - { 104161, true }, - { 104176, true }, - { 104189, true }, - { 104202, true }, - { 104216, true }, - { 104228, true }, - { 104240, true }, - { 104253, true }, - { 104268, true }, - { 104281, true }, - { 104293, true }, - { 104307, true }, - { 104318, true }, - { 104341, true }, - { 104359, true }, - { 104378, true }, - { 104389, true }, + { 104130, true }, + { 104143, true }, + { 104157, true }, + { 104169, true }, + { 104181, true }, + { 104196, true }, + { 104209, true }, + { 104221, true }, + { 104235, true }, + { 104246, true }, + { 104269, true }, + { 104287, true }, + { 104306, true }, + { 104317, true }, + { 104339, true }, + { 104347, true }, + { 104365, true }, + { 104381, true }, + { 104393, true }, { 104411, true }, - { 104419, true }, - { 104437, true }, - { 104453, true }, - { 104465, true }, - { 104483, true }, - { 104493, true }, - { 104507, true }, - { 104523, true }, - { 104549, false }, - { 104578, true }, - { 104589, true }, + { 104421, true }, + { 104435, true }, + { 104451, true }, + { 104477, false }, + { 104506, true }, + { 104517, true }, + { 104532, true }, + { 104548, true }, + { 104563, true }, + { 104577, true }, { 104604, true }, - { 104620, true }, - { 104635, true }, - { 104649, true }, - { 104676, true }, - { 104694, false }, - { 104705, true }, - { 104715, true }, - { 104730, true }, - { 104741, true }, - { 104759, true }, - { 104782, true }, - { 104800, true }, - { 104813, false }, - { 104827, true }, - { 104849, true }, + { 104622, false }, + { 104633, true }, + { 104643, true }, + { 104658, true }, + { 104669, true }, + { 104687, true }, + { 104710, true }, + { 104728, true }, + { 104741, false }, + { 104755, true }, + { 104777, true }, + { 104796, true }, + { 104810, true }, + { 104822, false }, + { 104842, true }, + { 104858, true }, { 104868, true }, { 104882, true }, - { 104894, false }, - { 104914, true }, + { 104900, true }, + { 104912, true }, + { 104922, true }, { 104930, true }, - { 104940, true }, - { 104954, true }, - { 104972, true }, - { 104984, true }, - { 104994, true }, - { 105002, true }, + { 104944, true }, + { 104956, true }, + { 104968, true }, + { 104980, true }, + { 104992, true }, + { 105004, true }, { 105016, true }, { 105028, true }, { 105040, true }, { 105052, true }, - { 105064, true }, - { 105076, true }, - { 105088, true }, - { 105100, true }, - { 105112, true }, - { 105124, true }, - { 105140, true }, - { 105149, true }, - { 105163, true }, - { 105179, true }, - { 105192, true }, - { 105215, true }, - { 105228, true }, - { 105236, false }, - { 105252, true }, - { 105270, true }, - { 105284, true }, - { 105294, true }, - { 105303, true }, - { 105316, true }, - { 105332, true }, - { 105349, false }, - { 105363, true }, - { 105383, true }, - { 105399, false }, - { 105411, true }, - { 105418, true }, - { 105433, true }, - { 105448, true }, - { 105460, true }, - { 105478, true }, - { 105497, true }, - { 105519, true }, - { 105539, true }, - { 105556, true }, - { 105574, true }, - { 105592, true }, - { 105609, true }, - { 105623, true }, + { 105068, true }, + { 105077, true }, + { 105091, true }, + { 105107, true }, + { 105120, true }, + { 105143, true }, + { 105156, true }, + { 105164, false }, + { 105180, true }, + { 105198, true }, + { 105212, true }, + { 105222, true }, + { 105231, true }, + { 105244, true }, + { 105260, true }, + { 105277, false }, + { 105291, true }, + { 105311, true }, + { 105327, false }, + { 105339, true }, + { 105346, true }, + { 105361, true }, + { 105376, true }, + { 105388, true }, + { 105406, true }, + { 105425, true }, + { 105447, true }, + { 105467, true }, + { 105484, true }, + { 105502, true }, + { 105520, true }, + { 105537, true }, + { 105551, true }, + { 105567, true }, + { 105584, true }, + { 105605, true }, + { 105620, true }, { 105639, true }, - { 105656, true }, - { 105677, true }, - { 105692, true }, - { 105711, true }, - { 105735, true }, - { 105752, true }, - { 105765, true }, - { 105776, true }, - { 105789, true }, - { 105802, true }, - { 105816, true }, - { 105826, true }, - { 105837, true }, - { 105848, true }, - { 105860, true }, - { 105869, true }, - { 105878, true }, - { 105889, true }, - { 105914, true }, - { 105925, true }, - { 105948, true }, - { 105969, true }, - { 105987, true }, - { 106006, false }, - { 106020, true }, - { 106031, true }, - { 106044, true }, - { 106059, true }, - { 106070, true }, - { 106081, true }, - { 106094, true }, - { 106108, true }, - { 106121, true }, - { 106135, true }, - { 106148, true }, - { 106159, true }, - { 106172, true }, - { 106186, true }, - { 106195, false }, - { 106210, true }, - { 106221, true }, - { 106234, true }, - { 106247, true }, - { 106266, true }, - { 106284, true }, - { 106300, true }, - { 106313, true }, - { 106328, true }, - { 106338, true }, - { 106352, true }, - { 106379, true }, - { 106393, true }, - { 106401, true }, - { 106423, true }, - { 106437, true }, - { 106451, true }, - { 106470, true }, - { 106489, true }, - { 106508, true }, + { 105663, true }, + { 105680, true }, + { 105693, true }, + { 105704, true }, + { 105717, true }, + { 105730, true }, + { 105744, true }, + { 105756, true }, + { 105766, true }, + { 105777, true }, + { 105788, true }, + { 105800, true }, + { 105809, true }, + { 105818, true }, + { 105829, true }, + { 105854, true }, + { 105865, true }, + { 105888, true }, + { 105909, true }, + { 105927, true }, + { 105946, false }, + { 105960, true }, + { 105971, true }, + { 105984, true }, + { 105999, true }, + { 106010, true }, + { 106021, true }, + { 106034, true }, + { 106048, true }, + { 106061, true }, + { 106075, true }, + { 106088, true }, + { 106099, true }, + { 106112, true }, + { 106126, true }, + { 106135, false }, + { 106150, true }, + { 106161, true }, + { 106174, true }, + { 106187, true }, + { 106206, true }, + { 106224, true }, + { 106240, true }, + { 106253, true }, + { 106268, true }, + { 106278, true }, + { 106292, true }, + { 106319, true }, + { 106333, true }, + { 106341, true }, + { 106363, true }, + { 106377, true }, + { 106391, true }, + { 106410, true }, + { 106429, true }, + { 106448, true }, + { 106467, true }, + { 106487, true }, + { 106507, true }, { 106527, true }, - { 106547, true }, - { 106567, true }, - { 106587, true }, - { 106605, true }, - { 106624, true }, - { 106643, true }, - { 106662, true }, - { 106681, true }, - { 106695, true }, - { 106707, true }, - { 106719, true }, - { 106732, false }, - { 106754, true }, - { 106766, true }, - { 106791, true }, - { 106807, true }, - { 106816, true }, - { 106830, true }, - { 106847, true }, - { 106860, true }, - { 106875, true }, - { 106888, true }, - { 106900, true }, - { 106911, true }, - { 106925, true }, - { 106940, true }, - { 106953, true }, - { 106964, true }, - { 106978, true }, - { 106993, true }, - { 107002, true }, - { 107015, true }, - { 107034, true }, - { 107048, true }, - { 107063, true }, - { 107074, true }, - { 107084, true }, - { 107099, true }, - { 107114, true }, - { 107135, true }, - { 107149, true }, - { 107167, true }, - { 107179, true }, - { 107189, true }, - { 107202, true }, - { 107217, true }, - { 107229, true }, - { 107244, true }, - { 107256, true }, + { 106545, true }, + { 106564, true }, + { 106583, true }, + { 106602, true }, + { 106621, true }, + { 106635, true }, + { 106647, true }, + { 106659, true }, + { 106672, false }, + { 106694, true }, + { 106706, true }, + { 106731, true }, + { 106747, true }, + { 106756, true }, + { 106770, true }, + { 106787, true }, + { 106800, true }, + { 106815, true }, + { 106828, true }, + { 106840, true }, + { 106851, true }, + { 106865, true }, + { 106880, true }, + { 106893, true }, + { 106904, true }, + { 106918, true }, + { 106933, true }, + { 106942, true }, + { 106955, true }, + { 106974, true }, + { 106988, true }, + { 107003, true }, + { 107014, true }, + { 107024, true }, + { 107039, true }, + { 107054, true }, + { 107075, true }, + { 107089, true }, + { 107107, true }, + { 107119, true }, + { 107129, true }, + { 107142, true }, + { 107157, true }, + { 107169, true }, + { 107184, true }, + { 107196, true }, + { 107204, true }, + { 107222, false }, + { 107232, true }, + { 107247, true }, { 107264, true }, - { 107282, false }, + { 107279, true }, { 107292, true }, - { 107307, true }, - { 107324, true }, - { 107339, true }, - { 107352, true }, - { 107368, true }, - { 107388, true }, - { 107403, true }, - { 107419, true }, - { 107433, true }, - { 107445, true }, - { 107458, true }, - { 107468, true }, - { 107482, true }, - { 107492, true }, - { 107512, true }, - { 107521, true }, - { 107531, true }, - { 107542, false }, - { 107551, true }, + { 107308, true }, + { 107328, true }, + { 107343, true }, + { 107359, true }, + { 107373, true }, + { 107385, true }, + { 107398, true }, + { 107408, true }, + { 107422, true }, + { 107432, true }, + { 107452, true }, + { 107461, true }, + { 107471, true }, + { 107482, false }, + { 107491, true }, + { 107504, true }, + { 107523, true }, + { 107533, true }, + { 107544, true }, + { 107557, true }, { 107564, true }, - { 107583, true }, - { 107593, true }, - { 107604, true }, - { 107617, true }, - { 107624, true }, - { 107640, true }, - { 107651, true }, + { 107580, true }, + { 107591, true }, + { 107598, true }, + { 107607, true }, + { 107615, true }, + { 107625, true }, + { 107646, true }, { 107658, true }, - { 107667, true }, - { 107675, true }, - { 107685, true }, + { 107669, true }, + { 107679, true }, + { 107690, true }, + { 107697, true }, { 107706, true }, - { 107718, true }, - { 107729, true }, - { 107739, true }, - { 107750, true }, - { 107757, true }, - { 107766, true }, - { 107774, true }, - { 107785, true }, - { 107797, true }, - { 107805, true }, - { 107813, true }, - { 107827, true }, - { 107837, true }, - { 107849, true }, - { 107863, true }, - { 107893, true }, - { 107913, true }, - { 107927, false }, - { 107945, false }, - { 107961, true }, - { 107976, true }, - { 107997, true }, - { 108016, true }, + { 107714, true }, + { 107725, true }, + { 107737, true }, + { 107745, true }, + { 107753, true }, + { 107767, true }, + { 107777, true }, + { 107789, true }, + { 107803, true }, + { 107833, true }, + { 107853, true }, + { 107867, false }, + { 107885, false }, + { 107901, true }, + { 107916, true }, + { 107937, true }, + { 107956, true }, + { 107969, true }, + { 107980, true }, + { 107990, true }, + { 108001, true }, + { 108015, true }, { 108029, true }, - { 108040, true }, - { 108050, true }, - { 108061, true }, - { 108075, true }, - { 108089, true }, - { 108102, true }, - { 108112, false }, - { 108128, true }, - { 108147, true }, - { 108173, true }, - { 108196, true }, - { 108213, true }, - { 108229, true }, - { 108242, true }, - { 108249, true }, - { 108261, true }, - { 108273, false }, - { 108291, true }, - { 108304, true }, - { 108315, true }, - { 108325, false }, - { 108341, true }, - { 108352, true }, - { 108361, true }, - { 108369, true }, - { 108380, true }, - { 108396, true }, - { 108408, false }, - { 108423, true }, - { 108438, true }, - { 108453, true }, + { 108042, true }, + { 108052, false }, + { 108068, true }, + { 108087, true }, + { 108113, true }, + { 108136, true }, + { 108153, true }, + { 108169, true }, + { 108182, true }, + { 108189, true }, + { 108201, true }, + { 108213, false }, + { 108231, true }, + { 108244, true }, + { 108255, true }, + { 108265, false }, + { 108281, true }, + { 108292, true }, + { 108301, true }, + { 108309, true }, + { 108320, true }, + { 108336, true }, + { 108348, false }, + { 108363, true }, + { 108378, true }, + { 108393, true }, + { 108412, true }, + { 108432, true }, + { 108443, true }, + { 108457, true }, { 108472, true }, - { 108492, true }, - { 108503, true }, - { 108517, true }, - { 108532, true }, - { 108548, true }, - { 108570, true }, - { 108583, true }, - { 108602, true }, - { 108615, true }, - { 108624, true }, - { 108639, true }, - { 108652, true }, - { 108664, true }, - { 108681, true }, - { 108705, true }, + { 108488, true }, + { 108510, true }, + { 108523, true }, + { 108542, true }, + { 108555, true }, + { 108564, true }, + { 108579, true }, + { 108592, true }, + { 108604, true }, + { 108621, true }, + { 108645, true }, + { 108662, true }, + { 108674, true }, + { 108687, true }, + { 108702, true }, + { 108709, true }, { 108722, true }, - { 108734, true }, - { 108747, true }, - { 108762, true }, - { 108769, true }, - { 108782, true }, - { 108795, true }, - { 108809, true }, - { 108826, true }, - { 108841, true }, - { 108853, true }, - { 108861, true }, - { 108876, true }, - { 108891, true }, - { 108906, true }, - { 108925, true }, - { 108944, true }, - { 108963, true }, - { 108978, true }, - { 108988, true }, - { 109001, true }, - { 109015, true }, - { 109026, true }, - { 109041, true }, - { 109057, true }, - { 109070, true }, - { 109083, true }, - { 109103, true }, - { 109112, true }, - { 109128, true }, - { 109141, true }, - { 109156, true }, - { 109165, true }, - { 109178, true }, - { 109196, true }, - { 109204, true }, - { 109217, true }, - { 109235, true }, - { 109253, true }, - { 109284, true }, - { 109314, true }, - { 109336, true }, - { 109352, true }, - { 109363, false }, - { 109376, true }, - { 109388, true }, - { 109403, true }, - { 109420, false }, - { 109439, true }, - { 109450, true }, - { 109466, false }, - { 109474, true }, - { 109484, true }, - { 109500, true }, + { 108735, true }, + { 108749, true }, + { 108766, true }, + { 108781, true }, + { 108793, true }, + { 108801, true }, + { 108816, true }, + { 108831, true }, + { 108846, true }, + { 108865, true }, + { 108884, true }, + { 108903, true }, + { 108918, true }, + { 108928, true }, + { 108941, true }, + { 108955, true }, + { 108966, true }, + { 108981, true }, + { 108997, true }, + { 109010, true }, + { 109023, true }, + { 109043, true }, + { 109052, true }, + { 109068, true }, + { 109081, true }, + { 109096, true }, + { 109105, true }, + { 109118, true }, + { 109136, true }, + { 109144, true }, + { 109157, true }, + { 109175, true }, + { 109193, true }, + { 109224, true }, + { 109254, true }, + { 109276, true }, + { 109292, true }, + { 109303, false }, + { 109316, true }, + { 109328, true }, + { 109343, true }, + { 109360, false }, + { 109379, true }, + { 109390, true }, + { 109406, false }, + { 109414, true }, + { 109424, true }, + { 109440, true }, + { 109451, true }, + { 109468, true }, + { 109481, true }, + { 109501, true }, { 109511, true }, - { 109528, true }, - { 109541, true }, - { 109561, true }, - { 109571, true }, - { 109582, true }, - { 109592, true }, - { 109607, true }, - { 109622, true }, - { 109639, true }, - { 109654, true }, - { 109665, true }, - { 109678, true }, - { 109691, true }, - { 109704, true }, - { 109721, true }, - { 109733, true }, - { 109746, true }, - { 109755, true }, - { 109766, true }, - { 109776, true }, - { 109790, true }, - { 109801, true }, - { 109809, true }, - { 109818, true }, - { 109832, true }, - { 109842, true }, - { 109854, true }, - { 109864, true }, - { 109873, true }, - { 109886, true }, - { 109897, true }, - { 109905, true }, - { 109912, true }, - { 109923, false }, - { 109943, false }, - { 109959, true }, - { 109979, true }, - { 109993, false }, - { 110004, true }, - { 110020, true }, - { 110033, true }, - { 110051, true }, - { 110065, true }, - { 110082, true }, - { 110101, true }, - { 110124, true }, - { 110136, true }, - { 110146, true }, - { 110160, true }, - { 110170, true }, - { 110181, true }, - { 110190, true }, + { 109522, true }, + { 109532, true }, + { 109547, true }, + { 109562, true }, + { 109579, true }, + { 109594, true }, + { 109605, true }, + { 109618, true }, + { 109631, true }, + { 109644, true }, + { 109661, true }, + { 109673, true }, + { 109686, true }, + { 109695, true }, + { 109706, true }, + { 109716, true }, + { 109730, true }, + { 109741, true }, + { 109749, true }, + { 109758, true }, + { 109772, true }, + { 109782, true }, + { 109794, true }, + { 109804, true }, + { 109813, true }, + { 109826, true }, + { 109837, true }, + { 109845, true }, + { 109852, true }, + { 109863, false }, + { 109883, false }, + { 109899, true }, + { 109919, true }, + { 109933, false }, + { 109944, true }, + { 109960, true }, + { 109973, true }, + { 109991, true }, + { 110005, true }, + { 110022, true }, + { 110041, true }, + { 110064, true }, + { 110076, true }, + { 110086, true }, + { 110100, true }, + { 110110, true }, + { 110121, true }, + { 110130, true }, + { 110139, true }, + { 110152, true }, + { 110169, true }, + { 110185, true }, { 110199, true }, - { 110212, true }, - { 110229, true }, - { 110245, true }, - { 110259, true }, - { 110267, true }, - { 110281, true }, - { 110300, true }, - { 110316, true }, - { 110329, true }, - { 110344, true }, - { 110355, true }, - { 110366, true }, - { 110380, true }, - { 110395, true }, - { 110416, true }, - { 110432, true }, - { 110450, true }, - { 110468, true }, - { 110481, true }, - { 110493, true }, - { 110509, true }, - { 110533, true }, - { 110550, true }, - { 110561, true }, - { 110580, true }, + { 110207, true }, + { 110221, true }, + { 110240, true }, + { 110256, true }, + { 110269, true }, + { 110284, true }, + { 110295, true }, + { 110306, true }, + { 110320, true }, + { 110335, true }, + { 110356, true }, + { 110372, true }, + { 110390, true }, + { 110408, true }, + { 110421, true }, + { 110433, true }, + { 110449, true }, + { 110473, true }, + { 110490, true }, + { 110501, true }, + { 110520, true }, + { 110528, true }, + { 110542, true }, + { 110551, true }, + { 110558, false }, + { 110568, false }, { 110588, true }, - { 110602, true }, - { 110611, true }, - { 110618, false }, - { 110628, false }, - { 110648, true }, - { 110658, false }, - { 110677, false }, - { 110690, false }, - { 110701, false }, - { 110713, true }, - { 110734, true }, - { 110747, true }, - { 110760, true }, - { 110778, true }, - { 110787, true }, - { 110803, true }, - { 110816, true }, - { 110840, false }, - { 110856, true }, - { 110874, true }, + { 110598, false }, + { 110617, false }, + { 110630, false }, + { 110641, false }, + { 110653, true }, + { 110674, true }, + { 110687, true }, + { 110700, true }, + { 110718, true }, + { 110727, true }, + { 110743, true }, + { 110756, true }, + { 110780, false }, + { 110796, true }, + { 110814, true }, + { 110826, true }, + { 110843, true }, + { 110857, true }, + { 110872, true }, { 110886, true }, - { 110903, true }, - { 110917, true }, - { 110932, true }, - { 110946, true }, - { 110964, true }, - { 110974, false }, - { 111003, true }, - { 111027, true }, - { 111037, true }, - { 111048, true }, - { 111061, true }, - { 111076, true }, - { 111090, true }, - { 111105, true }, - { 111123, true }, - { 111133, false }, - { 111148, true }, - { 111161, false }, - { 111175, true }, + { 110904, true }, + { 110914, false }, + { 110943, true }, + { 110967, true }, + { 110977, true }, + { 110988, true }, + { 111001, true }, + { 111016, true }, + { 111030, true }, + { 111045, true }, + { 111063, true }, + { 111073, false }, + { 111088, true }, + { 111101, false }, + { 111115, true }, + { 111126, true }, + { 111134, true }, + { 111142, true }, + { 111154, true }, + { 111166, true }, { 111186, true }, - { 111194, true }, - { 111202, true }, - { 111214, true }, - { 111226, true }, - { 111246, true }, - { 111269, true }, - { 111288, true }, - { 111307, true }, - { 111326, true }, - { 111345, true }, - { 111364, true }, - { 111383, true }, - { 111402, true }, - { 111419, true }, - { 111437, true }, - { 111454, true }, - { 111467, true }, - { 111481, true }, - { 111496, true }, - { 111509, false }, - { 111523, true }, - { 111547, true }, - { 111564, true }, - { 111582, true }, - { 111598, true }, - { 111616, true }, + { 111209, true }, + { 111228, true }, + { 111247, true }, + { 111266, true }, + { 111285, true }, + { 111304, true }, + { 111323, true }, + { 111342, true }, + { 111359, true }, + { 111377, true }, + { 111394, true }, + { 111407, true }, + { 111421, true }, + { 111436, true }, + { 111449, false }, + { 111463, true }, + { 111487, true }, + { 111504, true }, + { 111520, true }, + { 111538, true }, + { 111555, true }, + { 111571, true }, + { 111584, true }, + { 111601, true }, { 111633, true }, - { 111649, true }, - { 111662, true }, - { 111679, true }, - { 111711, true }, - { 111728, true }, - { 111736, true }, - { 111749, true }, - { 111776, true }, - { 111792, true }, - { 111808, true }, - { 111822, true }, - { 111835, true }, - { 111848, true }, - { 111858, true }, - { 111871, true }, - { 111881, true }, + { 111650, true }, + { 111658, true }, + { 111671, true }, + { 111698, true }, + { 111714, true }, + { 111730, true }, + { 111744, true }, + { 111757, true }, + { 111770, true }, + { 111780, true }, + { 111793, true }, + { 111803, true }, + { 111818, true }, + { 111833, false }, + { 111843, false }, + { 111853, true }, + { 111865, true }, + { 111876, false }, + { 111883, true }, { 111896, true }, - { 111911, false }, - { 111921, false }, - { 111931, true }, - { 111943, true }, - { 111954, false }, - { 111961, true }, - { 111974, true }, - { 111986, true }, - { 112006, true }, - { 112017, true }, - { 112038, true }, - { 112054, true }, - { 112073, true }, - { 112083, true }, - { 112094, true }, - { 112103, true }, + { 111908, true }, + { 111928, true }, + { 111939, true }, + { 111960, true }, + { 111976, true }, + { 111995, true }, + { 112005, true }, + { 112016, true }, + { 112025, true }, + { 112034, true }, + { 112047, true }, + { 112076, true }, + { 112095, true }, { 112112, true }, - { 112125, true }, - { 112142, true }, - { 112171, true }, - { 112190, true }, - { 112207, true }, - { 112230, true }, - { 112238, true }, - { 112256, false }, - { 112270, false }, - { 112281, true }, - { 112294, true }, - { 112305, true }, - { 112318, true }, - { 112335, true }, - { 112348, true }, - { 112359, false }, - { 112371, true }, - { 112380, true }, - { 112390, true }, - { 112399, true }, - { 112409, true }, + { 112135, true }, + { 112143, true }, + { 112161, false }, + { 112175, false }, + { 112186, true }, + { 112199, true }, + { 112210, true }, + { 112223, true }, + { 112240, true }, + { 112253, true }, + { 112264, false }, + { 112276, true }, + { 112285, true }, + { 112295, true }, + { 112304, true }, + { 112314, true }, + { 112327, true }, + { 112337, true }, + { 112350, true }, + { 112360, true }, + { 112369, true }, + { 112382, true }, + { 112393, true }, + { 112407, true }, { 112422, true }, - { 112432, true }, - { 112445, true }, - { 112455, true }, - { 112464, true }, - { 112477, true }, - { 112488, true }, - { 112502, true }, - { 112517, true }, - { 112531, true }, - { 112542, true }, - { 112554, true }, - { 112562, true }, - { 112576, true }, - { 112591, false }, - { 112605, true }, - { 112617, true }, - { 112632, true }, - { 112646, true }, - { 112655, true }, - { 112674, true }, + { 112436, true }, + { 112447, true }, + { 112459, true }, + { 112467, true }, + { 112481, true }, + { 112496, false }, + { 112510, true }, + { 112522, true }, + { 112537, true }, + { 112551, true }, + { 112560, true }, + { 112579, true }, + { 112594, true }, + { 112606, true }, + { 112619, true }, + { 112629, true }, + { 112650, true }, + { 112668, true }, { 112689, true }, - { 112701, true }, - { 112714, true }, - { 112724, true }, - { 112745, true }, - { 112763, true }, - { 112784, true }, - { 112810, true }, - { 112833, true }, - { 112852, true }, - { 112877, true }, - { 112901, true }, - { 112912, true }, - { 112923, true }, - { 112934, true }, - { 112948, true }, - { 112959, true }, - { 112969, true }, - { 112977, true }, - { 112984, true }, - { 112995, true }, + { 112715, true }, + { 112738, true }, + { 112757, true }, + { 112782, true }, + { 112806, true }, + { 112817, true }, + { 112828, true }, + { 112839, true }, + { 112853, true }, + { 112864, true }, + { 112874, true }, + { 112882, true }, + { 112889, true }, + { 112900, true }, + { 112911, true }, + { 112926, true }, + { 112941, true }, + { 112952, true }, + { 112961, true }, + { 112970, true }, + { 112981, true }, + { 112992, true }, { 113006, true }, - { 113021, true }, - { 113036, true }, + { 113015, true }, + { 113023, true }, + { 113035, true }, { 113047, true }, - { 113056, true }, - { 113065, true }, - { 113076, true }, - { 113087, true }, - { 113101, true }, - { 113110, true }, - { 113118, true }, - { 113130, true }, - { 113140, true }, - { 113159, true }, - { 113167, true }, - { 113180, true }, - { 113189, true }, - { 113210, true }, - { 113229, true }, - { 113245, true }, - { 113260, true }, - { 113273, true }, - { 113289, true }, - { 113297, true }, - { 113311, true }, - { 113330, false }, - { 113339, true }, - { 113349, true }, - { 113371, true }, - { 113393, true }, - { 113408, true }, - { 113421, false }, - { 113435, true }, - { 113449, true }, - { 113457, true }, - { 113469, true }, - { 113480, true }, - { 113492, true }, - { 113502, true }, - { 113511, true }, - { 113521, true }, - { 113531, true }, - { 113546, true }, - { 113558, true }, - { 113571, true }, - { 113581, true }, - { 113594, true }, - { 113605, true }, - { 113628, false }, - { 113642, true }, - { 113654, true }, + { 113063, true }, + { 113073, true }, + { 113092, true }, + { 113100, true }, + { 113113, true }, + { 113122, true }, + { 113143, true }, + { 113162, true }, + { 113178, true }, + { 113193, true }, + { 113206, true }, + { 113222, true }, + { 113230, true }, + { 113244, true }, + { 113263, false }, + { 113272, true }, + { 113282, true }, + { 113304, true }, + { 113326, true }, + { 113341, true }, + { 113354, false }, + { 113368, true }, + { 113376, true }, + { 113388, true }, + { 113399, true }, + { 113411, true }, + { 113421, true }, + { 113430, true }, + { 113440, true }, + { 113450, true }, + { 113465, true }, + { 113477, true }, + { 113490, true }, + { 113500, true }, + { 113513, true }, + { 113524, true }, + { 113547, false }, + { 113561, true }, + { 113573, true }, + { 113586, true }, + { 113599, true }, + { 113610, true }, + { 113624, true }, + { 113638, true }, + { 113648, true }, + { 113657, true }, { 113667, true }, - { 113680, true }, - { 113691, true }, - { 113705, true }, - { 113719, true }, - { 113729, true }, - { 113738, true }, - { 113748, true }, + { 113682, true }, + { 113694, true }, + { 113708, true }, + { 113725, true }, + { 113735, false }, + { 113744, false }, { 113763, true }, - { 113775, true }, - { 113787, true }, - { 113801, true }, - { 113818, true }, - { 113828, false }, - { 113837, false }, - { 113856, true }, - { 113872, true }, - { 113887, true }, - { 113902, true }, - { 113914, true }, - { 113927, true }, - { 113939, true }, - { 113952, true }, - { 113970, true }, - { 113985, true }, - { 114000, false }, - { 114016, true }, - { 114028, true }, - { 114040, true }, - { 114051, true }, - { 114064, false }, - { 114079, true }, - { 114094, true }, - { 114104, true }, - { 114124, true }, - { 114134, true }, - { 114148, true }, - { 114162, true }, - { 114173, true }, - { 114189, true }, - { 114200, true }, - { 114218, true }, - { 114236, true }, - { 114249, true }, - { 114270, false }, - { 114289, true }, - { 114309, true }, - { 114331, true }, - { 114343, true }, - { 114361, true }, - { 114376, true }, - { 114388, true }, - { 114404, true }, - { 114419, true }, - { 114435, true }, - { 114451, true }, - { 114468, true }, - { 114490, true }, - { 114501, true }, - { 114517, false }, - { 114530, true }, - { 114550, true }, - { 114565, true }, - { 114588, true }, - { 114603, true }, + { 113779, true }, + { 113794, true }, + { 113809, true }, + { 113821, true }, + { 113834, true }, + { 113846, true }, + { 113859, true }, + { 113877, true }, + { 113892, true }, + { 113907, false }, + { 113923, true }, + { 113935, true }, + { 113947, true }, + { 113958, true }, + { 113971, false }, + { 113986, true }, + { 114001, true }, + { 114011, true }, + { 114031, true }, + { 114041, true }, + { 114055, true }, + { 114069, true }, + { 114080, true }, + { 114096, true }, + { 114107, true }, + { 114125, true }, + { 114143, true }, + { 114156, true }, + { 114177, false }, + { 114196, true }, + { 114216, true }, + { 114238, true }, + { 114250, true }, + { 114268, true }, + { 114283, true }, + { 114295, true }, + { 114311, true }, + { 114326, true }, + { 114342, true }, + { 114358, true }, + { 114375, true }, + { 114397, true }, + { 114408, true }, + { 114424, false }, + { 114437, true }, + { 114457, true }, + { 114472, true }, + { 114495, true }, + { 114510, true }, + { 114535, true }, + { 114553, true }, + { 114568, true }, + { 114584, true }, + { 114599, true }, { 114628, true }, - { 114646, true }, - { 114661, true }, - { 114677, true }, - { 114692, true }, - { 114721, true }, - { 114746, true }, - { 114768, true }, - { 114786, true }, - { 114800, true }, - { 114813, true }, - { 114820, true }, - { 114836, true }, - { 114847, true }, - { 114858, true }, + { 114653, true }, + { 114675, true }, + { 114693, true }, + { 114707, true }, + { 114720, true }, + { 114727, true }, + { 114743, true }, + { 114754, true }, + { 114765, true }, + { 114775, true }, + { 114789, true }, + { 114803, true }, + { 114815, true }, + { 114827, true }, + { 114838, true }, + { 114853, true }, { 114868, true }, - { 114882, true }, - { 114896, true }, - { 114908, true }, + { 114875, true }, + { 114885, true }, + { 114895, true }, + { 114904, true }, { 114920, true }, - { 114931, true }, - { 114946, true }, - { 114961, true }, - { 114968, true }, - { 114978, true }, - { 114988, true }, - { 114997, true }, - { 115013, true }, - { 115022, true }, - { 115031, true }, - { 115046, true }, - { 115055, true }, - { 115067, true }, - { 115083, true }, - { 115102, true }, - { 115114, false }, - { 115131, true }, - { 115151, true }, - { 115166, true }, - { 115179, true }, - { 115197, true }, - { 115212, true }, - { 115221, true }, - { 115237, true }, - { 115252, true }, - { 115266, true }, - { 115282, true }, - { 115297, true }, - { 115316, true }, + { 114929, true }, + { 114938, true }, + { 114947, true }, + { 114959, true }, + { 114975, true }, + { 114994, true }, + { 115006, false }, + { 115023, true }, + { 115043, true }, + { 115058, true }, + { 115071, true }, + { 115089, true }, + { 115104, true }, + { 115113, true }, + { 115129, true }, + { 115144, true }, + { 115158, true }, + { 115174, true }, + { 115189, true }, + { 115208, true }, + { 115224, true }, + { 115235, true }, + { 115244, true }, + { 115254, true }, + { 115273, true }, + { 115288, true }, + { 115302, true }, + { 115315, true }, + { 115323, true }, { 115332, true }, - { 115343, true }, - { 115352, true }, - { 115362, true }, - { 115381, true }, - { 115396, true }, - { 115410, true }, - { 115423, true }, - { 115431, true }, - { 115440, true }, - { 115452, true }, - { 115461, true }, - { 115473, true }, - { 115481, true }, - { 115493, true }, - { 115519, true }, - { 115542, false }, - { 115558, true }, - { 115579, true }, - { 115598, true }, + { 115344, true }, + { 115353, true }, + { 115365, true }, + { 115373, true }, + { 115385, true }, + { 115411, true }, + { 115434, false }, + { 115450, true }, + { 115471, true }, + { 115490, true }, + { 115504, true }, + { 115518, true }, + { 115535, true }, + { 115549, true }, + { 115563, false }, + { 115578, true }, + { 115586, true }, + { 115601, true }, { 115612, true }, { 115626, true }, - { 115643, true }, - { 115657, true }, - { 115671, false }, - { 115686, true }, - { 115694, true }, - { 115709, true }, - { 115720, true }, + { 115637, true }, + { 115655, true }, + { 115672, true }, + { 115692, true }, + { 115716, true }, + { 115723, true }, { 115734, true }, { 115745, true }, - { 115763, true }, - { 115780, true }, - { 115800, true }, - { 115824, true }, - { 115831, true }, - { 115842, true }, - { 115853, true }, - { 115866, true }, - { 115878, false }, + { 115758, true }, + { 115770, false }, + { 115785, true }, + { 115798, true }, + { 115808, true }, + { 115823, false }, + { 115832, true }, + { 115846, true }, + { 115861, true }, + { 115871, true }, + { 115883, true }, { 115893, true }, { 115906, true }, - { 115916, true }, - { 115931, false }, - { 115940, true }, - { 115954, true }, - { 115969, true }, - { 115979, true }, - { 115991, true }, - { 116001, true }, - { 116014, true }, + { 115918, true }, + { 115926, true }, + { 115936, true }, + { 115947, true }, + { 115968, true }, + { 115978, false }, + { 115998, true }, + { 116009, true }, + { 116016, true }, { 116026, true }, - { 116034, true }, - { 116044, true }, - { 116055, true }, - { 116076, true }, - { 116086, false }, - { 116106, true }, - { 116117, true }, - { 116124, true }, - { 116134, true }, + { 116036, true }, + { 116044, false }, + { 116064, true }, + { 116073, true }, + { 116082, true }, + { 116090, true }, + { 116104, true }, + { 116119, true }, + { 116131, true }, { 116144, true }, - { 116152, false }, - { 116172, true }, + { 116152, true }, + { 116170, true }, { 116181, true }, - { 116190, true }, - { 116198, true }, - { 116212, true }, - { 116227, true }, - { 116239, true }, - { 116252, true }, - { 116260, true }, - { 116278, true }, - { 116289, true }, - { 116297, true }, - { 116307, true }, - { 116316, true }, - { 116329, true }, - { 116344, true }, - { 116356, true }, - { 116368, true }, - { 116382, true }, - { 116398, true }, - { 116416, true }, - { 116429, true }, - { 116442, false }, - { 116455, true }, - { 116469, true }, - { 116488, true }, - { 116496, true }, - { 116508, true }, - { 116528, true }, - { 116541, true }, - { 116553, true }, - { 116579, true }, - { 116597, true }, - { 116614, true }, - { 116625, true }, - { 116638, true }, - { 116654, true }, - { 116668, true }, - { 116686, true }, + { 116189, true }, + { 116199, true }, + { 116208, true }, + { 116221, true }, + { 116233, true }, + { 116247, true }, + { 116263, true }, + { 116281, true }, + { 116294, true }, + { 116307, false }, + { 116320, true }, + { 116334, true }, + { 116353, true }, + { 116361, true }, + { 116373, true }, + { 116393, true }, + { 116406, true }, + { 116418, true }, + { 116444, true }, + { 116462, true }, + { 116479, true }, + { 116490, true }, + { 116503, true }, + { 116519, true }, + { 116533, true }, + { 116551, true }, + { 116567, true }, + { 116590, true }, + { 116609, true }, + { 116623, true }, + { 116639, true }, + { 116656, true }, + { 116686, false }, { 116702, true }, + { 116714, true }, { 116725, true }, - { 116744, true }, - { 116758, true }, - { 116774, true }, - { 116791, true }, - { 116821, false }, - { 116837, true }, - { 116849, true }, - { 116860, true }, - { 116873, true }, - { 116887, true }, - { 116904, true }, - { 116919, true }, - { 116934, true }, - { 116945, true }, + { 116738, true }, + { 116752, true }, + { 116769, true }, + { 116784, true }, + { 116799, true }, + { 116810, true }, + { 116828, true }, + { 116844, true }, + { 116856, true }, + { 116866, true }, + { 116883, true }, + { 116899, true }, + { 116911, false }, + { 116925, true }, + { 116939, true }, + { 116949, true }, { 116963, true }, - { 116979, true }, - { 116991, true }, - { 117001, true }, - { 117018, true }, - { 117034, true }, - { 117046, false }, - { 117060, true }, - { 117074, true }, - { 117084, true }, + { 116975, true }, + { 116989, true }, + { 117005, true }, + { 117020, true }, + { 117031, true }, + { 117042, true }, + { 117054, true }, + { 117063, true }, + { 117072, true }, + { 117079, true }, + { 117090, true }, { 117098, true }, - { 117110, true }, - { 117124, true }, - { 117140, true }, - { 117155, true }, - { 117166, true }, + { 117105, true }, + { 117115, true }, + { 117123, true }, + { 117131, true }, + { 117139, true }, + { 117152, true }, + { 117167, true }, { 117177, true }, - { 117189, true }, - { 117198, true }, - { 117207, true }, - { 117214, true }, - { 117225, true }, - { 117233, true }, - { 117240, true }, - { 117250, true }, - { 117258, true }, - { 117266, true }, - { 117274, true }, - { 117287, true }, - { 117302, true }, - { 117312, true }, - { 117319, true }, - { 117331, true }, - { 117347, true }, - { 117359, true }, - { 117371, true }, - { 117383, true }, - { 117394, true }, - { 117402, true }, - { 117413, true }, - { 117424, true }, - { 117440, true }, - { 117452, false }, - { 117462, true }, - { 117483, true }, - { 117504, true }, - { 117519, true }, - { 117536, true }, - { 117549, true }, - { 117563, true }, - { 117574, true }, - { 117583, true }, - { 117593, true }, - { 117600, true }, - { 117608, true }, - { 117620, true }, - { 117629, true }, - { 117638, true }, - { 117646, true }, - { 117661, true }, - { 117669, true }, - { 117681, false }, - { 117691, true }, + { 117184, true }, + { 117196, true }, + { 117212, true }, + { 117224, true }, + { 117236, true }, + { 117248, true }, + { 117259, true }, + { 117267, true }, + { 117278, true }, + { 117289, true }, + { 117305, true }, + { 117317, false }, + { 117327, true }, + { 117348, true }, + { 117369, true }, + { 117384, true }, + { 117401, true }, + { 117414, true }, + { 117428, true }, + { 117439, true }, + { 117448, true }, + { 117458, true }, + { 117465, true }, + { 117473, true }, + { 117485, true }, + { 117494, true }, + { 117503, true }, + { 117511, true }, + { 117526, true }, + { 117534, true }, + { 117546, false }, + { 117556, true }, + { 117566, true }, + { 117577, true }, + { 117586, true }, + { 117604, true }, + { 117614, false }, + { 117625, true }, + { 117633, true }, + { 117641, false }, + { 117649, true }, + { 117665, true }, + { 117678, true }, + { 117689, true }, { 117701, true }, - { 117712, true }, - { 117721, true }, - { 117739, true }, - { 117749, false }, + { 117720, true }, + { 117746, true }, { 117760, true }, - { 117768, true }, - { 117776, false }, - { 117784, true }, - { 117800, true }, - { 117813, true }, - { 117824, true }, - { 117836, true }, - { 117855, true }, + { 117774, false }, + { 117792, true }, + { 117808, true }, + { 117823, true }, + { 117834, true }, + { 117853, true }, + { 117869, true }, { 117881, true }, - { 117895, true }, - { 117909, false }, - { 117927, true }, - { 117943, true }, - { 117958, true }, - { 117969, true }, - { 117988, true }, - { 118004, true }, - { 118016, true }, - { 118028, true }, - { 118041, true }, - { 118053, true }, - { 118066, true }, - { 118083, true }, - { 118105, true }, - { 118115, true }, - { 118125, true }, - { 118137, false }, - { 118148, true }, - { 118162, true }, - { 118171, true }, - { 118182, true }, - { 118198, true }, - { 118211, true }, - { 118227, true }, - { 118254, true }, - { 118266, true }, - { 118280, true }, - { 118290, false }, - { 118313, true }, - { 118330, true }, - { 118339, true }, - { 118351, true }, - { 118365, true }, - { 118374, true }, - { 118382, true }, - { 118395, true }, - { 118420, true }, - { 118431, true }, - { 118444, true }, - { 118458, true }, - { 118471, false }, - { 118482, true }, - { 118494, true }, - { 118505, true }, - { 118520, true }, + { 117893, true }, + { 117906, true }, + { 117918, true }, + { 117931, true }, + { 117948, true }, + { 117970, true }, + { 117980, true }, + { 117990, true }, + { 118002, false }, + { 118013, true }, + { 118027, true }, + { 118036, true }, + { 118047, true }, + { 118063, true }, + { 118076, true }, + { 118092, true }, + { 118119, true }, + { 118131, true }, + { 118145, true }, + { 118155, false }, + { 118178, true }, + { 118195, true }, + { 118204, true }, + { 118216, true }, + { 118230, true }, + { 118239, true }, + { 118247, true }, + { 118260, true }, + { 118285, true }, + { 118296, true }, + { 118309, true }, + { 118323, true }, + { 118336, false }, + { 118347, true }, + { 118355, true }, + { 118367, true }, + { 118378, true }, + { 118393, true }, + { 118413, true }, + { 118421, true }, + { 118435, false }, + { 118448, true }, + { 118469, true }, + { 118479, true }, + { 118492, true }, + { 118523, true }, { 118540, true }, - { 118548, true }, - { 118562, true }, - { 118580, false }, - { 118593, true }, + { 118553, true }, + { 118568, true }, + { 118580, true }, + { 118590, true }, + { 118597, true }, { 118614, true }, - { 118624, true }, - { 118637, true }, + { 118630, true }, + { 118642, true }, + { 118656, true }, { 118668, true }, - { 118685, true }, - { 118698, true }, - { 118713, true }, - { 118725, true }, + { 118683, true }, + { 118701, true }, + { 118714, true }, + { 118724, true }, { 118735, true }, - { 118742, true }, - { 118759, true }, - { 118775, true }, - { 118787, true }, - { 118801, true }, + { 118746, true }, + { 118757, true }, + { 118772, true }, + { 118784, false }, + { 118796, true }, { 118813, true }, - { 118828, true }, - { 118846, true }, - { 118859, true }, - { 118869, true }, - { 118880, true }, - { 118891, true }, - { 118902, true }, - { 118917, true }, - { 118929, false }, - { 118941, true }, - { 118958, true }, - { 118972, true }, - { 118989, true }, - { 118999, true }, - { 119012, false }, - { 119030, true }, - { 119041, true }, - { 119057, true }, - { 119072, true }, - { 119089, true }, - { 119106, true }, - { 119123, true }, - { 119133, true }, - { 119148, true }, - { 119158, true }, - { 119173, true }, - { 119190, true }, - { 119208, true }, - { 119223, true }, - { 119248, true }, - { 119265, true }, - { 119284, true }, - { 119301, true }, - { 119321, true }, - { 119342, true }, - { 119356, true }, + { 118827, true }, + { 118844, true }, + { 118854, true }, + { 118867, false }, + { 118885, true }, + { 118896, true }, + { 118912, true }, + { 118927, true }, + { 118944, true }, + { 118961, true }, + { 118978, true }, + { 118988, true }, + { 119003, true }, + { 119013, true }, + { 119028, true }, + { 119045, true }, + { 119063, true }, + { 119078, true }, + { 119103, true }, + { 119120, true }, + { 119139, true }, + { 119156, true }, + { 119176, true }, + { 119197, true }, + { 119211, true }, + { 119236, true }, + { 119257, true }, + { 119279, true }, + { 119309, true }, + { 119333, true }, + { 119348, true }, + { 119358, true }, { 119381, true }, - { 119402, true }, - { 119424, true }, - { 119454, true }, + { 119392, true }, + { 119399, true }, + { 119413, true }, + { 119432, true }, + { 119439, true }, + { 119459, true }, { 119478, true }, - { 119493, true }, - { 119503, true }, - { 119526, true }, - { 119537, true }, - { 119544, true }, - { 119558, true }, - { 119577, true }, - { 119584, true }, - { 119604, true }, - { 119623, true }, - { 119639, true }, - { 119649, true }, + { 119494, true }, + { 119504, true }, + { 119515, true }, + { 119525, true }, + { 119536, true }, + { 119550, true }, + { 119562, true }, + { 119578, true }, + { 119586, true }, + { 119596, true }, + { 119606, true }, + { 119618, true }, + { 119629, true }, + { 119645, true }, { 119660, true }, - { 119670, true }, - { 119681, true }, - { 119695, true }, - { 119707, true }, - { 119723, true }, - { 119731, true }, - { 119741, true }, - { 119751, true }, - { 119763, true }, - { 119774, true }, - { 119790, true }, - { 119805, true }, - { 119829, true }, + { 119684, true }, + { 119698, true }, + { 119706, true }, + { 119724, true }, + { 119735, true }, + { 119748, true }, + { 119759, true }, + { 119778, true }, + { 119789, true }, + { 119804, true }, + { 119819, false }, + { 119831, true }, { 119843, true }, - { 119851, true }, - { 119869, true }, - { 119880, true }, + { 119861, true }, + { 119881, true }, { 119893, true }, - { 119904, true }, - { 119923, true }, - { 119934, true }, - { 119949, true }, - { 119964, false }, - { 119976, true }, - { 119988, true }, - { 120006, true }, - { 120026, true }, - { 120038, true }, - { 120055, true }, - { 120070, true }, - { 120084, true }, - { 120098, true }, - { 120109, true }, - { 120118, true }, - { 120136, true }, - { 120147, true }, - { 120161, true }, - { 120168, true }, - { 120185, false }, - { 120211, false }, - { 120223, true }, - { 120236, true }, - { 120250, true }, - { 120261, true }, - { 120278, true }, - { 120288, true }, - { 120303, true }, - { 120324, true }, - { 120348, true }, - { 120362, true }, - { 120373, true }, - { 120387, true }, - { 120399, true }, - { 120414, true }, - { 120424, true }, - { 120447, true }, - { 120467, true }, + { 119910, true }, + { 119925, true }, + { 119939, true }, + { 119953, true }, + { 119964, true }, + { 119973, true }, + { 119991, true }, + { 120002, true }, + { 120016, true }, + { 120023, true }, + { 120040, false }, + { 120066, false }, + { 120078, true }, + { 120091, true }, + { 120105, true }, + { 120116, true }, + { 120133, true }, + { 120143, true }, + { 120158, true }, + { 120179, true }, + { 120203, true }, + { 120217, true }, + { 120228, true }, + { 120242, true }, + { 120254, true }, + { 120269, true }, + { 120279, true }, + { 120302, true }, + { 120322, true }, + { 120344, true }, + { 120358, true }, + { 120373, false }, + { 120386, true }, + { 120401, true }, + { 120412, true }, + { 120432, false }, + { 120451, true }, + { 120462, true }, + { 120481, true }, { 120489, true }, - { 120503, true }, - { 120518, false }, - { 120531, true }, - { 120546, true }, - { 120557, true }, - { 120577, true }, - { 120588, true }, - { 120607, true }, - { 120615, true }, - { 120631, true }, - { 120640, true }, - { 120651, true }, - { 120661, true }, - { 120671, true }, - { 120682, true }, - { 120689, true }, - { 120707, true }, - { 120719, true }, - { 120726, true }, - { 120737, true }, - { 120759, true }, - { 120773, true }, - { 120792, true }, - { 120812, true }, - { 120820, true }, - { 120839, true }, - { 120848, true }, - { 120860, true }, - { 120878, true }, - { 120892, true }, - { 120901, true }, - { 120917, true }, + { 120505, true }, + { 120514, true }, + { 120525, true }, + { 120535, true }, + { 120545, true }, + { 120556, true }, + { 120563, true }, + { 120581, true }, + { 120593, true }, + { 120600, true }, + { 120611, true }, + { 120633, true }, + { 120647, true }, + { 120666, true }, + { 120686, true }, + { 120694, true }, + { 120713, true }, + { 120722, true }, + { 120734, true }, + { 120752, true }, + { 120766, true }, + { 120775, true }, + { 120791, true }, + { 120799, true }, + { 120811, true }, + { 120826, true }, + { 120846, true }, + { 120854, true }, + { 120867, true }, + { 120879, true }, + { 120898, true }, + { 120912, true }, { 120925, true }, - { 120937, true }, - { 120952, true }, - { 120972, true }, - { 120980, true }, + { 120949, true }, + { 120965, true }, + { 120979, true }, { 120993, true }, - { 121005, true }, - { 121024, true }, + { 121010, true }, + { 121022, true }, { 121038, true }, - { 121058, true }, - { 121071, true }, - { 121095, true }, - { 121111, true }, - { 121125, true }, - { 121139, true }, - { 121156, true }, - { 121168, true }, - { 121184, true }, - { 121201, true }, - { 121209, true }, - { 121218, true }, - { 121236, true }, - { 121245, false }, - { 121254, true }, - { 121268, true }, - { 121278, true }, - { 121289, true }, - { 121298, true }, - { 121321, true }, - { 121333, true }, - { 121343, false }, - { 121352, true }, - { 121359, true }, - { 121368, true }, - { 121376, true }, - { 121385, true }, - { 121397, false }, - { 121411, true }, - { 121421, true }, - { 121431, true }, - { 121441, false }, - { 121454, true }, - { 121472, true }, - { 121482, true }, - { 121493, true }, - { 121502, true }, - { 121515, true }, - { 121530, true }, - { 121543, true }, - { 121553, true }, - { 121564, true }, - { 121573, true }, - { 121590, true }, - { 121599, true }, - { 121612, true }, - { 121623, true }, - { 121641, true }, - { 121651, true }, - { 121663, true }, - { 121675, false }, - { 121692, true }, - { 121715, true }, - { 121726, true }, - { 121739, true }, - { 121748, true }, - { 121761, false }, - { 121770, false }, - { 121781, true }, - { 121793, false }, - { 121808, false }, - { 121819, false }, - { 121826, true }, - { 121842, true }, - { 121860, true }, - { 121879, true }, - { 121896, true }, - { 121910, true }, - { 121926, true }, - { 121939, true }, - { 121953, true }, - { 121970, true }, - { 121989, true }, - { 122004, false }, + { 121055, true }, + { 121063, true }, + { 121072, true }, + { 121090, true }, + { 121099, false }, + { 121108, true }, + { 121122, true }, + { 121132, true }, + { 121143, true }, + { 121152, true }, + { 121175, true }, + { 121187, true }, + { 121197, false }, + { 121206, true }, + { 121213, true }, + { 121222, true }, + { 121230, true }, + { 121239, true }, + { 121251, false }, + { 121265, true }, + { 121275, true }, + { 121285, true }, + { 121295, false }, + { 121308, true }, + { 121326, true }, + { 121336, true }, + { 121347, true }, + { 121356, true }, + { 121369, true }, + { 121384, true }, + { 121397, true }, + { 121407, true }, + { 121418, true }, + { 121427, true }, + { 121444, true }, + { 121453, true }, + { 121466, true }, + { 121477, true }, + { 121495, true }, + { 121505, true }, + { 121517, true }, + { 121529, false }, + { 121546, true }, + { 121569, true }, + { 121580, true }, + { 121593, true }, + { 121602, true }, + { 121615, false }, + { 121624, false }, + { 121635, true }, + { 121647, false }, + { 121662, false }, + { 121673, false }, + { 121680, true }, + { 121696, true }, + { 121714, true }, + { 121733, true }, + { 121750, true }, + { 121764, true }, + { 121780, true }, + { 121793, true }, + { 121807, true }, + { 121824, true }, + { 121843, true }, + { 121858, false }, + { 121872, true }, + { 121886, true }, + { 121899, true }, + { 121920, true }, + { 121932, true }, + { 121945, true }, + { 121955, true }, + { 121975, true }, + { 121988, true }, + { 122000, true }, { 122018, true }, - { 122032, true }, - { 122045, true }, - { 122066, true }, - { 122078, true }, - { 122091, true }, - { 122101, true }, - { 122121, true }, - { 122134, true }, - { 122152, true }, - { 122171, true }, - { 122189, true }, - { 122203, true }, - { 122215, true }, - { 122229, true }, - { 122252, true }, - { 122266, true }, - { 122276, true }, - { 122291, true }, - { 122307, true }, - { 122331, true }, - { 122347, true }, - { 122357, true }, + { 122037, true }, + { 122055, true }, + { 122069, true }, + { 122081, true }, + { 122095, true }, + { 122118, true }, + { 122132, true }, + { 122142, true }, + { 122157, true }, + { 122173, true }, + { 122197, true }, + { 122213, true }, + { 122223, true }, + { 122237, true }, + { 122249, true }, + { 122261, true }, + { 122279, true }, + { 122297, true }, + { 122312, true }, + { 122335, true }, + { 122352, true }, { 122371, true }, - { 122383, true }, - { 122395, true }, - { 122413, true }, - { 122431, true }, - { 122446, true }, - { 122469, true }, - { 122486, true }, - { 122505, true }, - { 122525, true }, + { 122391, true }, + { 122414, true }, + { 122433, true }, + { 122452, true }, + { 122471, true }, + { 122482, true }, + { 122492, true }, + { 122507, true }, + { 122528, true }, { 122548, true }, { 122567, true }, - { 122586, true }, - { 122605, true }, - { 122616, true }, - { 122626, true }, - { 122641, true }, - { 122662, true }, - { 122682, true }, - { 122701, true }, - { 122715, true }, + { 122581, true }, + { 122593, true }, + { 122603, true }, + { 122615, true }, + { 122633, true }, + { 122649, true }, + { 122670, true }, + { 122680, false }, + { 122692, true }, + { 122709, true }, { 122727, true }, - { 122737, true }, - { 122749, true }, - { 122767, true }, - { 122783, true }, - { 122804, true }, - { 122814, false }, - { 122826, true }, - { 122843, true }, - { 122861, true }, - { 122881, true }, - { 122896, true }, - { 122907, true }, - { 122919, true }, - { 122931, false }, - { 122948, true }, - { 122961, true }, - { 122979, true }, - { 122994, true }, - { 123006, true }, - { 123026, true }, - { 123038, true }, - { 123052, true }, - { 123070, true }, - { 123083, true }, + { 122747, true }, + { 122762, true }, + { 122773, true }, + { 122785, true }, + { 122797, false }, + { 122814, true }, + { 122827, true }, + { 122845, true }, + { 122860, true }, + { 122872, true }, + { 122892, true }, + { 122904, true }, + { 122918, true }, + { 122936, true }, + { 122949, true }, + { 122965, true }, + { 122980, true }, + { 122992, true }, + { 123008, true }, + { 123018, true }, + { 123033, true }, + { 123053, true }, + { 123066, true }, + { 123077, true }, + { 123090, true }, { 123099, true }, - { 123114, true }, - { 123126, true }, - { 123142, true }, - { 123152, true }, - { 123167, true }, - { 123187, true }, - { 123200, true }, - { 123211, true }, - { 123224, true }, - { 123233, true }, - { 123253, true }, - { 123273, true }, - { 123296, true }, - { 123316, true }, - { 123328, true }, - { 123339, true }, - { 123350, false }, - { 123361, true }, - { 123372, false }, - { 123382, false }, - { 123399, true }, - { 123411, true }, - { 123427, true }, - { 123440, true }, - { 123449, true }, - { 123463, true }, - { 123474, true }, - { 123492, true }, - { 123506, true }, - { 123519, true }, - { 123528, true }, - { 123543, true }, - { 123554, true }, - { 123564, true }, - { 123584, true }, - { 123594, true }, - { 123605, true }, - { 123638, true }, - { 123650, true }, - { 123669, true }, - { 123680, true }, - { 123687, true }, - { 123701, true }, - { 123715, false }, - { 123735, true }, - { 123752, true }, - { 123763, true }, + { 123119, true }, + { 123139, true }, + { 123162, true }, + { 123182, true }, + { 123194, true }, + { 123205, true }, + { 123216, false }, + { 123227, true }, + { 123238, false }, + { 123248, false }, + { 123265, true }, + { 123277, true }, + { 123293, true }, + { 123306, true }, + { 123315, true }, + { 123329, true }, + { 123340, true }, + { 123358, true }, + { 123372, true }, + { 123385, true }, + { 123394, true }, + { 123409, true }, + { 123420, true }, + { 123430, true }, + { 123450, true }, + { 123460, true }, + { 123471, true }, + { 123504, true }, + { 123516, true }, + { 123535, true }, + { 123546, true }, + { 123553, true }, + { 123567, true }, + { 123581, false }, + { 123601, true }, + { 123618, true }, + { 123629, true }, + { 123642, true }, + { 123660, true }, + { 123676, true }, + { 123693, true }, + { 123707, true }, + { 123723, true }, + { 123736, true }, + { 123748, true }, + { 123759, true }, { 123776, true }, + { 123785, true }, { 123794, true }, - { 123810, true }, - { 123827, true }, - { 123841, true }, - { 123857, true }, - { 123870, true }, - { 123882, true }, - { 123893, true }, - { 123910, true }, - { 123919, true }, - { 123928, true }, - { 123941, true }, - { 123972, true }, - { 123985, true }, - { 123998, true }, - { 124009, true }, - { 124018, true }, - { 124042, true }, - { 124057, true }, - { 124069, true }, - { 124085, true }, - { 124102, true }, - { 124116, true }, - { 124128, true }, - { 124139, true }, - { 124156, true }, - { 124167, true }, - { 124185, false }, - { 124197, true }, - { 124233, true }, - { 124246, true }, - { 124260, true }, - { 124269, true }, - { 124279, true }, - { 124291, true }, - { 124309, true }, - { 124323, true }, - { 124341, true }, - { 124362, true }, - { 124382, true }, - { 124405, true }, - { 124421, true }, - { 124435, true }, - { 124451, true }, + { 123807, true }, + { 123838, true }, + { 123851, true }, + { 123864, true }, + { 123875, true }, + { 123884, true }, + { 123908, true }, + { 123923, true }, + { 123935, true }, + { 123951, true }, + { 123968, true }, + { 123982, true }, + { 123994, true }, + { 124005, true }, + { 124022, true }, + { 124033, true }, + { 124051, false }, + { 124063, true }, + { 124099, true }, + { 124112, true }, + { 124126, true }, + { 124135, true }, + { 124145, true }, + { 124157, true }, + { 124175, true }, + { 124189, true }, + { 124207, true }, + { 124228, true }, + { 124248, true }, + { 124271, true }, + { 124287, true }, + { 124301, true }, + { 124317, true }, + { 124331, true }, + { 124344, true }, + { 124365, true }, + { 124385, true }, + { 124394, true }, + { 124411, true }, + { 124422, true }, + { 124433, true }, + { 124452, true }, { 124464, true }, - { 124485, true }, - { 124505, true }, - { 124514, true }, - { 124531, true }, + { 124477, true }, + { 124493, true }, + { 124512, true }, + { 124527, false }, { 124542, true }, - { 124553, true }, - { 124572, true }, + { 124562, true }, + { 124573, true }, { 124584, true }, - { 124597, true }, + { 124604, false }, { 124613, true }, - { 124632, true }, - { 124647, false }, - { 124662, true }, - { 124682, true }, - { 124693, true }, - { 124704, true }, - { 124724, false }, - { 124733, true }, - { 124742, true }, - { 124753, true }, - { 124765, true }, - { 124779, true }, - { 124797, true }, - { 124809, true }, - { 124832, true }, - { 124847, true }, - { 124860, true }, - { 124877, true }, - { 124887, true }, - { 124908, true }, - { 124936, false }, - { 124947, true }, - { 124954, true }, - { 124965, true }, - { 124975, true }, - { 124989, true }, - { 125003, true }, - { 125014, false }, - { 125025, true }, - { 125033, false }, - { 125053, true }, - { 125068, true }, - { 125081, true }, - { 125097, true }, - { 125112, true }, - { 125125, true }, - { 125138, true }, - { 125154, true }, - { 125174, true }, - { 125187, true }, - { 125206, true }, - { 125224, true }, - { 125238, true }, - { 125246, true }, - { 125266, true }, + { 124622, true }, + { 124633, true }, + { 124645, true }, + { 124659, true }, + { 124677, true }, + { 124689, true }, + { 124712, true }, + { 124727, true }, + { 124740, true }, + { 124757, true }, + { 124767, true }, + { 124788, true }, + { 124816, false }, + { 124827, true }, + { 124834, true }, + { 124845, true }, + { 124855, true }, + { 124869, true }, + { 124883, true }, + { 124894, false }, + { 124905, true }, + { 124913, false }, + { 124933, true }, + { 124948, true }, + { 124961, true }, + { 124977, true }, + { 124992, true }, + { 125005, true }, + { 125018, true }, + { 125034, true }, + { 125054, true }, + { 125067, true }, + { 125086, true }, + { 125104, true }, + { 125118, true }, + { 125126, true }, + { 125146, true }, + { 125178, true }, + { 125193, true }, + { 125212, true }, + { 125227, true }, + { 125242, true }, + { 125263, true }, + { 125284, true }, { 125298, true }, - { 125313, true }, - { 125332, true }, - { 125347, true }, - { 125362, true }, - { 125383, true }, - { 125404, true }, - { 125418, true }, - { 125440, true }, - { 125456, true }, - { 125468, true }, - { 125481, true }, - { 125492, true }, - { 125509, true }, - { 125533, true }, - { 125547, true }, - { 125559, true }, - { 125572, true }, - { 125590, true }, - { 125610, true }, - { 125635, true }, - { 125648, true }, - { 125662, true }, - { 125676, true }, - { 125693, true }, - { 125713, true }, - { 125729, true }, - { 125744, true }, - { 125759, true }, - { 125772, true }, - { 125787, true }, - { 125795, false }, - { 125808, true }, - { 125820, true }, - { 125834, true }, + { 125320, true }, + { 125336, true }, + { 125348, true }, + { 125361, true }, + { 125372, true }, + { 125389, true }, + { 125413, true }, + { 125427, true }, + { 125439, true }, + { 125452, true }, + { 125470, true }, + { 125490, true }, + { 125515, true }, + { 125528, true }, + { 125542, true }, + { 125556, true }, + { 125573, true }, + { 125593, true }, + { 125609, true }, + { 125627, true }, + { 125642, true }, + { 125657, true }, + { 125670, true }, + { 125685, true }, + { 125693, false }, + { 125706, true }, + { 125718, true }, + { 125732, true }, + { 125754, true }, + { 125768, true }, + { 125782, true }, + { 125790, true }, + { 125806, true }, + { 125816, true }, + { 125829, true }, + { 125842, true }, { 125856, true }, - { 125870, true }, - { 125884, true }, - { 125892, true }, - { 125908, true }, - { 125918, true }, - { 125931, true }, - { 125944, true }, - { 125958, true }, - { 125974, true }, - { 125987, true }, - { 126001, true }, - { 126012, true }, - { 126022, true }, - { 126042, true }, - { 126056, true }, - { 126071, true }, - { 126083, true }, - { 126097, true }, - { 126105, true }, - { 126117, true }, - { 126128, true }, - { 126149, true }, - { 126168, true }, - { 126186, true }, - { 126206, true }, - { 126218, true }, - { 126236, true }, - { 126252, true }, - { 126265, true }, - { 126285, true }, - { 126299, true }, - { 126318, true }, - { 126331, true }, - { 126343, true }, - { 126355, true }, - { 126366, true }, - { 126380, true }, - { 126394, false }, - { 126409, true }, - { 126426, true }, - { 126437, true }, - { 126448, true }, - { 126462, true }, - { 126483, true }, - { 126502, true }, - { 126518, true }, - { 126536, true }, - { 126559, true }, - { 126571, true }, - { 126584, true }, - { 126602, true }, - { 126617, true }, - { 126635, true }, - { 126650, true }, - { 126666, true }, - { 126681, true }, - { 126696, true }, - { 126711, true }, - { 126727, true }, - { 126742, true }, - { 126757, true }, - { 126772, true }, - { 126782, true }, - { 126795, true }, - { 126805, true }, - { 126817, false }, - { 126828, true }, - { 126842, true }, - { 126851, false }, - { 126870, true }, - { 126887, true }, - { 126900, true }, - { 126916, true }, - { 126926, false }, - { 126939, false }, - { 126949, true }, - { 126962, true }, - { 126972, false }, - { 126981, false }, - { 126989, false }, - { 127009, true }, + { 125872, true }, + { 125885, true }, + { 125899, true }, + { 125910, true }, + { 125920, true }, + { 125940, true }, + { 125954, true }, + { 125969, true }, + { 125981, true }, + { 125995, true }, + { 126003, true }, + { 126015, true }, + { 126026, true }, + { 126047, true }, + { 126066, true }, + { 126084, true }, + { 126104, true }, + { 126116, true }, + { 126134, true }, + { 126150, true }, + { 126163, true }, + { 126183, true }, + { 126197, true }, + { 126216, true }, + { 126229, true }, + { 126241, true }, + { 126253, true }, + { 126264, true }, + { 126278, true }, + { 126292, false }, + { 126307, true }, + { 126324, true }, + { 126335, true }, + { 126346, true }, + { 126360, true }, + { 126381, true }, + { 126400, true }, + { 126416, true }, + { 126434, true }, + { 126457, true }, + { 126469, true }, + { 126482, true }, + { 126500, true }, + { 126515, true }, + { 126533, true }, + { 126548, true }, + { 126564, true }, + { 126579, true }, + { 126594, true }, + { 126609, true }, + { 126625, true }, + { 126640, true }, + { 126655, true }, + { 126670, true }, + { 126680, true }, + { 126693, true }, + { 126703, true }, + { 126715, false }, + { 126726, true }, + { 126740, true }, + { 126749, false }, + { 126768, true }, + { 126785, true }, + { 126798, true }, + { 126814, true }, + { 126824, false }, + { 126837, false }, + { 126847, true }, + { 126860, true }, + { 126870, false }, + { 126879, false }, + { 126887, false }, + { 126907, true }, + { 126921, true }, + { 126934, true }, + { 126946, true }, + { 126964, false }, + { 126976, true }, + { 126990, true }, + { 127007, true }, { 127023, true }, - { 127036, true }, - { 127048, true }, - { 127066, false }, - { 127078, true }, - { 127092, true }, - { 127109, true }, - { 127125, true }, - { 127144, false }, - { 127161, true }, - { 127175, true }, - { 127189, true }, - { 127203, true }, - { 127219, false }, - { 127233, true }, - { 127248, true }, - { 127262, true }, - { 127281, true }, - { 127303, true }, - { 127318, true }, - { 127331, true }, - { 127341, true }, - { 127349, true }, - { 127361, true }, - { 127374, true }, - { 127387, true }, - { 127397, true }, - { 127410, false }, - { 127419, true }, - { 127430, false }, - { 127441, true }, - { 127456, true }, - { 127467, true }, - { 127476, true }, - { 127485, false }, - { 127499, true }, - { 127517, true }, - { 127535, true }, - { 127552, true }, - { 127564, false }, - { 127580, false }, - { 127604, true }, - { 127631, true }, - { 127650, true }, - { 127658, true }, - { 127667, true }, - { 127679, true }, + { 127042, false }, + { 127059, true }, + { 127073, true }, + { 127087, true }, + { 127101, true }, + { 127117, false }, + { 127131, true }, + { 127146, true }, + { 127160, true }, + { 127179, true }, + { 127201, true }, + { 127214, true }, + { 127224, true }, + { 127232, true }, + { 127244, true }, + { 127257, true }, + { 127270, true }, + { 127280, true }, + { 127293, false }, + { 127302, true }, + { 127313, false }, + { 127324, true }, + { 127339, true }, + { 127350, true }, + { 127359, true }, + { 127368, false }, + { 127382, true }, + { 127400, true }, + { 127418, true }, + { 127435, true }, + { 127447, false }, + { 127463, false }, + { 127487, true }, + { 127514, true }, + { 127533, true }, + { 127541, true }, + { 127550, true }, + { 127562, true }, + { 127574, true }, + { 127599, true }, + { 127616, true }, + { 127633, true }, + { 127648, true }, + { 127660, true }, + { 127673, true }, { 127691, true }, - { 127716, true }, - { 127733, true }, - { 127750, true }, + { 127700, false }, + { 127708, true }, + { 127729, true }, + { 127743, true }, { 127765, true }, - { 127777, true }, - { 127790, true }, - { 127808, true }, - { 127817, false }, - { 127825, true }, + { 127778, true }, + { 127791, true }, + { 127803, true }, + { 127816, true }, + { 127832, true }, { 127846, true }, - { 127860, true }, - { 127882, true }, - { 127895, true }, - { 127908, true }, - { 127920, true }, - { 127933, true }, - { 127949, true }, - { 127963, true }, - { 127984, true }, - { 127996, true }, - { 128017, true }, - { 128036, true }, - { 128049, true }, - { 128061, true }, + { 127867, true }, + { 127879, true }, + { 127900, true }, + { 127919, true }, + { 127932, true }, + { 127944, true }, + { 127956, true }, + { 127974, true }, + { 127986, false }, + { 127995, true }, + { 128010, true }, + { 128032, true }, + { 128046, true }, + { 128060, true }, { 128073, true }, - { 128091, true }, - { 128103, false }, - { 128112, true }, - { 128127, true }, - { 128149, true }, - { 128163, true }, - { 128177, true }, + { 128095, true }, + { 128110, true }, + { 128125, true }, + { 128136, true }, + { 128161, true }, + { 128178, true }, { 128190, true }, - { 128212, true }, - { 128227, true }, - { 128242, true }, + { 128206, false }, + { 128221, false }, + { 128245, true }, { 128253, true }, - { 128278, true }, - { 128295, true }, - { 128307, true }, - { 128323, false }, - { 128338, false }, - { 128362, true }, - { 128370, true }, - { 128380, true }, - { 128392, true }, - { 128405, true }, - { 128418, true }, - { 128430, true }, + { 128263, true }, + { 128275, true }, + { 128288, true }, + { 128301, true }, + { 128313, true }, + { 128329, true }, + { 128344, true }, + { 128363, true }, + { 128377, true }, + { 128391, true }, + { 128411, true }, + { 128427, true }, { 128446, true }, - { 128461, true }, - { 128480, true }, - { 128494, true }, - { 128514, true }, - { 128530, true }, - { 128549, true }, - { 128569, true }, - { 128581, true }, - { 128593, true }, + { 128466, true }, + { 128478, true }, + { 128490, true }, + { 128520, true }, + { 128532, true }, + { 128543, true }, + { 128553, true }, + { 128567, true }, + { 128580, true }, + { 128598, false }, + { 128608, true }, { 128623, true }, - { 128635, true }, - { 128646, true }, - { 128656, true }, - { 128670, true }, - { 128683, true }, - { 128701, false }, - { 128711, true }, - { 128725, true }, - { 128740, true }, - { 128749, true }, - { 128762, true }, - { 128778, true }, - { 128789, true }, - { 128800, true }, - { 128810, true }, + { 128632, true }, + { 128645, false }, + { 128662, true }, + { 128678, true }, + { 128689, true }, + { 128700, true }, + { 128710, true }, + { 128719, true }, + { 128733, true }, + { 128754, true }, + { 128765, true }, + { 128780, true }, + { 128802, true }, { 128819, true }, - { 128833, true }, - { 128854, true }, - { 128865, true }, - { 128880, true }, - { 128902, true }, - { 128919, true }, - { 128929, true }, - { 128951, true }, - { 128973, true }, - { 128990, true }, - { 129004, true }, - { 129017, true }, - { 129034, true }, - { 129059, true }, - { 129075, true }, - { 129085, true }, - { 129096, true }, - { 129105, false }, - { 129114, true }, - { 129123, true }, - { 129133, true }, - { 129147, true }, - { 129165, true }, - { 129174, true }, - { 129195, true }, - { 129215, true }, + { 128829, true }, + { 128851, true }, + { 128873, true }, + { 128890, true }, + { 128904, true }, + { 128917, true }, + { 128934, true }, + { 128959, true }, + { 128975, true }, + { 128985, true }, + { 128996, true }, + { 129005, true }, + { 129014, true }, + { 129024, true }, + { 129038, true }, + { 129056, true }, + { 129065, true }, + { 129086, true }, + { 129106, true }, + { 129124, true }, + { 129141, true }, + { 129162, true }, + { 129180, true }, + { 129192, true }, + { 129214, false }, { 129233, true }, - { 129250, true }, - { 129271, true }, + { 129244, true }, + { 129257, true }, + { 129278, true }, { 129289, true }, - { 129301, true }, - { 129323, false }, - { 129342, true }, - { 129353, true }, - { 129366, true }, - { 129387, true }, - { 129398, true }, - { 129413, true }, - { 129430, true }, - { 129456, true }, - { 129473, false }, - { 129491, true }, - { 129510, false }, - { 129529, true }, - { 129549, true }, - { 129571, true }, - { 129593, true }, - { 129606, true }, - { 129629, true }, - { 129643, true }, + { 129304, true }, + { 129321, true }, + { 129347, true }, + { 129364, false }, + { 129382, true }, + { 129401, false }, + { 129420, true }, + { 129440, true }, + { 129462, true }, + { 129484, true }, + { 129497, true }, + { 129520, true }, + { 129534, true }, + { 129557, true }, + { 129567, true }, + { 129577, true }, + { 129596, true }, + { 129609, true }, + { 129624, false }, + { 129636, true }, + { 129656, true }, { 129666, true }, - { 129676, true }, - { 129686, true }, - { 129705, true }, + { 129685, true }, + { 129697, true }, { 129718, true }, - { 129733, false }, - { 129745, true }, + { 129744, true }, { 129765, true }, - { 129775, true }, - { 129794, true }, - { 129806, true }, - { 129827, true }, - { 129853, true }, - { 129874, true }, - { 129886, true }, - { 129900, true }, - { 129912, true }, - { 129924, true }, - { 129947, true }, - { 129963, true }, - { 129975, true }, + { 129777, true }, + { 129791, true }, + { 129803, true }, + { 129815, true }, + { 129838, true }, + { 129854, true }, + { 129866, true }, + { 129891, true }, + { 129906, true }, + { 129927, true }, + { 129944, true }, + { 129965, false }, + { 129982, true }, { 130000, true }, - { 130015, true }, - { 130036, true }, - { 130053, true }, - { 130074, false }, - { 130091, true }, - { 130109, true }, - { 130119, true }, - { 130133, true }, - { 130147, true }, - { 130157, true }, - { 130169, true }, - { 130181, true }, - { 130195, true }, - { 130207, true }, - { 130236, true }, - { 130251, true }, - { 130265, true }, - { 130281, true }, + { 130010, true }, + { 130024, true }, + { 130038, true }, + { 130048, true }, + { 130060, true }, + { 130072, true }, + { 130086, true }, + { 130098, true }, + { 130127, true }, + { 130142, true }, + { 130156, true }, + { 130172, true }, + { 130187, true }, + { 130199, true }, + { 130219, true }, + { 130233, true }, + { 130246, true }, + { 130258, true }, + { 130271, true }, + { 130284, true }, { 130296, true }, - { 130308, true }, - { 130328, true }, - { 130342, true }, - { 130355, true }, - { 130367, true }, - { 130380, true }, - { 130393, true }, - { 130405, true }, - { 130424, true }, - { 130450, true }, + { 130315, true }, + { 130341, true }, + { 130365, true }, + { 130388, true }, + { 130400, true }, + { 130416, true }, + { 130436, true }, + { 130454, true }, { 130474, true }, - { 130497, true }, - { 130509, true }, - { 130525, true }, - { 130545, true }, - { 130563, true }, - { 130583, true }, - { 130597, true }, - { 130610, true }, - { 130630, true }, - { 130638, true }, - { 130657, true }, - { 130676, true }, - { 130690, true }, - { 130708, true }, - { 130724, false }, - { 130743, true }, - { 130764, true }, - { 130783, true }, - { 130797, true }, - { 130806, true }, - { 130824, true }, - { 130841, true }, - { 130857, true }, - { 130879, true }, - { 130896, true }, - { 130914, true }, - { 130931, true }, - { 130944, true }, - { 130954, true }, + { 130488, true }, + { 130501, true }, + { 130521, true }, + { 130529, true }, + { 130548, true }, + { 130567, true }, + { 130581, true }, + { 130599, true }, + { 130615, false }, + { 130634, true }, + { 130655, true }, + { 130674, true }, + { 130688, true }, + { 130697, true }, + { 130715, true }, + { 130732, true }, + { 130748, true }, + { 130770, true }, + { 130787, true }, + { 130805, true }, + { 130822, true }, + { 130835, true }, + { 130845, true }, + { 130853, true }, + { 130881, true }, + { 130898, true }, + { 130912, true }, + { 130927, true }, + { 130940, true }, + { 130952, true }, { 130962, true }, + { 130975, true }, { 130990, true }, - { 131007, true }, - { 131021, true }, - { 131036, true }, - { 131049, true }, - { 131061, true }, - { 131071, true }, - { 131084, true }, - { 131099, true }, - { 131111, true }, - { 131123, true }, - { 131135, true }, - { 131147, true }, - { 131160, true }, - { 131173, true }, - { 131185, true }, - { 131201, true }, - { 131213, true }, - { 131226, true }, - { 131236, true }, - { 131246, true }, - { 131261, true }, - { 131272, true }, - { 131283, true }, - { 131301, true }, - { 131309, true }, - { 131317, true }, - { 131329, true }, - { 131343, true }, - { 131360, true }, - { 131375, true }, - { 131391, true }, - { 131406, true }, - { 131421, true }, - { 131436, true }, - { 131444, true }, - { 131459, true }, - { 131472, true }, - { 131480, true }, - { 131490, true }, - { 131511, true }, - { 131524, true }, - { 131536, true }, - { 131544, true }, - { 131561, true }, - { 131577, true }, - { 131584, true }, - { 131592, false }, - { 131616, true }, - { 131648, true }, - { 131668, true }, - { 131692, true }, - { 131709, true }, + { 131002, true }, + { 131014, true }, + { 131026, true }, + { 131038, true }, + { 131051, true }, + { 131064, true }, + { 131076, true }, + { 131092, true }, + { 131104, true }, + { 131117, true }, + { 131127, true }, + { 131137, true }, + { 131152, true }, + { 131163, true }, + { 131174, true }, + { 131192, true }, + { 131200, true }, + { 131208, true }, + { 131220, true }, + { 131234, true }, + { 131251, true }, + { 131266, true }, + { 131282, true }, + { 131297, true }, + { 131312, true }, + { 131327, true }, + { 131335, true }, + { 131350, true }, + { 131363, true }, + { 131371, true }, + { 131381, true }, + { 131402, true }, + { 131415, true }, + { 131427, true }, + { 131435, true }, + { 131452, true }, + { 131468, true }, + { 131475, true }, + { 131483, false }, + { 131507, true }, + { 131539, true }, + { 131559, true }, + { 131583, true }, + { 131600, true }, + { 131615, true }, + { 131626, true }, + { 131637, true }, + { 131647, true }, + { 131659, true }, + { 131667, true }, + { 131679, false }, + { 131691, false }, + { 131699, false }, { 131724, true }, - { 131735, true }, - { 131746, true }, - { 131756, true }, - { 131768, true }, - { 131776, true }, - { 131788, false }, - { 131800, false }, - { 131808, false }, - { 131833, true }, - { 131846, true }, - { 131861, true }, - { 131875, true }, - { 131888, true }, - { 131900, true }, - { 131913, true }, - { 131930, true }, - { 131944, true }, - { 131958, true }, - { 131973, true }, - { 131988, true }, - { 131999, true }, - { 132006, true }, - { 132020, true }, - { 132028, true }, - { 132036, false }, - { 132051, true }, - { 132063, true }, + { 131737, true }, + { 131752, true }, + { 131766, true }, + { 131779, true }, + { 131791, true }, + { 131804, true }, + { 131821, true }, + { 131835, true }, + { 131849, true }, + { 131864, true }, + { 131879, true }, + { 131890, true }, + { 131897, true }, + { 131911, true }, + { 131919, true }, + { 131927, false }, + { 131942, true }, + { 131954, true }, + { 131968, true }, + { 131976, true }, + { 131987, true }, + { 131997, true }, + { 132007, true }, + { 132014, true }, + { 132027, true }, + { 132036, true }, + { 132044, true }, + { 132052, true }, + { 132061, true }, { 132077, true }, - { 132085, true }, - { 132096, true }, - { 132106, true }, - { 132116, true }, - { 132123, true }, - { 132136, true }, - { 132145, true }, + { 132088, false }, + { 132099, true }, + { 132107, true }, + { 132128, true }, { 132153, true }, - { 132161, true }, - { 132170, true }, - { 132186, true }, - { 132197, false }, - { 132208, true }, - { 132216, true }, - { 132237, true }, - { 132262, true }, - { 132278, true }, - { 132290, true }, - { 132302, true }, - { 132315, true }, - { 132323, false }, - { 132343, true }, - { 132362, true }, - { 132376, true }, + { 132169, true }, + { 132181, true }, + { 132193, true }, + { 132206, true }, + { 132214, false }, + { 132234, false }, + { 132253, true }, + { 132267, false }, + { 132286, false }, + { 132306, false }, + { 132326, false }, + { 132346, false }, + { 132365, false }, + { 132384, true }, { 132395, true }, - { 132415, true }, - { 132435, true }, - { 132455, true }, - { 132474, true }, - { 132493, true }, - { 132504, true }, - { 132514, true }, - { 132523, true }, - { 132536, true }, - { 132546, true }, - { 132559, true }, - { 132571, false }, - { 132582, true }, - { 132593, true }, - { 132601, true }, - { 132614, true }, - { 132624, true }, - { 132633, true }, - { 132653, true }, - { 132676, true }, - { 132695, false }, - { 132706, true }, - { 132728, true }, - { 132737, true }, + { 132405, true }, + { 132414, true }, + { 132427, true }, + { 132437, true }, + { 132450, true }, + { 132462, false }, + { 132473, true }, + { 132484, true }, + { 132492, true }, + { 132505, true }, + { 132515, true }, + { 132524, true }, + { 132544, true }, + { 132567, true }, + { 132586, false }, + { 132597, true }, + { 132619, true }, + { 132628, true }, + { 132635, true }, + { 132642, true }, + { 132654, true }, + { 132671, true }, + { 132678, true }, + { 132686, true }, + { 132697, true }, + { 132711, true }, + { 132723, true }, + { 132735, true }, { 132744, true }, - { 132751, true }, - { 132763, true }, - { 132780, true }, - { 132787, true }, - { 132795, true }, - { 132806, true }, - { 132820, true }, - { 132832, true }, - { 132844, true }, - { 132853, true }, - { 132862, true }, - { 132874, false }, - { 132885, true }, - { 132898, true }, - { 132924, true }, - { 132947, true }, - { 132967, true }, - { 132984, true }, - { 132999, true }, - { 133017, true }, - { 133031, true }, + { 132753, true }, + { 132765, false }, + { 132776, true }, + { 132789, true }, + { 132815, true }, + { 132838, false }, + { 132858, true }, + { 132875, true }, + { 132890, true }, + { 132904, true }, + { 132922, true }, + { 132941, true }, + { 132952, true }, + { 132970, true }, + { 132985, true }, + { 133005, true }, + { 133014, true }, + { 133034, true }, { 133049, true }, - { 133068, true }, + { 133064, true }, { 133079, true }, - { 133097, true }, - { 133112, true }, - { 133132, true }, - { 133141, true }, - { 133161, true }, - { 133176, true }, + { 133093, true }, + { 133107, true }, + { 133116, true }, + { 133131, true }, + { 133139, true }, + { 133152, true }, + { 133170, true }, + { 133181, true }, { 133191, true }, - { 133206, true }, - { 133220, true }, + { 133200, true }, + { 133211, true }, + { 133221, true }, { 133234, true }, - { 133243, true }, - { 133258, true }, - { 133266, true }, - { 133279, true }, - { 133297, true }, - { 133308, true }, - { 133318, true }, - { 133327, true }, - { 133338, true }, - { 133348, true }, - { 133361, true }, - { 133372, true }, - { 133382, true }, - { 133389, true }, - { 133400, true }, + { 133245, true }, + { 133255, true }, + { 133262, true }, + { 133273, true }, + { 133284, true }, + { 133298, true }, + { 133305, true }, + { 133316, true }, + { 133324, true }, + { 133342, true }, + { 133355, true }, + { 133367, true }, + { 133375, true }, + { 133395, false }, { 133411, true }, - { 133425, true }, - { 133432, true }, - { 133443, true }, - { 133451, true }, - { 133469, true }, - { 133482, true }, - { 133494, true }, - { 133502, true }, - { 133522, false }, - { 133538, true }, - { 133557, true }, - { 133580, true }, - { 133599, true }, - { 133610, true }, - { 133632, true }, + { 133430, true }, + { 133453, true }, + { 133472, true }, + { 133483, true }, + { 133505, true }, + { 133518, true }, + { 133527, true }, + { 133550, true }, + { 133566, true }, + { 133582, true }, + { 133604, true }, + { 133631, true }, { 133645, true }, - { 133654, true }, - { 133677, true }, - { 133693, true }, - { 133709, true }, - { 133731, true }, - { 133758, true }, - { 133772, true }, - { 133782, true }, - { 133792, true }, - { 133811, true }, - { 133825, true }, - { 133839, true }, - { 133855, true }, - { 133866, true }, - { 133881, true }, - { 133904, true }, - { 133927, true }, - { 133945, true }, - { 133962, true }, - { 133972, true }, - { 133997, true }, - { 134015, true }, - { 134025, true }, - { 134037, true }, - { 134050, true }, - { 134061, true }, + { 133655, true }, + { 133665, true }, + { 133684, true }, + { 133698, true }, + { 133712, true }, + { 133728, true }, + { 133739, true }, + { 133754, true }, + { 133777, true }, + { 133800, true }, + { 133818, true }, + { 133835, true }, + { 133845, true }, + { 133870, true }, + { 133888, true }, + { 133898, true }, + { 133910, true }, + { 133923, true }, + { 133934, true }, + { 133951, true }, + { 133961, true }, + { 133976, true }, + { 133992, true }, + { 134013, true }, + { 134035, true }, + { 134053, true }, + { 134064, true }, { 134078, true }, - { 134088, true }, - { 134103, true }, - { 134119, true }, - { 134140, true }, - { 134162, true }, - { 134180, true }, - { 134191, true }, - { 134205, true }, - { 134218, true }, - { 134229, true }, - { 134242, true }, - { 134253, true }, - { 134263, true }, - { 134277, true }, - { 134287, true }, - { 134298, true }, - { 134311, true }, - { 134329, true }, - { 134338, true }, - { 134353, true }, - { 134369, false }, - { 134382, false }, - { 134395, false }, - { 134407, true }, + { 134091, true }, + { 134102, true }, + { 134115, true }, + { 134126, true }, + { 134136, true }, + { 134150, true }, + { 134160, true }, + { 134171, true }, + { 134184, true }, + { 134202, true }, + { 134211, true }, + { 134226, true }, + { 134242, false }, + { 134255, false }, + { 134268, false }, + { 134280, true }, + { 134291, true }, + { 134306, true }, + { 134318, true }, + { 134335, true }, + { 134349, true }, + { 134362, true }, + { 134371, true }, + { 134382, true }, + { 134393, true }, + { 134405, true }, { 134418, true }, - { 134433, true }, - { 134445, true }, - { 134462, true }, - { 134476, true }, - { 134489, true }, - { 134498, true }, - { 134509, true }, + { 134431, true }, + { 134440, true }, + { 134451, true }, + { 134467, true }, + { 134479, true }, + { 134491, true }, + { 134508, true }, { 134520, true }, - { 134532, true }, - { 134545, true }, - { 134558, true }, - { 134567, true }, + { 134534, true }, + { 134547, true }, + { 134564, true }, { 134578, true }, - { 134594, true }, - { 134606, true }, - { 134618, true }, - { 134635, true }, - { 134647, true }, - { 134661, true }, - { 134674, true }, - { 134691, true }, - { 134705, true }, - { 134720, true }, - { 134736, true }, - { 134752, true }, - { 134761, true }, - { 134768, true }, - { 134779, true }, - { 134796, true }, - { 134809, true }, - { 134824, true }, - { 134834, true }, - { 134845, true }, - { 134868, true }, - { 134880, false }, + { 134593, true }, + { 134609, true }, + { 134625, true }, + { 134634, true }, + { 134641, true }, + { 134652, true }, + { 134669, true }, + { 134682, true }, + { 134697, true }, + { 134707, true }, + { 134718, true }, + { 134741, true }, + { 134753, false }, + { 134767, true }, + { 134778, true }, + { 134794, false }, + { 134813, true }, + { 134832, true }, + { 134843, true }, + { 134864, true }, + { 134880, true }, { 134894, true }, - { 134905, true }, - { 134921, false }, + { 134908, true }, + { 134919, true }, { 134940, true }, - { 134959, true }, - { 134970, true }, + { 134953, true }, + { 134963, true }, + { 134974, true }, { 134991, true }, - { 135007, true }, - { 135021, true }, - { 135035, true }, - { 135046, true }, - { 135067, true }, - { 135080, true }, - { 135090, true }, - { 135101, true }, - { 135118, true }, - { 135138, true }, - { 135153, true }, - { 135172, false }, - { 135189, true }, - { 135212, true }, - { 135227, true }, - { 135243, true }, - { 135254, true }, - { 135264, true }, - { 135272, true }, - { 135295, true }, - { 135307, true }, - { 135315, true }, - { 135341, true }, - { 135359, true }, - { 135372, true }, - { 135380, true }, - { 135392, true }, - { 135419, true }, - { 135450, true }, - { 135466, true }, - { 135476, true }, - { 135491, true }, - { 135502, true }, - { 135513, false }, - { 135526, true }, - { 135535, true }, - { 135548, true }, - { 135576, true }, - { 135597, true }, - { 135611, true }, - { 135633, true }, - { 135643, true }, - { 135655, true }, - { 135671, true }, - { 135685, true }, - { 135696, true }, - { 135710, true }, - { 135728, true }, - { 135745, true }, - { 135765, true }, - { 135776, true }, - { 135787, false }, - { 135794, true }, - { 135821, true }, - { 135841, true }, - { 135859, true }, - { 135874, false }, - { 135885, true }, - { 135901, true }, - { 135918, true }, - { 135935, true }, - { 135957, true }, - { 135971, true }, - { 135987, false }, - { 136004, true }, - { 136020, true }, - { 136030, true }, - { 136051, true }, - { 136069, true }, + { 135011, true }, + { 135026, true }, + { 135045, false }, + { 135062, true }, + { 135085, true }, + { 135100, true }, + { 135116, true }, + { 135127, true }, + { 135137, true }, + { 135145, true }, + { 135168, true }, + { 135180, true }, + { 135188, true }, + { 135214, true }, + { 135232, true }, + { 135245, true }, + { 135253, true }, + { 135265, true }, + { 135292, true }, + { 135323, true }, + { 135339, true }, + { 135349, true }, + { 135364, true }, + { 135375, true }, + { 135386, false }, + { 135399, true }, + { 135408, true }, + { 135421, true }, + { 135449, true }, + { 135470, true }, + { 135484, true }, + { 135506, true }, + { 135516, true }, + { 135528, true }, + { 135544, true }, + { 135558, true }, + { 135569, true }, + { 135583, true }, + { 135601, true }, + { 135618, true }, + { 135638, true }, + { 135649, true }, + { 135660, false }, + { 135667, true }, + { 135694, true }, + { 135714, true }, + { 135732, true }, + { 135747, false }, + { 135758, true }, + { 135774, true }, + { 135791, true }, + { 135808, true }, + { 135830, true }, + { 135844, true }, + { 135860, false }, + { 135877, true }, + { 135893, true }, + { 135903, true }, + { 135924, true }, + { 135942, true }, + { 135960, true }, + { 135974, true }, + { 135985, true }, + { 136002, true }, + { 136022, true }, + { 136036, true }, + { 136053, true }, + { 136070, true }, { 136087, true }, - { 136101, true }, - { 136112, true }, - { 136129, true }, - { 136149, true }, - { 136163, true }, - { 136180, true }, - { 136197, true }, - { 136214, true }, - { 136235, true }, - { 136251, true }, - { 136274, true }, - { 136291, true }, - { 136309, true }, - { 136316, true }, - { 136326, true }, - { 136342, true }, - { 136353, false }, - { 136373, true }, - { 136386, true }, - { 136399, true }, - { 136409, true }, - { 136426, true }, - { 136446, true }, - { 136461, true }, - { 136478, true }, - { 136492, true }, - { 136506, true }, - { 136527, true }, - { 136541, false }, - { 136555, true }, - { 136572, true }, - { 136589, true }, - { 136605, true }, - { 136625, true }, - { 136648, true }, - { 136657, false }, + { 136108, true }, + { 136124, true }, + { 136147, true }, + { 136164, true }, + { 136182, true }, + { 136189, true }, + { 136199, true }, + { 136215, true }, + { 136226, false }, + { 136246, true }, + { 136259, true }, + { 136269, true }, + { 136286, true }, + { 136306, true }, + { 136321, true }, + { 136338, true }, + { 136352, true }, + { 136366, true }, + { 136387, true }, + { 136401, false }, + { 136415, true }, + { 136432, true }, + { 136449, true }, + { 136465, true }, + { 136485, true }, + { 136508, true }, + { 136517, false }, + { 136525, true }, + { 136537, false }, + { 136559, true }, + { 136574, true }, + { 136588, true }, + { 136602, true }, + { 136615, true }, + { 136630, true }, + { 136644, true }, { 136665, true }, - { 136677, false }, - { 136699, true }, - { 136714, true }, - { 136728, true }, + { 136675, true }, + { 136683, false }, + { 136705, true }, + { 136717, true }, { 136742, true }, - { 136755, true }, - { 136770, true }, - { 136784, true }, - { 136805, true }, + { 136752, true }, + { 136777, true }, + { 136790, false }, { 136815, true }, - { 136823, false }, - { 136845, true }, - { 136857, true }, + { 136832, true }, + { 136849, true }, + { 136862, true }, + { 136873, true }, { 136882, true }, - { 136892, true }, - { 136917, true }, - { 136930, false }, - { 136955, true }, - { 136972, true }, - { 136989, true }, - { 137002, true }, + { 136896, true }, + { 136909, true }, + { 136925, true }, + { 136941, true }, + { 136952, true }, + { 136963, true }, + { 136979, true }, + { 136989, false }, + { 137001, true }, { 137013, true }, - { 137021, true }, - { 137030, true }, - { 137044, true }, - { 137057, true }, - { 137073, true }, - { 137089, true }, - { 137100, true }, - { 137111, true }, - { 137127, true }, - { 137137, false }, - { 137149, true }, - { 137161, true }, - { 137176, true }, - { 137188, true }, - { 137198, true }, - { 137214, true }, - { 137238, true }, - { 137245, true }, - { 137252, true }, - { 137269, true }, - { 137283, true }, - { 137295, true }, - { 137307, true }, - { 137319, true }, - { 137333, true }, - { 137354, true }, - { 137367, true }, - { 137378, true }, - { 137395, true }, - { 137410, true }, - { 137435, true }, - { 137450, true }, - { 137460, true }, - { 137471, true }, - { 137480, true }, - { 137489, true }, - { 137504, true }, - { 137514, true }, - { 137530, true }, - { 137543, true }, - { 137555, true }, - { 137572, true }, - { 137593, true }, + { 137028, true }, + { 137046, true }, + { 137058, true }, + { 137068, true }, + { 137084, true }, + { 137108, true }, + { 137115, true }, + { 137122, true }, + { 137139, true }, + { 137153, true }, + { 137165, true }, + { 137177, true }, + { 137189, true }, + { 137203, true }, + { 137224, true }, + { 137237, true }, + { 137248, true }, + { 137265, true }, + { 137280, true }, + { 137305, true }, + { 137320, true }, + { 137330, true }, + { 137341, true }, + { 137350, true }, + { 137359, true }, + { 137374, true }, + { 137384, true }, + { 137400, true }, + { 137413, true }, + { 137425, true }, + { 137442, true }, + { 137463, true }, + { 137484, true }, + { 137501, true }, + { 137519, true }, + { 137531, true }, + { 137546, true }, + { 137562, true }, + { 137576, true }, + { 137588, true }, + { 137602, true }, { 137614, true }, - { 137631, true }, + { 137633, true }, { 137649, true }, - { 137661, true }, - { 137676, true }, - { 137692, true }, - { 137706, true }, - { 137718, true }, - { 137732, true }, - { 137744, true }, - { 137763, true }, - { 137779, true }, - { 137795, true }, - { 137811, true }, - { 137829, true }, - { 137846, true }, - { 137864, true }, - { 137878, true }, - { 137896, true }, - { 137913, true }, - { 137932, true }, - { 137952, true }, + { 137665, true }, + { 137681, true }, + { 137699, true }, + { 137716, true }, + { 137734, true }, + { 137748, true }, + { 137766, true }, + { 137783, true }, + { 137802, true }, + { 137822, true }, + { 137839, true }, + { 137855, true }, + { 137873, false }, + { 137886, true }, + { 137903, false }, + { 137924, true }, + { 137941, true }, + { 137956, true }, { 137969, true }, - { 137985, true }, - { 138003, false }, - { 138016, true }, - { 138033, false }, - { 138054, true }, - { 138071, true }, - { 138086, true }, - { 138099, true }, - { 138110, true }, - { 138128, true }, - { 138140, true }, + { 137980, true }, + { 137998, true }, + { 138010, true }, + { 138034, true }, + { 138043, true }, + { 138058, true }, + { 138085, true }, + { 138103, true }, + { 138112, true }, + { 138122, true }, + { 138133, true }, + { 138143, true }, + { 138156, true }, { 138164, true }, - { 138173, true }, - { 138188, true }, - { 138215, true }, + { 138171, true }, + { 138190, true }, + { 138197, true }, + { 138212, true }, + { 138221, true }, { 138233, true }, - { 138242, true }, - { 138252, true }, - { 138263, true }, - { 138273, true }, - { 138286, true }, - { 138294, true }, - { 138301, true }, - { 138320, true }, - { 138327, true }, - { 138342, true }, - { 138351, true }, + { 138245, false }, + { 138265, true }, + { 138279, true }, + { 138289, true }, + { 138306, true }, + { 138324, true }, + { 138341, true }, { 138363, true }, - { 138375, false }, + { 138376, true }, { 138395, true }, - { 138409, true }, - { 138419, true }, - { 138436, true }, + { 138407, true }, + { 138420, true }, + { 138439, true }, { 138454, true }, - { 138471, true }, - { 138493, true }, - { 138506, true }, - { 138525, true }, - { 138537, true }, - { 138550, true }, - { 138569, true }, - { 138584, true }, - { 138600, true }, - { 138620, true }, - { 138633, true }, - { 138647, true }, - { 138659, true }, - { 138670, true }, - { 138681, true }, - { 138692, true }, - { 138703, true }, + { 138470, true }, + { 138490, true }, + { 138503, true }, + { 138517, true }, + { 138529, true }, + { 138540, true }, + { 138551, true }, + { 138562, true }, + { 138573, true }, + { 138592, true }, + { 138609, true }, + { 138626, true }, + { 138638, true }, + { 138655, true }, + { 138666, true }, + { 138690, true }, + { 138700, true }, + { 138712, true }, { 138722, true }, - { 138739, true }, - { 138756, true }, - { 138768, true }, - { 138785, true }, - { 138796, true }, - { 138820, true }, - { 138830, true }, - { 138842, true }, + { 138753, true }, + { 138762, true }, + { 138779, true }, + { 138791, true }, + { 138810, true }, + { 138826, true }, + { 138839, true }, { 138852, true }, - { 138883, true }, - { 138892, true }, - { 138909, true }, - { 138921, true }, - { 138940, true }, - { 138956, true }, - { 138969, true }, - { 138982, true }, - { 138992, true }, - { 139006, true }, - { 139015, true }, - { 139025, true }, - { 139040, true }, - { 139050, true }, - { 139064, true }, - { 139080, true }, + { 138862, true }, + { 138876, true }, + { 138885, true }, + { 138895, true }, + { 138910, true }, + { 138920, true }, + { 138934, true }, + { 138950, true }, + { 138965, true }, + { 138975, true }, + { 138993, true }, + { 139010, true }, + { 139026, true }, + { 139043, true }, + { 139065, true }, + { 139077, true }, { 139095, true }, - { 139105, true }, - { 139123, true }, - { 139140, true }, - { 139156, true }, - { 139173, true }, - { 139195, true }, - { 139207, true }, - { 139225, true }, - { 139239, false }, - { 139254, true }, - { 139267, true }, + { 139109, false }, + { 139124, true }, + { 139137, true }, + { 139150, true }, + { 139162, true }, + { 139174, true }, + { 139185, true }, + { 139202, true }, + { 139214, true }, + { 139233, true }, + { 139242, true }, + { 139257, false }, + { 139264, true }, { 139280, true }, - { 139292, true }, - { 139304, true }, - { 139315, true }, - { 139332, true }, - { 139344, true }, - { 139363, true }, - { 139372, true }, - { 139387, false }, - { 139394, true }, - { 139410, true }, - { 139425, true }, - { 139447, true }, - { 139463, true }, - { 139481, true }, - { 139495, true }, - { 139505, true }, - { 139520, true }, - { 139530, true }, - { 139542, true }, - { 139560, true }, - { 139576, true }, - { 139591, true }, - { 139606, false }, - { 139629, true }, - { 139637, true }, - { 139653, true }, - { 139664, true }, - { 139681, true }, - { 139701, true }, - { 139713, true }, - { 139744, true }, - { 139765, true }, - { 139778, true }, - { 139799, true }, - { 139810, true }, - { 139827, true }, - { 139839, true }, - { 139847, true }, - { 139858, true }, - { 139867, true }, - { 139876, true }, - { 139890, true }, - { 139902, false }, - { 139909, true }, - { 139917, true }, - { 139926, true }, - { 139935, true }, - { 139946, true }, - { 139954, true }, - { 139968, true }, - { 139987, false }, - { 140007, true }, - { 140017, true }, - { 140038, true }, - { 140049, false }, - { 140061, true }, - { 140078, true }, - { 140089, true }, - { 140118, true }, - { 140132, true }, - { 140146, true }, - { 140163, true }, - { 140175, true }, - { 140190, true }, - { 140198, true }, - { 140212, true }, - { 140229, true }, - { 140247, true }, - { 140260, true }, - { 140269, false }, + { 139295, true }, + { 139317, true }, + { 139333, true }, + { 139351, true }, + { 139365, true }, + { 139375, true }, + { 139390, true }, + { 139400, true }, + { 139412, true }, + { 139430, true }, + { 139446, true }, + { 139461, true }, + { 139476, false }, + { 139499, true }, + { 139507, true }, + { 139523, true }, + { 139534, true }, + { 139551, true }, + { 139571, true }, + { 139583, true }, + { 139614, true }, + { 139635, true }, + { 139648, true }, + { 139669, true }, + { 139680, true }, + { 139697, true }, + { 139709, true }, + { 139717, true }, + { 139728, true }, + { 139737, true }, + { 139746, true }, + { 139760, true }, + { 139772, false }, + { 139779, true }, + { 139787, true }, + { 139796, true }, + { 139805, true }, + { 139816, true }, + { 139824, true }, + { 139838, true }, + { 139857, false }, + { 139877, true }, + { 139887, true }, + { 139908, true }, + { 139919, false }, + { 139931, true }, + { 139948, true }, + { 139959, true }, + { 139988, true }, + { 140002, true }, + { 140016, true }, + { 140033, true }, + { 140045, true }, + { 140060, true }, + { 140068, true }, + { 140082, true }, + { 140099, true }, + { 140117, true }, + { 140130, true }, + { 140139, false }, + { 140157, true }, + { 140169, true }, + { 140182, true }, + { 140191, true }, + { 140214, true }, + { 140228, true }, + { 140241, true }, + { 140257, true }, + { 140274, true }, { 140287, true }, - { 140299, true }, - { 140312, true }, - { 140321, true }, - { 140344, true }, - { 140358, true }, - { 140371, true }, - { 140387, true }, - { 140404, true }, - { 140417, true }, - { 140435, true }, - { 140447, true }, - { 140466, false }, - { 140482, true }, - { 140505, true }, - { 140514, true }, - { 140529, true }, - { 140537, true }, - { 140552, true }, - { 140571, true }, - { 140585, true }, - { 140601, true }, - { 140621, true }, - { 140631, true }, - { 140649, true }, - { 140656, true }, - { 140668, true }, - { 140681, true }, - { 140691, true }, - { 140697, true }, - { 140705, true }, - { 140713, true }, - { 140721, false }, - { 140744, true }, - { 140769, true }, - { 140786, true }, - { 140798, true }, - { 140810, true }, - { 140825, true }, - { 140834, true }, - { 140848, true }, - { 140861, true }, - { 140883, true }, - { 140893, true }, - { 140914, true }, - { 140935, true }, - { 140952, true }, - { 140968, true }, - { 140981, true }, - { 140991, true }, - { 141001, true }, - { 141014, true }, - { 141038, true }, - { 141057, true }, + { 140305, true }, + { 140317, true }, + { 140336, false }, + { 140352, true }, + { 140375, true }, + { 140384, true }, + { 140399, true }, + { 140407, true }, + { 140422, true }, + { 140441, true }, + { 140455, true }, + { 140471, true }, + { 140491, true }, + { 140501, true }, + { 140519, true }, + { 140526, true }, + { 140538, true }, + { 140551, true }, + { 140561, true }, + { 140567, true }, + { 140575, true }, + { 140583, true }, + { 140591, false }, + { 140614, true }, + { 140633, true }, + { 140658, true }, + { 140675, true }, + { 140687, true }, + { 140699, true }, + { 140714, true }, + { 140723, true }, + { 140737, true }, + { 140750, true }, + { 140772, true }, + { 140782, true }, + { 140803, true }, + { 140824, true }, + { 140841, true }, + { 140857, true }, + { 140870, true }, + { 140880, true }, + { 140890, true }, + { 140903, true }, + { 140927, true }, + { 140946, true }, + { 140958, true }, + { 140976, true }, + { 140993, false }, + { 141006, true }, + { 141019, false }, + { 141040, true }, + { 141050, true }, { 141069, true }, - { 141087, true }, - { 141104, false }, + { 141082, true }, + { 141097, true }, { 141117, true }, - { 141130, false }, - { 141151, true }, - { 141161, true }, - { 141180, true }, - { 141193, true }, - { 141208, true }, - { 141228, true }, - { 141239, true }, - { 141251, true }, - { 141264, true }, + { 141128, true }, + { 141140, true }, + { 141153, true }, + { 141168, true }, + { 141183, true }, + { 141196, false }, + { 141205, true }, + { 141224, true }, + { 141241, false }, + { 141256, true }, + { 141266, true }, { 141279, true }, - { 141294, true }, - { 141307, false }, - { 141316, true }, + { 141295, true }, + { 141313, true }, + { 141323, true }, { 141335, true }, - { 141352, false }, - { 141367, true }, - { 141377, true }, - { 141390, true }, - { 141406, true }, - { 141424, true }, - { 141434, true }, + { 141348, true }, + { 141361, true }, + { 141370, true }, + { 141394, false }, + { 141407, true }, + { 141418, true }, + { 141430, true }, { 141446, true }, - { 141459, true }, - { 141472, true }, - { 141481, true }, - { 141505, false }, - { 141518, true }, - { 141529, true }, - { 141541, true }, - { 141557, true }, - { 141574, true }, - { 141584, true }, - { 141601, true }, - { 141620, false }, - { 141629, true }, - { 141651, true }, - { 141665, true }, - { 141678, false }, + { 141463, true }, + { 141480, true }, + { 141499, false }, + { 141508, true }, + { 141530, true }, + { 141544, true }, + { 141557, false }, + { 141572, true }, + { 141587, true }, + { 141599, true }, + { 141618, false }, + { 141641, true }, + { 141657, true }, + { 141673, false }, { 141693, true }, - { 141708, true }, - { 141720, true }, - { 141739, false }, - { 141762, true }, - { 141778, true }, - { 141794, false }, - { 141814, true }, - { 141827, true }, - { 141843, true }, - { 141854, true }, - { 141873, true }, - { 141887, true }, - { 141898, true }, + { 141706, true }, + { 141722, true }, + { 141733, true }, + { 141752, true }, + { 141766, true }, + { 141777, true }, + { 141787, true }, + { 141804, true }, + { 141816, true }, + { 141834, true }, + { 141853, true }, + { 141865, true }, + { 141876, true }, + { 141895, true }, { 141908, true }, - { 141925, true }, - { 141937, true }, - { 141955, true }, - { 141974, true }, - { 141986, true }, - { 141997, true }, - { 142016, true }, - { 142029, true }, - { 142045, true }, - { 142069, false }, - { 142087, true }, - { 142105, false }, - { 142125, true }, - { 142141, true }, - { 142159, true }, - { 142171, true }, - { 142188, true }, - { 142207, true }, - { 142227, true }, - { 142240, true }, - { 142252, true }, - { 142275, true }, - { 142283, true }, - { 142303, true }, - { 142311, true }, - { 142327, true }, - { 142341, true }, - { 142350, true }, - { 142362, true }, - { 142372, true }, - { 142381, true }, - { 142398, true }, - { 142410, true }, - { 142421, true }, - { 142431, true }, - { 142442, true }, - { 142455, true }, - { 142468, true }, + { 141924, true }, + { 141948, false }, + { 141966, true }, + { 141984, false }, + { 142004, true }, + { 142020, true }, + { 142038, true }, + { 142050, true }, + { 142067, true }, + { 142086, true }, + { 142106, true }, + { 142119, true }, + { 142131, true }, + { 142154, true }, + { 142162, true }, + { 142182, true }, + { 142190, true }, + { 142206, true }, + { 142220, true }, + { 142229, true }, + { 142241, true }, + { 142251, true }, + { 142260, true }, + { 142277, true }, + { 142289, true }, + { 142300, true }, + { 142310, true }, + { 142321, true }, + { 142334, true }, + { 142347, true }, + { 142364, true }, + { 142375, true }, + { 142385, true }, + { 142402, true }, + { 142430, true }, + { 142444, true }, + { 142456, true }, + { 142475, true }, { 142485, true }, - { 142496, true }, - { 142506, true }, - { 142523, true }, - { 142551, true }, - { 142565, true }, - { 142577, true }, - { 142596, true }, - { 142606, true }, - { 142628, true }, - { 142642, true }, - { 142656, true }, - { 142671, true }, - { 142685, true }, - { 142694, true }, - { 142700, true }, - { 142708, true }, - { 142720, true }, - { 142741, true }, - { 142751, true }, - { 142769, true }, - { 142780, true }, - { 142798, true }, + { 142507, true }, + { 142521, true }, + { 142535, true }, + { 142550, true }, + { 142564, true }, + { 142573, true }, + { 142579, true }, + { 142587, true }, + { 142599, true }, + { 142620, true }, + { 142630, true }, + { 142648, true }, + { 142659, true }, + { 142677, true }, + { 142690, true }, + { 142709, true }, + { 142725, true }, + { 142738, true }, + { 142749, true }, + { 142762, true }, + { 142776, true }, + { 142793, true }, + { 142803, true }, { 142811, true }, - { 142830, true }, - { 142846, true }, - { 142859, true }, - { 142870, true }, + { 142828, true }, + { 142842, true }, + { 142856, true }, + { 142870, false }, { 142883, true }, - { 142897, true }, - { 142914, true }, - { 142924, true }, - { 142932, true }, - { 142949, true }, - { 142963, true }, - { 142977, true }, - { 142991, false }, - { 143004, true }, - { 143016, true }, - { 143028, true }, - { 143047, true }, - { 143066, true }, + { 142895, true }, + { 142907, true }, + { 142926, true }, + { 142945, true }, + { 142959, true }, + { 142971, true }, + { 142984, true }, + { 143000, true }, + { 143013, true }, + { 143026, true }, + { 143041, true }, + { 143069, true }, { 143080, true }, - { 143092, true }, - { 143105, true }, - { 143121, true }, - { 143134, true }, - { 143147, true }, + { 143093, true }, + { 143112, true }, + { 143125, true }, + { 143150, true }, { 143162, true }, + { 143176, true }, { 143190, true }, - { 143201, true }, - { 143214, true }, + { 143205, true }, + { 143219, true }, { 143233, true }, - { 143246, true }, - { 143271, true }, - { 143283, true }, - { 143297, true }, - { 143311, true }, - { 143326, true }, - { 143340, true }, - { 143354, true }, - { 143368, true }, - { 143384, true }, - { 143407, true }, + { 143247, true }, + { 143263, true }, + { 143286, true }, + { 143302, true }, + { 143317, true }, + { 143341, true }, + { 143360, true }, + { 143373, true }, + { 143403, true }, { 143423, true }, - { 143438, true }, - { 143462, true }, - { 143481, true }, - { 143494, true }, - { 143524, true }, - { 143544, true }, - { 143562, true }, - { 143575, true }, - { 143596, true }, - { 143614, true }, - { 143630, true }, - { 143643, true }, - { 143656, true }, - { 143673, true }, - { 143693, true }, - { 143706, true }, - { 143721, true }, - { 143733, true }, - { 143752, true }, - { 143771, true }, - { 143785, true }, + { 143441, true }, + { 143454, true }, + { 143475, true }, + { 143493, true }, + { 143509, true }, + { 143522, true }, + { 143535, true }, + { 143552, true }, + { 143572, true }, + { 143585, true }, + { 143600, true }, + { 143612, true }, + { 143631, true }, + { 143650, true }, + { 143664, true }, + { 143679, true }, + { 143691, true }, + { 143708, true }, + { 143723, true }, + { 143741, true }, + { 143753, true }, + { 143767, true }, + { 143778, true }, { 143800, true }, - { 143812, true }, - { 143829, true }, - { 143844, true }, - { 143862, true }, - { 143874, true }, + { 143809, true }, + { 143821, true }, + { 143836, true }, + { 143859, true }, + { 143870, true }, { 143888, true }, - { 143899, true }, - { 143921, true }, - { 143930, true }, - { 143942, true }, - { 143958, true }, - { 143981, true }, - { 143992, true }, - { 144010, true }, - { 144026, true }, - { 144042, true }, - { 144059, true }, - { 144078, true }, - { 144096, true }, - { 144102, true }, - { 144120, false }, - { 144140, true }, - { 144157, true }, - { 144171, true }, - { 144183, true }, - { 144202, false }, - { 144219, true }, - { 144238, true }, - { 144249, true }, - { 144268, true }, - { 144291, true }, - { 144309, true }, - { 144329, true }, - { 144346, true }, - { 144365, true }, - { 144383, true }, - { 144392, true }, - { 144399, true }, - { 144406, true }, - { 144418, false }, - { 144438, true }, - { 144446, true }, - { 144457, true }, - { 144480, true }, - { 144504, true }, - { 144527, true }, + { 143904, true }, + { 143920, true }, + { 143937, true }, + { 143956, true }, + { 143974, true }, + { 143980, true }, + { 143998, false }, + { 144018, true }, + { 144035, true }, + { 144049, true }, + { 144061, true }, + { 144080, false }, + { 144097, true }, + { 144116, true }, + { 144127, true }, + { 144146, true }, + { 144169, true }, + { 144187, true }, + { 144207, true }, + { 144224, true }, + { 144243, true }, + { 144261, true }, + { 144270, true }, + { 144277, true }, + { 144284, true }, + { 144296, false }, + { 144316, true }, + { 144324, true }, + { 144335, true }, + { 144358, true }, + { 144382, true }, + { 144405, true }, + { 144428, true }, + { 144456, true }, + { 144485, true }, + { 144500, true }, + { 144519, true }, + { 144532, true }, { 144550, true }, - { 144578, true }, - { 144607, true }, - { 144622, true }, - { 144641, true }, - { 144654, true }, - { 144672, true }, - { 144695, true }, - { 144712, true }, - { 144723, true }, - { 144734, true }, - { 144752, true }, - { 144778, true }, - { 144807, true }, - { 144819, true }, - { 144832, false }, - { 144852, true }, - { 144864, true }, - { 144882, false }, - { 144897, false }, + { 144573, true }, + { 144590, true }, + { 144601, true }, + { 144612, true }, + { 144630, true }, + { 144656, true }, + { 144685, true }, + { 144697, true }, + { 144710, false }, + { 144730, true }, + { 144742, true }, + { 144760, false }, + { 144775, false }, + { 144791, true }, + { 144809, true }, + { 144825, true }, + { 144843, true }, + { 144859, true }, + { 144871, true }, + { 144891, true }, { 144913, true }, - { 144931, true }, - { 144947, true }, - { 144965, true }, - { 144981, true }, - { 144993, true }, - { 145013, true }, - { 145035, true }, - { 145055, true }, - { 145073, true }, - { 145092, true }, - { 145112, true }, - { 145131, true }, - { 145148, true }, - { 145166, false }, - { 145184, true }, - { 145203, true }, - { 145215, true }, - { 145229, true }, - { 145244, true }, - { 145263, true }, - { 145277, true }, - { 145292, true }, - { 145307, true }, - { 145317, true }, - { 145330, true }, - { 145350, true }, - { 145359, true }, - { 145369, false }, - { 145386, true }, - { 145395, true }, + { 144933, true }, + { 144951, true }, + { 144970, true }, + { 144990, true }, + { 145009, true }, + { 145027, false }, + { 145045, true }, + { 145064, true }, + { 145076, true }, + { 145090, true }, + { 145105, true }, + { 145124, true }, + { 145138, true }, + { 145153, true }, + { 145168, true }, + { 145178, true }, + { 145191, true }, + { 145211, true }, + { 145220, true }, + { 145230, false }, + { 145247, true }, + { 145256, true }, + { 145269, true }, + { 145286, true }, + { 145300, true }, + { 145314, true }, + { 145326, true }, + { 145343, true }, + { 145353, true }, + { 145369, true }, + { 145381, true }, + { 145392, false }, { 145408, true }, - { 145425, true }, - { 145439, true }, - { 145453, true }, - { 145465, true }, - { 145482, true }, - { 145492, true }, - { 145508, true }, - { 145520, true }, - { 145531, false }, - { 145547, true }, - { 145558, true }, - { 145574, true }, - { 145583, true }, - { 145596, true }, - { 145613, true }, - { 145625, true }, - { 145637, true }, + { 145419, true }, + { 145435, true }, + { 145444, true }, + { 145457, true }, + { 145474, true }, + { 145486, true }, + { 145498, true }, + { 145510, true }, + { 145519, true }, + { 145531, true }, + { 145546, true }, + { 145560, true }, + { 145570, true }, + { 145591, true }, + { 145609, true }, + { 145621, true }, + { 145636, true }, { 145646, true }, - { 145658, true }, + { 145661, true }, { 145673, true }, - { 145687, true }, - { 145697, true }, - { 145718, true }, - { 145736, true }, - { 145748, true }, - { 145763, true }, - { 145773, true }, - { 145788, true }, - { 145800, true }, - { 145812, true }, - { 145827, true }, - { 145838, true }, - { 145849, true }, - { 145857, true }, - { 145870, true }, - { 145883, true }, - { 145892, true }, - { 145909, true }, - { 145919, true }, - { 145932, true }, - { 145949, true }, - { 145963, true }, - { 145972, true }, - { 145987, true }, - { 146001, true }, - { 146014, true }, - { 146028, true }, - { 146042, true }, - { 146061, true }, - { 146069, true }, - { 146086, true }, - { 146101, true }, - { 146116, true }, - { 146130, true }, - { 146146, true }, - { 146162, true }, - { 146176, true }, - { 146192, true }, - { 146209, true }, - { 146222, true }, - { 146236, false }, - { 146254, true }, - { 146269, true }, - { 146286, true }, - { 146303, false }, - { 146329, true }, - { 146344, true }, - { 146362, true }, - { 146375, true }, - { 146385, true }, - { 146398, true }, - { 146410, true }, - { 146429, true }, - { 146439, true }, - { 146454, true }, - { 146470, true }, - { 146482, true }, - { 146495, true }, - { 146506, true }, - { 146523, true }, - { 146554, true }, - { 146565, true }, - { 146577, true }, - { 146591, true }, - { 146599, true }, - { 146607, true }, + { 145685, true }, + { 145700, true }, + { 145711, true }, + { 145722, true }, + { 145730, true }, + { 145743, true }, + { 145756, true }, + { 145765, true }, + { 145782, true }, + { 145792, true }, + { 145805, true }, + { 145822, true }, + { 145836, true }, + { 145845, true }, + { 145860, true }, + { 145874, true }, + { 145887, true }, + { 145901, true }, + { 145915, true }, + { 145934, true }, + { 145942, true }, + { 145959, true }, + { 145974, true }, + { 145989, true }, + { 146003, true }, + { 146019, true }, + { 146035, true }, + { 146049, true }, + { 146065, true }, + { 146082, true }, + { 146095, true }, + { 146109, false }, + { 146127, true }, + { 146142, true }, + { 146159, true }, + { 146176, false }, + { 146202, true }, + { 146217, true }, + { 146235, true }, + { 146248, true }, + { 146258, true }, + { 146271, true }, + { 146283, true }, + { 146302, true }, + { 146312, true }, + { 146327, true }, + { 146343, true }, + { 146355, true }, + { 146368, true }, + { 146379, true }, + { 146396, true }, + { 146427, true }, + { 146438, true }, + { 146450, true }, + { 146464, true }, + { 146472, true }, + { 146480, true }, + { 146491, true }, + { 146502, false }, + { 146522, true }, + { 146540, true }, + { 146555, false }, + { 146569, true }, + { 146589, true }, + { 146600, true }, { 146618, true }, - { 146629, false }, - { 146649, true }, - { 146667, true }, - { 146682, true }, + { 146633, true }, + { 146650, true }, + { 146666, true }, + { 146691, true }, { 146702, true }, { 146713, true }, + { 146726, true }, { 146738, true }, - { 146756, true }, - { 146771, true }, - { 146788, true }, - { 146804, true }, - { 146829, true }, - { 146840, true }, - { 146851, true }, - { 146864, true }, - { 146876, true }, - { 146889, false }, - { 146897, true }, - { 146907, true }, - { 146922, true }, - { 146940, true }, - { 146959, true }, - { 146972, true }, - { 146987, true }, - { 147000, true }, - { 147013, true }, - { 147026, true }, - { 147046, true }, - { 147064, true }, - { 147078, true }, - { 147089, true }, - { 147100, true }, - { 147117, true }, + { 146751, false }, + { 146759, true }, + { 146769, true }, + { 146784, true }, + { 146802, true }, + { 146821, true }, + { 146834, true }, + { 146847, true }, + { 146862, true }, + { 146875, true }, + { 146888, true }, + { 146901, true }, + { 146921, true }, + { 146939, true }, + { 146953, true }, + { 146964, true }, + { 146975, true }, + { 146992, true }, + { 147007, true }, + { 147020, true }, + { 147045, true }, + { 147081, true }, + { 147094, true }, + { 147104, true }, + { 147119, true }, { 147132, true }, - { 147145, true }, - { 147170, true }, - { 147206, true }, - { 147219, true }, - { 147229, true }, - { 147244, true }, - { 147257, true }, - { 147279, true }, - { 147297, true }, - { 147310, true }, - { 147321, true }, - { 147333, true }, - { 147341, true }, - { 147374, true }, - { 147381, true }, - { 147398, true }, - { 147416, false }, + { 147154, true }, + { 147172, true }, + { 147185, true }, + { 147196, true }, + { 147208, true }, + { 147216, true }, + { 147249, true }, + { 147256, true }, + { 147273, true }, + { 147291, false }, + { 147309, true }, + { 147327, true }, + { 147339, true }, + { 147351, true }, + { 147364, true }, + { 147380, true }, + { 147394, true }, + { 147414, true }, { 147434, true }, - { 147452, true }, + { 147445, true }, + { 147455, true }, { 147464, true }, - { 147476, true }, - { 147489, true }, - { 147505, true }, - { 147519, true }, - { 147539, true }, + { 147475, true }, + { 147494, true }, + { 147508, true }, + { 147522, true }, + { 147545, true }, { 147559, true }, - { 147570, true }, - { 147580, true }, - { 147589, true }, - { 147600, true }, - { 147619, true }, - { 147633, true }, - { 147647, true }, - { 147670, true }, - { 147684, true }, - { 147698, true }, - { 147710, true }, - { 147724, true }, - { 147738, true }, - { 147747, true }, - { 147759, true }, - { 147771, true }, - { 147782, true }, - { 147791, true }, - { 147800, true }, - { 147812, true }, - { 147826, true }, - { 147838, true }, - { 147853, false }, - { 147880, true }, - { 147900, true }, - { 147910, true }, - { 147923, true }, - { 147936, true }, - { 147952, true }, - { 147973, true }, - { 147992, true }, - { 148002, true }, + { 147573, true }, + { 147585, true }, + { 147599, true }, + { 147613, true }, + { 147622, true }, + { 147634, true }, + { 147646, true }, + { 147657, true }, + { 147666, true }, + { 147675, true }, + { 147687, true }, + { 147701, true }, + { 147713, true }, + { 147728, false }, + { 147755, true }, + { 147775, true }, + { 147785, true }, + { 147798, true }, + { 147811, true }, + { 147827, true }, + { 147848, true }, + { 147867, true }, + { 147877, true }, + { 147889, true }, + { 147901, true }, + { 147912, false }, + { 147920, true }, + { 147935, true }, + { 147949, true }, + { 147958, true }, + { 147970, true }, + { 147983, true }, + { 147993, true }, { 148014, true }, - { 148026, false }, - { 148034, true }, - { 148049, true }, - { 148063, true }, - { 148072, true }, - { 148084, true }, - { 148097, true }, - { 148107, true }, - { 148128, true }, - { 148140, true }, - { 148151, true }, - { 148171, true }, - { 148190, true }, - { 148201, true }, - { 148216, true }, - { 148241, false }, - { 148269, false }, + { 148026, true }, + { 148037, true }, + { 148057, true }, + { 148076, true }, + { 148087, true }, + { 148102, true }, + { 148127, false }, + { 148155, false }, + { 148167, true }, + { 148178, true }, + { 148189, true }, + { 148204, true }, + { 148219, true }, + { 148236, true }, + { 148248, false }, + { 148265, true }, { 148281, true }, - { 148292, true }, - { 148303, true }, - { 148318, true }, - { 148333, true }, - { 148350, true }, - { 148362, false }, - { 148379, true }, - { 148395, true }, - { 148409, true }, + { 148295, true }, + { 148310, true }, + { 148325, true }, + { 148341, true }, + { 148364, true }, + { 148383, true }, + { 148404, true }, { 148424, true }, - { 148439, true }, - { 148455, true }, - { 148472, true }, - { 148495, true }, - { 148514, true }, - { 148535, true }, - { 148555, true }, - { 148573, true }, - { 148592, true }, - { 148610, true }, - { 148628, true }, - { 148643, false }, - { 148658, false }, - { 148672, true }, - { 148683, true }, + { 148442, true }, + { 148461, true }, + { 148479, true }, + { 148497, true }, + { 148512, false }, + { 148527, false }, + { 148541, true }, + { 148552, true }, + { 148563, true }, + { 148578, true }, + { 148596, true }, + { 148618, true }, + { 148632, true }, + { 148646, true }, + { 148665, true }, + { 148679, true }, { 148694, true }, - { 148709, true }, - { 148727, true }, - { 148749, true }, - { 148763, true }, - { 148777, true }, - { 148796, true }, - { 148810, true }, - { 148825, true }, - { 148841, true }, + { 148710, true }, + { 148728, true }, + { 148738, true }, + { 148750, false }, + { 148761, true }, + { 148774, true }, + { 148793, false }, + { 148812, true }, + { 148827, true }, + { 148840, false }, { 148859, true }, - { 148869, true }, - { 148881, false }, - { 148892, true }, - { 148905, true }, - { 148924, false }, - { 148943, true }, - { 148958, true }, - { 148971, false }, - { 148990, true }, - { 149001, true }, - { 149019, true }, - { 149033, true }, - { 149058, true }, - { 149073, true }, - { 149091, true }, - { 149108, true }, - { 149119, true }, - { 149129, true }, - { 149144, true }, - { 149153, true }, - { 149163, true }, - { 149178, false }, - { 149191, true }, - { 149207, true }, - { 149228, true }, - { 149247, true }, - { 149259, true }, - { 149270, true }, - { 149282, true }, + { 148870, true }, + { 148888, true }, + { 148902, true }, + { 148927, true }, + { 148945, true }, + { 148960, true }, + { 148977, true }, + { 148988, true }, + { 148998, true }, + { 149013, true }, + { 149022, true }, + { 149032, true }, + { 149042, true }, + { 149057, false }, + { 149070, true }, + { 149086, true }, + { 149107, true }, + { 149126, true }, + { 149138, true }, + { 149149, true }, + { 149161, true }, + { 149176, true }, + { 149190, true }, + { 149210, true }, + { 149233, true }, + { 149246, true }, + { 149264, true }, + { 149272, true }, + { 149280, true }, { 149297, true }, - { 149311, true }, - { 149331, true }, - { 149354, true }, - { 149367, true }, - { 149385, true }, - { 149393, true }, - { 149401, true }, - { 149418, true }, - { 149435, true }, - { 149446, false }, - { 149463, true }, + { 149314, true }, + { 149325, false }, + { 149342, true }, + { 149355, true }, + { 149366, false }, + { 149379, true }, + { 149394, false }, + { 149418, false }, + { 149430, true }, + { 149455, true }, + { 149464, true }, { 149476, true }, - { 149487, false }, - { 149500, true }, - { 149515, false }, - { 149539, false }, - { 149551, true }, - { 149576, true }, - { 149585, true }, - { 149597, true }, - { 149617, true }, - { 149634, true }, - { 149644, true }, - { 149665, true }, - { 149674, true }, - { 149693, true }, - { 149711, true }, - { 149727, true }, - { 149742, true }, - { 149757, true }, - { 149772, true }, - { 149792, true }, - { 149805, true }, - { 149818, true }, - { 149827, true }, - { 149841, true }, - { 149864, true }, - { 149886, true }, - { 149912, true }, - { 149927, true }, - { 149942, true }, - { 149956, true }, - { 149968, true }, - { 149991, true }, - { 150001, true }, - { 150009, true }, - { 150025, true }, - { 150039, true }, - { 150052, false }, - { 150070, true }, - { 150081, true }, - { 150094, true }, - { 150105, true }, - { 150118, true }, - { 150128, true }, - { 150143, true }, + { 149496, true }, + { 149513, true }, + { 149523, true }, + { 149544, true }, + { 149553, true }, + { 149572, true }, + { 149590, true }, + { 149606, true }, + { 149621, true }, + { 149636, true }, + { 149651, true }, + { 149671, true }, + { 149684, true }, + { 149697, true }, + { 149706, true }, + { 149720, true }, + { 149743, true }, + { 149765, true }, + { 149791, true }, + { 149806, true }, + { 149821, true }, + { 149835, true }, + { 149847, true }, + { 149870, true }, + { 149880, true }, + { 149888, true }, + { 149904, true }, + { 149918, true }, + { 149931, false }, + { 149949, true }, + { 149960, true }, + { 149973, true }, + { 149984, true }, + { 149997, true }, + { 150007, true }, + { 150022, true }, + { 150035, true }, + { 150051, true }, + { 150061, false }, + { 150071, true }, + { 150084, true }, + { 150099, true }, + { 150109, true }, + { 150121, true }, + { 150130, true }, + { 150145, true }, { 150156, true }, - { 150172, true }, - { 150182, false }, + { 150176, true }, { 150192, true }, - { 150205, true }, - { 150220, true }, - { 150230, true }, - { 150242, true }, - { 150251, true }, - { 150266, true }, - { 150277, true }, - { 150289, true }, - { 150309, true }, - { 150325, true }, - { 150342, true }, - { 150352, true }, - { 150362, true }, - { 150376, true }, - { 150388, true }, - { 150401, true }, - { 150418, true }, - { 150433, true }, - { 150450, true }, - { 150467, true }, - { 150481, true }, - { 150497, true }, - { 150510, true }, - { 150525, false }, - { 150537, true }, - { 150547, true }, - { 150556, true }, - { 150568, true }, - { 150576, true }, - { 150584, true }, - { 150592, true }, - { 150598, true }, - { 150611, true }, - { 150626, true }, - { 150645, true }, - { 150660, true }, - { 150684, true }, - { 150694, true }, - { 150710, true }, - { 150733, true }, - { 150754, true }, - { 150767, true }, - { 150780, true }, - { 150797, true }, - { 150811, true }, - { 150823, false }, - { 150836, true }, - { 150855, true }, - { 150873, true }, - { 150897, false }, - { 150924, true }, - { 150950, true }, - { 150965, true }, - { 150982, true }, - { 150998, true }, - { 151015, true }, - { 151028, true }, - { 151039, true }, - { 151050, true }, - { 151060, true }, - { 151069, true }, - { 151082, true }, - { 151095, true }, - { 151105, true }, - { 151116, true }, - { 151137, true }, - { 151151, true }, + { 150209, true }, + { 150219, true }, + { 150229, true }, + { 150243, true }, + { 150255, true }, + { 150268, true }, + { 150285, true }, + { 150300, true }, + { 150317, true }, + { 150334, true }, + { 150348, true }, + { 150364, true }, + { 150377, true }, + { 150392, false }, + { 150404, true }, + { 150414, true }, + { 150423, true }, + { 150435, true }, + { 150443, true }, + { 150451, true }, + { 150459, true }, + { 150465, true }, + { 150478, true }, + { 150493, true }, + { 150512, true }, + { 150527, true }, + { 150551, true }, + { 150561, true }, + { 150577, true }, + { 150600, true }, + { 150621, true }, + { 150634, true }, + { 150647, true }, + { 150664, true }, + { 150678, true }, + { 150690, false }, + { 150703, true }, + { 150722, true }, + { 150740, true }, + { 150764, false }, + { 150791, true }, + { 150817, true }, + { 150832, true }, + { 150849, true }, + { 150865, true }, + { 150882, true }, + { 150895, true }, + { 150906, true }, + { 150917, true }, + { 150927, true }, + { 150940, true }, + { 150953, true }, + { 150963, true }, + { 150974, true }, + { 150995, true }, + { 151009, true }, + { 151018, true }, + { 151025, true }, + { 151033, true }, + { 151056, true }, + { 151070, true }, + { 151079, true }, + { 151088, true }, + { 151096, true }, + { 151109, true }, + { 151117, true }, + { 151128, false }, + { 151144, true }, { 151160, true }, - { 151167, true }, - { 151175, true }, - { 151198, true }, - { 151212, true }, - { 151221, true }, - { 151230, true }, - { 151238, true }, - { 151251, true }, - { 151259, true }, - { 151270, false }, - { 151286, true }, - { 151302, true }, + { 151173, true }, + { 151184, true }, + { 151196, true }, + { 151211, true }, + { 151220, true }, + { 151232, true }, + { 151243, true }, + { 151255, true }, + { 151268, true }, + { 151283, true }, + { 151303, true }, { 151315, true }, - { 151326, true }, - { 151338, true }, + { 151332, true }, + { 151342, true }, { 151353, true }, - { 151362, true }, - { 151374, true }, - { 151385, true }, - { 151397, true }, - { 151410, true }, - { 151425, true }, - { 151445, true }, - { 151457, true }, - { 151474, true }, - { 151484, true }, - { 151495, true }, + { 151363, true }, + { 151370, true }, + { 151380, true }, + { 151394, true }, + { 151406, true }, + { 151422, true }, + { 151437, true }, + { 151446, true }, + { 151460, true }, + { 151480, true }, + { 151498, true }, { 151505, true }, - { 151512, true }, { 151522, true }, - { 151536, true }, - { 151548, true }, - { 151564, true }, - { 151579, true }, - { 151588, true }, - { 151602, true }, - { 151622, true }, + { 151539, true }, + { 151559, true }, + { 151578, false }, + { 151596, true }, + { 151623, true }, { 151640, true }, - { 151647, true }, - { 151664, true }, - { 151681, true }, - { 151701, true }, - { 151720, false }, - { 151738, true }, - { 151765, true }, - { 151782, true }, - { 151796, true }, - { 151811, false }, - { 151830, true }, + { 151654, true }, + { 151669, false }, + { 151688, true }, + { 151706, true }, + { 151724, true }, + { 151742, true }, + { 151759, true }, + { 151780, true }, + { 151799, true }, + { 151810, true }, + { 151818, true }, + { 151833, true }, { 151848, true }, - { 151866, true }, - { 151884, true }, - { 151901, true }, - { 151922, true }, - { 151941, true }, - { 151952, true }, - { 151960, true }, - { 151975, true }, - { 151990, true }, - { 152001, true }, - { 152023, true }, - { 152036, true }, - { 152055, true }, - { 152081, true }, - { 152097, false }, - { 152107, true }, - { 152125, true }, - { 152143, true }, - { 152158, true }, - { 152166, true }, - { 152179, true }, - { 152187, true }, - { 152201, true }, - { 152217, true }, - { 152226, true }, - { 152243, true }, - { 152253, true }, - { 152266, true }, - { 152284, true }, - { 152297, true }, - { 152316, false }, - { 152326, true }, - { 152343, true }, - { 152359, true }, - { 152382, true }, - { 152407, true }, - { 152421, true }, - { 152434, true }, - { 152445, true }, - { 152460, true }, - { 152472, true }, - { 152490, true }, - { 152515, true }, - { 152527, true }, - { 152539, true }, - { 152551, true }, - { 152569, true }, - { 152590, true }, - { 152606, true }, - { 152618, true }, - { 152632, true }, - { 152647, true }, - { 152660, true }, - { 152680, true }, - { 152690, false }, - { 152701, true }, - { 152709, false }, - { 152721, true }, - { 152738, true }, - { 152748, true }, - { 152759, true }, + { 151859, true }, + { 151881, true }, + { 151894, true }, + { 151913, true }, + { 151939, true }, + { 151955, true }, + { 151973, true }, + { 151991, true }, + { 152006, true }, + { 152014, true }, + { 152027, true }, + { 152035, true }, + { 152049, true }, + { 152065, true }, + { 152074, true }, + { 152091, true }, + { 152101, true }, + { 152114, true }, + { 152132, true }, + { 152145, true }, + { 152164, false }, + { 152174, true }, + { 152191, true }, + { 152207, true }, + { 152230, true }, + { 152255, true }, + { 152269, true }, + { 152282, true }, + { 152293, true }, + { 152308, true }, + { 152320, true }, + { 152338, true }, + { 152363, true }, + { 152375, true }, + { 152387, true }, + { 152399, true }, + { 152417, true }, + { 152438, true }, + { 152454, true }, + { 152466, true }, + { 152480, true }, + { 152495, true }, + { 152508, true }, + { 152518, false }, + { 152529, true }, + { 152537, false }, + { 152549, true }, + { 152566, true }, + { 152576, true }, + { 152587, true }, + { 152594, true }, + { 152605, true }, + { 152625, true }, + { 152640, true }, + { 152649, true }, + { 152656, true }, + { 152666, true }, + { 152677, true }, + { 152687, true }, + { 152708, true }, + { 152717, false }, + { 152730, true }, + { 152746, true }, { 152766, true }, - { 152777, true }, - { 152797, true }, - { 152812, true }, - { 152821, true }, - { 152828, true }, - { 152838, true }, - { 152849, true }, - { 152861, true }, - { 152871, true }, - { 152892, true }, - { 152901, false }, - { 152914, true }, - { 152930, true }, + { 152780, true }, + { 152796, true }, + { 152810, true }, + { 152825, true }, + { 152833, true }, + { 152846, true }, + { 152862, true }, + { 152875, true }, + { 152888, true }, + { 152910, true }, + { 152931, true }, { 152950, true }, - { 152964, true }, - { 152980, true }, - { 152994, true }, - { 153009, true }, - { 153017, true }, - { 153030, true }, - { 153046, true }, - { 153059, true }, - { 153072, true }, - { 153086, true }, - { 153108, true }, - { 153129, true }, - { 153148, true }, - { 153176, true }, - { 153197, true }, - { 153216, true }, - { 153240, true }, - { 153250, true }, - { 153259, true }, + { 152978, true }, + { 152999, true }, + { 153018, true }, + { 153042, true }, + { 153052, true }, + { 153061, true }, + { 153074, true }, + { 153080, true }, + { 153092, true }, + { 153106, true }, + { 153120, true }, + { 153134, false }, + { 153147, true }, + { 153160, true }, + { 153171, true }, + { 153181, true }, + { 153194, true }, + { 153213, true }, + { 153232, true }, + { 153252, true }, + { 153261, true }, { 153272, true }, - { 153278, true }, - { 153290, true }, - { 153304, true }, - { 153318, true }, - { 153332, false }, - { 153345, true }, - { 153358, true }, - { 153369, true }, - { 153379, true }, - { 153392, true }, - { 153411, true }, - { 153430, true }, - { 153450, true }, - { 153459, true }, + { 153281, true }, + { 153300, false }, + { 153316, false }, + { 153329, true }, + { 153340, true }, + { 153350, true }, + { 153365, true }, + { 153376, true }, + { 153395, true }, + { 153408, true }, + { 153420, true }, + { 153433, true }, + { 153448, true }, + { 153457, true }, { 153470, true }, - { 153479, true }, - { 153498, false }, - { 153514, false }, - { 153527, true }, - { 153538, true }, - { 153548, true }, - { 153563, true }, - { 153574, true }, - { 153593, true }, - { 153606, true }, - { 153618, true }, - { 153631, true }, - { 153646, true }, - { 153655, true }, - { 153668, true }, - { 153680, true }, - { 153695, true }, - { 153711, true }, - { 153728, true }, - { 153740, true }, - { 153754, true }, - { 153768, true }, - { 153792, true }, - { 153807, true }, - { 153823, true }, - { 153838, true }, - { 153851, true }, - { 153874, true }, - { 153887, true }, - { 153900, true }, - { 153920, true }, - { 153931, true }, - { 153945, true }, - { 153954, true }, - { 153963, true }, - { 153981, true }, - { 153995, true }, - { 154011, true }, - { 154023, true }, - { 154037, true }, - { 154062, true }, - { 154078, true }, - { 154095, true }, - { 154110, true }, - { 154120, true }, - { 154144, true }, + { 153482, true }, + { 153497, true }, + { 153513, true }, + { 153530, true }, + { 153542, true }, + { 153556, true }, + { 153570, true }, + { 153594, true }, + { 153609, true }, + { 153625, true }, + { 153640, true }, + { 153653, true }, + { 153676, true }, + { 153689, true }, + { 153702, true }, + { 153722, true }, + { 153733, true }, + { 153747, true }, + { 153756, true }, + { 153765, true }, + { 153783, true }, + { 153797, true }, + { 153813, true }, + { 153825, true }, + { 153839, true }, + { 153864, true }, + { 153880, true }, + { 153897, true }, + { 153912, true }, + { 153922, true }, + { 153946, true }, + { 153958, true }, + { 153971, true }, + { 153985, true }, + { 154014, true }, + { 154039, true }, + { 154064, true }, + { 154093, true }, + { 154105, true }, + { 154121, true }, + { 154130, true }, + { 154142, true }, { 154156, true }, - { 154169, true }, - { 154183, true }, - { 154212, true }, - { 154237, true }, - { 154262, true }, - { 154291, true }, - { 154303, true }, - { 154319, true }, - { 154328, true }, + { 154170, true }, + { 154184, true }, + { 154197, true }, + { 154216, true }, + { 154229, true }, + { 154246, true }, + { 154255, true }, + { 154273, true }, + { 154287, false }, + { 154298, false }, + { 154311, true }, + { 154321, true }, { 154340, true }, - { 154354, true }, - { 154368, true }, - { 154382, true }, + { 154362, true }, + { 154373, true }, + { 154384, true }, { 154395, true }, + { 154405, true }, { 154414, true }, - { 154427, true }, - { 154444, true }, + { 154422, false }, + { 154428, false }, + { 154436, true }, + { 154445, true }, { 154453, true }, - { 154471, true }, - { 154485, false }, - { 154496, false }, - { 154509, true }, - { 154519, true }, - { 154538, true }, - { 154560, true }, - { 154571, true }, - { 154582, true }, - { 154593, true }, - { 154603, true }, - { 154612, true }, - { 154620, false }, - { 154626, false }, - { 154634, true }, - { 154643, true }, - { 154651, true }, - { 154661, true }, - { 154680, true }, - { 154705, true }, - { 154712, true }, - { 154725, true }, - { 154739, true }, - { 154749, true }, - { 154759, true }, + { 154463, true }, + { 154482, true }, + { 154507, true }, + { 154514, true }, + { 154527, true }, + { 154541, true }, + { 154551, true }, + { 154561, true }, + { 154580, true }, + { 154592, true }, + { 154607, true }, + { 154619, true }, + { 154632, true }, + { 154645, true }, + { 154657, true }, + { 154676, true }, + { 154687, false }, + { 154698, true }, + { 154713, true }, + { 154729, true }, + { 154751, true }, + { 154765, true }, { 154778, true }, - { 154790, true }, - { 154805, true }, - { 154817, true }, - { 154830, true }, - { 154843, true }, - { 154855, true }, - { 154874, true }, - { 154885, false }, - { 154896, true }, - { 154911, true }, - { 154927, true }, + { 154791, true }, + { 154810, true }, + { 154826, true }, + { 154839, true }, + { 154859, false }, + { 154886, false }, + { 154902, true }, + { 154918, true }, + { 154933, true }, { 154949, true }, - { 154963, true }, - { 154976, true }, - { 154989, true }, - { 155008, true }, - { 155024, true }, - { 155037, true }, - { 155057, false }, - { 155084, false }, - { 155100, true }, - { 155116, true }, - { 155131, true }, - { 155147, true }, - { 155165, true }, - { 155184, true }, - { 155194, true }, + { 154967, true }, + { 154986, true }, + { 154996, true }, + { 155005, true }, + { 155018, true }, + { 155035, true }, + { 155054, true }, + { 155067, true }, + { 155083, true }, + { 155096, true }, + { 155115, true }, + { 155132, true }, + { 155150, true }, + { 155167, true }, + { 155185, true }, { 155203, true }, { 155216, true }, - { 155233, true }, - { 155252, true }, - { 155265, true }, - { 155281, true }, - { 155294, true }, - { 155313, true }, + { 155232, true }, + { 155253, true }, + { 155263, true }, + { 155284, true }, + { 155293, true }, + { 155304, true }, + { 155317, false }, { 155330, true }, - { 155348, true }, - { 155365, true }, - { 155383, true }, - { 155401, true }, - { 155414, true }, - { 155430, true }, - { 155451, true }, - { 155461, true }, - { 155482, true }, - { 155491, true }, - { 155502, true }, - { 155515, false }, - { 155528, true }, - { 155541, true }, - { 155557, true }, - { 155571, false }, - { 155586, true }, - { 155600, true }, - { 155615, true }, - { 155632, true }, - { 155648, true }, - { 155667, true }, - { 155683, true }, - { 155696, true }, - { 155705, true }, - { 155715, true }, - { 155724, true }, - { 155751, false }, - { 155768, true }, - { 155786, true }, - { 155810, true }, - { 155834, true }, - { 155848, true }, - { 155859, true }, - { 155887, true }, - { 155901, true }, - { 155910, true }, - { 155920, true }, - { 155940, true }, - { 155954, true }, - { 155967, true }, - { 155987, true }, - { 156005, true }, - { 156017, true }, - { 156032, true }, - { 156047, true }, - { 156063, true }, - { 156078, false }, - { 156095, true }, - { 156107, false }, - { 156130, true }, - { 156147, true }, - { 156160, true }, - { 156183, true }, - { 156201, true }, - { 156222, true }, - { 156244, true }, - { 156265, true }, - { 156286, true }, - { 156296, false }, - { 156310, true }, - { 156327, true }, - { 156344, true }, - { 156354, true }, - { 156367, true }, - { 156382, true }, - { 156400, true }, - { 156417, true }, - { 156433, true }, - { 156470, true }, - { 156489, true }, - { 156504, true }, - { 156519, false }, + { 155343, true }, + { 155359, true }, + { 155373, false }, + { 155388, true }, + { 155402, true }, + { 155417, true }, + { 155434, true }, + { 155450, true }, + { 155469, true }, + { 155485, true }, + { 155498, true }, + { 155507, true }, + { 155517, true }, + { 155526, true }, + { 155553, false }, + { 155570, true }, + { 155588, true }, + { 155612, true }, + { 155636, true }, + { 155650, true }, + { 155678, true }, + { 155692, true }, + { 155701, true }, + { 155711, true }, + { 155731, true }, + { 155745, true }, + { 155758, true }, + { 155778, true }, + { 155796, true }, + { 155808, true }, + { 155823, true }, + { 155838, true }, + { 155854, true }, + { 155869, false }, + { 155886, true }, + { 155898, false }, + { 155921, true }, + { 155938, true }, + { 155951, true }, + { 155974, true }, + { 155992, true }, + { 156013, true }, + { 156035, true }, + { 156056, true }, + { 156077, true }, + { 156087, false }, + { 156101, true }, + { 156118, true }, + { 156135, true }, + { 156145, true }, + { 156158, true }, + { 156173, true }, + { 156191, true }, + { 156208, true }, + { 156224, true }, + { 156261, true }, + { 156280, true }, + { 156295, true }, + { 156310, false }, + { 156322, true }, + { 156339, true }, + { 156356, false }, + { 156371, true }, + { 156392, false }, + { 156404, false }, + { 156421, true }, + { 156438, true }, + { 156455, true }, + { 156468, true }, + { 156484, true }, + { 156500, true }, + { 156513, true }, { 156531, true }, - { 156548, true }, - { 156565, false }, - { 156580, true }, - { 156601, false }, - { 156613, false }, - { 156630, true }, - { 156647, true }, + { 156541, false }, + { 156555, true }, + { 156566, true }, + { 156582, true }, + { 156592, true }, + { 156611, true }, + { 156624, true }, + { 156638, true }, + { 156653, true }, { 156664, true }, - { 156677, true }, - { 156693, true }, - { 156709, true }, + { 156684, true }, + { 156697, true }, + { 156710, true }, { 156722, true }, - { 156740, true }, - { 156750, false }, - { 156764, true }, - { 156775, true }, - { 156791, true }, - { 156801, true }, - { 156820, true }, - { 156833, true }, - { 156847, true }, - { 156862, true }, - { 156873, true }, - { 156893, true }, - { 156906, true }, - { 156919, true }, - { 156931, true }, - { 156950, true }, - { 156963, true }, - { 156974, true }, - { 156985, true }, - { 157005, true }, - { 157015, true }, - { 157025, true }, - { 157047, true }, - { 157067, true }, - { 157080, true }, - { 157089, true }, - { 157100, true }, - { 157116, true }, - { 157132, true }, - { 157154, true }, - { 157170, true }, - { 157186, true }, - { 157210, true }, - { 157225, true }, + { 156741, true }, + { 156754, true }, + { 156765, true }, + { 156776, true }, + { 156796, true }, + { 156806, true }, + { 156816, true }, + { 156838, true }, + { 156858, true }, + { 156871, true }, + { 156880, true }, + { 156891, true }, + { 156907, true }, + { 156923, true }, + { 156945, true }, + { 156961, true }, + { 156977, true }, + { 157001, true }, + { 157016, true }, + { 157029, true }, + { 157048, true }, + { 157058, true }, + { 157072, true }, + { 157083, true }, + { 157101, true }, + { 157118, true }, + { 157130, true }, + { 157143, true }, + { 157160, true }, + { 157172, true }, + { 157189, true }, + { 157198, true }, + { 157218, false }, { 157238, true }, - { 157257, true }, - { 157267, true }, - { 157281, true }, - { 157292, true }, - { 157310, true }, - { 157327, true }, - { 157339, true }, - { 157352, true }, - { 157369, true }, + { 157255, true }, + { 157265, true }, + { 157282, true }, + { 157294, true }, + { 157311, true }, + { 157330, true }, + { 157347, true }, + { 157364, true }, { 157381, true }, - { 157398, true }, - { 157407, true }, - { 157427, false }, - { 157447, true }, - { 157464, true }, - { 157474, true }, - { 157491, true }, - { 157503, true }, + { 157392, true }, + { 157404, true }, + { 157416, true }, + { 157426, true }, + { 157435, true }, + { 157448, true }, + { 157463, true }, + { 157473, true }, + { 157485, true }, + { 157499, false }, + { 157508, true }, { 157520, true }, - { 157539, true }, - { 157556, true }, - { 157573, true }, - { 157590, true }, - { 157601, true }, - { 157613, true }, - { 157625, true }, - { 157635, true }, - { 157644, true }, - { 157657, true }, - { 157667, true }, + { 157531, true }, + { 157544, true }, + { 157554, true }, + { 157565, true }, + { 157574, true }, + { 157586, false }, + { 157599, true }, + { 157610, true }, + { 157624, false }, + { 157635, false }, + { 157646, true }, + { 157656, true }, { 157679, true }, - { 157693, false }, - { 157702, true }, + { 157689, true }, + { 157701, true }, { 157714, true }, - { 157725, true }, - { 157738, true }, - { 157748, true }, + { 157722, true }, + { 157737, true }, + { 157746, true }, { 157758, true }, - { 157769, true }, - { 157778, true }, - { 157790, false }, - { 157803, true }, - { 157814, true }, - { 157828, false }, - { 157839, false }, - { 157850, true }, - { 157860, true }, - { 157883, true }, - { 157893, true }, - { 157905, true }, - { 157918, true }, - { 157926, true }, + { 157773, true }, + { 157782, true }, + { 157801, true }, + { 157816, true }, + { 157838, true }, + { 157854, true }, + { 157870, true }, + { 157884, true }, + { 157897, true }, + { 157908, true }, + { 157916, true }, + { 157930, true }, { 157941, true }, - { 157953, true }, - { 157968, true }, - { 157977, true }, - { 157996, true }, - { 158011, true }, + { 157958, true }, + { 157971, true }, + { 157984, true }, + { 158000, true }, + { 158017, true }, { 158033, true }, - { 158049, true }, - { 158065, true }, - { 158079, true }, - { 158092, true }, - { 158103, true }, + { 158046, true }, + { 158060, true }, + { 158087, true }, { 158111, true }, - { 158125, true }, - { 158136, true }, - { 158153, true }, - { 158166, true }, - { 158179, true }, - { 158195, true }, - { 158212, true }, - { 158228, true }, + { 158134, true }, + { 158156, true }, + { 158169, false }, + { 158182, true }, + { 158196, true }, + { 158210, false }, + { 158231, true }, { 158241, true }, - { 158255, true }, - { 158282, true }, + { 158253, true }, + { 158279, true }, + { 158292, true }, { 158306, true }, - { 158329, true }, - { 158351, true }, - { 158364, false }, - { 158377, true }, - { 158391, true }, - { 158405, false }, - { 158426, true }, + { 158325, true }, + { 158342, true }, + { 158360, true }, + { 158381, true }, + { 158395, true }, + { 158417, true }, { 158436, true }, { 158448, true }, - { 158474, true }, - { 158487, true }, - { 158501, true }, - { 158520, true }, - { 158537, true }, - { 158555, true }, - { 158576, true }, - { 158590, true }, - { 158612, true }, - { 158631, true }, - { 158643, true }, - { 158655, true }, - { 158679, true }, - { 158689, true }, - { 158702, true }, - { 158721, true }, - { 158736, true }, - { 158753, true }, - { 158769, true }, - { 158787, true }, - { 158804, true }, - { 158819, true }, - { 158835, true }, - { 158862, true }, - { 158876, true }, - { 158892, true }, - { 158907, true }, - { 158920, true }, - { 158929, true }, - { 158945, true }, - { 158960, true }, - { 158971, true }, - { 158983, true }, - { 159000, true }, - { 159011, true }, - { 159022, true }, - { 159045, true }, - { 159055, true }, + { 158460, true }, + { 158484, true }, + { 158494, true }, + { 158507, true }, + { 158526, true }, + { 158541, true }, + { 158558, true }, + { 158574, true }, + { 158592, true }, + { 158609, true }, + { 158624, true }, + { 158640, true }, + { 158667, true }, + { 158681, true }, + { 158697, true }, + { 158712, true }, + { 158725, true }, + { 158734, true }, + { 158750, true }, + { 158765, true }, + { 158776, true }, + { 158788, true }, + { 158805, true }, + { 158816, true }, + { 158827, true }, + { 158850, true }, + { 158860, true }, + { 158874, true }, + { 158883, true }, + { 158890, true }, + { 158904, false }, + { 158924, true }, + { 158935, true }, + { 158949, true }, + { 158962, true }, + { 158976, true }, + { 158984, true }, + { 158995, true }, + { 159013, true }, + { 159023, true }, + { 159033, true }, + { 159044, true }, { 159069, true }, - { 159078, true }, - { 159085, true }, - { 159099, false }, - { 159119, true }, - { 159130, true }, - { 159144, true }, - { 159157, true }, - { 159171, true }, - { 159179, true }, - { 159190, true }, - { 159208, true }, - { 159218, true }, - { 159228, true }, - { 159239, true }, - { 159264, true }, - { 159278, true }, - { 159289, true }, + { 159083, true }, + { 159094, true }, + { 159105, true }, + { 159120, true }, + { 159136, false }, + { 159147, true }, + { 159162, false }, + { 159181, true }, + { 159192, true }, + { 159202, true }, + { 159222, true }, + { 159236, true }, + { 159250, true }, + { 159261, true }, + { 159268, true }, + { 159281, false }, + { 159291, true }, { 159300, true }, - { 159315, false }, - { 159326, true }, - { 159341, false }, - { 159360, true }, - { 159371, true }, - { 159381, true }, - { 159401, true }, + { 159310, true }, + { 159321, true }, + { 159333, true }, + { 159341, true }, + { 159351, true }, + { 159368, true }, + { 159385, true }, + { 159404, true }, { 159415, true }, - { 159429, true }, - { 159440, true }, - { 159447, true }, - { 159460, false }, - { 159470, true }, + { 159434, false }, + { 159445, true }, + { 159462, true }, { 159479, true }, - { 159489, true }, - { 159500, true }, - { 159512, true }, - { 159520, true }, + { 159492, true }, + { 159508, true }, + { 159519, true }, { 159530, true }, { 159547, true }, - { 159564, true }, - { 159583, true }, - { 159594, true }, - { 159613, false }, - { 159624, true }, - { 159641, true }, - { 159658, true }, + { 159556, false }, + { 159564, false }, + { 159577, true }, + { 159588, true }, + { 159595, true }, + { 159609, true }, + { 159623, true }, + { 159643, false }, + { 159655, true }, { 159671, true }, - { 159687, true }, - { 159698, true }, - { 159709, true }, + { 159683, true }, + { 159702, true }, { 159726, true }, - { 159735, false }, - { 159743, false }, - { 159756, true }, - { 159767, true }, - { 159774, true }, - { 159788, true }, - { 159802, true }, - { 159822, false }, - { 159834, true }, - { 159850, true }, - { 159862, true }, - { 159881, true }, + { 159743, true }, + { 159759, true }, + { 159775, true }, + { 159784, true }, + { 159796, true }, + { 159809, true }, + { 159823, true }, + { 159839, false }, + { 159854, true }, + { 159863, true }, + { 159883, true }, + { 159891, true }, { 159905, true }, - { 159922, true }, - { 159938, true }, - { 159954, true }, - { 159963, true }, - { 159975, true }, - { 159988, true }, - { 160002, true }, - { 160018, false }, - { 160033, true }, - { 160042, true }, - { 160062, true }, - { 160070, true }, - { 160084, true }, - { 160095, true }, - { 160105, false }, - { 160115, true }, - { 160129, true }, - { 160141, true }, - { 160151, false }, - { 160164, true }, - { 160180, true }, - { 160202, true }, - { 160219, true }, - { 160228, true }, - { 160237, true }, - { 160252, true }, - { 160266, true }, - { 160276, true }, + { 159916, true }, + { 159926, false }, + { 159936, true }, + { 159950, true }, + { 159962, true }, + { 159972, false }, + { 159985, true }, + { 160001, true }, + { 160023, true }, + { 160040, true }, + { 160049, true }, + { 160058, true }, + { 160073, true }, + { 160087, true }, + { 160097, true }, + { 160107, true }, + { 160125, true }, + { 160146, true }, + { 160161, true }, + { 160175, true }, + { 160195, true }, + { 160211, true }, + { 160223, false }, + { 160239, true }, + { 160254, true }, + { 160269, true }, { 160286, true }, - { 160304, true }, - { 160325, true }, - { 160340, true }, - { 160354, true }, + { 160299, false }, + { 160318, false }, + { 160330, true }, + { 160346, true }, { 160374, true }, - { 160390, true }, - { 160402, false }, - { 160418, true }, + { 160406, true }, + { 160421, true }, { 160433, true }, - { 160448, true }, - { 160465, true }, - { 160478, false }, - { 160497, false }, - { 160509, true }, - { 160525, true }, - { 160553, true }, - { 160585, true }, - { 160600, true }, - { 160612, true }, - { 160626, false }, - { 160639, true }, - { 160657, true }, - { 160665, true }, + { 160447, false }, + { 160460, true }, + { 160478, true }, + { 160486, true }, + { 160500, true }, + { 160514, true }, + { 160526, true }, + { 160547, true }, + { 160562, true }, + { 160577, true }, + { 160593, false }, + { 160601, false }, + { 160613, true }, + { 160622, true }, + { 160632, true }, + { 160643, true }, + { 160655, true }, + { 160668, true }, { 160679, true }, - { 160693, true }, + { 160695, true }, { 160705, true }, - { 160726, true }, - { 160741, true }, - { 160756, true }, - { 160772, false }, - { 160780, false }, - { 160792, true }, - { 160801, true }, - { 160811, true }, - { 160822, true }, - { 160834, true }, - { 160847, true }, - { 160858, true }, - { 160874, true }, - { 160884, true }, - { 160895, true }, - { 160906, true }, - { 160918, true }, - { 160928, true }, - { 160937, true }, - { 160956, true }, - { 160984, true }, - { 161000, true }, - { 161015, true }, - { 161028, true }, - { 161044, false }, - { 161057, true }, - { 161071, true }, + { 160716, true }, + { 160727, true }, + { 160739, true }, + { 160749, true }, + { 160758, true }, + { 160777, true }, + { 160805, true }, + { 160821, true }, + { 160836, true }, + { 160849, true }, + { 160865, false }, + { 160878, true }, + { 160892, true }, + { 160904, true }, + { 160919, true }, + { 160939, true }, + { 160958, true }, + { 160977, true }, + { 160990, true }, + { 161006, true }, + { 161019, true }, + { 161034, true }, + { 161050, true }, + { 161067, true }, { 161083, true }, - { 161098, true }, - { 161118, true }, - { 161137, true }, - { 161156, true }, - { 161169, true }, - { 161185, true }, - { 161198, true }, - { 161213, true }, - { 161229, true }, - { 161246, true }, - { 161262, true }, - { 161279, true }, - { 161292, true }, - { 161307, true }, - { 161326, true }, - { 161339, true }, - { 161355, true }, - { 161367, true }, - { 161378, true }, - { 161391, true }, - { 161405, true }, - { 161419, true }, - { 161433, false }, - { 161449, true }, - { 161468, true }, + { 161100, true }, + { 161113, true }, + { 161128, true }, + { 161147, true }, + { 161160, true }, + { 161176, true }, + { 161188, true }, + { 161199, true }, + { 161212, true }, + { 161226, true }, + { 161240, true }, + { 161254, false }, + { 161270, true }, + { 161289, true }, + { 161309, true }, + { 161329, false }, + { 161345, true }, + { 161361, true }, + { 161377, true }, + { 161392, true }, + { 161407, true }, + { 161428, false }, + { 161447, true }, + { 161458, true }, + { 161474, true }, { 161488, true }, - { 161508, false }, - { 161524, true }, - { 161540, true }, - { 161556, true }, + { 161501, true }, + { 161514, true }, + { 161530, true }, + { 161541, true }, + { 161550, true }, + { 161560, true }, { 161571, true }, - { 161586, true }, - { 161607, false }, + { 161585, true }, + { 161594, true }, + { 161607, true }, { 161626, true }, - { 161637, true }, - { 161653, true }, - { 161667, true }, - { 161680, true }, - { 161693, true }, - { 161709, true }, - { 161720, true }, - { 161729, true }, - { 161739, true }, - { 161750, true }, + { 161643, false }, + { 161658, false }, + { 161670, true }, + { 161690, true }, + { 161703, true }, + { 161723, true }, + { 161746, true }, { 161764, true }, - { 161773, true }, - { 161786, true }, - { 161805, true }, - { 161822, false }, - { 161837, true }, - { 161853, false }, - { 161865, true }, - { 161885, true }, - { 161898, true }, + { 161780, true }, + { 161793, true }, + { 161807, true }, + { 161821, true }, + { 161829, true }, + { 161847, true }, + { 161857, true }, + { 161877, true }, + { 161894, true }, + { 161905, true }, { 161918, true }, - { 161941, true }, + { 161930, true }, + { 161946, true }, { 161959, true }, - { 161975, true }, - { 161988, true }, - { 162002, true }, - { 162016, true }, - { 162024, true }, - { 162042, true }, - { 162052, true }, - { 162072, true }, - { 162089, true }, - { 162100, true }, - { 162113, true }, - { 162125, true }, - { 162141, true }, - { 162154, true }, - { 162171, true }, - { 162192, true }, - { 162200, true }, - { 162210, true }, - { 162233, true }, - { 162242, true }, - { 162252, true }, - { 162264, true }, - { 162277, true }, - { 162287, true }, - { 162300, true }, - { 162321, true }, - { 162331, true }, - { 162345, true }, - { 162365, true }, - { 162378, true }, - { 162398, false }, - { 162421, true }, - { 162434, true }, - { 162445, true }, - { 162456, true }, - { 162466, true }, + { 161976, true }, + { 161997, true }, + { 162005, true }, + { 162015, true }, + { 162038, true }, + { 162047, true }, + { 162057, true }, + { 162069, true }, + { 162082, true }, + { 162092, true }, + { 162105, true }, + { 162126, true }, + { 162136, true }, + { 162150, true }, + { 162170, true }, + { 162183, true }, + { 162203, false }, + { 162226, true }, + { 162239, true }, + { 162250, true }, + { 162261, true }, + { 162271, true }, + { 162296, true }, + { 162306, true }, + { 162320, true }, + { 162334, false }, + { 162349, true }, + { 162363, true }, + { 162388, true }, + { 162402, true }, + { 162414, true }, + { 162428, true }, + { 162438, false }, + { 162458, true }, + { 162472, true }, { 162491, true }, - { 162501, true }, - { 162515, true }, - { 162529, false }, - { 162544, true }, - { 162558, true }, - { 162583, true }, - { 162597, true }, - { 162609, true }, - { 162623, true }, - { 162633, false }, - { 162653, true }, - { 162667, true }, - { 162686, true }, - { 162701, true }, - { 162714, true }, - { 162729, true }, - { 162739, true }, - { 162753, true }, - { 162762, true }, - { 162777, true }, - { 162788, true }, - { 162799, true }, - { 162810, true }, - { 162820, true }, - { 162829, false }, - { 162849, true }, - { 162864, true }, - { 162876, true }, - { 162888, true }, - { 162907, true }, - { 162927, true }, - { 162944, true }, - { 162954, true }, - { 162968, true }, - { 162985, true }, - { 163000, true }, - { 163008, true }, - { 163026, true }, - { 163047, false }, - { 163065, true }, - { 163077, true }, - { 163093, true }, - { 163108, true }, - { 163124, true }, - { 163135, true }, - { 163160, true }, - { 163182, true }, - { 163196, true }, - { 163217, true }, - { 163231, true }, - { 163248, true }, - { 163267, true }, + { 162504, true }, + { 162519, true }, + { 162529, true }, + { 162543, true }, + { 162552, true }, + { 162567, true }, + { 162578, true }, + { 162589, true }, + { 162600, true }, + { 162610, true }, + { 162619, false }, + { 162639, true }, + { 162654, true }, + { 162666, true }, + { 162678, true }, + { 162697, true }, + { 162717, true }, + { 162734, true }, + { 162744, true }, + { 162758, true }, + { 162775, true }, + { 162790, true }, + { 162798, true }, + { 162816, true }, + { 162837, false }, + { 162855, true }, + { 162867, true }, + { 162883, true }, + { 162898, true }, + { 162914, true }, + { 162925, true }, + { 162950, true }, + { 162972, true }, + { 162986, true }, + { 163007, true }, + { 163021, true }, + { 163038, true }, + { 163057, true }, + { 163076, true }, + { 163101, true }, + { 163114, true }, + { 163130, true }, + { 163156, true }, + { 163177, true }, + { 163195, true }, + { 163219, true }, + { 163235, true }, + { 163260, true }, { 163286, true }, - { 163311, true }, - { 163324, true }, - { 163340, true }, + { 163297, true }, + { 163323, true }, + { 163345, true }, { 163366, true }, - { 163387, true }, - { 163405, true }, + { 163383, true }, + { 163401, true }, + { 163411, false }, { 163429, true }, - { 163445, true }, - { 163470, true }, - { 163496, true }, - { 163507, true }, - { 163533, true }, - { 163555, true }, - { 163576, true }, - { 163593, true }, - { 163611, true }, - { 163621, false }, - { 163639, true }, - { 163654, false }, - { 163673, true }, + { 163444, false }, + { 163463, true }, + { 163485, true }, + { 163508, true }, + { 163527, true }, + { 163545, true }, + { 163568, true }, + { 163581, true }, + { 163597, true }, + { 163615, true }, + { 163631, true }, + { 163645, true }, + { 163663, true }, + { 163678, true }, { 163695, true }, - { 163718, true }, - { 163737, true }, - { 163755, true }, - { 163778, true }, - { 163791, true }, - { 163807, true }, - { 163825, true }, + { 163709, true }, + { 163723, false }, + { 163740, true }, + { 163758, true }, + { 163774, true }, + { 163790, true }, + { 163803, true }, + { 163823, true }, { 163841, true }, - { 163855, true }, + { 163860, true }, { 163873, true }, - { 163888, true }, - { 163905, true }, - { 163919, true }, - { 163933, false }, - { 163950, true }, + { 163896, true }, + { 163911, true }, + { 163927, true }, + { 163938, true }, { 163968, true }, { 163984, true }, - { 164000, true }, - { 164013, true }, - { 164033, true }, - { 164051, true }, - { 164070, true }, - { 164083, true }, - { 164106, true }, - { 164121, true }, - { 164137, true }, - { 164148, true }, - { 164178, true }, - { 164194, true }, - { 164209, true }, - { 164224, true }, - { 164235, true }, - { 164249, true }, - { 164271, true }, - { 164286, true }, - { 164309, true }, - { 164318, true }, - { 164340, true }, - { 164359, true }, - { 164383, true }, - { 164394, true }, - { 164411, true }, - { 164425, true }, - { 164438, true }, - { 164454, true }, - { 164473, true }, - { 164490, true }, - { 164501, true }, - { 164516, true }, - { 164535, true }, - { 164555, true }, - { 164572, false }, - { 164587, true }, - { 164605, true }, - { 164627, true }, + { 163999, true }, + { 164014, true }, + { 164025, true }, + { 164039, true }, + { 164061, true }, + { 164076, true }, + { 164099, true }, + { 164108, true }, + { 164130, true }, + { 164149, true }, + { 164173, true }, + { 164184, true }, + { 164201, true }, + { 164215, true }, + { 164228, true }, + { 164244, true }, + { 164263, true }, + { 164280, true }, + { 164291, true }, + { 164306, true }, + { 164325, true }, + { 164345, true }, + { 164362, false }, + { 164377, true }, + { 164395, true }, + { 164417, true }, + { 164433, true }, + { 164445, true }, + { 164457, true }, + { 164469, true }, + { 164485, true }, + { 164504, true }, + { 164520, true }, + { 164539, false }, + { 164553, true }, + { 164570, true }, + { 164591, true }, + { 164611, true }, + { 164625, true }, { 164643, true }, - { 164655, true }, - { 164667, true }, - { 164679, true }, - { 164695, true }, - { 164714, true }, - { 164730, true }, - { 164749, false }, - { 164763, true }, - { 164780, true }, - { 164801, true }, - { 164821, true }, - { 164835, true }, - { 164853, true }, - { 164869, true }, - { 164879, true }, - { 164890, true }, - { 164902, true }, - { 164921, true }, - { 164935, true }, - { 164948, true }, - { 164964, true }, - { 164975, true }, - { 164996, true }, + { 164659, true }, + { 164669, true }, + { 164680, true }, + { 164692, true }, + { 164711, true }, + { 164725, true }, + { 164738, true }, + { 164754, true }, + { 164765, true }, + { 164786, true }, + { 164814, true }, + { 164830, true }, + { 164843, true }, + { 164866, true }, + { 164884, true }, + { 164899, true }, + { 164924, false }, + { 164940, true }, + { 164949, true }, + { 164959, true }, + { 164971, true }, + { 164990, true }, + { 165007, true }, { 165024, true }, - { 165040, true }, - { 165053, true }, - { 165076, true }, - { 165094, true }, - { 165109, true }, - { 165134, false }, - { 165150, true }, - { 165159, true }, - { 165169, true }, - { 165181, true }, - { 165200, true }, - { 165217, true }, - { 165234, true }, - { 165250, false }, - { 165268, false }, - { 165288, true }, - { 165305, true }, - { 165318, true }, - { 165338, true }, - { 165362, true }, + { 165040, false }, + { 165058, false }, + { 165078, true }, + { 165095, true }, + { 165108, true }, + { 165128, true }, + { 165152, true }, + { 165170, true }, + { 165191, true }, + { 165206, true }, + { 165221, true }, + { 165233, true }, + { 165258, true }, + { 165271, true }, + { 165293, true }, + { 165303, true }, + { 165320, true }, + { 165333, true }, + { 165347, true }, { 165380, true }, - { 165401, true }, - { 165416, true }, - { 165431, true }, - { 165443, true }, - { 165468, true }, - { 165481, true }, - { 165503, true }, - { 165513, true }, - { 165530, true }, - { 165543, true }, - { 165557, true }, - { 165590, true }, - { 165605, true }, - { 165619, true }, - { 165628, true }, - { 165637, true }, - { 165647, true }, - { 165658, false }, - { 165672, true }, - { 165681, true }, - { 165692, true }, - { 165703, true }, - { 165721, true }, - { 165734, true }, - { 165749, true }, - { 165762, true }, - { 165781, true }, - { 165801, true }, - { 165818, true }, - { 165825, true }, - { 165836, true }, - { 165852, true }, - { 165870, true }, - { 165891, true }, - { 165903, true }, - { 165933, true }, - { 165946, true }, - { 165956, true }, - { 165968, true }, - { 165982, true }, - { 165996, true }, - { 166009, true }, - { 166020, true }, - { 166034, true }, - { 166053, true }, - { 166072, true }, - { 166087, true }, - { 166099, true }, - { 166110, true }, - { 166125, true }, - { 166137, true }, - { 166153, true }, - { 166169, true }, - { 166178, true }, - { 166192, true }, - { 166203, false }, - { 166218, true }, - { 166232, true }, - { 166248, true }, - { 166261, true }, - { 166281, true }, - { 166294, false }, - { 166314, true }, - { 166328, true }, - { 166339, true }, - { 166356, true }, - { 166370, true }, - { 166382, true }, - { 166396, true }, - { 166408, true }, - { 166420, true }, - { 166432, true }, - { 166442, true }, - { 166455, true }, - { 166472, true }, - { 166499, true }, - { 166512, true }, - { 166520, true }, - { 166532, true }, - { 166546, true }, + { 165395, true }, + { 165409, true }, + { 165418, true }, + { 165427, true }, + { 165437, true }, + { 165448, false }, + { 165462, true }, + { 165471, true }, + { 165482, true }, + { 165493, true }, + { 165511, true }, + { 165524, true }, + { 165539, true }, + { 165552, true }, + { 165571, true }, + { 165591, true }, + { 165608, true }, + { 165615, true }, + { 165631, true }, + { 165649, true }, + { 165670, true }, + { 165682, true }, + { 165712, true }, + { 165725, true }, + { 165735, true }, + { 165747, true }, + { 165761, true }, + { 165775, true }, + { 165788, true }, + { 165799, true }, + { 165813, true }, + { 165832, true }, + { 165851, true }, + { 165866, true }, + { 165878, true }, + { 165889, true }, + { 165904, true }, + { 165916, true }, + { 165932, true }, + { 165948, true }, + { 165957, true }, + { 165971, true }, + { 165982, false }, + { 165997, true }, + { 166011, true }, + { 166027, true }, + { 166040, true }, + { 166060, true }, + { 166073, false }, + { 166093, true }, + { 166107, true }, + { 166118, true }, + { 166135, true }, + { 166149, true }, + { 166161, true }, + { 166175, true }, + { 166187, true }, + { 166199, true }, + { 166211, true }, + { 166221, true }, + { 166234, true }, + { 166251, true }, + { 166278, true }, + { 166291, true }, + { 166299, true }, + { 166311, true }, + { 166325, true }, + { 166338, true }, + { 166365, false }, + { 166376, true }, + { 166394, true }, + { 166401, true }, + { 166409, true }, + { 166418, true }, + { 166427, true }, + { 166435, true }, + { 166448, true }, + { 166457, true }, + { 166469, true }, + { 166481, true }, + { 166488, true }, + { 166504, true }, + { 166521, true }, + { 166528, true }, + { 166542, true }, { 166559, true }, - { 166586, false }, - { 166597, true }, + { 166571, true }, + { 166579, true }, + { 166586, true }, + { 166595, true }, { 166615, true }, - { 166623, true }, - { 166632, true }, - { 166641, true }, - { 166649, true }, - { 166662, true }, - { 166671, true }, - { 166683, true }, - { 166695, true }, - { 166702, true }, - { 166718, true }, - { 166735, true }, - { 166742, true }, - { 166756, true }, + { 166631, true }, + { 166647, true }, + { 166666, true }, + { 166684, true }, + { 166699, true }, + { 166717, true }, + { 166727, true }, + { 166739, true }, + { 166758, true }, { 166773, true }, - { 166785, true }, - { 166793, true }, + { 166788, true }, { 166800, true }, - { 166809, true }, - { 166829, true }, - { 166845, true }, - { 166861, true }, - { 166880, true }, - { 166898, true }, - { 166913, true }, - { 166931, true }, - { 166941, true }, - { 166953, true }, - { 166972, true }, + { 166808, false }, + { 166833, true }, + { 166843, true }, + { 166858, true }, + { 166870, true }, + { 166884, true }, + { 166893, false }, + { 166905, true }, + { 166918, true }, + { 166951, true }, + { 166974, true }, { 166987, true }, - { 167002, true }, - { 167014, true }, - { 167022, false }, - { 167047, true }, - { 167057, true }, - { 167072, true }, - { 167084, true }, - { 167098, true }, - { 167107, false }, - { 167119, true }, - { 167132, true }, - { 167165, true }, - { 167188, true }, - { 167201, true }, - { 167212, true }, - { 167226, true }, - { 167246, true }, - { 167259, true }, - { 167269, true }, - { 167287, true }, - { 167301, true }, - { 167313, true }, - { 167328, true }, + { 166998, true }, + { 167012, true }, + { 167032, true }, + { 167045, true }, + { 167055, true }, + { 167073, true }, + { 167087, true }, + { 167099, true }, + { 167114, true }, + { 167136, true }, + { 167146, true }, + { 167158, true }, + { 167174, true }, + { 167186, true }, + { 167196, true }, + { 167209, true }, + { 167218, true }, + { 167231, false }, + { 167239, true }, + { 167250, true }, + { 167266, true }, + { 167277, true }, + { 167290, true }, + { 167302, false }, + { 167316, true }, + { 167329, true }, + { 167340, true }, { 167350, true }, - { 167360, true }, - { 167372, true }, - { 167388, true }, - { 167400, true }, - { 167410, true }, - { 167423, true }, - { 167436, false }, - { 167444, true }, - { 167455, false }, - { 167471, true }, - { 167482, true }, - { 167495, true }, - { 167507, false }, - { 167521, true }, - { 167534, true }, - { 167545, true }, - { 167555, true }, - { 167569, true }, - { 167588, true }, - { 167599, true }, - { 167613, true }, - { 167624, true }, - { 167635, true }, - { 167646, true }, - { 167657, true }, - { 167668, true }, - { 167682, true }, - { 167694, true }, - { 167709, true }, - { 167723, true }, - { 167738, true }, - { 167751, true }, - { 167767, true }, - { 167776, true }, - { 167785, true }, - { 167799, true }, - { 167810, true }, - { 167821, false }, - { 167837, true }, - { 167848, true }, - { 167859, true }, + { 167364, true }, + { 167383, true }, + { 167394, true }, + { 167408, true }, + { 167419, true }, + { 167430, true }, + { 167441, true }, + { 167452, true }, + { 167463, true }, + { 167477, true }, + { 167489, true }, + { 167504, true }, + { 167518, true }, + { 167533, true }, + { 167546, true }, + { 167562, true }, + { 167571, true }, + { 167580, true }, + { 167594, true }, + { 167605, true }, + { 167616, false }, + { 167632, true }, + { 167643, true }, + { 167654, true }, + { 167670, false }, + { 167684, true }, + { 167693, true }, + { 167703, true }, + { 167717, true }, + { 167727, true }, + { 167740, true }, + { 167754, true }, + { 167775, true }, + { 167789, true }, + { 167801, true }, + { 167816, true }, + { 167835, true }, + { 167847, true }, + { 167866, true }, { 167875, false }, - { 167889, true }, - { 167898, true }, - { 167908, true }, - { 167922, true }, - { 167932, true }, - { 167945, true }, - { 167959, true }, - { 167980, true }, - { 167994, true }, - { 168006, true }, - { 168021, true }, - { 168040, true }, - { 168052, true }, - { 168071, true }, - { 168080, false }, - { 168095, false }, - { 168107, true }, - { 168133, true }, - { 168144, true }, - { 168165, true }, - { 168183, true }, - { 168200, true }, + { 167890, false }, + { 167902, true }, + { 167928, true }, + { 167939, true }, + { 167960, true }, + { 167978, true }, + { 167995, true }, + { 168010, true }, + { 168030, true }, + { 168041, true }, + { 168053, true }, + { 168066, true }, + { 168084, true }, + { 168104, true }, + { 168123, true }, + { 168142, true }, + { 168163, true }, + { 168172, true }, + { 168196, false }, { 168215, true }, - { 168235, true }, - { 168246, true }, - { 168258, true }, - { 168271, true }, - { 168289, true }, - { 168309, true }, - { 168328, true }, - { 168347, true }, - { 168368, true }, - { 168377, true }, - { 168401, false }, + { 168229, true }, + { 168247, true }, + { 168264, true }, + { 168284, true }, + { 168298, true }, + { 168308, true }, + { 168321, true }, + { 168342, true }, + { 168354, true }, + { 168365, true }, + { 168380, true }, + { 168401, true }, { 168420, true }, - { 168434, true }, - { 168452, true }, - { 168469, true }, - { 168489, true }, - { 168503, true }, - { 168513, true }, - { 168526, true }, - { 168547, true }, - { 168559, true }, - { 168570, true }, - { 168585, true }, - { 168606, true }, - { 168625, true }, - { 168654, true }, + { 168449, true }, + { 168456, true }, + { 168468, true }, + { 168483, true }, + { 168499, true }, + { 168516, true }, + { 168538, true }, + { 168548, true }, + { 168560, true }, + { 168572, true }, + { 168589, false }, + { 168602, false }, + { 168622, true }, + { 168632, true }, + { 168644, true }, { 168661, true }, - { 168673, true }, - { 168688, true }, - { 168704, true }, - { 168721, true }, - { 168743, true }, - { 168753, true }, - { 168765, true }, - { 168777, true }, - { 168794, false }, - { 168807, false }, - { 168827, true }, - { 168837, true }, - { 168849, true }, - { 168866, true }, - { 168882, true }, - { 168897, true }, - { 168912, true }, - { 168925, true }, - { 168941, true }, - { 168959, true }, - { 168971, true }, - { 168985, true }, - { 168996, true }, - { 169015, true }, - { 169034, true }, - { 169045, true }, - { 169057, true }, - { 169070, true }, - { 169083, true }, - { 169096, true }, - { 169109, true }, - { 169122, true }, - { 169137, true }, + { 168677, true }, + { 168692, true }, + { 168707, true }, + { 168720, true }, + { 168736, true }, + { 168754, true }, + { 168766, true }, + { 168780, true }, + { 168791, true }, + { 168810, true }, + { 168829, true }, + { 168841, true }, + { 168854, true }, + { 168867, true }, + { 168880, true }, + { 168893, true }, + { 168906, true }, + { 168921, true }, + { 168931, true }, + { 168944, true }, + { 168963, true }, + { 168976, true }, + { 168994, true }, + { 169016, true }, + { 169029, true }, + { 169046, true }, + { 169062, true }, + { 169090, true }, + { 169115, true }, { 169147, true }, - { 169160, true }, - { 169179, true }, - { 169192, true }, - { 169210, true }, - { 169232, true }, - { 169245, true }, - { 169262, true }, - { 169278, true }, - { 169306, true }, - { 169331, true }, - { 169363, true }, - { 169382, true }, - { 169397, true }, - { 169417, true }, - { 169430, true }, - { 169446, true }, - { 169463, true }, - { 169480, true }, - { 169492, true }, - { 169505, true }, - { 169518, true }, - { 169540, true }, - { 169558, true }, - { 169572, true }, - { 169593, true }, - { 169605, true }, - { 169620, true }, - { 169637, true }, - { 169649, true }, - { 169664, true }, - { 169675, true }, - { 169689, true }, - { 169708, true }, - { 169725, true }, - { 169737, true }, - { 169757, true }, - { 169771, true }, - { 169784, true }, - { 169803, true }, - { 169817, true }, - { 169831, true }, - { 169841, true }, - { 169853, true }, - { 169871, false }, - { 169879, true }, - { 169895, true }, - { 169907, true }, - { 169919, true }, - { 169930, true }, - { 169942, true }, - { 169951, true }, - { 169965, true }, - { 169979, true }, - { 169993, true }, + { 169166, true }, + { 169181, true }, + { 169201, true }, + { 169214, true }, + { 169230, true }, + { 169247, true }, + { 169264, true }, + { 169276, true }, + { 169289, true }, + { 169302, true }, + { 169324, true }, + { 169342, true }, + { 169356, true }, + { 169377, true }, + { 169389, true }, + { 169404, true }, + { 169421, true }, + { 169433, true }, + { 169448, true }, + { 169462, true }, + { 169481, true }, + { 169498, true }, + { 169510, true }, + { 169530, true }, + { 169544, true }, + { 169557, true }, + { 169576, true }, + { 169590, true }, + { 169604, true }, + { 169614, true }, + { 169626, true }, + { 169644, false }, + { 169652, true }, + { 169668, true }, + { 169680, true }, + { 169692, true }, + { 169703, true }, + { 169715, true }, + { 169724, true }, + { 169738, true }, + { 169752, true }, + { 169766, true }, + { 169777, true }, + { 169785, true }, + { 169801, true }, + { 169812, true }, + { 169827, true }, + { 169845, true }, + { 169865, true }, + { 169878, true }, + { 169899, true }, + { 169910, false }, + { 169928, false }, + { 169949, true }, + { 169958, true }, + { 169981, true }, { 170004, true }, - { 170012, true }, - { 170028, true }, - { 170039, true }, + { 170021, true }, + { 170033, true }, { 170054, true }, - { 170072, true }, - { 170092, true }, - { 170105, true }, - { 170126, true }, - { 170137, false }, - { 170155, false }, - { 170176, true }, + { 170071, true }, + { 170091, true }, + { 170104, true }, + { 170117, true }, + { 170131, true }, + { 170153, true }, + { 170168, true }, { 170185, true }, - { 170208, true }, - { 170231, true }, - { 170248, true }, - { 170260, true }, - { 170281, true }, - { 170298, true }, - { 170318, true }, - { 170331, true }, - { 170344, true }, - { 170358, true }, - { 170380, true }, - { 170395, true }, - { 170412, true }, - { 170429, true }, - { 170449, true }, - { 170474, true }, - { 170499, true }, - { 170512, true }, - { 170528, true }, - { 170539, true }, - { 170554, true }, - { 170563, true }, - { 170574, true }, - { 170586, true }, - { 170600, true }, - { 170609, true }, - { 170631, true }, - { 170643, true }, - { 170651, true }, - { 170665, true }, - { 170673, true }, - { 170683, true }, - { 170690, true }, + { 170202, true }, + { 170222, true }, + { 170247, true }, + { 170272, true }, + { 170285, true }, + { 170301, true }, + { 170312, true }, + { 170327, true }, + { 170336, true }, + { 170347, true }, + { 170359, true }, + { 170373, true }, + { 170382, true }, + { 170404, true }, + { 170416, true }, + { 170424, true }, + { 170438, true }, + { 170446, true }, + { 170456, true }, + { 170463, true }, + { 170473, true }, + { 170480, true }, + { 170497, true }, + { 170509, true }, + { 170520, true }, + { 170530, true }, + { 170543, true }, + { 170553, true }, + { 170564, true }, + { 170575, true }, + { 170583, true }, + { 170595, true }, + { 170606, true }, + { 170620, true }, + { 170629, true }, + { 170642, true }, + { 170668, true }, + { 170684, true }, { 170700, true }, - { 170707, true }, - { 170724, true }, - { 170736, true }, - { 170747, true }, - { 170757, true }, - { 170770, true }, - { 170780, true }, - { 170791, true }, - { 170802, true }, - { 170810, true }, - { 170822, true }, - { 170833, true }, - { 170847, true }, - { 170856, true }, - { 170869, true }, - { 170895, true }, - { 170911, true }, - { 170927, true }, - { 170940, true }, - { 170952, true }, - { 170964, true }, - { 170985, true }, - { 170995, true }, - { 171017, true }, + { 170713, true }, + { 170725, true }, + { 170737, true }, + { 170758, true }, + { 170768, true }, + { 170790, true }, + { 170808, true }, + { 170821, true }, + { 170832, false }, + { 170843, true }, + { 170853, true }, + { 170865, true }, + { 170879, true }, + { 170890, false }, + { 170903, false }, + { 170923, true }, + { 170933, true }, + { 170941, false }, + { 170950, true }, + { 170963, true }, + { 171009, true }, + { 171022, true }, { 171035, true }, - { 171048, true }, - { 171059, false }, - { 171070, true }, - { 171080, true }, - { 171092, true }, - { 171101, true }, - { 171115, true }, - { 171126, false }, - { 171139, false }, - { 171159, true }, - { 171169, true }, - { 171177, false }, - { 171186, true }, - { 171199, true }, - { 171245, true }, - { 171258, true }, - { 171271, true }, - { 171294, true }, - { 171310, true }, - { 171323, true }, - { 171339, true }, - { 171349, false }, - { 171361, true }, - { 171378, true }, - { 171396, true }, + { 171058, true }, + { 171074, true }, + { 171087, true }, + { 171103, true }, + { 171113, false }, + { 171125, true }, + { 171142, true }, + { 171160, true }, + { 171171, true }, + { 171179, true }, + { 171189, true }, + { 171196, true }, + { 171205, true }, + { 171212, true }, + { 171221, true }, + { 171237, true }, + { 171256, true }, + { 171269, true }, + { 171283, true }, + { 171295, true }, + { 171309, true }, + { 171324, true }, + { 171336, true }, + { 171349, true }, + { 171360, true }, + { 171381, true }, + { 171391, true }, + { 171400, true }, { 171407, true }, { 171415, true }, - { 171425, true }, - { 171432, true }, - { 171441, true }, - { 171448, true }, - { 171457, true }, - { 171473, true }, - { 171492, true }, - { 171505, true }, - { 171519, true }, - { 171531, true }, - { 171545, true }, - { 171560, true }, - { 171572, true }, - { 171585, true }, - { 171596, true }, - { 171617, true }, - { 171627, true }, - { 171636, true }, - { 171643, true }, - { 171651, true }, - { 171675, true }, - { 171689, true }, + { 171439, true }, + { 171453, true }, + { 171463, true }, + { 171480, false }, + { 171495, true }, + { 171507, true }, + { 171521, true }, + { 171538, true }, + { 171549, true }, + { 171561, true }, + { 171573, true }, + { 171583, true }, + { 171593, true }, + { 171604, true }, + { 171614, true }, + { 171633, true }, + { 171645, true }, + { 171661, true }, + { 171676, true }, { 171699, true }, - { 171716, false }, - { 171731, true }, - { 171745, true }, - { 171757, true }, - { 171771, true }, - { 171788, true }, - { 171799, true }, - { 171811, true }, + { 171706, true }, + { 171719, true }, + { 171730, true }, + { 171740, true }, + { 171747, true }, + { 171759, true }, + { 171770, true }, + { 171780, false }, + { 171800, true }, { 171823, true }, - { 171833, true }, - { 171844, true }, - { 171854, true }, - { 171873, true }, - { 171885, true }, - { 171901, true }, - { 171916, true }, - { 171939, true }, - { 171946, true }, + { 171847, true }, + { 171868, true }, + { 171887, true }, + { 171897, true }, + { 171910, true }, + { 171924, true }, + { 171937, true }, + { 171948, true }, { 171959, true }, - { 171970, true }, - { 171980, true }, - { 171987, true }, - { 171999, true }, - { 172010, true }, - { 172020, false }, - { 172040, true }, - { 172063, true }, - { 172087, true }, - { 172108, true }, - { 172127, true }, - { 172137, true }, - { 172150, true }, - { 172164, true }, - { 172177, true }, - { 172188, true }, + { 171969, true }, + { 171979, true }, + { 171990, true }, + { 172005, true }, + { 172019, true }, + { 172030, true }, + { 172044, true }, + { 172058, true }, + { 172073, true }, + { 172086, true }, + { 172109, true }, + { 172124, true }, + { 172140, true }, + { 172155, true }, + { 172169, true }, + { 172185, true }, { 172199, true }, - { 172209, true }, - { 172219, true }, - { 172230, true }, - { 172245, true }, - { 172259, true }, - { 172270, true }, - { 172284, true }, - { 172298, true }, - { 172313, true }, - { 172326, true }, - { 172349, true }, - { 172364, true }, - { 172380, true }, - { 172395, true }, - { 172409, true }, - { 172425, true }, - { 172439, true }, - { 172453, true }, - { 172471, true }, - { 172489, true }, - { 172509, true }, + { 172213, true }, + { 172231, true }, + { 172249, true }, + { 172269, true }, + { 172288, true }, + { 172304, true }, + { 172319, true }, + { 172333, true }, + { 172353, true }, + { 172369, true }, + { 172384, true }, + { 172398, true }, + { 172429, true }, + { 172445, true }, + { 172456, true }, + { 172466, false }, + { 172490, true }, + { 172504, true }, + { 172518, true }, { 172528, true }, - { 172544, true }, - { 172559, true }, - { 172573, true }, - { 172593, true }, - { 172609, true }, - { 172624, true }, - { 172638, true }, - { 172669, true }, - { 172680, true }, - { 172690, false }, - { 172714, true }, - { 172728, true }, - { 172742, true }, - { 172752, true }, - { 172769, true }, - { 172782, true }, - { 172795, true }, - { 172812, true }, - { 172829, false }, - { 172846, true }, - { 172859, true }, - { 172876, true }, - { 172897, true }, - { 172910, true }, - { 172923, true }, - { 172943, true }, - { 172961, true }, - { 172971, true }, - { 172984, true }, - { 173003, true }, + { 172545, true }, + { 172558, true }, + { 172571, true }, + { 172588, true }, + { 172605, false }, + { 172622, true }, + { 172635, true }, + { 172652, true }, + { 172673, true }, + { 172686, true }, + { 172699, true }, + { 172719, true }, + { 172737, true }, + { 172747, true }, + { 172760, true }, + { 172779, true }, + { 172793, true }, + { 172807, false }, + { 172818, true }, + { 172835, true }, + { 172848, true }, + { 172871, true }, + { 172899, true }, + { 172911, true }, + { 172925, true }, + { 172938, true }, + { 172950, true }, + { 172963, true }, + { 172979, true }, + { 172989, true }, + { 173002, true }, { 173017, true }, - { 173031, false }, - { 173042, true }, - { 173059, true }, - { 173072, true }, - { 173095, true }, - { 173123, true }, - { 173135, true }, - { 173149, true }, - { 173162, true }, - { 173174, true }, - { 173190, true }, - { 173203, true }, - { 173219, true }, - { 173229, true }, - { 173242, true }, - { 173257, true }, - { 173265, true }, - { 173280, true }, + { 173025, true }, + { 173040, true }, + { 173057, true }, + { 173064, true }, + { 173074, true }, + { 173084, true }, + { 173105, true }, + { 173121, true }, + { 173140, true }, + { 173160, true }, + { 173175, true }, + { 173183, true }, + { 173202, false }, + { 173210, true }, + { 173217, true }, + { 173232, true }, + { 173240, true }, + { 173251, true }, + { 173262, true }, + { 173277, false }, { 173297, true }, - { 173304, true }, - { 173314, true }, - { 173324, true }, - { 173345, true }, - { 173361, true }, - { 173380, true }, - { 173400, true }, - { 173415, true }, - { 173423, true }, - { 173442, false }, - { 173450, true }, - { 173457, true }, - { 173472, true }, - { 173480, true }, + { 173312, true }, + { 173327, true }, + { 173338, true }, + { 173348, true }, + { 173360, true }, + { 173384, true }, + { 173397, true }, + { 173409, true }, + { 173422, true }, + { 173436, true }, + { 173452, true }, + { 173471, true }, { 173491, true }, { 173502, true }, - { 173517, false }, - { 173537, true }, - { 173552, true }, - { 173567, true }, - { 173578, true }, - { 173588, true }, - { 173600, true }, - { 173624, true }, - { 173637, true }, - { 173649, true }, - { 173662, true }, - { 173676, true }, - { 173692, true }, - { 173711, true }, - { 173731, true }, - { 173742, true }, - { 173753, true }, - { 173761, true }, - { 173774, true }, - { 173788, true }, - { 173798, true }, - { 173816, true }, - { 173843, true }, - { 173856, false }, - { 173879, true }, - { 173901, true }, + { 173513, true }, + { 173521, true }, + { 173534, true }, + { 173548, true }, + { 173558, true }, + { 173576, true }, + { 173603, true }, + { 173616, false }, + { 173639, true }, + { 173661, true }, + { 173674, true }, + { 173689, true }, + { 173696, true }, + { 173703, true }, + { 173714, true }, + { 173730, true }, + { 173743, true }, + { 173755, true }, + { 173765, true }, + { 173782, true }, + { 173797, true }, + { 173806, true }, + { 173817, true }, + { 173835, true }, + { 173847, true }, + { 173857, true }, + { 173869, true }, + { 173882, true }, + { 173897, true }, { 173914, true }, - { 173929, true }, - { 173936, true }, + { 173924, true }, { 173943, true }, - { 173954, true }, - { 173970, true }, - { 173982, true }, - { 173995, true }, - { 174007, true }, - { 174017, true }, - { 174034, true }, - { 174049, true }, - { 174058, true }, - { 174069, true }, - { 174087, true }, - { 174099, true }, - { 174109, true }, - { 174121, true }, - { 174134, true }, - { 174149, true }, - { 174166, true }, - { 174176, true }, + { 173962, true }, + { 173980, true }, + { 173992, true }, + { 174011, false }, + { 174026, true }, + { 174040, false }, + { 174050, false }, + { 174060, true }, + { 174066, true }, + { 174075, true }, + { 174094, true }, + { 174108, true }, + { 174126, true }, + { 174138, true }, + { 174148, true }, + { 174172, true }, { 174195, true }, - { 174214, true }, - { 174232, true }, - { 174244, true }, - { 174263, false }, - { 174278, true }, - { 174292, false }, - { 174302, false }, - { 174312, true }, - { 174318, true }, + { 174208, true }, + { 174224, true }, + { 174236, true }, + { 174250, false }, + { 174263, true }, + { 174282, true }, + { 174292, true }, + { 174314, true }, { 174327, true }, - { 174346, true }, + { 174336, true }, + { 174347, true }, { 174360, true }, - { 174378, true }, - { 174390, true }, - { 174400, true }, - { 174424, true }, - { 174447, true }, - { 174460, true }, - { 174476, true }, - { 174488, true }, - { 174502, false }, + { 174373, true }, + { 174384, true }, + { 174398, true }, + { 174413, true }, + { 174428, true }, + { 174451, false }, + { 174464, false }, + { 174478, true }, + { 174493, true }, + { 174505, true }, { 174515, true }, - { 174534, true }, - { 174544, true }, - { 174566, true }, - { 174579, true }, - { 174588, true }, - { 174599, true }, - { 174612, true }, - { 174625, true }, - { 174636, true }, - { 174650, true }, - { 174665, true }, - { 174680, true }, - { 174703, false }, - { 174716, false }, - { 174730, true }, + { 174529, true }, + { 174542, false }, + { 174556, true }, + { 174568, true }, + { 174580, true }, + { 174596, true }, + { 174622, true }, + { 174640, false }, + { 174653, true }, + { 174663, true }, + { 174673, true }, + { 174684, true }, + { 174699, true }, + { 174711, true }, + { 174727, true }, + { 174735, true }, { 174745, true }, - { 174757, true }, - { 174767, true }, - { 174781, true }, - { 174794, false }, - { 174808, true }, + { 174755, true }, + { 174766, true }, + { 174786, false }, + { 174807, true }, { 174820, true }, - { 174832, true }, - { 174848, true }, - { 174874, true }, - { 174892, false }, - { 174905, true }, - { 174915, true }, - { 174925, true }, - { 174936, true }, - { 174951, true }, - { 174963, true }, - { 174979, true }, - { 174987, true }, - { 174997, true }, - { 175007, true }, - { 175017, true }, - { 175028, true }, - { 175048, false }, - { 175069, true }, - { 175082, true }, - { 175096, true }, - { 175106, true }, - { 175119, true }, - { 175135, true }, - { 175146, false }, - { 175166, true }, - { 175176, true }, - { 175186, true }, - { 175203, true }, - { 175219, true }, - { 175230, true }, - { 175260, true }, - { 175286, true }, - { 175294, true }, - { 175313, true }, - { 175327, true }, - { 175346, true }, - { 175367, true }, - { 175377, true }, - { 175392, true }, - { 175408, true }, - { 175425, true }, - { 175436, true }, - { 175453, true }, - { 175469, true }, - { 175489, true }, - { 175511, true }, - { 175524, true }, - { 175534, true }, - { 175556, true }, - { 175577, true }, - { 175590, true }, - { 175614, true }, - { 175626, true }, - { 175638, true }, - { 175648, true }, - { 175666, false }, - { 175683, true }, - { 175715, true }, - { 175726, true }, - { 175736, true }, - { 175749, true }, - { 175762, true }, - { 175773, true }, - { 175784, true }, - { 175794, true }, - { 175801, true }, - { 175814, false }, - { 175826, true }, - { 175846, true }, - { 175856, true }, - { 175877, true }, - { 175894, true }, - { 175911, true }, - { 175929, true }, - { 175947, false }, - { 175965, false }, - { 175983, false }, - { 176000, true }, - { 176022, true }, - { 176035, true }, - { 176048, false }, - { 176063, false }, - { 176073, false }, - { 176087, true }, - { 176102, true }, - { 176114, true }, - { 176132, true }, - { 176147, true }, - { 176165, true }, - { 176177, true }, - { 176193, true }, - { 176203, true }, - { 176213, true }, - { 176241, true }, - { 176256, true }, - { 176267, true }, - { 176277, false }, - { 176295, true }, - { 176310, true }, - { 176322, true }, - { 176335, true }, - { 176352, true }, - { 176362, true }, - { 176373, false }, - { 176388, true }, - { 176406, true }, - { 176421, true }, - { 176439, true }, - { 176462, true }, - { 176476, true }, - { 176492, true }, - { 176510, true }, - { 176543, false }, - { 176566, true }, - { 176586, true }, - { 176603, true }, - { 176621, true }, - { 176634, true }, - { 176647, true }, - { 176664, true }, - { 176675, true }, - { 176697, true }, - { 176715, false }, - { 176729, true }, - { 176748, true }, - { 176762, true }, - { 176783, true }, - { 176801, true }, - { 176815, true }, - { 176824, true }, - { 176837, true }, - { 176855, true }, - { 176867, true }, - { 176883, true }, - { 176898, true }, - { 176911, true }, - { 176923, true }, - { 176935, true }, - { 176946, true }, - { 176957, true }, - { 176966, true }, - { 176979, true }, - { 176993, true }, - { 177004, true }, - { 177015, true }, - { 177028, true }, - { 177042, false }, - { 177055, true }, - { 177064, true }, - { 177074, true }, - { 177087, true }, - { 177096, true }, - { 177106, true }, - { 177117, true }, - { 177127, true }, - { 177135, false }, - { 177149, false }, - { 177169, true }, - { 177179, true }, - { 177193, true }, - { 177203, true }, - { 177214, true }, + { 174834, true }, + { 174844, true }, + { 174857, true }, + { 174873, true }, + { 174884, false }, + { 174904, true }, + { 174914, true }, + { 174924, true }, + { 174941, true }, + { 174957, true }, + { 174968, true }, + { 174998, true }, + { 175024, true }, + { 175032, true }, + { 175051, true }, + { 175065, true }, + { 175084, true }, + { 175105, true }, + { 175115, true }, + { 175130, true }, + { 175146, true }, + { 175163, true }, + { 175174, true }, + { 175191, true }, + { 175207, true }, + { 175227, true }, + { 175249, true }, + { 175262, true }, + { 175284, true }, + { 175305, true }, + { 175318, true }, + { 175342, true }, + { 175354, true }, + { 175366, true }, + { 175376, true }, + { 175394, false }, + { 175411, true }, + { 175443, true }, + { 175454, true }, + { 175464, true }, + { 175477, true }, + { 175490, true }, + { 175501, true }, + { 175512, true }, + { 175522, true }, + { 175529, true }, + { 175542, false }, + { 175554, true }, + { 175574, true }, + { 175584, true }, + { 175605, true }, + { 175622, true }, + { 175639, true }, + { 175657, true }, + { 175675, false }, + { 175693, false }, + { 175711, false }, + { 175728, true }, + { 175750, true }, + { 175763, true }, + { 175776, false }, + { 175791, false }, + { 175801, false }, + { 175815, true }, + { 175830, true }, + { 175842, true }, + { 175860, true }, + { 175875, true }, + { 175893, true }, + { 175905, true }, + { 175921, true }, + { 175931, true }, + { 175941, true }, + { 175969, true }, + { 175984, true }, + { 175995, true }, + { 176005, false }, + { 176023, true }, + { 176038, true }, + { 176050, true }, + { 176063, true }, + { 176080, true }, + { 176090, true }, + { 176101, false }, + { 176116, true }, + { 176134, true }, + { 176149, true }, + { 176167, true }, + { 176190, true }, + { 176204, true }, + { 176220, true }, + { 176238, true }, + { 176262, true }, + { 176295, false }, + { 176318, true }, + { 176338, true }, + { 176355, true }, + { 176373, true }, + { 176386, true }, + { 176403, true }, + { 176414, true }, + { 176436, true }, + { 176454, false }, + { 176468, true }, + { 176487, true }, + { 176501, true }, + { 176522, true }, + { 176540, true }, + { 176554, true }, + { 176563, true }, + { 176576, true }, + { 176594, true }, + { 176606, true }, + { 176622, true }, + { 176637, true }, + { 176650, true }, + { 176662, true }, + { 176674, true }, + { 176685, true }, + { 176696, true }, + { 176705, true }, + { 176718, true }, + { 176732, true }, + { 176743, true }, + { 176754, true }, + { 176767, true }, + { 176781, false }, + { 176794, true }, + { 176803, true }, + { 176813, true }, + { 176826, true }, + { 176835, true }, + { 176845, true }, + { 176856, true }, + { 176866, true }, + { 176874, false }, + { 176888, false }, + { 176908, true }, + { 176918, true }, + { 176932, true }, + { 176942, true }, + { 176953, true }, + { 176965, true }, + { 176977, true }, + { 176987, true }, + { 176999, true }, + { 177010, true }, + { 177022, true }, + { 177038, true }, + { 177053, true }, + { 177063, true }, + { 177078, true }, + { 177093, true }, + { 177105, true }, + { 177112, true }, + { 177123, true }, + { 177133, true }, + { 177148, true }, + { 177159, true }, + { 177172, true }, + { 177186, true }, + { 177200, true }, + { 177211, false }, { 177226, true }, - { 177238, true }, - { 177248, true }, - { 177257, true }, - { 177269, true }, - { 177280, true }, - { 177292, true }, - { 177308, true }, - { 177323, true }, - { 177333, true }, - { 177348, true }, - { 177363, true }, - { 177375, true }, - { 177382, true }, - { 177393, true }, + { 177235, true }, + { 177245, true }, + { 177252, true }, + { 177263, true }, + { 177275, true }, + { 177297, true }, + { 177320, false }, + { 177331, true }, + { 177341, true }, + { 177368, true }, + { 177377, true }, + { 177386, true }, { 177403, true }, - { 177418, true }, - { 177429, true }, - { 177442, true }, - { 177456, true }, - { 177470, true }, - { 177481, false }, - { 177496, true }, + { 177416, true }, + { 177443, true }, + { 177450, true }, + { 177461, true }, + { 177478, true }, + { 177494, true }, { 177505, true }, - { 177515, true }, - { 177522, true }, - { 177533, true }, - { 177545, true }, - { 177567, true }, - { 177590, false }, - { 177601, true }, - { 177611, true }, - { 177638, true }, - { 177647, true }, - { 177656, true }, - { 177673, true }, - { 177685, true }, - { 177698, true }, - { 177725, true }, + { 177518, true }, + { 177542, true }, + { 177549, true }, + { 177559, true }, + { 177566, true }, + { 177586, true }, + { 177598, true }, + { 177619, true }, + { 177630, true }, + { 177640, true }, + { 177649, true }, + { 177658, true }, + { 177677, true }, + { 177697, true }, + { 177711, true }, { 177732, true }, - { 177743, true }, - { 177760, true }, - { 177776, true }, - { 177787, true }, - { 177800, true }, - { 177824, true }, - { 177831, true }, - { 177841, true }, - { 177848, true }, - { 177868, true }, - { 177880, true }, - { 177901, true }, - { 177912, true }, - { 177924, true }, + { 177745, true }, + { 177757, true }, + { 177781, true }, + { 177799, false }, + { 177813, true }, + { 177828, true }, + { 177843, true }, + { 177852, false }, + { 177869, false }, + { 177879, true }, + { 177889, true }, + { 177903, true }, + { 177918, true }, { 177934, true }, - { 177943, true }, - { 177952, true }, + { 177950, true }, + { 177960, true }, { 177971, true }, - { 177991, true }, - { 178005, true }, - { 178026, true }, - { 178039, true }, - { 178051, true }, - { 178075, true }, - { 178093, false }, - { 178107, true }, - { 178122, true }, - { 178137, true }, - { 178146, false }, - { 178163, false }, - { 178173, true }, - { 178183, true }, - { 178197, true }, - { 178212, true }, - { 178228, true }, - { 178244, true }, - { 178254, true }, - { 178265, true }, - { 178276, true }, - { 178288, true }, - { 178300, true }, - { 178311, true }, - { 178325, true }, - { 178341, true }, - { 178353, false }, - { 178372, true }, - { 178387, true }, - { 178397, true }, - { 178415, true }, - { 178426, true }, - { 178446, true }, - { 178463, true }, - { 178479, true }, - { 178498, true }, - { 178513, true }, - { 178529, true }, - { 178546, true }, - { 178566, true }, - { 178578, true }, - { 178593, true }, - { 178612, true }, - { 178621, true }, - { 178638, true }, - { 178650, true }, - { 178662, true }, - { 178674, true }, - { 178683, true }, - { 178693, true }, - { 178710, true }, - { 178728, true }, - { 178739, true }, - { 178749, true }, - { 178764, true }, - { 178774, true }, - { 178784, false }, - { 178791, true }, - { 178801, true }, - { 178822, true }, - { 178842, true }, - { 178865, true }, - { 178885, true }, - { 178900, true }, - { 178918, true }, - { 178929, false }, + { 177982, true }, + { 177994, true }, + { 178006, true }, + { 178017, true }, + { 178031, true }, + { 178047, true }, + { 178059, false }, + { 178078, true }, + { 178093, true }, + { 178103, true }, + { 178121, true }, + { 178132, true }, + { 178152, true }, + { 178169, true }, + { 178185, true }, + { 178204, true }, + { 178219, true }, + { 178235, true }, + { 178252, true }, + { 178272, true }, + { 178284, true }, + { 178299, true }, + { 178318, true }, + { 178327, true }, + { 178344, true }, + { 178356, true }, + { 178368, true }, + { 178380, true }, + { 178389, true }, + { 178399, true }, + { 178416, true }, + { 178434, true }, + { 178445, true }, + { 178455, true }, + { 178470, true }, + { 178480, true }, + { 178490, false }, + { 178497, true }, + { 178507, true }, + { 178528, true }, + { 178548, true }, + { 178571, true }, + { 178591, true }, + { 178606, true }, + { 178624, true }, + { 178635, false }, + { 178659, true }, + { 178678, true }, + { 178691, true }, + { 178707, false }, + { 178723, true }, + { 178737, true }, + { 178744, true }, + { 178756, false }, + { 178770, true }, + { 178789, true }, + { 178807, true }, + { 178820, true }, + { 178834, false }, + { 178850, true }, + { 178868, true }, + { 178891, true }, + { 178904, true }, + { 178916, true }, + { 178927, true }, + { 178938, true }, { 178953, true }, - { 178972, true }, - { 178985, true }, - { 179001, false }, - { 179017, true }, - { 179031, true }, - { 179038, true }, - { 179050, false }, - { 179064, true }, - { 179083, true }, - { 179101, true }, - { 179114, true }, - { 179128, false }, - { 179144, true }, - { 179162, true }, - { 179185, true }, - { 179198, true }, - { 179210, true }, - { 179221, true }, - { 179232, true }, - { 179247, true }, - { 179261, true }, - { 179286, true }, - { 179319, true }, - { 179345, true }, - { 179379, true }, - { 179402, true }, - { 179414, true }, - { 179426, true }, - { 179442, false }, - { 179462, true }, - { 179475, false }, - { 179493, false }, + { 178967, true }, + { 178992, true }, + { 179025, true }, + { 179051, true }, + { 179085, true }, + { 179108, true }, + { 179120, true }, + { 179132, true }, + { 179148, false }, + { 179168, true }, + { 179181, false }, + { 179199, false }, + { 179222, true }, + { 179242, true }, + { 179258, true }, + { 179272, true }, + { 179293, true }, + { 179308, false }, + { 179321, true }, + { 179335, true }, + { 179347, true }, + { 179359, true }, + { 179375, false }, + { 179397, true }, + { 179417, true }, + { 179429, true }, + { 179445, true }, + { 179457, true }, + { 179470, true }, + { 179486, true }, + { 179504, true }, { 179516, true }, - { 179536, true }, - { 179552, true }, - { 179566, true }, - { 179587, true }, + { 179530, true }, + { 179544, true }, + { 179561, true }, + { 179578, true }, + { 179592, true }, { 179602, false }, - { 179615, true }, - { 179629, true }, - { 179641, true }, - { 179653, true }, - { 179669, false }, - { 179691, true }, - { 179711, true }, - { 179723, true }, - { 179739, true }, - { 179751, true }, - { 179764, true }, - { 179780, true }, - { 179798, true }, - { 179810, true }, - { 179824, true }, - { 179838, true }, - { 179855, true }, - { 179869, true }, - { 179879, false }, + { 179616, true }, + { 179626, true }, + { 179647, true }, + { 179660, true }, + { 179676, true }, + { 179689, true }, + { 179700, true }, + { 179713, true }, + { 179734, true }, + { 179754, true }, + { 179771, true }, + { 179785, true }, + { 179795, true }, + { 179805, true }, + { 179813, true }, + { 179829, true }, + { 179845, true }, + { 179861, true }, + { 179882, true }, { 179893, true }, - { 179903, true }, - { 179924, true }, - { 179937, true }, - { 179953, true }, - { 179966, true }, - { 179977, true }, - { 179990, true }, - { 180011, true }, - { 180031, true }, - { 180048, true }, - { 180060, true }, - { 180074, true }, - { 180084, true }, - { 180094, true }, - { 180102, true }, - { 180118, true }, - { 180134, true }, - { 180150, true }, - { 180171, true }, - { 180182, true }, - { 180194, true }, - { 180207, true }, - { 180232, true }, - { 180247, true }, + { 179905, true }, + { 179918, true }, + { 179943, true }, + { 179958, true }, + { 179978, true }, + { 179992, true }, + { 180006, true }, + { 180021, true }, + { 180043, true }, + { 180063, true }, + { 180078, true }, + { 180088, true }, + { 180106, true }, + { 180121, true }, + { 180137, true }, + { 180153, true }, + { 180162, false }, + { 180172, true }, + { 180184, true }, + { 180196, true }, + { 180212, true }, + { 180228, true }, + { 180249, false }, { 180267, true }, - { 180281, true }, - { 180295, true }, - { 180310, true }, - { 180332, true }, - { 180352, true }, - { 180367, true }, - { 180377, true }, - { 180395, true }, - { 180410, true }, - { 180426, true }, - { 180442, true }, - { 180451, false }, - { 180461, true }, - { 180473, true }, - { 180485, true }, - { 180501, true }, - { 180517, true }, - { 180538, true }, - { 180550, true }, - { 180569, false }, - { 180581, true }, - { 180591, true }, - { 180606, true }, - { 180618, true }, - { 180642, true }, - { 180654, true }, + { 180279, true }, + { 180298, true }, + { 180308, true }, + { 180323, true }, + { 180335, true }, + { 180359, true }, + { 180371, true }, + { 180392, true }, + { 180423, true }, + { 180448, true }, + { 180471, true }, + { 180482, true }, + { 180494, true }, + { 180509, true }, + { 180522, true }, + { 180535, true }, + { 180564, true }, + { 180587, true }, + { 180611, true }, + { 180638, true }, + { 180652, true }, { 180675, true }, - { 180706, true }, - { 180731, true }, - { 180754, true }, - { 180765, true }, - { 180777, true }, - { 180792, true }, - { 180805, true }, - { 180818, true }, - { 180847, true }, - { 180870, true }, - { 180894, true }, - { 180921, true }, - { 180935, true }, - { 180958, true }, - { 180984, true }, - { 181012, true }, - { 181043, true }, - { 181068, true }, - { 181076, true }, + { 180701, true }, + { 180729, true }, + { 180760, true }, + { 180785, true }, + { 180793, true }, + { 180800, true }, + { 180812, true }, + { 180824, true }, + { 180837, true }, + { 180858, true }, + { 180871, true }, + { 180892, true }, + { 180911, true }, + { 180930, true }, + { 180941, true }, + { 180954, true }, + { 180970, false }, + { 180986, true }, + { 180994, true }, + { 181009, false }, + { 181024, true }, + { 181040, true }, + { 181050, true }, + { 181069, true }, { 181083, true }, - { 181095, true }, - { 181107, true }, - { 181120, true }, - { 181141, true }, + { 181092, true }, + { 181104, true }, + { 181117, true }, + { 181132, true }, { 181154, true }, - { 181175, true }, - { 181194, true }, - { 181213, true }, - { 181224, true }, - { 181237, true }, - { 181253, false }, - { 181269, true }, - { 181277, true }, - { 181292, false }, - { 181307, true }, - { 181323, true }, - { 181333, true }, - { 181349, true }, - { 181368, true }, + { 181171, true }, + { 181185, true }, + { 181192, true }, + { 181205, true }, + { 181218, true }, + { 181244, true }, + { 181256, true }, + { 181267, true }, + { 181293, true }, + { 181303, false }, + { 181320, true }, + { 181332, true }, + { 181347, true }, + { 181357, true }, + { 181370, true }, { 181382, true }, - { 181391, true }, - { 181403, true }, - { 181416, true }, - { 181431, true }, - { 181453, true }, - { 181470, true }, - { 181484, true }, - { 181491, true }, - { 181504, true }, - { 181517, true }, - { 181543, true }, - { 181555, true }, - { 181566, true }, - { 181592, true }, - { 181602, false }, - { 181619, true }, - { 181631, true }, - { 181646, true }, - { 181656, true }, - { 181669, true }, - { 181681, true }, - { 181691, true }, - { 181704, false }, - { 181720, true }, - { 181736, true }, - { 181750, false }, - { 181765, true }, - { 181778, true }, - { 181792, true }, - { 181806, true }, - { 181820, true }, - { 181844, true }, - { 181857, true }, - { 181870, true }, - { 181884, true }, - { 181898, true }, - { 181913, true }, - { 181927, true }, - { 181943, true }, - { 181958, true }, - { 181973, true }, - { 181991, true }, - { 182003, true }, + { 181392, true }, + { 181405, false }, + { 181421, true }, + { 181437, true }, + { 181451, false }, + { 181466, true }, + { 181479, true }, + { 181493, true }, + { 181507, true }, + { 181521, true }, + { 181545, true }, + { 181558, true }, + { 181571, true }, + { 181585, true }, + { 181599, true }, + { 181614, true }, + { 181628, true }, + { 181644, true }, + { 181659, true }, + { 181674, true }, + { 181692, true }, + { 181704, true }, + { 181716, true }, + { 181732, true }, + { 181749, true }, + { 181773, true }, + { 181790, true }, + { 181808, true }, + { 181827, true }, + { 181847, true }, + { 181862, true }, + { 181874, true }, + { 181888, true }, + { 181905, true }, + { 181916, true }, + { 181925, true }, + { 181939, true }, + { 181954, true }, + { 181966, true }, + { 181976, true }, + { 181988, true }, + { 182002, true }, { 182015, true }, - { 182031, true }, - { 182048, true }, - { 182072, true }, - { 182089, true }, - { 182107, true }, - { 182126, true }, - { 182146, true }, - { 182161, true }, - { 182173, true }, - { 182187, true }, - { 182204, true }, - { 182215, true }, - { 182224, true }, - { 182238, true }, + { 182027, false }, + { 182046, true }, + { 182068, true }, + { 182083, true }, + { 182102, true }, + { 182116, false }, + { 182127, true }, + { 182142, true }, + { 182156, true }, + { 182168, true }, + { 182185, true }, + { 182203, true }, + { 182210, true }, + { 182223, true }, + { 182235, true }, + { 182243, true }, { 182253, true }, - { 182265, true }, - { 182275, true }, - { 182287, true }, - { 182301, true }, - { 182314, true }, - { 182326, false }, - { 182345, true }, - { 182367, true }, - { 182382, true }, - { 182401, true }, - { 182415, false }, - { 182426, true }, - { 182441, true }, - { 182455, true }, + { 182263, true }, + { 182278, true }, + { 182297, true }, + { 182309, true }, + { 182325, true }, + { 182340, false }, + { 182350, false }, + { 182362, true }, + { 182371, true }, + { 182385, true }, + { 182397, true }, + { 182405, true }, + { 182415, true }, + { 182434, true }, + { 182442, false }, + { 182454, true }, { 182467, true }, - { 182484, true }, - { 182502, true }, - { 182509, true }, - { 182522, true }, - { 182534, true }, - { 182542, true }, - { 182552, true }, - { 182562, true }, - { 182577, true }, - { 182596, true }, - { 182608, true }, - { 182624, true }, - { 182639, false }, - { 182649, false }, - { 182661, true }, - { 182670, true }, - { 182684, true }, - { 182696, true }, - { 182704, true }, - { 182714, true }, + { 182482, true }, + { 182504, true }, + { 182518, true }, + { 182530, true }, + { 182548, true }, + { 182564, true }, + { 182573, false }, + { 182590, true }, + { 182611, true }, + { 182632, true }, + { 182644, true }, + { 182669, true }, + { 182695, true }, + { 182721, true }, { 182733, true }, - { 182741, false }, - { 182753, true }, - { 182766, true }, - { 182781, true }, - { 182803, true }, - { 182817, true }, - { 182829, true }, - { 182847, true }, - { 182863, true }, - { 182872, false }, - { 182889, true }, - { 182910, true }, - { 182931, true }, - { 182943, true }, - { 182968, true }, + { 182746, true }, + { 182759, true }, + { 182769, true }, + { 182778, true }, + { 182792, true }, + { 182808, true }, + { 182828, true }, + { 182843, true }, + { 182853, true }, + { 182865, true }, + { 182885, true }, + { 182907, true }, + { 182924, true }, + { 182937, true }, + { 182956, true }, + { 182970, true }, { 182994, true }, - { 183020, true }, - { 183032, true }, - { 183045, true }, - { 183058, true }, - { 183068, true }, - { 183077, true }, - { 183091, true }, - { 183107, true }, - { 183127, true }, - { 183142, true }, - { 183158, true }, - { 183168, true }, - { 183180, true }, - { 183200, true }, - { 183222, true }, - { 183239, true }, - { 183252, true }, - { 183271, true }, - { 183285, true }, - { 183309, true }, - { 183326, false }, - { 183340, true }, - { 183353, true }, - { 183366, true }, - { 183385, true }, - { 183407, true }, - { 183419, true }, - { 183434, true }, - { 183455, true }, - { 183480, true }, + { 183011, false }, + { 183025, true }, + { 183038, true }, + { 183051, true }, + { 183070, true }, + { 183092, true }, + { 183104, true }, + { 183119, true }, + { 183140, true }, + { 183165, true }, + { 183181, true }, + { 183207, true }, + { 183223, true }, + { 183236, true }, + { 183254, true }, + { 183268, true }, + { 183287, true }, + { 183298, true }, + { 183310, true }, + { 183320, true }, + { 183329, true }, + { 183343, true }, + { 183354, true }, + { 183365, true }, + { 183373, true }, + { 183386, true }, + { 183400, true }, + { 183417, true }, + { 183428, false }, + { 183440, true }, + { 183459, true }, + { 183472, true }, + { 183483, true }, { 183496, true }, - { 183522, true }, + { 183508, true }, + { 183518, true }, + { 183528, true }, { 183538, true }, - { 183551, true }, - { 183569, true }, - { 183583, true }, - { 183594, true }, - { 183606, true }, - { 183616, true }, - { 183625, true }, - { 183639, true }, - { 183650, true }, - { 183661, true }, - { 183669, true }, - { 183682, true }, - { 183696, true }, - { 183713, true }, - { 183724, false }, - { 183736, true }, - { 183755, true }, - { 183768, true }, - { 183779, true }, - { 183792, true }, - { 183804, true }, - { 183814, true }, - { 183824, true }, - { 183834, true }, - { 183857, true }, - { 183869, true }, - { 183888, true }, - { 183896, true }, - { 183910, false }, - { 183923, true }, - { 183936, true }, - { 183947, true }, - { 183958, true }, - { 183974, true }, - { 183984, true }, - { 183998, true }, - { 184005, true }, - { 184018, true }, - { 184035, true }, - { 184045, true }, - { 184061, true }, - { 184076, true }, - { 184086, false }, - { 184097, false }, - { 184115, false }, - { 184128, true }, - { 184143, false }, - { 184161, false }, - { 184184, false }, - { 184205, false }, - { 184224, true }, - { 184240, false }, - { 184256, false }, - { 184272, true }, - { 184294, true }, - { 184307, false }, - { 184324, false }, - { 184341, true }, - { 184358, false }, - { 184375, false }, - { 184389, false }, - { 184408, false }, - { 184419, false }, - { 184431, false }, - { 184443, false }, - { 184462, true }, - { 184480, false }, - { 184494, false }, - { 184511, false }, - { 184528, false }, - { 184543, false }, - { 184559, true }, - { 184580, false }, - { 184599, false }, - { 184617, false }, - { 184637, true }, - { 184653, false }, - { 184668, true }, + { 183561, true }, + { 183573, true }, + { 183592, true }, + { 183600, true }, + { 183614, false }, + { 183627, true }, + { 183640, true }, + { 183651, true }, + { 183662, true }, + { 183678, true }, + { 183688, true }, + { 183702, true }, + { 183709, true }, + { 183722, true }, + { 183739, true }, + { 183749, true }, + { 183765, true }, + { 183780, true }, + { 183790, true }, + { 183802, false }, + { 183813, false }, + { 183831, false }, + { 183844, true }, + { 183859, false }, + { 183877, false }, + { 183900, false }, + { 183921, false }, + { 183940, true }, + { 183956, false }, + { 183972, false }, + { 183988, true }, + { 184010, true }, + { 184023, false }, + { 184040, false }, + { 184057, true }, + { 184074, false }, + { 184091, false }, + { 184105, false }, + { 184124, false }, + { 184135, false }, + { 184147, false }, + { 184159, false }, + { 184178, true }, + { 184196, false }, + { 184210, false }, + { 184227, false }, + { 184244, false }, + { 184259, false }, + { 184275, true }, + { 184296, false }, + { 184315, false }, + { 184333, false }, + { 184353, true }, + { 184369, false }, + { 184384, true }, + { 184399, true }, + { 184423, true }, + { 184430, true }, + { 184449, false }, + { 184467, false }, + { 184482, true }, + { 184503, false }, + { 184527, false }, + { 184546, false }, + { 184562, false }, + { 184577, false }, + { 184590, true }, + { 184606, false }, + { 184621, false }, + { 184635, false }, + { 184653, true }, + { 184664, true }, + { 184675, true }, { 184683, true }, - { 184707, true }, - { 184714, true }, - { 184733, false }, - { 184751, false }, - { 184766, true }, - { 184787, false }, - { 184811, false }, - { 184830, false }, - { 184846, false }, - { 184861, false }, - { 184874, true }, - { 184890, false }, - { 184905, false }, - { 184919, false }, + { 184698, true }, + { 184711, true }, + { 184728, true }, + { 184740, true }, + { 184748, true }, + { 184759, true }, + { 184775, true }, + { 184780, true }, + { 184785, true }, + { 184795, true }, + { 184803, true }, + { 184823, true }, + { 184830, true }, + { 184849, true }, + { 184856, true }, + { 184863, true }, + { 184872, true }, + { 184893, true }, + { 184913, true }, { 184937, true }, - { 184948, true }, - { 184959, true }, - { 184967, true }, - { 184982, true }, - { 184995, true }, - { 185012, true }, - { 185024, true }, - { 185032, true }, - { 185043, true }, - { 185059, true }, - { 185064, true }, - { 185069, true }, - { 185079, true }, - { 185087, true }, - { 185107, true }, - { 185114, true }, - { 185133, true }, - { 185140, true }, - { 185147, true }, - { 185156, true }, - { 185177, true }, - { 185197, true }, - { 185221, true }, - { 185228, true }, - { 185238, true }, - { 185255, true }, - { 185275, true }, - { 185281, true }, + { 184944, true }, + { 184954, true }, + { 184971, true }, + { 184991, true }, + { 184997, true }, + { 185004, true }, + { 185016, true }, + { 185029, true }, + { 185044, false }, + { 185055, true }, + { 185066, true }, + { 185074, false }, + { 185093, true }, + { 185104, true }, + { 185115, true }, + { 185122, true }, + { 185141, true }, + { 185157, true }, + { 185169, true }, + { 185180, true }, + { 185193, true }, + { 185207, true }, + { 185222, true }, + { 185237, true }, + { 185247, true }, + { 185257, false }, + { 185267, true }, + { 185277, true }, { 185288, true }, - { 185300, true }, - { 185313, true }, - { 185323, true }, - { 185338, false }, - { 185349, true }, - { 185360, true }, - { 185368, false }, - { 185387, true }, - { 185398, true }, - { 185409, true }, - { 185416, true }, - { 185435, true }, - { 185451, true }, - { 185463, true }, - { 185474, true }, - { 185487, true }, - { 185501, true }, - { 185516, true }, - { 185531, true }, - { 185541, true }, - { 185551, false }, - { 185561, true }, - { 185571, true }, - { 185582, true }, - { 185592, true }, - { 185601, true }, - { 185611, true }, - { 185619, true }, - { 185631, true }, - { 185642, true }, - { 185653, true }, + { 185298, true }, + { 185307, true }, + { 185317, true }, + { 185325, true }, + { 185337, true }, + { 185348, true }, + { 185359, true }, + { 185371, true }, + { 185381, true }, + { 185389, true }, + { 185403, true }, + { 185410, true }, + { 185428, true }, + { 185454, true }, + { 185480, true }, + { 185503, true }, + { 185534, true }, + { 185550, true }, + { 185562, true }, + { 185581, true }, + { 185614, true }, + { 185640, true }, { 185665, true }, - { 185675, true }, - { 185683, true }, - { 185697, true }, - { 185704, true }, - { 185722, true }, - { 185748, true }, - { 185774, true }, - { 185797, true }, - { 185828, true }, - { 185844, true }, - { 185856, true }, - { 185875, true }, - { 185908, true }, - { 185934, true }, - { 185959, true }, - { 185984, true }, - { 186014, true }, - { 186025, true }, - { 186044, true }, - { 186075, true }, - { 186086, false }, - { 186107, true }, - { 186130, true }, - { 186145, true }, - { 186159, true }, - { 186201, true }, - { 186224, true }, + { 185690, true }, + { 185720, true }, + { 185731, true }, + { 185750, true }, + { 185781, true }, + { 185792, false }, + { 185813, true }, + { 185836, true }, + { 185851, true }, + { 185865, true }, + { 185907, true }, + { 185930, true }, + { 185946, true }, + { 185972, true }, + { 186006, true }, + { 186030, false }, + { 186040, true }, + { 186046, true }, + { 186055, false }, + { 186065, true }, + { 186076, true }, + { 186086, true }, + { 186093, true }, + { 186100, true }, + { 186113, true }, + { 186120, true }, + { 186127, true }, + { 186141, true }, + { 186150, true }, + { 186164, true }, + { 186174, true }, + { 186184, true }, + { 186197, true }, + { 186204, true }, + { 186211, true }, + { 186220, true }, + { 186233, true }, { 186240, true }, - { 186266, true }, - { 186300, true }, - { 186324, false }, - { 186334, true }, - { 186340, true }, - { 186349, false }, - { 186359, true }, - { 186370, true }, - { 186380, true }, - { 186387, true }, - { 186394, true }, - { 186407, true }, - { 186414, true }, - { 186421, true }, - { 186435, true }, - { 186444, true }, - { 186458, true }, - { 186468, true }, - { 186478, true }, - { 186491, true }, - { 186498, true }, - { 186505, true }, - { 186514, true }, - { 186527, true }, - { 186534, true }, - { 186544, true }, - { 186552, true }, - { 186563, true }, - { 186573, true }, - { 186588, true }, - { 186598, true }, - { 186610, true }, - { 186630, true }, - { 186641, true }, - { 186652, true }, - { 186666, true }, - { 186682, true }, - { 186689, true }, - { 186701, true }, - { 186711, true }, - { 186723, false }, - { 186735, true }, - { 186749, true }, - { 186762, true }, - { 186772, true }, - { 186787, true }, - { 186799, true }, - { 186809, true }, - { 186822, true }, - { 186834, true }, - { 186842, true }, + { 186250, true }, + { 186258, true }, + { 186269, true }, + { 186279, true }, + { 186294, true }, + { 186304, true }, + { 186316, true }, + { 186336, true }, + { 186347, true }, + { 186358, true }, + { 186372, true }, + { 186379, true }, + { 186391, true }, + { 186401, true }, + { 186408, true }, + { 186420, false }, + { 186432, true }, + { 186446, true }, + { 186459, true }, + { 186469, true }, + { 186484, true }, + { 186496, true }, + { 186506, true }, + { 186519, true }, + { 186531, true }, + { 186541, true }, + { 186549, true }, + { 186561, true }, + { 186571, true }, + { 186579, true }, + { 186589, true }, + { 186596, true }, + { 186605, true }, + { 186625, true }, + { 186640, true }, + { 186655, true }, + { 186668, true }, + { 186680, true }, + { 186694, true }, + { 186704, false }, + { 186713, true }, + { 186729, true }, + { 186739, true }, + { 186748, true }, + { 186759, true }, + { 186770, true }, + { 186780, true }, + { 186791, true }, + { 186813, true }, + { 186828, true }, + { 186835, true }, + { 186846, true }, { 186854, true }, { 186864, true }, - { 186872, true }, - { 186882, true }, - { 186889, true }, - { 186898, true }, - { 186918, true }, - { 186933, true }, - { 186948, true }, - { 186961, true }, - { 186973, true }, - { 186987, true }, - { 186997, false }, + { 186877, false }, + { 186886, true }, + { 186900, true }, + { 186916, true }, + { 186940, true }, + { 186958, true }, + { 186969, true }, + { 186981, false }, + { 186996, true }, { 187006, true }, - { 187022, true }, - { 187032, true }, - { 187041, true }, - { 187052, true }, - { 187063, true }, - { 187073, true }, + { 187018, true }, + { 187038, true }, + { 187048, true }, + { 187059, true }, + { 187069, true }, { 187084, true }, - { 187106, true }, - { 187121, true }, + { 187098, true }, + { 187113, true }, { 187128, true }, - { 187139, true }, - { 187147, true }, - { 187157, true }, - { 187170, false }, - { 187179, true }, - { 187193, true }, - { 187209, true }, - { 187233, true }, - { 187251, true }, - { 187262, true }, - { 187274, false }, - { 187289, true }, - { 187299, true }, - { 187311, true }, - { 187331, true }, - { 187341, true }, - { 187352, true }, - { 187362, true }, - { 187377, true }, - { 187391, true }, - { 187406, true }, - { 187421, true }, - { 187433, true }, - { 187445, true }, - { 187463, true }, - { 187474, true }, - { 187484, true }, - { 187496, true }, - { 187511, true }, - { 187530, true }, - { 187545, true }, - { 187557, true }, - { 187568, true }, - { 187590, true }, + { 187140, true }, + { 187152, true }, + { 187170, true }, + { 187181, true }, + { 187191, true }, + { 187203, true }, + { 187218, true }, + { 187237, true }, + { 187252, true }, + { 187264, true }, + { 187275, true }, + { 187297, true }, + { 187313, true }, + { 187333, true }, + { 187342, true }, + { 187350, true }, + { 187358, true }, + { 187371, true }, + { 187383, true }, + { 187395, true }, + { 187403, true }, + { 187418, true }, + { 187428, true }, + { 187437, true }, + { 187446, true }, + { 187455, true }, + { 187466, true }, + { 187480, true }, + { 187492, true }, + { 187505, true }, + { 187513, false }, + { 187525, true }, + { 187539, true }, + { 187551, true }, + { 187559, true }, + { 187569, true }, + { 187578, true }, + { 187591, true }, + { 187596, true }, { 187606, true }, - { 187626, true }, - { 187635, true }, - { 187643, true }, - { 187651, true }, - { 187664, true }, - { 187676, true }, - { 187688, true }, - { 187696, true }, - { 187711, true }, - { 187721, true }, - { 187730, true }, - { 187739, true }, + { 187613, true }, + { 187620, false }, + { 187639, true }, + { 187655, true }, + { 187670, true }, + { 187686, true }, + { 187701, true }, + { 187714, true }, + { 187727, true }, + { 187735, true }, { 187748, true }, - { 187759, true }, - { 187773, true }, - { 187785, true }, - { 187798, true }, - { 187806, false }, - { 187818, true }, - { 187832, true }, + { 187761, true }, + { 187769, true }, + { 187778, true }, + { 187791, true }, + { 187803, true }, + { 187833, true }, { 187844, true }, - { 187851, true }, - { 187859, true }, - { 187869, true }, - { 187878, true }, - { 187891, true }, - { 187896, true }, - { 187906, true }, - { 187913, true }, - { 187920, false }, - { 187939, true }, - { 187955, true }, - { 187970, true }, - { 187986, true }, + { 187862, true }, + { 187886, true }, + { 187898, true }, + { 187916, true }, + { 187925, true }, + { 187936, true }, + { 187948, true }, + { 187956, true }, + { 187963, true }, + { 187971, true }, + { 187982, true }, + { 187992, true }, { 188001, true }, - { 188014, true }, - { 188027, true }, - { 188035, true }, - { 188048, true }, - { 188061, true }, - { 188069, true }, - { 188078, true }, - { 188091, true }, - { 188103, true }, - { 188133, true }, - { 188144, true }, - { 188162, true }, - { 188186, true }, - { 188198, true }, - { 188216, true }, - { 188225, true }, - { 188236, true }, - { 188248, true }, + { 188013, true }, + { 188038, true }, + { 188050, true }, + { 188072, true }, + { 188083, true }, + { 188094, true }, + { 188109, true }, + { 188127, true }, + { 188140, true }, + { 188156, true }, + { 188174, true }, + { 188184, true }, + { 188196, true }, + { 188208, true }, + { 188220, true }, + { 188231, true }, + { 188243, true }, { 188256, true }, - { 188263, true }, - { 188271, true }, - { 188282, true }, - { 188292, true }, - { 188301, true }, - { 188313, true }, - { 188338, true }, - { 188350, true }, - { 188372, true }, - { 188383, false }, - { 188398, true }, + { 188269, true }, + { 188281, true }, + { 188293, true }, + { 188304, false }, + { 188314, true }, + { 188325, true }, + { 188340, true }, + { 188353, true }, + { 188364, true }, + { 188374, true }, + { 188388, true }, + { 188400, true }, { 188416, true }, - { 188429, true }, - { 188445, true }, - { 188463, true }, - { 188473, true }, - { 188485, true }, - { 188497, true }, - { 188509, true }, - { 188520, true }, + { 188431, true }, + { 188444, true }, + { 188456, true }, + { 188469, true }, + { 188476, true }, + { 188491, true }, + { 188503, true }, + { 188512, true }, + { 188524, true }, { 188532, true }, - { 188545, true }, - { 188558, true }, - { 188570, true }, - { 188582, true }, - { 188593, false }, - { 188603, true }, - { 188614, true }, - { 188629, true }, - { 188642, true }, + { 188541, false }, + { 188549, true }, + { 188560, true }, + { 188568, true }, + { 188579, true }, + { 188590, true }, + { 188605, true }, + { 188622, false }, + { 188634, true }, { 188653, true }, - { 188663, true }, - { 188677, true }, - { 188689, true }, - { 188705, true }, - { 188720, true }, - { 188733, true }, - { 188745, true }, - { 188758, true }, - { 188765, true }, - { 188780, true }, - { 188792, true }, + { 188671, true }, + { 188683, true }, + { 188697, true }, + { 188707, true }, + { 188714, true }, + { 188725, true }, + { 188735, true }, + { 188741, true }, + { 188756, true }, + { 188771, true }, + { 188783, true }, + { 188790, true }, { 188801, true }, - { 188813, true }, - { 188821, true }, - { 188830, false }, + { 188814, true }, { 188838, true }, - { 188849, true }, - { 188857, true }, - { 188868, true }, - { 188879, true }, - { 188894, true }, - { 188911, false }, - { 188923, true }, - { 188942, true }, - { 188960, true }, - { 188972, true }, - { 188986, true }, - { 188996, true }, - { 189003, true }, - { 189014, true }, - { 189024, true }, - { 189030, true }, - { 189045, true }, - { 189060, true }, - { 189072, true }, - { 189079, true }, - { 189090, true }, + { 188845, true }, + { 188856, true }, + { 188867, true }, + { 188885, true }, + { 188898, true }, + { 188913, true }, + { 188929, true }, + { 188940, true }, + { 188956, true }, + { 188980, true }, + { 188995, true }, + { 189005, true }, + { 189013, true }, + { 189032, true }, + { 189043, true }, + { 189053, true }, + { 189068, true }, + { 189078, true }, + { 189089, true }, { 189103, true }, - { 189127, true }, + { 189117, true }, + { 189126, true }, { 189134, true }, - { 189145, true }, - { 189156, true }, - { 189174, true }, - { 189187, true }, - { 189202, true }, - { 189218, true }, - { 189229, true }, - { 189245, true }, - { 189269, true }, - { 189284, true }, - { 189294, true }, - { 189302, true }, - { 189321, true }, - { 189332, true }, - { 189342, true }, - { 189357, true }, - { 189367, true }, - { 189378, true }, - { 189392, true }, - { 189406, true }, - { 189415, true }, - { 189423, true }, - { 189433, true }, - { 189446, true }, - { 189460, true }, - { 189481, true }, - { 189488, true }, - { 189498, true }, - { 189506, true }, - { 189515, true }, - { 189528, true }, - { 189541, true }, - { 189552, true }, - { 189561, true }, - { 189571, true }, + { 189144, true }, + { 189157, true }, + { 189171, true }, + { 189192, true }, + { 189199, true }, + { 189209, true }, + { 189217, true }, + { 189226, true }, + { 189239, true }, + { 189252, true }, + { 189263, true }, + { 189272, true }, + { 189282, true }, }; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/manager/ssl/StaticHPKPins.h firefox-trunk-52.0~a1~hg20161113r322177/security/manager/ssl/StaticHPKPins.h --- firefox-trunk-52.0~a1~hg20161110r321971/security/manager/ssl/StaticHPKPins.h 2016-11-11 02:09:08.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/manager/ssl/StaticHPKPins.h 2016-11-14 02:09:25.000000000 +0000 @@ -1164,4 +1164,4 @@ static const int32_t kUnknownId = -1; -static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1487254042935000); +static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1487512969797000); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/manager/ssl/tests/unit/head_psm.js firefox-trunk-52.0~a1~hg20161113r322177/security/manager/ssl/tests/unit/head_psm.js --- firefox-trunk-52.0~a1~hg20161110r321971/security/manager/ssl/tests/unit/head_psm.js 2016-11-11 02:10:04.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/manager/ssl/tests/unit/head_psm.js 2016-11-14 02:10:32.000000000 +0000 @@ -332,15 +332,15 @@ aAfterStreamOpen, aFirstPartyDomain) { const REMOTE_PORT = 8443; - function Connection(aHost) { - this.host = aHost; + function Connection(host) { + this.host = host; let threadManager = Cc["@mozilla.org/thread-manager;1"] .getService(Ci.nsIThreadManager); this.thread = threadManager.currentThread; this.defer = Promise.defer(); let sts = Cc["@mozilla.org/network/socket-transport-service;1"] .getService(Ci.nsISocketTransportService); - this.transport = sts.createTransport(["ssl"], 1, aHost, REMOTE_PORT, null); + this.transport = sts.createTransport(["ssl"], 1, host, REMOTE_PORT, null); // See bug 1129771 - attempting to connect to [::1] when the server is // listening on 127.0.0.1 causes frequent failures on OS X 10.10. this.transport.connectionFlags |= Ci.nsISocketTransport.DISABLE_IPV6; @@ -400,11 +400,11 @@ } }; - /* Returns a promise to connect to aHost that resolves to the result of that + /* Returns a promise to connect to host that resolves to the result of that * connection */ - function connectTo(aHost) { - Services.prefs.setCharPref("network.dns.localDomains", aHost); - let connection = new Connection(aHost); + function connectTo(host) { + Services.prefs.setCharPref("network.dns.localDomains", host); + let connection = new Connection(host); return connection.go(); } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/manager/ssl/tests/unit/test_cert_blocklist.js firefox-trunk-52.0~a1~hg20161113r322177/security/manager/ssl/tests/unit/test_cert_blocklist.js --- firefox-trunk-52.0~a1~hg20161110r321971/security/manager/ssl/tests/unit/test_cert_blocklist.js 2016-11-11 02:10:05.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/manager/ssl/tests/unit/test_cert_blocklist.js 2016-11-14 02:10:32.000000000 +0000 @@ -29,11 +29,11 @@ // we need to ensure we setup revocation data before certDB, or we'll start with // no revocation.txt in the profile -var profile = do_get_profile(); +var gProfile = do_get_profile(); // Write out an empty blocklist.xml file to the profile to ensure nothing // is blocklisted by default -var blockFile = profile.clone(); +var blockFile = gProfile.clone(); blockFile.append("blocklist.xml"); var stream = Cc["@mozilla.org/network/file-output-stream;1"] .createInstance(Ci.nsIFileOutputStream); @@ -50,11 +50,11 @@ const PREF_BLOCKLIST_UPDATE_ENABLED = "services.blocklist.update_enabled"; const PREF_ONECRL_VIA_AMO = "security.onecrl.via.amo"; -var revocations = profile.clone(); -revocations.append("revocations.txt"); -if (!revocations.exists()) { +var gRevocations = gProfile.clone(); +gRevocations.append("revocations.txt"); +if (!gRevocations.exists()) { let existing = do_get_file("test_onecrl/sample_revocations.txt", false); - existing.copyTo(profile, "revocations.txt"); + existing.copyTo(gProfile, "revocations.txt"); } var certDB = Cc["@mozilla.org/security/x509certdb;1"] @@ -319,12 +319,12 @@ verify_cert(file, SEC_ERROR_UNKNOWN_ISSUER); // check that save with no further update is a no-op - let lastModified = revocations.lastModifiedTime; + let lastModified = gRevocations.lastModifiedTime; // add an already existing entry certList.revokeCertByIssuerAndSerial("YW5vdGhlciBpbWFnaW5hcnkgaXNzdWVy", "c2VyaWFsMi4="); certList.saveEntries(); - let newModified = revocations.lastModifiedTime; + let newModified = gRevocations.lastModifiedTime; equal(lastModified, newModified, "saveEntries with no modifications should not update the backing file"); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/manager/ssl/tests/unit/test_cert_keyUsage.js firefox-trunk-52.0~a1~hg20161113r322177/security/manager/ssl/tests/unit/test_cert_keyUsage.js --- firefox-trunk-52.0~a1~hg20161110r321971/security/manager/ssl/tests/unit/test_cert_keyUsage.js 2016-11-11 02:10:05.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/manager/ssl/tests/unit/test_cert_keyUsage.js 2016-11-14 02:10:33.000000000 +0000 @@ -46,12 +46,12 @@ add_task(function* () { for (let ca of caList) { addCertFromFile(certdb, "test_cert_keyUsage/" + ca + ".pem", "CTu,CTu,CTu"); - let cert = constructCertFromFile("test_cert_keyUsage/" + ca + ".pem"); - yield asyncTestCertificateUsages(certdb, cert, expectedUsagesMap[ca]); + let caCert = constructCertFromFile("test_cert_keyUsage/" + ca + ".pem"); + yield asyncTestCertificateUsages(certdb, caCert, expectedUsagesMap[ca]); for (let ee of eeList) { let eeFullName = ee + "-" + ca; - let cert = constructCertFromFile("test_cert_keyUsage/" + eeFullName + ".pem"); - yield asyncTestCertificateUsages(certdb, cert, expectedUsagesMap[eeFullName]); + let eeCert = constructCertFromFile("test_cert_keyUsage/" + eeFullName + ".pem"); + yield asyncTestCertificateUsages(certdb, eeCert, expectedUsagesMap[eeFullName]); } } }); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/manager/ssl/tests/unit/test_weak_crypto.js firefox-trunk-52.0~a1~hg20161113r322177/security/manager/ssl/tests/unit/test_weak_crypto.js --- firefox-trunk-52.0~a1~hg20161110r321971/security/manager/ssl/tests/unit/test_weak_crypto.js 2016-11-11 02:11:07.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/manager/ssl/tests/unit/test_weak_crypto.js 2016-11-14 02:12:14.000000000 +0000 @@ -69,8 +69,8 @@ equal(status.macLength, rc4only ? 160 : 128, "Using MAC of expected length"); input.asyncWait({ - onInputStreamReady: function(input) { - NetUtil.asyncCopy(input, output); + onInputStreamReady: function(streamReadyInput) { + NetUtil.asyncCopy(streamReadyInput, output); } }, 0, 0, Services.tm.currentThread); }, @@ -115,15 +115,17 @@ let handler = { - onTransportStatus: function(transport, status) { + onTransportStatus: function(unused, status) { if (status === Ci.nsISocketTransport.STATUS_CONNECTED_TO) { output.asyncWait(handler, 0, 0, Services.tm.currentThread); } }, - onInputStreamReady: function(input) { + onInputStreamReady: function(streamReadyInput) { try { - let data = NetUtil.readInputStreamToString(input, input.available()); + let data = + NetUtil.readInputStreamToString(streamReadyInput, + streamReadyInput.available()); equal(Cr.NS_OK, expectedResult, "Connection should succeed"); equal(data, "HELLO", "Echoed data received"); } catch (e) { @@ -132,25 +134,25 @@ deferred.reject(e); } } - input.close(); + streamReadyInput.close(); output.close(); deferred.resolve(); }, - onOutputStreamReady: function(output) { + onOutputStreamReady: function(streamReadyOutput) { try { try { - output.write("HELLO", 5); + streamReadyOutput.write("HELLO", 5); } catch (e) { if (e.result == Cr.NS_BASE_STREAM_WOULD_BLOCK) { - output.asyncWait(handler, 0, 0, Services.tm.currentThread); + streamReadyOutput.asyncWait(handler, 0, 0, Services.tm.currentThread); return; } if (e.result != Cr.NS_OK) { ok((e.result === expectedResult) || (options.allowReset && (e.result === Cr.NS_ERROR_NET_RESET)), "Actual and expected connection result should match"); - output.close(); + streamReadyOutput.close(); deferred.resolve(); return; } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/automation/taskcluster/graph/src/extend.js firefox-trunk-52.0~a1~hg20161113r322177/security/nss/automation/taskcluster/graph/src/extend.js --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/automation/taskcluster/graph/src/extend.js 2016-11-11 02:11:08.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/automation/taskcluster/graph/src/extend.js 2016-11-14 02:12:17.000000000 +0000 @@ -40,6 +40,11 @@ } } + // GYP builds with -Ddisable_libpkix=1 by default. + if (task.collection == "gyp" && task.tests == "chains") { + return false; + } + return true; }); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/coreconf/config.gypi firefox-trunk-52.0~a1~hg20161113r322177/security/nss/coreconf/config.gypi --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/coreconf/config.gypi 2016-11-11 02:13:39.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/coreconf/config.gypi 2016-11-14 02:15:04.000000000 +0000 @@ -90,7 +90,7 @@ 'disable_tests%': 0, 'disable_chachapoly%': 0, 'disable_dbm%': 0, - 'disable_libpkix%': 0, + 'disable_libpkix%': 1, 'disable_werror%': 0, 'mozilla_client%': 0, 'moz_fold_libs%': 0, diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/coreconf/coreconf.dep firefox-trunk-52.0~a1~hg20161113r322177/security/nss/coreconf/coreconf.dep --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/coreconf/coreconf.dep 2016-11-11 02:13:39.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/coreconf/coreconf.dep 2016-11-14 02:15:04.000000000 +0000 @@ -10,4 +10,3 @@ */ #error "Do not include this header file." - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/gtests/ssl_gtest/databuffer.h firefox-trunk-52.0~a1~hg20161113r322177/security/nss/gtests/ssl_gtest/databuffer.h --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/gtests/ssl_gtest/databuffer.h 2016-11-11 02:13:41.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/gtests/ssl_gtest/databuffer.h 2016-11-14 02:15:07.000000000 +0000 @@ -132,7 +132,9 @@ data_ = new uint8_t[len_ ? len_ : 1]; // The head of the old. - Write(0, old_value, std::min(old_len, index)); + if (old_value) { + Write(0, old_value, std::min(old_len, index)); + } // Maybe a gap. if (index > old_len) { memset(old_value + index, 0, index - old_len); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/gtests/ssl_gtest/libssl_internals.c firefox-trunk-52.0~a1~hg20161113r322177/security/nss/gtests/ssl_gtest/libssl_internals.c --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/gtests/ssl_gtest/libssl_internals.c 2016-11-11 02:13:41.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/gtests/ssl_gtest/libssl_internals.c 2016-11-14 02:15:07.000000000 +0000 @@ -179,12 +179,12 @@ return SECFailure; } - ss->ssl3.nextProtoState = SSL_NEXT_PROTO_EARLY_VALUE; - if (ss->ssl3.nextProto.data) { - SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE); + ss->xtnData.nextProtoState = SSL_NEXT_PROTO_EARLY_VALUE; + if (ss->xtnData.nextProto.data) { + SECITEM_FreeItem(&ss->xtnData.nextProto, PR_FALSE); } - if (!SECITEM_AllocItem(NULL, &ss->ssl3.nextProto, len)) return SECFailure; - PORT_Memcpy(ss->ssl3.nextProto.data, data, len); + if (!SECITEM_AllocItem(NULL, &ss->xtnData.nextProto, len)) return SECFailure; + PORT_Memcpy(ss->xtnData.nextProto.data, data, len); return SECSuccess; } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc firefox-trunk-52.0~a1~hg20161113r322177/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc 2016-11-11 02:13:41.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc 2016-11-14 02:15:07.000000000 +0000 @@ -154,6 +154,25 @@ extension->Write(3, namelen, 2); extension->Write(5, reinterpret_cast(name), namelen); } + + void HrrThenRemoveExtensionsTest(SSLExtensionType type, PRInt32 client_error, + PRInt32 server_error) { + static const std::vector client_groups = { + ssl_grp_ec_secp384r1, ssl_grp_ec_curve25519}; + static const std::vector server_groups = { + ssl_grp_ec_curve25519, ssl_grp_ec_secp384r1}; + client_->ConfigNamedGroups(client_groups); + server_->ConfigNamedGroups(server_groups); + EnsureTlsSetup(); + client_->StartConnect(); + server_->StartConnect(); + client_->Handshake(); // Send ClientHello + server_->Handshake(); // Send HRR. + client_->SetPacketFilter(new TlsExtensionDropper(type)); + Handshake(); + client_->CheckErrorCode(client_error); + server_->CheckErrorCode(server_error); + } }; class TlsExtensionTestDtls : public TlsExtensionTestBase, @@ -772,6 +791,24 @@ #endif } +TEST_P(TlsExtensionTest13, HrrThenRemoveSignatureAlgorithms) { + HrrThenRemoveExtensionsTest(ssl_signature_algorithms_xtn, + SSL_ERROR_MISSING_EXTENSION_ALERT, + SSL_ERROR_MISSING_SIGNATURE_ALGORITHMS_EXTENSION); +} + +TEST_P(TlsExtensionTest13, HrrThenRemoveKeyShare) { + HrrThenRemoveExtensionsTest(ssl_tls13_key_share_xtn, + SSL_ERROR_ILLEGAL_PARAMETER_ALERT, + SSL_ERROR_BAD_2ND_CLIENT_HELLO); +} + +TEST_P(TlsExtensionTest13, HrrThenRemoveSupportedGroups) { + HrrThenRemoveExtensionsTest(ssl_supported_groups_xtn, + SSL_ERROR_MISSING_EXTENSION_ALERT, + SSL_ERROR_MISSING_SUPPORTED_GROUPS_EXTENSION); +} + TEST_P(TlsExtensionTest13, EmptyVersionList) { static const uint8_t ext[] = {0x00, 0x00}; ConnectWithBogusVersionList(ext, sizeof(ext)); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/gtests/ssl_gtest/ssl_fuzz_unittest.cc firefox-trunk-52.0~a1~hg20161113r322177/security/nss/gtests/ssl_gtest/ssl_fuzz_unittest.cc --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/gtests/ssl_gtest/ssl_fuzz_unittest.cc 2016-11-11 02:13:41.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/gtests/ssl_gtest/ssl_fuzz_unittest.cc 2016-11-14 02:15:07.000000000 +0000 @@ -2,8 +2,10 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "blapi.h" #include "ssl.h" #include "sslimpl.h" +#include "tls_connect.h" #include "gtest/gtest.h" @@ -13,6 +15,17 @@ class TlsFuzzTest : public ::testing::Test {}; +void ResetState() { + // Clear the list of RSA blinding params. + BL_Cleanup(); + + // Reinit the list of RSA blinding params. + EXPECT_EQ(SECSuccess, BL_Init()); + + // Reset the RNG state. + EXPECT_EQ(SECSuccess, RNG_ResetForFuzzing()); +} + // Ensure that ssl_Time() returns a constant value. TEST_F(TlsFuzzTest, Fuzz_SSL_Time_Constant) { PRInt32 now = ssl_Time(); @@ -20,5 +33,68 @@ EXPECT_EQ(ssl_Time(), now); } +// Check that due to the deterministic PRNG we derive +// the same master secret in two consecutive TLS sessions. +TEST_P(TlsConnectGeneric, Fuzz_DeterministicExporter) { + const char kLabel[] = "label"; + std::vector out1(32), out2(32); + + ConfigureSessionCache(RESUME_NONE, RESUME_NONE); + DisableECDHEServerKeyReuse(); + + ResetState(); + Connect(); + + // Export a key derived from the MS and nonces. + SECStatus rv = + SSL_ExportKeyingMaterial(client_->ssl_fd(), kLabel, strlen(kLabel), false, + NULL, 0, out1.data(), out1.size()); + EXPECT_EQ(SECSuccess, rv); + + Reset(); + ConfigureSessionCache(RESUME_NONE, RESUME_NONE); + DisableECDHEServerKeyReuse(); + + ResetState(); + Connect(); + + // Export another key derived from the MS and nonces. + rv = SSL_ExportKeyingMaterial(client_->ssl_fd(), kLabel, strlen(kLabel), + false, NULL, 0, out2.data(), out2.size()); + EXPECT_EQ(SECSuccess, rv); + + // The two exported keys should be the same. + EXPECT_EQ(out1, out2); +} + +// Check that due to the deterministic RNG two consecutive +// TLS sessions will have the exact same transcript. +TEST_P(TlsConnectGeneric, Fuzz_DeterministicTranscript) { + // Connect a few times and compare the transcripts byte-by-byte. + DataBuffer last; + for (size_t i = 0; i < 5; i++) { + Reset(); + ConfigureSessionCache(RESUME_NONE, RESUME_NONE); + DisableECDHEServerKeyReuse(); + + DataBuffer buffer; + client_->SetPacketFilter(new TlsConversationRecorder(buffer)); + server_->SetPacketFilter(new TlsConversationRecorder(buffer)); + + ResetState(); + Connect(); + + // Ensure the filters go away before |buffer| does. + client_->SetPacketFilter(nullptr); + server_->SetPacketFilter(nullptr); + + if (last.len() > 0) { + EXPECT_EQ(last, buffer); + } + + last = buffer; + } +} + #endif } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/gtests/ssl_gtest/ssl_gtest.gyp firefox-trunk-52.0~a1~hg20161113r322177/security/nss/gtests/ssl_gtest/ssl_gtest.gyp --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/gtests/ssl_gtest/ssl_gtest.gyp 2016-11-11 02:13:41.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/gtests/ssl_gtest/ssl_gtest.gyp 2016-11-14 02:15:07.000000000 +0000 @@ -60,7 +60,7 @@ '<(DEPTH)/lib/pki/pki.gyp:nsspki', '<(DEPTH)/lib/dev/dev.gyp:nssdev', '<(DEPTH)/lib/base/base.gyp:nssb', - '<(DEPTH)/lib/freebl/freebl.gyp:freebl', + '<(DEPTH)/lib/freebl/freebl.gyp:<(freebl_name)', '<(DEPTH)/lib/nss/nss.gyp:nss_static', '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap', '<(DEPTH)/lib/certhigh/certhigh.gyp:certhi', diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/gtests/ssl_gtest/tls_agent.cc firefox-trunk-52.0~a1~hg20161113r322177/security/nss/gtests/ssl_gtest/tls_agent.cc --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/gtests/ssl_gtest/tls_agent.cc 2016-11-11 02:13:41.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/gtests/ssl_gtest/tls_agent.cc 2016-11-14 02:15:07.000000000 +0000 @@ -819,6 +819,12 @@ EXPECT_EQ(SECSuccess, rv); } +void TlsAgent::DisableECDHEServerKeyReuse() { + ASSERT_EQ(TlsAgent::SERVER, role_); + SECStatus rv = SSL_OptionSet(ssl_fd_, SSL_REUSE_SERVER_ECDHE_KEY, PR_FALSE); + EXPECT_EQ(SECSuccess, rv); +} + static const std::string kTlsRolesAllArr[] = {"CLIENT", "SERVER"}; ::testing::internal::ParamGenerator TlsAgentTestBase::kTlsRolesAll = ::testing::ValuesIn(kTlsRolesAllArr); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/gtests/ssl_gtest/tls_agent.h firefox-trunk-52.0~a1~hg20161113r322177/security/nss/gtests/ssl_gtest/tls_agent.h --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/gtests/ssl_gtest/tls_agent.h 2016-11-11 02:13:41.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/gtests/ssl_gtest/tls_agent.h 2016-11-14 02:15:07.000000000 +0000 @@ -150,6 +150,7 @@ void SetDowngradeCheckVersion(uint16_t version); void CheckSecretsDestroyed(); void ConfigNamedGroups(const std::vector& groups); + void DisableECDHEServerKeyReuse(); const std::string& name() const { return name_; } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/gtests/ssl_gtest/tls_connect.cc firefox-trunk-52.0~a1~hg20161113r322177/security/nss/gtests/ssl_gtest/tls_connect.cc --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/gtests/ssl_gtest/tls_connect.cc 2016-11-11 02:13:41.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/gtests/ssl_gtest/tls_connect.cc 2016-11-14 02:15:07.000000000 +0000 @@ -595,6 +595,10 @@ server_->CheckEarlyDataAccepted(expect_early_data_accepted_); } +void TlsConnectTestBase::DisableECDHEServerKeyReuse() { + server_->DisableECDHEServerKeyReuse(); +} + TlsConnectGeneric::TlsConnectGeneric() : TlsConnectTestBase(std::get<0>(GetParam()), std::get<1>(GetParam())) {} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/gtests/ssl_gtest/tls_connect.h firefox-trunk-52.0~a1~hg20161113r322177/security/nss/gtests/ssl_gtest/tls_connect.h --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/gtests/ssl_gtest/tls_connect.h 2016-11-11 02:13:41.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/gtests/ssl_gtest/tls_connect.h 2016-11-14 02:15:07.000000000 +0000 @@ -107,6 +107,7 @@ void Receive(size_t amount); void ExpectExtendedMasterSecret(bool expected); void ExpectEarlyDataAccepted(bool expected); + void DisableECDHEServerKeyReuse(); protected: Mode mode_; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/gtests/ssl_gtest/tls_filter.cc firefox-trunk-52.0~a1~hg20161113r322177/security/nss/gtests/ssl_gtest/tls_filter.cc --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/gtests/ssl_gtest/tls_filter.cc 2016-11-11 02:13:41.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/gtests/ssl_gtest/tls_filter.cc 2016-11-14 02:15:07.000000000 +0000 @@ -243,6 +243,12 @@ return KEEP; } +PacketFilter::Action TlsConversationRecorder::FilterRecord( + const RecordHeader& header, const DataBuffer& input, DataBuffer* output) { + buffer_.Append(input); + return KEEP; +} + PacketFilter::Action TlsAlertRecorder::FilterRecord(const RecordHeader& header, const DataBuffer& input, DataBuffer* output) { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/gtests/ssl_gtest/tls_filter.h firefox-trunk-52.0~a1~hg20161113r322177/security/nss/gtests/ssl_gtest/tls_filter.h --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/gtests/ssl_gtest/tls_filter.h 2016-11-11 02:13:41.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/gtests/ssl_gtest/tls_filter.h 2016-11-14 02:15:07.000000000 +0000 @@ -162,6 +162,19 @@ DataBuffer buffer_; }; +// Make a copy of the complete conversation. +class TlsConversationRecorder : public TlsRecordFilter { + public: + TlsConversationRecorder(DataBuffer& buffer) : buffer_(buffer) {} + + virtual PacketFilter::Action FilterRecord(const RecordHeader& header, + const DataBuffer& input, + DataBuffer* output); + + private: + DataBuffer& buffer_; +}; + // Records an alert. If an alert has already been recorded, it won't save the // new alert unless the old alert is a warning and the new one is fatal. class TlsAlertRecorder : public TlsRecordFilter { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/ssl3con.c firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/ssl3con.c --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/ssl3con.c 2016-11-11 02:16:19.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/ssl3con.c 2016-11-14 02:18:58.000000000 +0000 @@ -19,6 +19,8 @@ #include "sslimpl.h" #include "sslproto.h" #include "sslerr.h" +#include "ssl3ext.h" +#include "ssl3exthandle.h" #include "prtime.h" #include "prinrval.h" #include "prerror.h" @@ -759,7 +761,8 @@ /* Find the cipher configuration struct associate with suite */ /* XXX This does a linear search. A binary search would be better. */ static ssl3CipherSuiteCfg * -ssl_LookupCipherSuiteCfg(ssl3CipherSuite suite, ssl3CipherSuiteCfg *suites) +ssl_LookupCipherSuiteCfgMutable(ssl3CipherSuite suite, + ssl3CipherSuiteCfg *suites) { int i; @@ -772,6 +775,13 @@ return NULL; } +const static ssl3CipherSuiteCfg * +ssl_LookupCipherSuiteCfg(ssl3CipherSuite suite, const ssl3CipherSuiteCfg *suites) +{ + return ssl_LookupCipherSuiteCfgMutable(suite, + CONST_CAST(ssl3CipherSuiteCfg, suites)); +} + static PRBool ssl_NamedGroupTypeEnabled(const sslSocket *ss, SSLKEAType keaType) { @@ -803,7 +813,7 @@ * must have included an FFDHE group. peerSupportsFfdheGroups * is set to true in ssl_HandleSupportedGroupsXtn(). */ if (ss->opt.requireDHENamedGroups && - !ss->ssl3.hs.peerSupportsFfdheGroups) { + !ss->xtnData.peerSupportsFfdheGroups) { return PR_FALSE; } @@ -813,7 +823,7 @@ * 3. This isn't TLS 1.3. * 4. The weak group is enabled. */ if (!ss->opt.requireDHENamedGroups && - !ss->ssl3.hs.peerSupportsFfdheGroups && + !ss->xtnData.peerSupportsFfdheGroups && ss->version < SSL_LIBRARY_VERSION_TLS_1_3 && ss->ssl3.dheWeakGroupEnabled) { return PR_TRUE; @@ -4996,7 +5006,7 @@ PORT_Assert(IS_DTLS(ss) || type != client_hello_retransmit); SECITEM_FreeItem(&ss->ssl3.hs.newSessionTicket.ticket, PR_FALSE); ss->ssl3.hs.receivedNewSessionTicket = PR_FALSE; - PORT_Memset(&ss->xtnData, 0, sizeof(TLSExtensionData)); + ssl3_ResetExtensionData(&ss->xtnData); /* How many suites does our PKCS11 support (regardless of policy)? */ num_suites = ssl3_config_match_init(ss); @@ -6131,27 +6141,27 @@ /* DH shares need to be padded to the size of their prime. Some implementations * require this. TLS 1.3 also requires this. */ SECStatus -ssl_AppendPaddedDHKeyShare(sslSocket *ss, SECKEYPublicKey *pubKey, +ssl_AppendPaddedDHKeyShare(const sslSocket *ss, const SECKEYPublicKey *pubKey, PRBool appendLength) { SECStatus rv; unsigned int pad = pubKey->u.dh.prime.len - pubKey->u.dh.publicValue.len; if (appendLength) { - rv = ssl3_AppendHandshakeNumber(ss, pubKey->u.dh.prime.len, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, pubKey->u.dh.prime.len, 2); if (rv != SECSuccess) { return rv; } } while (pad) { - rv = ssl3_AppendHandshakeNumber(ss, 0, 1); + rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 1); if (rv != SECSuccess) { return rv; } --pad; } - rv = ssl3_AppendHandshake(ss, pubKey->u.dh.publicValue.data, - pubKey->u.dh.publicValue.len); + rv = ssl3_ExtAppendHandshake(ss, pubKey->u.dh.publicValue.data, + pubKey->u.dh.publicValue.len); if (rv != SECSuccess) { return rv; } @@ -6196,7 +6206,7 @@ /* If we require named groups, we will have already validated the group * in ssl_HandleDHServerKeyExchange() */ PORT_Assert(!ss->opt.requireDHENamedGroups && - !ss->ssl3.hs.peerSupportsFfdheGroups); + !ss->xtnData.peerSupportsFfdheGroups); customParams.name = ssl_grp_ffdhe_custom; customParams.prime.data = svrPubKey->u.dh.prime.data; @@ -6431,8 +6441,8 @@ /* Sets error code, if needed. */ return ssl_PickSignatureScheme(ss, keyPair->pubKey, keyPair->privKey, - ss->ssl3.hs.clientSigSchemes, - ss->ssl3.hs.numClientSigScheme, + ss->xtnData.clientSigSchemes, + ss->xtnData.numClientSigScheme, PR_FALSE /* requireSha1 */); } @@ -7333,7 +7343,7 @@ } SECStatus -ssl_ParseSignatureSchemes(sslSocket *ss, PLArenaPool *arena, +ssl_ParseSignatureSchemes(const sslSocket *ss, PLArenaPool *arena, SSLSignatureScheme **schemesOut, unsigned int *numSchemesOut, unsigned char **b, unsigned int *len) @@ -7344,13 +7354,13 @@ unsigned int numSchemes = 0; unsigned int max; - rv = ssl3_ConsumeHandshakeVariable(ss, &buf, 2, b, len); + rv = ssl3_ExtConsumeHandshakeVariable(ss, &buf, 2, b, len); if (rv != SECSuccess) { return SECFailure; } /* An empty or odd-length value is invalid. */ if (buf.len == 0 || (buf.len & 1) != 0) { - (void)SSL3_SendAlert(ss, alert_fatal, decode_error); + ssl3_ExtSendAlert(ss, alert_fatal, decode_error); return SECFailure; } @@ -7363,13 +7373,13 @@ schemes = PORT_ZNewArray(SSLSignatureScheme, max); } if (!schemes) { - (void)SSL3_SendAlert(ss, alert_fatal, internal_error); + ssl3_ExtSendAlert(ss, alert_fatal, internal_error); return SECFailure; } for (; max; --max) { PRInt32 tmp; - tmp = ssl3_ConsumeHandshakeNumber(ss, 2, &buf.data, &buf.len); + tmp = ssl3_ExtConsumeHandshakeNumber(ss, 2, &buf.data, &buf.len); if (tmp < 0) { PORT_Assert(0); PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); @@ -8157,8 +8167,8 @@ /* Need to tell the client that application has picked * the name from the offered list and reconfigured the socket. */ - ssl3_RegisterServerHelloExtensionSender(ss, ssl_server_name_xtn, - ssl3_SendServerNameXtn); + ssl3_RegisterExtensionSender(ss, &ss->xtnData, ssl_server_name_xtn, + ssl3_SendServerNameXtn); } else { /* Callback returned index outside of the boundary. */ PORT_Assert((unsigned int)ret < ss->xtnData.sniNameArrSize); @@ -8285,7 +8295,7 @@ /* We might be starting session renegotiation in which case we should * clear previous state. */ - PORT_Memset(&ss->xtnData, 0, sizeof(TLSExtensionData)); + ssl3_ResetExtensionData(&ss->xtnData); ss->statelessResume = PR_FALSE; if (IS_DTLS(ss)) { @@ -8943,9 +8953,9 @@ */ if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn) && ssl3_KEASupportsTickets(ss->ssl3.hs.kea_def)) { - ssl3_RegisterServerHelloExtensionSender(ss, - ssl_session_ticket_xtn, - ssl3_SendSessionTicketXtn); + ssl3_RegisterExtensionSender(ss, &ss->xtnData, + ssl_session_ticket_xtn, + ssl3_SendSessionTicketXtn); } rv = ssl3_ServerCallSNICallback(ss); @@ -9041,7 +9051,7 @@ ssl_GetSSL3HandshakeLock(ss); - PORT_Memset(&ss->xtnData, 0, sizeof(TLSExtensionData)); + ssl3_ResetExtensionData(&ss->xtnData); version = (buffer[1] << 8) | buffer[2]; if (version < SSL_LIBRARY_VERSION_3_0) { @@ -9540,7 +9550,7 @@ } SECStatus -ssl3_EncodeSigAlgs(sslSocket *ss, PRUint8 *buf, unsigned maxLen, PRUint32 *len) +ssl3_EncodeSigAlgs(const sslSocket *ss, PRUint8 *buf, unsigned maxLen, PRUint32 *len) { unsigned int i; PRUint8 *p = buf; @@ -11108,24 +11118,24 @@ int padding_len; static const unsigned char padding[32] = { 0 }; - if (ss->ssl3.nextProto.len == 0 || - ss->ssl3.nextProtoState == SSL_NEXT_PROTO_SELECTED) { + if (ss->xtnData.nextProto.len == 0 || + ss->xtnData.nextProtoState == SSL_NEXT_PROTO_SELECTED) { return SECSuccess; } PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); - padding_len = 32 - ((ss->ssl3.nextProto.len + 2) % 32); + padding_len = 32 - ((ss->xtnData.nextProto.len + 2) % 32); - rv = ssl3_AppendHandshakeHeader(ss, next_proto, ss->ssl3.nextProto.len + + rv = ssl3_AppendHandshakeHeader(ss, next_proto, ss->xtnData.nextProto.len + 2 + padding_len); if (rv != SECSuccess) { return rv; /* error code set by AppendHandshakeHeader */ } - rv = ssl3_AppendHandshakeVariable(ss, ss->ssl3.nextProto.data, - ss->ssl3.nextProto.len, 1); + rv = ssl3_AppendHandshakeVariable(ss, ss->xtnData.nextProto.data, + ss->xtnData.nextProto.len, 1); if (rv != SECSuccess) { return rv; /* error code set by AppendHandshake */ } @@ -11535,10 +11545,10 @@ sid->certType.authType = ssl_auth_null; } - if (ss->ssl3.nextProtoState != SSL_NEXT_PROTO_NO_SUPPORT && - ss->ssl3.nextProto.data) { + if (ss->xtnData.nextProtoState != SSL_NEXT_PROTO_NO_SUPPORT && + ss->xtnData.nextProto.data) { if (SECITEM_CopyItem( - NULL, &sid->u.ssl3.alpnSelection, &ss->ssl3.nextProto) != SECSuccess) { + NULL, &sid->u.ssl3.alpnSelection, &ss->xtnData.nextProto) != SECSuccess) { return SECFailure; /* error already set. */ } } @@ -12841,10 +12851,9 @@ ss->ssl3.hs.sendingSCSV = PR_FALSE; ss->ssl3.hs.preliminaryInfo = 0; - ss->ssl3.hs.peerSupportsFfdheGroups = PR_FALSE; ss->ssl3.hs.ws = (ss->sec.isServer) ? wait_client_hello : wait_server_hello; - PORT_Memset(&ss->xtnData, 0, sizeof(TLSExtensionData)); + ssl3_ResetExtensionData(&ss->xtnData); PR_INIT_CLIST(&ss->ssl3.hs.remoteExtensions); if (IS_DTLS(ss)) { ss->ssl3.hs.sendMessageSeq = 0; @@ -12857,7 +12866,6 @@ } ss->ssl3.hs.clientHelloHash = NULL; - PR_INIT_CLIST(&ss->ssl3.hs.remoteKeyShares); ss->ssl3.hs.currentSecret = NULL; ss->ssl3.hs.resumptionPsk = NULL; ss->ssl3.hs.resumptionContext = nullItem; @@ -12892,7 +12900,7 @@ { ssl3CipherSuiteCfg *suite; - suite = ssl_LookupCipherSuiteCfg(which, cipherSuites); + suite = ssl_LookupCipherSuiteCfgMutable(which, cipherSuites); if (suite == NULL) { return SECFailure; /* err code was set by ssl_LookupCipherSuiteCfg */ } @@ -12904,7 +12912,7 @@ SECStatus ssl3_GetPolicy(ssl3CipherSuite which, PRInt32 *oPolicy) { - ssl3CipherSuiteCfg *suite; + const ssl3CipherSuiteCfg *suite; PRInt32 policy; SECStatus rv; @@ -12926,7 +12934,7 @@ { ssl3CipherSuiteCfg *suite; - suite = ssl_LookupCipherSuiteCfg(which, cipherSuites); + suite = ssl_LookupCipherSuiteCfgMutable(which, cipherSuites); if (suite == NULL) { return SECFailure; /* err code was set by ssl_LookupCipherSuiteCfg */ } @@ -12938,7 +12946,7 @@ SECStatus ssl3_CipherPrefGetDefault(ssl3CipherSuite which, PRBool *enabled) { - ssl3CipherSuiteCfg *suite; + const ssl3CipherSuiteCfg *suite; PRBool pref; SECStatus rv; @@ -12959,7 +12967,7 @@ { ssl3CipherSuiteCfg *suite; - suite = ssl_LookupCipherSuiteCfg(which, ss->cipherSuites); + suite = ssl_LookupCipherSuiteCfgMutable(which, ss->cipherSuites); if (suite == NULL) { return SECFailure; /* err code was set by ssl_LookupCipherSuiteCfg */ } @@ -12968,9 +12976,9 @@ } SECStatus -ssl3_CipherPrefGet(sslSocket *ss, ssl3CipherSuite which, PRBool *enabled) +ssl3_CipherPrefGet(const sslSocket *ss, ssl3CipherSuite which, PRBool *enabled) { - ssl3CipherSuiteCfg *suite; + const ssl3CipherSuiteCfg *suite; PRBool pref; SECStatus rv; @@ -13197,9 +13205,6 @@ if (ss->ssl3.hs.sha) { PK11_DestroyContext(ss->ssl3.hs.sha, PR_TRUE); } - if (ss->ssl3.hs.clientSigSchemes) { - PORT_Free(ss->ssl3.hs.clientSigSchemes); - } if (ss->ssl3.hs.messages.buf) { sslBuffer_Clear(&ss->ssl3.hs.messages); } @@ -13229,9 +13234,7 @@ /* Destroy remote extensions */ ssl3_DestroyRemoteExtensions(&ss->ssl3.hs.remoteExtensions); - - /* Destroy TLS 1.3 handshake shares */ - tls13_DestroyKeyShares(&ss->ssl3.hs.remoteKeyShares); + ssl3_ResetExtensionData(&ss->xtnData); /* Destroy the stored hash. */ if (ss->ssl3.hs.clientHelloHash) { @@ -13267,7 +13270,7 @@ ss->ssl3.initialized = PR_FALSE; - SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE); + SECITEM_FreeItem(&ss->xtnData.nextProto, PR_FALSE); } #define MAP_NULL(x) (((x) != 0) ? (x) : SEC_OID_NULL_CIPHER) diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/ssl3ecc.c firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/ssl3ecc.c --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/ssl3ecc.c 2016-11-11 02:16:19.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/ssl3ecc.c 2016-11-14 02:18:58.000000000 +0000 @@ -18,6 +18,7 @@ #include "sslimpl.h" #include "sslproto.h" #include "sslerr.h" +#include "ssl3ext.h" #include "prtime.h" #include "prinrval.h" #include "prerror.h" @@ -269,14 +270,14 @@ /* This function encodes the key_exchange field in * the KeyShareEntry structure. */ SECStatus -tls13_EncodeECDHEKeyShareKEX(sslSocket *ss, const SECKEYPublicKey *pubKey) +tls13_EncodeECDHEKeyShareKEX(const sslSocket *ss, const SECKEYPublicKey *pubKey) { PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); PORT_Assert(pubKey->keyType == ecKey); - return ssl3_AppendHandshake(ss, pubKey->u.ec.publicValue.data, - pubKey->u.ec.publicValue.len); + return ssl3_ExtAppendHandshake(ss, pubKey->u.ec.publicValue.data, + pubKey->u.ec.publicValue.len); } /* @@ -860,7 +861,7 @@ /* Order(N^2). Yuk. */ static PRBool -ssl_IsSuiteEnabled(sslSocket *ss, const ssl3CipherSuite *list) +ssl_IsSuiteEnabled(const sslSocket *ss, const ssl3CipherSuite *list) { const ssl3CipherSuite *suite; @@ -877,7 +878,7 @@ /* Ask: is ANY ECC cipher suite enabled on this socket? */ PRBool -ssl_IsECCEnabled(sslSocket *ss) +ssl_IsECCEnabled(const sslSocket *ss) { PK11SlotInfo *slot; @@ -893,14 +894,16 @@ } PRBool -ssl_IsDHEEnabled(sslSocket *ss) +ssl_IsDHEEnabled(const sslSocket *ss) { return ssl_IsSuiteEnabled(ss, ssl_dhe_suites); } /* Send our Supported Groups extension. */ PRInt32 -ssl_SendSupportedGroupsXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes) +ssl_SendSupportedGroupsXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + PRBool append, PRUint32 maxBytes) { PRInt32 extension_length; unsigned char enabledGroups[64]; @@ -960,18 +963,17 @@ if (append) { SECStatus rv; - rv = ssl3_AppendHandshakeNumber(ss, ssl_supported_groups_xtn, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_supported_groups_xtn, 2); if (rv != SECSuccess) return -1; - rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 4, 2); if (rv != SECSuccess) return -1; - rv = ssl3_AppendHandshakeVariable(ss, enabledGroups, - enabledGroupsLen, 2); + rv = ssl3_ExtAppendHandshakeVariable(ss, enabledGroups, + enabledGroupsLen, 2); if (rv != SECSuccess) return -1; if (!ss->sec.isServer) { - TLSExtensionData *xtnData = &ss->xtnData; xtnData->advertised[xtnData->numAdvertised++] = ssl_supported_groups_xtn; } @@ -984,7 +986,8 @@ */ PRInt32 ssl3_SendSupportedPointFormatsXtn( - sslSocket *ss, + const sslSocket *ss, + TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { @@ -1003,138 +1006,13 @@ (ss->sec.isServer && ss->version >= SSL_LIBRARY_VERSION_TLS_1_3)) return 0; if (append && maxBytes >= (sizeof ecPtFmt)) { - SECStatus rv = ssl3_AppendHandshake(ss, ecPtFmt, (sizeof ecPtFmt)); + SECStatus rv = ssl3_ExtAppendHandshake(ss, ecPtFmt, (sizeof ecPtFmt)); if (rv != SECSuccess) return -1; if (!ss->sec.isServer) { - TLSExtensionData *xtnData = &ss->xtnData; xtnData->advertised[xtnData->numAdvertised++] = ssl_ec_point_formats_xtn; } } return sizeof(ecPtFmt); } - -/* Just make sure that the remote client supports uncompressed points, - * Since that is all we support. Disable ECC cipher suites if it doesn't. - */ -SECStatus -ssl3_HandleSupportedPointFormatsXtn(sslSocket *ss, PRUint16 ex_type, - SECItem *data) -{ - int i; - - if (data->len < 2 || data->len > 255 || !data->data || - data->len != (unsigned int)data->data[0] + 1) { - return ssl3_DecodeError(ss); - } - for (i = data->len; --i > 0;) { - if (data->data[i] == 0) { - /* indicate that we should send a reply */ - SECStatus rv; - rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type, - &ssl3_SendSupportedPointFormatsXtn); - return rv; - } - } - - /* Poor client doesn't support uncompressed points. */ - PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE); - return SECFailure; -} - -static SECStatus -ssl_UpdateSupportedGroups(sslSocket *ss, SECItem *data) -{ - PRInt32 list_len; - unsigned int i; - const sslNamedGroupDef *enabled[SSL_NAMED_GROUP_COUNT] = { 0 }; - PORT_Assert(SSL_NAMED_GROUP_COUNT == PR_ARRAY_SIZE(enabled)); - - if (!data->data || data->len < 4) { - (void)ssl3_DecodeError(ss); - return SECFailure; - } - - /* get the length of elliptic_curve_list */ - list_len = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len); - if (list_len < 0 || data->len != list_len || (data->len % 2) != 0) { - (void)ssl3_DecodeError(ss); - return SECFailure; - } - - /* disable all groups and remember the enabled groups */ - for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) { - enabled[i] = ss->namedGroupPreferences[i]; - ss->namedGroupPreferences[i] = NULL; - } - - /* Read groups from data and enable if in |enabled| */ - while (data->len) { - const sslNamedGroupDef *group; - PRInt32 curve_name = - ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len); - if (curve_name < 0) { - return SECFailure; /* fatal alert already sent */ - } - group = ssl_LookupNamedGroup(curve_name); - if (group) { - for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) { - if (enabled[i] && group == enabled[i]) { - ss->namedGroupPreferences[i] = enabled[i]; - break; - } - } - } - - /* "Codepoints in the NamedCurve registry with a high byte of 0x01 (that - * is, between 256 and 511 inclusive) are set aside for FFDHE groups," - * -- https://tools.ietf.org/html/draft-ietf-tls-negotiated-ff-dhe-10 - */ - if ((curve_name & 0xff00) == 0x0100) { - ss->ssl3.hs.peerSupportsFfdheGroups = PR_TRUE; - } - } - - /* Note: if ss->opt.requireDHENamedGroups is set, we disable DHE cipher - * suites, but we do that in ssl3_config_match(). */ - if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3 && - !ss->opt.requireDHENamedGroups && !ss->ssl3.hs.peerSupportsFfdheGroups) { - /* If we don't require that DHE use named groups, and no FFDHE was - * included, we pretend that they support all the FFDHE groups we do. */ - for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) { - if (enabled[i] && enabled[i]->keaType == ssl_kea_dh) { - ss->namedGroupPreferences[i] = enabled[i]; - } - } - } - - return SECSuccess; -} - -/* Ensure that the curve in our server cert is one of the ones supported - * by the remote client, and disable all ECC cipher suites if not. - */ -SECStatus -ssl_HandleSupportedGroupsXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data) -{ - SECStatus rv; - - rv = ssl_UpdateSupportedGroups(ss, data); - if (rv != SECSuccess) - return SECFailure; - - /* TLS 1.3 permits the server to send this extension so make it so. */ - if (ss->sec.isServer && ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) { - rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type, - &ssl_SendSupportedGroupsXtn); - if (rv != SECSuccess) { - return SECFailure; /* error already set. */ - } - } - - /* Remember that we negotiated this extension. */ - ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; - - return SECSuccess; -} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/ssl3ext.c firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/ssl3ext.c --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/ssl3ext.c 2016-11-11 02:16:19.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/ssl3ext.c 2016-11-14 02:18:58.000000000 +0000 @@ -130,17 +130,17 @@ } PRBool -ssl3_ExtensionNegotiated(sslSocket *ss, PRUint16 ex_type) +ssl3_ExtensionNegotiated(const sslSocket *ss, PRUint16 ex_type) { - TLSExtensionData *xtnData = &ss->xtnData; + const TLSExtensionData *xtnData = &ss->xtnData; return arrayContainsExtension(xtnData->negotiated, xtnData->numNegotiated, ex_type); } PRBool -ssl3_ClientExtensionAdvertised(sslSocket *ss, PRUint16 ex_type) +ssl3_ClientExtensionAdvertised(const sslSocket *ss, PRUint16 ex_type) { - TLSExtensionData *xtnData = &ss->xtnData; + const TLSExtensionData *xtnData = &ss->xtnData; return arrayContainsExtension(xtnData->advertised, xtnData->numAdvertised, ex_type); } @@ -297,7 +297,8 @@ if (handler->ex_type == extension->type) { SECStatus rv; - rv = (*handler->ex_handler)(ss, (PRUint16)extension->type, + rv = (*handler->ex_handler)(ss, &ss->xtnData, + (PRUint16)extension->type, &extension->data); if (rv != SECSuccess) { if (!ss->ssl3.fatalAlertSent) { @@ -336,20 +337,22 @@ /* Add a callback function to the table of senders of server hello extensions. */ SECStatus -ssl3_RegisterServerHelloExtensionSender(sslSocket *ss, PRUint16 ex_type, - ssl3HelloExtensionSenderFunc cb) +ssl3_RegisterExtensionSender(const sslSocket *ss, + TLSExtensionData *xtnData, + PRUint16 ex_type, + ssl3HelloExtensionSenderFunc cb) { int i; ssl3HelloExtensionSender *sender; if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { - sender = &ss->xtnData.serverHelloSenders[0]; + sender = &xtnData->serverHelloSenders[0]; } else { if (tls13_ExtensionAllowed(ex_type, server_hello)) { PORT_Assert(!tls13_ExtensionAllowed(ex_type, encrypted_extensions)); - sender = &ss->xtnData.serverHelloSenders[0]; + sender = &xtnData->serverHelloSenders[0]; } else { PORT_Assert(tls13_ExtensionAllowed(ex_type, encrypted_extensions)); - sender = &ss->xtnData.encryptedExtensionsSenders[0]; + sender = &xtnData->encryptedExtensionsSenders[0]; } } @@ -389,7 +392,7 @@ for (i = 0; i < SSL_MAX_EXTENSIONS; ++i, ++sender) { if (sender->ex_sender) { - PRInt32 extLen = (*sender->ex_sender)(ss, append, maxBytes); + PRInt32 extLen = (*sender->ex_sender)(ss, &ss->xtnData, append, maxBytes); if (extLen < 0) return -1; maxBytes -= extLen; @@ -410,3 +413,86 @@ PORT_Free(cur_p); } } + +/* Initialize the extension data block. */ +void +ssl3_InitExtensionData(TLSExtensionData *xtnData) +{ + /* Set things up to the right starting state. */ + PORT_Memset(xtnData, 0, sizeof(*xtnData)); + xtnData->peerSupportsFfdheGroups = PR_FALSE; + PR_INIT_CLIST(&xtnData->remoteKeyShares); +} + +/* Free everything that has been allocated and then reset back to + * the starting state. */ +void +ssl3_ResetExtensionData(TLSExtensionData *xtnData) +{ + /* Clean up. */ + ssl3_FreeSniNameArray(xtnData); + PORT_Free(xtnData->clientSigSchemes); + SECITEM_FreeItem(&xtnData->nextProto, PR_FALSE); + tls13_DestroyKeyShares(&xtnData->remoteKeyShares); + + /* Now reinit. */ + ssl3_InitExtensionData(xtnData); +} + +/* Thunks to let extension handlers operate on const sslSocket* objects. */ +SECStatus +ssl3_ExtAppendHandshake(const sslSocket *ss, const void *void_src, + PRInt32 bytes) +{ + return ssl3_AppendHandshake((sslSocket *)ss, void_src, bytes); +} + +SECStatus +ssl3_ExtAppendHandshakeNumber(const sslSocket *ss, PRInt32 num, + PRInt32 lenSize) +{ + return ssl3_AppendHandshakeNumber((sslSocket *)ss, num, lenSize); +} + +SECStatus +ssl3_ExtAppendHandshakeVariable(const sslSocket *ss, + const SSL3Opaque *src, PRInt32 bytes, + PRInt32 lenSize) +{ + return ssl3_AppendHandshakeVariable((sslSocket *)ss, src, bytes, lenSize); +} + +void +ssl3_ExtSendAlert(const sslSocket *ss, SSL3AlertLevel level, + SSL3AlertDescription desc) +{ + (void)SSL3_SendAlert((sslSocket *)ss, level, desc); +} + +void +ssl3_ExtDecodeError(const sslSocket *ss) +{ + (void)ssl3_DecodeError((sslSocket *)ss); +} + +SECStatus +ssl3_ExtConsumeHandshake(const sslSocket *ss, void *v, PRInt32 bytes, + SSL3Opaque **b, PRUint32 *length) +{ + return ssl3_ConsumeHandshake((sslSocket *)ss, v, bytes, b, length); +} + +PRInt32 +ssl3_ExtConsumeHandshakeNumber(const sslSocket *ss, PRInt32 bytes, + SSL3Opaque **b, PRUint32 *length) +{ + return ssl3_ConsumeHandshakeNumber((sslSocket *)ss, bytes, b, length); +} + +SECStatus +ssl3_ExtConsumeHandshakeVariable(const sslSocket *ss, SECItem *i, + PRInt32 bytes, SSL3Opaque **b, + PRUint32 *length) +{ + return ssl3_ConsumeHandshakeVariable((sslSocket *)ss, i, bytes, b, length); +} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/ssl3ext.h firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/ssl3ext.h --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/ssl3ext.h 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/ssl3ext.h 2016-11-14 02:18:58.000000000 +0000 @@ -0,0 +1,155 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is PRIVATE to SSL. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef __ssl3ext_h_ +#define __ssl3ext_h_ + +typedef enum { + sni_nametype_hostname +} SNINameType; +typedef struct TLSExtensionDataStr TLSExtensionData; + +/* registerable callback function that either appends extension to buffer + * or returns length of data that it would have appended. + */ +typedef PRInt32 (*ssl3HelloExtensionSenderFunc)(const sslSocket *ss, + TLSExtensionData *xtnData, + PRBool append, + PRUint32 maxBytes); + +/* registerable callback function that handles a received extension, + * of the given type. + */ +typedef SECStatus (*ssl3ExtensionHandlerFunc)(const sslSocket *ss, + TLSExtensionData *xtnData, + PRUint16 ex_type, + SECItem *data); + +/* row in a table of hello extension senders */ +typedef struct { + PRInt32 ex_type; + ssl3HelloExtensionSenderFunc ex_sender; +} ssl3HelloExtensionSender; + +/* row in a table of hello extension handlers */ +typedef struct { + PRInt32 ex_type; + ssl3ExtensionHandlerFunc ex_handler; +} ssl3ExtensionHandler; + +struct TLSExtensionDataStr { + /* registered callbacks that send server hello extensions */ + ssl3HelloExtensionSender serverHelloSenders[SSL_MAX_EXTENSIONS]; + ssl3HelloExtensionSender encryptedExtensionsSenders[SSL_MAX_EXTENSIONS]; + + /* Keep track of the extensions that are negotiated. */ + PRUint16 numAdvertised; + PRUint16 numNegotiated; + PRUint16 advertised[SSL_MAX_EXTENSIONS]; + PRUint16 negotiated[SSL_MAX_EXTENSIONS]; + + /* SessionTicket Extension related data. */ + PRBool ticketTimestampVerified; + PRBool emptySessionTicket; + PRBool sentSessionTicketInClientHello; + SECItem psk_ke_modes; + SECItem psk_auth_modes; + PRUint32 ticket_age_add; + PRBool ticket_age_add_found; + + /* SNI Extension related data + * Names data is not coppied from the input buffer. It can not be + * used outside the scope where input buffer is defined and that + * is beyond ssl3_HandleClientHello function. */ + SECItem *sniNameArr; + PRUint32 sniNameArrSize; + + /* Signed Certificate Timestamps extracted from the TLS extension. + * (client only). + * This container holds a temporary pointer to the extension data, + * until a session structure (the sec.ci.sid of an sslSocket) is setup + * that can hold a permanent copy of the data + * (in sec.ci.sid.u.ssl3.signedCertTimestamps). + * The data pointed to by this structure is neither explicitly allocated + * nor copied: the pointer points to the handshake message buffer and is + * only valid in the scope of ssl3_HandleServerHello. + */ + SECItem signedCertTimestamps; + + PRBool peerSupportsFfdheGroups; /* if the peer supports named ffdhe groups */ + + /* clientSigAndHash contains the contents of the signature_algorithms + * extension (if any) from the client. This is only valid for TLS 1.2 + * or later. */ + SSLSignatureScheme *clientSigSchemes; + unsigned int numClientSigScheme; + + /* In a client: if the server supports Next Protocol Negotiation, then + * this is the protocol that was negotiated. + */ + SECItem nextProto; + SSLNextProtoState nextProtoState; + + PRUint16 dtlsSRTPCipherSuite; /* 0 if not selected */ + + PRCList remoteKeyShares; /* The other side's public keys (TLS 1.3) */ +}; + +typedef struct TLSExtensionStr { + PRCList link; /* The linked list link */ + PRUint16 type; /* Extension type */ + SECItem data; /* Pointers into the handshake data. */ +} TLSExtension; + +SECStatus ssl3_HandleExtensions(sslSocket *ss, + SSL3Opaque **b, PRUint32 *length, + SSL3HandshakeType handshakeMessage); +SECStatus ssl3_ParseExtensions(sslSocket *ss, + SSL3Opaque **b, PRUint32 *length); +SECStatus ssl3_HandleParsedExtensions(sslSocket *ss, + SSL3HandshakeType handshakeMessage); +TLSExtension *ssl3_FindExtension(sslSocket *ss, + SSLExtensionType extension_type); +void ssl3_DestroyRemoteExtensions(PRCList *list); +void ssl3_InitExtensionData(TLSExtensionData *xtnData); +void ssl3_ResetExtensionData(TLSExtensionData *xtnData); + +PRBool ssl3_ExtensionNegotiated(const sslSocket *ss, PRUint16 ex_type); +PRBool ssl3_ClientExtensionAdvertised(const sslSocket *ss, PRUint16 ex_type); + +SECStatus ssl3_RegisterExtensionSender(const sslSocket *ss, + TLSExtensionData *xtnData, + PRUint16 ex_type, + ssl3HelloExtensionSenderFunc cb); +PRInt32 ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes, + const ssl3HelloExtensionSender *sender); + +unsigned int ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength); +PRInt32 ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen, + PRUint32 maxBytes); + +/* Thunks to let us operate on const sslSocket* objects. */ +SECStatus ssl3_ExtAppendHandshake(const sslSocket *ss, const void *void_src, + PRInt32 bytes); +SECStatus ssl3_ExtAppendHandshakeNumber(const sslSocket *ss, PRInt32 num, + PRInt32 lenSize); +SECStatus ssl3_ExtAppendHandshakeVariable(const sslSocket *ss, + const SSL3Opaque *src, PRInt32 bytes, + PRInt32 lenSize); +void ssl3_ExtSendAlert(const sslSocket *ss, SSL3AlertLevel level, + SSL3AlertDescription desc); +void ssl3_ExtDecodeError(const sslSocket *ss); +SECStatus ssl3_ExtConsumeHandshake(const sslSocket *ss, void *v, PRInt32 bytes, + SSL3Opaque **b, PRUint32 *length); +PRInt32 ssl3_ExtConsumeHandshakeNumber(const sslSocket *ss, PRInt32 bytes, + SSL3Opaque **b, PRUint32 *length); +SECStatus ssl3_ExtConsumeHandshakeVariable(const sslSocket *ss, SECItem *i, + PRInt32 bytes, SSL3Opaque **b, + PRUint32 *length); + +#endif diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/ssl3exthandle.c firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/ssl3exthandle.c --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/ssl3exthandle.c 2016-11-11 02:16:19.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/ssl3exthandle.c 2016-11-14 02:18:58.000000000 +0000 @@ -12,6 +12,7 @@ #include "pk11pub.h" #include "blapit.h" #include "prinit.h" +#include "ssl3ext.h" #include "ssl3exthandle.h" #include "tls13exthandle.h" /* For tls13_ServerSendStatusRequestXtn. */ @@ -30,6 +31,7 @@ PRInt32 lenSize); static SECStatus ssl3_GetSessionTicketKeys(sslSocket *ss, PK11SymKey **aes_key, PK11SymKey **mac_key); +static SECStatus ssl3_ConsumeFromItem(SECItem *item, unsigned char **buf, PRUint32 bytes); /* * Write bytes. Using this function means the SECItem structure @@ -150,12 +152,13 @@ *mac_key = session_ticket_mac_key; return SECSuccess; } + /* Format an SNI extension, using the name from the socket's URL, * unless that name is a dotted decimal string. * Used by client and server. */ PRInt32 -ssl3_SendServerNameXtn(sslSocket *ss, PRBool append, +ssl3_SendServerNameXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { SECStatus rv; @@ -176,27 +179,26 @@ len = PORT_Strlen(ss->url); if (append && maxBytes >= len + 9) { /* extension_type */ - rv = ssl3_AppendHandshakeNumber(ss, ssl_server_name_xtn, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_server_name_xtn, 2); if (rv != SECSuccess) return -1; /* length of extension_data */ - rv = ssl3_AppendHandshakeNumber(ss, len + 5, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, len + 5, 2); if (rv != SECSuccess) return -1; /* length of server_name_list */ - rv = ssl3_AppendHandshakeNumber(ss, len + 3, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, len + 3, 2); if (rv != SECSuccess) return -1; /* Name Type (sni_host_name) */ - rv = ssl3_AppendHandshake(ss, "\0", 1); + rv = ssl3_ExtAppendHandshake(ss, "\0", 1); if (rv != SECSuccess) return -1; /* HostName (length and value) */ - rv = ssl3_AppendHandshakeVariable(ss, (PRUint8 *)ss->url, len, 2); + rv = ssl3_ExtAppendHandshakeVariable(ss, (PRUint8 *)ss->url, len, 2); if (rv != SECSuccess) return -1; if (!ss->sec.isServer) { - TLSExtensionData *xtnData = &ss->xtnData; xtnData->advertised[xtnData->numAdvertised++] = ssl_server_name_xtn; } @@ -205,11 +207,11 @@ } /* Server side */ if (append && maxBytes >= 4) { - rv = ssl3_AppendHandshakeNumber(ss, ssl_server_name_xtn, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_server_name_xtn, 2); if (rv != SECSuccess) return -1; /* length of extension_data */ - rv = ssl3_AppendHandshakeNumber(ss, 0, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2); if (rv != SECSuccess) return -1; } @@ -218,10 +220,9 @@ /* Handle an incoming SNI extension. */ SECStatus -ssl3_HandleServerNameXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data) +ssl3_HandleServerNameXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { SECItem *names = NULL; - TLSExtensionData *xtnData = &ss->xtnData; PRInt32 listLenBytes = 0; if (!ss->sec.isServer) { @@ -235,7 +236,7 @@ } /* length of server_name_list */ - listLenBytes = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len); + listLenBytes = ssl3_ExtConsumeHandshakeNumber(ss, 2, &data->data, &data->len); if (listLenBytes < 0) { goto loser; /* alert already sent */ } @@ -250,14 +251,14 @@ PRInt32 type; /* Read Name Type. */ - type = ssl3_ConsumeHandshakeNumber(ss, 1, &data->data, &data->len); + type = ssl3_ExtConsumeHandshakeNumber(ss, 1, &data->data, &data->len); if (type < 0) { /* i.e., SECFailure cast to PRint32 */ /* alert sent in ConsumeHandshakeNumber */ goto loser; } /* Read ServerName (length and value). */ - rv = ssl3_ConsumeHandshakeVariable(ss, &tmp, 2, &data->data, &data->len); + rv = ssl3_ExtConsumeHandshakeVariable(ss, &tmp, 2, &data->data, &data->len); if (rv != SECSuccess) { goto loser; } @@ -296,7 +297,7 @@ return SECSuccess; alert_loser: - (void)ssl3_DecodeError(ss); + ssl3_ExtDecodeError(ss); loser: if (names) { PORT_Free(names); @@ -329,7 +330,8 @@ */ PRInt32 ssl3_SendSessionTicketXtn( - sslSocket *ss, + const sslSocket *ss, + TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { @@ -368,7 +370,7 @@ session_ticket = &sid->u.ssl3.locked.sessionTicket; if (session_ticket->ticket.data) { - if (ss->xtnData.ticketTimestampVerified) { + if (xtnData->ticketTimestampVerified) { extension_length += session_ticket->ticket.len; } else if (!append && (session_ticket->ticket_lifetime_hint == 0 || @@ -376,7 +378,7 @@ session_ticket->received_timestamp > ssl_Time()))) { extension_length += session_ticket->ticket.len; - ss->xtnData.ticketTimestampVerified = PR_TRUE; + xtnData->ticketTimestampVerified = PR_TRUE; } } } @@ -388,23 +390,22 @@ if (append) { SECStatus rv; /* extension_type */ - rv = ssl3_AppendHandshakeNumber(ss, ssl_session_ticket_xtn, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_session_ticket_xtn, 2); if (rv != SECSuccess) goto loser; if (session_ticket && session_ticket->ticket.data && - ss->xtnData.ticketTimestampVerified) { - rv = ssl3_AppendHandshakeVariable(ss, session_ticket->ticket.data, - session_ticket->ticket.len, 2); - ss->xtnData.ticketTimestampVerified = PR_FALSE; - ss->xtnData.sentSessionTicketInClientHello = PR_TRUE; + xtnData->ticketTimestampVerified) { + rv = ssl3_ExtAppendHandshakeVariable(ss, session_ticket->ticket.data, + session_ticket->ticket.len, 2); + xtnData->ticketTimestampVerified = PR_FALSE; + xtnData->sentSessionTicketInClientHello = PR_TRUE; } else { - rv = ssl3_AppendHandshakeNumber(ss, 0, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2); } if (rv != SECSuccess) goto loser; if (!ss->sec.isServer) { - TLSExtensionData *xtnData = &ss->xtnData; xtnData->advertised[xtnData->numAdvertised++] = ssl_session_ticket_xtn; } @@ -412,7 +413,7 @@ return extension_length; loser: - ss->xtnData.ticketTimestampVerified = PR_FALSE; + xtnData->ticketTimestampVerified = PR_FALSE; return -1; } @@ -444,7 +445,7 @@ /* handle an incoming Next Protocol Negotiation extension. */ SECStatus -ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type, +ssl3_ServerHandleNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { if (ss->firstHsDone || data->len != 0) { @@ -453,7 +454,7 @@ return SECFailure; } - ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ex_type; /* TODO: server side NPN support would require calling * ssl3_RegisterServerHelloExtensionSender here in order to echo the @@ -486,7 +487,8 @@ /* protocol selection handler for ALPN (server side) and NPN (client side) */ static SECStatus -ssl3_SelectAppProtocol(sslSocket *ss, PRUint16 ex_type, SECItem *data) +ssl3_SelectAppProtocol(const sslSocket *ss, TLSExtensionData *xtnData, + PRUint16 ex_type, SECItem *data) { SECStatus rv; unsigned char resultBuffer[255]; @@ -494,7 +496,7 @@ rv = ssl3_ValidateNextProtoNego(data->data, data->len); if (rv != SECSuccess) { - (void)SSL3_SendAlert(ss, alert_fatal, decode_error); + ssl3_ExtSendAlert(ss, alert_fatal, decode_error); PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); return rv; } @@ -509,7 +511,7 @@ result.data, &result.len, sizeof(resultBuffer)); if (rv != SECSuccess) { /* Expect callback to call PORT_SetError() */ - (void)SSL3_SendAlert(ss, alert_fatal, internal_error); + ssl3_ExtSendAlert(ss, alert_fatal, internal_error); return SECFailure; } @@ -521,24 +523,24 @@ return SECFailure; } - SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE); + SECITEM_FreeItem(&xtnData->nextProto, PR_FALSE); if (ex_type == ssl_app_layer_protocol_xtn && - ss->ssl3.nextProtoState != SSL_NEXT_PROTO_NEGOTIATED) { + xtnData->nextProtoState != SSL_NEXT_PROTO_NEGOTIATED) { /* The callback might say OK, but then it picks a default value - one * that was not listed. That's OK for NPN, but not ALPN. */ - (void)SSL3_SendAlert(ss, alert_fatal, no_application_protocol); + ssl3_ExtSendAlert(ss, alert_fatal, no_application_protocol); PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL); return SECFailure; } - ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; - return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &result); + xtnData->negotiated[xtnData->numNegotiated++] = ex_type; + return SECITEM_CopyItem(NULL, &xtnData->nextProto, &result); } /* handle an incoming ALPN extension at the server */ SECStatus -ssl3_ServerHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data) +ssl3_ServerHandleAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { int count; SECStatus rv; @@ -547,16 +549,16 @@ * despite it being permitted by the spec. */ if (ss->firstHsDone || data->len == 0) { /* Clients MUST send a non-empty ALPN extension. */ - (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter); + ssl3_ExtSendAlert(ss, alert_fatal, illegal_parameter); PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); return SECFailure; } /* Unlike NPN, ALPN has extra redundant length information so that * the extension is the same in both ClientHello and ServerHello. */ - count = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len); + count = ssl3_ExtConsumeHandshakeNumber(ss, 2, &data->data, &data->len); if (count != data->len) { - (void)ssl3_DecodeError(ss); + ssl3_ExtDecodeError(ss); return SECFailure; } @@ -565,17 +567,17 @@ return SECSuccess; } - rv = ssl3_SelectAppProtocol(ss, ex_type, data); + rv = ssl3_SelectAppProtocol(ss, xtnData, ex_type, data); if (rv != SECSuccess) { return rv; } /* prepare to send back a response, if we negotiated */ - if (ss->ssl3.nextProtoState == SSL_NEXT_PROTO_NEGOTIATED) { - rv = ssl3_RegisterServerHelloExtensionSender( - ss, ex_type, ssl3_ServerSendAppProtoXtn); + if (xtnData->nextProtoState == SSL_NEXT_PROTO_NEGOTIATED) { + rv = ssl3_RegisterExtensionSender( + ss, xtnData, ex_type, ssl3_ServerSendAppProtoXtn); if (rv != SECSuccess) { - (void)SSL3_SendAlert(ss, alert_fatal, internal_error); + ssl3_ExtSendAlert(ss, alert_fatal, internal_error); PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return rv; } @@ -584,7 +586,7 @@ } SECStatus -ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type, +ssl3_ClientHandleNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { PORT_Assert(!ss->firstHsDone); @@ -596,7 +598,7 @@ * we've negotiated NPN then we're required to send the NPN handshake * message. Thus, these two extensions cannot both be negotiated on the * same connection. */ - (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter); + ssl3_ExtSendAlert(ss, alert_fatal, illegal_parameter); PORT_SetError(SSL_ERROR_BAD_SERVER); return SECFailure; } @@ -607,16 +609,16 @@ * we sent the ClientHello and now. */ if (!ss->nextProtoCallback) { PORT_Assert(0); - (void)SSL3_SendAlert(ss, alert_fatal, internal_error); + ssl3_ExtSendAlert(ss, alert_fatal, internal_error); PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_NO_CALLBACK); return SECFailure; } - return ssl3_SelectAppProtocol(ss, ex_type, data); + return ssl3_SelectAppProtocol(ss, xtnData, ex_type, data); } SECStatus -ssl3_ClientHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data) +ssl3_ClientHandleAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { SECStatus rv; PRInt32 list_len; @@ -632,36 +634,36 @@ * uint8 len; // where len >= 1 * uint8 protocol_name[len]; */ if (data->len < 4 || data->len > 2 + 1 + 255) { - (void)SSL3_SendAlert(ss, alert_fatal, decode_error); + ssl3_ExtSendAlert(ss, alert_fatal, decode_error); PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); return SECFailure; } - list_len = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len); + list_len = ssl3_ExtConsumeHandshakeNumber(ss, 2, &data->data, &data->len); /* The list has to be the entire extension. */ if (list_len != data->len) { - (void)SSL3_SendAlert(ss, alert_fatal, decode_error); + ssl3_ExtSendAlert(ss, alert_fatal, decode_error); PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); return SECFailure; } - rv = ssl3_ConsumeHandshakeVariable(ss, &protocol_name, 1, - &data->data, &data->len); + rv = ssl3_ExtConsumeHandshakeVariable(ss, &protocol_name, 1, + &data->data, &data->len); /* The list must have exactly one value. */ if (rv != SECSuccess || data->len != 0) { - (void)SSL3_SendAlert(ss, alert_fatal, decode_error); + ssl3_ExtSendAlert(ss, alert_fatal, decode_error); PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); return SECFailure; } - SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE); - ss->ssl3.nextProtoState = SSL_NEXT_PROTO_SELECTED; - ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; - return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &protocol_name); + SECITEM_FreeItem(&xtnData->nextProto, PR_FALSE); + xtnData->nextProtoState = SSL_NEXT_PROTO_SELECTED; + xtnData->negotiated[xtnData->numNegotiated++] = ex_type; + return SECITEM_CopyItem(NULL, &xtnData->nextProto, &protocol_name); } PRInt32 -ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append, +ssl3_ClientSendNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { PRInt32 extension_length; @@ -678,13 +680,13 @@ } if (append) { SECStatus rv; - rv = ssl3_AppendHandshakeNumber(ss, ssl_next_proto_nego_xtn, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_next_proto_nego_xtn, 2); if (rv != SECSuccess) goto loser; - rv = ssl3_AppendHandshakeNumber(ss, 0, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2); if (rv != SECSuccess) goto loser; - ss->xtnData.advertised[ss->xtnData.numAdvertised++] = + xtnData->advertised[xtnData->numAdvertised++] = ssl_next_proto_nego_xtn; } @@ -695,7 +697,7 @@ } PRInt32 -ssl3_ClientSendAppProtoXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes) +ssl3_ClientSendAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { PRInt32 extension_length; unsigned char *alpn_protos = NULL; @@ -736,21 +738,21 @@ } } - rv = ssl3_AppendHandshakeNumber(ss, ssl_app_layer_protocol_xtn, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_app_layer_protocol_xtn, 2); if (rv != SECSuccess) { goto loser; } - rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 4, 2); if (rv != SECSuccess) { goto loser; } - rv = ssl3_AppendHandshakeVariable(ss, alpn_protos, len, 2); + rv = ssl3_ExtAppendHandshakeVariable(ss, alpn_protos, len, 2); PORT_Free(alpn_protos); alpn_protos = NULL; if (rv != SECSuccess) { goto loser; } - ss->xtnData.advertised[ss->xtnData.numAdvertised++] = + xtnData->advertised[xtnData->numAdvertised++] = ssl_app_layer_protocol_xtn; } @@ -764,40 +766,40 @@ } PRInt32 -ssl3_ServerSendAppProtoXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes) +ssl3_ServerSendAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { PRInt32 extension_length; /* we're in over our heads if any of these fail */ PORT_Assert(ss->opt.enableALPN); - PORT_Assert(ss->ssl3.nextProto.data); - PORT_Assert(ss->ssl3.nextProto.len > 0); - PORT_Assert(ss->ssl3.nextProtoState == SSL_NEXT_PROTO_NEGOTIATED); + PORT_Assert(xtnData->nextProto.data); + PORT_Assert(xtnData->nextProto.len > 0); + PORT_Assert(xtnData->nextProtoState == SSL_NEXT_PROTO_NEGOTIATED); PORT_Assert(!ss->firstHsDone); extension_length = 2 /* extension type */ + 2 /* extension length */ + 2 /* protocol name list */ + 1 /* name length */ + - ss->ssl3.nextProto.len; + xtnData->nextProto.len; if (maxBytes < (PRUint32)extension_length) { return 0; } if (append) { SECStatus rv; - rv = ssl3_AppendHandshakeNumber(ss, ssl_app_layer_protocol_xtn, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_app_layer_protocol_xtn, 2); if (rv != SECSuccess) { return -1; } - rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 4, 2); if (rv != SECSuccess) { return -1; } - rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.nextProto.len + 1, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, xtnData->nextProto.len + 1, 2); if (rv != SECSuccess) { return -1; } - rv = ssl3_AppendHandshakeVariable(ss, ss->ssl3.nextProto.data, - ss->ssl3.nextProto.len, 1); + rv = ssl3_ExtAppendHandshakeVariable(ss, xtnData->nextProto.data, + xtnData->nextProto.len, 1); if (rv != SECSuccess) { return -1; } @@ -807,7 +809,7 @@ } SECStatus -ssl3_ServerHandleStatusRequestXtn(sslSocket *ss, PRUint16 ex_type, +ssl3_ServerHandleStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { ssl3HelloExtensionSenderFunc sender; @@ -815,19 +817,20 @@ PORT_Assert(ss->sec.isServer); /* remember that we got this extension. */ - ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ex_type; if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) { sender = tls13_ServerSendStatusRequestXtn; } else { sender = ssl3_ServerSendStatusRequestXtn; } - return ssl3_RegisterServerHelloExtensionSender(ss, ex_type, sender); + return ssl3_RegisterExtensionSender(ss, xtnData, ex_type, sender); } PRInt32 ssl3_ServerSendStatusRequestXtn( - sslSocket *ss, + const sslSocket *ss, + TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { @@ -846,11 +849,11 @@ } if (append) { /* extension_type */ - rv = ssl3_AppendHandshakeNumber(ss, ssl_cert_status_xtn, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_cert_status_xtn, 2); if (rv != SECSuccess) return -1; /* length of extension_data */ - rv = ssl3_AppendHandshakeNumber(ss, 0, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2); if (rv != SECSuccess) return -1; /* The certificate status data is sent in ssl3_SendCertificateStatus. */ @@ -862,7 +865,7 @@ /* ssl3_ClientSendStatusRequestXtn builds the status_request extension on the * client side. See RFC 6066 section 8. */ PRInt32 -ssl3_ClientSendStatusRequestXtn(sslSocket *ss, PRBool append, +ssl3_ClientSendStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { PRInt32 extension_length; @@ -884,55 +887,54 @@ } if (append) { SECStatus rv; - TLSExtensionData *xtnData; /* extension_type */ - rv = ssl3_AppendHandshakeNumber(ss, ssl_cert_status_xtn, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_cert_status_xtn, 2); if (rv != SECSuccess) return -1; - rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 4, 2); if (rv != SECSuccess) return -1; - rv = ssl3_AppendHandshakeNumber(ss, 1 /* status_type ocsp */, 1); + rv = ssl3_ExtAppendHandshakeNumber(ss, 1 /* status_type ocsp */, 1); if (rv != SECSuccess) return -1; /* A zero length responder_id_list means that the responders are * implicitly known to the server. */ - rv = ssl3_AppendHandshakeNumber(ss, 0, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2); if (rv != SECSuccess) return -1; /* A zero length request_extensions means that there are no extensions. * Specifically, we don't set the id-pkix-ocsp-nonce extension. This * means that the server can replay a cached OCSP response to us. */ - rv = ssl3_AppendHandshakeNumber(ss, 0, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2); if (rv != SECSuccess) return -1; - xtnData = &ss->xtnData; xtnData->advertised[xtnData->numAdvertised++] = ssl_cert_status_xtn; } return extension_length; } SECStatus -ssl3_ClientHandleStatusRequestXtn(sslSocket *ss, PRUint16 ex_type, +ssl3_ClientHandleStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { /* In TLS 1.3, the extension carries the OCSP response. */ if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) { SECStatus rv; - rv = ssl_ReadCertificateStatus(ss, data->data, data->len); + rv = ssl_ReadCertificateStatus(CONST_CAST(sslSocket, ss), + data->data, data->len); if (rv != SECSuccess) { return SECFailure; /* code already set */ } } else if (data->len != 0) { - (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter); + ssl3_ExtSendAlert(ss, alert_fatal, illegal_parameter); PORT_SetError(SSL_ERROR_RX_MALFORMED_SERVER_HELLO); return SECFailure; } /* Keep track of negotiated extensions. */ - ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ex_type; return SECSuccess; } @@ -1037,9 +1039,9 @@ srvNameLen = 2 + srvName->len; /* len bytes + name len */ } - if (ss->ssl3.nextProtoState != SSL_NEXT_PROTO_NO_SUPPORT && - ss->ssl3.nextProto.data) { - alpnSelection = ss->ssl3.nextProto; + if (ss->xtnData.nextProtoState != SSL_NEXT_PROTO_NO_SUPPORT && + ss->xtnData.nextProto.data) { + alpnSelection = ss->xtnData.nextProto; } ciphertext_length = @@ -1324,7 +1326,7 @@ * message is expected during the handshake. */ SECStatus -ssl3_ClientHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type, +ssl3_ClientHandleSessionTicketXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { if (data->len != 0) { @@ -1332,7 +1334,7 @@ } /* Keep track of negotiated extensions. */ - ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ex_type; return SECSuccess; } @@ -1497,51 +1499,51 @@ } /* Read ticket_version and reject if the version is wrong */ - temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len); + temp = ssl3_ExtConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len); if (temp != TLS_EX_SESS_TICKET_VERSION) goto no_ticket; parsed_session_ticket->ticket_version = (SSL3ProtocolVersion)temp; /* Read SSLVersion. */ - temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len); + temp = ssl3_ExtConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len); if (temp < 0) goto no_ticket; parsed_session_ticket->ssl_version = (SSL3ProtocolVersion)temp; /* Read cipher_suite. */ - temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len); + temp = ssl3_ExtConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len); if (temp < 0) goto no_ticket; parsed_session_ticket->cipher_suite = (ssl3CipherSuite)temp; /* Read compression_method. */ - temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); + temp = ssl3_ExtConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); if (temp < 0) goto no_ticket; parsed_session_ticket->compression_method = (SSLCompressionMethod)temp; /* Read cipher spec parameters. */ - temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); + temp = ssl3_ExtConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); if (temp < 0) goto no_ticket; parsed_session_ticket->authType = (SSLAuthType)temp; - temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len); + temp = ssl3_ExtConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len); if (temp < 0) goto no_ticket; parsed_session_ticket->authKeyBits = (PRUint32)temp; - temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); + temp = ssl3_ExtConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); if (temp < 0) goto no_ticket; parsed_session_ticket->keaType = (SSLKEAType)temp; - temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len); + temp = ssl3_ExtConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len); if (temp < 0) goto no_ticket; parsed_session_ticket->keaKeyBits = (PRUint32)temp; /* Read certificate slot */ parsed_session_ticket->certType.authType = parsed_session_ticket->authType; - temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); + temp = ssl3_ExtConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); if (temp < 0) goto no_ticket; switch (parsed_session_ticket->authType) { @@ -1560,17 +1562,17 @@ } /* Read wrapped master_secret. */ - temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); + temp = ssl3_ExtConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); if (temp < 0) goto no_ticket; parsed_session_ticket->ms_is_wrapped = (PRBool)temp; - temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len); + temp = ssl3_ExtConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len); if (temp < 0) goto no_ticket; parsed_session_ticket->msWrapMech = (CK_MECHANISM_TYPE)temp; - temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len); + temp = ssl3_ExtConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len); if (temp < 0) goto no_ticket; parsed_session_ticket->ms_length = (PRUint16)temp; @@ -1588,7 +1590,7 @@ buffer_len -= parsed_session_ticket->ms_length; /* Read client_identity */ - temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); + temp = ssl3_ExtConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); if (temp < 0) goto no_ticket; parsed_session_ticket->client_identity.client_auth_type = @@ -1597,8 +1599,8 @@ case CLIENT_AUTH_ANONYMOUS: break; case CLIENT_AUTH_CERTIFICATE: - rv = ssl3_ConsumeHandshakeVariable(ss, &cert_item, 3, - &buffer, &buffer_len); + rv = ssl3_ExtConsumeHandshakeVariable(ss, &cert_item, 3, + &buffer, &buffer_len); if (rv != SECSuccess) goto no_ticket; rv = SECITEM_CopyItem(NULL, &parsed_session_ticket->peer_cert, @@ -1610,18 +1612,18 @@ goto no_ticket; } /* Read timestamp. */ - temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len); + temp = ssl3_ExtConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len); if (temp < 0) goto no_ticket; parsed_session_ticket->timestamp = (PRUint32)temp; /* Read server name */ nameType = - ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); + ssl3_ExtConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); if (nameType != TLS_STE_NO_SERVER_NAME) { SECItem name_item; - rv = ssl3_ConsumeHandshakeVariable(ss, &name_item, 2, &buffer, - &buffer_len); + rv = ssl3_ExtConsumeHandshakeVariable(ss, &name_item, 2, &buffer, + &buffer_len); if (rv != SECSuccess) goto no_ticket; rv = SECITEM_CopyItem(NULL, &parsed_session_ticket->srvName, @@ -1632,19 +1634,19 @@ } /* Read extendedMasterSecretUsed */ - temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); + temp = ssl3_ExtConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); if (temp < 0) goto no_ticket; PORT_Assert(temp == PR_TRUE || temp == PR_FALSE); parsed_session_ticket->extendedMasterSecretUsed = (PRBool)temp; - rv = ssl3_ConsumeHandshake(ss, &parsed_session_ticket->flags, 4, - &buffer, &buffer_len); + rv = ssl3_ExtConsumeHandshake(ss, &parsed_session_ticket->flags, 4, + &buffer, &buffer_len); if (rv != SECSuccess) goto no_ticket; parsed_session_ticket->flags = PR_ntohl(parsed_session_ticket->flags); - rv = ssl3_ConsumeHandshakeVariable(ss, &alpn_item, 1, &buffer, &buffer_len); + rv = ssl3_ExtConsumeHandshakeVariable(ss, &alpn_item, 1, &buffer, &buffer_len); if (rv != SECSuccess) goto no_ticket; if (alpn_item.len != 0) { @@ -1767,7 +1769,7 @@ } SECStatus -ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type, +ssl3_ServerHandleSessionTicketXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { @@ -1782,18 +1784,18 @@ } /* Keep track of negotiated extensions. */ - ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ex_type; /* Parse the received ticket sent in by the client. We are * lenient about some parse errors, falling back to a fullshake * instead of terminating the current connection. */ if (data->len == 0) { - ss->xtnData.emptySessionTicket = PR_TRUE; + xtnData->emptySessionTicket = PR_TRUE; return SECSuccess; } - return ssl3_ProcessSessionTicketCommon(ss, data); + return ssl3_ProcessSessionTicketCommon(CONST_CAST(sslSocket, ss), data); } /* @@ -1822,7 +1824,8 @@ */ PRInt32 ssl3_SendRenegotiationInfoXtn( - sslSocket *ss, + const sslSocket *ss, + TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { @@ -1846,20 +1849,19 @@ if (append) { SECStatus rv; /* extension_type */ - rv = ssl3_AppendHandshakeNumber(ss, ssl_renegotiation_info_xtn, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_renegotiation_info_xtn, 2); if (rv != SECSuccess) return -1; /* length of extension_data */ - rv = ssl3_AppendHandshakeNumber(ss, len + 1, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, len + 1, 2); if (rv != SECSuccess) return -1; /* verify_Data from previous Finished message(s) */ - rv = ssl3_AppendHandshakeVariable(ss, - ss->ssl3.hs.finishedMsgs.data, len, 1); + rv = ssl3_ExtAppendHandshakeVariable(ss, + ss->ssl3.hs.finishedMsgs.data, len, 1); if (rv != SECSuccess) return -1; if (!ss->sec.isServer) { - TLSExtensionData *xtnData = &ss->xtnData; xtnData->advertised[xtnData->numAdvertised++] = ssl_renegotiation_info_xtn; } @@ -1869,7 +1871,7 @@ /* This function runs in both the client and server. */ SECStatus -ssl3_HandleRenegotiationInfoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data) +ssl3_HandleRenegotiationInfoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { SECStatus rv = SECSuccess; PRUint32 len = 0; @@ -1879,28 +1881,29 @@ : ss->ssl3.hs.finishedBytes * 2; } if (data->len != 1 + len || data->data[0] != len) { - (void)ssl3_DecodeError(ss); + ssl3_ExtDecodeError(ss); return SECFailure; } if (len && NSS_SecureMemcmp(ss->ssl3.hs.finishedMsgs.data, data->data + 1, len)) { - (void)SSL3_SendAlert(ss, alert_fatal, handshake_failure); + ssl3_ExtSendAlert(ss, alert_fatal, handshake_failure); PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); return SECFailure; } /* remember that we got this extension and it was correct. */ - ss->peerRequestedProtection = 1; - ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; + CONST_CAST(sslSocket, ss) + ->peerRequestedProtection = 1; + xtnData->negotiated[xtnData->numNegotiated++] = ex_type; if (ss->sec.isServer) { /* prepare to send back the appropriate response */ - rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type, - ssl3_SendRenegotiationInfoXtn); + rv = ssl3_RegisterExtensionSender(ss, xtnData, ex_type, + ssl3_SendRenegotiationInfoXtn); } return rv; } PRInt32 -ssl3_ClientSendUseSRTPXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes) +ssl3_ClientSendUseSRTPXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { PRUint32 ext_data_len; PRInt16 i; @@ -1916,31 +1919,31 @@ if (append && maxBytes >= 4 + ext_data_len) { /* Extension type */ - rv = ssl3_AppendHandshakeNumber(ss, ssl_use_srtp_xtn, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_use_srtp_xtn, 2); if (rv != SECSuccess) return -1; /* Length of extension data */ - rv = ssl3_AppendHandshakeNumber(ss, ext_data_len, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ext_data_len, 2); if (rv != SECSuccess) return -1; /* Length of the SRTP cipher list */ - rv = ssl3_AppendHandshakeNumber(ss, - 2 * ss->ssl3.dtlsSRTPCipherCount, - 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, + 2 * ss->ssl3.dtlsSRTPCipherCount, + 2); if (rv != SECSuccess) return -1; /* The SRTP ciphers */ for (i = 0; i < ss->ssl3.dtlsSRTPCipherCount; i++) { - rv = ssl3_AppendHandshakeNumber(ss, - ss->ssl3.dtlsSRTPCiphers[i], - 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, + ss->ssl3.dtlsSRTPCiphers[i], + 2); if (rv != SECSuccess) return -1; } /* Empty MKI value */ - ssl3_AppendHandshakeVariable(ss, NULL, 0, 1); + ssl3_ExtAppendHandshakeVariable(ss, NULL, 0, 1); - ss->xtnData.advertised[ss->xtnData.numAdvertised++] = + xtnData->advertised[xtnData->numAdvertised++] = ssl_use_srtp_xtn; } @@ -1948,7 +1951,7 @@ } PRInt32 -ssl3_ServerSendUseSRTPXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes) +ssl3_ServerSendUseSRTPXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { SECStatus rv; @@ -1958,29 +1961,29 @@ } /* Extension type */ - rv = ssl3_AppendHandshakeNumber(ss, ssl_use_srtp_xtn, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_use_srtp_xtn, 2); if (rv != SECSuccess) return -1; /* Length of extension data */ - rv = ssl3_AppendHandshakeNumber(ss, 5, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, 5, 2); if (rv != SECSuccess) return -1; /* Length of the SRTP cipher list */ - rv = ssl3_AppendHandshakeNumber(ss, 2, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, 2, 2); if (rv != SECSuccess) return -1; /* The selected cipher */ - rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.dtlsSRTPCipherSuite, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, xtnData->dtlsSRTPCipherSuite, 2); if (rv != SECSuccess) return -1; /* Empty MKI value */ - ssl3_AppendHandshakeVariable(ss, NULL, 0, 1); + ssl3_ExtAppendHandshakeVariable(ss, NULL, 0, 1); return 9; } SECStatus -ssl3_ClientHandleUseSRTPXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data) +ssl3_ClientHandleUseSRTPXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { SECStatus rv; SECItem ciphers = { siBuffer, NULL, 0 }; @@ -1990,19 +1993,19 @@ SECItem litem; if (!data->data || !data->len) { - (void)ssl3_DecodeError(ss); + ssl3_ExtDecodeError(ss); return SECFailure; } /* Get the cipher list */ - rv = ssl3_ConsumeHandshakeVariable(ss, &ciphers, 2, - &data->data, &data->len); + rv = ssl3_ExtConsumeHandshakeVariable(ss, &ciphers, 2, + &data->data, &data->len); if (rv != SECSuccess) { return SECFailure; /* fatal alert already sent */ } /* Now check that the server has picked just 1 (i.e., len = 2) */ if (ciphers.len != 2) { - (void)ssl3_DecodeError(ss); + ssl3_ExtDecodeError(ss); return SECFailure; } @@ -2018,39 +2021,39 @@ } if (!found) { - (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter); + ssl3_ExtSendAlert(ss, alert_fatal, illegal_parameter); PORT_SetError(SSL_ERROR_RX_MALFORMED_SERVER_HELLO); return SECFailure; } /* Get the srtp_mki value */ - rv = ssl3_ConsumeHandshakeVariable(ss, &litem, 1, - &data->data, &data->len); + rv = ssl3_ExtConsumeHandshakeVariable(ss, &litem, 1, + &data->data, &data->len); if (rv != SECSuccess) { return SECFailure; /* alert already sent */ } /* We didn't offer an MKI, so this must be 0 length */ if (litem.len != 0) { - (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter); + ssl3_ExtSendAlert(ss, alert_fatal, illegal_parameter); PORT_SetError(SSL_ERROR_RX_MALFORMED_SERVER_HELLO); return SECFailure; } /* extra trailing bytes */ if (data->len != 0) { - (void)ssl3_DecodeError(ss); + ssl3_ExtDecodeError(ss); return SECFailure; } /* OK, this looks fine. */ - ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ssl_use_srtp_xtn; - ss->ssl3.dtlsSRTPCipherSuite = cipher; + xtnData->negotiated[xtnData->numNegotiated++] = ssl_use_srtp_xtn; + xtnData->dtlsSRTPCipherSuite = cipher; return SECSuccess; } SECStatus -ssl3_ServerHandleUseSRTPXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data) +ssl3_ServerHandleUseSRTPXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { SECStatus rv; SECItem ciphers = { siBuffer, NULL, 0 }; @@ -2067,19 +2070,19 @@ } if (!data->data || data->len < 5) { - (void)ssl3_DecodeError(ss); + ssl3_ExtDecodeError(ss); return SECFailure; } /* Get the cipher list */ - rv = ssl3_ConsumeHandshakeVariable(ss, &ciphers, 2, - &data->data, &data->len); + rv = ssl3_ExtConsumeHandshakeVariable(ss, &ciphers, 2, + &data->data, &data->len); if (rv != SECSuccess) { return SECFailure; /* alert already sent */ } /* Check that the list is even length */ if (ciphers.len % 2) { - (void)ssl3_DecodeError(ss); + ssl3_ExtDecodeError(ss); return SECFailure; } @@ -2096,13 +2099,13 @@ } /* Get the srtp_mki value */ - rv = ssl3_ConsumeHandshakeVariable(ss, &litem, 1, &data->data, &data->len); + rv = ssl3_ExtConsumeHandshakeVariable(ss, &litem, 1, &data->data, &data->len); if (rv != SECSuccess) { return SECFailure; } if (data->len != 0) { - (void)ssl3_DecodeError(ss); /* trailing bytes */ + ssl3_ExtDecodeError(ss); /* trailing bytes */ return SECFailure; } @@ -2113,18 +2116,19 @@ } /* OK, we have a valid cipher and we've selected it */ - ss->ssl3.dtlsSRTPCipherSuite = cipher; - ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ssl_use_srtp_xtn; + xtnData->dtlsSRTPCipherSuite = cipher; + xtnData->negotiated[xtnData->numNegotiated++] = ssl_use_srtp_xtn; - return ssl3_RegisterServerHelloExtensionSender(ss, ssl_use_srtp_xtn, - ssl3_ServerSendUseSRTPXtn); + return ssl3_RegisterExtensionSender(ss, xtnData, + ssl_use_srtp_xtn, + ssl3_ServerSendUseSRTPXtn); } /* ssl3_ServerHandleSigAlgsXtn handles the signature_algorithms extension * from a client. * See https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */ SECStatus -ssl3_ServerHandleSigAlgsXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data) +ssl3_ServerHandleSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { SECStatus rv; @@ -2133,13 +2137,13 @@ return SECSuccess; } - if (ss->ssl3.hs.clientSigSchemes) { - PORT_Free(ss->ssl3.hs.clientSigSchemes); - ss->ssl3.hs.clientSigSchemes = NULL; + if (xtnData->clientSigSchemes) { + PORT_Free(xtnData->clientSigSchemes); + xtnData->clientSigSchemes = NULL; } rv = ssl_ParseSignatureSchemes(ss, NULL, - &ss->ssl3.hs.clientSigSchemes, - &ss->ssl3.hs.numClientSigScheme, + &xtnData->clientSigSchemes, + &xtnData->numClientSigScheme, &data->data, &data->len); if (rv != SECSuccess) { PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); @@ -2147,20 +2151,20 @@ } /* Check for trailing data. */ if (data->len != 0) { - (void)SSL3_SendAlert(ss, alert_fatal, decode_error); + ssl3_ExtSendAlert(ss, alert_fatal, decode_error); PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); return SECFailure; } /* Keep track of negotiated extensions. */ - ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ex_type; return SECSuccess; } /* ssl3_ClientSendSigAlgsXtn sends the signature_algorithm extension for TLS * 1.2 ClientHellos. */ PRInt32 -ssl3_ClientSendSigAlgsXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes) +ssl3_ClientSendSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { PRInt32 extension_length; PRUint8 buf[MAX_SIGNATURE_SCHEMES * 2]; @@ -2189,21 +2193,21 @@ if (append) { SECStatus rv; - rv = ssl3_AppendHandshakeNumber(ss, ssl_signature_algorithms_xtn, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_signature_algorithms_xtn, 2); if (rv != SECSuccess) { return -1; } - rv = ssl3_AppendHandshakeNumber(ss, len + 2, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, len + 2, 2); if (rv != SECSuccess) { return -1; } - rv = ssl3_AppendHandshakeVariable(ss, buf, len, 2); + rv = ssl3_ExtAppendHandshakeVariable(ss, buf, len, 2); if (rv != SECSuccess) { return -1; } - ss->xtnData.advertised[ss->xtnData.numAdvertised++] = + xtnData->advertised[xtnData->numAdvertised++] = ssl_signature_algorithms_xtn; } @@ -2257,16 +2261,16 @@ return -1; } - if (SECSuccess != ssl3_AppendHandshakeNumber(ss, ssl_padding_xtn, 2)) + if (SECSuccess != ssl3_ExtAppendHandshakeNumber(ss, ssl_padding_xtn, 2)) return -1; - if (SECSuccess != ssl3_AppendHandshakeVariable(ss, padding, paddingLen, 2)) + if (SECSuccess != ssl3_ExtAppendHandshakeVariable(ss, padding, paddingLen, 2)) return -1; return extensionLen; } PRInt32 -ssl3_SendExtendedMasterSecretXtn(sslSocket *ss, PRBool append, +ssl3_SendExtendedMasterSecretXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { PRInt32 extension_length; @@ -2286,13 +2290,13 @@ if (append) { SECStatus rv; - rv = ssl3_AppendHandshakeNumber(ss, ssl_extended_master_secret_xtn, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_extended_master_secret_xtn, 2); if (rv != SECSuccess) goto loser; - rv = ssl3_AppendHandshakeNumber(ss, 0, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2); if (rv != SECSuccess) goto loser; - ss->xtnData.advertised[ss->xtnData.numAdvertised++] = + xtnData->advertised[xtnData->numAdvertised++] = ssl_extended_master_secret_xtn; } @@ -2303,7 +2307,7 @@ } SECStatus -ssl3_HandleExtendedMasterSecretXtn(sslSocket *ss, PRUint16 ex_type, +ssl3_HandleExtendedMasterSecretXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { if (ss->version < SSL_LIBRARY_VERSION_TLS_1_0) { @@ -2324,11 +2328,11 @@ SSL_GETPID(), ss->fd)); /* Keep track of negotiated extensions. */ - ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ex_type; if (ss->sec.isServer) { - return ssl3_RegisterServerHelloExtensionSender( - ss, ex_type, ssl3_SendExtendedMasterSecretXtn); + return ssl3_RegisterExtensionSender( + ss, xtnData, ex_type, ssl3_SendExtendedMasterSecretXtn); } return SECSuccess; } @@ -2336,7 +2340,7 @@ /* ssl3_ClientSendSignedCertTimestampXtn sends the signed_certificate_timestamp * extension for TLS ClientHellos. */ PRInt32 -ssl3_ClientSendSignedCertTimestampXtn(sslSocket *ss, PRBool append, +ssl3_ClientSendSignedCertTimestampXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { PRInt32 extension_length = 2 /* extension_type */ + @@ -2349,16 +2353,16 @@ if (append && maxBytes >= extension_length) { SECStatus rv; /* extension_type */ - rv = ssl3_AppendHandshakeNumber(ss, - ssl_signed_cert_timestamp_xtn, - 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, + ssl_signed_cert_timestamp_xtn, + 2); if (rv != SECSuccess) goto loser; /* zero length */ - rv = ssl3_AppendHandshakeNumber(ss, 0, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2); if (rv != SECSuccess) goto loser; - ss->xtnData.advertised[ss->xtnData.numAdvertised++] = + xtnData->advertised[xtnData->numAdvertised++] = ssl_signed_cert_timestamp_xtn; } else if (maxBytes < extension_length) { PORT_Assert(0); @@ -2371,7 +2375,7 @@ } SECStatus -ssl3_ClientHandleSignedCertTimestampXtn(sslSocket *ss, PRUint16 ex_type, +ssl3_ClientHandleSignedCertTimestampXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { /* We do not yet know whether we'll be resuming a session or creating @@ -2382,7 +2386,7 @@ * All parsing is currently left to the application and we accept * everything, including empty data. */ - SECItem *scts = &ss->xtnData.signedCertTimestamps; + SECItem *scts = &xtnData->signedCertTimestamps; PORT_Assert(!scts->data && !scts->len); if (!data->len) { @@ -2391,12 +2395,12 @@ } *scts = *data; /* Keep track of negotiated extensions. */ - ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ex_type; return SECSuccess; } PRInt32 -ssl3_ServerSendSignedCertTimestampXtn(sslSocket *ss, +ssl3_ServerSendSignedCertTimestampXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { @@ -2419,13 +2423,13 @@ if (append) { SECStatus rv; /* extension_type */ - rv = ssl3_AppendHandshakeNumber(ss, - ssl_signed_cert_timestamp_xtn, - 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, + ssl_signed_cert_timestamp_xtn, + 2); if (rv != SECSuccess) goto loser; /* extension_data */ - rv = ssl3_AppendHandshakeVariable(ss, scts->data, scts->len, 2); + rv = ssl3_ExtAppendHandshakeVariable(ss, scts->data, scts->len, 2); if (rv != SECSuccess) goto loser; } @@ -2437,11 +2441,140 @@ } SECStatus -ssl3_ServerHandleSignedCertTimestampXtn(sslSocket *ss, PRUint16 ex_type, +ssl3_ServerHandleSignedCertTimestampXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + PRUint16 ex_type, SECItem *data) { - ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ex_type; PORT_Assert(ss->sec.isServer); - return ssl3_RegisterServerHelloExtensionSender(ss, ex_type, - ssl3_ServerSendSignedCertTimestampXtn); + return ssl3_RegisterExtensionSender( + ss, xtnData, ex_type, ssl3_ServerSendSignedCertTimestampXtn); +} + +/* Just make sure that the remote client supports uncompressed points, + * Since that is all we support. Disable ECC cipher suites if it doesn't. + */ +SECStatus +ssl3_HandleSupportedPointFormatsXtn(const sslSocket *ss, TLSExtensionData *xtnData, + PRUint16 ex_type, + SECItem *data) +{ + int i; + + if (data->len < 2 || data->len > 255 || !data->data || + data->len != (unsigned int)data->data[0] + 1) { + ssl3_ExtDecodeError(ss); + return SECFailure; + } + for (i = data->len; --i > 0;) { + if (data->data[i] == 0) { + /* indicate that we should send a reply */ + SECStatus rv; + rv = ssl3_RegisterExtensionSender(ss, xtnData, ex_type, + &ssl3_SendSupportedPointFormatsXtn); + return rv; + } + } + + /* Poor client doesn't support uncompressed points. */ + PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE); + return SECFailure; +} + +static SECStatus +ssl_UpdateSupportedGroups(sslSocket *ss, SECItem *data) +{ + PRInt32 list_len; + unsigned int i; + const sslNamedGroupDef *enabled[SSL_NAMED_GROUP_COUNT] = { 0 }; + PORT_Assert(SSL_NAMED_GROUP_COUNT == PR_ARRAY_SIZE(enabled)); + + if (!data->data || data->len < 4) { + (void)ssl3_DecodeError(ss); + return SECFailure; + } + + /* get the length of elliptic_curve_list */ + list_len = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len); + if (list_len < 0 || data->len != list_len || (data->len % 2) != 0) { + (void)ssl3_DecodeError(ss); + return SECFailure; + } + + /* disable all groups and remember the enabled groups */ + for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) { + enabled[i] = ss->namedGroupPreferences[i]; + ss->namedGroupPreferences[i] = NULL; + } + + /* Read groups from data and enable if in |enabled| */ + while (data->len) { + const sslNamedGroupDef *group; + PRInt32 curve_name = + ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len); + if (curve_name < 0) { + return SECFailure; /* fatal alert already sent */ + } + group = ssl_LookupNamedGroup(curve_name); + if (group) { + for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) { + if (enabled[i] && group == enabled[i]) { + ss->namedGroupPreferences[i] = enabled[i]; + break; + } + } + } + + /* "Codepoints in the NamedCurve registry with a high byte of 0x01 (that + * is, between 256 and 511 inclusive) are set aside for FFDHE groups," + * -- https://tools.ietf.org/html/draft-ietf-tls-negotiated-ff-dhe-10 + */ + if ((curve_name & 0xff00) == 0x0100) { + ss->xtnData.peerSupportsFfdheGroups = PR_TRUE; + } + } + + /* Note: if ss->opt.requireDHENamedGroups is set, we disable DHE cipher + * suites, but we do that in ssl3_config_match(). */ + if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3 && + !ss->opt.requireDHENamedGroups && !ss->xtnData.peerSupportsFfdheGroups) { + /* If we don't require that DHE use named groups, and no FFDHE was + * included, we pretend that they support all the FFDHE groups we do. */ + for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) { + if (enabled[i] && enabled[i]->keaType == ssl_kea_dh) { + ss->namedGroupPreferences[i] = enabled[i]; + } + } + } + + return SECSuccess; +} + +/* Ensure that the curve in our server cert is one of the ones supported + * by the remote client, and disable all ECC cipher suites if not. + */ +SECStatus +ssl_HandleSupportedGroupsXtn(const sslSocket *ss, TLSExtensionData *xtnData, + PRUint16 ex_type, SECItem *data) +{ + SECStatus rv; + + rv = ssl_UpdateSupportedGroups(CONST_CAST(sslSocket, ss), data); + if (rv != SECSuccess) + return SECFailure; + + /* TLS 1.3 permits the server to send this extension so make it so. */ + if (ss->sec.isServer && ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) { + rv = ssl3_RegisterExtensionSender(ss, xtnData, ex_type, + &ssl_SendSupportedGroupsXtn); + if (rv != SECSuccess) { + return SECFailure; /* error already set. */ + } + } + + /* Remember that we negotiated this extension. */ + xtnData->negotiated[xtnData->numNegotiated++] = ex_type; + + return SECSuccess; } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/ssl3exthandle.h firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/ssl3exthandle.h --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/ssl3exthandle.h 2016-11-11 02:16:19.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/ssl3exthandle.h 2016-11-14 02:18:58.000000000 +0000 @@ -9,63 +9,87 @@ #ifndef __ssl3exthandle_h_ #define __ssl3exthandle_h_ -PRInt32 ssl3_SendRenegotiationInfoXtn(sslSocket *ss, +PRInt32 ssl3_SendRenegotiationInfoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes); -SECStatus ssl3_HandleRenegotiationInfoXtn(sslSocket *ss, +SECStatus ssl3_HandleRenegotiationInfoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); -SECStatus ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, +SECStatus ssl3_ClientHandleNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); -SECStatus ssl3_ClientHandleAppProtoXtn(sslSocket *ss, +SECStatus ssl3_ClientHandleAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); -SECStatus ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss, +SECStatus ssl3_ServerHandleNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); -SECStatus ssl3_ServerHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type, +SECStatus ssl3_ServerHandleAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); -PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append, +PRInt32 ssl3_ClientSendNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes); -PRInt32 ssl3_ClientSendAppProtoXtn(sslSocket *ss, PRBool append, +PRInt32 ssl3_ClientSendAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes); -PRInt32 ssl3_ServerSendAppProtoXtn(sslSocket *ss, PRBool append, +PRInt32 ssl3_ServerSendAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes); -PRInt32 ssl3_ClientSendUseSRTPXtn(sslSocket *ss, PRBool append, +PRInt32 ssl3_ClientSendUseSRTPXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes); -PRInt32 ssl3_ServerSendUseSRTPXtn(sslSocket *ss, PRBool append, +PRInt32 ssl3_ServerSendUseSRTPXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes); -SECStatus ssl3_ClientHandleUseSRTPXtn(sslSocket *ss, PRUint16 ex_type, +SECStatus ssl3_ClientHandleUseSRTPXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); -SECStatus ssl3_ServerHandleUseSRTPXtn(sslSocket *ss, PRUint16 ex_type, +SECStatus ssl3_ServerHandleUseSRTPXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); -PRInt32 ssl3_ServerSendStatusRequestXtn(sslSocket *ss, +PRInt32 ssl3_ServerSendStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes); -SECStatus ssl3_ServerHandleStatusRequestXtn(sslSocket *ss, +SECStatus ssl3_ServerHandleStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); -SECStatus ssl3_ClientHandleStatusRequestXtn(sslSocket *ss, +SECStatus ssl3_ClientHandleStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); -PRInt32 ssl3_ClientSendStatusRequestXtn(sslSocket *ss, PRBool append, +PRInt32 ssl3_ClientSendStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes); -PRInt32 ssl3_ClientSendSigAlgsXtn(sslSocket *ss, PRBool append, +PRInt32 ssl3_ClientSendSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes); -SECStatus ssl3_ServerHandleSigAlgsXtn(sslSocket *ss, PRUint16 ex_type, +SECStatus ssl3_ServerHandleSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); -PRInt32 ssl3_ClientSendSignedCertTimestampXtn(sslSocket *ss, +PRInt32 ssl3_ClientSendSignedCertTimestampXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes); -SECStatus ssl3_ClientHandleSignedCertTimestampXtn(sslSocket *ss, +SECStatus ssl3_ClientHandleSignedCertTimestampXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); -PRInt32 ssl3_ServerSendSignedCertTimestampXtn(sslSocket *ss, +PRInt32 ssl3_ServerSendSignedCertTimestampXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes); -SECStatus ssl3_ServerHandleSignedCertTimestampXtn(sslSocket *ss, +SECStatus ssl3_ServerHandleSignedCertTimestampXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); -PRInt32 ssl3_SendExtendedMasterSecretXtn(sslSocket *ss, PRBool append, +PRInt32 ssl3_SendExtendedMasterSecretXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes); -SECStatus ssl3_HandleExtendedMasterSecretXtn(sslSocket *ss, +SECStatus ssl3_HandleExtendedMasterSecretXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); SECStatus ssl3_ProcessSessionTicketCommon(sslSocket *ss, SECItem *data); +PRInt32 ssl3_SendServerNameXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + PRBool append, + PRUint32 maxBytes); +SECStatus ssl3_HandleServerNameXtn(const sslSocket *ss, TLSExtensionData *xtnData, + PRUint16 ex_type, SECItem *data); +SECStatus ssl_HandleSupportedGroupsXtn(const sslSocket *ss, TLSExtensionData *xtnData, + PRUint16 ex_type, SECItem *data); +SECStatus ssl3_HandleSupportedPointFormatsXtn(const sslSocket *ss, TLSExtensionData *xtnData, + PRUint16 ex_type, SECItem *data); +SECStatus ssl3_ClientHandleSessionTicketXtn(const sslSocket *ss, TLSExtensionData *xtnData, + PRUint16 ex_type, SECItem *data); +SECStatus ssl3_ServerHandleSessionTicketXtn(const sslSocket *ss, TLSExtensionData *xtnData, + PRUint16 ex_type, SECItem *data); +PRInt32 ssl3_SendSessionTicketXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + PRBool append, + PRUint32 maxBytes); +PRInt32 ssl_SendSupportedGroupsXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + PRBool append, PRUint32 maxBytes); +PRInt32 ssl3_SendSupportedPointFormatsXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + PRBool append, PRUint32 maxBytes); #endif diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/sslimpl.h firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/sslimpl.h --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/sslimpl.h 2016-11-11 02:16:19.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/sslimpl.h 2016-11-14 00:56:25.000000000 +0000 @@ -33,6 +33,10 @@ #include "sslt.h" /* for some formerly private types, now public */ +typedef struct sslSocketStr sslSocket; + +#include "ssl3ext.h" + /* to make some of these old enums public without namespace pollution, ** it was necessary to prepend ssl_ to the names. ** These #defines preserve compatibility with the old code here in libssl. @@ -102,6 +106,8 @@ #define LSB(x) ((unsigned char)((x)&0xff)) #define MSB(x) ((unsigned char)(((unsigned)(x)) >> 8)) +#define CONST_CAST(T, X) ((T *)(X)) + /************************************************************************/ typedef enum { SSLAppOpRead = 0, @@ -172,7 +178,6 @@ typedef struct sslGatherStr sslGather; typedef struct sslSecurityInfoStr sslSecurityInfo; typedef struct sslSessionIDStr sslSessionID; -typedef struct sslSocketStr sslSocket; typedef struct sslSocketOpsStr sslSocketOps; typedef struct ssl3StateStr ssl3State; @@ -196,46 +201,6 @@ unsigned int sidLen, CERTCertDBHandle *dbHandle); -/* registerable callback function that either appends extension to buffer - * or returns length of data that it would have appended. - */ -typedef PRInt32 (*ssl3HelloExtensionSenderFunc)(sslSocket *ss, PRBool append, - PRUint32 maxBytes); - -/* registerable callback function that handles a received extension, - * of the given type. - */ -typedef SECStatus (*ssl3ExtensionHandlerFunc)(sslSocket *ss, - PRUint16 ex_type, - SECItem *data); - -/* row in a table of hello extension senders */ -typedef struct { - PRInt32 ex_type; - ssl3HelloExtensionSenderFunc ex_sender; -} ssl3HelloExtensionSender; - -/* row in a table of hello extension handlers */ -typedef struct { - PRInt32 ex_type; - ssl3ExtensionHandlerFunc ex_handler; -} ssl3ExtensionHandler; - -extern SECStatus -ssl3_RegisterServerHelloExtensionSender(sslSocket *ss, PRUint16 ex_type, - ssl3HelloExtensionSenderFunc cb); - -extern PRInt32 -ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes, - const ssl3HelloExtensionSender *sender); - -extern unsigned int -ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength); - -extern PRInt32 -ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen, - PRUint32 maxBytes); - /* Socket ops */ struct sslSocketOpsStr { int (*connect)(sslSocket *, const PRNetAddr *); @@ -754,53 +719,8 @@ /* * TLS extension related constants and data structures. */ -typedef struct TLSExtensionDataStr TLSExtensionData; typedef struct SessionTicketDataStr SessionTicketData; -struct TLSExtensionDataStr { - /* registered callbacks that send server hello extensions */ - ssl3HelloExtensionSender serverHelloSenders[SSL_MAX_EXTENSIONS]; - ssl3HelloExtensionSender encryptedExtensionsSenders[SSL_MAX_EXTENSIONS]; - - /* Keep track of the extensions that are negotiated. */ - PRUint16 numAdvertised; - PRUint16 numNegotiated; - PRUint16 advertised[SSL_MAX_EXTENSIONS]; - PRUint16 negotiated[SSL_MAX_EXTENSIONS]; - - /* SessionTicket Extension related data. */ - PRBool ticketTimestampVerified; - PRBool emptySessionTicket; - PRBool sentSessionTicketInClientHello; - SECItem psk_ke_modes; - SECItem psk_auth_modes; - PRUint32 ticket_age_add; - PRBool ticket_age_add_found; - - /* SNI Extension related data - * Names data is not coppied from the input buffer. It can not be - * used outside the scope where input buffer is defined and that - * is beyond ssl3_HandleClientHello function. */ - SECItem *sniNameArr; - PRUint32 sniNameArrSize; - - /* Signed Certificate Timestamps extracted from the TLS extension. - * (client only). - * This container holds a temporary pointer to the extension data, - * until a session structure (the sec.ci.sid of an sslSocket) is setup - * that can hold a permanent copy of the data - * (in sec.ci.sid.u.ssl3.signedCertTimestamps). - * The data pointed to by this structure is neither explicitly allocated - * nor copied: the pointer points to the handshake message buffer and is - * only valid in the scope of ssl3_HandleServerHello. - */ - SECItem signedCertTimestamps; -}; - -typedef enum { - sni_nametype_hostname -} SNINameType; - typedef SECStatus (*sslRestartTarget)(sslSocket *); /* @@ -830,12 +750,6 @@ unsigned int len; } TLS13CombinedHash; -typedef struct TLSExtensionStr { - PRCList link; /* The linked list link */ - PRUint16 type; /* Extension type */ - SECItem data; /* Pointers into the handshake data. */ -} TLSExtension; - typedef enum { handshake_hash_unknown = 0, handshake_hash_combo = 1, /* The MD5/SHA-1 combination */ @@ -913,14 +827,6 @@ /* Which preliminaryinfo values have been set. */ PRUint32 preliminaryInfo; - PRBool peerSupportsFfdheGroups; /* if the peer supports named ffdhe groups */ - - /* clientSigAndHash contains the contents of the signature_algorithms - * extension (if any) from the client. This is only valid for TLS 1.2 - * or later. */ - SSLSignatureScheme *clientSigSchemes; - unsigned int numClientSigScheme; - /* Parsed extensions */ PRCList remoteExtensions; /* Parsed incoming extensions */ @@ -950,7 +856,6 @@ /* This group of values is used for TLS 1.3 and above */ PK11Context *clientHelloHash; /* The client hello hash state, used * by the server for 0-RTT. */ - PRCList remoteKeyShares; /* The other side's public keys */ PK11SymKey *currentSecret; /* The secret down the "left hand side" * of the TLS 1.3 key schedule. */ PK11SymKey *resumptionPsk; /* The resumption PSK. */ @@ -1014,18 +919,11 @@ SSL3HandshakeState hs; ssl3CipherSpec specs[2]; /* one is current, one is pending. */ - /* In a client: if the server supports Next Protocol Negotiation, then - * this is the protocol that was negotiated. - */ - SECItem nextProto; - SSLNextProtoState nextProtoState; - PRUint16 mtu; /* Our estimate of the MTU */ /* DTLS-SRTP cipher suite preferences (if any) */ PRUint16 dtlsSRTPCiphers[MAX_DTLS_SRTP_CIPHER_SUITES]; PRUint16 dtlsSRTPCipherCount; - PRUint16 dtlsSRTPCipherSuite; /* 0 if not selected */ PRBool fatalAlertSent; PRBool dheWeakGroupEnabled; /* used by server */ const sslNamedGroupDef *dhePreferredGroup; @@ -1664,10 +1562,12 @@ extern void ssl_FreeEphemeralKeyPair(sslEphemeralKeyPair *keyPair); extern sslEphemeralKeyPair *ssl_LookupEphemeralKeyPair( sslSocket *ss, const sslNamedGroupDef *groupDef); +extern PRBool ssl_HaveEphemeralKeyPair(const sslSocket *ss, + const sslNamedGroupDef *groupDef); extern void ssl_FreeEphemeralKeyPairs(sslSocket *ss); -extern SECStatus ssl_AppendPaddedDHKeyShare(sslSocket *ss, - SECKEYPublicKey *pubKey, +extern SECStatus ssl_AppendPaddedDHKeyShare(const sslSocket *ss, + const SECKEYPublicKey *pubKey, PRBool appendLength); extern const ssl3DHParams *ssl_GetDHEParams(const sslNamedGroupDef *groupDef); extern SECStatus ssl_SelectDHEGroup(sslSocket *ss, @@ -1682,8 +1582,8 @@ const sslNamedGroupDef **groupDef, const ssl3DHParams **dhParams); -extern PRBool ssl_IsECCEnabled(sslSocket *ss); -extern PRBool ssl_IsDHEEnabled(sslSocket *ss); +extern PRBool ssl_IsECCEnabled(const sslSocket *ss); +extern PRBool ssl_IsDHEEnabled(const sslSocket *ss); /* Macro for finding a curve equivalent in strength to RSA key's */ #define SSL_RSASTRENGTH_TO_ECSTRENGTH(s) \ @@ -1708,7 +1608,7 @@ extern SECStatus ssl3_CipherPrefGetDefault(ssl3CipherSuite which, PRBool *on); extern SECStatus ssl3_CipherPrefSet(sslSocket *ss, ssl3CipherSuite which, PRBool on); -extern SECStatus ssl3_CipherPrefGet(sslSocket *ss, ssl3CipherSuite which, PRBool *on); +extern SECStatus ssl3_CipherPrefGet(const sslSocket *ss, ssl3CipherSuite which, PRBool *on); extern SECStatus ssl3_SetPolicy(ssl3CipherSuite which, PRInt32 policy); extern SECStatus ssl3_GetPolicy(ssl3CipherSuite which, PRInt32 *policy); @@ -1744,7 +1644,7 @@ sslSocket *ss, SECKEYPublicKey *peerKey, SSL3Opaque *b, PRUint32 length, const sslNamedGroupDef *curve); unsigned int tls13_SizeOfECDHEKeyShareKEX(const SECKEYPublicKey *pubKey); -SECStatus tls13_EncodeECDHEKeyShareKEX(sslSocket *ss, +SECStatus tls13_EncodeECDHEKeyShareKEX(const sslSocket *ss, const SECKEYPublicKey *pubKey); extern SECStatus ssl3_ComputeCommonKeyHash(SSLHashType hashAlg, @@ -1775,7 +1675,7 @@ extern PRBool ssl_IsSupportedSignatureScheme(SSLSignatureScheme scheme); extern SECStatus ssl_CheckSignatureSchemeConsistency( sslSocket *ss, SSLSignatureScheme scheme, CERTCertificate *cert); -extern SECStatus ssl_ParseSignatureSchemes(sslSocket *ss, PLArenaPool *arena, +extern SECStatus ssl_ParseSignatureSchemes(const sslSocket *ss, PLArenaPool *arena, SSLSignatureScheme **schemesOut, unsigned int *numSchemesOut, unsigned char **b, @@ -1791,50 +1691,7 @@ ssl3CipherSpec *spec, SSLAuthType authType); extern void ssl3_FreeSniNameArray(TLSExtensionData *xtnData); -/* Functions that handle ClientHello and ServerHello extensions. */ -extern SECStatus ssl3_HandleServerNameXtn(sslSocket *ss, - PRUint16 ex_type, SECItem *data); -extern SECStatus ssl_HandleSupportedGroupsXtn(sslSocket *ss, - PRUint16 ex_type, SECItem *data); -extern SECStatus ssl3_HandleSupportedPointFormatsXtn(sslSocket *ss, - PRUint16 ex_type, SECItem *data); -extern SECStatus ssl3_ClientHandleSessionTicketXtn(sslSocket *ss, - PRUint16 ex_type, SECItem *data); -extern SECStatus ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, - PRUint16 ex_type, SECItem *data); - -/* ClientHello and ServerHello extension senders. - * Note that not all extension senders are exposed here; only those that - * that need exposure. - */ -extern PRInt32 ssl3_SendSessionTicketXtn(sslSocket *ss, PRBool append, - PRUint32 maxBytes); - -/* ClientHello and ServerHello extension senders. - * The code is in ssl3ext.c. - */ -extern PRInt32 ssl3_SendServerNameXtn(sslSocket *ss, PRBool append, - PRUint32 maxBytes); - -extern PRInt32 ssl_SendSupportedGroupsXtn(sslSocket *ss, - PRBool append, PRUint32 maxBytes); -extern PRInt32 ssl3_SendSupportedPointFormatsXtn(sslSocket *ss, - PRBool append, PRUint32 maxBytes); - -/* call the registered extension handlers. */ -extern SECStatus ssl3_HandleExtensions(sslSocket *ss, - SSL3Opaque **b, PRUint32 *length, - SSL3HandshakeType handshakeMessage); -extern SECStatus ssl3_ParseExtensions(sslSocket *ss, - SSL3Opaque **b, PRUint32 *length); -extern SECStatus ssl3_HandleParsedExtensions(sslSocket *ss, - SSL3HandshakeType handshakeMessage); -extern TLSExtension *ssl3_FindExtension(sslSocket *ss, - SSLExtensionType extension_type); -extern void ssl3_DestroyRemoteExtensions(PRCList *list); - /* Hello Extension related routines. */ -extern PRBool ssl3_ExtensionNegotiated(sslSocket *ss, PRUint16 ex_type); extern void ssl3_SetSIDSessionTicket(sslSessionID *sid, /*in/out*/ NewSessionTicket *session_ticket); SECStatus ssl3_EncodeSessionTicket(sslSocket *ss, @@ -1940,7 +1797,7 @@ SECStatus ssl3_SendCertificateStatus(sslSocket *ss); SECStatus ssl_ReadCertificateStatus(sslSocket *ss, SSL3Opaque *b, PRUint32 length); -SECStatus ssl3_EncodeSigAlgs(sslSocket *ss, PRUint8 *buf, +SECStatus ssl3_EncodeSigAlgs(const sslSocket *ss, PRUint8 *buf, unsigned maxLen, PRUint32 *len); void ssl3_GetCertificateRequestCAs(sslSocket *ss, int *calenp, SECItem **namesp, int *nnamesp); @@ -1955,8 +1812,6 @@ ssl3CipherSpec *spec, SSL3Hashes *hashes, PRUint32 sender); -PRInt32 tls13_ServerSendKeyShareXtn(sslSocket *ss, PRBool append, - PRUint32 maxBytes); SECStatus ssl_CreateECDHEphemeralKeyPair(const sslSocket *ss, const sslNamedGroupDef *ecGroup, sslEphemeralKeyPair **keyPair); @@ -1968,16 +1823,6 @@ const sslServerCert *serverCert, CK_MECHANISM_TYPE masterWrapMech, void *pwArg); -PRInt32 tls13_ServerSendPreSharedKeyXtn(sslSocket *ss, - PRBool append, - PRUint32 maxBytes); -PRInt32 tls13_ServerSendEarlyDataXtn(sslSocket *ss, - PRBool append, - PRUint32 maxBytes); -PRInt32 tls13_ServerSendSigAlgsXtn(sslSocket *ss, - PRBool append, - PRUint32 maxBytes); -PRBool ssl3_ClientExtensionAdvertised(sslSocket *ss, PRUint16 ex_type); SECStatus ssl3_FillInCachedSID(sslSocket *ss, sslSessionID *sid); const ssl3CipherSuiteDef *ssl_LookupCipherSuiteDef(ssl3CipherSuite suite); const ssl3BulkCipherDef * diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/sslsecur.c firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/sslsecur.c --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/sslsecur.c 2016-11-11 00:52:58.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/sslsecur.c 2016-11-14 00:56:26.000000000 +0000 @@ -200,6 +200,7 @@ ssl_Release1stHandshakeLock(ss); ssl3_DestroyRemoteExtensions(&ss->ssl3.hs.remoteExtensions); + ssl3_ResetExtensionData(&ss->xtnData); if (!ss->TCPconnected) ss->TCPconnected = (PR_SUCCESS == ssl_DefGetpeername(ss, &addr)); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/sslsock.c firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/sslsock.c --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/sslsock.c 2016-11-11 00:52:58.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/sslsock.c 2016-11-14 00:56:26.000000000 +0000 @@ -1760,7 +1760,7 @@ * indicated that it supports an FFDHE named group. */ if (ss->ssl3.dheWeakGroupEnabled && ss->version < SSL_LIBRARY_VERSION_TLS_1_3 && - !ss->ssl3.hs.peerSupportsFfdheGroups) { + !ss->xtnData.peerSupportsFfdheGroups) { *groupDef = &weak_group_def; return SECSuccess; } @@ -1889,7 +1889,7 @@ PORT_Memcmp(&protos[i + 1], &ss->opt.nextProtoNego.data[j + 1], protos[i]) == 0) { /* We found a match. */ - ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NEGOTIATED; + ss->xtnData.nextProtoState = SSL_NEXT_PROTO_NEGOTIATED; result = &protos[i]; goto found; } @@ -1902,7 +1902,7 @@ * protocols configured, or none of its options match ours. In this case we * request our favoured protocol. */ /* This will be treated as a failure for ALPN. */ - ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NO_OVERLAP; + ss->xtnData.nextProtoState = SSL_NEXT_PROTO_NO_OVERLAP; result = ss->opt.nextProtoNego.data; found: @@ -1961,16 +1961,16 @@ return SECFailure; } - *state = ss->ssl3.nextProtoState; + *state = ss->xtnData.nextProtoState; - if (ss->ssl3.nextProtoState != SSL_NEXT_PROTO_NO_SUPPORT && - ss->ssl3.nextProto.data) { - if (ss->ssl3.nextProto.len > bufLenMax) { + if (ss->xtnData.nextProtoState != SSL_NEXT_PROTO_NO_SUPPORT && + ss->xtnData.nextProto.data) { + if (ss->xtnData.nextProto.len > bufLenMax) { PORT_SetError(SEC_ERROR_OUTPUT_LEN); return SECFailure; } - PORT_Memcpy(buf, ss->ssl3.nextProto.data, ss->ssl3.nextProto.len); - *bufLen = ss->ssl3.nextProto.len; + PORT_Memcpy(buf, ss->xtnData.nextProto.data, ss->xtnData.nextProto.len); + *bufLen = ss->xtnData.nextProto.len; } else { *bufLen = 0; } @@ -2040,12 +2040,12 @@ return SECFailure; } - if (!ss->ssl3.dtlsSRTPCipherSuite) { + if (!ss->xtnData.dtlsSRTPCipherSuite) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } - *cipher = ss->ssl3.dtlsSRTPCipherSuite; + *cipher = ss->xtnData.dtlsSRTPCipherSuite; return SECSuccess; } @@ -3606,6 +3606,12 @@ PORT_Free(keyPair); } +PRBool +ssl_HaveEphemeralKeyPair(const sslSocket *ss, const sslNamedGroupDef *groupDef) +{ + return ssl_LookupEphemeralKeyPair((sslSocket *)ss, groupDef) != NULL; +} + sslEphemeralKeyPair * ssl_LookupEphemeralKeyPair(sslSocket *ss, const sslNamedGroupDef *groupDef) { @@ -3688,7 +3694,6 @@ ss->additionalShares = 0; PR_INIT_CLIST(&ss->ssl3.hs.remoteExtensions); PR_INIT_CLIST(&ss->ssl3.hs.lastMessageFlight); - PR_INIT_CLIST(&ss->ssl3.hs.remoteKeyShares); PR_INIT_CLIST(&ss->ssl3.hs.cipherSpecs); PR_INIT_CLIST(&ss->ssl3.hs.bufferedEarlyData); if (makeLocks) { @@ -3702,7 +3707,7 @@ rv = ssl3_InitGather(&ss->gs); if (rv != SECSuccess) goto loser; - + ssl3_InitExtensionData(&ss->xtnData); return ss; loser: diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/tls13con.c firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/tls13con.c --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/tls13con.c 2016-11-11 00:52:59.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/tls13con.c 2016-11-14 00:56:26.000000000 +0000 @@ -19,6 +19,7 @@ #include "sslerr.h" #include "tls13hkdf.h" #include "tls13con.h" +#include "tls13exthandle.h" typedef enum { TrafficKeyEarlyHandshake, @@ -976,7 +977,7 @@ } static PRBool -tls13_AlpnTagAllowed(sslSocket *ss, const SECItem *tag) +tls13_AlpnTagAllowed(const sslSocket *ss, const SECItem *tag) { const unsigned char *data = ss->opt.nextProtoNego.data; unsigned int length = ss->opt.nextProtoNego.len; @@ -1030,7 +1031,7 @@ PORT_Assert(ss->ssl3.hs.zeroRttState == ssl_0rtt_sent); if (sid && ss->opt.enable0RttData && (sid->u.ssl3.locked.sessionTicket.flags & ticket_allow_early_data) != 0 && - SECITEM_CompareItem(&ss->ssl3.nextProto, &sid->u.ssl3.alpnSelection) == 0) { + SECITEM_CompareItem(&ss->xtnData.nextProto, &sid->u.ssl3.alpnSelection) == 0) { SSL_TRC(3, ("%d: TLS13[%d]: enable 0-RTT", SSL_GETPID(), ss->fd)); PORT_Assert(ss->statelessResume); @@ -1068,8 +1069,8 @@ static TLS13KeyShareEntry * tls13_FindKeyShareEntry(sslSocket *ss, const sslNamedGroupDef *group) { - PRCList *cur_p = PR_NEXT_LINK(&ss->ssl3.hs.remoteKeyShares); - while (cur_p != &ss->ssl3.hs.remoteKeyShares) { + PRCList *cur_p = PR_NEXT_LINK(&ss->xtnData.remoteKeyShares); + while (cur_p != &ss->xtnData.remoteKeyShares) { TLS13KeyShareEntry *offer = (TLS13KeyShareEntry *)cur_p; if (offer->group == group) { return offer; @@ -1155,8 +1156,6 @@ SSL_TRC(3, ("%d: TLS13[%d]: group = %d", SSL_GETPID(), ss->fd, preferredGroup->name)); - SSL_TRC(3, ("%d: TLS13[%d]: group = %d", preferredGroup->name)); - if (!entry) { return tls13_SendHelloRetryRequest(ss, preferredGroup); } @@ -1198,8 +1197,8 @@ rv = ssl_PickSignatureScheme(ss, cert->serverKeyPair->pubKey, cert->serverKeyPair->privKey, - ss->ssl3.hs.clientSigSchemes, - ss->ssl3.hs.numClientSigScheme, + ss->xtnData.clientSigSchemes, + ss->xtnData.numClientSigScheme, PR_FALSE); if (rv == SECSuccess) { /* Found one. */ @@ -1241,8 +1240,8 @@ SSL_TRC(3, ("%d: TLS13[%d]: selected certificate authentication", SSL_GETPID(), ss->fd)); - rv = ssl3_RegisterServerHelloExtensionSender( - ss, ssl_signature_algorithms_xtn, + rv = ssl3_RegisterExtensionSender( + ss, &ss->xtnData, ssl_signature_algorithms_xtn, tls13_ServerSendSigAlgsXtn); if (rv != SECSuccess) { return SECFailure; /* Error code set already. */ @@ -1272,6 +1271,20 @@ int j; ssl3CipherSuite previousCipherSuite; + if (ssl3_ExtensionNegotiated(ss, ssl_tls13_early_data_xtn)) { + ss->ssl3.hs.zeroRttState = ssl_0rtt_sent; + + if (IS_DTLS(ss)) { + /* Save the null spec, which we should be currently reading. We will + * use this when 0-RTT sending is over. */ + ssl_GetSpecReadLock(ss); + ss->ssl3.hs.nullSpec = ss->ssl3.crSpec; + tls13_CipherSpecAddRef(ss->ssl3.hs.nullSpec); + PORT_Assert(ss->ssl3.hs.nullSpec->cipher_def->cipher == cipher_null); + ssl_ReleaseSpecReadLock(ss); + } + } + #ifndef PARANOID /* Look for a matching cipher suite. */ j = ssl3_config_match_init(ss); @@ -1367,8 +1380,9 @@ if (sid->peerCert != NULL) { ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); } - ssl3_RegisterServerHelloExtensionSender( - ss, ssl_tls13_pre_shared_key_xtn, tls13_ServerSendPreSharedKeyXtn); + ssl3_RegisterExtensionSender( + ss, &ss->xtnData, + ssl_tls13_pre_shared_key_xtn, tls13_ServerSendPreSharedKeyXtn); tls13_NegotiateZeroRtt(ss, sid); } else { @@ -1580,8 +1594,8 @@ ss->sec.keaKeyBits = SECKEY_PublicKeyStrengthInBits(keyPair->keys->pubKey); /* Register the sender */ - rv = ssl3_RegisterServerHelloExtensionSender(ss, ssl_tls13_key_share_xtn, - tls13_ServerSendKeyShareXtn); + rv = ssl3_RegisterExtensionSender(ss, &ss->xtnData, ssl_tls13_key_share_xtn, + tls13_ServerSendKeyShareXtn); if (rv != SECSuccess) { return SECFailure; /* Error code set already. */ } @@ -1857,8 +1871,8 @@ } if (ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted) { - rv = ssl3_RegisterServerHelloExtensionSender(ss, ssl_tls13_early_data_xtn, - tls13_ServerSendEarlyDataXtn); + rv = ssl3_RegisterExtensionSender(ss, &ss->xtnData, ssl_tls13_early_data_xtn, + tls13_ServerSendEarlyDataXtn); if (rv != SECSuccess) { return SECFailure; /* Error code set already. */ } @@ -2167,13 +2181,13 @@ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); /* This list should have one entry. */ - if (PR_CLIST_IS_EMPTY(&ss->ssl3.hs.remoteKeyShares)) { + if (PR_CLIST_IS_EMPTY(&ss->xtnData.remoteKeyShares)) { FATAL_ERROR(ss, SSL_ERROR_MISSING_KEY_SHARE, missing_extension); return SECFailure; } - entry = (TLS13KeyShareEntry *)PR_NEXT_LINK(&ss->ssl3.hs.remoteKeyShares); - PORT_Assert(PR_NEXT_LINK(&entry->link) == &ss->ssl3.hs.remoteKeyShares); + entry = (TLS13KeyShareEntry *)PR_NEXT_LINK(&ss->xtnData.remoteKeyShares); + PORT_Assert(PR_NEXT_LINK(&entry->link) == &ss->xtnData.remoteKeyShares); PORT_Assert(ssl_NamedGroupEnabled(ss, entry->group)); @@ -2869,19 +2883,28 @@ /* If we are doing 0-RTT, then we already have an NPN value. Stash * it for comparison. */ if (ss->ssl3.hs.zeroRttState == ssl_0rtt_sent && - ss->ssl3.nextProtoState == SSL_NEXT_PROTO_EARLY_VALUE) { - oldNpn = ss->ssl3.nextProto; - ss->ssl3.nextProto.data = NULL; - ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NO_SUPPORT; + ss->xtnData.nextProtoState == SSL_NEXT_PROTO_EARLY_VALUE) { + oldNpn = ss->xtnData.nextProto; + ss->xtnData.nextProto.data = NULL; + ss->xtnData.nextProtoState = SSL_NEXT_PROTO_NO_SUPPORT; } rv = ssl3_HandleExtensions(ss, &b, &length, encrypted_extensions); if (rv != SECSuccess) { return SECFailure; /* Error code set below */ } - if (ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted) { + /* We can only get here if we offered 0-RTT. */ + if (ssl3_ExtensionNegotiated(ss, ssl_tls13_early_data_xtn)) { + PORT_Assert(ss->ssl3.hs.zeroRttState == ssl_0rtt_sent); + if (!ss->statelessResume) { + /* Illegal to accept 0-RTT without also accepting PSK. */ + FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_ENCRYPTED_EXTENSIONS, + illegal_parameter); + } + ss->ssl3.hs.zeroRttState = ssl_0rtt_accepted; + /* Check that the server negotiated the same ALPN (if any). */ - if (SECITEM_CompareItem(&oldNpn, &ss->ssl3.nextProto)) { + if (SECITEM_CompareItem(&oldNpn, &ss->xtnData.nextProto)) { SECITEM_FreeItem(&oldNpn, PR_FALSE); FATAL_ERROR(ss, SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID, illegal_parameter); @@ -4075,7 +4098,7 @@ * Called from tls13_ClientSendEarlyDataXtn(). */ PRBool -tls13_ClientAllow0Rtt(sslSocket *ss, const sslSessionID *sid) +tls13_ClientAllow0Rtt(const sslSocket *ss, const sslSessionID *sid) { if (sid->version < SSL_LIBRARY_VERSION_TLS_1_3) return PR_FALSE; @@ -4096,11 +4119,12 @@ SECStatus rv; int bufferLen = ss->ssl3.hs.messages.len; - /* Don't do anything if this is the second ClientHello or we decided not to - * do 0-RTT (which means that there is no early_data extension). */ - if (ss->ssl3.hs.zeroRttState != ssl_0rtt_sent) { + /* Don't do anything if there is no early_data xtn, which means we're + * not doing early data. */ + if (!ssl3_ClientExtensionAdvertised(ss, ssl_tls13_early_data_xtn)) { return SECSuccess; } + ss->ssl3.hs.zeroRttState = ssl_0rtt_sent; SSL_TRC(3, ("%d: TLS13[%d]: in 0-RTT mode", SSL_GETPID(), ss->fd)); @@ -4113,8 +4137,8 @@ /* Set the ALPN data as if it was negotiated. We check in the ServerHello * handler that the server negotiates the same value. */ if (ss->sec.ci.sid->u.ssl3.alpnSelection.len) { - ss->ssl3.nextProtoState = SSL_NEXT_PROTO_EARLY_VALUE; - rv = SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, + ss->xtnData.nextProtoState = SSL_NEXT_PROTO_EARLY_VALUE; + rv = SECITEM_CopyItem(NULL, &ss->xtnData.nextProto, &ss->sec.ci.sid->u.ssl3.alpnSelection); if (rv != SECSuccess) return rv; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/tls13con.h firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/tls13con.h --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/tls13con.h 2016-11-11 00:52:59.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/tls13con.h 2016-11-14 00:56:26.000000000 +0000 @@ -69,7 +69,7 @@ PRInt32 tls13_Read0RttData(sslSocket *ss, void *buf, PRInt32 len); SECStatus tls13_HandleEndOfEarlyData(sslSocket *ss); SECStatus tls13_HandleEarlyApplicationData(sslSocket *ss, sslBuffer *origBuf); -PRBool tls13_ClientAllow0Rtt(sslSocket *ss, const sslSessionID *sid); +PRBool tls13_ClientAllow0Rtt(const sslSocket *ss, const sslSessionID *sid); PRUint16 tls13_EncodeDraftVersion(SSL3ProtocolVersion version); PRUint16 tls13_DecodeDraftVersion(PRUint16 version); SECStatus tls13_NegotiateVersion(sslSocket *ss, diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/tls13exthandle.c firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/tls13exthandle.c --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/tls13exthandle.c 2016-11-11 00:52:59.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/tls13exthandle.c 2016-11-14 00:56:26.000000000 +0000 @@ -10,12 +10,14 @@ #include "sslproto.h" #include "sslimpl.h" #include "pk11pub.h" +#include "ssl3ext.h" #include "ssl3exthandle.h" #include "tls13exthandle.h" PRInt32 tls13_ServerSendStatusRequestXtn( - sslSocket *ss, + const sslSocket *ss, + TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { @@ -38,19 +40,19 @@ } if (append) { /* extension_type */ - rv = ssl3_AppendHandshakeNumber(ss, ssl_cert_status_xtn, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_cert_status_xtn, 2); if (rv != SECSuccess) return -1; /* length of extension_data */ - rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 4, 2); if (rv != SECSuccess) return -1; /* status_type == ocsp */ - rv = ssl3_AppendHandshakeNumber(ss, 1 /*ocsp*/, 1); + rv = ssl3_ExtAppendHandshakeNumber(ss, 1 /*ocsp*/, 1); if (rv != SECSuccess) return rv; /* err set by AppendHandshake. */ /* opaque OCSPResponse<1..2^24-1> */ - rv = ssl3_AppendHandshakeVariable(ss, item->data, item->len, 3); + rv = ssl3_ExtAppendHandshakeVariable(ss, item->data, item->len, 3); if (rv != SECSuccess) return rv; /* err set by AppendHandshake. */ } @@ -84,7 +86,7 @@ * * opaque point <1..2^8-1>; */ -PRUint32 +static PRUint32 tls13_SizeOfKeyShareEntry(const SECKEYPublicKey *pubKey) { /* Size = NamedGroup(2) + length(2) + opaque share */ @@ -99,8 +101,8 @@ return 0; } -PRUint32 -tls13_SizeOfClientKeyShareExtension(sslSocket *ss) +static PRUint32 +tls13_SizeOfClientKeyShareExtension(const sslSocket *ss) { PRCList *cursor; /* Size is: extension(2) + extension_len(2) + client_shares(2) */ @@ -114,17 +116,17 @@ return size; } -SECStatus -tls13_EncodeKeyShareEntry(sslSocket *ss, const sslEphemeralKeyPair *keyPair) +static SECStatus +tls13_EncodeKeyShareEntry(const sslSocket *ss, const sslEphemeralKeyPair *keyPair) { SECStatus rv; SECKEYPublicKey *pubKey = keyPair->keys->pubKey; unsigned int size = tls13_SizeOfKeyShareEntry(pubKey); - rv = ssl3_AppendHandshakeNumber(ss, keyPair->group->name, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, keyPair->group->name, 2); if (rv != SECSuccess) return rv; - rv = ssl3_AppendHandshakeNumber(ss, size - 4, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, size - 4, 2); if (rv != SECSuccess) return rv; @@ -145,7 +147,7 @@ } PRInt32 -tls13_ClientSendKeyShareXtn(sslSocket *ss, PRBool append, +tls13_ClientSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { PRUint32 extension_length; @@ -169,17 +171,17 @@ SECStatus rv; PRCList *cursor; - rv = ssl3_AppendHandshakeNumber(ss, ssl_tls13_key_share_xtn, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_key_share_xtn, 2); if (rv != SECSuccess) goto loser; /* The extension length */ - rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 4, 2); if (rv != SECSuccess) goto loser; /* The length of KeyShares */ - rv = ssl3_AppendHandshakeNumber(ss, extension_length - 6, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 6, 2); if (rv != SECSuccess) goto loser; @@ -192,7 +194,7 @@ goto loser; } - ss->xtnData.advertised[ss->xtnData.numAdvertised++] = + xtnData->advertised[xtnData->numAdvertised++] = ssl_tls13_key_share_xtn; } @@ -202,8 +204,8 @@ return -1; } -SECStatus -tls13_HandleKeyShareEntry(sslSocket *ss, SECItem *data) +static SECStatus +tls13_HandleKeyShareEntry(const sslSocket *ss, TLSExtensionData *xtnData, SECItem *data) { SECStatus rv; PRInt32 group; @@ -211,14 +213,14 @@ TLS13KeyShareEntry *ks = NULL; SECItem share = { siBuffer, NULL, 0 }; - group = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len); + group = ssl3_ExtConsumeHandshakeNumber(ss, 2, &data->data, &data->len); if (group < 0) { PORT_SetError(SSL_ERROR_RX_MALFORMED_KEY_SHARE); goto loser; } groupDef = ssl_LookupNamedGroup(group); - rv = ssl3_ConsumeHandshakeVariable(ss, &share, 2, &data->data, - &data->len); + rv = ssl3_ExtConsumeHandshakeVariable(ss, &share, 2, &data->data, + &data->len); if (rv != SECSuccess) { goto loser; } @@ -236,7 +238,7 @@ if (rv != SECSuccess) goto loser; - PR_APPEND_LINK(&ks->link, &ss->ssl3.hs.remoteKeyShares); + PR_APPEND_LINK(&ks->link, &xtnData->remoteKeyShares); return SECSuccess; loser: @@ -244,14 +246,14 @@ tls13_DestroyKeyShareEntry(ks); return SECFailure; } - /* Handle an incoming KeyShare extension at the client and copy to - * |ss->ssl3.hs.remoteKeyShares| for future use. The key + * |xtnData->remoteKeyShares| for future use. The key * share is processed in tls13_HandleServerKeyShare(). */ SECStatus -tls13_ClientHandleKeyShareXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data) +tls13_ClientHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { SECStatus rv; + PORT_Assert(PR_CLIST_IS_EMPTY(&xtnData->remoteKeyShares)); PORT_Assert(!ss->sec.isServer); if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { @@ -265,7 +267,7 @@ SSL_TRC(3, ("%d: SSL3[%d]: handle key_share extension", SSL_GETPID(), ss->fd)); - rv = tls13_HandleKeyShareEntry(ss, data); + rv = tls13_HandleKeyShareEntry(ss, xtnData, data); if (rv != SECSuccess) { PORT_SetError(SSL_ERROR_RX_MALFORMED_KEY_SHARE); return SECFailure; @@ -280,7 +282,7 @@ } SECStatus -tls13_ClientHandleKeyShareXtnHrr(sslSocket *ss, PRUint16 ex_type, SECItem *data) +tls13_ClientHandleKeyShareXtnHrr(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { SECStatus rv; PRInt32 tmp; @@ -292,12 +294,12 @@ SSL_TRC(3, ("%d: SSL3[%d]: handle key_share extension in HRR", SSL_GETPID(), ss->fd)); - tmp = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len); + tmp = ssl3_ExtConsumeHandshakeNumber(ss, 2, &data->data, &data->len); if (tmp < 0) { return SECFailure; /* error code already set */ } if (data->len) { - (void)SSL3_SendAlert(ss, alert_fatal, decode_error); + ssl3_ExtSendAlert(ss, alert_fatal, decode_error); PORT_SetError(SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST); return SECFailure; } @@ -306,15 +308,15 @@ /* If the group is not enabled, or we already have a share for the * requested group, abort. */ if (!ssl_NamedGroupEnabled(ss, group) || - ssl_LookupEphemeralKeyPair(ss, group)) { - (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter); + ssl_HaveEphemeralKeyPair(ss, group)) { + ssl3_ExtSendAlert(ss, alert_fatal, illegal_parameter); PORT_SetError(SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST); return SECFailure; } - rv = tls13_CreateKeyShare(ss, group); + rv = tls13_CreateKeyShare(CONST_CAST(sslSocket, ss), group); if (rv != SECSuccess) { - (void)SSL3_SendAlert(ss, alert_fatal, internal_error); + ssl3_ExtSendAlert(ss, alert_fatal, internal_error); PORT_SetError(SEC_ERROR_KEYGEN_FAIL); return SECFailure; } @@ -323,15 +325,17 @@ } /* Handle an incoming KeyShare extension at the server and copy to - * |ss->ssl3.hs.remoteKeyShares| for future use. The key + * |xtnData->remoteKeyShares| for future use. The key * share is processed in tls13_HandleClientKeyShare(). */ SECStatus -tls13_ServerHandleKeyShareXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data) +tls13_ServerHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { SECStatus rv; PRInt32 length; PORT_Assert(ss->sec.isServer); + PORT_Assert(PR_CLIST_IS_EMPTY(&xtnData->remoteKeyShares)); + if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { return SECSuccess; } @@ -341,8 +345,8 @@ /* Redundant length because of TLS encoding (this vector consumes * the entire extension.) */ - length = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, - &data->len); + length = ssl3_ExtConsumeHandshakeNumber(ss, 2, &data->data, + &data->len); if (length < 0) goto loser; if (length != data->len) { @@ -352,19 +356,19 @@ } while (data->len) { - rv = tls13_HandleKeyShareEntry(ss, data); + rv = tls13_HandleKeyShareEntry(ss, xtnData, data); if (rv != SECSuccess) goto loser; } return SECSuccess; loser: - tls13_DestroyKeyShares(&ss->ssl3.hs.remoteKeyShares); + tls13_DestroyKeyShares(&xtnData->remoteKeyShares); return SECFailure; } PRInt32 -tls13_ServerSendKeyShareXtn(sslSocket *ss, PRBool append, +tls13_ServerSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { PRUint32 extension_length; @@ -387,11 +391,11 @@ } if (append) { - rv = ssl3_AppendHandshakeNumber(ss, ssl_tls13_key_share_xtn, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_key_share_xtn, 2); if (rv != SECSuccess) goto loser; - rv = ssl3_AppendHandshakeNumber(ss, entry_length, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, entry_length, 2); if (rv != SECSuccess) goto loser; @@ -427,7 +431,7 @@ * really a ticket label and there wll be at most one. */ PRInt32 -tls13_ClientSendPreSharedKeyXtn(sslSocket *ss, +tls13_ClientSendPreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { @@ -460,44 +464,44 @@ if (append) { SECStatus rv; /* extension_type */ - rv = ssl3_AppendHandshakeNumber(ss, ssl_tls13_pre_shared_key_xtn, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_pre_shared_key_xtn, 2); if (rv != SECSuccess) goto loser; - rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 4, 2); if (rv != SECSuccess) goto loser; - rv = ssl3_AppendHandshakeNumber(ss, extension_length - 6, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 6, 2); if (rv != SECSuccess) goto loser; - rv = ssl3_AppendHandshakeVariable(ss, ke_modes, ke_modes_len, 1); + rv = ssl3_ExtAppendHandshakeVariable(ss, ke_modes, ke_modes_len, 1); if (rv != SECSuccess) goto loser; - rv = ssl3_AppendHandshakeVariable(ss, auth_modes, auth_modes_len, 1); + rv = ssl3_ExtAppendHandshakeVariable(ss, auth_modes, auth_modes_len, 1); if (rv != SECSuccess) goto loser; - rv = ssl3_AppendHandshakeVariable(ss, session_ticket->ticket.data, - session_ticket->ticket.len, 2); + rv = ssl3_ExtAppendHandshakeVariable(ss, session_ticket->ticket.data, + session_ticket->ticket.len, 2); PRINT_BUF(50, (ss, "Sending PreSharedKey value", session_ticket->ticket.data, session_ticket->ticket.len)); - ss->xtnData.sentSessionTicketInClientHello = PR_TRUE; + xtnData->sentSessionTicketInClientHello = PR_TRUE; if (rv != SECSuccess) goto loser; - ss->xtnData.advertised[ss->xtnData.numAdvertised++] = + xtnData->advertised[xtnData->numAdvertised++] = ssl_tls13_pre_shared_key_xtn; } return extension_length; loser: - ss->xtnData.ticketTimestampVerified = PR_FALSE; + xtnData->ticketTimestampVerified = PR_FALSE; return -1; } /* Handle a TLS 1.3 PreSharedKey Extension. We only accept PSKs * that contain session tickets. */ SECStatus -tls13_ServerHandlePreSharedKeyXtn(sslSocket *ss, PRUint16 ex_type, +tls13_ServerHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { PRInt32 len; @@ -512,7 +516,7 @@ return SECSuccess; } - len = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len); + len = ssl3_ExtConsumeHandshakeNumber(ss, 2, &data->data, &data->len); if (len < 0) return SECFailure; @@ -526,22 +530,22 @@ /* IMPORTANT: We aren't copying these values, just setting pointers. * They will only be valid as long as the ClientHello is in memory. */ - rv = ssl3_ConsumeHandshakeVariable(ss, &ss->xtnData.psk_ke_modes, 1, - &data->data, &data->len); + rv = ssl3_ExtConsumeHandshakeVariable(ss, &xtnData->psk_ke_modes, 1, + &data->data, &data->len); if (rv != SECSuccess) return rv; - if (!ss->xtnData.psk_ke_modes.len) { + if (!xtnData->psk_ke_modes.len) { goto alert_loser; } - rv = ssl3_ConsumeHandshakeVariable(ss, &ss->xtnData.psk_auth_modes, 1, - &data->data, &data->len); + rv = ssl3_ExtConsumeHandshakeVariable(ss, &xtnData->psk_auth_modes, 1, + &data->data, &data->len); if (rv != SECSuccess) return rv; - if (!ss->xtnData.psk_auth_modes.len) { + if (!xtnData->psk_auth_modes.len) { goto alert_loser; } - rv = ssl3_ConsumeHandshakeVariable(ss, &label, 2, - &data->data, &data->len); + rv = ssl3_ExtConsumeHandshakeVariable(ss, &label, 2, + &data->data, &data->len); if (rv != SECSuccess) return rv; if (!label.len) { @@ -553,7 +557,8 @@ PRINT_BUF(50, (ss, "Handling PreSharedKey value", label.data, label.len)); - rv = ssl3_ProcessSessionTicketCommon(ss, &label); + rv = ssl3_ProcessSessionTicketCommon(CONST_CAST(sslSocket, ss), + &label); /* This only happens if we have an internal error, not * a malformed ticket. Bogus tickets just don't resume * and return SECSuccess. */ @@ -564,18 +569,18 @@ /* Keep track of negotiated extensions. Note that this does not * mean we are resuming. */ - ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ex_type; return SECSuccess; alert_loser: - (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter); + ssl3_ExtSendAlert(ss, alert_fatal, illegal_parameter); PORT_SetError(SSL_ERROR_MALFORMED_PRE_SHARED_KEY); return SECFailure; } PRInt32 -tls13_ServerSendPreSharedKeyXtn(sslSocket *ss, +tls13_ServerSendPreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { @@ -589,17 +594,17 @@ } if (append) { - rv = ssl3_AppendHandshakeNumber(ss, ssl_tls13_pre_shared_key_xtn, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_pre_shared_key_xtn, 2); if (rv != SECSuccess) return -1; - rv = ssl3_AppendHandshakeNumber(ss, 2, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, 2, 2); if (rv != SECSuccess) return -1; /* We only process the first session ticket the client sends, * so the index is always 0. */ - rv = ssl3_AppendHandshakeNumber(ss, 0, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2); if (rv != SECSuccess) return -1; } @@ -610,7 +615,7 @@ /* Handle a TLS 1.3 PreSharedKey Extension. We only accept PSKs * that contain session tickets. */ SECStatus -tls13_ClientHandlePreSharedKeyXtn(sslSocket *ss, PRUint16 ex_type, +tls13_ClientHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { PRInt32 index; @@ -623,7 +628,7 @@ return SECSuccess; } - index = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len); + index = ssl3_ExtConsumeHandshakeNumber(ss, 2, &data->data, &data->len); if (index < 0) return SECFailure; @@ -640,7 +645,7 @@ } /* Keep track of negotiated extensions. */ - ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ex_type; return SECSuccess; } @@ -657,7 +662,7 @@ * } EarlyDataIndication; */ PRInt32 -tls13_ClientSendEarlyDataXtn(sslSocket *ss, +tls13_ClientSendEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { @@ -680,11 +685,11 @@ if (append) { PRUint32 age; - rv = ssl3_AppendHandshakeNumber(ss, ssl_tls13_early_data_xtn, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_early_data_xtn, 2); if (rv != SECSuccess) return -1; - rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 4, 2); if (rv != SECSuccess) return -1; @@ -692,20 +697,19 @@ age = ssl_Time() - session_ticket->received_timestamp; age += session_ticket->ticket_age_add; - rv = ssl3_AppendHandshakeNumber(ss, age, 4); + rv = ssl3_ExtAppendHandshakeNumber(ss, age, 4); if (rv != SECSuccess) return -1; } - ss->ssl3.hs.zeroRttState = ssl_0rtt_sent; - ss->xtnData.advertised[ss->xtnData.numAdvertised++] = + xtnData->advertised[xtnData->numAdvertised++] = ssl_tls13_early_data_xtn; return extension_length; } SECStatus -tls13_ServerHandleEarlyDataXtn(sslSocket *ss, PRUint16 ex_type, +tls13_ServerHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { PRUint32 obfuscated_ticket_age; @@ -720,8 +724,8 @@ } /* Obfuscated ticket age. Ignore. Bug 1295163. */ - rv = ssl3_ConsumeHandshake(ss, &obfuscated_ticket_age, 4, - &data->data, &data->len); + rv = ssl3_ExtConsumeHandshake(ss, &obfuscated_ticket_age, 4, + &data->data, &data->len); if (rv != SECSuccess) { return SECFailure; } @@ -731,26 +735,14 @@ return SECFailure; } - if (IS_DTLS(ss)) { - /* Save the null spec, which we should be currently reading. We will - * use this when 0-RTT sending is over. */ - ssl_GetSpecReadLock(ss); - ss->ssl3.hs.nullSpec = ss->ssl3.crSpec; - tls13_CipherSpecAddRef(ss->ssl3.hs.nullSpec); - PORT_Assert(ss->ssl3.hs.nullSpec->cipher_def->cipher == cipher_null); - ssl_ReleaseSpecReadLock(ss); - } - - ss->ssl3.hs.zeroRttState = ssl_0rtt_sent; - - ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ex_type; return SECSuccess; } /* This is only registered if we are sending it. */ -SECStatus -tls13_ServerSendEarlyDataXtn(sslSocket *ss, +PRInt32 +tls13_ServerSendEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { @@ -766,11 +758,11 @@ if (append) { SECStatus rv; - rv = ssl3_AppendHandshakeNumber(ss, ssl_tls13_early_data_xtn, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_early_data_xtn, 2); if (rv != SECSuccess) return -1; - rv = ssl3_AppendHandshakeNumber(ss, 0, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2); if (rv != SECSuccess) return -1; } @@ -780,7 +772,7 @@ /* This will only be called if we also offered the extension. */ SECStatus -tls13_ClientHandleEarlyDataXtn(sslSocket *ss, PRUint16 ex_type, +tls13_ClientHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { SSL_TRC(3, ("%d: TLS13[%d]: handle early_data extension", @@ -798,14 +790,13 @@ } /* Keep track of negotiated extensions. */ - ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; - ss->ssl3.hs.zeroRttState = ssl_0rtt_accepted; + xtnData->negotiated[xtnData->numNegotiated++] = ex_type; return SECSuccess; } SECStatus -tls13_ClientHandleTicketEarlyDataInfoXtn(sslSocket *ss, PRUint16 ex_type, +tls13_ClientHandleTicketEarlyDataInfoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { PRUint32 utmp; @@ -820,8 +811,8 @@ return SECFailure; } - rv = ssl3_ConsumeHandshake(ss, &utmp, sizeof(utmp), - &data->data, &data->len); + rv = ssl3_ExtConsumeHandshake(ss, &utmp, sizeof(utmp), + &data->data, &data->len); if (rv != SECSuccess) { PORT_SetError(SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET); return SECFailure; @@ -831,15 +822,15 @@ return SECFailure; } - ss->xtnData.ticket_age_add_found = PR_TRUE; - ss->xtnData.ticket_age_add = PR_ntohl(utmp); + xtnData->ticket_age_add_found = PR_TRUE; + xtnData->ticket_age_add = PR_ntohl(utmp); return SECSuccess; } /* This is only registered if we are sending it. */ -SECStatus -tls13_ServerSendSigAlgsXtn(sslSocket *ss, +PRInt32 +tls13_ServerSendSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { @@ -853,11 +844,11 @@ if (append) { SECStatus rv; - rv = ssl3_AppendHandshakeNumber(ss, ssl_signature_algorithms_xtn, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_signature_algorithms_xtn, 2); if (rv != SECSuccess) return -1; - rv = ssl3_AppendHandshakeNumber(ss, 0, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2); if (rv != SECSuccess) return -1; } @@ -867,7 +858,7 @@ /* This will only be called if we also offered the extension. */ SECStatus -tls13_ClientHandleSigAlgsXtn(sslSocket *ss, PRUint16 ex_type, +tls13_ClientHandleSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { SSL_TRC(3, ("%d: TLS13[%d]: handle signature_algorithms extension", @@ -885,7 +876,7 @@ } /* Keep track of negotiated extensions. */ - ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ex_type; return SECSuccess; } @@ -896,7 +887,7 @@ * } SupportedVersions; */ PRInt32 -tls13_ClientSendSupportedVersionsXtn(sslSocket *ss, PRBool append, +tls13_ClientSendSupportedVersionsXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { PRInt32 extensions_len; @@ -921,20 +912,20 @@ } if (append) { - rv = ssl3_AppendHandshakeNumber(ss, ssl_tls13_supported_versions_xtn, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_supported_versions_xtn, 2); if (rv != SECSuccess) return -1; - rv = ssl3_AppendHandshakeNumber(ss, extensions_len - 4, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, extensions_len - 4, 2); if (rv != SECSuccess) return -1; - rv = ssl3_AppendHandshakeNumber(ss, extensions_len - 5, 1); + rv = ssl3_ExtAppendHandshakeNumber(ss, extensions_len - 5, 1); if (rv != SECSuccess) return -1; for (version = ss->vrange.max; version >= ss->vrange.min; --version) { - rv = ssl3_AppendHandshakeNumber( + rv = ssl3_ExtAppendHandshakeNumber( ss, tls13_EncodeDraftVersion(version), 2); if (rv != SECSuccess) return -1; @@ -950,7 +941,7 @@ * } Cookie; */ SECStatus -tls13_ClientHandleHrrCookie(sslSocket *ss, PRUint16 ex_type, SECItem *data) +tls13_ClientHandleHrrCookie(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) { SECStatus rv; @@ -960,14 +951,15 @@ PORT_Assert(ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3); /* IMPORTANT: this is only valid while the HelloRetryRequest is still valid. */ - rv = ssl3_ConsumeHandshakeVariable(ss, &ss->ssl3.hs.cookie, 2, - &data->data, &data->len); + rv = ssl3_ExtConsumeHandshakeVariable( + ss, &CONST_CAST(sslSocket, ss)->ssl3.hs.cookie, 2, + &data->data, &data->len); if (rv != SECSuccess) { PORT_SetError(SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST); return SECFailure; } if (!ss->ssl3.hs.cookie.len || data->len) { - (void)SSL3_SendAlert(ss, alert_fatal, decode_error); + ssl3_ExtSendAlert(ss, alert_fatal, decode_error); PORT_SetError(SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST); return SECFailure; } @@ -976,7 +968,7 @@ } PRInt32 -tls13_ClientSendHrrCookieXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes) +tls13_ClientSendHrrCookieXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) { PRInt32 extension_len; @@ -996,16 +988,16 @@ } if (append) { - SECStatus rv = ssl3_AppendHandshakeNumber(ss, ssl_tls13_cookie_xtn, 2); + SECStatus rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_cookie_xtn, 2); if (rv != SECSuccess) return -1; - rv = ssl3_AppendHandshakeNumber(ss, extension_len - 4, 2); + rv = ssl3_ExtAppendHandshakeNumber(ss, extension_len - 4, 2); if (rv != SECSuccess) return -1; - rv = ssl3_AppendHandshakeVariable(ss, ss->ssl3.hs.cookie.data, - ss->ssl3.hs.cookie.len, 2); + rv = ssl3_ExtAppendHandshakeVariable(ss, ss->ssl3.hs.cookie.data, + ss->ssl3.hs.cookie.len, 2); if (rv != SECSuccess) return -1; } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/tls13exthandle.h firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/tls13exthandle.h --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/lib/ssl/tls13exthandle.h 2016-11-11 00:52:59.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/lib/ssl/tls13exthandle.h 2016-11-14 00:56:26.000000000 +0000 @@ -9,45 +9,58 @@ #ifndef __tls13exthandle_h_ #define __tls13exthandle_h_ -PRInt32 tls13_ServerSendStatusRequestXtn(sslSocket *ss, +PRInt32 tls13_ServerSendStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes); -PRInt32 tls13_ClientSendKeyShareXtn(sslSocket *ss, PRBool append, +PRInt32 tls13_ClientSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes); -SECStatus tls13_ClientHandleKeyShareXtn(sslSocket *ss, +SECStatus tls13_ClientHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); -SECStatus tls13_ClientHandleKeyShareXtnHrr(sslSocket *ss, +SECStatus tls13_ClientHandleKeyShareXtnHrr(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); -SECStatus tls13_ServerHandleKeyShareXtn(sslSocket *ss, +SECStatus tls13_ServerHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); -PRInt32 tls13_ClientSendPreSharedKeyXtn(sslSocket *ss, PRBool append, +PRInt32 tls13_ServerSendKeyShareXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + PRBool append, + PRUint32 maxBytes); +PRInt32 tls13_ClientSendPreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes); -SECStatus tls13_ServerHandlePreSharedKeyXtn(sslSocket *ss, +SECStatus tls13_ServerHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); -SECStatus tls13_ClientHandlePreSharedKeyXtn(sslSocket *ss, +SECStatus tls13_ClientHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); -PRInt32 tls13_ClientSendEarlyDataXtn(sslSocket *ss, +PRInt32 tls13_ServerSendPreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData, + PRBool append, + PRUint32 maxBytes); +PRInt32 tls13_ClientSendEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes); -SECStatus tls13_ServerHandleEarlyDataXtn(sslSocket *ss, PRUint16 ex_type, +SECStatus tls13_ServerHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); -SECStatus tls13_ClientHandleEarlyDataXtn(sslSocket *ss, PRUint16 ex_type, +SECStatus tls13_ClientHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); +PRInt32 tls13_ServerSendEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, + PRBool append, + PRUint32 maxBytes); SECStatus tls13_ClientHandleTicketEarlyDataInfoXtn( - sslSocket *ss, PRUint16 ex_type, + const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); -SECStatus tls13_ClientHandleSigAlgsXtn(sslSocket *ss, PRUint16 ex_type, +SECStatus tls13_ClientHandleSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); -PRInt32 tls13_ClientSendSupportedVersionsXtn(sslSocket *ss, +PRInt32 tls13_ServerSendSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, + PRBool append, + PRUint32 maxBytes); +PRInt32 tls13_ClientSendSupportedVersionsXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes); -SECStatus tls13_ClientHandleHrrCookie(sslSocket *ss, PRUint16 ex_type, +SECStatus tls13_ClientHandleHrrCookie(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data); -PRInt32 tls13_ClientSendHrrCookieXtn(sslSocket *ss, +PRInt32 tls13_ClientSendHrrCookieXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/security/nss/TAG-INFO firefox-trunk-52.0~a1~hg20161113r322177/security/nss/TAG-INFO --- firefox-trunk-52.0~a1~hg20161110r321971/security/nss/TAG-INFO 2016-11-11 02:11:08.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/security/nss/TAG-INFO 2016-11-14 02:12:16.000000000 +0000 @@ -1 +1 @@ -457e3b2beeb9 +5d2424d699a0 diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/SOURCE_CHANGESET firefox-trunk-52.0~a1~hg20161113r322177/SOURCE_CHANGESET --- firefox-trunk-52.0~a1~hg20161110r321971/SOURCE_CHANGESET 2016-11-11 02:20:22.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/SOURCE_CHANGESET 2016-11-14 02:25:46.000000000 +0000 @@ -1 +1 @@ -d38d06f85ef59c5dbb5d4a1a8d895957a78714de \ No newline at end of file +47e0584afe0ab0b867412189c610b302b6ba0ea7 \ No newline at end of file diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/taskcluster/ci/desktop-test/tests.yml firefox-trunk-52.0~a1~hg20161113r322177/taskcluster/ci/desktop-test/tests.yml --- firefox-trunk-52.0~a1~hg20161110r321971/taskcluster/ci/desktop-test/tests.yml 2016-11-11 00:54:53.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/taskcluster/ci/desktop-test/tests.yml 2016-11-14 01:00:11.000000000 +0000 @@ -178,6 +178,7 @@ suite: marionette treeherder-symbol: tc(Mn) max-run-time: 5400 + docker-image: {"in-tree": "desktop1604-test"} mozharness: script: marionette.py no-read-buildbot-config: true diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/taskcluster/ci/docker-image/image.yml firefox-trunk-52.0~a1~hg20161113r322177/taskcluster/ci/docker-image/image.yml --- firefox-trunk-52.0~a1~hg20161110r321971/taskcluster/ci/docker-image/image.yml 2016-11-11 00:54:53.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/taskcluster/ci/docker-image/image.yml 2016-11-14 01:00:11.000000000 +0000 @@ -10,45 +10,54 @@ source: '{{source}}' owner: mozilla-taskcluster-maintenance@mozilla.com tags: - createdForUser: {{owner}} + createdForUser: '{{owner}}' workerType: taskcluster-images provisionerId: aws-provisioner-v1 schedulerId: task-graph-scheduler routes: - - index.docker.images.v1.{{project}}.{{image_name}}.latest - - index.docker.images.v1.{{project}}.{{image_name}}.pushdate.{{year}}.{{month}}-{{day}}-{{pushtime}} - - index.docker.images.v1.{{project}}.{{image_name}}.hash.{{context_hash}} + # Indexing routes to avoid building the same image twice + - index.{{index_image_prefix}}.level-{{level}}.{{image_name}}.latest + - index.{{index_image_prefix}}.level-{{level}}.{{image_name}}.pushdate.{{year}}.{{month}}-{{day}}-{{pushtime}} + - index.{{index_image_prefix}}.level-{{level}}.{{image_name}}.hash.{{context_hash}} + # Treeherder routes - tc-treeherder.v2.{{project}}.{{head_rev}}.{{pushlog_id}} - tc-treeherder-stage.v2.{{project}}.{{head_rev}}.{{pushlog_id}} + scopes: + - secrets:get:project/taskcluster/gecko/hgfingerprint + - docker-worker:cache:level-{{level}}-imagebuilder-v1 + payload: env: HASH: '{{context_hash}}' PROJECT: '{{project}}' CONTEXT_URL: '{{context_url}}' - CONTEXT_PATH: '{{context_path}}' - BASE_REPOSITORY: '{{base_repository}}' - HEAD_REPOSITORY: '{{head_repository}}' - HEAD_REV: '{{head_rev}}' - HEAD_REF: '{{head_ref}}' + IMAGE_NAME: '{{image_name}}' + GECKO_BASE_REPOSITORY: '{{base_repository}}' + GECKO_HEAD_REPOSITORY: '{{head_repository}}' + GECKO_HEAD_REV: '{{head_rev}}' + HG_STORE_PATH: '/home/worker/checkouts/hg-store' + cache: + 'level-{{level}}-imagebuilder-v1': '/home/worker/checkouts' features: dind: true chainOfTrust: true + taskclusterProxy: true image: '{{#docker_image}}image_builder{{/docker_image}}' - command: - - /bin/bash - - -c - - /home/worker/bin/build_image.sh maxRunTime: 3600 artifacts: '{{artifact_path}}': type: 'file' - path: '/artifacts/image.tar' + path: '/home/worker/workspace/artifacts/image.tar.zst' expires: relative-datestamp: "1 year" extra: + imageMeta: # Useful when converting back from JSON in action tasks + level: '{{level}}' + contextHash: '{{context_hash}}' + imageName: '{{image_name}}' treeherderEnv: - staging - production @@ -57,4 +66,3 @@ build: platform: 'taskcluster-images' symbol: 'I' - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/taskcluster/mach_commands.py firefox-trunk-52.0~a1~hg20161113r322177/taskcluster/mach_commands.py --- firefox-trunk-52.0~a1~hg20161110r321971/taskcluster/mach_commands.py 2016-11-11 00:54:54.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/taskcluster/mach_commands.py 2016-11-14 01:00:12.000000000 +0000 @@ -274,11 +274,17 @@ description='Build a Docker image') @CommandArgument('image_name', help='Name of the image to build') - def build_image(self, image_name): - from taskgraph.docker import build_image - + @CommandArgument('--context-only', + help="File name the context tarball should be written to." + "with this option it will only build the context.tar.", + metavar='context.tar') + def build_image(self, image_name, context_only): + from taskgraph.docker import build_image, build_context try: - build_image(image_name) + if context_only is None: + build_image(image_name) + else: + build_context(image_name, context_only) except Exception: traceback.print_exc() sys.exit(1) diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/taskcluster/taskgraph/docker.py firefox-trunk-52.0~a1~hg20161113r322177/taskcluster/taskgraph/docker.py --- firefox-trunk-52.0~a1~hg20161110r321971/taskcluster/taskgraph/docker.py 2016-11-11 00:55:46.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/taskcluster/taskgraph/docker.py 2016-11-14 01:00:12.000000000 +0000 @@ -18,7 +18,7 @@ GECKO = os.path.realpath(os.path.join(__file__, '..', '..', '..')) IMAGE_DIR = os.path.join(GECKO, 'testing', 'docker') -INDEX_URL = 'https://index.taskcluster.net/v1/task/docker.images.v1.{}.{}.hash.{}' +INDEX_URL = 'https://index.taskcluster.net/v1/task/' + docker.INDEX_PREFIX + '.{}.{}.hash.{}' ARTIFACT_URL = 'https://queue.taskcluster.net/v1/task/{}/artifacts/{}' @@ -39,9 +39,14 @@ # read it back. filename = 'temp-docker-image.tar' - artifact_url = ARTIFACT_URL.format(task_id, 'public/image.tar') + artifact_url = ARTIFACT_URL.format(task_id, 'public/image.tar.zst') print("Downloading", artifact_url) - subprocess.check_call(['curl', '-#', '-L', '-o', filename, artifact_url]) + tempfilename = 'temp-docker-image.tar.zst' + subprocess.check_call(['curl', '-#', '-L', '-o', tempfilename, artifact_url]) + print("Decompressing") + subprocess.check_call(['zstd', '-d', tempfilename, '-o', filename]) + print("Deleting temporary file") + os.unlink(tempfilename) print("Determining image name") tf = tarfile.open(filename) @@ -66,6 +71,21 @@ print("Try: docker run -ti --rm {} bash".format(name)) +def build_context(name, outputFile): + """Build a context.tar for image with specified name. + """ + if not name: + raise ValueError('must provide a Docker image name') + if not outputFile: + raise ValueError('must provide a outputFile') + + image_dir = os.path.join(IMAGE_DIR, name) + if not os.path.isdir(image_dir): + raise Exception('image directory does not exist: %s' % image_dir) + + docker.create_context_tar(GECKO, image_dir, outputFile, "") + + def build_image(name): """Build a Docker image of specified name. diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/taskcluster/taskgraph/task/docker_image.py firefox-trunk-52.0~a1~hg20161113r322177/taskcluster/taskgraph/task/docker_image.py --- firefox-trunk-52.0~a1~hg20161110r321971/taskcluster/taskgraph/task/docker_image.py 2016-11-11 00:55:46.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/taskcluster/taskgraph/task/docker_image.py 2016-11-14 01:00:12.000000000 +0000 @@ -7,14 +7,13 @@ import logging import json import os -import re import urllib2 from . import base from taskgraph.util.docker import ( - create_context_tar, docker_image, generate_context_hash, + INDEX_PREFIX, ) from taskgraph.util.templates import Templates @@ -22,7 +21,6 @@ GECKO = os.path.realpath(os.path.join(__file__, '..', '..', '..', '..')) ARTIFACT_URL = 'https://queue.taskcluster.net/v1/task/{}/artifacts/{}' INDEX_URL = 'https://index.taskcluster.net/v1/task/{}' -INDEX_REGEX = r'index\.(docker\.images\.v1\.(.+)\.(.+)\.hash\.(.+))' class DockerImageTask(base.Task): @@ -54,57 +52,31 @@ 'level': params['level'], 'source': '{repo}file/{rev}/taskcluster/ci/docker-image/image.yml' .format(repo=params['head_repository'], rev=params['head_rev']), + 'index_image_prefix': INDEX_PREFIX, + 'artifact_path': 'public/image.tar.zst', } tasks = [] templates = Templates(path) for image_name in config['images']: context_path = os.path.join('testing', 'docker', image_name) + context_hash = generate_context_hash(GECKO, context_path, image_name) image_parameters = dict(parameters) - image_parameters['context_path'] = context_path - image_parameters['artifact_path'] = 'public/image.tar' image_parameters['image_name'] = image_name - - image_artifact_path = \ - "public/docker_image_contexts/{}/context.tar.gz".format(image_name) - if os.environ.get('TASK_ID'): - # We put image context tar balls in a different artifacts folder - # on the Gecko decision task in order to have longer expiration - # dates for smaller artifacts. - destination = os.path.join( - os.environ['HOME'], - "docker_image_contexts/{}/context.tar.gz".format(image_name)) - image_parameters['context_url'] = ARTIFACT_URL.format( - os.environ['TASK_ID'], image_artifact_path) - - destination = os.path.abspath(destination) - if not os.path.exists(os.path.dirname(destination)): - os.makedirs(os.path.dirname(destination)) - - context_hash = create_context_tar(GECKO, context_path, - destination, image_name) - else: - # skip context generation since this isn't a decision task - # TODO: generate context tarballs using subdirectory clones in - # the image-building task so we don't have to worry about this. - image_parameters['context_url'] = 'file:///tmp/' + image_artifact_path - context_hash = generate_context_hash(GECKO, context_path, image_name) - image_parameters['context_hash'] = context_hash image_task = templates.load('image.yml', image_parameters) - attributes = {'image_name': image_name} - # As an optimization, if the context hash exists for mozilla-central, that image + # As an optimization, if the context hash exists for a high level, that image # task ID will be used. The reasoning behind this is that eventually everything ends - # up on mozilla-central at some point if most tasks use this as a common image + # up on level 3 at some point if most tasks use this as a common image # for a given context hash, a worker within Taskcluster does not need to contain # the same image per branch. - index_paths = ['docker.images.v1.{}.{}.hash.{}'.format( - project, image_name, context_hash) - for project in ['mozilla-central', params['project']]] + index_paths = ['{}.level-{}.{}.hash.{}'.format( + INDEX_PREFIX, level, image_name, context_hash) + for level in range(int(params['level']), 4)] tasks.append(cls(kind, 'build-docker-image-' + image_name, task=image_task['task'], attributes=attributes, @@ -126,7 +98,7 @@ # artifact, but 'project' might not. Only return no task ID if all # branches have been tried request = urllib2.Request( - ARTIFACT_URL.format(existing_task['taskId'], 'public/image.tar')) + ARTIFACT_URL.format(existing_task['taskId'], 'public/image.tar.zst')) request.get_method = lambda: 'HEAD' urllib2.urlopen(request) @@ -140,15 +112,12 @@ @classmethod def from_json(cls, task_dict): # Generating index_paths for optimization - routes = task_dict['task']['routes'] - index_paths = [] - for route in routes: - index_path_regex = re.compile(INDEX_REGEX) - result = index_path_regex.search(route) - if result is None: - continue - index_paths.append(result.group(1)) - index_paths.append(result.group(1).replace(result.group(2), 'mozilla-central')) + imgMeta = task_dict['task']['extra']['imageMeta'] + image_name = imgMeta['imageName'] + context_hash = imgMeta['contextHash'] + index_paths = ['{}.level-{}.{}.hash.{}'.format( + INDEX_PREFIX, level, image_name, context_hash) + for level in range(int(imgMeta['level']), 4)] docker_image_task = cls(kind='docker-image', label=task_dict['label'], attributes=task_dict['attributes'], diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/taskcluster/taskgraph/test/test_taskgraph.py firefox-trunk-52.0~a1~hg20161113r322177/taskcluster/taskgraph/test/test_taskgraph.py --- firefox-trunk-52.0~a1~hg20161110r321971/taskcluster/taskgraph/test/test_taskgraph.py 2016-11-11 00:55:46.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/taskcluster/taskgraph/test/test_taskgraph.py 2016-11-14 01:00:13.000000000 +0000 @@ -11,11 +11,24 @@ from ..task.transform import TransformTask from ..taskgraph import TaskGraph from mozunit import main +from taskgraph.util.docker import INDEX_PREFIX class TestTargetTasks(unittest.TestCase): def test_from_json(self): + task = { + "routes": [], + "extra": { + "imageMeta": { + "contextHash": "", + "imageName": "", + "level": "1" + } + } + } + index_paths = ["{}.level-{}..hash.".format(INDEX_PREFIX, level) + for level in range(1, 4)] graph = TaskGraph(tasks={ 'a': TransformTask( kind='fancy', @@ -29,8 +42,8 @@ 'b': DockerImageTask(kind='docker-image', label='b', attributes={}, - task={"routes": []}, - index_paths=[]), + task=task, + index_paths=index_paths), }, graph=Graph(nodes={'a', 'b'}, edges=set())) tasks, new_graph = TaskGraph.from_json(graph.to_json()) diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/taskcluster/taskgraph/transforms/task.py firefox-trunk-52.0~a1~hg20161113r322177/taskcluster/taskgraph/transforms/task.py --- firefox-trunk-52.0~a1~hg20161110r321971/taskcluster/taskgraph/transforms/task.py 2016-11-11 00:55:47.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/taskcluster/taskgraph/transforms/task.py 2016-11-14 01:00:13.000000000 +0000 @@ -349,7 +349,7 @@ docker_image_task = 'build-docker-image-' + image['in-tree'] task.setdefault('dependencies', {})['docker-image'] = docker_image_task image = { - "path": "public/image.tar", + "path": "public/image.tar.zst", "taskId": {"task-reference": ""}, "type": "task-image", } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/taskcluster/taskgraph/util/docker.py firefox-trunk-52.0~a1~hg20161113r322177/taskcluster/taskgraph/util/docker.py --- firefox-trunk-52.0~a1~hg20161110r321971/taskcluster/taskgraph/util/docker.py 2016-11-11 00:55:48.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/taskcluster/taskgraph/util/docker.py 2016-11-14 01:00:14.000000000 +0000 @@ -18,6 +18,7 @@ GECKO = os.path.realpath(os.path.join(__file__, '..', '..', '..', '..')) DOCKER_ROOT = os.path.join(GECKO, 'testing', 'docker') +INDEX_PREFIX = 'docker.images.v2' ARTIFACT_URL = 'https://queue.taskcluster.net/v1/task/{}/artifacts/{}' diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/.taskcluster.yml firefox-trunk-52.0~a1~hg20161113r322177/.taskcluster.yml --- firefox-trunk-52.0~a1~hg20161110r321971/.taskcluster.yml 2016-11-11 00:52:58.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/.taskcluster.yml 2016-11-14 00:56:25.000000000 +0000 @@ -119,10 +119,6 @@ type: 'directory' path: '/home/worker/artifacts' expires: '{{#from_now}}364 days{{/from_now}}' - 'public/docker_image_contexts': - type: 'directory' - path: '/home/worker/docker_image_contexts' - expires: '{{#from_now}}7 days{{/from_now}}' extra: treeherder: diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/cppunittest.ini firefox-trunk-52.0~a1~hg20161113r322177/testing/cppunittest.ini --- firefox-trunk-52.0~a1~hg20161110r321971/testing/cppunittest.ini 2016-11-11 00:55:48.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/cppunittest.ini 2016-11-14 01:00:38.000000000 +0000 @@ -15,9 +15,6 @@ [TestCookie] [TestCountPopulation] [TestCountZeroes] -[TestDeadlockDetector] -skip-if = os == 'b2g' || (os == 'android' && debug) # Bug 1054249 -[TestDeadlockDetectorScalability] [TestDllInterceptor] skip-if = os != 'win' [TestEndian] diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/docker/image_builder/bin/build_image.sh firefox-trunk-52.0~a1~hg20161113r322177/testing/docker/image_builder/bin/build_image.sh --- firefox-trunk-52.0~a1~hg20161110r321971/testing/docker/image_builder/bin/build_image.sh 2016-11-11 00:55:49.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/docker/image_builder/bin/build_image.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -#!/bin/bash -vex - -# Set bash options to exit immediately if a pipeline exists non-zero, expand -# print a trace of commands, and make output verbose (print shell input as it's -# read) -# See https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html -set -x -e -v - -# Prefix errors with taskcluster error prefix so that they are parsed by Treeherder -raise_error() { - echo - echo "[taskcluster-image-build:error] $1" - exit 1 -} - -# Ensure that the PROJECT is specified so the image can be indexed -test -n "$PROJECT" || raise_error "Project must be provided." -test -n "$HASH" || raise_error "Context Hash must be provided." - -mkdir /artifacts - -if [ ! -z "$CONTEXT_URL" ]; then - mkdir /context - if ! curl -L --retry 5 --connect-timeout 30 --fail "$CONTEXT_URL" | tar -xz --strip-components 1 -C /context; then - raise_error "Error downloading image context from decision task." - fi - CONTEXT_PATH=/context -else - tc-vcs checkout /home/worker/workspace/src $BASE_REPOSITORY $HEAD_REPOSITORY $HEAD_REV $HEAD_REF - CONTEXT_PATH=/home/worker/workspace/src/$CONTEXT_PATH -fi - -test -d $CONTEXT_PATH || raise_error "Context Path $CONTEXT_PATH does not exist." -test -f "$CONTEXT_PATH/Dockerfile" || raise_error "Dockerfile must be present in $CONTEXT_PATH." - -docker build -t $PROJECT:$HASH $CONTEXT_PATH -docker save $PROJECT:$HASH > /artifacts/image.tar diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/docker/image_builder/build-image.sh firefox-trunk-52.0~a1~hg20161113r322177/testing/docker/image_builder/build-image.sh --- firefox-trunk-52.0~a1~hg20161110r321971/testing/docker/image_builder/build-image.sh 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/docker/image_builder/build-image.sh 2016-11-14 01:00:39.000000000 +0000 @@ -0,0 +1,59 @@ +#!/bin/bash -vex + +# Set bash options to exit immediately if a pipeline exists non-zero, expand +# print a trace of commands, and make output verbose (print shell input as it's +# read) +# See https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html +set -x -e -v + +# Prefix errors with taskcluster error prefix so that they are parsed by Treeherder +raise_error() { + echo + echo "[taskcluster-image-build:error] $1" + exit 1 +} + +# Ensure that the PROJECT is specified so the image can be indexed +test -n "$PROJECT" || raise_error "PROJECT must be provided." +test -n "$HASH" || raise_error "Context HASH must be provided." +test -n "$IMAGE_NAME" || raise_error "IMAGE_NAME must be provided." + +# Create artifact folder +mkdir -p /home/worker/workspace/artifacts + +# Construct a CONTEXT_FILE +CONTEXT_FILE=/home/worker/workspace/context.tar + +# Run ./mach taskcluster-build-image with --context-only to build context +run-task \ + --chown-recursive "/home/worker/workspace" \ + --vcs-checkout "/home/worker/checkouts/gecko" \ + -- \ + /home/worker/checkouts/gecko/mach taskcluster-build-image \ + --context-only "$CONTEXT_FILE" \ + "$IMAGE_NAME" +test -f "$CONTEXT_FILE" || raise_error "Context file wasn't created" + +# Post context tar-ball to docker daemon +# This interacts directly with the docker remote API, see: +# https://docs.docker.com/engine/reference/api/docker_remote_api_v1.18/ +curl -s \ + -X POST \ + --header 'Content-Type: application/tar' \ + --data-binary "@$CONTEXT_FILE" \ + --unix-socket /var/run/docker.sock "http:/build?t=$IMAGE_NAME:$HASH" \ + | tee /tmp/docker-build.log \ + | jq -r '.status + .progress, .stream[:-1], .error | select(. != null)' + +# Exit non-zero if there is error entries in the log +if cat /tmp/docker-build.log | jq -se 'add | .error' > /dev/null; then + raise_error "Image build failed: `cat /tmp/docker-build.log | jq -rse 'add | .error'`"; +fi + +# Get image from docker daemon +# This interacts directly with the docker remote API, see: +# https://docs.docker.com/engine/reference/api/docker_remote_api_v1.18/ +curl -s \ + -X GET \ + --unix-socket /var/run/docker.sock "http:/images/$IMAGE_NAME:$HASH/get" \ + | zstd -3 -c -o /home/worker/workspace/artifacts/image.tar.zst diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/docker/image_builder/Dockerfile firefox-trunk-52.0~a1~hg20161113r322177/testing/docker/image_builder/Dockerfile --- firefox-trunk-52.0~a1~hg20161110r321971/testing/docker/image_builder/Dockerfile 2016-11-11 00:55:49.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/docker/image_builder/Dockerfile 2016-11-14 01:00:39.000000000 +0000 @@ -1,34 +1,40 @@ -FROM ubuntu:14.04 +FROM ubuntu:16.04 -WORKDIR /home/worker/bin +# %include testing/docker/recipes/tooltool.py +ADD topsrcdir/testing/docker/recipes/tooltool.py /setup/tooltool.py -RUN apt-get update && apt-get install -y apt-transport-https -RUN sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9 && \ - sudo sh -c "echo deb https://get.docker.io/ubuntu docker main\ - > /etc/apt/sources.list.d/docker.list" -RUN apt-get update && apt-get install -y \ - lxc-docker-1.6.1 \ - curl \ - wget \ - git \ - mercurial \ - tar \ - zip \ - unzip \ - vim \ - sudo \ - ca-certificates \ - build-essential - -ENV NODE_VERSION v0.12.4 -RUN cd /usr/local/ && \ - curl https://nodejs.org/dist/$NODE_VERSION/node-$NODE_VERSION-linux-x64.tar.gz | tar -xz --strip-components 1 && \ - node -v +# %include testing/docker/recipes/common.sh +ADD topsrcdir/testing/docker/recipes/common.sh /setup/common.sh -RUN npm install -g taskcluster-vcs@2.3.11 - -ADD bin /home/worker/bin -RUN chmod +x /home/worker/bin/* - -# Set a default command useful for debugging -CMD ["/bin/bash", "--login"] +# %include testing/docker/recipes/install-mercurial.sh +ADD topsrcdir/testing/docker/recipes/install-mercurial.sh /setup/install-mercurial.sh + +# %include testing/mozharness/external_tools/robustcheckout.py +ADD topsrcdir/testing/mozharness/external_tools/robustcheckout.py /usr/local/mercurial/robustcheckout.py + +# %include testing/docker/recipes/run-task +ADD topsrcdir/testing/docker/recipes/run-task /usr/local/bin/run-task + +# Add and run setup script +ADD build-image.sh /usr/local/bin/build-image.sh +ADD setup.sh /setup/setup.sh +RUN bash /setup/setup.sh + +# Setup a workspace that won't use AUFS +VOLUME /home/worker/workspace + +# Set variable normally configured at login, by the shells parent process, these +# are taken from GNU su manual +ENV HOME /home/worker +ENV SHELL /bin/bash +ENV USER worker +ENV LOGNAME worker +ENV HOSTNAME taskcluster-worker +ENV LC_ALL C + +# Create worker user +RUN useradd -d /home/worker -s /bin/bash -m worker + +# Set some sane defaults +WORKDIR /home/worker/ +CMD build-image.sh diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/docker/image_builder/setup.sh firefox-trunk-52.0~a1~hg20161113r322177/testing/docker/image_builder/setup.sh --- firefox-trunk-52.0~a1~hg20161110r321971/testing/docker/image_builder/setup.sh 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/docker/image_builder/setup.sh 2016-11-14 01:00:39.000000000 +0000 @@ -0,0 +1,53 @@ +#!/bin/bash -vex +set -v -e -x + +export DEBIAN_FRONTEND=noninteractive + +# Update apt-get lists +apt-get update -y + +# Install dependencies +apt-get install -y \ + curl \ + tar \ + jq \ + python \ + build-essential # Only needed for zstd installation, will be removed later + +# Install mercurial +. /setup/common.sh +. /setup/install-mercurial.sh + +# Install build-image.sh script +chmod +x /usr/local/bin/build-image.sh +chmod +x /usr/local/bin/run-task + +# Create workspace +mkdir -p /home/worker/workspace + +# Install zstd 1.1.1 +cd /setup +tooltool_fetch <= 0`); item.button = actionItem.button; break; case action.PointerMove: item.duration = actionItem.duration; if (typeof item.duration != "undefined"){ - assertPositiveInteger(item.duration, "duration"); + assert.positiveInteger(item.duration, + error.pprint`Expected 'duration' (${item.duration}) to be >= 0`); } if (typeof actionItem.element != "undefined" && !element.isWebElementReference(actionItem.element)) { @@ -267,11 +265,11 @@ item.x = actionItem.x; if (typeof item.x != "undefined") { - assertPositiveInteger(item.x, "x"); + assert.positiveInteger(item.x, error.pprint`Expected 'x' (${item.x}) to be >= 0`); } item.y = actionItem.y; if (typeof item.y != "undefined") { - assertPositiveInteger(item.y, "y"); + assert.positiveInteger(item.y, error.pprint`Expected 'y' (${item.y}) to be >= 0`); } break; @@ -282,7 +280,8 @@ case action.Pause: item.duration = actionItem.duration; if (typeof item.duration != "undefined") { - assertPositiveInteger(item.duration, "duration"); + assert.positiveInteger(item.duration, + error.pprint`Expected 'duration' (${item.duration}) to be >= 0`); } break; } @@ -390,7 +389,7 @@ action.PointerParameters = class { constructor(pointerType = "mouse", primary = true) { this.pointerType = action.PointerType.get(pointerType); - assertBoolean(primary, "primary"); + assert.boolean(primary); this.primary = primary; }; @@ -441,20 +440,6 @@ }; // helpers -function assertPositiveInteger(value, name = undefined) { - let suffix = name ? ` (${name})` : ''; - if (!Number.isInteger(value) || value < 0) { - throw new InvalidArgumentError(`Expected integer >= 0${suffix}, got: ${value}`); - } -} - -function assertBoolean(value, name = undefined) { - let suffix = name ? ` (${name})` : ''; - if (typeof(value) != "boolean") { - throw new InvalidArgumentError(`Expected boolean${suffix}, got: ${value}`); - } -} - function capitalize(str) { if (typeof str != "string") { throw new InvalidArgumentError(`Expected string, got: ${str}`); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/marionette/assert.js firefox-trunk-52.0~a1~hg20161113r322177/testing/marionette/assert.js --- firefox-trunk-52.0~a1~hg20161110r321971/testing/marionette/assert.js 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/marionette/assert.js 2016-11-14 01:01:13.000000000 +0000 @@ -0,0 +1,220 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const {classes: Cc, interfaces: Ci, utils: Cu} = Components; + +Cu.import("resource://gre/modules/AppConstants.jsm"); +Cu.import("resource://gre/modules/Preferences.jsm"); + +Cu.import("chrome://marionette/content/error.js"); + +this.EXPORTED_SYMBOLS = ["assert"]; + +const isFennec = () => AppConstants.platform == "android"; +const isB2G = () => AppConstants.MOZ_B2G; +const isFirefox = () => Services.appinfo.name == "Firefox"; + +/** Shorthands for common assertions made in Marionette. */ +this.assert = {}; + +/** + * Asserts that the current browser is Firefox Desktop. + * + * @param {string=} msg + * Custom error message. + * + * @throws {UnsupportedOperationError} + * If current browser is not Firefox. + */ +assert.firefox = function(msg = "") { + msg = msg || "Expected Firefox"; + assert.that(isFirefox, msg, UnsupportedOperationError)(); +}; + +/** + * Asserts that the current browser is Fennec, or Firefox for Android. + * + * @param {string=} msg + * Custom error message. + * + * @throws {UnsupportedOperationError} + * If current browser is not Fennec. + */ +assert.fennec = function(msg = "") { + msg = msg || "Expected Fennec"; + assert.that(isFennec, msg, UnsupportedOperationError)(); +}; + +/** + * Asserts that the current browser is B2G. + * + * @param {string=} msg + * Custom error message. + * + * @throws {UnsupportedOperationError} + * If the current browser is not B2G. + */ +assert.b2g = function(msg = "") { + msg = msg || "Expected B2G" + assert.that(isB2G, msg, UnsupportedOperationError)(); +}; + +/** + * Asserts that the current browser is a mobile browser, that is either + * B2G or Fennec. + * + * @param {string=} msg + * Custom error message. + * + * @throws {UnsupportedOperationError} + * If the current browser is not B2G or Fennec. + */ +assert.mobile = function(msg = "") { + msg = msg || "Expected Fennec or B2G"; + assert.that(() => isFennec() || isB2G(), msg, UnsupportedOperationError)(); +}; + +/** + * Asserts that |obj| is defined. + * + * @param {?} obj + * Value to test. + * @param {string=} msg + * Custom error message. + * + * @return {?} + * |obj| is returned unaltered. + * + * @throws {InvalidArgumentError} + * If |obj| is not defined. + */ +assert.defined = function(obj, msg = "") { + msg = msg || error.pprint`Expected ${obj} to be defined`; + return assert.that(o => typeof o != "undefined", msg)(obj); +}; + +/** + * Asserts that |obj| is an integer. + * + * @param {?} obj + * Value to test. + * @param {string=} msg + * Custom error message. + * + * @return {number} + * |obj| is returned unaltered. + * + * @throws {InvalidArgumentError} + * If |obj| is not an integer. + */ +assert.integer = function(obj, msg = "") { + msg = msg || error.pprint`Expected ${obj} to be an integer`; + return assert.that(Number.isInteger, msg)(obj); +}; + +/** + * Asserts that |obj| is a positive integer. + * + * @param {?} obj + * Value to test. + * @param {string=} msg + * Custom error message. + * + * @return {number} + * |obj| is returned unaltered. + * + * @throws {InvalidArgumentError} + * If |obj| is not a positive integer. + */ +assert.positiveInteger = function(obj, msg = "") { + assert.integer(obj, msg); + msg = msg || error.pprint`Expected ${obj} to be >= 0`; + return assert.that(n => n >= 0, msg)(obj); +}; + +/** + * Asserts that |obj| is a boolean. + * + * @param {?} obj + * Value to test. + * @param {string=} msg + * Custom error message. + * + * @return {boolean} + * |obj| is returned unaltered. + * + * @throws {InvalidArgumentError} + * If |obj| is not a boolean. + */ +assert.boolean = function(obj, msg = "") { + msg = msg || error.pprint`Expected ${obj} to be boolean`; + return assert.that(b => typeof b == "boolean", msg)(obj); +}; + +/** + * Asserts that |obj| is a string. + * + * @param {?} obj + * Value to test. + * @param {string=} msg + * Custom error message. + * + * @return {string} + * |obj| is returned unaltered. + * + * @throws {InvalidArgumentError} + * If |obj| is not a string. + */ +assert.string = function(obj, msg = "") { + msg = msg || error.pprint`Expected ${obj} to be a string`; + return assert.that(s => typeof s == "string", msg)(obj); +}; + +/** + * Asserts that |obj| is an object. + * + * @param {?} obj + * Value to test. + * @param {string=} msg + * Custom error message. + * + * @return {Object} + * |obj| is returned unaltered. + * + * @throws {InvalidArgumentError} + * If |obj| is not an object. + */ +assert.object = function(obj, msg = "") { + msg = msg || error.pprint`Expected ${obj} to be an object`; + return assert.that(o => typeof o == "object", msg)(obj); +}; + +/** + * Returns a function that is used to assert the |predicate|. + * + * @param {function(?): boolean} predicate + * Evaluated on calling the return value of this function. If its + * return value of the inner function is false, |error| is thrown + * with |message|. + * @param {string=} message + * Custom error message. + * @param {Error=} error + * Custom error type by its class. + * + * @return {function(?): ?} + * Function that takes and returns the passed in value unaltered, and + * which may throw |error| with |message| if |predicate| evaluates + * to false. + */ +assert.that = function( + predicate, message = "", error = InvalidArgumentError) { + return obj => { + if (!predicate(obj)) { + throw new error(message); + } + return obj; + }; +}; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/marionette/client/marionette_driver/marionette.py firefox-trunk-52.0~a1~hg20161113r322177/testing/marionette/client/marionette_driver/marionette.py --- firefox-trunk-52.0~a1~hg20161110r321971/testing/marionette/client/marionette_driver/marionette.py 2016-11-11 00:56:41.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/marionette/client/marionette_driver/marionette.py 2016-11-14 01:01:14.000000000 +0000 @@ -811,7 +811,8 @@ if returncode is None: message = ('Process killed because the connection to Marionette server is ' 'lost. Check gecko.log for errors') - self.quit() + # This will force-close the application without sending any other message. + self.cleanup() else: # If Firefox quit itself check if there was a crash crash_count = self.check_for_crash() diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/marionette/driver.js firefox-trunk-52.0~a1~hg20161113r322177/testing/marionette/driver.js --- firefox-trunk-52.0~a1~hg20161110r321971/testing/marionette/driver.js 2016-11-11 00:56:41.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/marionette/driver.js 2016-11-14 01:01:15.000000000 +0000 @@ -18,6 +18,7 @@ this, "cookieManager", "@mozilla.org/cookiemanager;1", "nsICookieManager2"); Cu.import("chrome://marionette/content/accessibility.js"); +Cu.import("chrome://marionette/content/assert.js"); Cu.import("chrome://marionette/content/atom.js"); Cu.import("chrome://marionette/content/browser.js"); Cu.import("chrome://marionette/content/element.js"); @@ -648,51 +649,51 @@ GeckoDriver.prototype.setUpProxy = function(proxy) { logger.config("User-provided proxy settings: " + JSON.stringify(proxy)); - if (typeof proxy == "object" && proxy.hasOwnProperty("proxyType")) { - switch (proxy.proxyType.toUpperCase()) { - case "MANUAL": - Preferences.set("network.proxy.type", 1); - if (proxy.httpProxy && proxy.httpProxyPort){ - Preferences.set("network.proxy.http", proxy.httpProxy); - Preferences.set("network.proxy.http_port", proxy.httpProxyPort); - } - if (proxy.sslProxy && proxy.sslProxyPort){ - Preferences.set("network.proxy.ssl", proxy.sslProxy); - Preferences.set("network.proxy.ssl_port", proxy.sslProxyPort); - } - if (proxy.ftpProxy && proxy.ftpProxyPort) { - Preferences.set("network.proxy.ftp", proxy.ftpProxy); - Preferences.set("network.proxy.ftp_port", proxy.ftpProxyPort); - } - if (proxy.socksProxy) { - Preferences.set("network.proxy.socks", proxy.socksProxy); - Preferences.set("network.proxy.socks_port", proxy.socksProxyPort); - if (proxy.socksVersion) { - Preferences.set("network.proxy.socks_version", proxy.socksVersion); - } + assert.object(proxy); + if (!proxy.hasOwnProperty("proxyType")) { + throw new InvalidArgumentError(); + } + switch (proxy.proxyType.toUpperCase()) { + case "MANUAL": + Preferences.set("network.proxy.type", 1); + if (proxy.httpProxy && proxy.httpProxyPort){ + Preferences.set("network.proxy.http", proxy.httpProxy); + Preferences.set("network.proxy.http_port", proxy.httpProxyPort); + } + if (proxy.sslProxy && proxy.sslProxyPort){ + Preferences.set("network.proxy.ssl", proxy.sslProxy); + Preferences.set("network.proxy.ssl_port", proxy.sslProxyPort); + } + if (proxy.ftpProxy && proxy.ftpProxyPort) { + Preferences.set("network.proxy.ftp", proxy.ftpProxy); + Preferences.set("network.proxy.ftp_port", proxy.ftpProxyPort); + } + if (proxy.socksProxy) { + Preferences.set("network.proxy.socks", proxy.socksProxy); + Preferences.set("network.proxy.socks_port", proxy.socksProxyPort); + if (proxy.socksVersion) { + Preferences.set("network.proxy.socks_version", proxy.socksVersion); } - break; + } + break; - case "PAC": - Preferences.set("network.proxy.type", 2); - Preferences.set("network.proxy.autoconfig_url", proxy.proxyAutoconfigUrl); - break; + case "PAC": + Preferences.set("network.proxy.type", 2); + Preferences.set("network.proxy.autoconfig_url", proxy.proxyAutoconfigUrl); + break; - case "AUTODETECT": - Preferences.set("network.proxy.type", 4); - break; + case "AUTODETECT": + Preferences.set("network.proxy.type", 4); + break; - case "SYSTEM": - Preferences.set("network.proxy.type", 5); - break; + case "SYSTEM": + Preferences.set("network.proxy.type", 5); + break; - case "NOPROXY": - default: - Preferences.set("network.proxy.type", 0); - break; - } - } else { - throw new InvalidArgumentError("Value of 'proxy' should be an object"); + case "NOPROXY": + default: + Preferences.set("network.proxy.type", 0); + break; } }; @@ -1265,10 +1266,8 @@ } let {x, y} = cmd.parameters; - if (!Number.isInteger(x) || !Number.isInteger(y) || - x < 0 || y < 0) { - throw new InvalidArgumentError(); - } + assert.positiveInteger(x); + assert.positiveInteger(y); let win = this.getCurrentWindow(); win.moveTo(x, y); @@ -1570,9 +1569,7 @@ } for (let [typ, ms] of Object.entries(timeouts)) { - if (!Number.isInteger(ms)) { - throw new InvalidArgumentError(); - } + assert.positiveInteger(ms); switch (typ) { case "implicit": @@ -2011,10 +2008,7 @@ */ GeckoDriver.prototype.sendKeysToElement = function*(cmd, resp) { let {id, value} = cmd.parameters; - - if (!value) { - throw new InvalidArgumentError(`Expected character sequence: ${value}`); - } + assert.defined(value, `Expected character sequence: ${value}`); switch (this.context) { case Context.CHROME: @@ -2436,19 +2430,18 @@ * and "portrait-secondary" as well as "landscape-secondary". */ GeckoDriver.prototype.setScreenOrientation = function(cmd, resp) { - if (this.appName == "Firefox") { - throw new UnsupportedOperationError(); - } + assert.fennec(); const ors = [ "portrait", "landscape", "portrait-primary", "landscape-primary", - "portrait-secondary", "landscape-secondary" + "portrait-secondary", "landscape-secondary", ]; let or = String(cmd.parameters.orientation); + assert.string(or); let mozOr = or.toLowerCase(); - if (ors.indexOf(mozOr) < 0) { + if (!ors.include(mozOr)) { throw new InvalidArgumentError(`Unknown screen orientation: ${or}`); } @@ -2586,10 +2579,7 @@ * True if the server should accept new socket connections. */ GeckoDriver.prototype.acceptConnections = function(cmd, resp) { - if (typeof cmd.parameters.value != "boolean") { - throw InvalidArgumentError("Value has to be of type 'boolean'"); - } - + assert.boolean(cmd.parameters.value); this._server.acceptConnections = cmd.parameters.value; } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/marionette/error.js firefox-trunk-52.0~a1~hg20161113r322177/testing/marionette/error.js --- firefox-trunk-52.0~a1~hg20161110r321971/testing/marionette/error.js 2016-11-11 00:56:41.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/marionette/error.js 2016-11-14 01:01:15.000000000 +0000 @@ -129,6 +129,32 @@ }; /** + * Pretty-print values passed to template strings. + * + * Usage: + * + * let input = {value: true}; + * error.pprint`Expected boolean, got ${input}`; + * => "Expected boolean, got [object Object] {"value": true}" + */ +error.pprint = function(strings, ...values) { + let res = []; + for (let i = 0; i < strings.length; i++) { + res.push(strings[i]); + if (i < values.length) { + let val = values[i]; + res.push(Object.prototype.toString.call(val)); + let s = JSON.stringify(val); + if (s && s.length > 0) { + res.push(" "); + res.push(s); + } + } + } + return res.join(""); +}; + +/** * Marshal a WebDriverError prototype to a JSON dictionary. * * @param {WebDriverError} err diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/marionette/jar.mn firefox-trunk-52.0~a1~hg20161113r322177/testing/marionette/jar.mn --- firefox-trunk-52.0~a1~hg20161110r321971/testing/marionette/jar.mn 2016-11-11 00:57:58.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/marionette/jar.mn 2016-11-14 01:02:02.000000000 +0000 @@ -27,6 +27,7 @@ content/evaluate.js (evaluate.js) content/logging.js (logging.js) content/navigate.js (navigate.js) + content/assert.js (assert.js) #ifdef ENABLE_TESTS content/test.xul (harness/marionette/chrome/test.xul) content/test2.xul (harness/marionette/chrome/test2.xul) diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/marionette/test_action.js firefox-trunk-52.0~a1~hg20161113r322177/testing/marionette/test_action.js --- firefox-trunk-52.0~a1~hg20161110r321971/testing/marionette/test_action.js 2016-11-11 00:58:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/marionette/test_action.js 2016-11-14 01:02:02.000000000 +0000 @@ -18,6 +18,7 @@ Assert.throws( () => new action.Action(1, 2, "sometype"), /Expected string/, "Non-string arguments."); ok(new action.Action("id", "sometype", "sometype")); + run_next_test(); }); @@ -37,8 +38,7 @@ check(/Unknown pointerType/, message, parametersData); parametersData.pointerType = "pen"; parametersData.primary = "a"; - check(/Expected boolean \(primary\)/, message, parametersData); - + check(/Expected \[object String\] "a" to be boolean/, message, parametersData); parametersData.primary = false; deepEqual(action.PointerParameters.fromJson(parametersData), {pointerType: action.PointerType.Pen, primary: false}); @@ -52,7 +52,7 @@ for (let d of [-1, "a"]) { actionItem.button = d; checkErrors( - /integer >= 0/, action.Action.fromJson, [actionSequence, actionItem], + /Expected 'button' \(.*\) to be >= 0/, action.Action.fromJson, [actionSequence, actionItem], `button: ${actionItem.button}`); } actionItem.button = 5; @@ -69,7 +69,7 @@ message = message || `duration: ${actionItem.duration}, subtype: ${subtype}`; actionItem.type = subtype; actionSequence.type = type; - checkErrors(/integer >= 0/, + checkErrors(/Expected '.*' \(.*\) to be >= 0/, action.Action.fromJson, [actionSequence, actionItem], message); }; for (let d of [-1, "a"]) { @@ -97,7 +97,7 @@ [actionSequence, actionItem], `actionItem.element: (${getTypeString(d)})`); } - actionItem.element = {[element.Key]:"something"}; + actionItem.element = {[element.Key]: "something"}; let a = action.Action.fromJson(actionSequence, actionItem); deepEqual(a.element, actionItem.element); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/marionette/test_assert.js firefox-trunk-52.0~a1~hg20161113r322177/testing/marionette/test_assert.js --- firefox-trunk-52.0~a1~hg20161110r321971/testing/marionette/test_assert.js 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/marionette/test_assert.js 2016-11-14 01:02:02.000000000 +0000 @@ -0,0 +1,85 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const {utils: Cu} = Components; + +Cu.import("chrome://marionette/content/assert.js"); +Cu.import("chrome://marionette/content/error.js"); + +add_test(function test_platforms() { + // at least one will fail + let raised; + for (let fn of [assert.firefox, assert.fennec, assert.b2g, assert.mobile]) { + try { + fn(); + } catch (e) { + raised = e; + } + } + ok(raised instanceof UnsupportedOperationError); + + run_next_test(); +}); + +add_test(function test_defined() { + assert.defined({}); + Assert.throws(() => assert.defined(undefined), InvalidArgumentError); + + run_next_test(); +}); + +add_test(function test_integer() { + assert.integer(1); + assert.integer(0); + assert.integer(-1); + Assert.throws(() => assert.integer("foo"), InvalidArgumentError); + + run_next_test(); +}); + +add_test(function test_positiveInteger() { + assert.positiveInteger(1); + assert.positiveInteger(0); + Assert.throws(() => assert.positiveInteger(-1), InvalidArgumentError); + Assert.throws(() => assert.positiveInteger("foo"), InvalidArgumentError); + + run_next_test(); +}); + +add_test(function test_boolean() { + assert.boolean(true); + assert.boolean(false); + Assert.throws(() => assert.boolean("false"), InvalidArgumentError); + Assert.throws(() => assert.boolean(undefined), InvalidArgumentError); + + run_next_test(); +}); + +add_test(function test_string() { + assert.string("foo"); + assert.string(`bar`); + Assert.throws(() => assert.string(42), InvalidArgumentError); + + run_next_test(); +}); + +add_test(function test_object() { + assert.object({}); + assert.object(new Object()); + Assert.throws(() => assert.object(42), InvalidArgumentError); + + run_next_test(); +}); + +add_test(function test_that() { + equal(1, assert.that(n => n + 1)(1)); + Assert.throws(() => assert.that(() => false)()); + Assert.throws(() => assert.that(val => val)(false)); + Assert.throws(() => assert.that(val => val, "foo", SessionNotCreatedError)(false), + SessionNotCreatedError); + + run_next_test(); +}); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/marionette/unit.ini firefox-trunk-52.0~a1~hg20161113r322177/testing/marionette/unit.ini --- firefox-trunk-52.0~a1~hg20161110r321971/testing/marionette/unit.ini 2016-11-11 00:58:12.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/marionette/unit.ini 2016-11-14 01:02:02.000000000 +0000 @@ -8,6 +8,7 @@ skip-if = appname == "thunderbird" [test_action.js] +[test_assert.js] [test_element.js] [test_error.js] [test_message.js] diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/meta/html/semantics/forms/constraints/form-validation-validity-valueMissing.html.ini firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/meta/html/semantics/forms/constraints/form-validation-validity-valueMissing.html.ini --- firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/meta/html/semantics/forms/constraints/form-validation-validity-valueMissing.html.ini 2016-11-11 01:12:52.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/meta/html/semantics/forms/constraints/form-validation-validity-valueMissing.html.ini 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -[form-validation-validity-valueMissing.html] - type: testharness - [[INPUT in DATETIME status\] The datetime type must be supported.] - expected: FAIL - - [[INPUT in DATETIME-LOCAL status\] The datetime-local type must be supported.] - expected: FAIL - - [[INPUT in DATETIME-LOCAL status\] The value attribute is a number(1234567)] - expected: FAIL - - [[INPUT in DATETIME-LOCAL status\] The value attribute is a Date object] - expected: FAIL - - [[INPUT in DATETIME-LOCAL status\] Invalid local date and time string(1979-10-99 99:99)] - expected: FAIL - - [[INPUT in DATETIME-LOCAL status\] Invalid local date and time string(2001-12-21 12:00)-two white space] - expected: FAIL - - [[INPUT in DATETIME-LOCAL status\] the value attribute is a string(abc)] - expected: FAIL - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/meta/html/semantics/forms/the-input-element/datetime-local.html.ini firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/meta/html/semantics/forms/the-input-element/datetime-local.html.ini --- firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/meta/html/semantics/forms/the-input-element/datetime-local.html.ini 2016-11-11 01:13:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/meta/html/semantics/forms/the-input-element/datetime-local.html.ini 2016-11-14 01:08:26.000000000 +0000 @@ -1,29 +1,8 @@ [datetime-local.html] type: testharness - [datetime-local input value set to 2014-01-01 11:11:11.111 without min/max] - expected: FAIL - - [datetime-local input value set to 2014-01-01 11:11 without min/max] - expected: FAIL - - [datetime-local input value set to 2014-01-01 00:00:00.000 without min/max] - expected: FAIL - - [datetime-local input value set to 2014-01-0 11:11 without min/max] - expected: FAIL - - [datetime-local input value set to 2014-01-01 11:1 without min/max] - expected: FAIL - - [Value >= min attribute] - expected: FAIL - [Value < min attribute] expected: FAIL - [Value <= max attribute] - expected: FAIL - [Value > max attribute] expected: FAIL diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/meta/html/semantics/forms/the-input-element/type-change-state.html.ini firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/meta/html/semantics/forms/the-input-element/type-change-state.html.ini --- firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/meta/html/semantics/forms/the-input-element/type-change-state.html.ini 2016-11-11 01:13:01.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/meta/html/semantics/forms/the-input-element/type-change-state.html.ini 2016-11-14 01:08:27.000000000 +0000 @@ -501,7 +501,7 @@ [change state from file to password] expected: FAIL - [change state from file to datetime] + [change state from file to datetime-local] expected: FAIL [change state from file to date] @@ -555,28 +555,25 @@ [change state from button to datetime] expected: FAIL - [change state from hidden to datetime-local] + [change state from datetime-local to hidden] expected: FAIL - [change state from text to datetime-local] + [change state from datetime-local to text] expected: FAIL - [change state from search to datetime-local] + [change state from datetime-local to search] expected: FAIL - [change state from tel to datetime-local] + [change state from datetime-local to tel] expected: FAIL - [change state from url to datetime-local] + [change state from datetime-local to url] expected: FAIL - [change state from email to datetime-local] + [change state from datetime-local to email] expected: FAIL - [change state from password to datetime-local] - expected: FAIL - - [change state from datetime-local to hidden] + [change state from datetime-local to password] expected: FAIL [change state from datetime-local to checkbox] @@ -596,31 +593,3 @@ [change state from datetime-local to button] expected: FAIL - - [change state from range to datetime-local] - expected: FAIL - - [change state from color to datetime-local] - expected: FAIL - - [change state from checkbox to datetime-local] - expected: FAIL - - [change state from radio to datetime-local] - expected: FAIL - - [change state from file to datetime-local] - expected: FAIL - - [change state from submit to datetime-local] - expected: FAIL - - [change state from image to datetime-local] - expected: FAIL - - [change state from reset to datetime-local] - expected: FAIL - - [change state from button to datetime-local] - expected: FAIL - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/meta/html/semantics/forms/the-input-element/valueMode.html.ini firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/meta/html/semantics/forms/the-input-element/valueMode.html.ini --- firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/meta/html/semantics/forms/the-input-element/valueMode.html.ini 2016-11-11 01:13:01.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/meta/html/semantics/forms/the-input-element/valueMode.html.ini 2016-11-14 01:08:27.000000000 +0000 @@ -47,10 +47,3 @@ [value IDL attribute of input type button with value attribute] expected: FAIL - - [value IDL attribute of input type datetime-local without value attribute] - expected: FAIL - - [value IDL attribute of input type datetime-local with value attribute] - expected: FAIL - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/meta/MANIFEST.json firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/meta/MANIFEST.json --- firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/meta/MANIFEST.json 2016-11-11 01:08:18.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/meta/MANIFEST.json 2016-11-14 01:07:07.000000000 +0000 @@ -14816,10 +14816,18 @@ "url": "/cookies/secure/set-from-dom.https.sub.html" }, { + "path": "cookies/secure/set-from-dom.sub.html", + "url": "/cookies/secure/set-from-dom.sub.html" + }, + { "path": "cookies/secure/set-from-http.https.sub.html", "url": "/cookies/secure/set-from-http.https.sub.html" }, { + "path": "cookies/secure/set-from-http.sub.html", + "url": "/cookies/secure/set-from-http.sub.html" + }, + { "path": "cookies/secure/set-from-ws.https.sub.html", "url": "/cookies/secure/set-from-ws.https.sub.html" }, @@ -38609,6 +38617,12 @@ "url": "/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.worker" } ], + "html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resume-timer-on-history-back.html": [ + { + "path": "html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resume-timer-on-history-back.html", + "url": "/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resume-timer-on-history-back.html" + } + ], "html/browsers/the-window-object/window-open-noopener.html": [ { "path": "html/browsers/the-window-object/window-open-noopener.html", diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/meta/web-animations/animation-model/animation-types/type-per-property.html.ini firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/meta/web-animations/animation-model/animation-types/type-per-property.html.ini --- firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/meta/web-animations/animation-model/animation-types/type-per-property.html.ini 2016-11-11 01:20:32.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/meta/web-animations/animation-model/animation-types/type-per-property.html.ini 2016-11-14 01:10:26.000000000 +0000 @@ -1,3 +1,7 @@ +prefs: [layout.css.contain.enabled:true, + layout.css.initial-letter.enabled:true, + layout.css.overflow-clip-box.enabled:true, + layout.css.shape-outside.enabled:true] [type-per-property.html] type: testharness [flex-basis supports animating as combination units 'px' and '%'] @@ -31,4 +35,3 @@ [text-combine-upright uses discrete animation when animating between 'all' and 'digits' with keyframe easing] expected: FAIL bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1258635 - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/tests/cookies/secure/set-from-dom.sub.html firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/tests/cookies/secure/set-from-dom.sub.html --- firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/tests/cookies/secure/set-from-dom.sub.html 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/tests/cookies/secure/set-from-dom.sub.html 2016-11-14 01:25:56.000000000 +0000 @@ -0,0 +1,47 @@ + + + + + Set 'secure' cookie from `document.cookie` on a non-secure page + + + + + + +
+ + + + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/tests/cookies/secure/set-from-http.sub.html firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/tests/cookies/secure/set-from-http.sub.html --- firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/tests/cookies/secure/set-from-http.sub.html 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/tests/cookies/secure/set-from-http.sub.html 2016-11-14 01:25:56.000000000 +0000 @@ -0,0 +1,36 @@ + + + + + Set 'secure' cookie from `Set-Cookie` HTTP header on a non-secure page + + + + + + +
+ + + + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/post_name_on_load.html firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/post_name_on_load.html --- firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/post_name_on_load.html 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/post_name_on_load.html 2016-11-14 01:29:06.000000000 +0000 @@ -0,0 +1,7 @@ + + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resume-timer-on-history-back.html firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resume-timer-on-history-back.html --- firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resume-timer-on-history-back.html 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resume-timer-on-history-back.html 2016-11-14 01:29:06.000000000 +0000 @@ -0,0 +1,145 @@ + +Verify history.back() on a persisted page resumes timers + + + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/tests/service-workers/service-worker/resources/fetch-rewrite-worker.js firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/tests/service-workers/service-worker/resources/fetch-rewrite-worker.js --- firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/tests/service-workers/service-worker/resources/fetch-rewrite-worker.js 2016-11-11 01:47:52.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/tests/service-workers/service-worker/resources/fetch-rewrite-worker.js 2016-11-14 01:44:19.000000000 +0000 @@ -76,6 +76,7 @@ } else { event.respondWith(new Response('NO_ACCEPT')); } + return; } event.respondWith(new Promise(function(resolve, reject) { var request = event.request; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/tests/web-animations/animation-model/animation-types/type-per-property.html firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/tests/web-animations/animation-model/animation-types/type-per-property.html --- firefox-trunk-52.0~a1~hg20161110r321971/testing/web-platform/tests/web-animations/animation-model/animation-types/type-per-property.html 2016-11-11 01:50:05.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/web-platform/tests/web-animations/animation-model/animation-types/type-per-property.html 2016-11-14 01:47:08.000000000 +0000 @@ -34,12 +34,144 @@ discrete("flex-start", "flex-end") ] }, + "backface-visibility": { + // https://drafts.csswg.org/css-transforms/#propdef-backface-visibility + "tests": [ + discrete("visible", "hidden") + ] + }, + "background-attachment": { + // https://drafts.csswg.org/css-backgrounds-3/#background-attachment + "tests": [ + discrete("fixed", "local") + ] + }, + "background-blend-mode": { + // https://drafts.fxtf.org/compositing-1/#propdef-background-blend-mode + "tests": [ + discrete("multiply", "screen") + ] + }, + "background-clip": { + // https://drafts.csswg.org/css-backgrounds-3/#background-clip + "tests": [ + discrete("padding-box", "content-box") + ] + }, + "background-image": { + // https://drafts.csswg.org/css-backgrounds-3/#background-image + "tests": [ + discrete("url(\"http://localhost/test-1\")", "url(\"http://localhost/test-2\")") + ] + }, + "background-origin": { + // https://drafts.csswg.org/css-backgrounds-3/#background-origin + "tests": [ + discrete("padding-box", "content-box") + ] + }, + "background-repeat": { + // https://drafts.csswg.org/css-backgrounds-3/#background-repeat + "tests": [ + discrete("space", "round") + ] + }, + "border-bottom-style": { + // https://drafts.csswg.org/css-backgrounds-3/#border-bottom-style + "tests": [ + discrete("dotted", "solid") + ] + }, + "border-collapse": { + // https://drafts.csswg.org/css-tables/#propdef-border-collapse + "tests": [ + discrete("collapse", "separate") + ] + }, + "border-image-outset": { + // https://drafts.csswg.org/css-backgrounds-3/#border-image-outset + "tests": [ + discrete("1 1 1 1", "5 5 5 5") + ] + }, + "border-image-repeat": { + // https://drafts.csswg.org/css-backgrounds-3/#border-image-repeat + "tests": [ + discrete("stretch stretch", "repeat repeat") + ] + }, + "border-image-slice": { + // https://drafts.csswg.org/css-backgrounds-3/#border-image-slice + "tests": [ + discrete("1 1 1 1", "5 5 5 5") + ] + }, + "border-image-source": { + // https://drafts.csswg.org/css-backgrounds-3/#border-image-source + "tests": [ + discrete("url(\"http://localhost/test-1\")", "url(\"http://localhost/test-2\")") + ] + }, + "border-image-width": { + // https://drafts.csswg.org/css-backgrounds-3/#border-image-width + "tests": [ + discrete("1 1 1 1", "5 5 5 5") + ] + }, + "border-left-style": { + // https://drafts.csswg.org/css-backgrounds-3/#border-left-style + "tests": [ + discrete("dotted", "solid") + ] + }, + "border-right-style": { + // https://drafts.csswg.org/css-backgrounds-3/#border-right-style + "tests": [ + discrete("dotted", "solid") + ] + }, + "border-top-style": { + // https://drafts.csswg.org/css-backgrounds-3/#border-top-style + "tests": [ + discrete("dotted", "solid") + ] + }, + "box-decoration-break": { + // https://drafts.csswg.org/css-break/#propdef-box-decoration-break + "tests": [ + discrete("slice", "clone") + ] + }, + "box-sizing": { + // https://drafts.csswg.org/css-ui-4/#box-sizing + "tests": [ + discrete("content-box", "border-box") + ] + }, + "caption-side": { + // https://drafts.csswg.org/css-tables/#propdef-caption-side + "tests": [ + discrete("top", "bottom") + ] + }, + "clear": { + // https://drafts.csswg.org/css-page-floats/#propdef-clear + "tests": [ + discrete("inline-start", "inline-end") + ] + }, "clip-rule": { // https://drafts.fxtf.org/css-masking-1/#propdef-clip-rule tests: [ discrete("evenodd", "nonzero") ] }, + "color-adjust": { + // https://drafts.csswg.org/css-color-4/#color-adjust + tests: [ + discrete("economy", "exact") + ] + }, "color-interpolation": { // https://svgwg.org/svg2-draft/painting.html#ColorInterpolationProperty tests: [ @@ -52,12 +184,67 @@ discrete("sRGB", "linearRGB") ] }, + "column-fill": { + // https://drafts.csswg.org/css-multicol/#propdef-column-fill + tests: [ + discrete("auto", "balance") + ] + }, + "column-rule-style": { + // https://drafts.csswg.org/css-multicol/#propdef-column-rule-style + tests: [ + discrete("none", "dotted") + ] + }, + "contain": { + // https://drafts.csswg.org/css-containment/#propdef-contain + tests: [ + discrete("strict", "none") + ] + }, + "content": { + // https://drafts.csswg.org/css-content-3/#propdef-content + tests: [ + discrete("\"a\"", "\"b\"") + ], + tagName: "::before" + }, + "counter-increment": { + // https://drafts.csswg.org/css-lists-3/#propdef-counter-increment + tests: [ + discrete("ident-1 1", "ident-2 2") + ] + }, + "counter-reset": { + // https://drafts.csswg.org/css-lists-3/#propdef-counter-reset + tests: [ + discrete("ident-1 1", "ident-2 2") + ] + }, + "cursor": { + // https://drafts.csswg.org/css2/ui.html#propdef-cursor + tests: [ + discrete("pointer", "wait") + ] + }, + "direction": { + // https://drafts.csswg.org/css-writing-modes-3/#propdef-direction + tests: [ + discrete("ltr", "rtl") + ] + }, "dominant-baseline": { // https://drafts.csswg.org/css-inline/#propdef-dominant-baseline tests: [ discrete("ideographic", "alphabetic") ] }, + "empty-cells": { + // https://drafts.csswg.org/css-tables/#propdef-empty-cells + tests: [ + discrete("show", "hide") + ] + }, "fill-rule": { // https://svgwg.org/svg2-draft/painting.html#FillRuleProperty tests: [ @@ -101,10 +288,172 @@ discrete("italic", "oblique") ] }, - "image-rendering": { - // https://drafts.csswg.org/css-images/#propdef-image-rendering + "float": { + // https://drafts.csswg.org/css-page-floats/#propdef-float tests: [ - discrete("optimizeQuality", "pixelated") + discrete("left", "right") + ] + }, + "font-family": { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-family + tests: [ + discrete("helvetica", "verdana") + ] + }, + "font-feature-settings": { + // https://drafts.csswg.org/css-fonts/#descdef-font-feature-settings + tests: [ + discrete("\"liga\" 5", "normal") + ] + }, + "font-kerning": { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-kerning + tests: [ + discrete("auto", "normal") + ] + }, + "font-language-override": { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-language-override + tests: [ + discrete("\"eng\"", "normal") + ] + }, + "font-style": { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-style + tests: [ + discrete("italic", "oblique") + ] + }, + "font-synthesis": { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-synthesis + tests: [ + discrete("none", "weight style") + ] + }, + "font-variant-alternates": { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-variant-alternates + tests: [ + discrete("swash(unknown)", "stylistic(unknown)") + ] + }, + "font-variant-caps": { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-variant-caps + tests: [ + discrete("small-caps", "unicase") + ] + }, + "font-variant-east-asian": { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-variant-east-asian + tests: [ + discrete("full-width", "proportional-width") + ] + }, + "font-variant-ligatures": { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-variant-ligatures + tests: [ + discrete("common-ligatures", "no-common-ligatures") + ] + }, + "font-variant-numeric": { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-variant-numeric + tests: [ + discrete("lining-nums", "oldstyle-nums") + ] + }, + "font-variant-position": { + // https://drafts.csswg.org/css-fonts-3/#propdef-font-variant-position + tests: [ + discrete("sub", "super") + ] + }, + "grid-auto-columns": { + // https://drafts.csswg.org/css-grid/#propdef-grid-auto-columns + tests: [ + discrete("1px", "5px") + ] + }, + "grid-auto-flow": { + // https://drafts.csswg.org/css-grid/#propdef-grid-auto-flow + tests: [ + discrete("row", "column") + ] + }, + "grid-auto-rows": { + // https://drafts.csswg.org/css-grid/#propdef-grid-auto-rows + tests: [ + discrete("1px", "5px") + ] + }, + "grid-column-end": { + // https://drafts.csswg.org/css-grid/#propdef-grid-column-end + tests: [ + discrete("1", "5") + ] + }, + "grid-column-start": { + // https://drafts.csswg.org/css-grid/#propdef-grid-column-start + tests: [ + discrete("1", "5") + ] + }, + "grid-row-end": { + // https://drafts.csswg.org/css-grid/#propdef-grid-row-end + tests: [ + discrete("1", "5") + ] + }, + "grid-row-start": { + // https://drafts.csswg.org/css-grid/#propdef-grid-row-start + tests: [ + discrete("1", "5") + ] + }, + "grid-template-areas": { + // https://drafts.csswg.org/css-template/#grid-template-areas + tests: [ + discrete("\". . a b\" \". .a b\"", "none") + ] + }, + "grid-template-columns": { + // https://drafts.csswg.org/css-template/#grid-template-columns + tests: [ + discrete("1px", "5px") + ] + }, + "grid-template-rows": { + // https://drafts.csswg.org/css-template/#grid-template-rows + tests: [ + discrete("1px", "5px") + ] + }, + "hyphens": { + // https://drafts.csswg.org/css-text-3/#propdef-hyphens + tests: [ + discrete("manual", "auto") + ] + }, + "image-orientation": { + // https://drafts.csswg.org/css-images-3/#propdef-image-orientation + tests: [ + discrete("0deg", "90deg") + ] + }, + "ime-mode": { + // https://drafts.csswg.org/css-ui/#input-method-editor + tests: [ + discrete("disabled", "auto") + ] + }, + "initial-letter": { + // https://drafts.csswg.org/css-inline/#propdef-initial-letter + tests: [ + discrete("1 2", "3 4") + ] + }, + "isolation": { + // https://drafts.fxtf.org/compositing-1/#propdef-isolation + tests: [ + discrete("auto", "isolate") ] }, "justify-content": { @@ -125,24 +474,186 @@ discrete("baseline", "last baseline") ] }, + "list-style-image": { + // https://drafts.csswg.org/css-lists-3/#propdef-list-style-image + tests: [ + discrete("url(\"http://localhost/test-1\")", "url(\"http://localhost/test-2\")") + ] + }, + "list-style-position": { + // https://drafts.csswg.org/css-lists-3/#propdef-list-style-position + tests: [ + discrete("inside", "outside") + ] + }, + "list-style-type": { + // https://drafts.csswg.org/css-lists-3/#propdef-list-style-type + tests: [ + discrete("circle", "square") + ] + }, + "marker-end": { + // https://svgwg.org/specs/markers/#MarkerEndProperty + tests: [ + discrete("url(\"http://localhost/test-1\")", "url(\"http://localhost/test-2\")") + ] + }, + "marker-mid": { + // https://svgwg.org/specs/markers/#MarkerMidProperty + tests: [ + discrete("url(\"http://localhost/test-1\")", "url(\"http://localhost/test-2\")") + ] + }, + "marker-start": { + // https://svgwg.org/specs/markers/#MarkerStartProperty + tests: [ + discrete("url(\"http://localhost/test-1\")", "url(\"http://localhost/test-2\")") + ] + }, + "mask": { + // https://drafts.fxtf.org/css-masking-1/#the-mask + tests: [ + discrete("url(\"http://localhost/test-1\")", "url(\"http://localhost/test-2\")") + ] + }, + "mask-clip": { + // https://drafts.fxtf.org/css-masking-1/#propdef-mask-clip + tests: [ + discrete("content-box", "border-box") + ] + }, + "mask-composite": { + // https://drafts.fxtf.org/css-masking-1/#propdef-mask-composite + tests: [ + discrete("add", "subtract") + ] + }, + "mask-image": { + // https://drafts.fxtf.org/css-masking-1/#propdef-mask-image + tests: [ + discrete("url(\"http://localhost/test-1\")", "url(\"http://localhost/test-2\")") + ] + }, + "mask-mode": { + // https://drafts.fxtf.org/css-masking-1/#propdef-mask-mode + tests: [ + discrete("alpha", "luminance") + ] + }, + "mask-origin": { + // https://drafts.fxtf.org/css-masking-1/#propdef-mask-origin + tests: [ + discrete("content-box", "border-box") + ] + }, + "mask-repeat": { + // https://drafts.fxtf.org/css-masking-1/#propdef-mask-repeat + tests: [ + discrete("space", "round") + ] + }, "mask-type": { // https://drafts.fxtf.org/css-masking-1/#propdef-mask-type tests: [ discrete("alpha", "luminance") ] }, + "mix-blend-mode": { + // https://drafts.fxtf.org/compositing-1/#propdef-mix-blend-mode + tests: [ + discrete("multiply", "screen") + ] + }, + "object-fit": { + // https://drafts.csswg.org/css-images-3/#propdef-object-fit + tests: [ + discrete("fill", "contain") + ] + }, "order": { // https://drafts.csswg.org/css-flexbox/#propdef-order tests: [ integer() ] }, + "outline-style": { + // https://drafts.csswg.org/css-ui/#propdef-outline-style + tests: [ + discrete("none", "dotted") + ] + }, + "overflow-clip-box": { + // https://developer.mozilla.org/en/docs/Web/CSS/overflow-clip-box + tests: [ + discrete("padding-box", "content-box") + ] + }, + "overflow-wrap": { + // https://drafts.csswg.org/css-text-3/#propdef-overflow-wrap + tests: [ + discrete("normal", "break-word") + ] + }, + "overflow-x": { + // https://drafts.csswg.org/css-overflow-3/#propdef-overflow-x + tests: [ + discrete("visible", "hidden") + ] + }, + "overflow-y": { + // https://drafts.csswg.org/css-overflow-3/#propdef-overflow-y + tests: [ + discrete("visible", "hidden") + ] + }, + "page-break-after": { + // https://drafts.csswg.org/css-break-3/#propdef-break-after + tests: [ + discrete("always", "auto") + ] + }, + "page-break-before": { + // https://drafts.csswg.org/css-break-3/#propdef-break-before + tests: [ + discrete("always", "auto") + ] + }, + "page-break-inside": { + // https://drafts.csswg.org/css-break-3/#propdef-break-inside + tests: [ + discrete("auto", "avoid") + ] + }, + "paint-order": { + // https://svgwg.org/svg2-draft/painting.html#PaintOrderProperty + tests: [ + discrete("fill", "stroke") + ] + }, "pointer-events": { // https://svgwg.org/svg2-draft/interact.html#PointerEventsProperty tests: [ discrete("fill", "none") ] }, + "position": { + // https://drafts.csswg.org/css-position/#propdef-position + tests: [ + discrete("absolute", "fixed") + ] + }, + "quotes": { + // https://drafts.csswg.org/css-content-3/#propdef-quotes + tests: [ + discrete("\"“\" \"”\" \"‘\" \"’\"", "\"‘\" \"’\" \"“\" \"”\"") + ] + }, + "resize": { + // https://drafts.csswg.org/css-ui/#propdef-resize + tests: [ + discrete("both", "horizontal") + ] + }, "ruby-align": { // https://drafts.csswg.org/css-ruby-1/#propdef-ruby-align tests: [ @@ -156,6 +667,30 @@ ], tagName: "ruby" }, + "scroll-behavior": { + // https://drafts.csswg.org/cssom-view/#propdef-scroll-behavior + tests: [ + discrete("auto", "smooth") + ] + }, + "scroll-snap-type-x": { + // https://developer.mozilla.org/en/docs/Web/CSS/scroll-snap-type-x + tests: [ + discrete("mandatory", "proximity") + ] + }, + "scroll-snap-type-y": { + // https://developer.mozilla.org/en/docs/Web/CSS/scroll-snap-type-y + tests: [ + discrete("mandatory", "proximity") + ] + }, + "shape-outside": { + // http://dev.w3.org/csswg/css-shapes/#propdef-shape-outside + tests: [ + discrete("url(\"http://localhost/test-1\")", "url(\"http://localhost/test-2\")") + ] + }, "shape-rendering": { // https://svgwg.org/svg2-draft/painting.html#ShapeRenderingProperty tests: [ @@ -175,6 +710,24 @@ ], tagName: "rect" }, + "table-layout": { + // https://drafts.csswg.org/css-tables/#propdef-table-layout + tests: [ + discrete("auto", "fixed") + ] + }, + "text-align": { + // https://drafts.csswg.org/css-text-3/#propdef-text-align + tests: [ + discrete("start", "end") + ] + }, + "text-align-last": { + // https://drafts.csswg.org/css-text-3/#propdef-text-align-last + tests: [ + discrete("start", "end") + ] + }, "text-anchor": { // https://svgwg.org/svg2-draft/text.html#TextAnchorProperty tests: [ @@ -184,7 +737,7 @@ "text-combine-upright": { // https://drafts.csswg.org/css-writing-modes-3/#propdef-text-combine-upright tests: [ - discrete("all", "digits") + discrete("all", "none") ] }, "text-decoration-line": { @@ -193,18 +746,72 @@ discrete("underline", "overline") ] }, + "text-decoration-style": { + // http://dev.w3.org/csswg/css-text-decor-3/#propdef-text-decoration-style + tests: [ + discrete("solid", "dotted") + ] + }, + "text-emphasis-position": { + // http://dev.w3.org/csswg/css-text-decor-3/#propdef-text-emphasis-position + tests: [ + discrete("over right", "under left") + ] + }, + "text-emphasis-style": { + // http://dev.w3.org/csswg/css-text-decor-3/#propdef-text-emphasis-style + tests: [ + discrete("filled circle", "open dot") + ] + }, "text-orientation": { // https://drafts.csswg.org/css-writing-modes-3/#propdef-text-orientation tests: [ discrete("upright", "sideways") ] }, + "text-overflow": { + // https://drafts.csswg.org/css-ui/#propdef-text-overflow + tests: [ + discrete("clip", "ellipsis") + ] + }, "text-rendering": { // https://svgwg.org/svg2-draft/painting.html#TextRenderingProperty tests: [ discrete("optimizeSpeed", "optimizeLegibility") ] }, + "text-transform": { + // https://drafts.csswg.org/css-text-3/#propdef-text-transform + tests: [ + discrete("capitalize", "uppercase") + ] + }, + "touch-action": { + // https://w3c.github.io/pointerevents/#the-touch-action-css-property + tests: [ + discrete("auto", "none") + ] + }, + "transform-box": { + // https://drafts.csswg.org/css-transforms/#propdef-transform-box + tests: [ + discrete("fill-box", "border-box") + ] + }, + "transform-style": { + // https://drafts.csswg.org/css-transforms/#propdef-transform-style + tests: [ + discrete("flat", "preserve-3d") + ] + }, + "unicode-bidi": { + // https://drafts.csswg.org/css-writing-modes-3/#propdef-unicode-bidi + tests: [ + discrete("embed", "bidi-override") + ] + }, "vector-effect": { // https://svgwg.org/svg2-draft/coords.html#VectorEffectProperty tests: [ @@ -217,12 +824,24 @@ visibility() ] }, + "white-space": { + // https://drafts.csswg.org/css-text-4/#propdef-white-space + tests: [ + discrete("pre", "nowrap") + ] + }, "word-break": { // https://drafts.csswg.org/css-text-3/#propdef-word-break tests: [ discrete("keep-all", "break-all") ] }, + "will-change": { + // http://dev.w3.org/csswg/css-will-change/#propdef-will-change + tests: [ + discrete("scroll-position", "contents") + ] + }, "writing-mode": { // https://drafts.csswg.org/css-writing-modes-3/#propdef-writing-mode tests: [ @@ -247,7 +866,7 @@ var idlName = propertyToIDL(property); var keyframes = {}; keyframes[idlName] = [from, to]; - var target = createElement(t, options.tagName); + var target = createTestElement(t, options.tagName); var animation = target.animate(keyframes, { duration: 1000, fill: "both" }); testAnimationSamples(animation, idlName, @@ -265,7 +884,7 @@ var idlName = propertyToIDL(property); var keyframes = {}; keyframes[idlName] = [from, to]; - var target = createElement(t, options.tagName); + var target = createTestElement(t, options.tagName); var animation = target.animate(keyframes, { duration: 1000, fill: "both", easing: "cubic-bezier(0.68,0,1,0.01)" }); @@ -284,7 +903,7 @@ var keyframes = {}; keyframes[idlName] = [from, to]; keyframes.easing = "cubic-bezier(0.68,0,1,0.01)"; - var target = createElement(t, options.tagName); + var target = createTestElement(t, options.tagName); var animation = target.animate(keyframes, { duration: 1000, fill: "both" }); testAnimationSamples(animation, idlName, @@ -302,7 +921,7 @@ var idlName = propertyToIDL(property); var keyframes = {}; keyframes[idlName] = ["10px", "50px"]; - var target = createElement(t, options.tagName); + var target = createTestElement(t, options.tagName); var animation = target.animate(keyframes, { duration: 1000, fill: "both" }); testAnimationSamples(animation, idlName, @@ -315,7 +934,7 @@ var idlName = propertyToIDL(property); var keyframes = {}; keyframes[idlName] = ["1rem", "5rem"]; - var target = createElement(t, options.tagName); + var target = createTestElement(t, options.tagName); var animation = target.animate(keyframes, { duration: 1000, fill: "both" }); testAnimationSamples(animation, idlName, @@ -332,7 +951,7 @@ var idlName = propertyToIDL(property); var keyframes = {}; keyframes[idlName] = ["10%", "50%"]; - var target = createElement(t, options.tagName); + var target = createTestElement(t, options.tagName); var animation = target.animate(keyframes, { duration: 1000, fill: "both" }); testAnimationSamples(animation, idlName, @@ -349,7 +968,7 @@ var idlName = propertyToIDL(property); var keyframes = {}; keyframes[idlName] = [-2, 2]; - var target = createElement(t, options.tagName); + var target = createTestElement(t, options.tagName); var animation = target.animate(keyframes, { duration: 1000, fill: "both" }); testAnimationSamples(animation, idlName, @@ -366,7 +985,7 @@ var idlName = propertyToIDL(property); var keyframes = {}; keyframes[idlName] = [1.1, 1.5]; - var target = createElement(t, options.tagName); + var target = createTestElement(t, options.tagName); var animation = target.animate(keyframes, { duration: 1000, fill: "both" }); testAnimationSamples(animation, idlName, @@ -386,7 +1005,7 @@ var idlName = propertyToIDL(property); var keyframes = {}; keyframes[idlName] = ["10px", "20%"]; - var target = createElement(t, options.tagName); + var target = createTestElement(t, options.tagName); var animation = target.animate(keyframes, { duration: 1000, fill: "both" }); testAnimationSamples(animation, idlName, @@ -399,7 +1018,7 @@ var idlName = propertyToIDL(property); var keyframes = {}; keyframes[idlName] = ["10%", "2em"]; - var target = createElement(t, options.tagName); + var target = createTestElement(t, options.tagName); var animation = target.animate(keyframes, { duration: 1000, fill: "both" }); testAnimationSamples(animation, idlName, @@ -412,7 +1031,7 @@ var idlName = propertyToIDL(property); var keyframes = {}; keyframes[idlName] = ["1em", "2rem"]; - var target = createElement(t, options.tagName); + var target = createTestElement(t, options.tagName); var animation = target.animate(keyframes, { duration: 1000, fill: "both" }); testAnimationSamples(animation, idlName, @@ -425,7 +1044,7 @@ var idlName = propertyToIDL(property); var keyframes = {}; keyframes[idlName] = ["10px", "calc(1em + 20%)"]; - var target = createElement(t, options.tagName); + var target = createTestElement(t, options.tagName); var animation = target.animate(keyframes, { duration: 1000, fill: "both" }); testAnimationSamples(animation, idlName, @@ -438,7 +1057,7 @@ var idlName = propertyToIDL(property); var keyframes = {}; keyframes[idlName] = ["calc(10px + 10%)", "calc(1em + 1rem + 20%)"]; - var target = createElement(t, options.tagName); + var target = createTestElement(t, options.tagName); var animation = target.animate(keyframes, { duration: 1000, fill: "both" }); testAnimationSamples(animation, idlName, @@ -458,7 +1077,7 @@ var idlName = propertyToIDL(property); var keyframes = {}; keyframes[idlName] = ["visible", "hidden"]; - var target = createElement(t, options.tagName); + var target = createTestElement(t, options.tagName); var animation = target.animate(keyframes, { duration: 1000, fill: "both" }); testAnimationSamples(animation, idlName, @@ -472,7 +1091,7 @@ var idlName = propertyToIDL(property); var keyframes = {}; keyframes[idlName] = ["hidden", "visible"]; - var target = createElement(t, options.tagName); + var target = createTestElement(t, options.tagName); var animation = target.animate(keyframes, { duration: 1000, fill: "both" }); testAnimationSamples(animation, idlName, @@ -486,7 +1105,7 @@ var idlName = propertyToIDL(property); var keyframes = {}; keyframes[idlName] = ["hidden", "collapse"]; - var target = createElement(t, options.tagName); + var target = createTestElement(t, options.tagName); var animation = target.animate(keyframes, { duration: 1000, fill: "both" }); testAnimationSamples(animation, idlName, @@ -504,7 +1123,7 @@ var idlName = propertyToIDL(property); var keyframes = {}; keyframes[idlName] = ["visible", "hidden"]; - var target = createElement(t, options.tagName); + var target = createTestElement(t, options.tagName); var animation = target.animate(keyframes, { duration: 1000, fill: "both", @@ -523,15 +1142,25 @@ } function testAnimationSamples(animation, idlName, testSamples) { - var target = animation.effect.target; + var type = animation.effect.target.type; + var target = type + ? animation.effect.target.parentElement + : animation.effect.target; testSamples.forEach(function(testSample) { animation.currentTime = testSample.time; - assert_equals(getComputedStyle(target)[idlName], testSample.expected, + assert_equals(getComputedStyle(target, type)[idlName], + testSample.expected, "The value should be " + testSample.expected + " at " + testSample.time + "ms"); }); } +function createTestElement(t, tagName) { + return tagName && tagName.startsWith("::") + ? createPseudo(t, tagName.substring(2)) + : createElement(t, tagName); +} + function isSupported(property) { var testKeyframe = new TestKeyframe(propertyToIDL(property)); try { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/testing/xpcshell/xpcshell.eslintrc.js firefox-trunk-52.0~a1~hg20161113r322177/testing/xpcshell/xpcshell.eslintrc.js --- firefox-trunk-52.0~a1~hg20161110r321971/testing/xpcshell/xpcshell.eslintrc.js 2016-11-11 01:54:05.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/testing/xpcshell/xpcshell.eslintrc.js 2016-11-14 01:52:12.000000000 +0000 @@ -3,6 +3,7 @@ rules: { "mozilla/import-headjs-globals": "warn", "mozilla/mark-test-function-used": "warn", + "no-shadow": "error", }, // All globals made available in the test environment. diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/aboutmemory/content/aboutMemory.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/aboutmemory/content/aboutMemory.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/aboutmemory/content/aboutMemory.js 2016-11-11 01:55:16.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/aboutmemory/content/aboutMemory.js 2016-11-14 01:53:53.000000000 +0000 @@ -1227,7 +1227,7 @@ } else { delete aT._kids; } - aT._amount = kid._amount; + aT._amount = kidBytes; aT._description = kid._description; if (kid._nMerged !== undefined) { aT._nMerged = kid._nMerged diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/aboutperformance/content/aboutPerformance.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/aboutperformance/content/aboutPerformance.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/aboutperformance/content/aboutPerformance.js 2016-11-11 01:55:16.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/aboutperformance/content/aboutPerformance.js 2016-11-14 01:53:53.000000000 +0000 @@ -569,7 +569,7 @@ } // Grab everything from the DOM before cleaning up - let eltContainer = this._setupStructure(id); + this._setupStructure(id); // An array of `cachedElements` that need to be added let toAdd = []; @@ -649,7 +649,6 @@ cachedElements.eltRoot.setAttribute("impact", Math.round(impact)); } - let result = delta.diff.jank.totalCPUTime/delta.diff.deltaT; cachedElements.eltCPU.textContent = `CPU usage: ${Math.ceil(delta.diff.jank.totalCPUTime/delta.diff.deltaT/10)}% (total ${delta.diff.jank.totalUserTime}ms).`; cachedElements.eltSystem.textContent = `System usage: ${Math.ceil(delta.diff.jank.totalSystemTime/delta.diff.deltaT/10)}% (total ${delta.diff.jank.totalSystemTime}ms).`; cachedElements.eltCPOW.textContent = `Blocking process calls: ${Math.ceil(delta.diff.cpow.totalCPOWTime/delta.diff.deltaT/10)}% (total ${delta.diff.cpow.totalCPOWTime}ms).`; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/aboutperformance/tests/browser/browser_aboutperformance.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/aboutperformance/tests/browser/browser_aboutperformance.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/aboutperformance/tests/browser/browser_aboutperformance.js 2016-11-11 01:55:16.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/aboutperformance/tests/browser/browser_aboutperformance.js 2016-11-14 01:53:53.000000000 +0000 @@ -68,7 +68,6 @@ try { let reFullname = /Full name: (.+)/; let reFps = /Impact on framerate: (\d+)\/10( \((\d+) alerts\))?/; - let reCpu = /CPU usage: (\d+)%/ let reCpow = /Blocking process calls: (\d+)%( \((\d+) alerts\))?/; let getContentOfSelector = function(eltContainer, selector, re) { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/addoncompat/multiprocessShims.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/addoncompat/multiprocessShims.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/addoncompat/multiprocessShims.js 2016-11-11 01:55:16.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/addoncompat/multiprocessShims.js 2016-11-14 01:53:53.000000000 +0000 @@ -113,7 +113,6 @@ return Cu.getCrossProcessWrapperTag(target); } - const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; if (target instanceof Ci.nsIDOMXULElement) { if (target.localName == "browser" && target.isRemoteBrowser) { return "RemoteBrowserElement"; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/addoncompat/Prefetcher.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/addoncompat/Prefetcher.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/addoncompat/Prefetcher.jsm 2016-11-11 01:55:16.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/addoncompat/Prefetcher.jsm 2016-11-14 01:53:53.000000000 +0000 @@ -163,7 +163,7 @@ PropertyOp.prototype.makeCacheEntry = function(item, cache) { - let [index, obj, has, propValue] = item; + let [, obj, , propValue] = item; let desc = { configurable: false, enumerable: true, writable: false, value: propValue }; @@ -201,7 +201,7 @@ MethodOp.prototype.makeCacheEntry = function(item, cache) { - let [index, obj, result] = item; + let [, obj, result] = item; if (!cache.has(obj)) { cache.set(obj, new Map()); @@ -256,7 +256,7 @@ CollectionOp.prototype.makeCacheEntry = function(item, cache) { - let [index, obj, ...elements] = item; + let [, obj, ...elements] = item; if (!cache.has(obj)) { cache.set(obj, new Map()); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/alerts/test/test_alerts_requireinteraction.html firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/alerts/test/test_alerts_requireinteraction.html --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/alerts/test/test_alerts_requireinteraction.html 2016-11-11 01:55:16.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/alerts/test/test_alerts_requireinteraction.html 2016-11-14 01:53:54.000000000 +0000 @@ -98,7 +98,6 @@ var actualSequence = []; - var sequenceIdx = 0; function createAlertListener(name, showCallback, finishCallback) { return (subject, topic, data) => { if (topic == "alertshow") { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/alerts/test/test_image.html firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/alerts/test/test_image.html --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/alerts/test/test_image.html 2016-11-11 01:55:16.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/alerts/test/test_image.html 2016-11-14 01:53:54.000000000 +0000 @@ -51,7 +51,7 @@ inUserData.data = 123; var alert = makeAlert(null, imageServerURL + "?f=image.png"); - var [ready, request, userData] = yield promiseImage(alert, 0, inUserData); + var [ready, , userData] = yield promiseImage(alert, 0, inUserData); ok(ready, "Should load requested image"); is(userData.QueryInterface(Ci.nsISupportsPRInt64).data, 123, "Should pass user data for loaded image"); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/asyncshutdown/AsyncShutdown.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/asyncshutdown/AsyncShutdown.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/asyncshutdown/AsyncShutdown.jsm 2016-11-11 01:55:16.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/asyncshutdown/AsyncShutdown.jsm 2016-11-14 01:53:54.000000000 +0000 @@ -525,7 +525,6 @@ observe: function() { let topic = this._topic; debug(`Starting phase ${ topic }`); - let barrier = this._barrier; Services.obs.removeObserver(this, topic); let satisfied = false; // |true| once we have satisfied all conditions diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/asyncshutdown/tests/xpcshell/head.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/asyncshutdown/tests/xpcshell/head.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/asyncshutdown/tests/xpcshell/head.js 2016-11-11 01:55:17.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/asyncshutdown/tests/xpcshell/head.js 2016-11-14 01:53:54.000000000 +0000 @@ -62,7 +62,7 @@ let name = "test-xpcom-Barrier-" + ++makeLock.counter; let barrier = asyncShutdownService.makeBarrier(name); return { - addBlocker: function(name, condition, state) { + addBlocker: function(blockerName, condition, state) { if (condition == null) { // Slight trick as `null` or `undefined` cannot be used as keys // for `xpcomMap`. Note that this has no incidence on the result @@ -73,7 +73,7 @@ let blocker = makeLock.xpcomMap.get(condition); if (!blocker) { blocker = { - name: name, + name: blockerName, state: state, blockShutdown: function(aBarrierClient) { return Task.spawn(function*() { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/asyncshutdown/tests/xpcshell/test_AsyncShutdown.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/asyncshutdown/tests/xpcshell/test_AsyncShutdown.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/asyncshutdown/tests/xpcshell/test_AsyncShutdown.js 2016-11-11 01:55:17.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/asyncshutdown/tests/xpcshell/test_AsyncShutdown.js 2016-11-14 01:53:54.000000000 +0000 @@ -100,15 +100,15 @@ }; lock.addBlocker("Wait forever", blocker); - let do_remove_blocker = function(lock, blocker, shouldRemove) { - do_print("Attempting to remove blocker " + blocker + ", expecting result " + shouldRemove); + let do_remove_blocker = function(aLock, aBlocker, aShouldRemove) { + do_print("Attempting to remove blocker " + aBlocker + ", expecting result " + aShouldRemove); if (kind == "xpcom-barrier") { // The xpcom variant always returns `undefined`, so we can't // check its result. - lock.removeBlocker(blocker); + aLock.removeBlocker(aBlocker); return; } - do_check_eq(lock.removeBlocker(blocker), shouldRemove); + do_check_eq(aLock.removeBlocker(aBlocker), aShouldRemove); }; do_remove_blocker(lock, blocker, true); do_remove_blocker(lock, blocker, false); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/autocomplete/tests/unit/test_immediate_search.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/autocomplete/tests/unit/test_immediate_search.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/autocomplete/tests/unit/test_immediate_search.js 2016-11-11 01:55:17.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/autocomplete/tests/unit/test_immediate_search.js 2016-11-14 01:55:43.000000000 +0000 @@ -35,7 +35,6 @@ * An immediate search should be executed synchronously. */ add_test(function test_immediate_search() { - let immediateResults = ["mozillaTest"]; let inputStr = "moz"; let immediateSearch = new AutoCompleteImmediateSearch( @@ -79,7 +78,6 @@ * An immediate search should be executed before any delayed search. */ add_test(function test_immediate_search_notimeout() { - let immediateResults = ["mozillaTest"]; let inputStr = "moz"; let immediateSearch = new AutoCompleteImmediateSearch( @@ -124,7 +122,6 @@ * A delayed search should be executed synchronously with a zero timeout. */ add_test(function test_delayed_search_notimeout() { - let immediateResults = ["mozillaTest"]; let inputStr = "moz"; let delayedSearch = new AutoCompleteDelayedSearch( diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/autocomplete/tests/unit/test_previousResult.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/autocomplete/tests/unit/test_previousResult.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/autocomplete/tests/unit/test_previousResult.js 2016-11-11 01:55:17.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/autocomplete/tests/unit/test_previousResult.js 2016-11-14 01:55:43.000000000 +0000 @@ -243,7 +243,6 @@ var input = new AutoCompleteInput([search1.name, search2.name]); var numSearchesStarted = 0; - var previousResult = null; input.onSearchBegin = function() { numSearchesStarted++; @@ -279,4 +278,3 @@ controller.startSearch("test"); } - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/contentprefs/tests/unit/test_contentPrefs.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/contentprefs/tests/unit/test_contentPrefs.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/contentprefs/tests/unit/test_contentPrefs.js 2016-11-11 01:55:17.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/contentprefs/tests/unit/test_contentPrefs.js 2016-11-14 01:55:44.000000000 +0000 @@ -197,33 +197,34 @@ // Site-Specificity - // These are all different sites, and setting a pref for one of them - // shouldn't set it for the others. - var uri1 = ContentPrefTest.getURI("http://www.domain1.com/"); - var uri2 = ContentPrefTest.getURI("http://foo.domain1.com/"); - var uri3 = ContentPrefTest.getURI("http://domain1.com/"); - var uri4 = ContentPrefTest.getURI("http://www.domain2.com/"); - - cps.setPref(uri1, "test.site-specificity.uri1", 5); - do_check_false(cps.hasPref(uri2, "test.site-specificity.uri1")); - do_check_false(cps.hasPref(uri3, "test.site-specificity.uri1")); - do_check_false(cps.hasPref(uri4, "test.site-specificity.uri1")); - - cps.setPref(uri2, "test.site-specificity.uri2", 5); - do_check_false(cps.hasPref(uri1, "test.site-specificity.uri2")); - do_check_false(cps.hasPref(uri3, "test.site-specificity.uri2")); - do_check_false(cps.hasPref(uri4, "test.site-specificity.uri2")); - - cps.setPref(uri3, "test.site-specificity.uri3", 5); - do_check_false(cps.hasPref(uri1, "test.site-specificity.uri3")); - do_check_false(cps.hasPref(uri2, "test.site-specificity.uri3")); - do_check_false(cps.hasPref(uri4, "test.site-specificity.uri3")); - - cps.setPref(uri4, "test.site-specificity.uri4", 5); - do_check_false(cps.hasPref(uri1, "test.site-specificity.uri4")); - do_check_false(cps.hasPref(uri2, "test.site-specificity.uri4")); - do_check_false(cps.hasPref(uri3, "test.site-specificity.uri4")); - + { + // These are all different sites, and setting a pref for one of them + // shouldn't set it for the others. + let uri1 = ContentPrefTest.getURI("http://www.domain1.com/"); + let uri2 = ContentPrefTest.getURI("http://foo.domain1.com/"); + let uri3 = ContentPrefTest.getURI("http://domain1.com/"); + let uri4 = ContentPrefTest.getURI("http://www.domain2.com/"); + + cps.setPref(uri1, "test.site-specificity.uri1", 5); + do_check_false(cps.hasPref(uri2, "test.site-specificity.uri1")); + do_check_false(cps.hasPref(uri3, "test.site-specificity.uri1")); + do_check_false(cps.hasPref(uri4, "test.site-specificity.uri1")); + + cps.setPref(uri2, "test.site-specificity.uri2", 5); + do_check_false(cps.hasPref(uri1, "test.site-specificity.uri2")); + do_check_false(cps.hasPref(uri3, "test.site-specificity.uri2")); + do_check_false(cps.hasPref(uri4, "test.site-specificity.uri2")); + + cps.setPref(uri3, "test.site-specificity.uri3", 5); + do_check_false(cps.hasPref(uri1, "test.site-specificity.uri3")); + do_check_false(cps.hasPref(uri2, "test.site-specificity.uri3")); + do_check_false(cps.hasPref(uri4, "test.site-specificity.uri3")); + + cps.setPref(uri4, "test.site-specificity.uri4", 5); + do_check_false(cps.hasPref(uri1, "test.site-specificity.uri4")); + do_check_false(cps.hasPref(uri2, "test.site-specificity.uri4")); + do_check_false(cps.hasPref(uri3, "test.site-specificity.uri4")); + } // Observers diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/cookie/content/cookieAcceptDialog.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/cookie/content/cookieAcceptDialog.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/cookie/content/cookieAcceptDialog.js 2016-11-11 01:55:17.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/cookie/content/cookieAcceptDialog.js 2016-11-14 01:55:44.000000000 +0000 @@ -59,7 +59,6 @@ if ("arguments" in window && window.arguments.length >= 1 && window.arguments[0]) { try { params = window.arguments[0].QueryInterface(nsIDialogParamBlock); - var objects = params.objects; var cookie = params.objects.queryElementAt(0, nsICookie); var cookiesFromHost = params.GetInt(nsICookieAcceptDialog.COOKIESFROMHOST); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/crashes/CrashManager.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/crashes/CrashManager.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/crashes/CrashManager.jsm 2016-11-11 01:55:17.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/crashes/CrashManager.jsm 2016-11-14 01:55:44.000000000 +0000 @@ -1043,7 +1043,7 @@ */ get crashes() { let crashes = []; - for (let [id, crash] of this._data.crashes) { + for (let [, crash] of this._data.crashes) { crashes.push(new CrashRecord(crash)); } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/crashes/CrashService.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/crashes/CrashService.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/crashes/CrashService.js 2016-11-11 01:55:17.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/crashes/CrashService.js 2016-11-14 01:55:44.000000000 +0000 @@ -62,7 +62,7 @@ switch (topic) { case "profile-after-change": // Side-effect is the singleton is instantiated. - let m = Services.crashmanager; + Services.crashmanager; break; } }, diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/ctypes/tests/unit/test_finalizer_shouldfail.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/ctypes/tests/unit/test_finalizer_shouldfail.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/ctypes/tests/unit/test_finalizer_shouldfail.js 2016-11-11 01:57:14.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/ctypes/tests/unit/test_finalizer_shouldfail.js 2016-11-14 01:55:45.000000000 +0000 @@ -113,7 +113,7 @@ exception = false; try { - let v = ctypes.CDataFinalizer(acquire(0), null_dispose); + ctypes.CDataFinalizer(acquire(0), null_dispose); } catch (x) { exception = true; } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/ctypes/tests/unit/test_jsctypes.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/ctypes/tests/unit/test_jsctypes.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/ctypes/tests/unit/test_jsctypes.js 2016-11-11 01:57:14.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/ctypes/tests/unit/test_jsctypes.js 2016-11-14 01:55:45.000000000 +0000 @@ -304,110 +304,110 @@ do_check_throws(function() { ctypes.Int64.prototype.toString(); }, TypeError); do_check_throws(function() { ctypes.Int64.prototype.toSource(); }, TypeError); - let i = ctypes.Int64(0); - do_check_true(i.__proto__ === ctypes.Int64.prototype); - do_check_true(i instanceof ctypes.Int64); + let int64 = ctypes.Int64(0); + do_check_true(int64.__proto__ === ctypes.Int64.prototype); + do_check_true(int64 instanceof ctypes.Int64); // Test Int64.toString([radix]). - do_check_eq(i.toString(), "0"); + do_check_eq(int64.toString(), "0"); for (let radix = 2; radix <= 36; ++radix) - do_check_eq(i.toString(radix), "0"); - do_check_throws(function() { i.toString(0); }, RangeError); - do_check_throws(function() { i.toString(1); }, RangeError); - do_check_throws(function() { i.toString(37); }, RangeError); - do_check_throws(function() { i.toString(10, 2); }, TypeError); + do_check_eq(int64.toString(radix), "0"); + do_check_throws(function() { int64.toString(0); }, RangeError); + do_check_throws(function() { int64.toString(1); }, RangeError); + do_check_throws(function() { int64.toString(37); }, RangeError); + do_check_throws(function() { int64.toString(10, 2); }, TypeError); // Test Int64.toSource(). - do_check_eq(i.toSource(), "ctypes.Int64(\"0\")"); - do_check_throws(function() { i.toSource(10); }, TypeError); + do_check_eq(int64.toSource(), "ctypes.Int64(\"0\")"); + do_check_throws(function() { int64.toSource(10); }, TypeError); - i = ctypes.Int64("0x28590a1c921def71"); - do_check_eq(i.toString(), i.toString(10)); - do_check_eq(i.toString(10), "2907366152271163249"); - do_check_eq(i.toString(16), "28590a1c921def71"); - do_check_eq(i.toString(2), "10100001011001000010100001110010010010000111011110111101110001"); - do_check_eq(i.toSource(), "ctypes.Int64(\"" + i.toString(10) + "\")"); - - i = ctypes.Int64("-0x28590a1c921def71"); - do_check_eq(i.toString(), i.toString(10)); - do_check_eq(i.toString(10), "-2907366152271163249"); - do_check_eq(i.toString(16), "-28590a1c921def71"); - do_check_eq(i.toString(2), "-10100001011001000010100001110010010010000111011110111101110001"); - do_check_eq(i.toSource(), "ctypes.Int64(\"" + i.toString(10) + "\")"); - - i = ctypes.Int64("-0X28590A1c921DEf71"); - do_check_eq(i.toString(), i.toString(10)); - do_check_eq(i.toString(10), "-2907366152271163249"); - do_check_eq(i.toString(16), "-28590a1c921def71"); - do_check_eq(i.toString(2), "-10100001011001000010100001110010010010000111011110111101110001"); - do_check_eq(i.toSource(), "ctypes.Int64(\"" + i.toString(10) + "\")"); + int64 = ctypes.Int64("0x28590a1c921def71"); + do_check_eq(int64.toString(), int64.toString(10)); + do_check_eq(int64.toString(10), "2907366152271163249"); + do_check_eq(int64.toString(16), "28590a1c921def71"); + do_check_eq(int64.toString(2), "10100001011001000010100001110010010010000111011110111101110001"); + do_check_eq(int64.toSource(), "ctypes.Int64(\"" + int64.toString(10) + "\")"); + + int64 = ctypes.Int64("-0x28590a1c921def71"); + do_check_eq(int64.toString(), int64.toString(10)); + do_check_eq(int64.toString(10), "-2907366152271163249"); + do_check_eq(int64.toString(16), "-28590a1c921def71"); + do_check_eq(int64.toString(2), "-10100001011001000010100001110010010010000111011110111101110001"); + do_check_eq(int64.toSource(), "ctypes.Int64(\"" + int64.toString(10) + "\")"); + + int64 = ctypes.Int64("-0X28590A1c921DEf71"); + do_check_eq(int64.toString(), int64.toString(10)); + do_check_eq(int64.toString(10), "-2907366152271163249"); + do_check_eq(int64.toString(16), "-28590a1c921def71"); + do_check_eq(int64.toString(2), "-10100001011001000010100001110010010010000111011110111101110001"); + do_check_eq(int64.toSource(), "ctypes.Int64(\"" + int64.toString(10) + "\")"); // Test Int64(primitive double) constructor. - i = ctypes.Int64(-0); - do_check_eq(i.toString(), "0"); + int64 = ctypes.Int64(-0); + do_check_eq(int64.toString(), "0"); - i = ctypes.Int64(0x7ffffffffffff000); - do_check_eq(i.toString(), i.toString(10)); - do_check_eq(i.toString(10), "9223372036854771712"); - do_check_eq(i.toString(16), "7ffffffffffff000"); - do_check_eq(i.toString(2), "111111111111111111111111111111111111111111111111111000000000000"); - - i = ctypes.Int64(-0x8000000000000000); - do_check_eq(i.toString(), i.toString(10)); - do_check_eq(i.toString(10), "-9223372036854775808"); - do_check_eq(i.toString(16), "-8000000000000000"); - do_check_eq(i.toString(2), "-1000000000000000000000000000000000000000000000000000000000000000"); + int64 = ctypes.Int64(0x7ffffffffffff000); + do_check_eq(int64.toString(), int64.toString(10)); + do_check_eq(int64.toString(10), "9223372036854771712"); + do_check_eq(int64.toString(16), "7ffffffffffff000"); + do_check_eq(int64.toString(2), "111111111111111111111111111111111111111111111111111000000000000"); + + int64 = ctypes.Int64(-0x8000000000000000); + do_check_eq(int64.toString(), int64.toString(10)); + do_check_eq(int64.toString(10), "-9223372036854775808"); + do_check_eq(int64.toString(16), "-8000000000000000"); + do_check_eq(int64.toString(2), "-1000000000000000000000000000000000000000000000000000000000000000"); // Test Int64(string) constructor. - i = ctypes.Int64("0x7fffffffffffffff"); - do_check_eq(i.toString(), i.toString(10)); - do_check_eq(i.toString(10), "9223372036854775807"); - do_check_eq(i.toString(16), "7fffffffffffffff"); - do_check_eq(i.toString(2), "111111111111111111111111111111111111111111111111111111111111111"); - - i = ctypes.Int64("-0x8000000000000000"); - do_check_eq(i.toString(), i.toString(10)); - do_check_eq(i.toString(10), "-9223372036854775808"); - do_check_eq(i.toString(16), "-8000000000000000"); - do_check_eq(i.toString(2), "-1000000000000000000000000000000000000000000000000000000000000000"); - - i = ctypes.Int64("9223372036854775807"); - do_check_eq(i.toString(), i.toString(10)); - do_check_eq(i.toString(10), "9223372036854775807"); - do_check_eq(i.toString(16), "7fffffffffffffff"); - do_check_eq(i.toString(2), "111111111111111111111111111111111111111111111111111111111111111"); - - i = ctypes.Int64("-9223372036854775808"); - do_check_eq(i.toString(), i.toString(10)); - do_check_eq(i.toString(10), "-9223372036854775808"); - do_check_eq(i.toString(16), "-8000000000000000"); - do_check_eq(i.toString(2), "-1000000000000000000000000000000000000000000000000000000000000000"); + int64 = ctypes.Int64("0x7fffffffffffffff"); + do_check_eq(int64.toString(), int64.toString(10)); + do_check_eq(int64.toString(10), "9223372036854775807"); + do_check_eq(int64.toString(16), "7fffffffffffffff"); + do_check_eq(int64.toString(2), "111111111111111111111111111111111111111111111111111111111111111"); + + int64 = ctypes.Int64("-0x8000000000000000"); + do_check_eq(int64.toString(), int64.toString(10)); + do_check_eq(int64.toString(10), "-9223372036854775808"); + do_check_eq(int64.toString(16), "-8000000000000000"); + do_check_eq(int64.toString(2), "-1000000000000000000000000000000000000000000000000000000000000000"); + + int64 = ctypes.Int64("9223372036854775807"); + do_check_eq(int64.toString(), int64.toString(10)); + do_check_eq(int64.toString(10), "9223372036854775807"); + do_check_eq(int64.toString(16), "7fffffffffffffff"); + do_check_eq(int64.toString(2), "111111111111111111111111111111111111111111111111111111111111111"); + + int64 = ctypes.Int64("-9223372036854775808"); + do_check_eq(int64.toString(), int64.toString(10)); + do_check_eq(int64.toString(10), "-9223372036854775808"); + do_check_eq(int64.toString(16), "-8000000000000000"); + do_check_eq(int64.toString(2), "-1000000000000000000000000000000000000000000000000000000000000000"); // Test Int64(other Int64) constructor. - i = ctypes.Int64(ctypes.Int64(0)); - do_check_eq(i.toString(), "0"); + int64 = ctypes.Int64(ctypes.Int64(0)); + do_check_eq(int64.toString(), "0"); - i = ctypes.Int64(ctypes.Int64("0x7fffffffffffffff")); - do_check_eq(i.toString(), i.toString(10)); - do_check_eq(i.toString(10), "9223372036854775807"); - do_check_eq(i.toString(16), "7fffffffffffffff"); - do_check_eq(i.toString(2), "111111111111111111111111111111111111111111111111111111111111111"); - - i = ctypes.Int64(ctypes.Int64("-0x8000000000000000")); - do_check_eq(i.toString(), i.toString(10)); - do_check_eq(i.toString(10), "-9223372036854775808"); - do_check_eq(i.toString(16), "-8000000000000000"); - do_check_eq(i.toString(2), "-1000000000000000000000000000000000000000000000000000000000000000"); + int64 = ctypes.Int64(ctypes.Int64("0x7fffffffffffffff")); + do_check_eq(int64.toString(), int64.toString(10)); + do_check_eq(int64.toString(10), "9223372036854775807"); + do_check_eq(int64.toString(16), "7fffffffffffffff"); + do_check_eq(int64.toString(2), "111111111111111111111111111111111111111111111111111111111111111"); + + int64 = ctypes.Int64(ctypes.Int64("-0x8000000000000000")); + do_check_eq(int64.toString(), int64.toString(10)); + do_check_eq(int64.toString(10), "-9223372036854775808"); + do_check_eq(int64.toString(16), "-8000000000000000"); + do_check_eq(int64.toString(2), "-1000000000000000000000000000000000000000000000000000000000000000"); // Test Int64(other UInt64) constructor. - i = ctypes.Int64(ctypes.UInt64(0)); - do_check_eq(i.toString(), "0"); + int64 = ctypes.Int64(ctypes.UInt64(0)); + do_check_eq(int64.toString(), "0"); - i = ctypes.Int64(ctypes.UInt64("0x7fffffffffffffff")); - do_check_eq(i.toString(), i.toString(10)); - do_check_eq(i.toString(10), "9223372036854775807"); - do_check_eq(i.toString(16), "7fffffffffffffff"); - do_check_eq(i.toString(2), "111111111111111111111111111111111111111111111111111111111111111"); + int64 = ctypes.Int64(ctypes.UInt64("0x7fffffffffffffff")); + do_check_eq(int64.toString(), int64.toString(10)); + do_check_eq(int64.toString(10), "9223372036854775807"); + do_check_eq(int64.toString(16), "7fffffffffffffff"); + do_check_eq(int64.toString(2), "111111111111111111111111111111111111111111111111111111111111111"); let vals = [-0x8000000000001000, 0x8000000000000000, ctypes.UInt64("0x8000000000000000"), @@ -474,91 +474,91 @@ do_check_throws(function() { ctypes.UInt64.prototype.toString(); }, TypeError); do_check_throws(function() { ctypes.UInt64.prototype.toSource(); }, TypeError); - let i = ctypes.UInt64(0); - do_check_true(i.__proto__ === ctypes.UInt64.prototype); - do_check_true(i instanceof ctypes.UInt64); + let uint64 = ctypes.UInt64(0); + do_check_true(uint64.__proto__ === ctypes.UInt64.prototype); + do_check_true(uint64 instanceof ctypes.UInt64); // Test UInt64.toString([radix]). - do_check_eq(i.toString(), "0"); + do_check_eq(uint64.toString(), "0"); for (let radix = 2; radix <= 36; ++radix) - do_check_eq(i.toString(radix), "0"); - do_check_throws(function() { i.toString(0); }, RangeError); - do_check_throws(function() { i.toString(1); }, RangeError); - do_check_throws(function() { i.toString(37); }, RangeError); - do_check_throws(function() { i.toString(10, 2); }, TypeError); + do_check_eq(uint64.toString(radix), "0"); + do_check_throws(function() { uint64.toString(0); }, RangeError); + do_check_throws(function() { uint64.toString(1); }, RangeError); + do_check_throws(function() { uint64.toString(37); }, RangeError); + do_check_throws(function() { uint64.toString(10, 2); }, TypeError); // Test UInt64.toSource(). - do_check_eq(i.toSource(), "ctypes.UInt64(\"0\")"); - do_check_throws(function() { i.toSource(10); }, TypeError); + do_check_eq(uint64.toSource(), "ctypes.UInt64(\"0\")"); + do_check_throws(function() { uint64.toSource(10); }, TypeError); - i = ctypes.UInt64("0x28590a1c921def71"); - do_check_eq(i.toString(), i.toString(10)); - do_check_eq(i.toString(10), "2907366152271163249"); - do_check_eq(i.toString(16), "28590a1c921def71"); - do_check_eq(i.toString(2), "10100001011001000010100001110010010010000111011110111101110001"); - do_check_eq(i.toSource(), "ctypes.UInt64(\"" + i.toString(10) + "\")"); - - i = ctypes.UInt64("0X28590A1c921DEf71"); - do_check_eq(i.toString(), i.toString(10)); - do_check_eq(i.toString(10), "2907366152271163249"); - do_check_eq(i.toString(16), "28590a1c921def71"); - do_check_eq(i.toString(2), "10100001011001000010100001110010010010000111011110111101110001"); - do_check_eq(i.toSource(), "ctypes.UInt64(\"" + i.toString(10) + "\")"); + uint64 = ctypes.UInt64("0x28590a1c921def71"); + do_check_eq(uint64.toString(), uint64.toString(10)); + do_check_eq(uint64.toString(10), "2907366152271163249"); + do_check_eq(uint64.toString(16), "28590a1c921def71"); + do_check_eq(uint64.toString(2), "10100001011001000010100001110010010010000111011110111101110001"); + do_check_eq(uint64.toSource(), "ctypes.UInt64(\"" + uint64.toString(10) + "\")"); + + uint64 = ctypes.UInt64("0X28590A1c921DEf71"); + do_check_eq(uint64.toString(), uint64.toString(10)); + do_check_eq(uint64.toString(10), "2907366152271163249"); + do_check_eq(uint64.toString(16), "28590a1c921def71"); + do_check_eq(uint64.toString(2), "10100001011001000010100001110010010010000111011110111101110001"); + do_check_eq(uint64.toSource(), "ctypes.UInt64(\"" + uint64.toString(10) + "\")"); // Test UInt64(primitive double) constructor. - i = ctypes.UInt64(-0); - do_check_eq(i.toString(), "0"); + uint64 = ctypes.UInt64(-0); + do_check_eq(uint64.toString(), "0"); - i = ctypes.UInt64(0xfffffffffffff000); - do_check_eq(i.toString(), i.toString(10)); - do_check_eq(i.toString(10), "18446744073709547520"); - do_check_eq(i.toString(16), "fffffffffffff000"); - do_check_eq(i.toString(2), "1111111111111111111111111111111111111111111111111111000000000000"); + uint64 = ctypes.UInt64(0xfffffffffffff000); + do_check_eq(uint64.toString(), uint64.toString(10)); + do_check_eq(uint64.toString(10), "18446744073709547520"); + do_check_eq(uint64.toString(16), "fffffffffffff000"); + do_check_eq(uint64.toString(2), "1111111111111111111111111111111111111111111111111111000000000000"); // Test UInt64(string) constructor. - i = ctypes.UInt64("0xffffffffffffffff"); - do_check_eq(i.toString(), i.toString(10)); - do_check_eq(i.toString(10), "18446744073709551615"); - do_check_eq(i.toString(16), "ffffffffffffffff"); - do_check_eq(i.toString(2), "1111111111111111111111111111111111111111111111111111111111111111"); - - i = ctypes.UInt64("0x0"); - do_check_eq(i.toString(), i.toString(10)); - do_check_eq(i.toString(10), "0"); - do_check_eq(i.toString(16), "0"); - do_check_eq(i.toString(2), "0"); - - i = ctypes.UInt64("18446744073709551615"); - do_check_eq(i.toString(), i.toString(10)); - do_check_eq(i.toString(10), "18446744073709551615"); - do_check_eq(i.toString(16), "ffffffffffffffff"); - do_check_eq(i.toString(2), "1111111111111111111111111111111111111111111111111111111111111111"); + uint64 = ctypes.UInt64("0xffffffffffffffff"); + do_check_eq(uint64.toString(), uint64.toString(10)); + do_check_eq(uint64.toString(10), "18446744073709551615"); + do_check_eq(uint64.toString(16), "ffffffffffffffff"); + do_check_eq(uint64.toString(2), "1111111111111111111111111111111111111111111111111111111111111111"); + + uint64 = ctypes.UInt64("0x0"); + do_check_eq(uint64.toString(), uint64.toString(10)); + do_check_eq(uint64.toString(10), "0"); + do_check_eq(uint64.toString(16), "0"); + do_check_eq(uint64.toString(2), "0"); + + uint64 = ctypes.UInt64("18446744073709551615"); + do_check_eq(uint64.toString(), uint64.toString(10)); + do_check_eq(uint64.toString(10), "18446744073709551615"); + do_check_eq(uint64.toString(16), "ffffffffffffffff"); + do_check_eq(uint64.toString(2), "1111111111111111111111111111111111111111111111111111111111111111"); - i = ctypes.UInt64("0"); - do_check_eq(i.toString(), "0"); + uint64 = ctypes.UInt64("0"); + do_check_eq(uint64.toString(), "0"); // Test UInt64(other UInt64) constructor. - i = ctypes.UInt64(ctypes.UInt64(0)); - do_check_eq(i.toString(), "0"); + uint64 = ctypes.UInt64(ctypes.UInt64(0)); + do_check_eq(uint64.toString(), "0"); - i = ctypes.UInt64(ctypes.UInt64("0xffffffffffffffff")); - do_check_eq(i.toString(), i.toString(10)); - do_check_eq(i.toString(10), "18446744073709551615"); - do_check_eq(i.toString(16), "ffffffffffffffff"); - do_check_eq(i.toString(2), "1111111111111111111111111111111111111111111111111111111111111111"); + uint64 = ctypes.UInt64(ctypes.UInt64("0xffffffffffffffff")); + do_check_eq(uint64.toString(), uint64.toString(10)); + do_check_eq(uint64.toString(10), "18446744073709551615"); + do_check_eq(uint64.toString(16), "ffffffffffffffff"); + do_check_eq(uint64.toString(2), "1111111111111111111111111111111111111111111111111111111111111111"); - i = ctypes.UInt64(ctypes.UInt64("0x0")); - do_check_eq(i.toString(), "0"); + uint64 = ctypes.UInt64(ctypes.UInt64("0x0")); + do_check_eq(uint64.toString(), "0"); // Test UInt64(other Int64) constructor. - i = ctypes.UInt64(ctypes.Int64(0)); - do_check_eq(i.toString(), "0"); + uint64 = ctypes.UInt64(ctypes.Int64(0)); + do_check_eq(uint64.toString(), "0"); - i = ctypes.UInt64(ctypes.Int64("0x7fffffffffffffff")); - do_check_eq(i.toString(), i.toString(10)); - do_check_eq(i.toString(10), "9223372036854775807"); - do_check_eq(i.toString(16), "7fffffffffffffff"); - do_check_eq(i.toString(2), "111111111111111111111111111111111111111111111111111111111111111"); + uint64 = ctypes.UInt64(ctypes.Int64("0x7fffffffffffffff")); + do_check_eq(uint64.toString(), uint64.toString(10)); + do_check_eq(uint64.toString(10), "9223372036854775807"); + do_check_eq(uint64.toString(16), "7fffffffffffffff"); + do_check_eq(uint64.toString(2), "111111111111111111111111111111111111111111111111111111111111111"); let vals = [-1, 0x10000000000000000, "-1", "-0x1", ctypes.Int64("-1"), Infinity, -Infinity, NaN, 0.1, @@ -951,9 +951,9 @@ do_check_throws(function () { d.value = vals[i]; }, TypeError); // Check that values roundtrip through toSource() correctly. - function test_roundtrip(t, val) + function test_roundtrip(tFn, val) { - let f1 = t(val); + let f1 = tFn(val); eval("var f2 = " + f1.toSource()); do_check_eq(f1.value, f2.value); } @@ -1437,7 +1437,6 @@ do_check_eq(g_t.array().name, name + "[]"); do_check_eq(g_t.array(5).name, name + "[5]"); - let h_t = ctypes.StructType("h_t", [{ a: ctypes.int32_t }, { b: ctypes.int16_t }]); let s_t = new ctypes.StructType("s_t", [{ a: ctypes.int32_t }, { b: g_t }, { c: ctypes.int8_t }]); let fields = [{ a: ctypes.int32_t }, { b: ctypes.int8_t }, { c: g_t }, { d: ctypes.int8_t }]; @@ -1686,11 +1685,11 @@ do_check_eq(ptrValue(v), ptrValue(p)); // Test 'contents'. - let i = ctypes.int32_t(9); - p = i.address(); - do_check_eq(p.contents, i.value); + let int32_t = ctypes.int32_t(9); + p = int32_t.address(); + do_check_eq(p.contents, int32_t.value); p.contents = ctypes.int32_t(12); - do_check_eq(i.value, 12); + do_check_eq(int32_t.value, 12); // Test 'isNull'. let n = f_t(0); @@ -1845,7 +1844,6 @@ }, Error); let g_t = ctypes.StructType("g_t", [{ a: ctypes.int32_t }, { b: ctypes.double }]); - let g = g_t(1, 2); let f_t = ctypes.FunctionType(ctypes.default_abi, g_t); let name = "g_t()"; @@ -2172,7 +2170,6 @@ // Test casting between special types. let g_t = ctypes.StructType("g_t", [{ a: ctypes.int32_t }, { b: ctypes.double }]); let a_t = ctypes.ArrayType(g_t, 4); - let p_t = ctypes.PointerType(g_t); let f_t = ctypes.FunctionType(ctypes.default_abi, ctypes.void_t).ptr; let a = a_t(); @@ -2184,7 +2181,6 @@ let a2 = ctypes.cast(g, g_t.array(1)); do_check_eq(ptrValue(a2.address()), ptrValue(g.address())); do_check_eq(a2[0].a, g.a); - let a3 = ctypes.cast(g, g_t.array(0)); let p = g.address(); let ip = ctypes.cast(p, ctypes.int32_t.ptr); @@ -2215,7 +2211,7 @@ // Win32 (it's all the same on Win64 though). if (ctypes.voidptr_t.size == 4) { do_check_throws(function() { - let test_winapi_t = library.declare("test_void_t_stdcall", ctypes.winapi_abi, ctypes.void_t); + library.declare("test_void_t_stdcall", ctypes.winapi_abi, ctypes.void_t); }, Error); } } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/downloads/ApplicationReputation.cpp firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/downloads/ApplicationReputation.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/downloads/ApplicationReputation.cpp 2016-11-11 01:57:15.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/downloads/ApplicationReputation.cpp 2016-11-14 01:55:45.000000000 +0000 @@ -27,6 +27,7 @@ #include "nsIX509CertDB.h" #include "nsIX509CertList.h" +#include "mozilla/ArrayUtils.h" #include "mozilla/BasePrincipal.h" #include "mozilla/ErrorNames.h" #include "mozilla/LoadContext.h" @@ -51,6 +52,7 @@ #include "nsILoadInfo.h" #include "nsContentUtils.h" +using mozilla::ArrayLength; using mozilla::BasePrincipal; using mozilla::DocShellOriginAttributes; using mozilla::PrincipalOriginAttributes; @@ -385,6 +387,292 @@ LOG(("Destroying pending lookup [this = %p]", this)); } +static const char16_t* kBinaryFileExtensions[] = { + // Extracted from the "File Type Policies" Chrome extension + //u".001", + //u".7z", + //u".ace", + //u".action", // Mac script + //u".ad", // Windows + u".ade", // MS Access + u".adp", // MS Access + u".apk", // Android package + u".app", // Executable application + u".application", // MS ClickOnce + u".appref-ms", // MS ClickOnce + //u".arc", + //u".arj", + u".as", // Mac archive + u".asp", // Windows Server script + u".asx", // Windows Media Player + //u".b64", + //u".balz", + u".bas", // Basic script + u".bash", // Linux shell + u".bat", // Windows shell + //u".bhx", + //u".bin", + u".bz", // Linux archive (bzip) + u".bz2", // Linux archive (bzip2) + u".bzip2", // Linux archive (bzip2) + u".cab", // Windows archive + u".cdr", // Mac disk image + u".cfg", // Windows + u".chi", // Windows Help + u".chm", // Windows Help + u".class", // Java + u".cmd", // Windows executable + u".com", // Windows executable + u".command", // Mac script + u".cpgz", // Mac archive + //u".cpio", + u".cpl", // Windows executable + u".crt", // Windows signed certificate + u".crx", // Chrome extensions + u".csh", // Linux shell + u".dart", // Mac disk image + u".dc42", // Apple DiskCopy Image + u".deb", // Linux package + u".dex", // Android + u".diskcopy42", // Apple DiskCopy Image + u".dll", // Windows executable + u".dmg", // Mac disk image + u".dmgpart", // Mac disk image + //u".docb", // MS Office + //u".docm", // MS Word + //u".docx", // MS Word + //u".dotm", // MS Word + //u".dott", // MS Office + u".drv", // Windows driver + u".dvdr", // Mac Disk image + u".efi", // Firmware + u".eml", // MS Outlook + u".exe", // Windows executable + //u".fat", + u".fon", // Windows font + u".fxp", // MS FoxPro + u".gadget", // Windows + u".grp", // Windows + u".gz", // Linux archive (gzip) + u".gzip", // Linux archive (gzip) + u".hfs", // Mac disk image + u".hlp", // Windows Help + u".hqx", // Mac archive + u".hta", // HTML trusted application + u".htt", // MS HTML template + u".img", // Mac disk image + u".imgpart", // Mac disk image + u".inf", // Windows installer + u".ini", // Generic config file + u".ins", // IIS config + //u".inx", // InstallShield + u".iso", // CD image + u".isp", // IIS config + //u".isu", // InstallShield + u".jar", // Java + u".jnlp", // Java + //u".job", // Windows + u".js", // JavaScript script + u".jse", // JScript + u".ksh", // Linux shell + //u".lha", + u".lnk", // Windows + u".local", // Windows + //u".lpaq1", + //u".lpaq5", + //u".lpaq8", + //u".lzh", + //u".lzma", + u".mad", // MS Access + u".maf", // MS Access + u".mag", // MS Access + u".mam", // MS Access + u".manifest", // Windows + u".maq", // MS Access + u".mar", // MS Access + u".mas", // MS Access + u".mat", // MS Access + u".mau", // Media attachment + u".mav", // MS Access + u".maw", // MS Access + u".mda", // MS Access + u".mdb", // MS Access + u".mde", // MS Access + u".mdt", // MS Access + u".mdw", // MS Access + u".mdz", // MS Access + u".mht", // MS HTML + u".mhtml", // MS HTML + u".mim", // MS Mail + u".mmc", // MS Office + u".mof", // Windows + u".mpkg", // Mac installer + u".msc", // Windows executable + u".msg", // MS Outlook + u".msh", // Windows shell + u".msh1", // Windows shell + u".msh1xml", // Windows shell + u".msh2", // Windows shell + u".msh2xml", // Windows shell + u".mshxml", // Windows + u".msi", // Windows installer + u".msp", // Windows installer + u".mst", // Windows installer + u".ndif", // Mac disk image + //u".ntfs", // 7z + u".ocx", // ActiveX + u".ops", // MS Office + //u".out", // Linux binary + //u".paf", // PortableApps package + //u".paq8f", + //u".paq8jd", + //u".paq8l", + //u".paq8o", + u".partial", // Downloads + u".pax", // Mac archive + u".pcd", // Microsoft Visual Test + u".pdf", // Adobe Acrobat + //u".pea", + u".pet", // Linux package + u".pif", // Windows + u".pkg", // Mac installer + u".pl", // Perl script + u".plg", // MS Visual Studio + //u".potx", // MS PowerPoint + //u".ppam", // MS PowerPoint + //u".ppsx", // MS PowerPoint + //u".pptm", // MS PowerPoint + //u".pptx", // MS PowerPoint + u".prf", // MS Outlook + u".prg", // Windows + u".ps1", // Windows shell + u".ps1xml", // Windows shell + u".ps2", // Windows shell + u".ps2xml", // Windows shell + u".psc1", // Windows shell + u".psc2", // Windows shell + u".pst", // MS Outlook + u".pup", // Linux package + u".py", // Python script + u".pyc", // Python binary + u".pyw", // Python GUI + //u".quad", + //u".r00", + //u".r01", + //u".r02", + //u".r03", + //u".r04", + //u".r05", + //u".r06", + //u".r07", + //u".r08", + //u".r09", + //u".r10", + //u".r11", + //u".r12", + //u".r13", + //u".r14", + //u".r15", + //u".r16", + //u".r17", + //u".r18", + //u".r19", + //u".r20", + //u".r21", + //u".r22", + //u".r23", + //u".r24", + //u".r25", + //u".r26", + //u".r27", + //u".r28", + //u".r29", + //u".rar", + u".rb", // Ruby script + u".reg", // Windows Registry + u".rels", // MS Office + //u".rgs", // Windows Registry + u".rpm", // Linux package + //u".rtf", // MS Office + //u".run", // Linux shell + u".scf", // Windows shell + u".scr", // Windows + u".sct", // Windows shell + u".search-ms", // Windows + u".sh", // Linux shell + u".shar", // Linux shell + u".shb", // Windows + u".shs", // Windows shell + //u".sldm", // MS PowerPoint + //u".sldx", // MS PowerPoint + u".slp", // Linux package + u".smi", // Mac disk image + u".sparsebundle", // Mac disk image + u".sparseimage", // Mac disk image + u".spl", // Adobe Flash + //u".squashfs", + u".svg", + u".swf", // Adobe Flash + u".swm", // Windows Imaging + u".sys", // Windows + u".tar", // Linux archive + u".taz", // Linux archive (bzip2) + u".tbz", // Linux archive (bzip2) + u".tbz2", // Linux archive (bzip2) + u".tcsh", // Linux shell + u".tgz", // Linux archive (gzip) + //u".toast", // Roxio disk image + //u".torrent", // Bittorrent + u".tpz", // Linux archive (gzip) + u".txz", // Linux archive (xz) + u".tz", // Linux archive (gzip) + //u".u3p", // U3 Smart Apps + u".udf", // MS Excel + u".udif", // Mac disk image + u".url", // Windows + //u".uu", + //u".uue", + u".vb", // Visual Basic script + u".vbe", // Visual Basic script + u".vbs", // Visual Basic script + //u".vbscript", // Visual Basic script + u".vhd", // Windows virtual hard drive + u".vhdx", // Windows virtual hard drive + u".vmdk", // VMware virtual disk + u".vsd", // MS Visio + u".vsmacros", // MS Visual Studio + u".vss", // MS Visio + u".vst", // MS Visio + u".vsw", // MS Visio + u".website", // Windows + u".wim", // Windows Imaging + //u".workflow", // Mac Automator + //u".wrc", // FreeArc archive + u".ws", // Windows script + u".wsc", // Windows script + u".wsf", // Windows script + u".wsh", // Windows script + u".xar", // MS Excel + u".xbap", // XAML Browser Application + u".xip", // Mac archive + //u".xlsm", // MS Excel + //u".xlsx", // MS Excel + //u".xltm", // MS Excel + //u".xltx", // MS Excel + u".xml", + u".xnk", // MS Exchange + u".xrm-ms", // Windows + u".xsl", // XML Stylesheet + //u".xxe", + u".xz", // Linux archive (xz) + u".z", // InstallShield +#ifdef XP_WIN // disable on Mac/Linux, see 1167493 + u".zip", // Generic archive +#endif + u".zipx", // WinZip + //u".zpaq", +}; + bool PendingLookup::IsBinaryFile() { @@ -396,290 +684,14 @@ } LOG(("Suggested filename: %s [this = %p]", NS_ConvertUTF16toUTF8(fileName).get(), this)); - return - // Extracted from the "File Type Policies" Chrome extension - //StringEndsWith(fileName, NS_LITERAL_STRING(".001")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".7z")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".ace")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".action")) || // Mac script - //StringEndsWith(fileName, NS_LITERAL_STRING(".ad")) || // Windows - StringEndsWith(fileName, NS_LITERAL_STRING(".ade")) || // MS Access - StringEndsWith(fileName, NS_LITERAL_STRING(".adp")) || // MS Access - StringEndsWith(fileName, NS_LITERAL_STRING(".apk")) || // Android package - StringEndsWith(fileName, NS_LITERAL_STRING(".app")) || // Executable application - StringEndsWith(fileName, NS_LITERAL_STRING(".application")) || // MS ClickOnce - StringEndsWith(fileName, NS_LITERAL_STRING(".appref-ms")) || // MS ClickOnce - //StringEndsWith(fileName, NS_LITERAL_STRING(".arc")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".arj")) || - StringEndsWith(fileName, NS_LITERAL_STRING(".as")) || // Mac archive - StringEndsWith(fileName, NS_LITERAL_STRING(".asp")) || // Windows Server script - StringEndsWith(fileName, NS_LITERAL_STRING(".asx")) || // Windows Media Player - //StringEndsWith(fileName, NS_LITERAL_STRING(".b64")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".balz")) || - StringEndsWith(fileName, NS_LITERAL_STRING(".bas")) || // Basic script - StringEndsWith(fileName, NS_LITERAL_STRING(".bash")) || // Linux shell - StringEndsWith(fileName, NS_LITERAL_STRING(".bat")) || // Windows shell - //StringEndsWith(fileName, NS_LITERAL_STRING(".bhx")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".bin")) || - StringEndsWith(fileName, NS_LITERAL_STRING(".bz")) || // Linux archive (bzip) - StringEndsWith(fileName, NS_LITERAL_STRING(".bz2")) || // Linux archive (bzip2) - StringEndsWith(fileName, NS_LITERAL_STRING(".bzip2")) || // Linux archive (bzip2) - StringEndsWith(fileName, NS_LITERAL_STRING(".cab")) || // Windows archive - StringEndsWith(fileName, NS_LITERAL_STRING(".cdr")) || // Mac disk image - StringEndsWith(fileName, NS_LITERAL_STRING(".cfg")) || // Windows - StringEndsWith(fileName, NS_LITERAL_STRING(".chi")) || // Windows Help - StringEndsWith(fileName, NS_LITERAL_STRING(".chm")) || // Windows Help - StringEndsWith(fileName, NS_LITERAL_STRING(".class")) || // Java - StringEndsWith(fileName, NS_LITERAL_STRING(".cmd")) || // Windows executable - StringEndsWith(fileName, NS_LITERAL_STRING(".com")) || // Windows executable - StringEndsWith(fileName, NS_LITERAL_STRING(".command")) || // Mac script - StringEndsWith(fileName, NS_LITERAL_STRING(".cpgz")) || // Mac archive - //StringEndsWith(fileName, NS_LITERAL_STRING(".cpio")) || - StringEndsWith(fileName, NS_LITERAL_STRING(".cpl")) || // Windows executable - StringEndsWith(fileName, NS_LITERAL_STRING(".crt")) || // Windows signed certificate - StringEndsWith(fileName, NS_LITERAL_STRING(".crx")) || // Chrome extensions - StringEndsWith(fileName, NS_LITERAL_STRING(".csh")) || // Linux shell - StringEndsWith(fileName, NS_LITERAL_STRING(".dart")) || // Mac disk image - StringEndsWith(fileName, NS_LITERAL_STRING(".dc42")) || // Apple DiskCopy Image - StringEndsWith(fileName, NS_LITERAL_STRING(".deb")) || // Linux package - StringEndsWith(fileName, NS_LITERAL_STRING(".dex")) || // Android - StringEndsWith(fileName, NS_LITERAL_STRING(".diskcopy42")) || // Apple DiskCopy Image - StringEndsWith(fileName, NS_LITERAL_STRING(".dll")) || // Windows executable - StringEndsWith(fileName, NS_LITERAL_STRING(".dmg")) || // Mac disk image - StringEndsWith(fileName, NS_LITERAL_STRING(".dmgpart")) || // Mac disk image - //StringEndsWith(fileName, NS_LITERAL_STRING(".docb")) || // MS Office - //StringEndsWith(fileName, NS_LITERAL_STRING(".docm")) || // MS Word - //StringEndsWith(fileName, NS_LITERAL_STRING(".docx")) || // MS Word - //StringEndsWith(fileName, NS_LITERAL_STRING(".dotm")) || // MS Word - //StringEndsWith(fileName, NS_LITERAL_STRING(".dott")) || // MS Office - StringEndsWith(fileName, NS_LITERAL_STRING(".drv")) || // Windows driver - StringEndsWith(fileName, NS_LITERAL_STRING(".dvdr")) || // Mac Disk image - StringEndsWith(fileName, NS_LITERAL_STRING(".efi")) || // Firmware - StringEndsWith(fileName, NS_LITERAL_STRING(".eml")) || // MS Outlook - StringEndsWith(fileName, NS_LITERAL_STRING(".exe")) || // Windows executable - //StringEndsWith(fileName, NS_LITERAL_STRING(".fat")) || - StringEndsWith(fileName, NS_LITERAL_STRING(".fon")) || // Windows font - StringEndsWith(fileName, NS_LITERAL_STRING(".fxp")) || // MS FoxPro - StringEndsWith(fileName, NS_LITERAL_STRING(".gadget")) || // Windows - StringEndsWith(fileName, NS_LITERAL_STRING(".grp")) || // Windows - StringEndsWith(fileName, NS_LITERAL_STRING(".gz")) || // Linux archive (gzip) - StringEndsWith(fileName, NS_LITERAL_STRING(".gzip")) || // Linux archive (gzip) - StringEndsWith(fileName, NS_LITERAL_STRING(".hfs")) || // Mac disk image - StringEndsWith(fileName, NS_LITERAL_STRING(".hlp")) || // Windows Help - StringEndsWith(fileName, NS_LITERAL_STRING(".hqx")) || // Mac archive - StringEndsWith(fileName, NS_LITERAL_STRING(".hta")) || // HTML trusted application - StringEndsWith(fileName, NS_LITERAL_STRING(".htt")) || // MS HTML template - StringEndsWith(fileName, NS_LITERAL_STRING(".img")) || // Mac disk image - StringEndsWith(fileName, NS_LITERAL_STRING(".imgpart")) || // Mac disk image - StringEndsWith(fileName, NS_LITERAL_STRING(".inf")) || // Windows installer - StringEndsWith(fileName, NS_LITERAL_STRING(".ini")) || // Generic config file - StringEndsWith(fileName, NS_LITERAL_STRING(".ins")) || // IIS config - //StringEndsWith(fileName, NS_LITERAL_STRING(".inx")) || // InstallShield - StringEndsWith(fileName, NS_LITERAL_STRING(".iso")) || // CD image - StringEndsWith(fileName, NS_LITERAL_STRING(".isp")) || // IIS config - //StringEndsWith(fileName, NS_LITERAL_STRING(".isu")) || // InstallShield - StringEndsWith(fileName, NS_LITERAL_STRING(".jar")) || // Java - StringEndsWith(fileName, NS_LITERAL_STRING(".jnlp")) || // Java - //StringEndsWith(fileName, NS_LITERAL_STRING(".job")) || // Windows - StringEndsWith(fileName, NS_LITERAL_STRING(".js")) || // JavaScript script - StringEndsWith(fileName, NS_LITERAL_STRING(".jse")) || // JScript - StringEndsWith(fileName, NS_LITERAL_STRING(".ksh")) || // Linux shell - //StringEndsWith(fileName, NS_LITERAL_STRING(".lha")) || - StringEndsWith(fileName, NS_LITERAL_STRING(".lnk")) || // Windows - StringEndsWith(fileName, NS_LITERAL_STRING(".local")) || // Windows - //StringEndsWith(fileName, NS_LITERAL_STRING(".lpaq1")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".lpaq5")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".lpaq8")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".lzh")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".lzma")) || - StringEndsWith(fileName, NS_LITERAL_STRING(".mad")) || // MS Access - StringEndsWith(fileName, NS_LITERAL_STRING(".maf")) || // MS Access - StringEndsWith(fileName, NS_LITERAL_STRING(".mag")) || // MS Access - StringEndsWith(fileName, NS_LITERAL_STRING(".mam")) || // MS Access - StringEndsWith(fileName, NS_LITERAL_STRING(".manifest")) || // Windows - StringEndsWith(fileName, NS_LITERAL_STRING(".maq")) || // MS Access - StringEndsWith(fileName, NS_LITERAL_STRING(".mar")) || // MS Access - StringEndsWith(fileName, NS_LITERAL_STRING(".mas")) || // MS Access - StringEndsWith(fileName, NS_LITERAL_STRING(".mat")) || // MS Access - StringEndsWith(fileName, NS_LITERAL_STRING(".mau")) || // Media attachment - StringEndsWith(fileName, NS_LITERAL_STRING(".mav")) || // MS Access - StringEndsWith(fileName, NS_LITERAL_STRING(".maw")) || // MS Access - StringEndsWith(fileName, NS_LITERAL_STRING(".mda")) || // MS Access - StringEndsWith(fileName, NS_LITERAL_STRING(".mdb")) || // MS Access - StringEndsWith(fileName, NS_LITERAL_STRING(".mde")) || // MS Access - StringEndsWith(fileName, NS_LITERAL_STRING(".mdt")) || // MS Access - StringEndsWith(fileName, NS_LITERAL_STRING(".mdw")) || // MS Access - StringEndsWith(fileName, NS_LITERAL_STRING(".mdz")) || // MS Access - StringEndsWith(fileName, NS_LITERAL_STRING(".mht")) || // MS HTML - StringEndsWith(fileName, NS_LITERAL_STRING(".mhtml")) || // MS HTML - StringEndsWith(fileName, NS_LITERAL_STRING(".mim")) || // MS Mail - StringEndsWith(fileName, NS_LITERAL_STRING(".mmc")) || // MS Office - StringEndsWith(fileName, NS_LITERAL_STRING(".mof")) || // Windows - StringEndsWith(fileName, NS_LITERAL_STRING(".mpkg")) || // Mac installer - StringEndsWith(fileName, NS_LITERAL_STRING(".msc")) || // Windows executable - StringEndsWith(fileName, NS_LITERAL_STRING(".msg")) || // MS Outlook - StringEndsWith(fileName, NS_LITERAL_STRING(".msh")) || // Windows shell - StringEndsWith(fileName, NS_LITERAL_STRING(".msh1")) || // Windows shell - StringEndsWith(fileName, NS_LITERAL_STRING(".msh1xml")) || // Windows shell - StringEndsWith(fileName, NS_LITERAL_STRING(".msh2")) || // Windows shell - StringEndsWith(fileName, NS_LITERAL_STRING(".msh2xml")) || // Windows shell - StringEndsWith(fileName, NS_LITERAL_STRING(".mshxml")) || // Windows - StringEndsWith(fileName, NS_LITERAL_STRING(".msi")) || // Windows installer - StringEndsWith(fileName, NS_LITERAL_STRING(".msp")) || // Windows installer - StringEndsWith(fileName, NS_LITERAL_STRING(".mst")) || // Windows installer - StringEndsWith(fileName, NS_LITERAL_STRING(".ndif")) || // Mac disk image - //StringEndsWith(fileName, NS_LITERAL_STRING(".ntfs")) || // 7z - StringEndsWith(fileName, NS_LITERAL_STRING(".ocx")) || // ActiveX - StringEndsWith(fileName, NS_LITERAL_STRING(".ops")) || // MS Office - //StringEndsWith(fileName, NS_LITERAL_STRING(".out")) || // Linux binary - //StringEndsWith(fileName, NS_LITERAL_STRING(".paf")) || // PortableApps package - //StringEndsWith(fileName, NS_LITERAL_STRING(".paq8f")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".paq8jd")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".paq8l")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".paq8o")) || - StringEndsWith(fileName, NS_LITERAL_STRING(".partial")) || // Downloads - StringEndsWith(fileName, NS_LITERAL_STRING(".pax")) || // Mac archive - StringEndsWith(fileName, NS_LITERAL_STRING(".pcd")) || // Microsoft Visual Test - StringEndsWith(fileName, NS_LITERAL_STRING(".pdf")) || // Adobe Acrobat - //StringEndsWith(fileName, NS_LITERAL_STRING(".pea")) || - StringEndsWith(fileName, NS_LITERAL_STRING(".pet")) || // Linux package - StringEndsWith(fileName, NS_LITERAL_STRING(".pif")) || // Windows - StringEndsWith(fileName, NS_LITERAL_STRING(".pkg")) || // Mac installer - StringEndsWith(fileName, NS_LITERAL_STRING(".pl")) || // Perl script - StringEndsWith(fileName, NS_LITERAL_STRING(".plg")) || // MS Visual Studio - //StringEndsWith(fileName, NS_LITERAL_STRING(".potx")) || // MS PowerPoint - //StringEndsWith(fileName, NS_LITERAL_STRING(".ppam")) || // MS PowerPoint - //StringEndsWith(fileName, NS_LITERAL_STRING(".ppsx")) || // MS PowerPoint - //StringEndsWith(fileName, NS_LITERAL_STRING(".pptm")) || // MS PowerPoint - //StringEndsWith(fileName, NS_LITERAL_STRING(".pptx")) || // MS PowerPoint - StringEndsWith(fileName, NS_LITERAL_STRING(".prf")) || // MS Outlook - StringEndsWith(fileName, NS_LITERAL_STRING(".prg")) || // Windows - StringEndsWith(fileName, NS_LITERAL_STRING(".ps1")) || // Windows shell - StringEndsWith(fileName, NS_LITERAL_STRING(".ps1xml")) || // Windows shell - StringEndsWith(fileName, NS_LITERAL_STRING(".ps2")) || // Windows shell - StringEndsWith(fileName, NS_LITERAL_STRING(".ps2xml")) || // Windows shell - StringEndsWith(fileName, NS_LITERAL_STRING(".psc1")) || // Windows shell - StringEndsWith(fileName, NS_LITERAL_STRING(".psc2")) || // Windows shell - StringEndsWith(fileName, NS_LITERAL_STRING(".pst")) || // MS Outlook - StringEndsWith(fileName, NS_LITERAL_STRING(".pup")) || // Linux package - StringEndsWith(fileName, NS_LITERAL_STRING(".py")) || // Python script - StringEndsWith(fileName, NS_LITERAL_STRING(".pyc")) || // Python binary - StringEndsWith(fileName, NS_LITERAL_STRING(".pyw")) || // Python GUI - //StringEndsWith(fileName, NS_LITERAL_STRING(".quad")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r00")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r01")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r02")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r03")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r04")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r05")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r06")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r07")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r08")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r09")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r10")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r11")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r12")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r13")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r14")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r15")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r16")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r17")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r18")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r19")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r20")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r21")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r22")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r23")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r24")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r25")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r26")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r27")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r28")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".r29")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".rar")) || - StringEndsWith(fileName, NS_LITERAL_STRING(".rb")) || // Ruby script - StringEndsWith(fileName, NS_LITERAL_STRING(".reg")) || // Windows Registry - StringEndsWith(fileName, NS_LITERAL_STRING(".rels")) || // MS Office - //StringEndsWith(fileName, NS_LITERAL_STRING(".rgs")) || // Windows Registry - StringEndsWith(fileName, NS_LITERAL_STRING(".rpm")) || // Linux package - //StringEndsWith(fileName, NS_LITERAL_STRING(".rtf")) || // MS Office - //StringEndsWith(fileName, NS_LITERAL_STRING(".run")) || // Linux shell - StringEndsWith(fileName, NS_LITERAL_STRING(".scf")) || // Windows shell - StringEndsWith(fileName, NS_LITERAL_STRING(".scr")) || // Windows - StringEndsWith(fileName, NS_LITERAL_STRING(".sct")) || // Windows shell - StringEndsWith(fileName, NS_LITERAL_STRING(".search-ms")) || // Windows - StringEndsWith(fileName, NS_LITERAL_STRING(".sh")) || // Linux shell - StringEndsWith(fileName, NS_LITERAL_STRING(".shar")) || // Linux shell - StringEndsWith(fileName, NS_LITERAL_STRING(".shb")) || // Windows - StringEndsWith(fileName, NS_LITERAL_STRING(".shs")) || // Windows shell - //StringEndsWith(fileName, NS_LITERAL_STRING(".sldm")) || // MS PowerPoint - //StringEndsWith(fileName, NS_LITERAL_STRING(".sldx")) || // MS PowerPoint - StringEndsWith(fileName, NS_LITERAL_STRING(".slp")) || // Linux package - StringEndsWith(fileName, NS_LITERAL_STRING(".smi")) || // Mac disk image - StringEndsWith(fileName, NS_LITERAL_STRING(".sparsebundle")) || // Mac disk image - StringEndsWith(fileName, NS_LITERAL_STRING(".sparseimage")) || // Mac disk image - StringEndsWith(fileName, NS_LITERAL_STRING(".spl")) || // Adobe Flash - //StringEndsWith(fileName, NS_LITERAL_STRING(".squashfs")) || - StringEndsWith(fileName, NS_LITERAL_STRING(".svg")) || - StringEndsWith(fileName, NS_LITERAL_STRING(".swf")) || // Adobe Flash - StringEndsWith(fileName, NS_LITERAL_STRING(".swm")) || // Windows Imaging - StringEndsWith(fileName, NS_LITERAL_STRING(".sys")) || // Windows - StringEndsWith(fileName, NS_LITERAL_STRING(".tar")) || // Linux archive - StringEndsWith(fileName, NS_LITERAL_STRING(".taz")) || // Linux archive (bzip2) - StringEndsWith(fileName, NS_LITERAL_STRING(".tbz")) || // Linux archive (bzip2) - StringEndsWith(fileName, NS_LITERAL_STRING(".tbz2")) || // Linux archive (bzip2) - StringEndsWith(fileName, NS_LITERAL_STRING(".tcsh")) || // Linux shell - StringEndsWith(fileName, NS_LITERAL_STRING(".tgz")) || // Linux archive (gzip) - //StringEndsWith(fileName, NS_LITERAL_STRING(".toast")) || // Roxio disk image - //StringEndsWith(fileName, NS_LITERAL_STRING(".torrent")) || // Bittorrent - StringEndsWith(fileName, NS_LITERAL_STRING(".tpz")) || // Linux archive (gzip) - StringEndsWith(fileName, NS_LITERAL_STRING(".txz")) || // Linux archive (xz) - StringEndsWith(fileName, NS_LITERAL_STRING(".tz")) || // Linux archive (gzip) - //StringEndsWith(fileName, NS_LITERAL_STRING(".u3p")) || // U3 Smart Apps - StringEndsWith(fileName, NS_LITERAL_STRING(".udf")) || // MS Excel - StringEndsWith(fileName, NS_LITERAL_STRING(".udif")) || // Mac disk image - StringEndsWith(fileName, NS_LITERAL_STRING(".url")) || // Windows - //StringEndsWith(fileName, NS_LITERAL_STRING(".uu")) || - //StringEndsWith(fileName, NS_LITERAL_STRING(".uue")) || - StringEndsWith(fileName, NS_LITERAL_STRING(".vb")) || // Visual Basic script - StringEndsWith(fileName, NS_LITERAL_STRING(".vbe")) || // Visual Basic script - StringEndsWith(fileName, NS_LITERAL_STRING(".vbs")) || // Visual Basic script - //StringEndsWith(fileName, NS_LITERAL_STRING(".vbscript")) || // Visual Basic script - StringEndsWith(fileName, NS_LITERAL_STRING(".vhd")) || // Windows virtual hard drive - StringEndsWith(fileName, NS_LITERAL_STRING(".vhdx")) || // Windows virtual hard drive - StringEndsWith(fileName, NS_LITERAL_STRING(".vmdk")) || // VMware virtual disk - StringEndsWith(fileName, NS_LITERAL_STRING(".vsd")) || // MS Visio - StringEndsWith(fileName, NS_LITERAL_STRING(".vsmacros")) || // MS Visual Studio - StringEndsWith(fileName, NS_LITERAL_STRING(".vss")) || // MS Visio - StringEndsWith(fileName, NS_LITERAL_STRING(".vst")) || // MS Visio - StringEndsWith(fileName, NS_LITERAL_STRING(".vsw")) || // MS Visio - StringEndsWith(fileName, NS_LITERAL_STRING(".website")) || // Windows - StringEndsWith(fileName, NS_LITERAL_STRING(".wim")) || // Windows Imaging - //StringEndsWith(fileName, NS_LITERAL_STRING(".workflow")) || // Mac Automator - //StringEndsWith(fileName, NS_LITERAL_STRING(".wrc")) || // FreeArc archive - StringEndsWith(fileName, NS_LITERAL_STRING(".ws")) || // Windows script - StringEndsWith(fileName, NS_LITERAL_STRING(".wsc")) || // Windows script - StringEndsWith(fileName, NS_LITERAL_STRING(".wsf")) || // Windows script - StringEndsWith(fileName, NS_LITERAL_STRING(".wsh")) || // Windows script - StringEndsWith(fileName, NS_LITERAL_STRING(".xar")) || // MS Excel - StringEndsWith(fileName, NS_LITERAL_STRING(".xbap")) || // XAML Browser Application - StringEndsWith(fileName, NS_LITERAL_STRING(".xip")) || // Mac archive - //StringEndsWith(fileName, NS_LITERAL_STRING(".xlsm")) || // MS Excel - //StringEndsWith(fileName, NS_LITERAL_STRING(".xlsx")) || // MS Excel - //StringEndsWith(fileName, NS_LITERAL_STRING(".xltm")) || // MS Excel - //StringEndsWith(fileName, NS_LITERAL_STRING(".xltx")) || // MS Excel - StringEndsWith(fileName, NS_LITERAL_STRING(".xml")) || - StringEndsWith(fileName, NS_LITERAL_STRING(".xnk")) || // MS Exchange - StringEndsWith(fileName, NS_LITERAL_STRING(".xrm-ms")) || // Windows - StringEndsWith(fileName, NS_LITERAL_STRING(".xsl")) || // XML Stylesheet - //StringEndsWith(fileName, NS_LITERAL_STRING(".xxe")) || - StringEndsWith(fileName, NS_LITERAL_STRING(".xz")) || // Linux archive (xz) - StringEndsWith(fileName, NS_LITERAL_STRING(".z")) || // InstallShield -#ifdef XP_WIN // disable on Mac/Linux, see 1167493 - StringEndsWith(fileName, NS_LITERAL_STRING(".zip")) || // Generic archive -#endif - StringEndsWith(fileName, NS_LITERAL_STRING(".zipx")); // WinZip - //StringEndsWith(fileName, NS_LITERAL_STRING(".zpaq")); + + for (size_t i = 0; i < ArrayLength(kBinaryFileExtensions); ++i) { + if (StringEndsWith(fileName, nsDependentString(kBinaryFileExtensions[i]))) { + return true; + } + } + + return false; } ClientDownloadRequest::DownloadType diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/downloads/test/unit/test_app_rep.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/downloads/test/unit/test_app_rep.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/downloads/test/unit/test_app_rep.js 2016-11-11 01:57:15.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/downloads/test/unit/test_app_rep.js 2016-11-14 01:55:46.000000000 +0000 @@ -187,8 +187,6 @@ return response; } gHttpServ.registerPathHandler("/downloads", function(request, response) { - let buf = NetUtil.readInputStreamToString(request.bodyInputStream, - request.bodyInputStream.available()); let blob = processUpdateRequest(); response.setHeader("Content-Type", "application/vnd.google.safebrowsing-update", false); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/downloads/test/unit/test_app_rep_maclinux.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/downloads/test/unit/test_app_rep_maclinux.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/downloads/test/unit/test_app_rep_maclinux.js 2016-11-11 01:57:15.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/downloads/test/unit/test_app_rep_maclinux.js 2016-11-14 01:55:46.000000000 +0000 @@ -162,8 +162,6 @@ function waitForUpdates() { let deferred = Promise.defer(); gHttpServer.registerPathHandler("/downloads", function(request, response) { - let buf = NetUtil.readInputStreamToString(request.bodyInputStream, - request.bodyInputStream.available()); let blob = processUpdateRequest(); response.setHeader("Content-Type", "application/vnd.google.safebrowsing-update", false); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/downloads/test/unit/test_app_rep_windows.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/downloads/test/unit/test_app_rep_windows.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/downloads/test/unit/test_app_rep_windows.js 2016-11-11 01:57:15.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/downloads/test/unit/test_app_rep_windows.js 2016-11-14 01:55:46.000000000 +0000 @@ -79,13 +79,13 @@ function promiseSaverComplete(aSaver, aOnTargetChangeFn) { let deferred = Promise.defer(); aSaver.observer = { - onTargetChange: function BFSO_onSaveComplete(aSaver, aTarget) + onTargetChange: function BFSO_onSaveComplete(unused, aTarget) { if (aOnTargetChangeFn) { aOnTargetChangeFn(aTarget); } }, - onSaveComplete: function BFSO_onSaveComplete(aSaver, aStatus) + onSaveComplete: function BFSO_onSaveComplete(unused, aStatus) { if (Components.isSuccessCode(aStatus)) { deferred.resolve(); @@ -262,8 +262,6 @@ function waitForUpdates() { let deferred = Promise.defer(); gHttpServer.registerPathHandler("/downloads", function(request, response) { - let buf = NetUtil.readInputStreamToString(request.bodyInputStream, - request.bodyInputStream.available()); let blob = processUpdateRequest(); response.setHeader("Content-Type", "application/vnd.google.safebrowsing-update", false); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/.eslintrc.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/.eslintrc.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/.eslintrc.js 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/.eslintrc.js 2016-11-14 01:53:52.000000000 +0000 @@ -0,0 +1,11 @@ +"use strict"; + +module.exports = { + "rules": { + "no-unused-vars": ["error", { + "vars": "local", + "varsIgnorePattern": "^Cc|Ci|Cu|Cr|EXPORTED_SYMBOLS", + "args": "none", + }] + } +}; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/ext-c-runtime.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/ext-c-runtime.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/ext-c-runtime.js 2016-11-11 01:57:16.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/ext-c-runtime.js 2016-11-14 01:55:46.000000000 +0000 @@ -1,6 +1,4 @@ "use strict"; -XPCOMUtils.defineLazyModuleGetter(this, "NativeApp", - "resource://gre/modules/NativeMessaging.jsm"); function runtimeApiFactory(context) { let {extension} = context; @@ -62,13 +60,8 @@ childId: context.childManager.id, toNativeApp: application, }; - let rawPort = context.messenger.connectGetRawPort(context.messageManager, "", recipient); - let port = rawPort.api(); - port.postMessage = message => { - message = NativeApp.encodeMessage(context, message); - rawPort.postMessage(message); - }; - return port; + + return context.messenger.connectNative(context.messageManager, "", recipient); }, sendNativeMessage(application, message) { @@ -76,8 +69,7 @@ childId: context.childManager.id, toNativeApp: application, }; - message = NativeApp.encodeMessage(context, message); - return context.messenger.sendMessage(context.messageManager, message, recipient); + return context.messenger.sendNativeMessage(context.messageManager, message, recipient); }, get lastError() { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/ExtensionChild.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/ExtensionChild.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/ExtensionChild.jsm 2016-11-11 01:57:16.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/ExtensionChild.jsm 2016-11-14 01:55:46.000000000 +0000 @@ -19,34 +19,436 @@ const Cu = Components.utils; const Cr = Components.results; -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "ExtensionParent", + "resource://gre/modules/ExtensionParent.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "MessageChannel", "resource://gre/modules/MessageChannel.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "NativeApp", + "resource://gre/modules/NativeMessaging.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils", + "resource://gre/modules/PromiseUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Schemas", "resource://gre/modules/Schemas.jsm"); +XPCOMUtils.defineLazyGetter(this, "ParentAPIManager", + () => ExtensionParent.ParentAPIManager); + const CATEGORY_EXTENSION_SCRIPTS_ADDON = "webextension-scripts-addon"; +Cu.import("resource://gre/modules/ExtensionCommon.jsm"); Cu.import("resource://gre/modules/ExtensionUtils.jsm"); -var { + +const { + EventManager, + SingletonEventManager, + SpreadArgs, + defineLazyGetter, + findPathInObject, getInnerWindowID, + getMessageManager, + injectAPI, +} = ExtensionUtils; + +const { BaseContext, - ChildAPIManager, - defineLazyGetter, LocalAPIImplementation, - Messenger, + SchemaAPIInterface, SchemaAPIManager, -} = ExtensionUtils; +} = ExtensionCommon; -// There is a circular dependency between Extension.jsm and us. -// Long-term this file should not reference Extension.jsm (because they would -// live in different processes), but for now use lazy getters. -XPCOMUtils.defineLazyGetter(this, "findPathInObject", - () => Cu.import("resource://gre/modules/Extension.jsm", {}).findPathInObject); -XPCOMUtils.defineLazyGetter(this, "ParentAPIManager", - () => Cu.import("resource://gre/modules/Extension.jsm", {}).ParentAPIManager); +var ExtensionChild; + +let gNextPortId = 1; + +/** + * Abstraction for a Port object in the extension API. + * + * @param {BaseContext} context The context that owns this port. + * @param {nsIMessageSender} senderMM The message manager to send messages to. + * @param {Array} receiverMMs Message managers to + * listen on. + * @param {string} name Arbitrary port name as defined by the addon. + * @param {string} id An ID that uniquely identifies this port's channel. + * @param {object} sender The `port.sender` property. + * @param {object} recipient The recipient of messages sent from this port. + */ +class Port { + constructor(context, senderMM, receiverMMs, name, id, sender, recipient) { + this.context = context; + this.senderMM = senderMM; + this.receiverMMs = receiverMMs; + this.name = name; + this.id = id; + this.sender = sender; + this.recipient = recipient; + this.disconnected = false; + this.disconnectListeners = new Set(); + this.unregisterMessageFuncs = new Set(); + + // Common options for onMessage and onDisconnect. + this.handlerBase = { + messageFilterStrict: {portId: id}, + + filterMessage: (sender, recipient) => { + return sender.contextId !== this.context.contextId; + }, + }; + + this.disconnectHandler = Object.assign({ + receiveMessage: ({data}) => this.disconnectByOtherEnd(data), + }, this.handlerBase); + + MessageChannel.addListener(this.receiverMMs, "Extension:Port:Disconnect", this.disconnectHandler); + + this.context.callOnClose(this); + } + + static getNextID() { + return `${gNextPortId++}-${Services.appinfo.uniqueProcessID}`; + } + + api() { + let portObj = Cu.createObjectIn(this.context.cloneScope); + + let portError = null; + let publicAPI = { + name: this.name, + + disconnect: () => { + this.disconnect(); + }, + + postMessage: json => { + this.postMessage(json); + }, + + onDisconnect: new EventManager(this.context, "Port.onDisconnect", fire => { + return this.registerOnDisconnect(error => { + portError = error && this.context.normalizeError(error); + fire.withoutClone(portObj); + }); + }).api(), + + onMessage: new EventManager(this.context, "Port.onMessage", fire => { + return this.registerOnMessage(msg => { + msg = Cu.cloneInto(msg, this.context.cloneScope); + fire.withoutClone(msg, portObj); + }); + }).api(), + + get error() { + return portError; + }, + }; + + if (this.sender) { + publicAPI.sender = this.sender; + } + + injectAPI(publicAPI, portObj); + return portObj; + } + + postMessage(json) { + if (this.disconnected) { + throw new this.context.cloneScope.Error("Attempt to postMessage on disconnected port"); + } + + this._sendMessage("Extension:Port:PostMessage", json); + } + + /** + * Register a callback that is called when the port is disconnected by the + * *other* end. The callback is automatically unregistered when the port or + * context is closed. + * + * @param {function} callback Called when the other end disconnects the port. + * If the disconnect is caused by an error, the first parameter is an + * object with a "message" string property that describes the cause. + * @returns {function} Function to unregister the listener. + */ + registerOnDisconnect(callback) { + let listener = error => { + if (this.context.active && !this.disconnected) { + callback(error); + } + }; + this.disconnectListeners.add(listener); + return () => { + this.disconnectListeners.delete(listener); + }; + } + + /** + * Register a callback that is called when a message is received. The callback + * is automatically unregistered when the port or context is closed. + * + * @param {function} callback Called when a message is received. + * @returns {function} Function to unregister the listener. + */ + registerOnMessage(callback) { + let handler = Object.assign({ + receiveMessage: ({data}) => { + if (this.context.active && !this.disconnected) { + callback(data); + } + }, + }, this.handlerBase); + + let unregister = () => { + this.unregisterMessageFuncs.delete(unregister); + MessageChannel.removeListener(this.receiverMMs, "Extension:Port:PostMessage", handler); + }; + MessageChannel.addListener(this.receiverMMs, "Extension:Port:PostMessage", handler); + this.unregisterMessageFuncs.add(unregister); + return unregister; + } + + _sendMessage(message, data) { + let options = { + recipient: Object.assign({}, this.recipient, {portId: this.id}), + responseType: MessageChannel.RESPONSE_NONE, + }; + + return this.context.sendMessage(this.senderMM, message, data, options); + } + + handleDisconnection() { + MessageChannel.removeListener(this.receiverMMs, "Extension:Port:Disconnect", this.disconnectHandler); + for (let unregister of this.unregisterMessageFuncs) { + unregister(); + } + this.context.forgetOnClose(this); + this.disconnected = true; + } + + /** + * Disconnect the port from the other end (which may not even exist). + * + * @param {Error|{message: string}} [error] The reason for disconnecting, + * if it is an abnormal disconnect. + */ + disconnectByOtherEnd(error = null) { + if (this.disconnected) { + return; + } + + for (let listener of this.disconnectListeners) { + listener(error); + } + + this.handleDisconnection(); + } + + /** + * Disconnect the port from this end. + * + * @param {Error|{message: string}} [error] The reason for disconnecting, + * if it is an abnormal disconnect. + */ + disconnect(error = null) { + if (this.disconnected) { + // disconnect() may be called without side effects even after the port is + // closed - https://developer.chrome.com/extensions/runtime#type-Port + return; + } + this.handleDisconnection(); + if (error) { + error = {message: this.context.normalizeError(error).message}; + } + this._sendMessage("Extension:Port:Disconnect", error); + } + + close() { + this.disconnect(); + } +} + +class NativePort extends Port { + postMessage(data) { + data = NativeApp.encodeMessage(this.context, data); + + return super.postMessage(data); + } +} + +/** + * Each extension context gets its own Messenger object. It handles the + * basics of sendMessage, onMessage, connect and onConnect. + * + * @param {BaseContext} context The context to which this Messenger is tied. + * @param {Array} messageManagers + * The message managers used to receive messages (e.g. onMessage/onConnect + * requests). + * @param {object} sender Describes this sender to the recipient. This object + * is extended further by BaseContext's sendMessage method and appears as + * the `sender` object to `onConnect` and `onMessage`. + * Do not set the `extensionId`, `contextId` or `tab` properties. The former + * two are added by BaseContext's sendMessage, while `sender.tab` is set by + * the ProxyMessenger in the main process. + * @param {object} filter A recipient filter to apply to incoming messages from + * the broker. Messages are only handled by this Messenger if all key-value + * pairs match the `recipient` as specified by the sender of the message. + * In other words, this filter defines the required fields of `recipient`. + * @param {object} [optionalFilter] An additional filter to apply to incoming + * messages. Unlike `filter`, the keys from `optionalFilter` are allowed to + * be omitted from `recipient`. Only keys that are present in both + * `optionalFilter` and `recipient` are applied to filter incoming messages. + */ +class Messenger { + constructor(context, messageManagers, sender, filter, optionalFilter) { + this.context = context; + this.messageManagers = messageManagers; + this.sender = sender; + this.filter = filter; + this.optionalFilter = optionalFilter; + } + + _sendMessage(messageManager, message, data, recipient) { + let options = { + recipient, + sender: this.sender, + responseType: MessageChannel.RESPONSE_FIRST, + }; + + return this.context.sendMessage(messageManager, message, data, options); + } + + sendMessage(messageManager, msg, recipient, responseCallback) { + let promise = this._sendMessage(messageManager, "Extension:Message", msg, recipient) + .catch(error => { + if (error.result == MessageChannel.RESULT_NO_HANDLER) { + return Promise.reject({message: "Could not establish connection. Receiving end does not exist."}); + } else if (error.result != MessageChannel.RESULT_NO_RESPONSE) { + return Promise.reject({message: error.message}); + } + }); + + return this.context.wrapPromise(promise, responseCallback); + } + + sendNativeMessage(messageManager, msg, recipient, responseCallback) { + msg = NativeApp.encodeMessage(this.context, msg); + return this.sendMessage(messageManager, msg, recipient, responseCallback); + } + + onMessage(name) { + return new SingletonEventManager(this.context, name, callback => { + let listener = { + messageFilterPermissive: this.optionalFilter, + messageFilterStrict: this.filter, + + filterMessage: (sender, recipient) => { + // Ignore the message if it was sent by this Messenger. + return sender.contextId !== this.context.contextId; + }, + + receiveMessage: ({target, data: message, sender, recipient}) => { + if (!this.context.active) { + return; + } + + let sendResponse; + let response = undefined; + let promise = new Promise(resolve => { + sendResponse = value => { + resolve(value); + response = promise; + }; + }); + + message = Cu.cloneInto(message, this.context.cloneScope); + sender = Cu.cloneInto(sender, this.context.cloneScope); + sendResponse = Cu.exportFunction(sendResponse, this.context.cloneScope); + + // Note: We intentionally do not use runSafe here so that any + // errors are propagated to the message sender. + let result = callback(message, sender, sendResponse); + if (result instanceof this.context.cloneScope.Promise) { + return result; + } else if (result === true) { + return promise; + } + return response; + }, + }; + + MessageChannel.addListener(this.messageManagers, "Extension:Message", listener); + return () => { + MessageChannel.removeListener(this.messageManagers, "Extension:Message", listener); + }; + }).api(); + } + + _connect(messageManager, port, recipient) { + let msg = { + name: port.name, + portId: port.id, + }; + + this._sendMessage(messageManager, "Extension:Connect", msg, recipient).catch(error => { + if (error.result === MessageChannel.RESULT_NO_HANDLER) { + error = {message: "Could not establish connection. Receiving end does not exist."}; + } else if (error.result === MessageChannel.RESULT_DISCONNECTED) { + error = null; + } + port.disconnectByOtherEnd(error); + }); + + return port.api(); + } + + connect(messageManager, name, recipient) { + let portId = Port.getNextID(); + + let port = new Port(this.context, messageManager, this.messageManagers, name, portId, null, recipient); + + return this._connect(messageManager, port, recipient); + } + + connectNative(messageManager, name, recipient) { + let portId = Port.getNextID(); + + let port = new NativePort(this.context, messageManager, this.messageManagers, name, portId, null, recipient); + + return this._connect(messageManager, port, recipient); + } + + onConnect(name) { + return new SingletonEventManager(this.context, name, callback => { + let listener = { + messageFilterPermissive: this.optionalFilter, + messageFilterStrict: this.filter, + + filterMessage: (sender, recipient) => { + // Ignore the port if it was created by this Messenger. + return sender.contextId !== this.context.contextId; + }, + + receiveMessage: ({target, data: message, sender}) => { + let {name, portId} = message; + let mm = getMessageManager(target); + let recipient = Object.assign({}, sender); + if (recipient.tab) { + recipient.tabId = recipient.tab.id; + delete recipient.tab; + } + let port = new Port(this.context, mm, this.messageManagers, name, portId, sender, recipient); + this.context.runSafeWithoutClone(callback, port.api()); + return true; + }, + }; + + MessageChannel.addListener(this.messageManagers, "Extension:Connect", listener); + return () => { + MessageChannel.removeListener(this.messageManagers, "Extension:Connect", listener); + }; + }).api(); + } +} var apiManager = new class extends SchemaAPIManager { constructor() { @@ -71,57 +473,299 @@ } }(); +/** + * An object that runs an remote implementation of an API. + */ +class ProxyAPIImplementation extends SchemaAPIInterface { + /** + * @param {string} namespace The full path to the namespace that contains the + * `name` member. This may contain dots, e.g. "storage.local". + * @param {string} name The name of the method or property. + * @param {ChildAPIManager} childApiManager The owner of this implementation. + */ + constructor(namespace, name, childApiManager) { + super(); + this.path = `${namespace}.${name}`; + this.childApiManager = childApiManager; + } + + callFunctionNoReturn(args) { + this.childApiManager.callParentFunctionNoReturn(this.path, args); + } + + callAsyncFunction(args, callback) { + return this.childApiManager.callParentAsyncFunction(this.path, args, callback); + } + + addListener(listener, args) { + let set = this.childApiManager.listeners.get(this.path); + if (!set) { + set = new Set(); + this.childApiManager.listeners.set(this.path, set); + } + + set.add(listener); + + if (set.size == 1) { + args = args.slice(1); + + this.childApiManager.messageManager.sendAsyncMessage("API:AddListener", { + childId: this.childApiManager.id, + path: this.path, + args, + }); + } + } + + removeListener(listener) { + let set = this.childApiManager.listeners.get(this.path); + if (!set) { + return; + } + set.delete(listener); + + if (set.size == 0) { + this.childApiManager.messageManager.sendAsyncMessage("API:RemoveListener", { + childId: this.childApiManager.id, + path: this.path, + }); + } + } + + hasListener(listener) { + let set = this.childApiManager.listeners.get(this.path); + return set ? set.has(listener) : false; + } +} + +let nextId = 1; + +// We create one instance of this class for every extension context that +// needs to use remote APIs. It uses the message manager to communicate +// with the ParentAPIManager singleton in ExtensionParent.jsm. It +// handles asynchronous function calls as well as event listeners. +class ChildAPIManagerBase { + constructor(context, messageManager, localApis, contextData) { + this.context = context; + this.messageManager = messageManager; + + // The root namespace of all locally implemented APIs. If an extension calls + // an API that does not exist in this object, then the implementation is + // delegated to the ParentAPIManager. + this.localApis = localApis; + + this.id = `${context.extension.id}.${context.contextId}`; + + messageManager.addMessageListener("API:RunListener", this); + messageManager.addMessageListener("API:CallResult", this); + + // Map[path -> Set[listener]] + // path is, e.g., "runtime.onMessage". + this.listeners = new Map(); + + // Map[callId -> Deferred] + this.callPromises = new Map(); + } + + receiveMessage({name, data}) { + if (data.childId != this.id) { + return; + } + + switch (name) { + case "API:RunListener": + let listeners = this.listeners.get(data.path); + for (let callback of listeners) { + this.context.runSafe(callback, ...data.args); + } + break; + + case "API:CallResult": + let deferred = this.callPromises.get(data.callId); + if ("error" in data) { + deferred.reject(data.error); + } else { + deferred.resolve(new SpreadArgs(data.result)); + } + this.callPromises.delete(data.callId); + break; + } + } + + /** + * Call a function in the parent process and ignores its return value. + * + * @param {string} path The full name of the method, e.g. "tabs.create". + * @param {Array} args The parameters for the function. + */ + callParentFunctionNoReturn(path, args) { + this.messageManager.sendAsyncMessage("API:Call", { + childId: this.id, + path, + args, + }); + } + + /** + * Calls a function in the parent process and returns its result + * asynchronously. + * + * @param {string} path The full name of the method, e.g. "tabs.create". + * @param {Array} args The parameters for the function. + * @param {function(*)} [callback] The callback to be called when the function + * completes. + * @returns {Promise|undefined} Must be void if `callback` is set, and a + * promise otherwise. The promise is resolved when the function completes. + */ + callParentAsyncFunction(path, args, callback) { + let callId = nextId++; + let deferred = PromiseUtils.defer(); + this.callPromises.set(callId, deferred); + + this.messageManager.sendAsyncMessage("API:Call", { + childId: this.id, + callId, + path, + args, + }); + + return this.context.wrapPromise(deferred.promise, callback); + } + + /** + * Create a proxy for an event in the parent process. The returned event + * object shares its internal state with other instances. For instance, if + * `removeListener` is used on a listener that was added on another object + * through `addListener`, then the event is unregistered. + * + * @param {string} path The full name of the event, e.g. "tabs.onCreated". + * @returns {object} An object with the addListener, removeListener and + * hasListener methods. See SchemaAPIInterface for documentation. + */ + getParentEvent(path) { + path = path.split("."); + + let name = path.pop(); + let namespace = path.join("."); + + let impl = new ProxyAPIImplementation(namespace, name, this); + return { + addListener: (listener, ...args) => impl.addListener(listener, args), + removeListener: (listener) => impl.removeListener(listener), + hasListener: (listener) => impl.hasListener(listener), + }; + } + + close() { + this.messageManager.sendAsyncMessage("API:CloseProxyContext", {childId: this.id}); + } + + get cloneScope() { + return this.context.cloneScope; + } + + get principal() { + return this.context.principal; + } + + shouldInject(namespace, name, allowedContexts) { + // Do not generate content script APIs, unless explicitly allowed. + if (this.context.envType === "content_child" && + !allowedContexts.includes("content")) { + return false; + } + if (allowedContexts.includes("addon_parent_only")) { + return false; + } + return true; + } + + getImplementation(namespace, name) { + let obj = namespace.split(".").reduce( + (object, prop) => object && object[prop], + this.localApis); + + if (obj && name in obj) { + return new LocalAPIImplementation(obj, name, this.context); + } + + return this.getFallbackImplementation(namespace, name); + } + + getFallbackImplementation(namespace, name) { + // No local API found, defer implementation to the parent. + return new ProxyAPIImplementation(namespace, name, this); + } + + hasPermission(permission) { + return this.context.extension.hasPermission(permission); + } +} + +class ChildAPIManager extends ChildAPIManagerBase { + constructor(context, messageManager, localApis, contextData) { + super(context, messageManager, localApis, contextData); + + let params = { + childId: this.id, + extensionId: context.extension.id, + principal: context.principal, + }; + Object.assign(params, contextData); + + this.messageManager.sendAsyncMessage("API:CreateProxyContext", params); + } +} + + // A class that behaves identical to a ChildAPIManager, except // 1) creation of the ProxyContext in the parent is synchronous, and // 2) APIs without a local implementation and marked as incompatible with the // out-of-process model fall back to directly invoking the parent methods. // TODO(robwu): Remove this when all APIs have migrated. -class PseudoChildAPIManager extends ChildAPIManager { - createProxyContextInConstructor(originalData) { - // Create a structured clone to simulate IPC. - let data = Object.assign({}, originalData, {principal: null}); - data = Cu.cloneInto(data, {}); +class PseudoChildAPIManager extends ChildAPIManagerBase { + constructor(context, messageManager, localApis, contextData) { + super(context, messageManager, localApis, contextData); + + let params = { + childId: this.id, + extensionId: context.extension.id, + }; + Object.assign(params, contextData); + + // Structured clone the parameters to simulate cross-process messaging. + params = Cu.cloneInto(params, {}); // Principals can be structured cloned by message managers, but not // by cloneInto. - data.principal = originalData.principal; + params.principal = context.principal; + params.cloneScope = this.cloneScope; - this.url = data.url; + this.url = params.url; - let name = "API:CreateProxyContext"; - // The that receives messages from `this.messageManager`. - let target = this.context.contentWindow - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDocShell) - .chromeEventHandler; - ParentAPIManager.receiveMessage({name, data, target}); - - let proxyContext = ParentAPIManager.proxyContexts.get(this.id); - - // Use an identical cloneScope in the parent as the child to have identical - // behavior for proxied vs direct calls. If all APIs are proxied, then the - // parent cloneScope does not really matter (because when the message - // arrives locally, the object is cloned into the local clone scope). - // If all calls are direct, then the parent cloneScope does matter, because - // the objects are not cloned again. - Object.defineProperty(proxyContext, "cloneScope", { - get: () => this.cloneScope, + let browserElement = this.context.docShell.chromeEventHandler; + ParentAPIManager.receiveMessage({ + name: "API:CreateProxyContext", + data: params, + target: browserElement, }); + this.parentContext = ParentAPIManager.proxyContexts.get(this.id); + // Synchronously unload the ProxyContext because we synchronously create it. - this.context.callOnClose(proxyContext); + this.context.callOnClose(this.parentContext); } getFallbackImplementation(namespace, name) { // This is gross and should be removed ASAP. - let shouldSynchronouslyUseParentAPI = false; - // Incompatible APIs are listed here. - if (namespace == "webNavigation" || // ChildAPIManager is oblivious to filters. - namespace == "webRequest") { // Incompatible by design (synchronous). - shouldSynchronouslyUseParentAPI = true; - } - if (shouldSynchronouslyUseParentAPI) { - let proxyContext = ParentAPIManager.proxyContexts.get(this.id); - let apiObj = findPathInObject(proxyContext.apiObj, namespace, false); + let useDirectParentAPI = ( + // Incompatible APIs are listed here. + namespace == "webNavigation" || // ChildAPIManager is oblivious to filters. + namespace == "webRequest" // Incompatible by design (synchronous). + ); + + if (useDirectParentAPI) { + let apiObj = findPathInObject(this.parentContext.apiObj, namespace, false); + if (apiObj && name in apiObj) { return new LocalAPIImplementation(apiObj, name, this.context); } @@ -134,11 +778,14 @@ } } -class ExtensionContext extends BaseContext { +class ExtensionPageContextChild extends BaseContext { /** - * This ExtensionContext represents a privileged addon execution environment - * that has full access to the WebExtensions APIs (provided that the correct - * permissions have been requested). + * This ExtensionPageContextChild represents a privileged addon + * execution environment that has full access to the WebExtensions + * APIs (provided that the correct permissions have been requested). + * + * This is the child side of the ExtensionPageContextParent class + * defined in ExtensionParent.jsm. * * @param {BrowserExtensionContent} extension This context's owner. * @param {object} params @@ -154,7 +801,7 @@ if (Services.appinfo.processType != Services.appinfo.PROCESS_TYPE_DEFAULT) { // This check is temporary. It should be removed once the proxy creation // is asynchronous. - throw new Error("ExtensionContext cannot be created in child processes"); + throw new Error("ExtensionPageContextChild cannot be created in child processes"); } let {viewType, uri, contentWindow, tabId} = params; @@ -232,7 +879,7 @@ } } -defineLazyGetter(ExtensionContext.prototype, "messenger", function() { +defineLazyGetter(ExtensionPageContextChild.prototype, "messenger", function() { let filter = {extensionId: this.extension.id}; let optionalFilter = {}; // Addon-generated messages (not necessarily from the same process as the @@ -243,7 +890,7 @@ filter, optionalFilter); }); -defineLazyGetter(ExtensionContext.prototype, "childManager", function() { +defineLazyGetter(ExtensionPageContextChild.prototype, "childManager", function() { let localApis = {}; apiManager.generateAPIs(this, localApis); @@ -361,11 +1008,11 @@ } } -this.ExtensionChild = { +ExtensionChild = { // Map contentGlobals: new Map(), - // Map + // Map extensionContexts: new Map(), initOnce() { @@ -415,12 +1062,12 @@ let uri = contentWindow.document.documentURIObject; - context = new ExtensionContext(extension, {viewType, contentWindow, uri, tabId}); + context = new ExtensionPageContextChild(extension, {viewType, contentWindow, uri, tabId}); this.extensionContexts.set(windowId, context); }, /** - * Close the ExtensionContext belonging to the given window, if any. + * Close the ExtensionPageContextChild belonging to the given window, if any. * * @param {number} windowId The inner window ID of the destroyed context. */ @@ -446,7 +1093,15 @@ if (Services.appinfo.processType != Services.appinfo.PROCESS_TYPE_DEFAULT) { Object.keys(ExtensionChild).forEach(function(key) { if (typeof ExtensionChild[key] == "function") { + // :/ ExtensionChild[key] = () => {}; } }); } + +Object.assign(ExtensionChild, { + ChildAPIManager, + Messenger, + Port, +}); + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/ExtensionCommon.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/ExtensionCommon.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/ExtensionCommon.jsm 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/ExtensionCommon.jsm 2016-11-14 01:55:46.000000000 +0000 @@ -0,0 +1,683 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +/** + * This module contains utilities and base classes for logic which is + * common between the parent and child process, and in particular + * between ExtensionParent.jsm and ExtensionChild.jsm. + */ + +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; + +/* exported ExtensionCommon */ + +this.EXPORTED_SYMBOLS = ["ExtensionCommon"]; + +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +XPCOMUtils.defineLazyModuleGetter(this, "MessageChannel", + "resource://gre/modules/MessageChannel.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils", + "resource://gre/modules/PrivateBrowsingUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "Schemas", + "resource://gre/modules/Schemas.jsm"); + +Cu.import("resource://gre/modules/ExtensionUtils.jsm"); + +var { + EventEmitter, + ExtensionError, + SpreadArgs, + getConsole, + getInnerWindowID, + runSafeSync, + runSafeSyncWithoutClone, + instanceOf, +} = ExtensionUtils; + +XPCOMUtils.defineLazyGetter(this, "console", getConsole); + +let gContextId = 0; + +class BaseContext { + constructor(envType, extension) { + this.envType = envType; + this.onClose = new Set(); + this.checkedLastError = false; + this._lastError = null; + this.contextId = `${++gContextId}-${Services.appinfo.uniqueProcessID}`; + this.unloaded = false; + this.extension = extension; + this.jsonSandbox = null; + this.active = true; + this.incognito = null; + this.messageManager = null; + this.docShell = null; + this.contentWindow = null; + this.innerWindowID = 0; + } + + setContentWindow(contentWindow) { + let {document} = contentWindow; + let docShell = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDocShell); + + this.innerWindowID = getInnerWindowID(contentWindow); + this.messageManager = docShell.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIContentFrameMessageManager); + + if (this.incognito == null) { + this.incognito = PrivateBrowsingUtils.isContentWindowPrivate(contentWindow); + } + + MessageChannel.setupMessageManagers([this.messageManager]); + + let onPageShow = event => { + if (!event || event.target === document) { + this.docShell = docShell; + this.contentWindow = contentWindow; + this.active = true; + } + }; + let onPageHide = event => { + if (!event || event.target === document) { + // Put this off until the next tick. + Promise.resolve().then(() => { + this.docShell = null; + this.contentWindow = null; + this.active = false; + }); + } + }; + + onPageShow(); + contentWindow.addEventListener("pagehide", onPageHide, true); + contentWindow.addEventListener("pageshow", onPageShow, true); + this.callOnClose({ + close: () => { + onPageHide(); + if (this.active) { + contentWindow.removeEventListener("pagehide", onPageHide, true); + contentWindow.removeEventListener("pageshow", onPageShow, true); + } + }, + }); + } + + get cloneScope() { + throw new Error("Not implemented"); + } + + get principal() { + throw new Error("Not implemented"); + } + + runSafe(...args) { + if (this.unloaded) { + Cu.reportError("context.runSafe called after context unloaded"); + } else if (!this.active) { + Cu.reportError("context.runSafe called while context is inactive"); + } else { + return runSafeSync(this, ...args); + } + } + + runSafeWithoutClone(...args) { + if (this.unloaded) { + Cu.reportError("context.runSafeWithoutClone called after context unloaded"); + } else if (!this.active) { + Cu.reportError("context.runSafeWithoutClone called while context is inactive"); + } else { + return runSafeSyncWithoutClone(...args); + } + } + + checkLoadURL(url, options = {}) { + let ssm = Services.scriptSecurityManager; + + let flags = ssm.STANDARD; + if (!options.allowScript) { + flags |= ssm.DISALLOW_SCRIPT; + } + if (!options.allowInheritsPrincipal) { + flags |= ssm.DISALLOW_INHERIT_PRINCIPAL; + } + if (options.dontReportErrors) { + flags |= ssm.DONT_REPORT_ERRORS; + } + + try { + ssm.checkLoadURIStrWithPrincipal(this.principal, url, flags); + } catch (e) { + return false; + } + return true; + } + + /** + * Safely call JSON.stringify() on an object that comes from an + * extension. + * + * @param {array} args Arguments for JSON.stringify() + * @returns {string} The stringified representation of obj + */ + jsonStringify(...args) { + if (!this.jsonSandbox) { + this.jsonSandbox = Cu.Sandbox(this.principal, { + sameZoneAs: this.cloneScope, + wantXrays: false, + }); + } + + return Cu.waiveXrays(this.jsonSandbox.JSON).stringify(...args); + } + + callOnClose(obj) { + this.onClose.add(obj); + } + + forgetOnClose(obj) { + this.onClose.delete(obj); + } + + /** + * A wrapper around MessageChannel.sendMessage which adds the extension ID + * to the recipient object, and ensures replies are not processed after the + * context has been unloaded. + * + * @param {nsIMessageManager} target + * @param {string} messageName + * @param {object} data + * @param {object} [options] + * @param {object} [options.sender] + * @param {object} [options.recipient] + * + * @returns {Promise} + */ + sendMessage(target, messageName, data, options = {}) { + options.recipient = options.recipient || {}; + options.sender = options.sender || {}; + + // TODO(robwu): This should not unconditionally be overwritten once we + // support onMessageExternal / onConnectExternal (bugzil.la/1258360). + options.recipient.extensionId = this.extension.id; + options.sender.extensionId = this.extension.id; + options.sender.contextId = this.contextId; + + return MessageChannel.sendMessage(target, messageName, data, options); + } + + get lastError() { + this.checkedLastError = true; + return this._lastError; + } + + set lastError(val) { + this.checkedLastError = false; + this._lastError = val; + } + + /** + * Normalizes the given error object for use by the target scope. If + * the target is an error object which belongs to that scope, it is + * returned as-is. If it is an ordinary object with a `message` + * property, it is converted into an error belonging to the target + * scope. If it is an Error object which does *not* belong to the + * clone scope, it is reported, and converted to an unexpected + * exception error. + * + * @param {Error|object} error + * @returns {Error} + */ + normalizeError(error) { + if (error instanceof this.cloneScope.Error) { + return error; + } + let message; + if (instanceOf(error, "Object") || error instanceof ExtensionError) { + message = error.message; + } else if (typeof error == "object" && + this.principal.subsumes(Cu.getObjectPrincipal(error))) { + message = error.message; + } else { + Cu.reportError(error); + } + message = message || "An unexpected error occurred"; + return new this.cloneScope.Error(message); + } + + /** + * Sets the value of `.lastError` to `error`, calls the given + * callback, and reports an error if the value has not been checked + * when the callback returns. + * + * @param {object} error An object with a `message` property. May + * optionally be an `Error` object belonging to the target scope. + * @param {function} callback The callback to call. + * @returns {*} The return value of callback. + */ + withLastError(error, callback) { + this.lastError = this.normalizeError(error); + try { + return callback(); + } finally { + if (!this.checkedLastError) { + Cu.reportError(`Unchecked lastError value: ${this.lastError}`); + } + this.lastError = null; + } + } + + /** + * Wraps the given promise so it can be safely returned to extension + * code in this context. + * + * If `callback` is provided, however, it is used as a completion + * function for the promise, and no promise is returned. In this case, + * the callback is called when the promise resolves or rejects. In the + * latter case, `lastError` is set to the rejection value, and the + * callback function must check `browser.runtime.lastError` or + * `extension.runtime.lastError` in order to prevent it being reported + * to the console. + * + * @param {Promise} promise The promise with which to wrap the + * callback. May resolve to a `SpreadArgs` instance, in which case + * each element will be used as a separate argument. + * + * Unless the promise object belongs to the cloneScope global, its + * resolution value is cloned into cloneScope prior to calling the + * `callback` function or resolving the wrapped promise. + * + * @param {function} [callback] The callback function to wrap + * + * @returns {Promise|undefined} If callback is null, a promise object + * belonging to the target scope. Otherwise, undefined. + */ + wrapPromise(promise, callback = null) { + let runSafe = this.runSafe.bind(this); + if (promise instanceof this.cloneScope.Promise) { + runSafe = this.runSafeWithoutClone.bind(this); + } + + if (callback) { + promise.then( + args => { + if (this.unloaded) { + dump(`Promise resolved after context unloaded\n`); + } else if (!this.active) { + dump(`Promise resolved while context is inactive\n`); + } else if (args instanceof SpreadArgs) { + runSafe(callback, ...args); + } else { + runSafe(callback, args); + } + }, + error => { + this.withLastError(error, () => { + if (this.unloaded) { + dump(`Promise rejected after context unloaded\n`); + } else if (!this.active) { + dump(`Promise rejected while context is inactive\n`); + } else { + this.runSafeWithoutClone(callback); + } + }); + }); + } else { + return new this.cloneScope.Promise((resolve, reject) => { + promise.then( + value => { + if (this.unloaded) { + dump(`Promise resolved after context unloaded\n`); + } else if (!this.active) { + dump(`Promise resolved while context is inactive\n`); + } else if (value instanceof SpreadArgs) { + runSafe(resolve, value.length == 1 ? value[0] : value); + } else { + runSafe(resolve, value); + } + }, + value => { + if (this.unloaded) { + dump(`Promise rejected after context unloaded: ${value && value.message}\n`); + } else if (!this.active) { + dump(`Promise rejected while context is inactive: ${value && value.message}\n`); + } else { + this.runSafeWithoutClone(reject, this.normalizeError(value)); + } + }); + }); + } + } + + unload() { + this.unloaded = true; + + MessageChannel.abortResponses({ + extensionId: this.extension.id, + contextId: this.contextId, + }); + + for (let obj of this.onClose) { + obj.close(); + } + } + + /** + * A simple proxy for unload(), for use with callOnClose(). + */ + close() { + this.unload(); + } +} + +/** + * An object that runs the implementation of a schema API. Instantiations of + * this interfaces are used by Schemas.jsm. + * + * @interface + */ +class SchemaAPIInterface { + /** + * Calls this as a function that returns its return value. + * + * @abstract + * @param {Array} args The parameters for the function. + * @returns {*} The return value of the invoked function. + */ + callFunction(args) { + throw new Error("Not implemented"); + } + + /** + * Calls this as a function and ignores its return value. + * + * @abstract + * @param {Array} args The parameters for the function. + */ + callFunctionNoReturn(args) { + throw new Error("Not implemented"); + } + + /** + * Calls this as a function that completes asynchronously. + * + * @abstract + * @param {Array} args The parameters for the function. + * @param {function(*)} [callback] The callback to be called when the function + * completes. + * @returns {Promise|undefined} Must be void if `callback` is set, and a + * promise otherwise. The promise is resolved when the function completes. + */ + callAsyncFunction(args, callback) { + throw new Error("Not implemented"); + } + + /** + * Retrieves the value of this as a property. + * + * @abstract + * @returns {*} The value of the property. + */ + getProperty() { + throw new Error("Not implemented"); + } + + /** + * Assigns the value to this as property. + * + * @abstract + * @param {string} value The new value of the property. + */ + setProperty(value) { + throw new Error("Not implemented"); + } + + /** + * Registers a `listener` to this as an event. + * + * @abstract + * @param {function} listener The callback to be called when the event fires. + * @param {Array} args Extra parameters for EventManager.addListener. + * @see EventManager.addListener + */ + addListener(listener, args) { + throw new Error("Not implemented"); + } + + /** + * Checks whether `listener` is listening to this as an event. + * + * @abstract + * @param {function} listener The event listener. + * @returns {boolean} Whether `listener` is registered with this as an event. + * @see EventManager.hasListener + */ + hasListener(listener) { + throw new Error("Not implemented"); + } + + /** + * Unregisters `listener` from this as an event. + * + * @abstract + * @param {function} listener The event listener. + * @see EventManager.removeListener + */ + removeListener(listener) { + throw new Error("Not implemented"); + } +} + +/** + * An object that runs a locally implemented API. + */ +class LocalAPIImplementation extends SchemaAPIInterface { + /** + * Constructs an implementation of the `name` method or property of `pathObj`. + * + * @param {object} pathObj The object containing the member with name `name`. + * @param {string} name The name of the implemented member. + * @param {BaseContext} context The context in which the schema is injected. + */ + constructor(pathObj, name, context) { + super(); + this.pathObj = pathObj; + this.name = name; + this.context = context; + } + + callFunction(args) { + return this.pathObj[this.name](...args); + } + + callFunctionNoReturn(args) { + this.pathObj[this.name](...args); + } + + callAsyncFunction(args, callback) { + let promise; + try { + promise = this.pathObj[this.name](...args) || Promise.resolve(); + } catch (e) { + promise = Promise.reject(e); + } + return this.context.wrapPromise(promise, callback); + } + + getProperty() { + return this.pathObj[this.name]; + } + + setProperty(value) { + this.pathObj[this.name] = value; + } + + addListener(listener, args) { + try { + this.pathObj[this.name].addListener.call(null, listener, ...args); + } catch (e) { + throw this.context.normalizeError(e); + } + } + + hasListener(listener) { + return this.pathObj[this.name].hasListener.call(null, listener); + } + + removeListener(listener) { + this.pathObj[this.name].removeListener.call(null, listener); + } +} + +/** + * This object loads the ext-*.js scripts that define the extension API. + * + * This class instance is shared with the scripts that it loads, so that the + * ext-*.js scripts and the instantiator can communicate with each other. + */ +class SchemaAPIManager extends EventEmitter { + /** + * @param {string} processType + * "main" - The main, one and only chrome browser process. + * "addon" - An addon process. + * "content" - A content process. + */ + constructor(processType) { + super(); + this.processType = processType; + this.global = this._createExtGlobal(); + this._scriptScopes = []; + this._schemaApis = { + addon_parent: [], + addon_child: [], + content_parent: [], + content_child: [], + }; + } + + /** + * Create a global object that is used as the shared global for all ext-*.js + * scripts that are loaded via `loadScript`. + * + * @returns {object} A sandbox that is used as the global by `loadScript`. + */ + _createExtGlobal() { + let global = Cu.Sandbox(Services.scriptSecurityManager.getSystemPrincipal(), { + wantXrays: false, + sandboxName: `Namespace of ext-*.js scripts for ${this.processType}`, + }); + + Object.assign(global, {global, Cc, Ci, Cu, Cr, XPCOMUtils, extensions: this}); + + XPCOMUtils.defineLazyGetter(global, "console", getConsole); + + XPCOMUtils.defineLazyModuleGetter(global, "require", + "resource://devtools/shared/Loader.jsm"); + + return global; + } + + /** + * Load an ext-*.js script. The script runs in its own scope, if it wishes to + * share state with another script it can assign to the `global` variable. If + * it wishes to communicate with this API manager, use `extensions`. + * + * @param {string} scriptUrl The URL of the ext-*.js script. + */ + loadScript(scriptUrl) { + // Create the object in the context of the sandbox so that the script runs + // in the sandbox's context instead of here. + let scope = Cu.createObjectIn(this.global); + + Services.scriptloader.loadSubScript(scriptUrl, scope, "UTF-8"); + + // Save the scope to avoid it being garbage collected. + this._scriptScopes.push(scope); + } + + /** + * Called by an ext-*.js script to register an API. + * + * @param {string} namespace The API namespace. + * Intended to match the namespace of the generated API, but not used at + * the moment - see bugzil.la/1295774. + * @param {string} envType Restricts the API to contexts that run in the + * given environment. Must be one of the following: + * - "addon_parent" - addon APIs that runs in the main process. + * - "addon_child" - addon APIs that runs in an addon process. + * - "content_parent" - content script APIs that runs in the main process. + * - "content_child" - content script APIs that runs in a content process. + * @param {function(BaseContext)} getAPI A function that returns an object + * that will be merged with |chrome| and |browser|. The next example adds + * the create, update and remove methods to the tabs API. + * + * registerSchemaAPI("tabs", "addon_parent", (context) => ({ + * tabs: { create, update }, + * })); + * registerSchemaAPI("tabs", "addon_parent", (context) => ({ + * tabs: { remove }, + * })); + */ + registerSchemaAPI(namespace, envType, getAPI) { + this._schemaApis[envType].push({namespace, getAPI}); + } + + /** + * Exports all registered scripts to `obj`. + * + * @param {BaseContext} context The context for which the API bindings are + * generated. + * @param {object} obj The destination of the API. + */ + generateAPIs(context, obj) { + let apis = this._schemaApis[context.envType]; + if (!apis) { + Cu.reportError(`No APIs have been registered for ${context.envType}`); + return; + } + SchemaAPIManager.generateAPIs(context, apis, obj); + } + + /** + * Mash together all the APIs from `apis` into `obj`. + * + * @param {BaseContext} context The context for which the API bindings are + * generated. + * @param {Array} apis A list of objects, see `registerSchemaAPI`. + * @param {object} obj The destination of the API. + */ + static generateAPIs(context, apis, obj) { + // Recursively copy properties from source to dest. + function copy(dest, source) { + for (let prop in source) { + let desc = Object.getOwnPropertyDescriptor(source, prop); + if (typeof(desc.value) == "object") { + if (!(prop in dest)) { + dest[prop] = {}; + } + copy(dest[prop], source[prop]); + } else { + Object.defineProperty(dest, prop, desc); + } + } + } + + for (let api of apis) { + if (Schemas.checkPermissions(api.namespace, context.extension)) { + api = api.getAPI(context); + copy(obj, api); + } + } + } +} + +const ExtensionCommon = { + BaseContext, + LocalAPIImplementation, + SchemaAPIInterface, + SchemaAPIManager, +}; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/ExtensionContent.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/ExtensionContent.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/ExtensionContent.jsm 2016-11-11 01:57:16.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/ExtensionContent.jsm 2016-11-14 01:55:46.000000000 +0000 @@ -45,21 +45,28 @@ "resource://gre/modules/WebNavigationFrames.jsm"); Cu.import("resource://gre/modules/ExtensionChild.jsm"); - +Cu.import("resource://gre/modules/ExtensionCommon.jsm"); Cu.import("resource://gre/modules/ExtensionUtils.jsm"); -var { - runSafeSyncWithoutClone, - defineLazyGetter, - BaseContext, + +const { LocaleData, - Messenger, + defineLazyGetter, flushJarCache, getInnerWindowID, promiseDocumentReady, - ChildAPIManager, - SchemaAPIManager, + runSafeSyncWithoutClone, } = ExtensionUtils; +const { + BaseContext, + SchemaAPIManager, +} = ExtensionCommon; + +const { + ChildAPIManager, + Messenger, +} = ExtensionChild; + XPCOMUtils.defineLazyGetter(this, "console", ExtensionUtils.getConsole); const CATEGORY_EXTENSION_SCRIPTS_CONTENT = "webextension-scripts-content"; @@ -279,10 +286,13 @@ var DocumentManager; var ExtensionManager; -// Scope in which extension content script code can run. It uses -// Cu.Sandbox to run the code. There is a separate scope for each -// frame. -class ExtensionContext extends BaseContext { +/** + * An execution context for semi-privileged extension content scripts. + * + * This is the child side of the ContentScriptContextParent class + * defined in ExtensionParent.jsm. + */ +class ContentScriptContextChild extends BaseContext { constructor(extension, contentWindow, contextOptions = {}) { super("content_child", extension); @@ -434,7 +444,7 @@ } } -defineLazyGetter(ExtensionContext.prototype, "messenger", function() { +defineLazyGetter(ContentScriptContextChild.prototype, "messenger", function() { // The |sender| parameter is passed directly to the extension. let sender = {id: this.extension.uuid, frameId: this.frameId, url: this.url}; let filter = {extensionId: this.extension.id}; @@ -443,7 +453,7 @@ return new Messenger(this, [this.messageManager], sender, filter, optionalFilter); }); -defineLazyGetter(ExtensionContext.prototype, "childManager", function() { +defineLazyGetter(ContentScriptContextChild.prototype, "childManager", function() { let localApis = {}; apiManager.generateAPIs(this, localApis); @@ -462,10 +472,10 @@ DocumentManager = { extensionCount: 0, - // Map[windowId -> Map[extensionId -> ExtensionContext]] + // Map[windowId -> Map[extensionId -> ContentScriptContextChild]] contentScriptWindows: new Map(), - // Map[windowId -> ExtensionContext] + // Map[windowId -> ContentScriptContextChild] extensionPageWindows: new Map(), init() { @@ -664,7 +674,7 @@ let extensions = this.contentScriptWindows.get(winId); if (!extensions.has(extension.id)) { - let context = new ExtensionContext(extension, window); + let context = new ContentScriptContextChild(extension, window); extensions.set(extension.id, context); } @@ -676,7 +686,7 @@ let context = this.extensionPageWindows.get(winId); if (!context) { - let context = new ExtensionContext(extension, window, {isExtensionPage: true}); + let context = new ContentScriptContextChild(extension, window, {isExtensionPage: true}); this.extensionPageWindows.set(winId, context); } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/Extension.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/Extension.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/Extension.jsm 2016-11-11 01:57:16.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/Extension.jsm 2016-11-14 01:55:46.000000000 +0000 @@ -34,8 +34,8 @@ "resource://gre/modules/ExtensionAPI.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "ExtensionStorage", "resource://gre/modules/ExtensionStorage.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", - "resource://gre/modules/FileUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "ExtensionTestCommon", + "resource://testing-common/ExtensionTestCommon.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Locale", "resource://gre/modules/Locale.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Log", @@ -46,8 +46,6 @@ "resource://gre/modules/MatchPattern.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "MessageChannel", "resource://gre/modules/MessageChannel.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "NativeApp", - "resource://gre/modules/NativeMessaging.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "OS", @@ -65,31 +63,22 @@ Cu.import("resource://gre/modules/ExtensionContent.jsm"); Cu.import("resource://gre/modules/ExtensionManagement.jsm"); +Cu.import("resource://gre/modules/ExtensionParent.jsm"); +Cu.import("resource://gre/modules/ExtensionUtils.jsm"); XPCOMUtils.defineLazyServiceGetter(this, "uuidGen", "@mozilla.org/uuid-generator;1", "nsIUUIDGenerator"); -const BASE_SCHEMA = "chrome://extensions/content/schemas/manifest.json"; -const CATEGORY_EXTENSION_SCHEMAS = "webextension-schemas"; -const CATEGORY_EXTENSION_SCRIPTS = "webextension-scripts"; - -let schemaURLs = new Set(); - -if (!AppConstants.RELEASE_OR_BETA) { - schemaURLs.add("chrome://extensions/content/schemas/experiments.json"); -} - -Cu.import("resource://gre/modules/ExtensionUtils.jsm"); var { - BaseContext, + GlobalManager, + ParentAPIManager, + apiManager: Management, +} = ExtensionParent; + +const { EventEmitter, LocaleData, - SchemaAPIManager, - SpreadArgs, - defineLazyGetter, - flushJarCache, - instanceOf, } = ExtensionUtils; XPCOMUtils.defineLazyGetter(this, "console", ExtensionUtils.getConsole); @@ -111,475 +100,6 @@ //.* `.replace(/\s+/g, ""), "gm"); -var GlobalManager; -var ParentAPIManager; - -// This object loads the ext-*.js scripts that define the extension API. -var Management = new class extends SchemaAPIManager { - constructor() { - super("main"); - this.initialized = null; - } - - // Loads all the ext-*.js scripts currently registered. - lazyInit() { - if (this.initialized) { - return this.initialized; - } - - // Load order matters here. The base manifest defines types which are - // extended by other schemas, so needs to be loaded first. - let promise = Schemas.load(BASE_SCHEMA).then(() => { - let promises = []; - for (let [/* name */, url] of XPCOMUtils.enumerateCategoryEntries(CATEGORY_EXTENSION_SCHEMAS)) { - promises.push(Schemas.load(url)); - } - for (let url of schemaURLs) { - promises.push(Schemas.load(url)); - } - return Promise.all(promises); - }); - - for (let [/* name */, value] of XPCOMUtils.enumerateCategoryEntries(CATEGORY_EXTENSION_SCRIPTS)) { - this.loadScript(value); - } - - this.initialized = promise; - return this.initialized; - } - - registerSchemaAPI(namespace, envType, getAPI) { - if (envType == "addon_parent" || envType == "content_parent") { - super.registerSchemaAPI(namespace, envType, getAPI); - } - } -}(); - -// Subscribes to messages related to the extension messaging API and forwards it -// to the relevant message manager. The "sender" field for the `onMessage` and -// `onConnect` events are updated if needed. -let ProxyMessenger = { - _initialized: false, - init() { - if (this._initialized) { - return; - } - this._initialized = true; - - // TODO(robwu): When addons move to a separate process, we should use the - // parent process manager(s) of the addon process(es) instead of the - // in-process one. - let pipmm = Services.ppmm.getChildAt(0); - // Listen on the global frame message manager because content scripts send - // and receive extension messages via their frame. - // Listen on the parent process message manager because `runtime.connect` - // and `runtime.sendMessage` requests must be delivered to all frames in an - // addon process (by the API contract). - // And legacy addons are not associated with a frame, so that is another - // reason for having a parent process manager here. - let messageManagers = [Services.mm, pipmm]; - - MessageChannel.addListener(messageManagers, "Extension:Connect", this); - MessageChannel.addListener(messageManagers, "Extension:Message", this); - MessageChannel.addListener(messageManagers, "Extension:Port:Disconnect", this); - MessageChannel.addListener(messageManagers, "Extension:Port:PostMessage", this); - }, - - receiveMessage({target, messageName, channelId, sender, recipient, data, responseType}) { - if (recipient.toNativeApp) { - let {childId, toNativeApp} = recipient; - if (messageName == "Extension:Message") { - let context = ParentAPIManager.getContextById(childId); - return new NativeApp(context, toNativeApp).sendMessage(data); - } - if (messageName == "Extension:Connect") { - let context = ParentAPIManager.getContextById(childId); - NativeApp.onConnectNative(context, target.messageManager, data.portId, sender, toNativeApp); - return true; - } - // "Extension:Port:Disconnect" and "Extension:Port:PostMessage" for - // native messages are handled by NativeApp. - return; - } - let extension = GlobalManager.extensionMap.get(sender.extensionId); - let receiverMM = this._getMessageManagerForRecipient(recipient); - if (!extension || !receiverMM) { - return Promise.reject({ - result: MessageChannel.RESULT_NO_HANDLER, - message: "No matching message handler for the given recipient.", - }); - } - - if ((messageName == "Extension:Message" || - messageName == "Extension:Connect") && - Management.global.tabGetSender) { - // From ext-tabs.js, undefined on Android. - Management.global.tabGetSender(extension, target, sender); - } - return MessageChannel.sendMessage(receiverMM, messageName, data, { - sender, - recipient, - responseType, - }); - }, - - /** - * @param {object} recipient An object that was passed to - * `MessageChannel.sendMessage`. - * @returns {object|null} The message manager matching the recipient if found. - */ - _getMessageManagerForRecipient(recipient) { - let {extensionId, tabId} = recipient; - // tabs.sendMessage / tabs.connect - if (tabId) { - // `tabId` being set implies that the tabs API is supported, so we don't - // need to check whether `TabManager` exists. - let tab = Management.global.TabManager.getTab(tabId, null, null); - return tab && tab.linkedBrowser.messageManager; - } - - // runtime.sendMessage / runtime.connect - if (extensionId) { - // TODO(robwu): map the extensionId to the addon parent process's message - // manager when they run in a separate process. - return Services.ppmm.getChildAt(0); - } - - return null; - }, -}; - -class BrowserDocshellFollower { - /** - * Follows the belonging to the `xulBrowser`'s current docshell. - * - * @param {XULElement} xulBrowser A tag. - * @param {function} onBrowserChange Called when the changes. - */ - constructor(xulBrowser, onBrowserChange) { - this.xulBrowser = xulBrowser; - this.onBrowserChange = onBrowserChange; - - xulBrowser.addEventListener("SwapDocShells", this); - } - - destroy() { - this.xulBrowser.removeEventListener("SwapDocShells", this); - this.xulBrowser = null; - } - - handleEvent({detail: otherBrowser}) { - this.xulBrowser.removeEventListener("SwapDocShells", this); - this.xulBrowser = otherBrowser; - this.xulBrowser.addEventListener("SwapDocShells", this); - this.onBrowserChange(otherBrowser); - } -} - -class ProxyContext extends BaseContext { - constructor(envType, extension, params, xulBrowser, principal) { - super(envType, extension); - - this.uri = NetUtil.newURI(params.url); - - this.incognito = params.incognito; - - // This message manager is used by ParentAPIManager to send messages and to - // close the ProxyContext if the underlying message manager closes. This - // message manager object may change when `xulBrowser` swaps docshells, e.g. - // when a tab is moved to a different window. - this.currentMessageManager = xulBrowser.messageManager; - this._docShellTracker = new BrowserDocshellFollower( - xulBrowser, this.onBrowserChange.bind(this)); - - Object.defineProperty(this, "principal", { - value: principal, enumerable: true, configurable: true, - }); - - this.listenerProxies = new Map(); - - Management.emit("proxy-context-load", this); - } - - get cloneScope() { - return this.sandbox; - } - - onBrowserChange(browser) { - // Make sure that the message manager is set. Otherwise the ProxyContext may - // never be destroyed because the ParentAPIManager would fail to detect that - // the message manager is closed. - if (!browser.messageManager) { - throw new Error("BrowserDocshellFollower: The new browser has no message manager"); - } - - this.currentMessageManager = browser.messageManager; - } - - shutdown() { - this.unload(); - } - - unload() { - if (this.unloaded) { - return; - } - this._docShellTracker.destroy(); - super.unload(); - Management.emit("proxy-context-unload", this); - } -} - -defineLazyGetter(ProxyContext.prototype, "apiObj", function() { - let obj = {}; - GlobalManager.injectInObject(this, false, obj); - return obj; -}); - -defineLazyGetter(ProxyContext.prototype, "sandbox", function() { - return Cu.Sandbox(this.principal); -}); - -// The parent ProxyContext of an ExtensionContext in ExtensionChild.jsm. -class ExtensionChildProxyContext extends ProxyContext { - constructor(envType, extension, params, xulBrowser) { - super(envType, extension, params, xulBrowser, extension.principal); - - this.viewType = params.viewType; - // WARNING: The xulBrowser may change when docShells are swapped, e.g. when - // the tab moves to a different window. - this.xulBrowser = xulBrowser; - } - - // The window that contains this context. This may change due to moving tabs. - get xulWindow() { - return this.xulBrowser.ownerGlobal; - } - - get windowId() { - if (!Management.global.WindowManager || this.viewType == "background") { - return; - } - // viewType popup or tab: - return Management.global.WindowManager.getId(this.xulWindow); - } - - get tabId() { - if (!Management.global.TabManager) { - return; // Not yet supported on Android. - } - let {gBrowser} = this.xulBrowser.ownerGlobal; - let tab = gBrowser && gBrowser.getTabForBrowser(this.xulBrowser); - return tab && Management.global.TabManager.getId(tab); - } - - onBrowserChange(browser) { - super.onBrowserChange(browser); - this.xulBrowser = browser; - } - - shutdown() { - Management.emit("page-shutdown", this); - super.shutdown(); - } -} - -function findPathInObject(obj, path, printErrors = true) { - let parent; - for (let elt of path.split(".")) { - if (!obj || !(elt in obj)) { - if (printErrors) { - Cu.reportError(`WebExtension API ${path} not found (it may be unimplemented by Firefox).`); - } - return null; - } - - parent = obj; - obj = obj[elt]; - } - - if (typeof obj === "function") { - return obj.bind(parent); - } - return obj; -} - -ParentAPIManager = { - proxyContexts: new Map(), - - init() { - Services.obs.addObserver(this, "message-manager-close", false); - - Services.mm.addMessageListener("API:CreateProxyContext", this); - Services.mm.addMessageListener("API:CloseProxyContext", this, true); - Services.mm.addMessageListener("API:Call", this); - Services.mm.addMessageListener("API:AddListener", this); - Services.mm.addMessageListener("API:RemoveListener", this); - }, - - // "message-manager-close" observer. - observe(subject, topic, data) { - let mm = subject; - for (let [childId, context] of this.proxyContexts) { - if (context.currentMessageManager == mm) { - this.closeProxyContext(childId); - } - } - }, - - shutdownExtension(extensionId) { - for (let [childId, context] of this.proxyContexts) { - if (context.extension.id == extensionId) { - context.shutdown(); - this.proxyContexts.delete(childId); - } - } - }, - - receiveMessage({name, data, target}) { - switch (name) { - case "API:CreateProxyContext": - this.createProxyContext(data, target); - break; - - case "API:CloseProxyContext": - this.closeProxyContext(data.childId); - break; - - case "API:Call": - this.call(data, target); - break; - - case "API:AddListener": - this.addListener(data, target); - break; - - case "API:RemoveListener": - this.removeListener(data); - break; - } - }, - - createProxyContext(data, target) { - let {envType, extensionId, childId, principal} = data; - if (this.proxyContexts.has(childId)) { - throw new Error("A WebExtension context with the given ID already exists!"); - } - - let extension = GlobalManager.getExtension(extensionId); - if (!extension) { - throw new Error(`No WebExtension found with ID ${extensionId}`); - } - - let context; - if (envType == "addon_parent") { - // Privileged addon contexts can only be loaded in documents whose main - // frame is also the same addon. - if (principal.URI.prePath != extension.baseURI.prePath || - !target.contentPrincipal.subsumes(principal)) { - throw new Error(`Refused to create privileged WebExtension context for ${principal.URI.spec}`); - } - context = new ExtensionChildProxyContext(envType, extension, data, target); - } else if (envType == "content_parent") { - context = new ProxyContext(envType, extension, data, target, principal); - } else { - throw new Error(`Invalid WebExtension context envType: ${envType}`); - } - this.proxyContexts.set(childId, context); - }, - - closeProxyContext(childId) { - let context = this.proxyContexts.get(childId); - if (!context) { - return; - } - context.unload(); - this.proxyContexts.delete(childId); - }, - - call(data, target) { - let context = this.getContextById(data.childId); - if (context.currentMessageManager !== target.messageManager) { - Cu.reportError("WebExtension warning: Message manager unexpectedly changed"); - } - - try { - let args = Cu.cloneInto(data.args, context.sandbox); - let result = findPathInObject(context.apiObj, data.path)(...args); - - if (data.callId) { - result = result || Promise.resolve(); - - result.then(result => { - result = result instanceof SpreadArgs ? [...result] : [result]; - - context.currentMessageManager.sendAsyncMessage("API:CallResult", { - childId: data.childId, - callId: data.callId, - result, - }); - }, error => { - error = context.normalizeError(error); - context.currentMessageManager.sendAsyncMessage("API:CallResult", { - childId: data.childId, - callId: data.callId, - error: {message: error.message}, - }); - }); - } - } catch (e) { - if (data.callId) { - let error = context.normalizeError(e); - context.currentMessageManager.sendAsyncMessage("API:CallResult", { - childId: data.childId, - callId: data.callId, - error: {message: error.message}, - }); - } else { - Cu.reportError(e); - } - } - }, - - addListener(data, target) { - let context = this.getContextById(data.childId); - if (context.currentMessageManager !== target.messageManager) { - Cu.reportError("WebExtension warning: Message manager unexpectedly changed"); - } - - function listener(...listenerArgs) { - context.currentMessageManager.sendAsyncMessage("API:RunListener", { - childId: data.childId, - path: data.path, - args: listenerArgs, - }); - } - - context.listenerProxies.set(data.path, listener); - - let args = Cu.cloneInto(data.args, context.sandbox); - findPathInObject(context.apiObj, data.path).addListener(listener, ...args); - }, - - removeListener(data) { - let context = this.getContextById(data.childId); - let listener = context.listenerProxies.get(data.path); - findPathInObject(context.apiObj, data.path).removeListener(listener); - }, - - getContextById(childId) { - let context = this.proxyContexts.get(childId); - if (!context) { - let error = new Error("WebExtension context not found!"); - Cu.reportError(error); - throw error; - } - return context; - }, -}; - -ParentAPIManager.init(); - // All moz-extension URIs use a machine-specific UUID rather than the // extension's own ID in the host component. This makes it more // difficult for web pages to detect whether a user has a given add-on @@ -685,52 +205,7 @@ }, }; -// Responsible for loading extension APIs into the right globals. -GlobalManager = { - // Map[extension ID -> Extension]. Determines which extension is - // responsible for content under a particular extension ID. - extensionMap: new Map(), - initialized: false, - - init(extension) { - if (this.extensionMap.size == 0) { - UninstallObserver.init(); - ProxyMessenger.init(); - Management.on("extension-browser-inserted", this._onExtensionBrowser); - this.initialized = true; - } - - this.extensionMap.set(extension.id, extension); - }, - - uninit(extension) { - this.extensionMap.delete(extension.id); - - if (this.extensionMap.size == 0 && this.initialized) { - Management.off("extension-browser-inserted", this._onExtensionBrowser); - this.initialized = false; - } - }, - - _onExtensionBrowser(type, browser) { - browser.messageManager.loadFrameScript(`data:, - Components.utils.import("resource://gre/modules/ExtensionContent.jsm"); - ExtensionContent.init(this); - addEventListener("unload", function() { - ExtensionContent.uninit(this); - }); - `, false); - }, - - getExtension(extensionId) { - return this.extensionMap.get(extensionId); - }, - - injectInObject(context, isChromeCompat, dest) { - Management.generateAPIs(context, dest); - SchemaAPIManager.generateAPIs(context, context.extension.apis, dest); - }, -}; +UninstallObserver.init(); // Represents the data contained in an extension, contained either // in a directory or a zip file, which may or may not be installed. @@ -1087,95 +562,6 @@ } }; - -/** - * A skeleton Extension-like object, used for testing, which installs an - * add-on via the add-on manager when startup() is called, and - * uninstalles it on shutdown(). - * - * @param {string} id - * @param {nsIFile} file - * @param {nsIURI} rootURI - * @param {string} installType - */ -class MockExtension { - constructor(file, rootURI, installType) { - this.id = null; - this.file = file; - this.rootURI = rootURI; - this.installType = installType; - this.addon = null; - - let promiseEvent = eventName => new Promise(resolve => { - let onstartup = (msg, extension) => { - if (this.addon && extension.id == this.addon.id) { - Management.off(eventName, onstartup); - - this.id = extension.id; - this._extension = extension; - resolve(extension); - } - }; - Management.on(eventName, onstartup); - }); - - this._extension = null; - this._extensionPromise = promiseEvent("startup"); - this._readyPromise = promiseEvent("ready"); - } - - testMessage(...args) { - return this._extension.testMessage(...args); - } - - on(...args) { - this._extensionPromise.then(extension => { - extension.on(...args); - }); - } - - off(...args) { - this._extensionPromise.then(extension => { - extension.off(...args); - }); - } - - startup() { - if (this.installType == "temporary") { - return AddonManager.installTemporaryAddon(this.file).then(addon => { - this.addon = addon; - return this._readyPromise; - }); - } else if (this.installType == "permanent") { - return new Promise((resolve, reject) => { - AddonManager.getInstallForFile(this.file, install => { - let listener = { - onInstallFailed: reject, - onInstallEnded: (install, newAddon) => { - this.addon = newAddon; - resolve(this._readyPromise); - }, - }; - - install.addListener(listener); - install.install(); - }); - }); - } - throw new Error("installType must be one of: temporary, permanent"); - } - - shutdown() { - this.addon.uninstall(); - return this.cleanupGeneratedFile(); - } - - cleanupGeneratedFile() { - flushJarCache(this.file); - return OS.File.remove(this.file.path); - } -} - let _browserUpdated = false; // We create one instance of this class per extension. |addonData| @@ -1221,207 +607,16 @@ return _browserUpdated; } - /** - * This code is designed to make it easy to test a WebExtension - * without creating a bunch of files. Everything is contained in a - * single JSON blob. - * - * Properties: - * "background": "" - * A script to be loaded as the background script. - * The "background" section of the "manifest" property is overwritten - * if this is provided. - * "manifest": {...} - * Contents of manifest.json - * "files": {"filename1": "contents1", ...} - * Data to be included as files. Can be referenced from the manifest. - * If a manifest file is provided here, it takes precedence over - * a generated one. Always use "/" as a directory separator. - * Directories should appear here only implicitly (as a prefix - * to file names) - * - * To make things easier, the value of "background" and "files"[] can - * be a function, which is converted to source that is run. - * - * The generated extension is stored in the system temporary directory, - * and an nsIFile object pointing to it is returned. - * - * @param {object} data - * @returns {nsIFile} - */ static generateXPI(data) { - let manifest = data.manifest; - if (!manifest) { - manifest = {}; - } - - let files = data.files; - if (!files) { - files = {}; - } - - function provide(obj, keys, value, override = false) { - if (keys.length == 1) { - if (!(keys[0] in obj) || override) { - obj[keys[0]] = value; - } - } else { - if (!(keys[0] in obj)) { - obj[keys[0]] = {}; - } - provide(obj[keys[0]], keys.slice(1), value, override); - } - } - - provide(manifest, ["name"], "Generated extension"); - provide(manifest, ["manifest_version"], 2); - provide(manifest, ["version"], "1.0"); - - if (data.background) { - let bgScript = uuidGen.generateUUID().number + ".js"; - - provide(manifest, ["background", "scripts"], [bgScript], true); - files[bgScript] = data.background; - } - - provide(files, ["manifest.json"], manifest); - - if (data.embedded) { - // Package this as a webextension embedded inside a legacy - // extension. - - let xpiFiles = { - "install.rdf": ` - - - - - - - - - - `, - - "bootstrap.js": ` - function install() {} - function uninstall() {} - function shutdown() {} - - function startup(data) { - data.webExtension.startup(); - } - `, - }; - - for (let [path, data] of Object.entries(files)) { - xpiFiles[`webextension/${path}`] = data; - } - - files = xpiFiles; - } - - return this.generateZipFile(files); + return ExtensionTestCommon.generateXPI(data); } static generateZipFile(files, baseName = "generated-extension.xpi") { - let ZipWriter = Components.Constructor("@mozilla.org/zipwriter;1", "nsIZipWriter"); - let zipW = new ZipWriter(); - - let file = FileUtils.getFile("TmpD", [baseName]); - file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); - - const MODE_WRONLY = 0x02; - const MODE_TRUNCATE = 0x20; - zipW.open(file, MODE_WRONLY | MODE_TRUNCATE); - - // Needs to be in microseconds for some reason. - let time = Date.now() * 1000; - - function generateFile(filename) { - let components = filename.split("/"); - let path = ""; - for (let component of components.slice(0, -1)) { - path += component + "/"; - if (!zipW.hasEntry(path)) { - zipW.addEntryDirectory(path, time, false); - } - } - } - - for (let filename in files) { - let script = files[filename]; - if (typeof(script) == "function") { - script = "(" + script.toString() + ")()"; - } else if (instanceOf(script, "Object") || instanceOf(script, "Array")) { - script = JSON.stringify(script); - } - - if (!instanceOf(script, "ArrayBuffer")) { - script = new TextEncoder("utf-8").encode(script).buffer; - } - - let stream = Cc["@mozilla.org/io/arraybuffer-input-stream;1"].createInstance(Ci.nsIArrayBufferInputStream); - stream.setData(script, 0, script.byteLength); - - generateFile(filename); - zipW.addEntryStream(filename, time, 0, stream, false); - } - - zipW.close(); - - return file; + return ExtensionTestCommon.generateZipFile(files, baseName); } - /** - * Generates a new extension using |Extension.generateXPI|, and initializes a - * new |Extension| instance which will execute it. - * - * @param {object} data - * @returns {Extension} - */ static generate(data) { - let file = this.generateXPI(data); - - flushJarCache(file); - Services.ppmm.broadcastAsyncMessage("Extension:FlushJarCache", {path: file.path}); - - let fileURI = Services.io.newFileURI(file); - let jarURI = Services.io.newURI("jar:" + fileURI.spec + "!/", null, null); - - // This may be "temporary" or "permanent". - if (data.useAddonManager) { - return new MockExtension(file, jarURI, data.useAddonManager); - } - - let id; - if (data.manifest) { - if (data.manifest.applications && data.manifest.applications.gecko) { - id = data.manifest.applications.gecko.id; - } else if (data.manifest.browser_specific_settings && data.manifest.browser_specific_settings.gecko) { - id = data.manifest.browser_specific_settings.gecko.id; - } - } - if (!id) { - id = uuidGen.generateUUID().number; - } - - return new Extension({ - id, - resourceURI: jarURI, - cleanupFile: file, - }); + return ExtensionTestCommon.generate(data); } on(hook, f) { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/ExtensionParent.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/ExtensionParent.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/ExtensionParent.jsm 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/ExtensionParent.jsm 2016-11-14 01:55:46.000000000 +0000 @@ -0,0 +1,548 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +/** + * This module contains code for managing APIs that need to run in the + * parent process, and handles the parent side of operations that need + * to be proxied from ExtensionChild.jsm. + */ + +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; + +/* exported ExtensionParent */ + +this.EXPORTED_SYMBOLS = ["ExtensionParent"]; + +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +XPCOMUtils.defineLazyModuleGetter(this, "AddonManager", + "resource://gre/modules/AddonManager.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "AppConstants", + "resource://gre/modules/AppConstants.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "MessageChannel", + "resource://gre/modules/MessageChannel.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "NativeApp", + "resource://gre/modules/NativeMessaging.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", + "resource://gre/modules/NetUtil.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "Schemas", + "resource://gre/modules/Schemas.jsm"); + +Cu.import("resource://gre/modules/ExtensionCommon.jsm"); +Cu.import("resource://gre/modules/ExtensionUtils.jsm"); + +var { + BaseContext, + SchemaAPIManager, +} = ExtensionCommon; + +var { + MessageManagerProxy, + SpreadArgs, + defineLazyGetter, + findPathInObject, +} = ExtensionUtils; + +const BASE_SCHEMA = "chrome://extensions/content/schemas/manifest.json"; +const CATEGORY_EXTENSION_SCHEMAS = "webextension-schemas"; +const CATEGORY_EXTENSION_SCRIPTS = "webextension-scripts"; + +let schemaURLs = new Set(); + +if (!AppConstants.RELEASE_OR_BETA) { + schemaURLs.add("chrome://extensions/content/schemas/experiments.json"); +} + +let GlobalManager; +let ParentAPIManager; +let ProxyMessenger; + +// This object loads the ext-*.js scripts that define the extension API. +let apiManager = new class extends SchemaAPIManager { + constructor() { + super("main"); + this.initialized = null; + } + + // Loads all the ext-*.js scripts currently registered. + lazyInit() { + if (this.initialized) { + return this.initialized; + } + + // Load order matters here. The base manifest defines types which are + // extended by other schemas, so needs to be loaded first. + let promise = Schemas.load(BASE_SCHEMA).then(() => { + let promises = []; + for (let [/* name */, url] of XPCOMUtils.enumerateCategoryEntries(CATEGORY_EXTENSION_SCHEMAS)) { + promises.push(Schemas.load(url)); + } + for (let url of schemaURLs) { + promises.push(Schemas.load(url)); + } + return Promise.all(promises); + }); + + for (let [/* name */, value] of XPCOMUtils.enumerateCategoryEntries(CATEGORY_EXTENSION_SCRIPTS)) { + this.loadScript(value); + } + + this.initialized = promise; + return this.initialized; + } + + registerSchemaAPI(namespace, envType, getAPI) { + if (envType == "addon_parent" || envType == "content_parent") { + super.registerSchemaAPI(namespace, envType, getAPI); + } + } +}(); + +// Subscribes to messages related to the extension messaging API and forwards it +// to the relevant message manager. The "sender" field for the `onMessage` and +// `onConnect` events are updated if needed. +ProxyMessenger = { + _initialized: false, + init() { + if (this._initialized) { + return; + } + this._initialized = true; + + // TODO(robwu): When addons move to a separate process, we should use the + // parent process manager(s) of the addon process(es) instead of the + // in-process one. + let pipmm = Services.ppmm.getChildAt(0); + // Listen on the global frame message manager because content scripts send + // and receive extension messages via their frame. + // Listen on the parent process message manager because `runtime.connect` + // and `runtime.sendMessage` requests must be delivered to all frames in an + // addon process (by the API contract). + // And legacy addons are not associated with a frame, so that is another + // reason for having a parent process manager here. + let messageManagers = [Services.mm, pipmm]; + + MessageChannel.addListener(messageManagers, "Extension:Connect", this); + MessageChannel.addListener(messageManagers, "Extension:Message", this); + MessageChannel.addListener(messageManagers, "Extension:Port:Disconnect", this); + MessageChannel.addListener(messageManagers, "Extension:Port:PostMessage", this); + }, + + receiveMessage({target, messageName, channelId, sender, recipient, data, responseType}) { + if (recipient.toNativeApp) { + let {childId, toNativeApp} = recipient; + if (messageName == "Extension:Message") { + let context = ParentAPIManager.getContextById(childId); + return new NativeApp(context, toNativeApp).sendMessage(data); + } + if (messageName == "Extension:Connect") { + let context = ParentAPIManager.getContextById(childId); + NativeApp.onConnectNative(context, target.messageManager, data.portId, sender, toNativeApp); + return true; + } + // "Extension:Port:Disconnect" and "Extension:Port:PostMessage" for + // native messages are handled by NativeApp. + return; + } + let extension = GlobalManager.extensionMap.get(sender.extensionId); + let receiverMM = this._getMessageManagerForRecipient(recipient); + if (!extension || !receiverMM) { + return Promise.reject({ + result: MessageChannel.RESULT_NO_HANDLER, + message: "No matching message handler for the given recipient.", + }); + } + + if ((messageName == "Extension:Message" || + messageName == "Extension:Connect") && + apiManager.global.tabGetSender) { + // From ext-tabs.js, undefined on Android. + apiManager.global.tabGetSender(extension, target, sender); + } + return MessageChannel.sendMessage(receiverMM, messageName, data, { + sender, + recipient, + responseType, + }); + }, + + /** + * @param {object} recipient An object that was passed to + * `MessageChannel.sendMessage`. + * @returns {object|null} The message manager matching the recipient if found. + */ + _getMessageManagerForRecipient(recipient) { + let {extensionId, tabId} = recipient; + // tabs.sendMessage / tabs.connect + if (tabId) { + // `tabId` being set implies that the tabs API is supported, so we don't + // need to check whether `TabManager` exists. + let tab = apiManager.global.TabManager.getTab(tabId, null, null); + return tab && tab.linkedBrowser.messageManager; + } + + // runtime.sendMessage / runtime.connect + if (extensionId) { + // TODO(robwu): map the extensionId to the addon parent process's message + // manager when they run in a separate process. + return Services.ppmm.getChildAt(0); + } + + return null; + }, +}; + +// Responsible for loading extension APIs into the right globals. +GlobalManager = { + // Map[extension ID -> Extension]. Determines which extension is + // responsible for content under a particular extension ID. + extensionMap: new Map(), + initialized: false, + + init(extension) { + if (this.extensionMap.size == 0) { + ProxyMessenger.init(); + apiManager.on("extension-browser-inserted", this._onExtensionBrowser); + this.initialized = true; + } + + this.extensionMap.set(extension.id, extension); + }, + + uninit(extension) { + this.extensionMap.delete(extension.id); + + if (this.extensionMap.size == 0 && this.initialized) { + apiManager.off("extension-browser-inserted", this._onExtensionBrowser); + this.initialized = false; + } + }, + + _onExtensionBrowser(type, browser) { + browser.messageManager.loadFrameScript(`data:, + Components.utils.import("resource://gre/modules/ExtensionContent.jsm"); + ExtensionContent.init(this); + addEventListener("unload", function() { + ExtensionContent.uninit(this); + }); + `, false); + }, + + getExtension(extensionId) { + return this.extensionMap.get(extensionId); + }, + + injectInObject(context, isChromeCompat, dest) { + apiManager.generateAPIs(context, dest); + SchemaAPIManager.generateAPIs(context, context.extension.apis, dest); + }, +}; + +/** + * The proxied parent side of a context in ExtensionChild.jsm, for the + * parent side of a proxied API. + */ +class ProxyContextParent extends BaseContext { + constructor(envType, extension, params, xulBrowser, principal) { + super(envType, extension); + + this.uri = NetUtil.newURI(params.url); + + this.incognito = params.incognito; + + // This message manager is used by ParentAPIManager to send messages and to + // close the ProxyContext if the underlying message manager closes. This + // message manager object may change when `xulBrowser` swaps docshells, e.g. + // when a tab is moved to a different window. + this.messageManagerProxy = new MessageManagerProxy(xulBrowser); + + Object.defineProperty(this, "principal", { + value: principal, enumerable: true, configurable: true, + }); + + // TODO: Replace this with a Sandbox with our content principal when + // we move to separate processes. + if (params.cloneScope) { + Object.defineProperty(this, "cloneScope", { + value: params.cloneScope, enumerable: true, configurable: true, + }); + } + + this.listenerProxies = new Map(); + + apiManager.emit("proxy-context-load", this); + } + + get cloneScope() { + return this.sandbox; + } + + get xulBrowser() { + return this.messageManagerProxy.eventTarget; + } + + get parentMessageManager() { + return this.messageManagerProxy.messageManager; + } + + shutdown() { + this.unload(); + } + + unload() { + if (this.unloaded) { + return; + } + this.messageManagerProxy.dispose(); + super.unload(); + apiManager.emit("proxy-context-unload", this); + } +} + +defineLazyGetter(ProxyContextParent.prototype, "apiObj", function() { + let obj = {}; + GlobalManager.injectInObject(this, false, obj); + return obj; +}); + +defineLazyGetter(ProxyContextParent.prototype, "sandbox", function() { + return Cu.Sandbox(this.principal); +}); + +/** + * The parent side of proxied API context for extension content script + * running in ExtensionContent.jsm. + */ +class ContentScriptContextParent extends ProxyContextParent { +} + +/** + * The parent side of proxied API context for extension page, such as a + * background script, a tab page, or a popup, running in + * ExtensionChild.jsm. + */ +class ExtensionPageContextParent extends ProxyContextParent { + constructor(envType, extension, params, xulBrowser) { + super(envType, extension, params, xulBrowser, extension.principal); + + this.viewType = params.viewType; + } + + // The window that contains this context. This may change due to moving tabs. + get xulWindow() { + return this.xulBrowser.ownerGlobal; + } + + get windowId() { + if (!apiManager.global.WindowManager || this.viewType == "background") { + return; + } + // viewType popup or tab: + return apiManager.global.WindowManager.getId(this.xulWindow); + } + + get tabId() { + if (!apiManager.global.TabManager) { + return; // Not yet supported on Android. + } + let {gBrowser} = this.xulBrowser.ownerGlobal; + let tab = gBrowser && gBrowser.getTabForBrowser(this.xulBrowser); + return tab && apiManager.global.TabManager.getId(tab); + } + + onBrowserChange(browser) { + super.onBrowserChange(browser); + this.xulBrowser = browser; + } + + shutdown() { + apiManager.emit("page-shutdown", this); + super.shutdown(); + } +} + +ParentAPIManager = { + proxyContexts: new Map(), + + init() { + Services.obs.addObserver(this, "message-manager-close", false); + + Services.mm.addMessageListener("API:CreateProxyContext", this); + Services.mm.addMessageListener("API:CloseProxyContext", this, true); + Services.mm.addMessageListener("API:Call", this); + Services.mm.addMessageListener("API:AddListener", this); + Services.mm.addMessageListener("API:RemoveListener", this); + }, + + observe(subject, topic, data) { + if (topic === "message-manager-close") { + let mm = subject; + for (let [childId, context] of this.proxyContexts) { + if (context.parentMessageManager === mm) { + this.closeProxyContext(childId); + } + } + } + }, + + shutdownExtension(extensionId) { + for (let [childId, context] of this.proxyContexts) { + if (context.extension.id == extensionId) { + context.shutdown(); + this.proxyContexts.delete(childId); + } + } + }, + + receiveMessage({name, data, target}) { + switch (name) { + case "API:CreateProxyContext": + this.createProxyContext(data, target); + break; + + case "API:CloseProxyContext": + this.closeProxyContext(data.childId); + break; + + case "API:Call": + this.call(data, target); + break; + + case "API:AddListener": + this.addListener(data, target); + break; + + case "API:RemoveListener": + this.removeListener(data); + break; + } + }, + + createProxyContext(data, target) { + let {envType, extensionId, childId, principal} = data; + if (this.proxyContexts.has(childId)) { + throw new Error("A WebExtension context with the given ID already exists!"); + } + + let extension = GlobalManager.getExtension(extensionId); + if (!extension) { + throw new Error(`No WebExtension found with ID ${extensionId}`); + } + + let context; + if (envType == "addon_parent") { + // Privileged addon contexts can only be loaded in documents whose main + // frame is also the same addon. + if (principal.URI.prePath !== extension.baseURI.prePath || + !target.contentPrincipal.subsumes(principal)) { + throw new Error(`Refused to create privileged WebExtension context for ${principal.URI.spec}`); + } + context = new ExtensionPageContextParent(envType, extension, data, target); + } else if (envType == "content_parent") { + context = new ContentScriptContextParent(envType, extension, data, target, principal); + } else { + throw new Error(`Invalid WebExtension context envType: ${envType}`); + } + this.proxyContexts.set(childId, context); + }, + + closeProxyContext(childId) { + let context = this.proxyContexts.get(childId); + if (context) { + context.unload(); + this.proxyContexts.delete(childId); + } + }, + + call(data, target) { + let context = this.getContextById(data.childId); + if (context.parentMessageManager !== target.messageManager) { + Cu.reportError("WebExtension warning: Message manager unexpectedly changed"); + } + + try { + let args = Cu.cloneInto(data.args, context.sandbox); + let result = findPathInObject(context.apiObj, data.path)(...args); + + if (data.callId) { + result = result || Promise.resolve(); + + result.then(result => { + result = result instanceof SpreadArgs ? [...result] : [result]; + + context.parentMessageManager.sendAsyncMessage("API:CallResult", { + childId: data.childId, + callId: data.callId, + result, + }); + }, error => { + error = context.normalizeError(error); + context.parentMessageManager.sendAsyncMessage("API:CallResult", { + childId: data.childId, + callId: data.callId, + error: {message: error.message}, + }); + }); + } + } catch (e) { + if (data.callId) { + let error = context.normalizeError(e); + context.parentMessageManager.sendAsyncMessage("API:CallResult", { + childId: data.childId, + callId: data.callId, + error: {message: error.message}, + }); + } else { + Cu.reportError(e); + } + } + }, + + addListener(data, target) { + let context = this.getContextById(data.childId); + if (context.parentMessageManager !== target.messageManager) { + Cu.reportError("WebExtension warning: Message manager unexpectedly changed"); + } + + function listener(...listenerArgs) { + context.parentMessageManager.sendAsyncMessage("API:RunListener", { + childId: data.childId, + path: data.path, + args: listenerArgs, + }); + } + + context.listenerProxies.set(data.path, listener); + + let args = Cu.cloneInto(data.args, context.sandbox); + findPathInObject(context.apiObj, data.path).addListener(listener, ...args); + }, + + removeListener(data) { + let context = this.getContextById(data.childId); + let listener = context.listenerProxies.get(data.path); + findPathInObject(context.apiObj, data.path).removeListener(listener); + }, + + getContextById(childId) { + let context = this.proxyContexts.get(childId); + if (!context) { + let error = new Error("WebExtension context not found!"); + Cu.reportError(error); + throw error; + } + return context; + }, +}; + +ParentAPIManager.init(); + + +const ExtensionParent = { + GlobalManager, + ParentAPIManager, + apiManager, +}; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/ExtensionTestCommon.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/ExtensionTestCommon.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/ExtensionTestCommon.jsm 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/ExtensionTestCommon.jsm 2016-11-14 01:55:46.000000000 +0000 @@ -0,0 +1,343 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +/** + * This module contains extension testing helper logic which is common + * between all test suites. + */ + +/* exported ExtensionTestCommon, MockExtension */ + +this.EXPORTED_SYMBOLS = ["ExtensionTestCommon", "MockExtension"]; + +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; + +Cu.importGlobalProperties(["TextEncoder"]); + +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +XPCOMUtils.defineLazyModuleGetter(this, "AddonManager", + "resource://gre/modules/AddonManager.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "AppConstants", + "resource://gre/modules/AppConstants.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "Extension", + "resource://gre/modules/Extension.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "ExtensionParent", + "resource://gre/modules/ExtensionParent.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", + "resource://gre/modules/FileUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "OS", + "resource://gre/modules/osfile.jsm"); + +XPCOMUtils.defineLazyGetter(this, "apiManager", + () => ExtensionParent.apiManager); + +Cu.import("resource://gre/modules/ExtensionUtils.jsm"); + +XPCOMUtils.defineLazyServiceGetter(this, "uuidGen", + "@mozilla.org/uuid-generator;1", + "nsIUUIDGenerator"); + +const { + flushJarCache, + instanceOf, +} = ExtensionUtils; + +XPCOMUtils.defineLazyGetter(this, "console", ExtensionUtils.getConsole); + + +/** + * A skeleton Extension-like object, used for testing, which installs an + * add-on via the add-on manager when startup() is called, and + * uninstalles it on shutdown(). + * + * @param {string} id + * @param {nsIFile} file + * @param {nsIURI} rootURI + * @param {string} installType + */ +class MockExtension { + constructor(file, rootURI, installType) { + this.id = null; + this.file = file; + this.rootURI = rootURI; + this.installType = installType; + this.addon = null; + + let promiseEvent = eventName => new Promise(resolve => { + let onstartup = (msg, extension) => { + if (this.addon && extension.id == this.addon.id) { + apiManager.off(eventName, onstartup); + + this.id = extension.id; + this._extension = extension; + resolve(extension); + } + }; + apiManager.on(eventName, onstartup); + }); + + this._extension = null; + this._extensionPromise = promiseEvent("startup"); + this._readyPromise = promiseEvent("ready"); + } + + testMessage(...args) { + return this._extension.testMessage(...args); + } + + on(...args) { + this._extensionPromise.then(extension => { + extension.on(...args); + }); + } + + off(...args) { + this._extensionPromise.then(extension => { + extension.off(...args); + }); + } + + startup() { + if (this.installType == "temporary") { + return AddonManager.installTemporaryAddon(this.file).then(addon => { + this.addon = addon; + return this._readyPromise; + }); + } else if (this.installType == "permanent") { + return new Promise((resolve, reject) => { + AddonManager.getInstallForFile(this.file, install => { + let listener = { + onInstallFailed: reject, + onInstallEnded: (install, newAddon) => { + this.addon = newAddon; + resolve(this._readyPromise); + }, + }; + + install.addListener(listener); + install.install(); + }); + }); + } + throw new Error("installType must be one of: temporary, permanent"); + } + + shutdown() { + this.addon.uninstall(); + return this.cleanupGeneratedFile(); + } + + cleanupGeneratedFile() { + flushJarCache(this.file); + return OS.File.remove(this.file.path); + } +} + +class ExtensionTestCommon { + /** + * This code is designed to make it easy to test a WebExtension + * without creating a bunch of files. Everything is contained in a + * single JSON blob. + * + * Properties: + * "background": "" + * A script to be loaded as the background script. + * The "background" section of the "manifest" property is overwritten + * if this is provided. + * "manifest": {...} + * Contents of manifest.json + * "files": {"filename1": "contents1", ...} + * Data to be included as files. Can be referenced from the manifest. + * If a manifest file is provided here, it takes precedence over + * a generated one. Always use "/" as a directory separator. + * Directories should appear here only implicitly (as a prefix + * to file names) + * + * To make things easier, the value of "background" and "files"[] can + * be a function, which is converted to source that is run. + * + * The generated extension is stored in the system temporary directory, + * and an nsIFile object pointing to it is returned. + * + * @param {object} data + * @returns {nsIFile} + */ + static generateXPI(data) { + let manifest = data.manifest; + if (!manifest) { + manifest = {}; + } + + let files = data.files; + if (!files) { + files = {}; + } + + function provide(obj, keys, value, override = false) { + if (keys.length == 1) { + if (!(keys[0] in obj) || override) { + obj[keys[0]] = value; + } + } else { + if (!(keys[0] in obj)) { + obj[keys[0]] = {}; + } + provide(obj[keys[0]], keys.slice(1), value, override); + } + } + + provide(manifest, ["name"], "Generated extension"); + provide(manifest, ["manifest_version"], 2); + provide(manifest, ["version"], "1.0"); + + if (data.background) { + let bgScript = uuidGen.generateUUID().number + ".js"; + + provide(manifest, ["background", "scripts"], [bgScript], true); + files[bgScript] = data.background; + } + + provide(files, ["manifest.json"], manifest); + + if (data.embedded) { + // Package this as a webextension embedded inside a legacy + // extension. + + let xpiFiles = { + "install.rdf": ` + + + + + + + + + + `, + + "bootstrap.js": ` + function install() {} + function uninstall() {} + function shutdown() {} + + function startup(data) { + data.webExtension.startup(); + } + `, + }; + + for (let [path, data] of Object.entries(files)) { + xpiFiles[`webextension/${path}`] = data; + } + + files = xpiFiles; + } + + return this.generateZipFile(files); + } + + static generateZipFile(files, baseName = "generated-extension.xpi") { + let ZipWriter = Components.Constructor("@mozilla.org/zipwriter;1", "nsIZipWriter"); + let zipW = new ZipWriter(); + + let file = FileUtils.getFile("TmpD", [baseName]); + file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); + + const MODE_WRONLY = 0x02; + const MODE_TRUNCATE = 0x20; + zipW.open(file, MODE_WRONLY | MODE_TRUNCATE); + + // Needs to be in microseconds for some reason. + let time = Date.now() * 1000; + + function generateFile(filename) { + let components = filename.split("/"); + let path = ""; + for (let component of components.slice(0, -1)) { + path += component + "/"; + if (!zipW.hasEntry(path)) { + zipW.addEntryDirectory(path, time, false); + } + } + } + + for (let filename in files) { + let script = files[filename]; + if (typeof(script) == "function") { + script = "(" + script.toString() + ")()"; + } else if (instanceOf(script, "Object") || instanceOf(script, "Array")) { + script = JSON.stringify(script); + } + + if (!instanceOf(script, "ArrayBuffer")) { + script = new TextEncoder("utf-8").encode(script).buffer; + } + + let stream = Cc["@mozilla.org/io/arraybuffer-input-stream;1"].createInstance(Ci.nsIArrayBufferInputStream); + stream.setData(script, 0, script.byteLength); + + generateFile(filename); + zipW.addEntryStream(filename, time, 0, stream, false); + } + + zipW.close(); + + return file; + } + + /** + * Generates a new extension using |Extension.generateXPI|, and initializes a + * new |Extension| instance which will execute it. + * + * @param {object} data + * @returns {Extension} + */ + static generate(data) { + let file = this.generateXPI(data); + + flushJarCache(file); + Services.ppmm.broadcastAsyncMessage("Extension:FlushJarCache", {path: file.path}); + + let fileURI = Services.io.newFileURI(file); + let jarURI = Services.io.newURI("jar:" + fileURI.spec + "!/", null, null); + + // This may be "temporary" or "permanent". + if (data.useAddonManager) { + return new MockExtension(file, jarURI, data.useAddonManager); + } + + let id; + if (data.manifest) { + if (data.manifest.applications && data.manifest.applications.gecko) { + id = data.manifest.applications.gecko.id; + } else if (data.manifest.browser_specific_settings && data.manifest.browser_specific_settings.gecko) { + id = data.manifest.browser_specific_settings.gecko.id; + } + } + if (!id) { + id = uuidGen.generateUUID().number; + } + + return new Extension({ + id, + resourceURI: jarURI, + cleanupFile: file, + }); + } +} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/ExtensionUtils.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/ExtensionUtils.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/ExtensionUtils.jsm 2016-11-11 01:57:16.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/ExtensionUtils.jsm 2016-11-14 01:55:46.000000000 +0000 @@ -32,10 +32,6 @@ "resource://gre/modules/NetUtil.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Preferences", "resource://gre/modules/Preferences.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils", - "resource://gre/modules/PrivateBrowsingUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils", - "resource://gre/modules/PromiseUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Schemas", "resource://gre/modules/Schemas.jsm"); @@ -183,340 +179,6 @@ } } -let gContextId = 0; - -class BaseContext { - constructor(envType, extension) { - this.envType = envType; - this.onClose = new Set(); - this.checkedLastError = false; - this._lastError = null; - this.contextId = `${++gContextId}-${Services.appinfo.uniqueProcessID}`; - this.unloaded = false; - this.extension = extension; - this.jsonSandbox = null; - this.active = true; - this.incognito = null; - this.messageManager = null; - this.docShell = null; - this.contentWindow = null; - this.innerWindowID = 0; - } - - setContentWindow(contentWindow) { - let {document} = contentWindow; - let docShell = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIDocShell); - - this.innerWindowID = getInnerWindowID(contentWindow); - this.messageManager = docShell.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIContentFrameMessageManager); - - if (this.incognito == null) { - this.incognito = PrivateBrowsingUtils.isContentWindowPrivate(contentWindow); - } - - MessageChannel.setupMessageManagers([this.messageManager]); - - let onPageShow = event => { - if (!event || event.target === document) { - this.docShell = docShell; - this.contentWindow = contentWindow; - this.active = true; - } - }; - let onPageHide = event => { - if (!event || event.target === document) { - // Put this off until the next tick. - Promise.resolve().then(() => { - this.docShell = null; - this.contentWindow = null; - this.active = false; - }); - } - }; - - onPageShow(); - contentWindow.addEventListener("pagehide", onPageHide, true); - contentWindow.addEventListener("pageshow", onPageShow, true); - this.callOnClose({ - close: () => { - onPageHide(); - if (this.active) { - contentWindow.removeEventListener("pagehide", onPageHide, true); - contentWindow.removeEventListener("pageshow", onPageShow, true); - } - }, - }); - } - - get cloneScope() { - throw new Error("Not implemented"); - } - - get principal() { - throw new Error("Not implemented"); - } - - runSafe(...args) { - if (this.unloaded) { - Cu.reportError("context.runSafe called after context unloaded"); - } else if (!this.active) { - Cu.reportError("context.runSafe called while context is inactive"); - } else { - return runSafeSync(this, ...args); - } - } - - runSafeWithoutClone(...args) { - if (this.unloaded) { - Cu.reportError("context.runSafeWithoutClone called after context unloaded"); - } else if (!this.active) { - Cu.reportError("context.runSafeWithoutClone called while context is inactive"); - } else { - return runSafeSyncWithoutClone(...args); - } - } - - checkLoadURL(url, options = {}) { - let ssm = Services.scriptSecurityManager; - - let flags = ssm.STANDARD; - if (!options.allowScript) { - flags |= ssm.DISALLOW_SCRIPT; - } - if (!options.allowInheritsPrincipal) { - flags |= ssm.DISALLOW_INHERIT_PRINCIPAL; - } - if (options.dontReportErrors) { - flags |= ssm.DONT_REPORT_ERRORS; - } - - try { - ssm.checkLoadURIStrWithPrincipal(this.principal, url, flags); - } catch (e) { - return false; - } - return true; - } - - /** - * Safely call JSON.stringify() on an object that comes from an - * extension. - * - * @param {array} args Arguments for JSON.stringify() - * @returns {string} The stringified representation of obj - */ - jsonStringify(...args) { - if (!this.jsonSandbox) { - this.jsonSandbox = Cu.Sandbox(this.principal, { - sameZoneAs: this.cloneScope, - wantXrays: false, - }); - } - - return Cu.waiveXrays(this.jsonSandbox.JSON).stringify(...args); - } - - callOnClose(obj) { - this.onClose.add(obj); - } - - forgetOnClose(obj) { - this.onClose.delete(obj); - } - - /** - * A wrapper around MessageChannel.sendMessage which adds the extension ID - * to the recipient object, and ensures replies are not processed after the - * context has been unloaded. - * - * @param {nsIMessageManager} target - * @param {string} messageName - * @param {object} data - * @param {object} [options] - * @param {object} [options.sender] - * @param {object} [options.recipient] - * - * @returns {Promise} - */ - sendMessage(target, messageName, data, options = {}) { - options.recipient = options.recipient || {}; - options.sender = options.sender || {}; - - // TODO(robwu): This should not unconditionally be overwritten once we - // support onMessageExternal / onConnectExternal (bugzil.la/1258360). - options.recipient.extensionId = this.extension.id; - options.sender.extensionId = this.extension.id; - options.sender.contextId = this.contextId; - - return MessageChannel.sendMessage(target, messageName, data, options); - } - - get lastError() { - this.checkedLastError = true; - return this._lastError; - } - - set lastError(val) { - this.checkedLastError = false; - this._lastError = val; - } - - /** - * Normalizes the given error object for use by the target scope. If - * the target is an error object which belongs to that scope, it is - * returned as-is. If it is an ordinary object with a `message` - * property, it is converted into an error belonging to the target - * scope. If it is an Error object which does *not* belong to the - * clone scope, it is reported, and converted to an unexpected - * exception error. - * - * @param {Error|object} error - * @returns {Error} - */ - normalizeError(error) { - if (error instanceof this.cloneScope.Error) { - return error; - } - let message; - if (instanceOf(error, "Object") || error instanceof ExtensionError) { - message = error.message; - } else if (typeof error == "object" && - this.principal.subsumes(Cu.getObjectPrincipal(error))) { - message = error.message; - } else { - Cu.reportError(error); - } - message = message || "An unexpected error occurred"; - return new this.cloneScope.Error(message); - } - - /** - * Sets the value of `.lastError` to `error`, calls the given - * callback, and reports an error if the value has not been checked - * when the callback returns. - * - * @param {object} error An object with a `message` property. May - * optionally be an `Error` object belonging to the target scope. - * @param {function} callback The callback to call. - * @returns {*} The return value of callback. - */ - withLastError(error, callback) { - this.lastError = this.normalizeError(error); - try { - return callback(); - } finally { - if (!this.checkedLastError) { - Cu.reportError(`Unchecked lastError value: ${this.lastError}`); - } - this.lastError = null; - } - } - - /** - * Wraps the given promise so it can be safely returned to extension - * code in this context. - * - * If `callback` is provided, however, it is used as a completion - * function for the promise, and no promise is returned. In this case, - * the callback is called when the promise resolves or rejects. In the - * latter case, `lastError` is set to the rejection value, and the - * callback function must check `browser.runtime.lastError` or - * `extension.runtime.lastError` in order to prevent it being reported - * to the console. - * - * @param {Promise} promise The promise with which to wrap the - * callback. May resolve to a `SpreadArgs` instance, in which case - * each element will be used as a separate argument. - * - * Unless the promise object belongs to the cloneScope global, its - * resolution value is cloned into cloneScope prior to calling the - * `callback` function or resolving the wrapped promise. - * - * @param {function} [callback] The callback function to wrap - * - * @returns {Promise|undefined} If callback is null, a promise object - * belonging to the target scope. Otherwise, undefined. - */ - wrapPromise(promise, callback = null) { - let runSafe = this.runSafe.bind(this); - if (promise instanceof this.cloneScope.Promise) { - runSafe = this.runSafeWithoutClone.bind(this); - } - - if (callback) { - promise.then( - args => { - if (this.unloaded) { - dump(`Promise resolved after context unloaded\n`); - } else if (!this.active) { - dump(`Promise resolved while context is inactive\n`); - } else if (args instanceof SpreadArgs) { - runSafe(callback, ...args); - } else { - runSafe(callback, args); - } - }, - error => { - this.withLastError(error, () => { - if (this.unloaded) { - dump(`Promise rejected after context unloaded\n`); - } else if (!this.active) { - dump(`Promise rejected while context is inactive\n`); - } else { - this.runSafeWithoutClone(callback); - } - }); - }); - } else { - return new this.cloneScope.Promise((resolve, reject) => { - promise.then( - value => { - if (this.unloaded) { - dump(`Promise resolved after context unloaded\n`); - } else if (!this.active) { - dump(`Promise resolved while context is inactive\n`); - } else if (value instanceof SpreadArgs) { - runSafe(resolve, value.length == 1 ? value[0] : value); - } else { - runSafe(resolve, value); - } - }, - value => { - if (this.unloaded) { - dump(`Promise rejected after context unloaded: ${value && value.message}\n`); - } else if (!this.active) { - dump(`Promise rejected while context is inactive: ${value && value.message}\n`); - } else { - this.runSafeWithoutClone(reject, this.normalizeError(value)); - } - }); - }); - } - } - - unload() { - this.unloaded = true; - - MessageChannel.abortResponses({ - extensionId: this.extension.id, - contextId: this.contextId, - }); - - for (let obj of this.onClose) { - obj.close(); - } - } - - /** - * A simple proxy for unload(), for use with callOnClose(). - */ - close() { - this.unload(); - } -} - // Manages icon details for toolbar buttons in the |pageAction| and // |browserAction| APIs. let IconDetails = { @@ -1209,210 +871,6 @@ }); } - -/* - * Messaging primitives. - */ - -let gNextPortId = 1; - -/** - * Abstraction for a Port object in the extension API. - * - * @param {BaseContext} context The context that owns this port. - * @param {nsIMessageSender} senderMM The message manager to send messages to. - * @param {Array} receiverMMs Message managers to - * listen on. - * @param {string} name Arbitrary port name as defined by the addon. - * @param {string} id An ID that uniquely identifies this port's channel. - * @param {object} sender The `port.sender` property. - * @param {object} recipient The recipient of messages sent from this port. - */ -function Port(context, senderMM, receiverMMs, name, id, sender, recipient) { - this.context = context; - this.senderMM = senderMM; - this.receiverMMs = receiverMMs; - this.name = name; - this.id = id; - this.sender = sender; - this.recipient = recipient; - this.disconnected = false; - this.disconnectListeners = new Set(); - this.unregisterMessageFuncs = new Set(); - - // Common options for onMessage and onDisconnect. - this.handlerBase = { - messageFilterStrict: {portId: id}, - filterMessage: (sender, recipient) => { - if (!sender.contextId) { - Cu.reportError("Missing sender.contextId in message to Port"); - return false; - } - return sender.contextId !== this.context.contextId; - }, - }; - - this.disconnectHandler = Object.assign({ - receiveMessage: ({data}) => this.disconnectByOtherEnd(data), - }, this.handlerBase); - MessageChannel.addListener(this.receiverMMs, "Extension:Port:Disconnect", this.disconnectHandler); - this.context.callOnClose(this); -} - -Port.prototype = { - api() { - let portObj = Cu.createObjectIn(this.context.cloneScope); - - let portError = null; - let publicAPI = { - name: this.name, - disconnect: () => { - this.disconnect(); - }, - postMessage: json => { - this.postMessage(json); - }, - onDisconnect: new EventManager(this.context, "Port.onDisconnect", fire => { - return this.registerOnDisconnect(error => { - portError = error && this.context.normalizeError(error); - fire.withoutClone(portObj); - }); - }).api(), - onMessage: new EventManager(this.context, "Port.onMessage", fire => { - return this.registerOnMessage(msg => { - msg = Cu.cloneInto(msg, this.context.cloneScope); - fire.withoutClone(msg, portObj); - }); - }).api(), - - get error() { - return portError; - }, - }; - - if (this.sender) { - publicAPI.sender = this.sender; - } - - injectAPI(publicAPI, portObj); - return portObj; - }, - - postMessage(json) { - if (this.disconnected) { - throw new this.context.cloneScope.Error("Attempt to postMessage on disconnected port"); - } - - this._sendMessage("Extension:Port:PostMessage", json); - }, - - /** - * Register a callback that is called when the port is disconnected by the - * *other* end. The callback is automatically unregistered when the port or - * context is closed. - * - * @param {function} callback Called when the other end disconnects the port. - * If the disconnect is caused by an error, the first parameter is an - * object with a "message" string property that describes the cause. - * @returns {function} Function to unregister the listener. - */ - registerOnDisconnect(callback) { - let listener = error => { - if (this.context.active && !this.disconnected) { - callback(error); - } - }; - this.disconnectListeners.add(listener); - return () => { - this.disconnectListeners.delete(listener); - }; - }, - - /** - * Register a callback that is called when a message is received. The callback - * is automatically unregistered when the port or context is closed. - * - * @param {function} callback Called when a message is received. - * @returns {function} Function to unregister the listener. - */ - registerOnMessage(callback) { - let handler = Object.assign({ - receiveMessage: ({data}) => { - if (this.context.active && !this.disconnected) { - callback(data); - } - }, - }, this.handlerBase); - - let unregister = () => { - this.unregisterMessageFuncs.delete(unregister); - MessageChannel.removeListener(this.receiverMMs, "Extension:Port:PostMessage", handler); - }; - MessageChannel.addListener(this.receiverMMs, "Extension:Port:PostMessage", handler); - this.unregisterMessageFuncs.add(unregister); - return unregister; - }, - - _sendMessage(message, data) { - let options = { - recipient: Object.assign({}, this.recipient, {portId: this.id}), - responseType: MessageChannel.RESPONSE_NONE, - }; - - return this.context.sendMessage(this.senderMM, message, data, options); - }, - - handleDisconnection() { - MessageChannel.removeListener(this.receiverMMs, "Extension:Port:Disconnect", this.disconnectHandler); - for (let unregister of this.unregisterMessageFuncs) { - unregister(); - } - this.context.forgetOnClose(this); - this.disconnected = true; - }, - - /** - * Disconnect the port from the other end (which may not even exist). - * - * @param {Error|{message: string}} [error] The reason for disconnecting, - * if it is an abnormal disconnect. - */ - disconnectByOtherEnd(error = null) { - if (this.disconnected) { - return; - } - - for (let listener of this.disconnectListeners) { - listener(error); - } - - this.handleDisconnection(); - }, - - /** - * Disconnect the port from this end. - * - * @param {Error|{message: string}} [error] The reason for disconnecting, - * if it is an abnormal disconnect. - */ - disconnect(error = null) { - if (this.disconnected) { - // disconnect() may be called without side effects even after the port is - // closed - https://developer.chrome.com/extensions/runtime#type-Port - return; - } - this.handleDisconnection(); - if (error) { - error = {message: this.context.normalizeError(error).message}; - } - this._sendMessage("Extension:Port:Disconnect", error); - }, - - close() { - this.disconnect(); - }, -}; - function getMessageManager(target) { if (target instanceof Ci.nsIFrameLoaderOwner) { return target.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader.messageManager; @@ -1420,163 +878,6 @@ return target.QueryInterface(Ci.nsIMessageSender); } -/** - * Each extension context gets its own Messenger object. It handles the - * basics of sendMessage, onMessage, connect and onConnect. - * - * @param {BaseContext} context The context to which this Messenger is tied. - * @param {Array} messageManagers - * The message managers used to receive messages (e.g. onMessage/onConnect - * requests). - * @param {object} sender Describes this sender to the recipient. This object - * is extended further by BaseContext's sendMessage method and appears as - * the `sender` object to `onConnect` and `onMessage`. - * Do not set the `extensionId`, `contextId` or `tab` properties. The former - * two are added by BaseContext's sendMessage, while `sender.tab` is set by - * the ProxyMessenger in the main process. - * @param {object} filter A recipient filter to apply to incoming messages from - * the broker. Messages are only handled by this Messenger if all key-value - * pairs match the `recipient` as specified by the sender of the message. - * In other words, this filter defines the required fields of `recipient`. - * @param {object} [optionalFilter] An additional filter to apply to incoming - * messages. Unlike `filter`, the keys from `optionalFilter` are allowed to - * be omitted from `recipient`. Only keys that are present in both - * `optionalFilter` and `recipient` are applied to filter incoming messages. - */ -function Messenger(context, messageManagers, sender, filter, optionalFilter) { - this.context = context; - this.messageManagers = messageManagers; - this.sender = sender; - this.filter = filter; - this.optionalFilter = optionalFilter; -} - -Messenger.prototype = { - _sendMessage(messageManager, message, data, recipient) { - let options = { - recipient, - sender: this.sender, - responseType: MessageChannel.RESPONSE_FIRST, - }; - - return this.context.sendMessage(messageManager, message, data, options); - }, - - sendMessage(messageManager, msg, recipient, responseCallback) { - let promise = this._sendMessage(messageManager, "Extension:Message", msg, recipient) - .catch(error => { - if (error.result == MessageChannel.RESULT_NO_HANDLER) { - return Promise.reject({message: "Could not establish connection. Receiving end does not exist."}); - } else if (error.result != MessageChannel.RESULT_NO_RESPONSE) { - return Promise.reject({message: error.message}); - } - }); - - return this.context.wrapPromise(promise, responseCallback); - }, - - onMessage(name) { - return new SingletonEventManager(this.context, name, callback => { - let listener = { - messageFilterPermissive: this.optionalFilter, - messageFilterStrict: this.filter, - - filterMessage: (sender, recipient) => { - // Ignore the message if it was sent by this Messenger. - return sender.contextId !== this.context.contextId; - }, - - receiveMessage: ({target, data: message, sender, recipient}) => { - if (!this.context.active) { - return; - } - - let sendResponse; - let response = undefined; - let promise = new Promise(resolve => { - sendResponse = value => { - resolve(value); - response = promise; - }; - }); - - message = Cu.cloneInto(message, this.context.cloneScope); - sender = Cu.cloneInto(sender, this.context.cloneScope); - sendResponse = Cu.exportFunction(sendResponse, this.context.cloneScope); - - // Note: We intentionally do not use runSafe here so that any - // errors are propagated to the message sender. - let result = callback(message, sender, sendResponse); - if (result instanceof this.context.cloneScope.Promise) { - return result; - } else if (result === true) { - return promise; - } - return response; - }, - }; - - MessageChannel.addListener(this.messageManagers, "Extension:Message", listener); - return () => { - MessageChannel.removeListener(this.messageManagers, "Extension:Message", listener); - }; - }).api(); - }, - - connectGetRawPort(messageManager, name, recipient) { - let portId = `${gNextPortId++}-${Services.appinfo.uniqueProcessID}`; - let port = new Port(this.context, messageManager, this.messageManagers, name, portId, null, recipient); - let msg = {name, portId}; - this._sendMessage(messageManager, "Extension:Connect", msg, recipient) - .catch(e => { - if (e.result === MessageChannel.RESULT_NO_HANDLER) { - e = {message: "Could not establish connection. Receiving end does not exist."}; - } else if (e.result === MessageChannel.RESULT_DISCONNECTED) { - e = null; - } - port.disconnectByOtherEnd(e); - }); - return port; - }, - - connect(messageManager, name, recipient) { - let port = this.connectGetRawPort(messageManager, name, recipient); - return port.api(); - }, - - onConnect(name) { - return new SingletonEventManager(this.context, name, callback => { - let listener = { - messageFilterPermissive: this.optionalFilter, - messageFilterStrict: this.filter, - - filterMessage: (sender, recipient) => { - // Ignore the port if it was created by this Messenger. - return sender.contextId !== this.context.contextId; - }, - - receiveMessage: ({target, data: message, sender}) => { - let {name, portId} = message; - let mm = getMessageManager(target); - let recipient = Object.assign({}, sender); - if (recipient.tab) { - recipient.tabId = recipient.tab.id; - delete recipient.tab; - } - let port = new Port(this.context, mm, this.messageManagers, name, portId, sender, recipient); - this.context.runSafeWithoutClone(callback, port.api()); - return true; - }, - }; - - MessageChannel.addListener(this.messageManagers, "Extension:Connect", listener); - return () => { - MessageChannel.removeListener(this.messageManagers, "Extension:Connect", listener); - }; - }).api(); - }, -}; - function flushJarCache(jarFile) { Services.obs.notifyObservers(jarFile, "flush-cache-entry", null); } @@ -1614,622 +915,267 @@ } /** - * An object that runs the implementation of a schema API. Instantiations of - * this interfaces are used by Schemas.jsm. + * Convert any of several different representations of a date/time to a Date object. + * Accepts several formats: + * a Date object, an ISO8601 string, or a number of milliseconds since the epoch as + * either a number or a string. * - * @interface + * @param {Date|string|number} date + * The date to convert. + * @returns {Date} + * A Date object */ -class SchemaAPIInterface { - /** - * Calls this as a function that returns its return value. - * - * @abstract - * @param {Array} args The parameters for the function. - * @returns {*} The return value of the invoked function. - */ - callFunction(args) { - throw new Error("Not implemented"); - } - - /** - * Calls this as a function and ignores its return value. - * - * @abstract - * @param {Array} args The parameters for the function. - */ - callFunctionNoReturn(args) { - throw new Error("Not implemented"); - } - - /** - * Calls this as a function that completes asynchronously. - * - * @abstract - * @param {Array} args The parameters for the function. - * @param {function(*)} [callback] The callback to be called when the function - * completes. - * @returns {Promise|undefined} Must be void if `callback` is set, and a - * promise otherwise. The promise is resolved when the function completes. - */ - callAsyncFunction(args, callback) { - throw new Error("Not implemented"); - } - - /** - * Retrieves the value of this as a property. - * - * @abstract - * @returns {*} The value of the property. - */ - getProperty() { - throw new Error("Not implemented"); - } - - /** - * Assigns the value to this as property. - * - * @abstract - * @param {string} value The new value of the property. - */ - setProperty(value) { - throw new Error("Not implemented"); - } - - /** - * Registers a `listener` to this as an event. - * - * @abstract - * @param {function} listener The callback to be called when the event fires. - * @param {Array} args Extra parameters for EventManager.addListener. - * @see EventManager.addListener - */ - addListener(listener, args) { - throw new Error("Not implemented"); - } - - /** - * Checks whether `listener` is listening to this as an event. - * - * @abstract - * @param {function} listener The event listener. - * @returns {boolean} Whether `listener` is registered with this as an event. - * @see EventManager.hasListener - */ - hasListener(listener) { - throw new Error("Not implemented"); - } - - /** - * Unregisters `listener` from this as an event. - * - * @abstract - * @param {function} listener The event listener. - * @see EventManager.removeListener - */ - removeListener(listener) { - throw new Error("Not implemented"); - } +function normalizeTime(date) { + // Of all the formats we accept the "number of milliseconds since the epoch as a string" + // is an outlier, everything else can just be passed directly to the Date constructor. + return new Date((typeof date == "string" && /^\d+$/.test(date)) + ? parseInt(date, 10) : date); } +const stylesheetMap = new DefaultMap(url => { + let uri = NetUtil.newURI(url); + return styleSheetService.preloadSheet(uri, styleSheetService.AGENT_SHEET); +}); + /** - * An object that runs a locally implemented API. + * Defines a lazy getter for the given property on the given object. The + * first time the property is accessed, the return value of the getter + * is defined on the current `this` object with the given property name. + * Importantly, this means that a lazy getter defined on an object + * prototype will be invoked separately for each object instance that + * it's accessed on. + * + * @param {object} object + * The prototype object on which to define the getter. + * @param {string|Symbol} prop + * The property name for which to define the getter. + * @param {function} getter + * The function to call in order to generate the final property + * value. */ -class LocalAPIImplementation extends SchemaAPIInterface { - /** - * Constructs an implementation of the `name` method or property of `pathObj`. - * - * @param {object} pathObj The object containing the member with name `name`. - * @param {string} name The name of the implemented member. - * @param {BaseContext} context The context in which the schema is injected. - */ - constructor(pathObj, name, context) { - super(); - this.pathObj = pathObj; - this.name = name; - this.context = context; - } - - callFunction(args) { - return this.pathObj[this.name](...args); - } - - callFunctionNoReturn(args) { - this.pathObj[this.name](...args); - } +function defineLazyGetter(object, prop, getter) { + let redefine = (obj, value) => { + Object.defineProperty(obj, prop, { + enumerable: true, + configurable: true, + writable: true, + value, + }); + return value; + }; - callAsyncFunction(args, callback) { - let promise; - try { - promise = this.pathObj[this.name](...args) || Promise.resolve(); - } catch (e) { - promise = Promise.reject(e); - } - return this.context.wrapPromise(promise, callback); - } + Object.defineProperty(object, prop, { + enumerable: true, + configurable: true, - getProperty() { - return this.pathObj[this.name]; - } + get() { + return redefine(this, getter.call(this)); + }, - setProperty(value) { - this.pathObj[this.name] = value; - } + set(value) { + redefine(this, value); + }, + }); +} - addListener(listener, args) { - try { - this.pathObj[this.name].addListener.call(null, listener, ...args); - } catch (e) { - throw this.context.normalizeError(e); +function findPathInObject(obj, path, printErrors = true) { + let parent; + for (let elt of path.split(".")) { + if (!obj || !(elt in obj)) { + if (printErrors) { + Cu.reportError(`WebExtension API ${path} not found (it may be unimplemented by Firefox).`); + } + return null; } - } - hasListener(listener) { - return this.pathObj[this.name].hasListener.call(null, listener); + parent = obj; + obj = obj[elt]; } - removeListener(listener) { - this.pathObj[this.name].removeListener.call(null, listener); + if (typeof obj === "function") { + return obj.bind(parent); } + return obj; } -let nextId = 1; - /** - * An object that runs an remote implementation of an API. + * Acts as a proxy for a message manager or message manager owner, and + * tracks docShell swaps so that messages are always sent to the same + * receiver, even if it is moved to a different . + * + * @param {nsIMessageSender|Element} target + * The target message manager on which to send messages, or the + * element which owns it. */ -class ProxyAPIImplementation extends SchemaAPIInterface { - /** - * @param {string} namespace The full path to the namespace that contains the - * `name` member. This may contain dots, e.g. "storage.local". - * @param {string} name The name of the method or property. - * @param {ChildAPIManager} childApiManager The owner of this implementation. - */ - constructor(namespace, name, childApiManager) { - super(); - this.path = `${namespace}.${name}`; - this.childApiManager = childApiManager; - } - - callFunctionNoReturn(args) { - this.childApiManager.callParentFunctionNoReturn(this.path, args); - } - - callAsyncFunction(args, callback) { - return this.childApiManager.callParentAsyncFunction(this.path, args, callback); - } - - addListener(listener, args) { - let set = this.childApiManager.listeners.get(this.path); - if (!set) { - set = new Set(); - this.childApiManager.listeners.set(this.path, set); - } - - set.add(listener); - - if (set.size == 1) { - args = args.slice(1); - - this.childApiManager.messageManager.sendAsyncMessage("API:AddListener", { - childId: this.childApiManager.id, - path: this.path, - args, +class MessageManagerProxy { + constructor(target) { + this.listeners = new DefaultMap(() => new Map()); + + if (target instanceof Ci.nsIMessageSender) { + Object.defineProperty(this, "messageManager", { + value: target, + configurable: true, + writable: true, }); - } - } - - removeListener(listener) { - let set = this.childApiManager.listeners.get(this.path); - if (!set) { - return; - } - set.delete(listener); - - if (set.size == 0) { - this.childApiManager.messageManager.sendAsyncMessage("API:RemoveListener", { - childId: this.childApiManager.id, - path: this.path, - }); - } - } - - hasListener(listener) { - let set = this.childApiManager.listeners.get(this.path); - return set ? set.has(listener) : false; - } -} - -// We create one instance of this class for every extension context -// that needs to use remote APIs. It uses the message manager to -// communicate with the ParentAPIManager singleton in -// Extension.jsm. It handles asynchronous function calls as well as -// event listeners. -class ChildAPIManager { - constructor(context, messageManager, localApis, contextData) { - this.context = context; - this.messageManager = messageManager; - - // The root namespace of all locally implemented APIs. If an extension calls - // an API that does not exist in this object, then the implementation is - // delegated to the ParentAPIManager. - this.localApis = localApis; - - let id = String(context.extension.id) + "." + String(context.contextId); - this.id = id; - - let data = {childId: id, extensionId: context.extension.id, principal: context.principal}; - Object.assign(data, contextData); - - messageManager.addMessageListener("API:RunListener", this); - messageManager.addMessageListener("API:CallResult", this); - - // Map[path -> Set[listener]] - // path is, e.g., "runtime.onMessage". - this.listeners = new Map(); - - // Map[callId -> Deferred] - this.callPromises = new Map(); - - this.createProxyContextInConstructor(data); - } - - createProxyContextInConstructor(data) { - this.messageManager.sendAsyncMessage("API:CreateProxyContext", data); - } - - receiveMessage({name, data}) { - if (data.childId != this.id) { - return; - } - - switch (name) { - case "API:RunListener": - let listeners = this.listeners.get(data.path); - for (let callback of listeners) { - runSafe(this.context, callback, ...data.args); - } - break; - - case "API:CallResult": - let deferred = this.callPromises.get(data.callId); - if ("error" in data) { - deferred.reject(data.error); - } else { - deferred.resolve(new SpreadArgs(data.result)); - } - this.callPromises.delete(data.callId); - break; + } else { + this.addListeners(target); } } /** - * Call a function in the parent process and ignores its return value. + * Disposes of the proxy object, removes event listeners, and drops + * all references to the underlying message manager. * - * @param {string} path The full name of the method, e.g. "tabs.create". - * @param {Array} args The parameters for the function. + * Must be called before the last reference to the proxy is dropped, + * unless the underlying message manager or is also being + * destroyed. */ - callParentFunctionNoReturn(path, args) { - this.messageManager.sendAsyncMessage("API:Call", { - childId: this.id, - path, - args, - }); + dispose() { + if (this.eventTarget) { + this.removeListeners(this.eventTarget); + this.eventTarget = null; + } else { + this.messageManager = null; + } } /** - * Calls a function in the parent process and returns its result - * asynchronously. + * Returns true if the given target is the same as, or owns, the given + * message manager. + * + * @param {nsIMessageSender|MessageManagerProxy|Element} target + * The message manager, MessageManagerProxy, or + * element agaisnt which to match. + * @param {nsIMessageSender} messageManager + * The message manager against which to match `target`. * - * @param {string} path The full name of the method, e.g. "tabs.create". - * @param {Array} args The parameters for the function. - * @param {function(*)} [callback] The callback to be called when the function - * completes. - * @returns {Promise|undefined} Must be void if `callback` is set, and a - * promise otherwise. The promise is resolved when the function completes. + * @returns {boolean} + * True if `messageManager` is the same object as `target`, or + * `target` is a MessageManagerProxy or element that + * is tied to it. */ - callParentAsyncFunction(path, args, callback) { - let callId = nextId++; - let deferred = PromiseUtils.defer(); - this.callPromises.set(callId, deferred); - - this.messageManager.sendAsyncMessage("API:Call", { - childId: this.id, - callId, - path, - args, - }); - - return this.context.wrapPromise(deferred.promise, callback); + static matches(target, messageManager) { + return target === messageManager || target.messageManager === messageManager; } /** - * Create a proxy for an event in the parent process. The returned event - * object shares its internal state with other instances. For instance, if - * `removeListener` is used on a listener that was added on another object - * through `addListener`, then the event is unregistered. - * - * @param {string} path The full name of the event, e.g. "tabs.onCreated". - * @returns {object} An object with the addListener, removeListener and - * hasListener methods. See SchemaAPIInterface for documentation. + * @property {nsIMessageSender|null} messageManager + * The message manager that is currently being proxied. This + * may change during the life of the proxy object, so should + * not be stored elsewhere. */ - getParentEvent(path) { - let parsed = /^(.+)\.(on[A-Z][^.]+)$/.exec(path); - if (!parsed) { - throw new Error("getParentEvent: Invalid event name: " + path); - } - let [, namespace, name] = parsed; - let impl = new ProxyAPIImplementation(namespace, name, this); - return { - addListener: (listener, ...args) => impl.addListener(listener, args), - removeListener: (listener) => impl.removeListener(listener), - hasListener: (listener) => impl.hasListener(listener), - }; + get messageManager() { + return this.eventTarget && this.eventTarget.messageManager; } - close() { - this.messageManager.sendAsyncMessage("API:CloseProxyContext", {childId: this.id}); - } - - get cloneScope() { - return this.context.cloneScope; - } - - get principal() { - return this.context.principal; - } - - shouldInject(namespace, name, allowedContexts) { - // Do not generate content script APIs, unless explicitly allowed. - if (this.context.envType === "content_child" && - !allowedContexts.includes("content")) { - return false; - } - if (allowedContexts.includes("addon_parent_only")) { - return false; - } - return true; - } - - getImplementation(namespace, name) { - let pathObj = this.localApis; - if (pathObj) { - for (let part of namespace.split(".")) { - pathObj = pathObj[part]; - if (!pathObj) { - break; - } - } - if (pathObj && name in pathObj) { - return new LocalAPIImplementation(pathObj, name, this.context); - } - } - - return this.getFallbackImplementation(namespace, name); - } - - getFallbackImplementation(namespace, name) { - // No local API found, defer implementation to the parent. - return new ProxyAPIImplementation(namespace, name, this); - } - - hasPermission(permission) { - return this.context.extension.hasPermission(permission); - } -} - -/** - * This object loads the ext-*.js scripts that define the extension API. - * - * This class instance is shared with the scripts that it loads, so that the - * ext-*.js scripts and the instantiator can communicate with each other. - */ -class SchemaAPIManager extends EventEmitter { /** - * @param {string} processType - * "main" - The main, one and only chrome browser process. - * "addon" - An addon process. - * "content" - A content process. + * Sends a message on the proxied message manager. + * + * @param {array} args + * Arguments to be passed verbatim to the underlying + * sendAsyncMessage method. + * @returns {undefined} */ - constructor(processType) { - super(); - this.processType = processType; - this.global = this._createExtGlobal(); - this._scriptScopes = []; - this._schemaApis = { - addon_parent: [], - addon_child: [], - content_parent: [], - content_child: [], - }; + sendAsyncMessage(...args) { + return this.messageManager.sendAsyncMessage(...args); } /** - * Create a global object that is used as the shared global for all ext-*.js - * scripts that are loaded via `loadScript`. + * Adds a message listener to the current message manager, and + * transfers it to the new message manager after a docShell swap. * - * @returns {object} A sandbox that is used as the global by `loadScript`. + * @param {string} message + * The name of the message to listen for. + * @param {nsIMessageListener} listener + * The listener to add. + * @param {boolean} [listenWhenClosed = false] + * If true, the listener will receive messages which were sent + * after the remote side of the listener began closing. */ - _createExtGlobal() { - let global = Cu.Sandbox(Services.scriptSecurityManager.getSystemPrincipal(), { - wantXrays: false, - sandboxName: `Namespace of ext-*.js scripts for ${this.processType}`, - }); - - Object.assign(global, {global, Cc, Ci, Cu, Cr, XPCOMUtils, extensions: this}); - - XPCOMUtils.defineLazyGetter(global, "console", getConsole); - - XPCOMUtils.defineLazyModuleGetter(global, "require", - "resource://devtools/shared/Loader.jsm"); - - return global; + addMessageListener(message, listener, listenWhenClosed = false) { + this.messageManager.addMessageListener(message, listener, listenWhenClosed); + this.listeners.get(message).set(listener, listenWhenClosed); } /** - * Load an ext-*.js script. The script runs in its own scope, if it wishes to - * share state with another script it can assign to the `global` variable. If - * it wishes to communicate with this API manager, use `extensions`. + * Adds a message listener from the current message manager. * - * @param {string} scriptUrl The URL of the ext-*.js script. + * @param {string} message + * The name of the message to stop listening for. + * @param {nsIMessageListener} listener + * The listener to remove. */ - loadScript(scriptUrl) { - // Create the object in the context of the sandbox so that the script runs - // in the sandbox's context instead of here. - let scope = Cu.createObjectIn(this.global); - - Services.scriptloader.loadSubScript(scriptUrl, scope, "UTF-8"); + removeMessageListener(message, listener) { + this.messageManager.removeMessageListener(message, listener); - // Save the scope to avoid it being garbage collected. - this._scriptScopes.push(scope); + let listeners = this.listeners.get(message); + listeners.delete(listener); + if (!listeners.size) { + this.listeners.delete(message); + } } /** - * Called by an ext-*.js script to register an API. - * - * @param {string} namespace The API namespace. - * Intended to match the namespace of the generated API, but not used at - * the moment - see bugzil.la/1295774. - * @param {string} envType Restricts the API to contexts that run in the - * given environment. Must be one of the following: - * - "addon_parent" - addon APIs that runs in the main process. - * - "addon_child" - addon APIs that runs in an addon process. - * - "content_parent" - content script APIs that runs in the main process. - * - "content_child" - content script APIs that runs in a content process. - * @param {function(BaseContext)} getAPI A function that returns an object - * that will be merged with |chrome| and |browser|. The next example adds - * the create, update and remove methods to the tabs API. - * - * registerSchemaAPI("tabs", "addon_parent", (context) => ({ - * tabs: { create, update }, - * })); - * registerSchemaAPI("tabs", "addon_parent", (context) => ({ - * tabs: { remove }, - * })); + * @private + * Iterates over all of the currently registered message listeners. */ - registerSchemaAPI(namespace, envType, getAPI) { - this._schemaApis[envType].push({namespace, getAPI}); + * iterListeners() { + for (let [message, listeners] of this.listeners) { + for (let [listener, listenWhenClosed] of listeners) { + yield {message, listener, listenWhenClosed}; + } + } } /** - * Exports all registered scripts to `obj`. + * @private + * Adds docShell swap listeners to the message manager owner. * - * @param {BaseContext} context The context for which the API bindings are - * generated. - * @param {object} obj The destination of the API. + * @param {Element} target + * The target element. */ - generateAPIs(context, obj) { - let apis = this._schemaApis[context.envType]; - if (!apis) { - Cu.reportError(`No APIs have been registered for ${context.envType}`); - return; + addListeners(target) { + target.addEventListener("SwapDocShells", this); + + for (let {message, listener, listenWhenClosed} of this.iterListeners()) { + target.addMessageListener(message, listener, listenWhenClosed); } - SchemaAPIManager.generateAPIs(context, apis, obj); + + this.eventTarget = target; } /** - * Mash together all the APIs from `apis` into `obj`. + * @private + * Removes docShell swap listeners to the message manager owner. * - * @param {BaseContext} context The context for which the API bindings are - * generated. - * @param {Array} apis A list of objects, see `registerSchemaAPI`. - * @param {object} obj The destination of the API. + * @param {Element} target + * The target element. */ - static generateAPIs(context, apis, obj) { - // Recursively copy properties from source to dest. - function copy(dest, source) { - for (let prop in source) { - let desc = Object.getOwnPropertyDescriptor(source, prop); - if (typeof(desc.value) == "object") { - if (!(prop in dest)) { - dest[prop] = {}; - } - copy(dest[prop], source[prop]); - } else { - Object.defineProperty(dest, prop, desc); - } - } - } + removeListeners(target) { + target.removeEventListener("SwapDocShells", this); - for (let api of apis) { - if (Schemas.checkPermissions(api.namespace, context.extension)) { - api = api.getAPI(context); - copy(obj, api); - } + for (let {message, listener} of this.iterListeners()) { + target.removeMessageListener(message, listener); } } -} - -/** - * Convert any of several different representations of a date/time to a Date object. - * Accepts several formats: - * a Date object, an ISO8601 string, or a number of milliseconds since the epoch as - * either a number or a string. - * - * @param {Date|string|number} date - * The date to convert. - * @returns {Date} - * A Date object - */ -function normalizeTime(date) { - // Of all the formats we accept the "number of milliseconds since the epoch as a string" - // is an outlier, everything else can just be passed directly to the Date constructor. - return new Date((typeof date == "string" && /^\d+$/.test(date)) - ? parseInt(date, 10) : date); -} -const stylesheetMap = new DefaultMap(url => { - let uri = NetUtil.newURI(url); - return styleSheetService.preloadSheet(uri, styleSheetService.AGENT_SHEET); -}); - -/** - * Defines a lazy getter for the given property on the given object. The - * first time the property is accessed, the return value of the getter - * is defined on the current `this` object with the given property name. - * Importantly, this means that a lazy getter defined on an object - * prototype will be invoked separately for each object instance that - * it's accessed on. - * - * @param {object} object - * The prototype object on which to define the getter. - * @param {string|Symbol} prop - * The property name for which to define the getter. - * @param {function} getter - * The function to call in order to generate the final property - * value. - */ -function defineLazyGetter(object, prop, getter) { - let redefine = (obj, value) => { - Object.defineProperty(obj, prop, { - enumerable: true, - configurable: true, - writable: true, - value, - }); - return value; - }; - - Object.defineProperty(object, prop, { - enumerable: true, - configurable: true, - - get() { - return redefine(this, getter.call(this)); - }, - - set(value) { - redefine(this, value); - }, - }); + handleEvent(event) { + if (event.type == "SwapDocShells") { + this.removeListeners(this.eventTarget); + this.addListeners(event.detail); + } + } } this.ExtensionUtils = { defineLazyGetter, detectLanguage, extend, + findPathInObject, flushJarCache, getConsole, getInnerWindowID, + getMessageManager, ignoreEvent, injectAPI, instanceOf, @@ -2243,21 +1189,15 @@ runSafeSyncWithoutClone, runSafeWithoutClone, stylesheetMap, - BaseContext, DefaultMap, DefaultWeakMap, EventEmitter, EventManager, ExtensionError, IconDetails, - LocalAPIImplementation, LocaleData, - Messenger, - Port, + MessageManagerProxy, PlatformInfo, - SchemaAPIInterface, SingletonEventManager, SpreadArgs, - ChildAPIManager, - SchemaAPIManager, }; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/LegacyExtensionsUtils.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/LegacyExtensionsUtils.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/LegacyExtensionsUtils.jsm 2016-11-11 01:57:16.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/LegacyExtensionsUtils.jsm 2016-11-14 01:55:46.000000000 +0000 @@ -22,12 +22,16 @@ XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/ExtensionUtils.jsm"); +Cu.import("resource://gre/modules/ExtensionChild.jsm"); +Cu.import("resource://gre/modules/ExtensionCommon.jsm"); var { BaseContext, +} = ExtensionCommon; + +var { Messenger, -} = ExtensionUtils; +} = ExtensionChild; /** * Instances created from this class provide to a legacy extension diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/MessageChannel.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/MessageChannel.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/MessageChannel.jsm 2016-11-11 01:57:16.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/MessageChannel.jsm 2016-11-14 01:55:46.000000000 +0000 @@ -108,123 +108,15 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "ExtensionUtils", + "resource://gre/modules/ExtensionUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils", "resource://gre/modules/PromiseUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm"); -/** - * Acts as a proxy for a message manager or message manager owner, and - * tracks docShell swaps so that messages are always sent to the same - * receiver, even if it is moved to a different . - * - * Currently only proxies message sending functions, and does not handle - * transfering listeners in any way. - * - * @param {nsIMessageSender|Element} target - * The target message manager on which to send messages, or the - * element which owns it. - */ -class MessageManagerProxy { - constructor(target) { - if (target instanceof Ci.nsIMessageSender) { - Object.defineProperty(this, "messageManager", { - value: target, - configurable: true, - writable: true, - }); - } else { - this.addListeners(target); - } - } - - /** - * Disposes of the proxy object, removes event listeners, and drops - * all references to the underlying message manager. - * - * Must be called before the last reference to the proxy is dropped, - * unless the underlying message manager or is also being - * destroyed. - */ - dispose() { - if (this.eventTarget) { - this.removeListeners(this.eventTarget); - this.eventTarget = null; - } else { - this.messageManager = null; - } - } - - /** - * Returns true if the given target is the same as, or owns, the given - * message manager. - * - * @param {nsIMessageSender|MessageManagerProxy|Element} target - * The message manager, MessageManagerProxy, or - * element agaisnt which to match. - * @param {nsIMessageSender} messageManager - * The message manager against which to match `target`. - * - * @returns {boolean} - * True if `messageManager` is the same object as `target`, or - * `target` is a MessageManagerProxy or element that - * is tied to it. - */ - static matches(target, messageManager) { - return target === messageManager || target.messageManager === messageManager; - } - - /** - * @property {nsIMessageSender|null} messageManager - * The message manager that is currently being proxied. This - * may change during the life of the proxy object, so should - * not be stored elsewhere. - */ - get messageManager() { - return this.eventTarget && this.eventTarget.messageManager; - } - - /** - * Sends a message on the proxied message manager. - * - * @param {array} args - * Arguments to be passed verbatim to the underlying - * sendAsyncMessage method. - * @returns {undefined} - */ - sendAsyncMessage(...args) { - return this.messageManager.sendAsyncMessage(...args); - } - - /** - * @private - * Adds docShell swap listeners to the message manager owner. - * - * @param {Element} target - * The target element. - */ - addListeners(target) { - target.addEventListener("SwapDocShells", this); - this.eventTarget = target; - } - - /** - * @private - * Removes docShell swap listeners to the message manager owner. - * - * @param {Element} target - * The target element. - */ - removeListeners(target) { - target.removeEventListener("SwapDocShells", this); - } - handleEvent(event) { - if (event.type == "SwapDocShells") { - this.removeListeners(this.eventTarget); - this.addListeners(event.detail); - } - } -} +XPCOMUtils.defineLazyGetter(this, "MessageManagerProxy", + () => ExtensionUtils.MessageManagerProxy); /** * Handles the mapping and dispatching of messages to their registered diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/moz.build firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/moz.build --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/moz.build 2016-11-11 01:57:16.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/moz.build 2016-11-14 01:55:46.000000000 +0000 @@ -8,8 +8,10 @@ 'Extension.jsm', 'ExtensionAPI.jsm', 'ExtensionChild.jsm', + 'ExtensionCommon.jsm', 'ExtensionContent.jsm', 'ExtensionManagement.jsm', + 'ExtensionParent.jsm', 'ExtensionStorage.jsm', 'ExtensionUtils.jsm', 'LegacyExtensionsUtils.jsm', @@ -23,6 +25,7 @@ ] TESTING_JS_MODULES += [ + 'ExtensionTestCommon.jsm', 'ExtensionXPCShellUtils.jsm', ] diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/NativeMessaging.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/NativeMessaging.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/NativeMessaging.jsm 2016-11-11 01:57:16.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/NativeMessaging.jsm 2016-11-14 01:55:46.000000000 +0000 @@ -17,8 +17,8 @@ "resource://gre/modules/AppConstants.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "AsyncShutdown", "resource://gre/modules/AsyncShutdown.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "ExtensionUtils", - "resource://gre/modules/ExtensionUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "ExtensionChild", + "resource://gre/modules/ExtensionChild.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Schemas", @@ -231,7 +231,7 @@ */ static onConnectNative(context, messageManager, portId, sender, application) { let app = new NativeApp(context, application); - let port = new ExtensionUtils.Port(context, messageManager, [messageManager], "", portId, sender, sender); + let port = new ExtensionChild.Port(context, messageManager, [messageManager], "", portId, sender, sender); app.once("disconnect", (what, err) => port.disconnect(err)); /* eslint-disable mozilla/balanced-listeners */ diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/mochitest/.eslintrc.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/mochitest/.eslintrc.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/mochitest/.eslintrc.js 2016-11-11 01:57:16.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/mochitest/.eslintrc.js 2016-11-14 01:55:47.000000000 +0000 @@ -19,6 +19,14 @@ "NetUtil": true, "webrequest_test": false, "XPCOMUtils": true, + + // head_webrequest.js symbols + "addStylesheet": true, + "addLink": true, + "addImage": true, + "addScript": true, + "addFrame": true, + "makeExtension": false, }, "rules": { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/mochitest/file_WebRequest_page1.html firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/mochitest/file_WebRequest_page1.html --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/mochitest/file_WebRequest_page1.html 2016-11-11 01:57:16.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/mochitest/file_WebRequest_page1.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ - - - - - - - - - - - -
Sample text
- - - - - - - - - - - - - - - - - - -link -
- - - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/mochitest/file_WebRequest_page2.html firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/mochitest/file_WebRequest_page2.html --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/mochitest/file_WebRequest_page2.html 2016-11-11 01:57:16.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/mochitest/file_WebRequest_page2.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ - - - - - - - - - - - -
Sample text
- - - - - - - - - - - - - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/mochitest/head_webrequest.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/mochitest/head_webrequest.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/mochitest/head_webrequest.js 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/mochitest/head_webrequest.js 2016-11-14 01:56:50.000000000 +0000 @@ -0,0 +1,315 @@ +"use strict"; + +let commonEvents = { + "onBeforeRequest": [{urls: [""]}, ["blocking"]], + "onBeforeSendHeaders": [{urls: [""]}, ["blocking", "requestHeaders"]], + "onSendHeaders": [{urls: [""]}, ["requestHeaders"]], + "onBeforeRedirect": [{urls: [""]}], + "onHeadersReceived": [{urls: [""]}, ["blocking", "responseHeaders"]], + "onResponseStarted": [{urls: [""]}], + "onCompleted": [{urls: [""]}, ["responseHeaders"]], + "onErrorOccurred": [{urls: [""]}], +}; + +function background(events) { + let expect; + let defaultOrigin; + + browser.test.onMessage.addListener((msg, expected) => { + if (msg !== "set-expected") { + return; + } + expect = expected.expect; + defaultOrigin = expected.origin; + let promises = []; + // Initialize some stuff we'll need in the tests. + for (let entry of Object.values(expect)) { + // a place for the test infrastructure to store some state. + entry.test = {}; + // Each entry in expected gets a Promise that will be resolved in the + // last event for that entry. This will either be onCompleted, or the + // last entry if an events list was provided. + promises.push(new Promise(resolve => { entry.test.resolve = resolve; })); + // If events was left undefined, we're expecting all normal events we're + // listening for, exclude onBeforeRedirect and onErrorOccurred + if (entry.events === undefined) { + entry.events = Object.keys(events).filter(name => name != "onErrorOccurred" && name != "onBeforeRedirect"); + } + } + // When every expected entry has finished our test is done. + Promise.all(promises).then(() => { + browser.test.sendMessage("done"); + }); + browser.test.sendMessage("continue"); + }); + + // Retrieve the per-file/test expected values. + function getExpected(details) { + let url = new URL(details.url); + let filename; + if (url.protocol == "data:") { + // pathname is everything after protocol. + filename = url.pathname; + } else { + filename = url.pathname.split("/").pop(); + } + let expected = expect[filename]; + if (!expected) { + browser.test.fail(`unexpected request ${filename}`); + return; + } + // Save filename for redirect verification. + expected.test.filename = filename; + return expected; + } + + // Process any test header modifications that can happen in request or response phases. + // If a test includes headers, it needs a complete header object, no undefined + // objects even if empty: + // request: { + // add: {"HeaderName": "value",}, + // modify: {"HeaderName": "value",}, + // remove: ["HeaderName",], + // }, + // response: { + // add: {"HeaderName": "value",}, + // modify: {"HeaderName": "value",}, + // remove: ["HeaderName",], + // }, + function processHeaders(phase, expected, details) { + // This should only happen once per phase [request|response]. + browser.test.assertFalse(!!expected.test[phase], `First processing of headers for ${phase}`); + expected.test[phase] = true; + + let headers = details[`${phase}Headers`]; + browser.test.assertTrue(Array.isArray(headers), `${phase}Headers array present`); + + let {add, modify, remove} = expected.headers[phase]; + + for (let name in add) { + browser.test.assertTrue(!headers.find(h => h.name === name), `header ${name} to be added not present yet in ${phase}Headers`); + let header = {name: name}; + if (name.endsWith("-binary")) { + header.binaryValue = Array.from(add[name], c => c.charCodeAt(0)); + } else { + header.value = add[name]; + } + headers.push(header); + } + + let modifiedAny = false; + for (let header of headers) { + if (header.name.toLowerCase() in modify) { + header.value = modify[header.name.toLowerCase()]; + modifiedAny = true; + } + } + browser.test.assertTrue(modifiedAny, `at least one ${phase}Headers element to modify`); + + let deletedAny = false; + for (let j = headers.length; j-- > 0;) { + if (remove.includes(headers[j].name.toLowerCase())) { + headers.splice(j, 1); + deletedAny = true; + } + } + browser.test.assertTrue(deletedAny, `at least one ${phase}Headers element to delete`); + + return headers; + } + + // phase is request or response. + function checkHeaders(phase, expected, details) { + if (!/^https?:/.test(details.url)) { + return; + } + + let headers = details[`${phase}Headers`]; + browser.test.assertTrue(Array.isArray(headers), `valid ${phase}Headers array`); + + let {add, modify, remove} = expected.headers[phase]; + for (let name in add) { + let value = headers.find(h => h.name.toLowerCase() === name.toLowerCase()).value; + browser.test.assertEq(value, add[name], `header ${name} correctly injected in ${phase}Headers`); + } + + for (let name in modify) { + let value = headers.find(h => h.name.toLowerCase() === name.toLowerCase()).value; + browser.test.assertEq(value, modify[name], `header ${name} matches modified value`); + } + + for (let name of remove) { + let found = headers.find(h => h.name.toLowerCase() === name.toLowerCase()); + browser.test.assertFalse(!!found, `deleted header ${name} still found in ${phase}Headers`); + } + } + + function getListener(name) { + return details => { + let result = {}; + browser.test.log(`${name} ${details.requestId} ${details.url}`); + let expected = getExpected(details); + if (!expected) { + return result; + } + let expectedEvent = expected.events[0] == name; + browser.test.assertTrue(expectedEvent, `recieved ${name}`); + if (expectedEvent) { + expected.events.shift(); + } + browser.test.assertEq(expected.type, details.type, "resource type is correct"); + browser.test.assertEq(expected.origin || defaultOrigin, details.originUrl, "origin is correct"); + + if (name == "onBeforeRequest") { + // Save some values to test request consistency in later events. + browser.test.assertTrue(details.tabId !== undefined, `tabId ${details.tabId}`); + browser.test.assertTrue(details.requestId !== undefined, `requestId ${details.requestId}`); + // Validate requestId if it's already set, this happens with redirects. + if (expected.test.requestId !== undefined) { + browser.test.assertEq("string", typeof expected.test.requestId, `requestid ${expected.test.requestId} is string`); + browser.test.assertEq("string", typeof details.requestId, `requestid ${details.requestId} is string`); + browser.test.assertEq("number", typeof parseInt(details.requestId, 10), "parsed requestid is number"); + browser.test.assertNotEq(expected.test.requestId, details.requestId, + `last requestId ${expected.test.requestId} different from this one ${details.requestId}`); + } else { + // Save any values we want to validate in later events. + expected.test.requestId = details.requestId; + expected.test.tabId = details.tabId; + } + // Tests we don't need to do every event. + browser.test.assertTrue(details.type.toUpperCase() in browser.webRequest.ResourceType, `valid resource type ${details.type}`); + } else { + // On events after onBeforeRequest, check the previous values. + browser.test.assertEq(expected.test.requestId, details.requestId, "correct requestId"); + browser.test.assertEq(expected.test.tabId, details.tabId, "correct tabId"); + } + if (name == "onBeforeSendHeaders") { + if (expected.headers && expected.headers.request) { + result.requestHeaders = processHeaders("request", expected, details); + } + if (expected.redirect) { + browser.test.log(`${name} redirect request`); + result.redirectUrl = details.url.replace(expected.test.filename, expected.redirect); + } + } + if (name == "onSendHeaders") { + if (expected.headers && expected.headers.request) { + checkHeaders("request", expected, details); + } + } + if (name == "onHeadersReceived") { + browser.test.assertEq(expected.status || 200, details.statusCode, + `expected HTTP status recieved for ${details.url}`); + if (expected.headers && expected.headers.response) { + result.responseHeaders = processHeaders("response", expected, details); + } + } + if (name == "onCompleted") { + // If we have already completed a GET request for this url, + // and it was found, we expect for the response to come fromCache. + // expected.cached may be undefined, force boolean. + let expectCached = !!expected.cached && details.method === "GET" && details.statusCode != 404; + browser.test.assertEq(expectCached, details.fromCache, "fromCache is correct"); + // We can only tell IPs for non-cached HTTP requests. + if (!details.fromCache && /^https?:/.test(details.url)) { + browser.test.assertEq("127.0.0.1", details.ip, `correct ip for ${details.url}`); + } + if (expected.headers && expected.headers.response) { + checkHeaders("response", expected, details); + } + } + + if (expected.cancel && expected.cancel == name) { + browser.test.log(`${name} cancel request`); + browser.test.sendMessage("cancelled"); + result.cancel = true; + } + // If we've used up all the events for this test, resolve the promise. + // If something wrong happens and more events come through, there will be + // failures. + if (expected.events.length <= 0) { + expected.test.resolve(); + } + return result; + }; + } + + for (let [name, args] of Object.entries(events)) { + browser.test.log(`adding listener for ${name}`); + try { + browser.webRequest[name].addListener(getListener(name), ...args); + } catch (e) { + browser.test.assertTrue(/\brequestBody\b/.test(e.message), + "Request body is unsupported"); + + // RequestBody is disabled in release builds. + if (!/\brequestBody\b/.test(e.message)) { + throw e; + } + + args.splice(args.indexOf("requestBody"), 1); + browser.webRequest[name].addListener(getListener(name), ...args); + } + } +} + +/* exported makeExtension */ + +function makeExtension(events = commonEvents) { + return ExtensionTestUtils.loadExtension({ + manifest: { + permissions: [ + "webRequest", + "webRequestBlocking", + "", + ], + }, + background: `(${background})(${JSON.stringify(events)})`, + }); +} + +/* exported addStylesheet */ + +function addStylesheet(file) { + let link = document.createElement("link"); + link.setAttribute("rel", "stylesheet"); + link.setAttribute("href", file); + document.body.appendChild(link); +} + +/* exported addLink */ + +function addLink(file) { + let a = document.createElement("a"); + a.setAttribute("href", file); + a.setAttribute("target", "_blank"); + document.body.appendChild(a); + return a; +} + +/* exported addImage */ + +function addImage(file) { + let img = document.createElement("img"); + img.setAttribute("src", file); + document.body.appendChild(img); +} + +/* exported addScript */ + +function addScript(file) { + let script = document.createElement("script"); + script.setAttribute("type", "text/javascript"); + script.setAttribute("src", file); + document.getElementsByTagName("head").item(0).appendChild(script); +} + +/* exported addFrame */ + +function addFrame(file) { + let frame = document.createElement("iframe"); + frame.setAttribute("width", "200"); + frame.setAttribute("height", "200"); + frame.setAttribute("src", file); + document.body.appendChild(frame); +} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/mochitest/mochitest.ini firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/mochitest/mochitest.ini --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/mochitest/mochitest.ini 2016-11-11 01:57:16.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/mochitest/mochitest.ini 2016-11-14 01:56:50.000000000 +0000 @@ -2,10 +2,9 @@ support-files = head.js file_mixed.html + head_webrequest.js file_csp.html file_csp.html^headers^ - file_WebRequest_page1.html - file_WebRequest_page2.html file_WebRequest_page3.html file_webNavigation_clientRedirect.html file_webNavigation_clientRedirect_httpHeaders.html @@ -93,10 +92,10 @@ skip-if = (os == 'android') # Bug 1258975 on android. [test_ext_web_accessible_resources.html] skip-if = (os == 'android') # Bug 1258975 on android. -[test_ext_webrequest.html] -skip-if = os == 'android' # webrequest api unsupported (bug 1258975). [test_ext_webrequest_background_events.html] skip-if = os == 'android' # webrequest api unsupported (bug 1258975). +[test_ext_webrequest_basic.html] +skip-if = os == 'android' # webrequest api unsupported (bug 1258975). [test_ext_webrequest_suspend.html] skip-if = os == 'android' # webrequest api unsupported (bug 1258975). [test_ext_webrequest_upload.html] diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/mochitest/test_ext_webrequest_basic.html firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/mochitest/test_ext_webrequest_basic.html --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/mochitest/test_ext_webrequest_basic.html 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/mochitest/test_ext_webrequest_basic.html 2016-11-14 01:56:51.000000000 +0000 @@ -0,0 +1,282 @@ + + + + + + + + + + + + + + +
Sample text
+ + + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/mochitest/test_ext_webrequest.html firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/mochitest/test_ext_webrequest.html --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/mochitest/test_ext_webrequest.html 2016-11-11 01:57:17.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/mochitest/test_ext_webrequest.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,548 +0,0 @@ - - - - Test for simple WebExtension - - - - - - - - - - - - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_ext_apimanager.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_ext_apimanager.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_ext_apimanager.js 2016-11-11 01:57:17.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_ext_apimanager.js 2016-11-14 01:56:52.000000000 +0000 @@ -4,7 +4,11 @@ "use strict"; -let {ExtensionUtils: {SchemaAPIManager}} = Cu.import("resource://gre/modules/ExtensionUtils.jsm", {}); +Cu.import("resource://gre/modules/ExtensionCommon.jsm"); + +const { + SchemaAPIManager, +} = ExtensionCommon; this.unknownvar = "Some module-global var"; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_ext_contexts.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_ext_contexts.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_ext_contexts.js 2016-11-11 01:57:17.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_ext_contexts.js 2016-11-14 01:56:52.000000000 +0000 @@ -4,9 +4,14 @@ Cu.import("resource://gre/modules/Timer.jsm"); +Cu.import("resource://gre/modules/ExtensionCommon.jsm"); Cu.import("resource://gre/modules/ExtensionUtils.jsm"); + var { BaseContext, +} = ExtensionCommon; + +var { EventManager, SingletonEventManager, } = ExtensionUtils; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_ext_downloads_download.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_ext_downloads_download.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_ext_downloads_download.js 2016-11-11 01:57:17.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_ext_downloads_download.js 2016-11-14 01:56:52.000000000 +0000 @@ -7,12 +7,12 @@ Cu.import("resource://gre/modules/osfile.jsm"); Cu.import("resource://gre/modules/Downloads.jsm"); -const server = createHttpServer(); -server.registerDirectory("/data/", do_get_file("data")); +const gServer = createHttpServer(); +gServer.registerDirectory("/data/", do_get_file("data")); const WINDOWS = AppConstants.platform == "win"; -const BASE = `http://localhost:${server.identity.primaryPort}/data`; +const BASE = `http://localhost:${gServer.identity.primaryPort}/data`; const FILE_NAME = "file_download.txt"; const FILE_URL = BASE + "/" + FILE_NAME; const FILE_NAME_UNIQUE = "file_download(1).txt"; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_ext_downloads_misc.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_ext_downloads_misc.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_ext_downloads_misc.js 2016-11-11 01:57:17.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_ext_downloads_misc.js 2016-11-14 01:56:52.000000000 +0000 @@ -102,14 +102,14 @@ // set to false to allow other events and options.inorder can be set to // false to allow the events to arrive in any order. function waitForEvents(expected, options = {}) { - function compare(received, expected) { - if (typeof expected == "object" && expected != null) { - if (typeof received != "object") { + function compare(a, b) { + if (typeof b == "object" && b != null) { + if (typeof a != "object") { return false; } - return Object.keys(expected).every(fld => compare(received[fld], expected[fld])); + return Object.keys(b).every(fld => compare(a[fld], b[fld])); } - return (received == expected); + return (a == b); } const exact = ("exact" in options) ? options.exact : true; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_ext_downloads_search.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_ext_downloads_search.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_ext_downloads_search.js 2016-11-11 01:57:17.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_ext_downloads_search.js 2016-11-14 01:56:52.000000000 +0000 @@ -156,12 +156,12 @@ // Search for each individual download and check // the corresponding DownloadItem. function* checkDownloadItem(id, expect) { - let msg = yield search({id}); - equal(msg.status, "success", "search() succeeded"); - equal(msg.downloads.length, 1, "search() found exactly 1 download"); + let item = yield search({id}); + equal(item.status, "success", "search() succeeded"); + equal(item.downloads.length, 1, "search() found exactly 1 download"); Object.keys(expect).forEach(function(field) { - equal(msg.downloads[0][field], expect[field], `DownloadItem.${field} is correct"`); + equal(item.downloads[0][field], expect[field], `DownloadItem.${field} is correct"`); }); } yield checkDownloadItem(downloadIds.txt1, { @@ -209,11 +209,11 @@ }); function* checkSearch(query, expected, description, exact) { - let msg = yield search(query); - equal(msg.status, "success", "search() succeeded"); - equal(msg.downloads.length, expected.length, `search() for ${description} found exactly ${expected.length} downloads`); + let item = yield search(query); + equal(item.status, "success", "search() succeeded"); + equal(item.downloads.length, expected.length, `search() for ${description} found exactly ${expected.length} downloads`); - let receivedIds = msg.downloads.map(item => item.id); + let receivedIds = item.downloads.map(i => i.id); if (exact) { receivedIds.forEach((id, idx) => { equal(id, downloadIds[expected[idx]], `search() for ${description} returned ${expected[idx]} in position ${idx}`); @@ -381,9 +381,9 @@ // Check bad arguments. function* checkBadSearch(query, pattern, description) { - let msg = yield search(query); - equal(msg.status, "error", "search() failed"); - ok(pattern.test(msg.errmsg), `error message for ${description} was correct (${msg.errmsg}).`); + let item = yield search(query); + equal(item.status, "error", "search() failed"); + ok(pattern.test(item.errmsg), `error message for ${description} was correct (${item.errmsg}).`); } yield checkBadSearch("myquery", /Incorrect argument type/, "query is not an object"); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_ext_legacy_extension_context.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_ext_legacy_extension_context.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_ext_legacy_extension_context.js 2016-11-11 01:57:17.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_ext_legacy_extension_context.js 2016-11-14 01:56:52.000000000 +0000 @@ -41,8 +41,8 @@ } else if (msg == "do-connect") { port = browser.runtime.connect(); - port.onMessage.addListener(msg => { - browser.test.assertEq("legacy_extension -> webextension port message", msg, + port.onMessage.addListener(portMsg => { + browser.test.assertEq("legacy_extension -> webextension port message", portMsg, "Got the expected message from the LegacyExtensionContext"); port.postMessage("webextension -> legacy_extension port message"); }); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_ext_native_messaging_perf.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_ext_native_messaging_perf.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_ext_native_messaging_perf.js 2016-11-11 01:57:17.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_ext_native_messaging_perf.js 2016-11-14 01:56:52.000000000 +0000 @@ -90,7 +90,7 @@ } let count = 0; - port.onMessage.addListener(msg => { + port.onMessage.addListener(() => { if (count == 0) { // Skip the first round, since it includes the time it takes // the app to start up. diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_ext_schemas_api_injection.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_ext_schemas_api_injection.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_ext_schemas_api_injection.js 2016-11-11 01:57:17.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_ext_schemas_api_injection.js 2016-11-14 01:56:52.000000000 +0000 @@ -1,12 +1,12 @@ "use strict"; -Components.utils.import("resource://gre/modules/ExtensionUtils.jsm"); +Components.utils.import("resource://gre/modules/ExtensionCommon.jsm"); Components.utils.import("resource://gre/modules/Schemas.jsm"); let { BaseContext, SchemaAPIManager, -} = ExtensionUtils; +} = ExtensionCommon; let nestedNamespaceJson = [ { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_ext_schemas_async.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_ext_schemas_async.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_ext_schemas_async.js 2016-11-11 01:57:17.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_ext_schemas_async.js 2016-11-14 01:56:52.000000000 +0000 @@ -1,9 +1,9 @@ "use strict"; -Components.utils.import("resource://gre/modules/ExtensionUtils.jsm"); +Components.utils.import("resource://gre/modules/ExtensionCommon.jsm"); Components.utils.import("resource://gre/modules/Schemas.jsm"); -let {BaseContext, LocalAPIImplementation} = ExtensionUtils; +let {BaseContext, LocalAPIImplementation} = ExtensionCommon; let schemaJson = [ { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_ext_schemas.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_ext_schemas.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_ext_schemas.js 2016-11-11 01:57:17.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_ext_schemas.js 2016-11-14 01:56:52.000000000 +0000 @@ -2,9 +2,9 @@ Components.utils.import("resource://gre/modules/Schemas.jsm"); Components.utils.import("resource://gre/modules/BrowserUtils.jsm"); -Components.utils.import("resource://gre/modules/ExtensionUtils.jsm"); +Components.utils.import("resource://gre/modules/ExtensionCommon.jsm"); -let {LocalAPIImplementation, SchemaAPIInterface} = ExtensionUtils; +let {LocalAPIImplementation, SchemaAPIInterface} = ExtensionCommon; let json = [ {namespace: "testing", @@ -637,8 +637,8 @@ "should throw for access denied"); } - for (let url of ["//foo.html", "http://foo/bar.html"]) { - Assert.throws(() => root.testing.format({strictRelativeUrl: url}), + for (let urlString of ["//foo.html", "http://foo/bar.html"]) { + Assert.throws(() => root.testing.format({strictRelativeUrl: urlString}), /must be a relative URL/, "should throw for non-relative URL"); } @@ -753,10 +753,10 @@ "should throw when passing a Proxy"); if (Symbol.toStringTag) { - let target = {prop1: 12, prop2: ["value1", "value3"]}; - target[Symbol.toStringTag] = () => "[object Object]"; - let proxy = new Proxy(target, {}); - Assert.throws(() => root.testing.quack(proxy), + let stringTarget = {prop1: 12, prop2: ["value1", "value3"]}; + stringTarget[Symbol.toStringTag] = () => "[object Object]"; + let stringProxy = new Proxy(stringTarget, {}); + Assert.throws(() => root.testing.quack(stringProxy), /Expected a plain JavaScript object, got a Proxy/, "should throw when passing a Proxy"); } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_ext_storage.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_ext_storage.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_ext_storage.js 2016-11-11 01:57:17.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_ext_storage.js 2016-11-14 01:56:52.000000000 +0000 @@ -20,8 +20,8 @@ let globalChanges = {}; - browser.storage.onChanged.addListener((changes, storage) => { - browser.test.assertEq("local", storage, "storage is local"); + browser.storage.onChanged.addListener((changes, changedStorage) => { + browser.test.assertEq("local", changedStorage, "storage is local"); Object.assign(globalChanges, changes); }); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_native_messaging.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_native_messaging.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/extensions/test/xpcshell/test_native_messaging.js 2016-11-11 01:57:17.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/extensions/test/xpcshell/test_native_messaging.js 2016-11-14 01:56:52.000000000 +0000 @@ -3,7 +3,7 @@ /* global OS, HostManifestManager, NativeApp */ Cu.import("resource://gre/modules/AppConstants.jsm"); Cu.import("resource://gre/modules/AsyncShutdown.jsm"); -Cu.import("resource://gre/modules/ExtensionUtils.jsm"); +Cu.import("resource://gre/modules/ExtensionCommon.jsm"); Cu.import("resource://gre/modules/FileUtils.jsm"); Cu.import("resource://gre/modules/Schemas.jsm"); Cu.import("resource://gre/modules/Services.jsm"); @@ -84,7 +84,7 @@ forgetOnClose: () => {}, }; -class MockContext extends ExtensionUtils.BaseContext { +class MockContext extends ExtensionCommon.BaseContext { constructor(extensionId) { let fakeExtension = {id: extensionId}; super("testEnv", fakeExtension); @@ -272,8 +272,8 @@ yield writeManifest(manifestPath, manifest); } - let context = new MockContext(ID); - let app = new NativeApp(context, "wontdie"); + let mockContext = new MockContext(ID); + let app = new NativeApp(mockContext, "wontdie"); // send a message and wait for the reply to make sure the app is running let MSG = "test"; @@ -286,7 +286,7 @@ app.on("message", listener); }); - let buffer = NativeApp.encodeMessage(context, MSG); + let buffer = NativeApp.encodeMessage(mockContext, MSG); app.send(buffer); yield recvPromise; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/feeds/FeedProcessor.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/feeds/FeedProcessor.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/feeds/FeedProcessor.js 2016-11-11 01:57:17.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/feeds/FeedProcessor.js 2016-11-14 01:56:52.000000000 +0000 @@ -970,8 +970,6 @@ }, startElement: function EH_startElement(uri, localName, qName, attrs) { ++this._depth; - var prefix = gNamespaces[uri] ? gNamespaces[uri] + ":" : ""; - var key = prefix + localName; if (this._depth == 1) { this._uri = uri; @@ -1498,7 +1496,7 @@ // attributes and child elements. _processComplexElement: function FP__processComplexElement(elementInfo, attributes) { - var obj, key, prefix; + var obj; // If the container is an entry/item, it'll need to have its // more esoteric properties put in the 'fields' property bag. diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/filepicker/content/filepicker.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/filepicker/content/filepicker.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/filepicker/content/filepicker.js 2016-11-11 01:57:18.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/filepicker/content/filepicker.js 2016-11-14 01:57:22.000000000 +0000 @@ -661,9 +661,7 @@ var parent = file.parent; if (!(parent.exists() && parent.isDirectory() && parent.isWritable())) { - var oldParent = parent; while (!parent.exists()) { - oldParent = parent; parent = parent.parent; } if (parent.isFile()) { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/filepicker/nsFilePicker.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/filepicker/nsFilePicker.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/filepicker/nsFilePicker.js 2016-11-11 01:57:18.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/filepicker/nsFilePicker.js 2016-11-14 01:57:22.000000000 +0000 @@ -270,17 +270,6 @@ } } - var parentWin = null; - try { - parentWin = parent.QueryInterface(nsIInterfaceRequestor) - .getInterface(nsIWebNavigation) - .QueryInterface(nsIDocShellTreeItem) - .treeOwner - .QueryInterface(nsIInterfaceRequestor) - .getInterface(nsIBaseWindow); - } catch (ex) { - dump("file picker couldn't get base window\n"+ex+"\n"); - } try { parent.openDialog("chrome://global/content/filepicker.xul", "", @@ -328,4 +317,3 @@ } return strBundle; } - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/gfx/SanityTest.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/gfx/SanityTest.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/gfx/SanityTest.js 2016-11-11 01:57:19.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/gfx/SanityTest.js 2016-11-14 01:57:22.000000000 +0000 @@ -180,7 +180,6 @@ }, receiveMessage(message) { - let data = message.data; switch (message.name) { case "gfxSanity:ContentLoaded": this.runSanityTest(); @@ -244,7 +243,6 @@ shouldRunTest: function() { // Only test gfx features if firefox has updated, or if the user has a new // gpu or drivers. - var appInfo = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo); var buildId = Services.appinfo.platformBuildID; var gfxinfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/jsdownloads/test/unit/common_test_Download.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/jsdownloads/test/unit/common_test_Download.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/jsdownloads/test/unit/common_test_Download.js 2016-11-11 01:58:59.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/jsdownloads/test/unit/common_test_Download.js 2016-11-14 01:57:22.000000000 +0000 @@ -2380,11 +2380,11 @@ let download; if (gUseLegacySaver) { download = yield promiseStartLegacyDownload(httpUrl("source.txt"), - { targetFile: targetFile }); + { isPrivate, targetFile }); } else { download = yield Downloads.createDownload({ - source: httpUrl("source.txt"), + source: { url: httpUrl("source.txt"), isPrivate }, target: targetFile, }); download.start().catch(() => {}); @@ -2469,8 +2469,6 @@ * mode after they have been launched. */ add_task(function* test_launchWhenSucceeded_deleteTempFileOnExit() { - const kDeleteTempFileOnExit = "browser.helperApps.deleteTempFileOnExit"; - let customLauncherPath = getTempFile("app-launcher").path; let autoDeleteTargetPathOne = getTempFile(TEST_TARGET_FILE_NAME).path; let autoDeleteTargetPathTwo = getTempFile(TEST_TARGET_FILE_NAME).path; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/jsdownloads/test/unit/head.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/jsdownloads/test/unit/head.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/jsdownloads/test/unit/head.js 2016-11-11 01:58:59.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/jsdownloads/test/unit/head.js 2016-11-14 01:57:22.000000000 +0000 @@ -418,9 +418,9 @@ onStartRequest: function (aRequest, aContext) { - let channel = aRequest.QueryInterface(Ci.nsIChannel); + let requestChannel = aRequest.QueryInterface(Ci.nsIChannel); this.contentListener = gExternalHelperAppService.doContent( - channel.contentType, aRequest, null, true); + requestChannel.contentType, aRequest, null, true); this.contentListener.onStartRequest(aRequest, aContext); }, @@ -820,11 +820,6 @@ }, })); - // Get a reference to nsIComponentRegistrar, and ensure that is is freed - // before the XPCOM shutdown. - let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); - do_register_cleanup(() => registrar = null); - // Make sure that downloads started using nsIExternalHelperAppService are // saved to disk without asking for a destination interactively. let mock = { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/jsdownloads/test/unit/test_DownloadIntegration.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/jsdownloads/test/unit/test_DownloadIntegration.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/jsdownloads/test/unit/test_DownloadIntegration.js 2016-11-11 01:59:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/jsdownloads/test/unit/test_DownloadIntegration.js 2016-11-14 01:57:22.000000000 +0000 @@ -408,7 +408,7 @@ let download1 = yield promiseNewDownload(httpUrl("source.txt")); let download2 = yield promiseNewDownload(httpUrl("interruptible.txt")); let promiseAttempt1 = download1.start(); - let promiseAttempt2 = download2.start(); + download2.start(); // Add downloads to list. yield privateList.add(download1); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/jsdownloads/test/unit/test_DownloadStore.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/jsdownloads/test/unit/test_DownloadStore.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/jsdownloads/test/unit/test_DownloadStore.js 2016-11-11 01:59:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/jsdownloads/test/unit/test_DownloadStore.js 2016-11-14 01:57:22.000000000 +0000 @@ -111,7 +111,7 @@ */ add_task(function* test_save_empty() { - let [list, store] = yield promiseNewListAndStore(); + let [, store] = yield promiseNewListAndStore(); let createdFile = yield OS.File.open(store.path, { create: true }); yield createdFile.close(); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/mediasniffer/test/unit/test_mediasniffer_ext.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/mediasniffer/test/unit/test_mediasniffer_ext.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/mediasniffer/test/unit/test_mediasniffer_ext.js 2016-11-11 01:59:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/mediasniffer/test/unit/test_mediasniffer_ext.js 2016-11-14 01:57:23.000000000 +0000 @@ -56,7 +56,7 @@ var bis = Components.classes["@mozilla.org/binaryinputstream;1"] .createInstance(Components.interfaces.nsIBinaryInputStream); bis.setInputStream(stream); - var array = bis.readByteArray(bis.available()); + bis.readByteArray(bis.available()); } catch (ex) { do_throw("Error in onDataAvailable: " + ex); } @@ -88,7 +88,6 @@ } function getFileContents(aFile) { - const PR_RDONLY = 0x01; var fileStream = Cc["@mozilla.org/network/file-input-stream;1"] .createInstance(Ci.nsIFileInputStream); fileStream.init(aFile, 1, -1, null); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/perfmonitoring/tests/browser/browser_AddonWatcher.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/perfmonitoring/tests/browser/browser_AddonWatcher.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/perfmonitoring/tests/browser/browser_AddonWatcher.js 2016-11-11 01:59:04.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/perfmonitoring/tests/browser/browser_AddonWatcher.js 2016-11-14 01:58:26.000000000 +0000 @@ -41,15 +41,6 @@ addon.uninstall() }); - - let freezeThreshold = Preferences.get("browser.addon-watch.freeze-threshold-micros", /* 5 seconds */ 5000000); - let jankThreshold = Preferences.get("browser.addon-watch.jank-threshold-micros", /* 256 ms == 8 frames*/ 256000); - let occurrencesBetweenAlerts = Preferences.get("browser.addon-watch.occurrences-between-alerts", 3); - let delayBetweenAlerts = Preferences.get("browser.addon-watch.delay-between-alerts-ms", 6 * 3600 * 1000 /* 6h */); - let delayBetweenFreezeAlerts = Preferences.get("browser.addon-watch.delay-between-freeze-alerts-ms", 2 * 60 * 1000 /* 2 min */); - let prescriptionDelay = Preferences.get("browser.addon-watch.prescription-delay", 5 * 60 * 1000 /* 5 minutes */); - let highestNumberOfAddonsToReport = Preferences.get("browser.addon-watch.max-simultaneous-reports", 1); - Preferences.set("browser.addon-watch.warmup-ms", 0); Preferences.set("browser.addon-watch.freeze-threshold-micros", 0); Preferences.set("browser.addon-watch.jank-threshold-micros", 0); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/perfmonitoring/tests/browser/browser_compartments.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/perfmonitoring/tests/browser/browser_compartments.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/perfmonitoring/tests/browser/browser_compartments.js 2016-11-11 01:59:31.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/perfmonitoring/tests/browser/browser_compartments.js 2016-11-14 01:58:26.000000000 +0000 @@ -27,9 +27,6 @@ const { utils: Cu, classes: Cc, interfaces: Ci } = Components; Cu.import("resource://gre/modules/PerformanceStats.jsm"); Cu.import("resource://gre/modules/Services.jsm"); - let performanceStatsService = - Cc["@mozilla.org/toolkit/performance-stats-service;1"]. - getService(Ci.nsIPerformanceStatsService); // Make sure that the stopwatch is now active. let monitor = PerformanceStats.getMonitor(["jank", "cpow", "ticks", "compartments"]); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/BookmarkHTMLUtils.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/BookmarkHTMLUtils.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/BookmarkHTMLUtils.jsm 2016-11-11 02:00:02.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/BookmarkHTMLUtils.jsm 2016-11-14 01:58:30.000000000 +0000 @@ -520,8 +520,6 @@ let keyword = this._safeTrim(aElt.getAttribute("shortcuturl")); let postData = this._safeTrim(aElt.getAttribute("post_data")); let webPanel = this._safeTrim(aElt.getAttribute("web_panel")); - let micsumGenURI = this._safeTrim(aElt.getAttribute("micsum_gen_uri")); - let generatedTitle = this._safeTrim(aElt.getAttribute("generated_title")); let dateAdded = this._safeTrim(aElt.getAttribute("add_date")); let lastModified = this._safeTrim(aElt.getAttribute("last_modified")); let tags = this._safeTrim(aElt.getAttribute("tags")); @@ -1124,9 +1122,8 @@ }, *_writeItem(aItem, aIndent) { - let uri = null; try { - uri = NetUtil.newURI(aItem.uri); + NetUtil.newURI(aItem.uri); } catch (ex) { // If the item URI is invalid, skip the item instead of failing later. return; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/Bookmarks.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/Bookmarks.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/Bookmarks.jsm 2016-11-11 02:00:04.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/Bookmarks.jsm 2016-11-14 01:58:32.000000000 +0000 @@ -269,7 +269,6 @@ return Object.assign({}, item); } - let time = (updateInfo && updateInfo.dateAdded) || new Date(); updateInfo = validateBookmarkObject(updateInfo, { url: { validIf: () => item.type == this.TYPE_BOOKMARK } , title: { validIf: () => [ this.TYPE_BOOKMARK diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/ExtensionSearchHandler.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/ExtensionSearchHandler.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/ExtensionSearchHandler.jsm 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/ExtensionSearchHandler.jsm 2016-11-14 01:59:09.000000000 +0000 @@ -0,0 +1,292 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +this.EXPORTED_SYMBOLS = [ "ExtensionSearchHandler" ]; + +// Used to keep track of all of the registered keywords, where each keyword is +// mapped to a KeywordInfo instance. +let gKeywordMap = new Map(); + +// Used to keep track of the active input session. +let gActiveInputSession = null; + +// Used to keep track of who has control over the active suggestion callback +// so older callbacks can be ignored. The callback ID should increment whenever +// the input changes or the input session ends. +let gCurrentCallbackID = 0; + +// Handles keeping track of information associated to the registered keyword. +class KeywordInfo { + constructor(extension, description) { + this._extension = extension; + this._description = description; + } + + get description() { + return this._description; + } + + set description(desc) { + this._description = desc; + } + + get extension() { + return this._extension; + } +} + +// Responsible for handling communication between the extension and the urlbar. +class InputSession { + constructor(keyword, extension) { + this._keyword = keyword; + this._extension = extension; + this._suggestionsCallback = null; + this._searchFinishedCallback = null; + } + + get keyword() { + return this._keyword; + } + + addSuggestions(suggestions) { + this._suggestionsCallback(suggestions); + } + + start(eventName) { + this._extension.emit(eventName); + } + + update(eventName, text, suggestionsCallback, searchFinishedCallback) { + if (this._searchFinishedCallback) { + this._searchFinishedCallback(); + } + this._searchFinishedCallback = searchFinishedCallback; + this._suggestionsCallback = suggestionsCallback; + this._extension.emit(eventName, text, ++gCurrentCallbackID); + } + + cancel(eventName) { + this._searchFinishedCallback(); + this._extension.emit(eventName); + } + + end(eventName, text, disposition) { + this._searchFinishedCallback(); + this._extension.emit(eventName, text, disposition); + } +} + +var ExtensionSearchHandler = Object.freeze({ + MSG_INPUT_STARTED: "webext-omnibox-input-started", + MSG_INPUT_CHANGED: "webext-omnibox-input-changed", + MSG_INPUT_ENTERED: "webext-omnibox-input-entered", + MSG_INPUT_CANCELLED: "webext-omnibox-input-cancelled", + + /** + * Registers a keyword. + * + * @param {string} keyword The keyword to register. + * @param {Extension} extension The extension registering the keyword. + */ + registerKeyword(keyword, extension) { + if (gKeywordMap.has(keyword)) { + throw new Error(`The keyword provided is already registered: "${keyword}"`); + } + gKeywordMap.set(keyword, new KeywordInfo(extension, extension.name)); + }, + + /** + * Unregisters a keyword. + * + * @param {string} keyword The keyword to unregister. + */ + unregisterKeyword(keyword) { + if (!gKeywordMap.has(keyword)) { + throw new Error(`The keyword provided is not registered: "${keyword}"`); + } + gActiveInputSession = null; + gKeywordMap.delete(keyword); + }, + + /** + * Checks if a keyword is registered. + * + * @param {string} keyword The word to check. + * @return {boolean} true if the word is a registered keyword. + */ + isKeywordRegistered(keyword) { + return gKeywordMap.has(keyword); + }, + + /** + * @return {boolean} true if there is an active input session. + */ + hasActiveInputSession() { + return gActiveInputSession != null; + }, + + /** + * @param {string} keyword The keyword to look up. + * @return {string} the description to use for the heuristic result. + */ + getDescription(keyword) { + if (!gKeywordMap.has(keyword)) { + throw new Error(`The keyword provided is not registered: "${keyword}"`); + } + return gKeywordMap.get(keyword).description; + }, + + /** + * Sets the default suggestion for the registered keyword. The suggestion's + * description will be used for the comment in the heuristic result. + * + * @param {string} keyword The keyword. + * @param {string} description The description to use for the heuristic result. + */ + setDefaultSuggestion(keyword, {description}) { + if (!gKeywordMap.has(keyword)) { + throw new Error(`The keyword provided is not registered: "${keyword}"`); + } + gKeywordMap.get(keyword).description = description; + }, + + /** + * Adds suggestions for the registered keyword. This function will throw if + * the keyword provided is not registered or active, or if the callback ID + * provided is no longer equal to the active callback ID. + * + * @param {string} keyword The keyword. + * @param {integer} id The ID of the suggestion callback. + * @param {Array} suggestions An array of suggestions to provide to the urlbar. + */ + addSuggestions(keyword, id, suggestions) { + if (!gKeywordMap.has(keyword)) { + throw new Error(`The keyword provided is not registered: "${keyword}"`); + } + + if (!gActiveInputSession || gActiveInputSession.keyword != keyword) { + throw new Error(`The keyword provided is not apart of an active input session: "${keyword}"`); + } + + if (id != gCurrentCallbackID) { + throw new Error(`The callback is no longer active for the keyword provided: "${keyword}"`); + } + + gActiveInputSession.addSuggestions(suggestions); + }, + + /** + * Called when the input in the urlbar begins with ``. + * + * If the keyword is inactive, MSG_INPUT_STARTED is emitted and the + * keyword is marked as active. If the keyword is followed by any text, + * MSG_INPUT_CHANGED is fired with the current callback ID that can be + * used to provide suggestions to the urlbar while the callback ID is active. + * The callback is invalidated when either the input changes or the urlbar blurs. + * + * @param {string} keyword The keyword to handle. + * @param {string} text The search text in the urlbar. + * @param {Function} callback The callback used to provide search suggestions. + * @return {Promise} promise that resolves when the current search is complete. + */ + handleSearch(keyword, text, callback) { + if (!gKeywordMap.has(keyword)) { + throw new Error(`The keyword provided is not registered: "${keyword}"`); + } + + if (gActiveInputSession && gActiveInputSession.keyword != keyword) { + throw new Error("A different input session is already ongoing"); + } + + if (!text || !text.startsWith(`${keyword} `)) { + throw new Error(`The text provided must start with: "${keyword} "`); + } + + if (!callback) { + throw new Error("A callback must be provided"); + } + + // The search text in the urlbar currently starts with , and + // we only want the text that follows. + text = text.substring(keyword.length + 1); + + // We fire MSG_INPUT_STARTED once we have , and only fire + // MSG_INPUT_CHANGED when we have text to process. This is different from Chrome's + // behavior, which always fires MSG_INPUT_STARTED right before MSG_INPUT_CHANGED + // first fires, but this is a bug in Chrome according to https://crbug.com/258911. + if (!gActiveInputSession) { + gActiveInputSession = new InputSession(keyword, gKeywordMap.get(keyword).extension); + gActiveInputSession.start(this.MSG_INPUT_STARTED); + + // Resolve early if there is no text to process. There can be text to process when + // the input starts if the user copy/pastes the text into the urlbar. + if (!text.length) { + return Promise.resolve(); + } + } + + return new Promise(resolve => { + gActiveInputSession.update(this.MSG_INPUT_CHANGED, text, callback, resolve); + }); + }, + + /** + * Called when the user clicks on a suggestion that was added by + * an extension. MSG_INPUT_ENTERED is emitted to the extension with + * the keyword, the current search string, and info about how the + * the search should be handled. This ends the active input session. + * + * @param {string} keyword The keyword associated to the suggestion. + * @param {string} text The search text in the urlbar. + * @param {string} where How the page should be opened. Accepted values are: + * "current": open the page in the same tab. + * "tab": open the page in a new foreground tab. + * "tabshifted": open the page in a new background tab. + */ + handleInputEntered(keyword, text, where) { + if (!gKeywordMap.has(keyword)) { + throw new Error(`The keyword provided is not registered: "${keyword}"`); + } + + if (gActiveInputSession && gActiveInputSession.keyword != keyword) { + throw new Error("A different input session is already ongoing"); + } + + if (!text || !text.startsWith(`${keyword} `)) { + throw new Error(`The text provided must start with: "${keyword} "`); + } + + let dispositionMap = { + current: "currentTab", + tab: "newForegroundTab", + tabshifted: "newBackgroundTab", + } + let disposition = dispositionMap[where]; + + if (!disposition) { + throw new Error(`Invalid "where" argument: ${where}`); + } + + // The search text in the urlbar currently starts with , and + // we only want to send the text that follows. + text = text.substring(keyword.length + 1); + + gActiveInputSession.end(this.MSG_INPUT_ENTERED, text, disposition) + gActiveInputSession = null; + }, + + /** + * If the user has ended the keyword input session without accepting the input, + * MSG_INPUT_CANCELLED is emitted and the input session is ended. + */ + handleInputCancelled() { + if (!gActiveInputSession) { + throw new Error("There is no active input session"); + } + gActiveInputSession.cancel(this.MSG_INPUT_CANCELLED); + gActiveInputSession = null; + } +}); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/History.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/History.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/History.jsm 2016-11-11 02:00:25.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/History.jsm 2016-11-14 01:59:26.000000000 +0000 @@ -875,13 +875,10 @@ let onResultData = onResult ? [] : null; let pages = []; - let hasPagesToKeep = false; let hasPagesToRemove = false; yield db.execute(query, null, Task.async(function*(row) { let hasForeign = row.getResultByName("foreign_count") != 0; - if (hasForeign) { - hasPagesToKeep = true; - } else { + if (!hasForeign) { hasPagesToRemove = true; } let id = row.getResultByName("id"); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/moz.build firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/moz.build --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/moz.build 2016-11-11 02:00:25.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/moz.build 2016-11-14 01:59:27.000000000 +0000 @@ -64,6 +64,7 @@ 'ClusterLib.js', 'ColorAnalyzer_worker.js', 'ColorConversion.js', + 'ExtensionSearchHandler.jsm', 'History.jsm', 'PlacesBackups.jsm', 'PlacesDBUtils.jsm', diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/mozIPlacesAutoComplete.idl firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/mozIPlacesAutoComplete.idl --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/mozIPlacesAutoComplete.idl 2016-11-11 02:00:25.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/mozIPlacesAutoComplete.idl 2016-11-14 01:59:27.000000000 +0000 @@ -116,8 +116,10 @@ * * @param aURI * The URI to register as an open page. + * @param aUserContextId + * The Container Id of the tab. */ - void registerOpenPage(in nsIURI aURI); + void registerOpenPage(in nsIURI aURI, in uint32_t aUserContextId); /** * Mark a page as no longer being open (either by closing the window or tab, @@ -129,6 +131,8 @@ * * @param aURI * The URI to unregister as an open page. + * @param aUserContextId + * The Container Id of the tab. */ - void unregisterOpenPage(in nsIURI aURI); + void unregisterOpenPage(in nsIURI aURI, in uint32_t aUserContextId); }; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/nsNavHistory.cpp firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/nsNavHistory.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/nsNavHistory.cpp 2016-11-11 02:00:27.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/nsNavHistory.cpp 2016-11-14 01:59:28.000000000 +0000 @@ -677,7 +677,7 @@ nsNavHistory *history = static_cast(aClosure); if (history) { history->mCachedNow = 0; - history->mExpireNowTimer = 0; + history->mExpireNowTimer = nullptr; } } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/nsPlacesTables.h firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/nsPlacesTables.h --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/nsPlacesTables.h 2016-11-11 02:00:27.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/nsPlacesTables.h 2016-11-14 01:59:28.000000000 +0000 @@ -133,8 +133,10 @@ // nsPlacesAutoComplete.js. #define CREATE_MOZ_OPENPAGES_TEMP NS_LITERAL_CSTRING( \ "CREATE TEMP TABLE moz_openpages_temp (" \ - " url TEXT PRIMARY KEY" \ + " url TEXT" \ + ", userContextId INTEGER" \ ", open_count INTEGER" \ + ", PRIMARY KEY (url, userContextId)" \ ")" \ ) diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/nsPlacesTriggers.h firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/nsPlacesTriggers.h --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/nsPlacesTriggers.h 2016-11-11 02:00:27.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/nsPlacesTriggers.h 2016-11-14 01:59:28.000000000 +0000 @@ -192,7 +192,8 @@ "WHEN NEW.open_count = 0 " \ "BEGIN " \ "DELETE FROM moz_openpages_temp " \ - "WHERE url = NEW.url;" \ + "WHERE url = NEW.url " \ + "AND userContextId = NEW.userContextId;" \ "END" \ ) diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/PlacesTransactions.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/PlacesTransactions.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/PlacesTransactions.jsm 2016-11-11 02:00:25.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/PlacesTransactions.jsm 2016-11-14 01:59:27.000000000 +0000 @@ -313,7 +313,6 @@ * @see Batches in the module documentation. */ batch(aToBatch) { - let batchFunc; if (Array.isArray(aToBatch)) { if (aToBatch.length == 0) throw new Error("aToBatch must not be an empty array"); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/PlacesUtils.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/PlacesUtils.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/PlacesUtils.jsm 2016-11-11 02:00:25.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/PlacesUtils.jsm 2016-11-14 01:59:27.000000000 +0000 @@ -1178,7 +1178,7 @@ // Fetch keywords for this href. let cache = yield gKeywordsCachePromise; - for (let [ keyword, entry ] of cache) { + for (let [ , entry ] of cache) { // Set the POST data on keywords not having it. if (entry.url.href == bm.url.href && !entry.postData) { entry.postData = aPostData; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_1016953-renaming-uncompressed.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_1016953-renaming-uncompressed.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_1016953-renaming-uncompressed.js 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_1016953-renaming-uncompressed.js 2016-11-14 01:59:28.000000000 +0000 @@ -51,7 +51,7 @@ let backupFolder = yield PlacesBackups.getBackupFolder(); let tempPath = OS.Path.join(OS.Constants.Path.profileDir, "bug10169583_bookmarks.json"); - let {count, hash} = yield BookmarkJSONUtils.exportToFile(tempPath); + let {count} = yield BookmarkJSONUtils.exportToFile(tempPath); let dateObj = new Date(); let filename = "bookmarks-" + PlacesBackups.toISODateString(dateObj) + "_" + count + "_" + "differentHash==" + ".json"; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_1129529.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_1129529.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_1129529.js 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_1129529.js 2016-11-14 01:59:28.000000000 +0000 @@ -61,7 +61,7 @@ let uri = "data:" + contentType + "," + JSON.stringify(aData); yield BookmarkJSONUtils.importFromURL(uri, false); - let [bookmarks, count] = yield PlacesBackups.getBookmarksTree(); + let [bookmarks] = yield PlacesBackups.getBookmarksTree(); let unsortedBookmarks = bookmarks.children[2].children; Assert.equal(unsortedBookmarks.length, 3); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_417228-other-roots.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_417228-other-roots.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_417228-other-roots.js 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_417228-other-roots.js 2016-11-14 01:59:28.000000000 +0000 @@ -129,9 +129,6 @@ // make json file let jsonFile = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.json"); - // array of ids not to delete when restoring - var excludedItemsFromRestore = []; - // populate db tests.forEach(function(aTest) { aTest.populate(); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_466303-json-remove-backups.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_466303-json-remove-backups.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_466303-json-remove-backups.js 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_466303-json-remove-backups.js 2016-11-14 01:59:28.000000000 +0000 @@ -25,7 +25,6 @@ // Export bookmarks to JSON. // Allow 2 backups, the older one should be removed. yield PlacesBackups.create(2); - let backupFilename = PlacesBackups.getFilenameForDate(); let count = 0; let lastBackupPath = null; @@ -53,7 +52,6 @@ // Export bookmarks to JSON. // Allow 3 backups, none should be removed. yield PlacesBackups.create(3); - let backupFilename = PlacesBackups.getFilenameForDate(); let count = 0; let lastBackupPath = null; @@ -79,7 +77,6 @@ // Allow infinite backups, none should be removed, a new one is not created // since one for today already exists. yield PlacesBackups.create(null); - let backupFilename = PlacesBackups.getFilenameForDate(); let count = 0; let lastBackupPath = null; @@ -105,7 +102,6 @@ // Allow infinite backups, none should be removed, a new one is not created // since one for today already exists. yield PlacesBackups.create(); - let backupFilename = PlacesBackups.getFilenameForDate(); let count = 0; let lastBackupPath = null; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_477583_json-backup-in-future.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_477583_json-backup-in-future.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_477583_json-backup-in-future.js 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_477583_json-backup-in-future.js 2016-11-14 01:59:28.000000000 +0000 @@ -41,7 +41,6 @@ do_check_eq((yield PlacesBackups.getBackupFiles()).length, 1); let mostRecentBackupFile = yield PlacesBackups.getMostRecentBackup(); do_check_neq(mostRecentBackupFile, null); - let todayFilename = PlacesBackups.getFilenameForDate(); do_check_true(PlacesBackups.filenamesRegex.test(OS.Path.basename(mostRecentBackupFile))); // Check that future backup has been removed. diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_711914.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_711914.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_711914.js 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_711914.js 2016-11-14 01:59:28.000000000 +0000 @@ -38,11 +38,10 @@ .createFolder(folder1, "Folder2", PlacesUtils.bookmarks.DEFAULT_INDEX); - let itemId = PlacesUtils.bookmarks - .insertBookmark(folder2, - NetUtil.newURI("http://mozilla.org/"), - PlacesUtils.bookmarks.DEFAULT_INDEX, - "Mozilla"); + PlacesUtils.bookmarks.insertBookmark(folder2, + NetUtil.newURI("http://mozilla.org/"), + PlacesUtils.bookmarks.DEFAULT_INDEX, + "Mozilla"); PlacesUtils.bookmarks.removeFolderChildren(folder1); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_818587_compress-bookmarks-backups.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_818587_compress-bookmarks-backups.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_818587_compress-bookmarks-backups.js 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_818587_compress-bookmarks-backups.js 2016-11-14 01:59:28.000000000 +0000 @@ -9,8 +9,6 @@ } add_task(function* compress_bookmark_backups_test() { - let backupFolder = yield PlacesBackups.getBackupFolder(); - // Check for jsonlz4 extension let todayFilename = PlacesBackups.getFilenameForDate(new Date(2014, 4, 15), true); do_check_eq(todayFilename, "bookmarks-2014-05-15.jsonlz4"); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_bookmarks_eraseEverything.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_bookmarks_eraseEverything.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_bookmarks_eraseEverything.js 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_bookmarks_eraseEverything.js 2016-11-14 01:59:28.000000000 +0000 @@ -29,7 +29,7 @@ let menuBookmark = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.menuGuid, type: PlacesUtils.bookmarks.TYPE_BOOKMARK, url: "http://example.com/" }); - checkBookmarkObject(unfiledBookmark); + checkBookmarkObject(menuBookmark); let menuBookmarkInFolder = yield PlacesUtils.bookmarks.insert({ parentGuid: menuFolder.guid, type: PlacesUtils.bookmarks.TYPE_BOOKMARK, diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_bookmarks.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_bookmarks.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_bookmarks.js 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_bookmarks.js 2016-11-14 01:59:28.000000000 +0000 @@ -92,13 +92,13 @@ // test getFolderIdForItem() with bogus item id will throw try { - let id = bs.getFolderIdForItem(0); + bs.getFolderIdForItem(0); do_throw("getFolderIdForItem accepted bad input"); } catch (ex) {} // test getFolderIdForItem() with bogus item id will throw try { - let id = bs.getFolderIdForItem(-1); + bs.getFolderIdForItem(-1); do_throw("getFolderIdForItem accepted bad input"); } catch (ex) {} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_bookmarks_notifications.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_bookmarks_notifications.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_bookmarks_notifications.js 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_bookmarks_notifications.js 2016-11-14 01:59:28.000000000 +0000 @@ -161,8 +161,8 @@ add_task(function* update_move_same_folder() { // Ensure there are at least two items in place (others test do so for us, // but we don't have to depend on that). - let sep = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_SEPARATOR, - parentGuid: PlacesUtils.bookmarks.unfiledGuid }); + yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_SEPARATOR, + parentGuid: PlacesUtils.bookmarks.unfiledGuid }); let bm = yield PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_BOOKMARK, parentGuid: PlacesUtils.bookmarks.unfiledGuid, url: new URL("http://move.example.com/") }); @@ -270,7 +270,7 @@ let tagParentId = yield PlacesUtils.promiseItemId(tag.parentGuid); let observer = expectNotifications(); - let removed = yield PlacesUtils.bookmarks.remove(tag.guid); + yield PlacesUtils.bookmarks.remove(tag.guid); observer.check([ { name: "onItemRemoved", arguments: [ tagId, tagParentId, tag.index, tag.type, diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_bookmarks_remove.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_bookmarks_remove.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_bookmarks_remove.js 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_bookmarks_remove.js 2016-11-14 01:59:28.000000000 +0000 @@ -192,9 +192,9 @@ let folder1 = yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid, type: PlacesUtils.bookmarks.TYPE_FOLDER, title: "a folder" }); - let folder2 = yield PlacesUtils.bookmarks.insert({ parentGuid: folder1.guid, - type: PlacesUtils.bookmarks.TYPE_FOLDER, - title: "a folder" }); + yield PlacesUtils.bookmarks.insert({ parentGuid: folder1.guid, + type: PlacesUtils.bookmarks.TYPE_FOLDER, + title: "a folder" }); yield Assert.rejects(PlacesUtils.bookmarks.remove(folder1, {preventRemovalOfNonEmptyFolders: true}), /Cannot remove a non-empty folder./); }); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_keywords.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_keywords.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/bookmarks/test_keywords.js 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/bookmarks/test_keywords.js 2016-11-14 01:59:28.000000000 +0000 @@ -275,7 +275,6 @@ }); add_task(function* test_addRemoveBookmark() { - let fc = yield foreign_count(URI3); let observer = expectNotifications(); let itemId = diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/browser/browser_favicon_setAndFetchFaviconForPage_failures.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/browser/browser_favicon_setAndFetchFaviconForPage_failures.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/browser/browser_favicon_setAndFetchFaviconForPage_failures.js 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/browser/browser_favicon_setAndFetchFaviconForPage_failures.js 2016-11-14 01:59:29.000000000 +0000 @@ -41,7 +41,7 @@ let stmt = DBConn().createAsyncStatement("SELECT url FROM moz_favicons"); stmt.executeAsync({ handleResult: function final_handleResult(aResultSet) { - for (let row; (row = aResultSet.getNextRow()); ) { + while (aResultSet.getNextRow()) { favIconsResultCount++; } }, @@ -142,7 +142,6 @@ function testErrorIcon(aWindow, aCallback) { let pageURI = NetUtil.newURI("http://example.com/errorIcon"); - let places = [{ uri: pageURI, transition: TRANSITION_TYPED }]; addVisits({ uri: pageURI, transition: TRANSITION_TYPED }, aWindow, function () { aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI, diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/browser/browser_favicon_setAndFetchFaviconForPage.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/browser/browser_favicon_setAndFetchFaviconForPage.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/browser/browser_favicon_setAndFetchFaviconForPage.js 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/browser/browser_favicon_setAndFetchFaviconForPage.js 2016-11-14 01:59:29.000000000 +0000 @@ -7,7 +7,6 @@ // Initialization waitForExplicitFinish(); let windowsToClose = []; - let testURI = "https://www.mozilla.org/en-US/"; let favIconLocation = "http://example.org/tests/toolkit/components/places/tests/browser/favicon-normal32.png"; let favIconURI = NetUtil.newURI(favIconLocation); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/browser/browser_visituri_privatebrowsing_perwindowpb.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/browser/browser_visituri_privatebrowsing_perwindowpb.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/browser/browser_visituri_privatebrowsing_perwindowpb.js 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/browser/browser_visituri_privatebrowsing_perwindowpb.js 2016-11-14 01:59:29.000000000 +0000 @@ -6,7 +6,6 @@ // initialization waitForExplicitFinish(); let windowsToClose = []; - let testURI = "https://www.mozilla.org/en-US/"; let initialURL = "http://example.com/tests/toolkit/components/places/tests/browser/begin.html"; let finalURL = diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/browser/head.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/browser/head.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/browser/head.js 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/browser/head.js 2016-11-14 01:59:29.000000000 +0000 @@ -125,7 +125,6 @@ * The stack frame used to report errors. */ function addVisits(aPlaceInfo, aWindow, aCallback, aStack) { - let stack = aStack || Components.stack.caller; let places = []; if (aPlaceInfo instanceof Ci.nsIURI) { places.push({ uri: aPlaceInfo }); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/favicons/test_expireAllFavicons.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/favicons/test_expireAllFavicons.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/favicons/test_expireAllFavicons.js 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/favicons/test_expireAllFavicons.js 2016-11-14 01:59:29.000000000 +0000 @@ -8,8 +8,6 @@ const BOOKMARKED_PAGE_URI = NetUtil.newURI("http://example.com/bookmarked"); add_task(function* test_expireAllFavicons() { - const {FAVICON_LOAD_NON_PRIVATE} = PlacesUtils.favicons; - // Add a visited page. yield PlacesTestUtils.addVisits({ uri: TEST_PAGE_URI, transition: TRANSITION_TYPED }); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/favicons/test_moz-anno_favicon_mime_type.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/favicons/test_moz-anno_favicon_mime_type.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/favicons/test_moz-anno_favicon_mime_type.js 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/favicons/test_moz-anno_favicon_mime_type.js 2016-11-14 01:59:29.000000000 +0000 @@ -52,8 +52,6 @@ { let fs = Cc["@mozilla.org/browser/favicon-service;1"]. getService(Ci.nsIFaviconService); - let ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); // Test that the default icon has the content type of image/png. let channel = NetUtil.newChannel({ diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/favicons/test_query_result_favicon_changed_on_child.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/favicons/test_query_result_favicon_changed_on_child.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/favicons/test_query_result_favicon_changed_on_child.js 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/favicons/test_query_result_favicon_changed_on_child.js 2016-11-14 01:59:29.000000000 +0000 @@ -9,7 +9,7 @@ add_task(function* test_query_result_favicon_changed_on_child() { // Bookmark our test page, so it will appear in the query resultset. - let testBookmark = yield PlacesUtils.bookmarks.insert({ + yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.menuGuid, title: "test_bookmark", url: PAGE_URI diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/head_common.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/head_common.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/head_common.js 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/head_common.js 2016-11-14 01:59:29.000000000 +0000 @@ -509,7 +509,6 @@ let bookmarksBackupDir = gProfD.clone(); bookmarksBackupDir.append("bookmarkbackups"); let files = bookmarksBackupDir.directoryEntries; - let backup_date = PlacesBackups.toISODateString(new Date()); while (files.hasMoreElements()) { let entry = files.getNext().QueryInterface(Ci.nsIFile); if (PlacesBackups.filenamesRegex.test(entry.leafName)) { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/history/test_insert.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/history/test_insert.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/history/test_insert.js 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/history/test_insert.js 2016-11-14 01:59:29.000000000 +0000 @@ -8,13 +8,6 @@ add_task(function* test_insert_error_cases() { const TEST_URL = "http://mozilla.com"; - let validPageInfo = { - url: TEST_URL, - visits: [ - {transition: TRANSITION_LINK} - ] - }; - Assert.throws( () => PlacesUtils.history.insert(), /TypeError: pageInfo must be an object/, diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/history/test_remove.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/history/test_remove.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/history/test_remove.js 2016-11-11 02:00:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/history/test_remove.js 2016-11-14 01:59:29.000000000 +0000 @@ -154,7 +154,6 @@ let uri = NetUtil.newURI("http://mozilla.com/test_browserhistory/test_remove?sample=" + i + "&salt=" + Math.random()); let title = "Visit " + i + ", " + Math.random(); let hasBookmark = i % 3 == 0; - let resolve; let page = { uri: uri, title: title, diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/queries/head_queries.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/queries/head_queries.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/queries/head_queries.js 2016-11-11 02:01:29.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/queries/head_queries.js 2016-11-14 01:59:30.000000000 +0000 @@ -164,7 +164,7 @@ data.lastModified = new Date(qdata.lastModified / 1000); } - let item = yield PlacesUtils.bookmarks.insert(data); + yield PlacesUtils.bookmarks.insert(data); if (qdata.keyword) { yield PlacesUtils.keywords.insert({ url: qdata.uri, diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/queries/test_tags.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/queries/test_tags.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/queries/test_tags.js 2016-11-11 02:01:30.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/queries/test_tags.js 2016-11-14 01:59:30.000000000 +0000 @@ -13,21 +13,21 @@ add_task(function* tags_getter_setter() { do_print("Tags getter/setter should work correctly"); do_print("Without setting tags, tags getter should return empty array"); - var [query, dummy] = makeQuery(); + var [query] = makeQuery(); do_check_eq(query.tags.length, 0); do_print("Setting tags to an empty array, tags getter should return "+ "empty array"); - [query, dummy] = makeQuery([]); + [query] = makeQuery([]); do_check_eq(query.tags.length, 0); do_print("Setting a few tags, tags getter should return correct array"); var tags = ["bar", "baz", "foo"]; - [query, dummy] = makeQuery(tags); + [query] = makeQuery(tags); setsAreEqual(query.tags, tags, true); do_print("Setting some dupe tags, tags getter return unique tags"); - [query, dummy] = makeQuery(["foo", "foo", "bar", "foo", "baz", "bar"]); + [query] = makeQuery(["foo", "foo", "bar", "foo", "baz", "bar"]); setsAreEqual(query.tags, ["bar", "baz", "foo"], true); }); @@ -417,7 +417,7 @@ title: tagName }); - let bm = yield PlacesUtils.bookmarks.insert({ + yield PlacesUtils.bookmarks.insert({ parentGuid: dupTag.guid, title: "title", url: TEST_URI @@ -442,7 +442,7 @@ PlacesUtils.tagging.tagURI(TEST_URI, [tagName]); do_print("Create folder with same name as tag"); - let folder = yield PlacesUtils.bookmarks.insert({ + yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid, type: PlacesUtils.bookmarks.TYPE_FOLDER, title: tagName @@ -481,40 +481,40 @@ do_print("Query for /1 OR query for /2 should match both /1 and /2"); var [query1, opts] = makeQuery(urisAndTags["http://example.com/1"]); - var [query2, dummy] = makeQuery(urisAndTags["http://example.com/2"]); + var [query2] = makeQuery(urisAndTags["http://example.com/2"]); var root = PlacesUtils.history.executeQueries([query1, query2], 2, opts).root; queryResultsAre(root, ["http://example.com/1", "http://example.com/2"]); do_print("Query for /1 OR query on bogus tag should match only /1"); [query1, opts] = makeQuery(urisAndTags["http://example.com/1"]); - [query2, dummy] = makeQuery(["bogus"]); + [query2] = makeQuery(["bogus"]); root = PlacesUtils.history.executeQueries([query1, query2], 2, opts).root; queryResultsAre(root, ["http://example.com/1"]); do_print("Query for /1 OR query for /1 should match only /1"); [query1, opts] = makeQuery(urisAndTags["http://example.com/1"]); - [query2, dummy] = makeQuery(urisAndTags["http://example.com/1"]); + [query2] = makeQuery(urisAndTags["http://example.com/1"]); root = PlacesUtils.history.executeQueries([query1, query2], 2, opts).root; queryResultsAre(root, ["http://example.com/1"]); do_print("Query for /1 with tagsAreNot OR query for /2 with tagsAreNot " + "should match both /1 and /2"); [query1, opts] = makeQuery(urisAndTags["http://example.com/1"], true); - [query2, dummy] = makeQuery(urisAndTags["http://example.com/2"], true); + [query2] = makeQuery(urisAndTags["http://example.com/2"], true); root = PlacesUtils.history.executeQueries([query1, query2], 2, opts).root; queryResultsAre(root, ["http://example.com/1", "http://example.com/2"]); do_print("Query for /1 OR query for /2 with tagsAreNot should match " + "only /1"); [query1, opts] = makeQuery(urisAndTags["http://example.com/1"]); - [query2, dummy] = makeQuery(urisAndTags["http://example.com/2"], true); + [query2] = makeQuery(urisAndTags["http://example.com/2"], true); root = PlacesUtils.history.executeQueries([query1, query2], 2, opts).root; queryResultsAre(root, ["http://example.com/1"]); do_print("Query for /1 OR query for /1 with tagsAreNot should match " + "both URIs"); [query1, opts] = makeQuery(urisAndTags["http://example.com/1"]); - [query2, dummy] = makeQuery(urisAndTags["http://example.com/1"], true); + [query2] = makeQuery(urisAndTags["http://example.com/1"], true); root = PlacesUtils.history.executeQueries([query1, query2], 2, opts).root; queryResultsAre(root, ["http://example.com/1", "http://example.com/2"]); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unifiedcomplete/head_autocomplete.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unifiedcomplete/head_autocomplete.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unifiedcomplete/head_autocomplete.js 2016-11-11 02:01:30.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unifiedcomplete/head_autocomplete.js 2016-11-14 01:59:30.000000000 +0000 @@ -111,7 +111,7 @@ // A helper for check_autocomplete to check a specific match against data from // the controller. function _check_autocomplete_matches(match, result) { - let { uri, title, tags, searchEngine, style } = match; + let { uri, title, tags, style } = match; if (tags) title += " \u2013 " + tags.sort().join(", "); if (style) @@ -167,20 +167,21 @@ do_print("onSearchBegin received"); numSearchesStarted++; }; - let deferred = Promise.defer(); - input.onSearchComplete = () => { - do_print("onSearchComplete received"); - deferred.resolve(); - } - + let searchCompletePromise = new Promise(resolve => { + input.onSearchComplete = () => { + do_print("onSearchComplete received"); + resolve(); + } + }); let expectedSearches = 1; if (test.incompleteSearch) { controller.startSearch(test.incompleteSearch); expectedSearches++; } + do_print("Searching for: '" + test.search + "'"); controller.startSearch(test.search); - yield deferred.promise; + yield searchCompletePromise; Assert.equal(numSearchesStarted, expectedSearches, "All searches started"); @@ -271,7 +272,7 @@ title: aBookmarkObj.title || "A bookmark", url: aBookmarkObj.uri }); - let itemId = yield PlacesUtils.promiseItemId(bm.guid); + yield PlacesUtils.promiseItemId(bm.guid); if (aBookmarkObj.keyword) { yield PlacesUtils.keywords.insert({ keyword: aBookmarkObj.keyword, @@ -285,19 +286,19 @@ } }); -function addOpenPages(aUri, aCount=1) { +function addOpenPages(aUri, aCount=1, aUserContextId=0) { let ac = Cc["@mozilla.org/autocomplete/search;1?name=unifiedcomplete"] .getService(Ci.mozIPlacesAutoComplete); for (let i = 0; i < aCount; i++) { - ac.registerOpenPage(aUri); + ac.registerOpenPage(aUri, aUserContextId); } } -function removeOpenPages(aUri, aCount=1) { +function removeOpenPages(aUri, aCount=1, aUserContextId=0) { let ac = Cc["@mozilla.org/autocomplete/search;1?name=unifiedcomplete"] .getService(Ci.mozIPlacesAutoComplete); for (let i = 0; i < aCount; i++) { - ac.unregisterOpenPage(aUri); + ac.unregisterOpenPage(aUri, aUserContextId); } } @@ -415,6 +416,22 @@ } } +function makeExtensionMatch(extra = {}) { + let style = [ "action", "extension" ]; + if (extra.heuristic) { + style.push("heuristic"); + } + + return { + uri: makeActionURI("extension", { + content: extra.content, + keyword: extra.keyword, + }), + title: extra.description, + style, + }; +} + function setFaviconForHref(href, iconHref) { return new Promise(resolve => { PlacesUtils.favicons.setAndFetchFaviconForPage( diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unifiedcomplete/test_extension_matches.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unifiedcomplete/test_extension_matches.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unifiedcomplete/test_extension_matches.js 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unifiedcomplete/test_extension_matches.js 2016-11-14 01:59:31.000000000 +0000 @@ -0,0 +1,384 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- + * vim:set ts=2 sw=2 sts=2 et: + * 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/. */ + +Cu.import("resource://gre/modules/ExtensionSearchHandler.jsm"); + +let controller = Cc["@mozilla.org/autocomplete/controller;1"].getService(Ci.nsIAutoCompleteController); + +add_task(function* test_correct_errors_are_thrown() { + let keyword = "foo"; + let anotherKeyword = "bar"; + let unregisteredKeyword = "baz"; + + // Register a keyword. + ExtensionSearchHandler.registerKeyword(keyword, { emit: () => {} }); + + // Try registering the keyword again. + Assert.throws(() => ExtensionSearchHandler.registerKeyword(keyword, { emit: () => {} })); + + // Register a different keyword. + ExtensionSearchHandler.registerKeyword(anotherKeyword, { emit: () => {} }); + + // Try calling handleSearch for an unregistered keyword. + Assert.throws(() => ExtensionSearchHandler.handleSearch(unregisteredKeyword, `${unregisteredKeyword} `, () => {})); + + // Try calling handleSearch without a callback. + Assert.throws(() => ExtensionSearchHandler.handleSearch(unregisteredKeyword, `${unregisteredKeyword} `)); + + // Try getting the description for a keyword which isn't registered. + Assert.throws(() => ExtensionSearchHandler.getDescription(unregisteredKeyword)); + + // Try getting the extension name for a keyword which isn't registered. + Assert.throws(() => ExtensionSearchHandler.getExtensionName(unregisteredKeyword)); + + // Try setting the default suggestion for a keyword which isn't registered. + Assert.throws(() => ExtensionSearchHandler.setDefaultSuggestion(unregisteredKeyword, "suggestion")); + + // Try calling handleInputCancelled when there is no active input session. + Assert.throws(() => ExtensionSearchHandler.handleInputCancelled()); + + // Try calling handleInputEntered when there is no active input session. + Assert.throws(() => ExtensionSearchHandler.handleInputEntered(anotherKeyword, `${anotherKeyword} test`, "tab")); + + // Start a session by calling handleSearch with the registered keyword. + ExtensionSearchHandler.handleSearch(keyword, `${keyword} test`, () => {}); + + // Try providing suggestions for an unregistered keyword. + Assert.throws(() => ExtensionSearchHandler.addSuggestions(unregisteredKeyword, 0, [])); + + // Try providing suggestions for an inactive keyword. + Assert.throws(() => ExtensionSearchHandler.addSuggestions(anotherKeyword, 0, [])); + + // Try calling handleSearch for an inactive keyword. + Assert.throws(() => ExtensionSearchHandler.handleSearch(anotherKeyword, `${anotherKeyword} `, () => {})); + + // Try calling addSuggestions with an old callback ID. + Assert.throws(() => ExtensionSearchHandler.addSuggestions(keyword, 0, [])); + + // Add suggestions with a valid callback ID. + ExtensionSearchHandler.addSuggestions(keyword, 1, []); + + // Add suggestions again with a valid callback ID. + ExtensionSearchHandler.addSuggestions(keyword, 1, []); + + // Try calling addSuggestions with a future callback ID. + Assert.throws(() => ExtensionSearchHandler.addSuggestions(keyword, 2, [])); + + // End the input session by calling handleInputCancelled. + ExtensionSearchHandler.handleInputCancelled(); + + // Try calling handleInputCancelled after the session has ended. + Assert.throws(() => ExtensionSearchHandler.handleInputCancelled()); + + // Try calling handleSearch that doesn't have a space after the keyword. + Assert.throws(() => ExtensionSearchHandler.handleSearch(anotherKeyword, `${anotherKeyword}`, () => {})); + + // Try calling handleSearch with text starting with the wrong keyword. + Assert.throws(() => ExtensionSearchHandler.handleSearch(anotherKeyword, `${keyword} test`, () => {})); + + // Start a new session by calling handleSearch with a different keyword + ExtensionSearchHandler.handleSearch(anotherKeyword, `${anotherKeyword} test`, () => {}); + + // Try adding suggestions again with the same callback ID now that the input session has ended. + Assert.throws(() => ExtensionSearchHandler.addSuggestions(keyword, 1, [])); + + // Add suggestions with a valid callback ID. + ExtensionSearchHandler.addSuggestions(anotherKeyword, 2, []); + + // Try adding suggestions with a valid callback ID but a different keyword. + Assert.throws(() => ExtensionSearchHandler.addSuggestions(keyword, 2, [])); + + // Try adding suggestions with a valid callback ID but an unregistered keyword. + Assert.throws(() => ExtensionSearchHandler.addSuggestions(unregisteredKeyword, 2, [])); + + // Set the default suggestion. + ExtensionSearchHandler.setDefaultSuggestion(anotherKeyword, {description: "test result"}); + + // Try ending the session using handleInputEntered with a different keyword. + Assert.throws(() => ExtensionSearchHandler.handleInputEntered(keyword, `${keyword} test`, "tab")); + + // Try calling handleInputEntered with invalid text. + Assert.throws(() => ExtensionSearchHandler.handleInputEntered(anotherKeyword, ` test`, "tab")); + + // Try calling handleInputEntered with an invalid disposition. + Assert.throws(() => ExtensionSearchHandler.handleInputEntered(anotherKeyword, `${anotherKeyword} test`, "invalid")); + + // End the session by calling handleInputEntered. + ExtensionSearchHandler.handleInputEntered(anotherKeyword, `${anotherKeyword} test`, "tab"); + + // Try calling handleInputEntered after the session has ended. + Assert.throws(() => ExtensionSearchHandler.handleInputEntered(anotherKeyword, `${anotherKeyword} test`, "tab")); + + // Unregister the keyword. + ExtensionSearchHandler.unregisterKeyword(keyword); + + // Try setting the default suggestion for the unregistered keyword. + Assert.throws(() => ExtensionSearchHandler.setDefaultSuggestion(keyword, {description: "test"})); + + // Try handling a search with the unregistered keyword. + Assert.throws(() => ExtensionSearchHandler.handleSearch(keyword, `${keyword} test`, () => {})); + + // Try unregistering the keyword again. + Assert.throws(() => ExtensionSearchHandler.unregisterKeyword(keyword)); + + // Unregister the other keyword. + ExtensionSearchHandler.unregisterKeyword(anotherKeyword); + + // Try unregistering the word which was never registered. + Assert.throws(() => ExtensionSearchHandler.unregisterKeyword(unregisteredKeyword)); + + // Try setting the default suggestion for a word that was never registered. + Assert.throws(() => ExtensionSearchHandler.setDefaultSuggestion(unregisteredKeyword, {description: "test"})); + + yield cleanup(); +}); + +add_task(function* test_correct_events_are_emitted() { + let events = []; + function checkEvents(expectedEvents) { + Assert.equal(events.length, expectedEvents.length, "The correct number of events fired"); + expectedEvents.forEach((e, i) => Assert.equal(e, events[i], `Expected "${e}" event to fire`)); + events = []; + } + + let mockExtension = { emit: message => events.push(message) }; + + let keyword = "foo"; + let anotherKeyword = "bar"; + + ExtensionSearchHandler.registerKeyword(keyword, mockExtension); + ExtensionSearchHandler.registerKeyword(anotherKeyword, mockExtension); + + ExtensionSearchHandler.handleSearch(keyword, `${keyword} `, () => {}); + checkEvents([ExtensionSearchHandler.MSG_INPUT_STARTED]); + + ExtensionSearchHandler.handleSearch(keyword, `${keyword} f`, () => {}); + checkEvents([ExtensionSearchHandler.MSG_INPUT_CHANGED]); + + ExtensionSearchHandler.handleInputEntered(keyword, `${keyword} f`, "tab"); + checkEvents([ExtensionSearchHandler.MSG_INPUT_ENTERED]); + + ExtensionSearchHandler.handleSearch(keyword, `${keyword} f`, () => {}); + checkEvents([ + ExtensionSearchHandler.MSG_INPUT_STARTED, + ExtensionSearchHandler.MSG_INPUT_CHANGED + ]); + + ExtensionSearchHandler.handleInputCancelled(); + checkEvents([ExtensionSearchHandler.MSG_INPUT_CANCELLED]); + + ExtensionSearchHandler.handleSearch(anotherKeyword, `${anotherKeyword} baz`, () => {}); + checkEvents([ + ExtensionSearchHandler.MSG_INPUT_STARTED, + ExtensionSearchHandler.MSG_INPUT_CHANGED + ]); + + ExtensionSearchHandler.handleInputEntered(anotherKeyword, `${anotherKeyword} baz`, "tab"); + checkEvents([ExtensionSearchHandler.MSG_INPUT_ENTERED]); + + ExtensionSearchHandler.unregisterKeyword(keyword); +}); + +add_task(function* test_removes_suggestion_if_its_content_is_typed_in() { + let keyword = "test"; + let extensionName = "Foo Bar"; + + let mockExtension = { + name: extensionName, + emit(message, text, id) { + if (message === ExtensionSearchHandler.MSG_INPUT_CHANGED) { + ExtensionSearchHandler.addSuggestions(keyword, id, [ + {content: "foo", description: "first suggestion"}, + {content: "bar", description: "second suggestion"}, + {content: "baz", description: "third suggestion"}, + ]); + controller.stopSearch(); + } + } + }; + + ExtensionSearchHandler.registerKeyword(keyword, mockExtension); + + yield check_autocomplete({ + search: `${keyword} unmatched`, + searchParam: "enable-actions", + matches: [ + makeExtensionMatch({heuristic: true, keyword, description: extensionName, content: `${keyword} unmatched`}), + makeExtensionMatch({keyword, content: `${keyword} foo`, description: "first suggestion"}), + makeExtensionMatch({keyword, content: `${keyword} bar`, description: "second suggestion"}), + makeExtensionMatch({keyword, content: `${keyword} baz`, description: "third suggestion"}) + ] + }); + + yield check_autocomplete({ + search: `${keyword} foo`, + searchParam: "enable-actions", + matches: [ + makeExtensionMatch({heuristic: true, keyword, description: extensionName, content: `${keyword} foo`}), + makeExtensionMatch({keyword, content: `${keyword} bar`, description: "second suggestion"}), + makeExtensionMatch({keyword, content: `${keyword} baz`, description: "third suggestion"}) + ] + }); + + yield check_autocomplete({ + search: `${keyword} bar`, + searchParam: "enable-actions", + matches: [ + makeExtensionMatch({heuristic: true, keyword, description: extensionName, content: `${keyword} bar`}), + makeExtensionMatch({keyword, content: `${keyword} foo`, description: "first suggestion"}), + makeExtensionMatch({keyword, content: `${keyword} baz`, description: "third suggestion"}) + ] + }); + + yield check_autocomplete({ + search: `${keyword} baz`, + searchParam: "enable-actions", + matches: [ + makeExtensionMatch({heuristic: true, keyword, description: extensionName, content: `${keyword} baz`}), + makeExtensionMatch({keyword, content: `${keyword} foo`, description: "first suggestion"}), + makeExtensionMatch({keyword, content: `${keyword} bar`, description: "second suggestion"}) + ] + }); + + ExtensionSearchHandler.unregisterKeyword(keyword); + yield cleanup(); +}); + +add_task(function* test_extension_results_should_come_first() { + let keyword = "test"; + let extensionName = "Omnibox Example"; + + let uri = NetUtil.newURI(`http://a.com/b`); + yield PlacesTestUtils.addVisits([ + { uri, title: `${keyword} -` }, + ]); + + let mockExtension = { + name: extensionName, + emit(message, text, id) { + if (message === ExtensionSearchHandler.MSG_INPUT_CHANGED) { + ExtensionSearchHandler.addSuggestions(keyword, id, [ + {content: "foo", description: "first suggestion"}, + {content: "bar", description: "second suggestion"}, + {content: "baz", description: "third suggestion"}, + ]); + } + controller.stopSearch(); + } + }; + + ExtensionSearchHandler.registerKeyword(keyword, mockExtension); + + // Start an input session before testing MSG_INPUT_CHANGED. + ExtensionSearchHandler.handleSearch(keyword, `${keyword} `, () => {}); + + yield check_autocomplete({ + search: `${keyword} -`, + searchParam: "enable-actions", + matches: [ + makeExtensionMatch({heuristic: true, keyword, description: extensionName, content: `${keyword} -`}), + makeExtensionMatch({keyword, content: `${keyword} foo`, description: "first suggestion"}), + makeExtensionMatch({keyword, content: `${keyword} bar`, description: "second suggestion"}), + makeExtensionMatch({keyword, content: `${keyword} baz`, description: "third suggestion"}), + { uri, title: `${keyword} -` } + ] + }); + + ExtensionSearchHandler.unregisterKeyword(keyword); + yield cleanup(); +}); + +add_task(function* test_setting_the_default_suggestion() { + let keyword = "test"; + let extensionName = "Omnibox Example"; + + let mockExtension = { + name: extensionName, + emit(message, text, id) { + if (message === ExtensionSearchHandler.MSG_INPUT_CHANGED) { + ExtensionSearchHandler.addSuggestions(keyword, id, []); + } + controller.stopSearch(); + } + }; + + ExtensionSearchHandler.registerKeyword(keyword, mockExtension); + + ExtensionSearchHandler.setDefaultSuggestion(keyword, { + description: "hello world" + }); + + let searchString = `${keyword} search query`; + yield check_autocomplete({ + search: searchString, + searchParam: "enable-actions", + matches: [ + makeExtensionMatch({heuristic: true, keyword, description: "hello world", content: searchString}), + ] + }); + + ExtensionSearchHandler.setDefaultSuggestion(keyword, { + description: "foo bar" + }); + + yield check_autocomplete({ + search: searchString, + searchParam: "enable-actions", + matches: [ + makeExtensionMatch({heuristic: true, keyword, description: "foo bar", content: searchString}), + ] + }); + + ExtensionSearchHandler.unregisterKeyword(keyword); + yield cleanup(); +}); + +add_task(function* test_maximum_number_of_suggestions_is_enforced() { + let keyword = "test"; + let extensionName = "Omnibox Example"; + + let mockExtension = { + name: extensionName, + emit(message, text, id) { + if (message === ExtensionSearchHandler.MSG_INPUT_CHANGED) { + ExtensionSearchHandler.addSuggestions(keyword, id, [ + {content: "a", description: "first suggestion"}, + {content: "b", description: "second suggestion"}, + {content: "c", description: "third suggestion"}, + {content: "d", description: "fourth suggestion"}, + {content: "e", description: "fifth suggestion"}, + {content: "f", description: "sixth suggestion"}, + {content: "g", description: "seventh suggestion"}, + {content: "h", description: "eigth suggestion"}, + {content: "i", description: "ninth suggestion"}, + {content: "j", description: "tenth suggestion"}, + ]); + controller.stopSearch(); + } + } + }; + + ExtensionSearchHandler.registerKeyword(keyword, mockExtension); + + // Start an input session before testing MSG_INPUT_CHANGED. + ExtensionSearchHandler.handleSearch(keyword, `${keyword} `, () => {}); + + yield check_autocomplete({ + search: `${keyword} #`, + searchParam: "enable-actions", + matches: [ + makeExtensionMatch({heuristic: true, keyword, description: extensionName, content: `${keyword} #`}), + makeExtensionMatch({keyword, content: `${keyword} a`, description: "first suggestion"}), + makeExtensionMatch({keyword, content: `${keyword} b`, description: "second suggestion"}), + makeExtensionMatch({keyword, content: `${keyword} c`, description: "third suggestion"}), + makeExtensionMatch({keyword, content: `${keyword} d`, description: "fourth suggestion"}), + makeExtensionMatch({keyword, content: `${keyword} e`, description: "fifth suggestion"}), + ] + }); + + ExtensionSearchHandler.unregisterKeyword(keyword); + yield cleanup(); +}); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unifiedcomplete/test_tab_matches.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unifiedcomplete/test_tab_matches.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unifiedcomplete/test_tab_matches.js 2016-11-11 02:01:31.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unifiedcomplete/test_tab_matches.js 2016-11-14 01:59:31.000000000 +0000 @@ -11,9 +11,11 @@ let uri2 = NetUtil.newURI("http://xyz.net/"); let uri3 = NetUtil.newURI("about:mozilla"); let uri4 = NetUtil.newURI("data:text/html,test"); + let uri5 = NetUtil.newURI("http://foobar.org"); yield PlacesTestUtils.addVisits([ { uri: uri1, title: "ABC rocks" }, - { uri: uri2, title: "xyz.net - we're better than ABC" } + { uri: uri2, title: "xyz.net - we're better than ABC" }, + { uri: uri5, title: "foobar.org - much better than ABC, definitely better than XYZ" } ]); addOpenPages(uri1, 1); // Pages that cannot be registered in history. @@ -35,7 +37,8 @@ searchParam: "enable-actions", matches: [ makeSearchMatch("abc", { heuristic: true }), makeSwitchToTabMatch("http://abc.com/", { title: "ABC rocks" }), - { uri: uri2, title: "xyz.net - we're better than ABC", style: [ "favicon" ] } ] + { uri: uri2, title: "xyz.net - we're better than ABC", style: [ "favicon" ] }, + { uri: uri5, title: "foobar.org - much better than ABC, definitely better than XYZ", style: [ "favicon" ] } ] }); do_print("three results, both normal results are tab matches"); @@ -45,7 +48,39 @@ searchParam: "enable-actions", matches: [ makeSearchMatch("abc", { heuristic: true }), makeSwitchToTabMatch("http://abc.com/", { title: "ABC rocks" }), - makeSwitchToTabMatch("http://xyz.net/", { title: "xyz.net - we're better than ABC" }) ] + makeSwitchToTabMatch("http://xyz.net/", { title: "xyz.net - we're better than ABC" }), + { uri: uri5, title: "foobar.org - much better than ABC, definitely better than XYZ", style: [ "favicon" ] } ] + }); + + do_print("a container tab is not visible in 'switch to tab'"); + addOpenPages(uri5, 1, /* userContextId: */ 3); + yield check_autocomplete({ + search: "abc", + searchParam: "enable-actions", + matches: [ makeSearchMatch("abc", { heuristic: true }), + makeSwitchToTabMatch("http://abc.com/", { title: "ABC rocks" }), + makeSwitchToTabMatch("http://xyz.net/", { title: "xyz.net - we're better than ABC" }), + { uri: uri5, title: "foobar.org - much better than ABC, definitely better than XYZ", style: [ "favicon" ] } ] + }); + + do_print("a container tab should not see 'switch to tab' for other container tabs"); + yield check_autocomplete({ + search: "abc", + searchParam: "enable-actions user-context-id:3", + matches: [ makeSearchMatch("abc", { heuristic: true }), + makeSwitchToTabMatch("http://foobar.org/", { title: "foobar.org - much better than ABC, definitely better than XYZ" }), + { uri: uri1, title: "ABC rocks", style: [ "favicon" ] }, + { uri: uri2, title: "xyz.net - we're better than ABC", style: [ "favicon" ] } ] + }); + + do_print("a different container tab should not see any 'switch to tab'"); + yield check_autocomplete({ + search: "abc", + searchParam: "enable-actions user-context-id:2", + matches: [ makeSearchMatch("abc", { heuristic: true }), + { uri: uri1, title: "ABC rocks", style: [ "favicon" ] }, + { uri: uri2, title: "xyz.net - we're better than ABC", style: [ "favicon" ] }, + { uri: uri5, title: "foobar.org - much better than ABC, definitely better than XYZ", style: [ "favicon" ] } ] }); do_print("three results, both normal results are tab matches, one has multiple tabs"); @@ -55,7 +90,8 @@ searchParam: "enable-actions", matches: [ makeSearchMatch("abc", { heuristic: true }), makeSwitchToTabMatch("http://abc.com/", { title: "ABC rocks" }), - makeSwitchToTabMatch("http://xyz.net/", { title: "xyz.net - we're better than ABC" }) ] + makeSwitchToTabMatch("http://xyz.net/", { title: "xyz.net - we're better than ABC" }), + { uri: uri5, title: "foobar.org - much better than ABC, definitely better than XYZ", style: [ "favicon" ] } ] }); do_print("three results, no tab matches (disable-private-actions)"); @@ -64,7 +100,8 @@ searchParam: "enable-actions disable-private-actions", matches: [ makeSearchMatch("abc", { heuristic: true }), { uri: uri1, title: "ABC rocks", style: [ "favicon" ] }, - { uri: uri2, title: "xyz.net - we're better than ABC", style: [ "favicon" ] } ] + { uri: uri2, title: "xyz.net - we're better than ABC", style: [ "favicon" ] }, + { uri: uri5, title: "foobar.org - much better than ABC, definitely better than XYZ", style: [ "favicon" ] } ] }); do_print("two results (actions disabled)"); @@ -72,7 +109,8 @@ search: "abc", searchParam: "", matches: [ { uri: uri1, title: "ABC rocks", style: [ "favicon" ] }, - { uri: uri2, title: "xyz.net - we're better than ABC", style: [ "favicon" ] } ] + { uri: uri2, title: "xyz.net - we're better than ABC", style: [ "favicon" ] }, + { uri: uri5, title: "foobar.org - much better than ABC, definitely better than XYZ", style: [ "favicon" ] } ] }); do_print("three results, no tab matches"); @@ -83,7 +121,8 @@ searchParam: "enable-actions", matches: [ makeSearchMatch("abc", { heuristic: true }), { uri: uri1, title: "ABC rocks", style: [ "favicon" ] }, - { uri: uri2, title: "xyz.net - we're better than ABC", style: [ "favicon" ] } ] + { uri: uri2, title: "xyz.net - we're better than ABC", style: [ "favicon" ] }, + { uri: uri5, title: "foobar.org - much better than ABC, definitely better than XYZ", style: [ "favicon" ] } ] }); do_print("tab match search with restriction character"); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unifiedcomplete/xpcshell.ini firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unifiedcomplete/xpcshell.ini --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unifiedcomplete/xpcshell.ini 2016-11-11 02:01:31.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unifiedcomplete/xpcshell.ini 2016-11-14 01:59:31.000000000 +0000 @@ -24,6 +24,7 @@ [test_empty_search.js] [test_enabled.js] [test_escape_self.js] +[test_extension_matches.js] [test_ignore_protocol.js] [test_keyword_search.js] [test_keyword_search_actions.js] diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_000_frecency.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_000_frecency.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_000_frecency.js 2016-11-11 02:01:40.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_000_frecency.js 2016-11-14 01:59:31.000000000 +0000 @@ -56,7 +56,7 @@ function* task_initializeBucket(bucket) { let [cutoffName, weightName] = bucket; // get pref values - var weight = 0, cutoff = 0, bonus = 0; + var weight = 0, cutoff = 0; try { weight = prefs.getIntPref(prefPrefix + weightName); } catch (ex) {} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_317472.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_317472.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_317472.js 2016-11-11 02:01:40.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_317472.js 2016-11-14 01:59:31.000000000 +0000 @@ -22,11 +22,11 @@ yield PlacesTestUtils.addVisits(TEST_BOOKMARKED_URI); // create bookmarks on TEST_BOOKMARKED_URI - var bm1 = PlacesUtils.bookmarks.insertBookmark( + PlacesUtils.bookmarks.insertBookmark( PlacesUtils.unfiledBookmarksFolderId, TEST_BOOKMARKED_URI, PlacesUtils.bookmarks.DEFAULT_INDEX, TEST_BOOKMARKED_URI.spec); - var bm2 = PlacesUtils.bookmarks.insertBookmark( + PlacesUtils.bookmarks.insertBookmark( PlacesUtils.toolbarFolderId, TEST_BOOKMARKED_URI, PlacesUtils.bookmarks.DEFAULT_INDEX, TEST_BOOKMARKED_URI.spec); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_399264_query_to_string.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_399264_query_to_string.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_399264_query_to_string.js 2016-11-11 02:01:40.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_399264_query_to_string.js 2016-11-14 01:59:31.000000000 +0000 @@ -24,8 +24,6 @@ function run_test() { - var hs = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsINavHistoryService); var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. getService(Ci.nsINavBookmarksService); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_399264_string_to_query.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_399264_string_to_query.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_399264_string_to_query.js 2016-11-11 02:01:40.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_399264_string_to_query.js 2016-11-14 01:59:31.000000000 +0000 @@ -32,8 +32,6 @@ function run_test() { - var hs = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsINavHistoryService); var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. getService(Ci.nsINavBookmarksService); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_402799.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_402799.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_402799.js 2016-11-11 02:01:40.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_402799.js 2016-11-14 01:59:31.000000000 +0000 @@ -36,10 +36,10 @@ var uri1 = uri("http://foo.bar/"); // create 2 bookmarks on the same uri - var bookmark1id = bmsvc.insertBookmark(bmsvc.bookmarksMenuFolder, uri1, - bmsvc.DEFAULT_INDEX, "title 1"); - var bookmark2id = bmsvc.insertBookmark(bmsvc.toolbarFolder, uri1, - bmsvc.DEFAULT_INDEX, "title 2"); + bmsvc.insertBookmark(bmsvc.bookmarksMenuFolder, uri1, + bmsvc.DEFAULT_INDEX, "title 1"); + bmsvc.insertBookmark(bmsvc.toolbarFolder, uri1, + bmsvc.DEFAULT_INDEX, "title 2"); // add some tags tagssvc.tagURI(uri1, ["foo", "bar", "foobar", "foo bar"]); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_412132.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_412132.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_412132.js 2016-11-11 02:01:40.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_412132.js 2016-11-14 01:59:39.000000000 +0000 @@ -77,10 +77,10 @@ TEST_URI, PlacesUtils.bookmarks.DEFAULT_INDEX, "bookmark 1 title"); - let id2 = PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId, - TEST_URI, - PlacesUtils.bookmarks.DEFAULT_INDEX, - "bookmark 2 title"); + PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId, + TEST_URI, + PlacesUtils.bookmarks.DEFAULT_INDEX, + "bookmark 2 title"); yield PlacesTestUtils.promiseAsyncUpdates(); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_async_history_api.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_async_history_api.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_async_history_api.js 2016-11-11 02:01:41.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_async_history_api.js 2016-11-14 02:00:49.000000000 +0000 @@ -239,7 +239,6 @@ const TEST_URI = NetUtil.newURI(TEST_DOMAIN + "test_no_id_or_guid_no_visits_throws"); const TEST_GUID = "_RANDOMGUID_"; - const TEST_PLACEID = 2; let log_test_conditions = function(aPlace) { let str = "Testing place with " + @@ -617,21 +616,12 @@ const EXPECTED_COUNT_SUCCESS = 2; const EXPECTED_COUNT_FAILURE = 1; - let callbackCountSuccess = 0; - let callbackCountFailure = 0; - let placesResult = yield promiseUpdatePlaces(places); - for (let place of placesResult.results) { - let checker = PlacesUtils.history.canAddURI(place.uri) ? - do_check_true : do_check_false; - callbackCountSuccess++; - } - for (let error of placesResult.errors) { - callbackCountFailure++; - } + let {results, errors} = yield promiseUpdatePlaces(places); + + do_check_eq(results.length, EXPECTED_COUNT_SUCCESS); + do_check_eq(errors.length, EXPECTED_COUNT_FAILURE); - do_check_eq(callbackCountSuccess, EXPECTED_COUNT_SUCCESS); - do_check_eq(callbackCountFailure, EXPECTED_COUNT_FAILURE); yield PlacesTestUtils.promiseAsyncUpdates(); }); @@ -666,7 +656,6 @@ do_check_eq(visits.length, 1); let visit = visits[0]; do_check_eq(visit.visitDate, VISIT_TIME); - let transitions = do_check_true(Object.values(PlacesUtils.history.TRANSITIONS).includes(visit.transitionType)); do_check_true(visit.referrerURI === null); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_async_transactions.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_async_transactions.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_async_transactions.js 2016-11-11 02:01:41.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_async_transactions.js 2016-11-14 02:00:49.000000000 +0000 @@ -1214,7 +1214,7 @@ }); function* doTest(aInfo) { - let urls, tagsToRemove; + let urls, tagsRemoved; if (aInfo instanceof Ci.nsIURI) { urls = [aInfo]; tagsRemoved = []; @@ -1501,9 +1501,9 @@ } // Test duplicating leafs (bookmark, separator, empty folder) - let bmTxn = PT.NewBookmark({ url: new URL("http://test.item.duplicate") - , parentGuid: rootGuid - , annos: [{ name: "Anno", value: "AnnoValue"}] }); + PT.NewBookmark({ url: new URL("http://test.item.duplicate") + , parentGuid: rootGuid + , annos: [{ name: "Anno", value: "AnnoValue"}] }); let sepTxn = PT.NewSeparator({ parentGuid: rootGuid, index: 1 }); let livemarkTxn = PT.NewLivemark( { feedUrl: new URL("http://test.feed.uri") @@ -1664,7 +1664,7 @@ let nestedFolderGuid = yield PT.NewFolder({ title: "Nested Test Folder" , parentGuid: folderGuid }).transact(); - let nestedSepGuid = yield PT.NewSeparator(nestedFolderGuid).transact(); + yield PT.NewSeparator(nestedFolderGuid).transact(); guids.push(folderGuid); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_bookmarks_html.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_bookmarks_html.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_bookmarks_html.js 2016-11-11 02:01:41.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_bookmarks_html.js 2016-11-14 02:00:49.000000000 +0000 @@ -188,7 +188,7 @@ yield PlacesTestUtils.promiseAsyncUpdates(); do_print("Insert bookmark"); - let bookmark = yield PlacesUtils.bookmarks.insert({ + yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid, url: PAGE_URI, title: "Test" diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_crash_476292.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_crash_476292.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_crash_476292.js 2016-11-11 02:01:41.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_crash_476292.js 2016-11-14 02:00:49.000000000 +0000 @@ -23,6 +23,6 @@ dbFile.copyTo(profD, "places.sqlite"); // Now get the bookmarks service. This will crash when the bug exists. - let bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. - getService(Ci.nsINavBookmarksService); + Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. + getService(Ci.nsINavBookmarksService); } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_getPlacesInfo.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_getPlacesInfo.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_getPlacesInfo.js 2016-11-11 02:01:41.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_getPlacesInfo.js 2016-11-14 02:00:49.000000000 +0000 @@ -81,7 +81,7 @@ function* test_invalid_guid() { try { - let placeInfoByGUID = yield PlacesUtils.promisePlaceInfo("###"); + yield PlacesUtils.promisePlaceInfo("###"); do_throw("getPlacesInfo should fail for invalid guids") } catch (ex) { } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_pageGuid_bookmarkGuid.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_pageGuid_bookmarkGuid.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_pageGuid_bookmarkGuid.js 2016-11-11 02:01:42.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_pageGuid_bookmarkGuid.js 2016-11-14 02:00:50.000000000 +0000 @@ -13,14 +13,14 @@ add_task(function* test_addBookmarksAndCheckGuids() { let folder = bmsvc.createFolder(bmsvc.placesRoot, "test folder", bmsvc.DEFAULT_INDEX); - let b1 = bmsvc.insertBookmark(folder, uri("http://test1.com/"), - bmsvc.DEFAULT_INDEX, "1 title"); - let b2 = bmsvc.insertBookmark(folder, uri("http://test2.com/"), - bmsvc.DEFAULT_INDEX, "2 title"); - let b3 = bmsvc.insertBookmark(folder, uri("http://test3.com/"), - bmsvc.DEFAULT_INDEX, "3 title"); - let s1 = bmsvc.insertSeparator(folder, bmsvc.DEFAULT_INDEX); - let f1 = bmsvc.createFolder(folder, "test folder 2", bmsvc.DEFAULT_INDEX); + bmsvc.insertBookmark(folder, uri("http://test1.com/"), + bmsvc.DEFAULT_INDEX, "1 title"); + bmsvc.insertBookmark(folder, uri("http://test2.com/"), + bmsvc.DEFAULT_INDEX, "2 title"); + bmsvc.insertBookmark(folder, uri("http://test3.com/"), + bmsvc.DEFAULT_INDEX, "3 title"); + bmsvc.insertSeparator(folder, bmsvc.DEFAULT_INDEX); + bmsvc.createFolder(folder, "test folder 2", bmsvc.DEFAULT_INDEX); let root = PlacesUtils.getFolderContents(folder).root; do_check_eq(root.childCount, 5); @@ -90,7 +90,6 @@ add_task(function* test_addVisitAndCheckGuid() { // add a visit and test page guid and non-existing bookmark guids. - let now = Date.now() * 1000; let sourceURI = uri("http://test4.com/"); yield PlacesTestUtils.addVisits({ uri: sourceURI }); do_check_eq(bmsvc.getBookmarkedURIFor(sourceURI), null); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_PlacesSearchAutocompleteProvider.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_PlacesSearchAutocompleteProvider.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_PlacesSearchAutocompleteProvider.js 2016-11-11 02:01:41.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_PlacesSearchAutocompleteProvider.js 2016-11-14 02:00:49.000000000 +0000 @@ -41,7 +41,7 @@ do_check_eq(null, yield PlacesSearchAutocompleteProvider.findMatchByToken("bacon")); Services.search.addEngineWithDetails("bacon", "", "pork", "Search Bacon", "GET", "http://www.bacon.moz/?search={searchTerms}"); - yield promiseSearchTopic; + yield promiseTopic; let match = yield PlacesSearchAutocompleteProvider.findMatchByToken("bacon"); do_check_eq(match.url, "http://www.bacon.moz"); do_check_eq(match.engineName, "bacon"); @@ -72,7 +72,7 @@ do_check_eq(null, yield PlacesSearchAutocompleteProvider.findMatchByToken("patch")); Services.search.addEngineWithDetails("patch", "", "PR", "Search Patch", "GET", "http://www.patch.moz/?search={searchTerms}"); - yield promiseSearchTopic; + yield promiseTopic; // lower case let match = yield PlacesSearchAutocompleteProvider.findMatchByAlias("pr"); do_check_eq(match.engineName, "patch"); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_placesTxn.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_placesTxn.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_placesTxn.js 2016-11-11 02:01:42.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_placesTxn.js 2016-11-14 02:00:50.000000000 +0000 @@ -321,7 +321,6 @@ let testFolder = bmsvc.createFolder(root, "Test removing an item with a tag", bmsvc.DEFAULT_INDEX); - const KEYWORD = "test: test removing an item with a tag"; const TAG_NAME = "tag-test_remove_item_with_tag"; let testURI = NetUtil.newURI("http://test_remove_item_with_tag.com"); let testBkmId = bmsvc.insertBookmark(testFolder, testURI, bmsvc.DEFAULT_INDEX, "test-item1"); @@ -364,7 +363,6 @@ bmsvc.DEFAULT_INDEX); const KEYWORD = "test: test removing an item with a keyword"; - const TAG_NAME = "tag-test_remove_item_with_keyword"; let testURI = NetUtil.newURI("http://test_remove_item_with_keyword.com"); let testBkmId = bmsvc.insertBookmark(testFolder, testURI, bmsvc.DEFAULT_INDEX, "test-item1"); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_promiseBookmarksTree.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_promiseBookmarksTree.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_promiseBookmarksTree.js 2016-11-11 02:01:42.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_promiseBookmarksTree.js 2016-11-14 02:00:50.000000000 +0000 @@ -168,7 +168,7 @@ var itemsCount = 0; function* new_bookmark(aInfo) { - let currentItem = ++itemsCount; + ++itemsCount; if (!("url" in aInfo)) aInfo.url = uri("http://test.item." + itemsCount); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_resultsAsVisit_details.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_resultsAsVisit_details.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_resultsAsVisit_details.js 2016-11-11 02:01:42.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_resultsAsVisit_details.js 2016-11-14 02:00:50.000000000 +0000 @@ -64,8 +64,8 @@ add_task(function* test_bookmarkFields() { let folder = bookmarks.createFolder(bookmarks.placesRoot, "test folder", bookmarks.DEFAULT_INDEX); - let bm = bookmarks.insertBookmark(folder, uri("http://test4.com/"), - bookmarks.DEFAULT_INDEX, "test4 title"); + bookmarks.insertBookmark(folder, uri("http://test4.com/"), + bookmarks.DEFAULT_INDEX, "test4 title"); let root = PlacesUtils.getFolderContents(folder).root; equal(root.childCount, 1); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_sync_utils.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_sync_utils.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_sync_utils.js 2016-11-11 02:01:42.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_sync_utils.js 2016-11-14 02:00:50.000000000 +0000 @@ -481,7 +481,7 @@ }); add_task(function* test_insert_livemark() { - let { server, site, stopServer } = makeLivemarkServer(); + let { site, stopServer } = makeLivemarkServer(); try { do_print("Insert livemark with feed URL"); @@ -531,7 +531,7 @@ }); add_task(function* test_update_livemark() { - let { server, site, stopServer } = makeLivemarkServer(); + let { site, stopServer } = makeLivemarkServer(); let feedURI = uri(site + "/feed/1"); try { @@ -715,7 +715,7 @@ }); add_task(function* test_insert_tags() { - let newItems = yield Promise.all([{ + yield Promise.all([{ kind: "bookmark", url: "https://example.com", syncId: makeGuid(), @@ -785,7 +785,7 @@ add_task(function* test_insert_keyword() { do_print("Insert item with new keyword"); { - let bookmark = yield PlacesSyncUtils.bookmarks.insert({ + yield PlacesSyncUtils.bookmarks.insert({ kind: "bookmark", parentSyncId: "menu", url: "https://example.com", @@ -799,7 +799,7 @@ do_print("Insert item with existing keyword"); { - let bookmark = yield PlacesSyncUtils.bookmarks.insert({ + yield PlacesSyncUtils.bookmarks.insert({ kind: "bookmark", parentSyncId: "menu", url: "https://mozilla.org", @@ -923,7 +923,7 @@ do_print("Use the public tagging API to ensure we added the tag correctly"); { - let bookmark = yield PlacesUtils.bookmarks.insert({ + yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.menuGuid, type: PlacesUtils.bookmarks.TYPE_BOOKMARK, url: "https://mozilla.org", @@ -970,7 +970,7 @@ do_print("Insert the grandparent"); { - let grandParent = yield PlacesSyncUtils.bookmarks.insert({ + yield PlacesSyncUtils.bookmarks.insert({ kind: "folder", parentSyncId: "menu", syncId: grandParentGuid, @@ -1116,7 +1116,7 @@ }); add_task(function* test_fetch_livemark() { - let { server, site, stopServer } = makeLivemarkServer(); + let { site, stopServer } = makeLivemarkServer(); try { do_print("Create livemark"); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_tagging.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_tagging.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_tagging.js 2016-11-11 02:01:42.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_tagging.js 2016-11-14 02:00:50.000000000 +0000 @@ -83,7 +83,6 @@ // get array of tag folder ids => title // for testing tagging with mixed folder ids and tags - var tagFolders = []; var child = tagRoot.getChild(0); var tagId = child.itemId; var tagTitle = child.title; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_update_frecency_after_delete.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_update_frecency_after_delete.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/tests/unit/test_update_frecency_after_delete.js 2016-11-11 02:01:42.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/tests/unit/test_update_frecency_after_delete.js 2016-11-14 02:00:50.000000000 +0000 @@ -70,7 +70,7 @@ title: "bookmark 1 title", url: TEST_URI }); - let bm2 = yield PlacesUtils.bookmarks.insert({ + yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid, title: "bookmark 2 title", url: TEST_URI @@ -94,7 +94,7 @@ do_print("After removing all children from bookmark's parent, frecency " + "of bookmark's URI should not be zero if URI is visited."); const TEST_URI = NetUtil.newURI("http://example.com/1"); - let bm = yield PlacesUtils.bookmarks.insert({ + yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid, title: "bookmark title", url: TEST_URI @@ -120,7 +120,7 @@ "of bookmark's URI should not be zero if URI is still " + "bookmarked."); const TEST_URI = NetUtil.newURI("http://example.com/1"); - let bm1 = yield PlacesUtils.bookmarks.insert({ + yield PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.toolbarGuid, title: "bookmark 1 title", url: TEST_URI @@ -131,7 +131,7 @@ type: PlacesUtils.bookmarks.TYPE_FOLDER, title: "bookmark 2 folder" }); - let bm2 = yield PlacesUtils.bookmarks.insert({ + yield PlacesUtils.bookmarks.insert({ title: "bookmark 2 title", parentGuid: folder.guid, url: TEST_URI diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/UnifiedComplete.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/UnifiedComplete.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/places/UnifiedComplete.js 2016-11-11 02:00:25.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/places/UnifiedComplete.js 2016-11-14 01:59:27.000000000 +0000 @@ -69,6 +69,11 @@ // always try to have at least MINIMUM_LOCAL_MATCHES local matches. const MINIMUM_LOCAL_MATCHES = 6; +// Extensions are allowed to add suggestions if they have registered a keyword +// with the omnibox API. This is the maximum number of suggestions an extension +// is allowed to add for a given search string. +const MAXIMUM_ALLOWED_EXTENSION_MATCHES = 6; + // A regex that matches "single word" hostnames for whitelisting purposes. // The hostname will already have been checked for general validity, so we // don't need to be exhaustive here, so allow dashes anywhere. @@ -119,7 +124,9 @@ h.visit_count, h.typed, h.id, t.open_count, h.frecency FROM moz_places h LEFT JOIN moz_favicons f ON f.id = h.favicon_id - LEFT JOIN moz_openpages_temp t ON t.url = h.url + LEFT JOIN moz_openpages_temp t + ON t.url = h.url + AND t.userContextId = :userContextId WHERE h.frecency <> 0 AND AUTOCOMPLETE_MATCH(:searchString, h.url, CASE WHEN bookmarked THEN @@ -143,6 +150,7 @@ FROM moz_openpages_temp t LEFT JOIN moz_places h ON h.url_hash = hash(t.url) AND h.url = t.url WHERE h.id IS NULL + AND t.userContextId = :userContextId AND AUTOCOMPLETE_MATCH(:searchString, t.url, t.url, NULL, NULL, NULL, NULL, t.open_count, :matchBehavior, :searchBehavior) @@ -162,7 +170,9 @@ ) AS i JOIN moz_places h ON h.id = i.place_id LEFT JOIN moz_favicons f ON f.id = h.favicon_id - LEFT JOIN moz_openpages_temp t ON t.url = h.url + LEFT JOIN moz_openpages_temp t + ON t.url = h.url + AND t.userContextId = :userContextId WHERE AUTOCOMPLETE_MATCH(NULL, h.url, IFNULL(btitle, h.title), tags, h.visit_count, h.typed, bookmarked, @@ -264,6 +274,8 @@ "resource://gre/modules/osfile.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils", "resource://gre/modules/PromiseUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "ExtensionSearchHandler", + "resource://gre/modules/ExtensionSearchHandler.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "PlacesSearchAutocompleteProvider", @@ -291,15 +303,17 @@ XPCOMUtils.defineLazyGetter(this, "SwitchToTabStorage", () => Object.seal({ _conn: null, // Temporary queue used while the database connection is not available. - _queue: new Set(), + _queue: new Map(), initDatabase: Task.async(function* (conn) { // To reduce IO use an in-memory table for switch-to-tab tracking. // Note: this should be kept up-to-date with the definition in // nsPlacesTables.h. yield conn.execute( `CREATE TEMP TABLE moz_openpages_temp ( - url TEXT PRIMARY KEY, - open_count INTEGER + url TEXT, + userContextId INTEGER, + open_count INTEGER, + PRIMARY KEY (url, userContextId) )`); // Note: this should be kept up-to-date with the definition in @@ -310,43 +324,64 @@ WHEN NEW.open_count = 0 BEGIN DELETE FROM moz_openpages_temp - WHERE url = NEW.url; + WHERE url = NEW.url + AND userContextId = NEW.userContextId; END`); this._conn = conn; // Populate the table with the current cache contents... - this._queue.forEach(this.add, this); + for (let [userContextId, uris] of this._queue) { + for (let uri of uris) { + this.add(uri, userContextId); + } + } + // ...then clear it to avoid double additions. this._queue.clear(); }), - add: function (uri) { + add(uri, userContextId) { if (!this._conn) { - this._queue.add(uri); + if (!this._queue.has(userContextId)) { + this._queue.set(userContextId, new Set()); + } + this._queue.get(userContextId).add(uri); return; } this._conn.executeCached( - `INSERT OR REPLACE INTO moz_openpages_temp (url, open_count) - VALUES ( :url, IFNULL( (SELECT open_count + 1 - FROM moz_openpages_temp - WHERE url = :url), - 1 - ) + `INSERT OR REPLACE INTO moz_openpages_temp (url, userContextId, open_count) + VALUES ( :url, + :userContextId, + IFNULL( ( SELECT open_count + 1 + FROM moz_openpages_temp + WHERE url = :url + AND userContextId = :userContextId ), + 1 + ) )` - , { url: uri.spec }); + , { url: uri.spec, userContextId }); }, - delete: function (uri) { + delete(uri, userContextId) { if (!this._conn) { - this._queue.delete(uri); + // This should not happen. + if (!this._queue.has(userContextId)) { + throw new Error("Unknown userContextId!"); + } + + this._queue.get(userContextId).delete(uri); + if (this._queue.get(userContextId).size == 0) { + this._queue.delete(userContextId); + } return; } this._conn.executeCached( `UPDATE moz_openpages_temp SET open_count = open_count - 1 - WHERE url = :url` - , { url: uri.spec }); + WHERE url = :url + AND userContextId = :userContextId` + , { url: uri.spec, userContextId }); }, shutdown: function () { @@ -715,11 +750,16 @@ // The index to insert remote matches at. this._remoteMatchesStartIndex = 0; + // The index to insert local matches at. + + this._localMatchesStartIndex = 0; // Counts the number of inserted local matches. this._localMatchesCount = 0; // Counts the number of inserted remote matches. this._remoteMatchesCount = 0; + // Counts the number of inserted extension matches. + this._extensionMatchesCount = 0; } Search.prototype = { @@ -942,7 +982,19 @@ } } - // Ensure to fill any remaining space. + // Only add extension suggestions if the first token is a registered keyword + // and the search string has characters after the first token. + if (ExtensionSearchHandler.isKeywordRegistered(this._searchTokens[0]) && + this._originalSearchString.length > this._searchTokens[0].length) { + yield this._matchExtensionSuggestions(); + if (!this.pending) + return; + } else if (ExtensionSearchHandler.hasActiveInputSession()) { + ExtensionSearchHandler.handleInputCancelled(); + } + + // Ensure to fill any remaining space. Suggestions which come from extensions are + // inserted at the beginning, so any suggestions yield Promise.all(this._remoteMatchesPromises); }), @@ -950,7 +1002,15 @@ // We always try to make the first result a special "heuristic" result. The // heuristics below determine what type of result it will be, if any. - let hasSearchTerms = this._searchTokens.length > 0 ; + let hasSearchTerms = this._searchTokens.length > 0; + + if (hasSearchTerms) { + // It may be a keyword registered by an extension. + let matched = yield this._matchExtensionHeuristicResult(); + if (matched) { + return true; + } + } if (this._enableActions && hasSearchTerms) { // It may be a search engine with an alias - which works like a keyword. @@ -1124,6 +1184,16 @@ return gotResult; }, + _matchExtensionHeuristicResult: function* () { + if (ExtensionSearchHandler.isKeywordRegistered(this._searchTokens[0]) && + this._originalSearchString.length > this._searchTokens[0].length) { + let description = ExtensionSearchHandler.getDescription(this._searchTokens[0]); + this._addExtensionMatch(this._originalSearchString, description); + return true; + } + return false; + }, + _matchPlacesKeyword: function* () { // The first word could be a keyword, so that's what we'll search. let keyword = this._searchTokens[0]; @@ -1236,6 +1306,24 @@ return true; }, + _addExtensionMatch(content, comment) { + if (this._extensionMatchesCount >= MAXIMUM_ALLOWED_EXTENSION_MATCHES) { + return; + } + + this._addMatch({ + value: PlacesUtils.mozActionURI("extension", { + content, + keyword: this._searchTokens[0] + }), + comment, + icon: "chrome://browser/content/extension.svg", + style: "action extension", + frecency: FRECENCY_DEFAULT, + extension: true, + }); + }, + _addSearchEngineMatch(match, query, suggestion) { let actionURLParams = { engineName: match.engineName, @@ -1259,9 +1347,21 @@ }); }, + *_matchExtensionSuggestions() { + let promise = ExtensionSearchHandler.handleSearch(this._searchTokens[0], this._originalSearchString, + suggestions => { + suggestions.forEach(suggestion => { + let content = `${this._searchTokens[0]} ${suggestion.content}`; + this._addExtensionMatch(content, suggestion.description); + }); + } + ); + this._remoteMatchesPromises.push(promise); + }, + *_matchRemoteTabs() { let matches = yield PlacesRemoteTabsAutocompleteProvider.getMatches(this._originalSearchString); - for (let {url, title, icon, deviceClass, deviceName} of matches) { + for (let {url, title, icon, deviceName} of matches) { // It's rare that Sync supplies the icon for the page (but if it does, it // is a string URL) if (!icon) { @@ -1464,6 +1564,11 @@ // Append after local matches. index = this._remoteMatchesStartIndex + this._remoteMatchesCount; this._remoteMatchesCount++; + } else if (match.extension) { + index = this._localMatchesStartIndex; + this._localMatchesStartIndex++; + this._remoteMatchesStartIndex++; + this._extensionMatchesCount++; } else { // This is a local match. if (match.frecency > FRECENCY_DEFAULT || @@ -1554,7 +1659,6 @@ _processRow: function (row) { let match = {}; match.placeId = row.getResultByIndex(QUERYINDEX_PLACEID); - let queryType = row.getResultByIndex(QUERYINDEX_QUERYTYPE); let escapedURL = row.getResultByIndex(QUERYINDEX_URL); let openPageCount = row.getResultByIndex(QUERYINDEX_SWITCHTAB) || 0; let historyTitle = row.getResultByIndex(QUERYINDEX_TITLE) || ""; @@ -1675,6 +1779,7 @@ // We only want to search the tokens that we are left with - not the // original search string. searchString: this._searchTokens.join(" "), + userContextId: this._userContextId, // Limit the query to the the maximum number of desired results. // This way we can avoid doing more work than needed. maxResults: Prefs.maxRichResults @@ -1698,6 +1803,7 @@ // We only want to search the tokens that we are left with - not the // original search string. searchString: this._searchTokens.join(" "), + userContextId: this._userContextId, maxResults: Prefs.maxRichResults } ]; @@ -1717,7 +1823,8 @@ search_string: this._searchString, query_type: QUERYTYPE_FILTERED, matchBehavior: this._matchBehavior, - searchBehavior: this._behavior + searchBehavior: this._behavior, + userContextId: this._userContextId, } ]; }, @@ -1901,12 +2008,12 @@ // mozIPlacesAutoComplete - registerOpenPage: function PAC_registerOpenPage(uri) { - SwitchToTabStorage.add(uri); + registerOpenPage(uri, userContextId) { + SwitchToTabStorage.add(uri, userContextId); }, - unregisterOpenPage: function PAC_unregisterOpenPage(uri) { - SwitchToTabStorage.delete(uri); + unregisterOpenPage(uri, userContextId) { + SwitchToTabStorage.delete(uri, userContextId); }, // nsIAutoCompleteSearch diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/printing/content/printjoboptions.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/printing/content/printjoboptions.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/printing/content/printjoboptions.js 2016-11-11 02:01:42.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/printing/content/printjoboptions.js 2016-11-14 02:00:50.000000000 +0000 @@ -135,8 +135,6 @@ var paperWidths = [ 8.5, 8.5, 7.25, 148.0, 210.0, 287.0, 420.0, 594.0, 841.0]; var paperHeights = [11.0, 14.0, 10.50, 210.0, 297.0, 420.0, 594.0, 841.0, 1189.0]; var paperInches = [true, true, true, false, false, false, false, false, false]; - // this is deprecated - var paperEnums = [0, 1, 2, 3, 4, 5, 6, 7, 8]; gPaperArray = new Array(); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/promiseworker/PromiseWorker.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/promiseworker/PromiseWorker.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/promiseworker/PromiseWorker.jsm 2016-11-11 02:01:42.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/promiseworker/PromiseWorker.jsm 2016-11-14 02:00:50.000000000 +0000 @@ -305,14 +305,12 @@ this.log("Message posted"); let reply; - let isError = false; try { this.log("Expecting reply"); reply = yield deferred.promise; } catch (error) { this.log("Got error", error); reply = error; - isError = true; if (error instanceof WorkerError) { // We know how to deserialize most well-known errors diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/prompts/content/selectDialog.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/prompts/content/selectDialog.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/prompts/content/selectDialog.js 2016-11-11 02:01:42.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/prompts/content/selectDialog.js 2016-11-14 02:00:51.000000000 +0000 @@ -56,7 +56,6 @@ } function dialogOK() { - let selected = listBox.selectedIndex; gArgs.setProperty("selected", listBox.selectedIndex); gArgs.setProperty("ok", true); return true; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/prompts/content/tabprompts.xml firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/prompts/content/tabprompts.xml --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/prompts/content/tabprompts.xml 2016-11-11 02:01:42.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/prompts/content/tabprompts.xml 2016-11-14 02:00:51.000000000 +0000 @@ -300,7 +300,6 @@ event.stopPropagation(); if (action == "default") { let bnum = this.args.defaultButtonNum || 0; - let button = this.ui["button" + bnum]; this.onButtonClick(bnum); } else { // action == "cancel" this.onButtonClick(1); // Cancel button diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/satchel/FormHistory.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/satchel/FormHistory.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/satchel/FormHistory.jsm 2016-11-11 02:01:43.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/satchel/FormHistory.jsm 2016-11-14 02:01:42.000000000 +0000 @@ -782,7 +782,6 @@ let handlers = { handleResult : function(aResultSet) { - let formHistoryFields = dbSchema.tables.moz_formhistory; for (let row = aResultSet.getNextRow(); row; row = aResultSet.getNextRow()) { let result = {}; for (let field of aSelectTerms) { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/satchel/nsFormHistory.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/satchel/nsFormHistory.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/satchel/nsFormHistory.js 2016-11-11 02:01:43.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/satchel/nsFormHistory.js 2016-11-14 02:01:43.000000000 +0000 @@ -303,7 +303,7 @@ entryExists : function entryExists(name, value) { this.log("entryExists for " + name + "=" + value); - let [id, guid] = this.getExistingEntryID(name, value); + let [id] = this.getExistingEntryID(name, value); this.log("entryExists: id=" + id); return (id != -1); }, diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/satchel/test/test_bug_511615.html firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/satchel/test/test_bug_511615.html --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/satchel/test/test_bug_511615.html 2016-11-11 02:01:44.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/satchel/test/test_bug_511615.html 2016-11-14 02:01:44.000000000 +0000 @@ -74,7 +74,7 @@ function doKeyUnprivileged(key) { let keyName = "DOM_VK_" + key.toUpperCase(); - let keycode, charcode, alwaysVal; + let keycode, charcode; if (key.length == 1) { keycode = 0; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/satchel/test/unit/test_notify.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/satchel/test/unit/test_notify.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/satchel/test/unit/test_notify.js 2016-11-11 02:01:44.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/satchel/test/unit/test_notify.js 2016-11-14 02:01:46.000000000 +0000 @@ -54,8 +54,6 @@ var testdesc = "Setup of test form history entries"; var entry1 = ["entry1", "value1"]; -var entry2 = ["entry2", "value2"]; - /* ========== 1 ========== */ testnum = 1; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/search/tests/xpcshell/head_search.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/search/tests/xpcshell/head_search.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/search/tests/xpcshell/head_search.js 2016-11-11 02:01:44.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/search/tests/xpcshell/head_search.js 2016-11-14 02:01:53.000000000 +0000 @@ -59,8 +59,6 @@ */ function configureToLoadJarEngines() { - let defaultBranch = Services.prefs.getDefaultBranch(null); - let url = "chrome://testsearchplugin/locale/searchplugins/"; let resProt = Services.io.getProtocolHandler("resource") .QueryInterface(Ci.nsIResProtocolHandler); @@ -81,9 +79,9 @@ function installAddonEngine(name = "engine-addon") { const XRE_EXTENSIONS_DIR_LIST = "XREExtDL"; - const gProfD = do_get_profile().QueryInterface(Ci.nsILocalFile); + const profD = do_get_profile().QueryInterface(Ci.nsILocalFile); - let dir = gProfD.clone(); + let dir = profD.clone(); dir.append("extensions"); if (!dir.exists()) dir.create(dir.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); @@ -133,9 +131,9 @@ { const XRE_APP_DISTRIBUTION_DIR = "XREAppDist"; - const gProfD = do_get_profile().QueryInterface(Ci.nsILocalFile); + const profD = do_get_profile().QueryInterface(Ci.nsILocalFile); - let dir = gProfD.clone(); + let dir = profD.clone(); dir.append("distribution"); dir.create(dir.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); let distDir = dir.clone(); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/search/tests/xpcshell/test_engineUpdate.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/search/tests/xpcshell/test_engineUpdate.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/search/tests/xpcshell/test_engineUpdate.js 2016-11-11 02:01:46.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/search/tests/xpcshell/test_engineUpdate.js 2016-11-14 02:01:53.000000000 +0000 @@ -33,9 +33,9 @@ yield new Promise(resolve => { Services.obs.addObserver(function obs(subject, topic, data) { if (data == "engine-loaded") { - let engine = subject.QueryInterface(Ci.nsISearchEngine); - let rawEngine = engine.wrappedJSObject; - equal(engine.alias, KEYWORD, "Keyword not cleared by update"); + let loadedEngine = subject.QueryInterface(Ci.nsISearchEngine); + let rawEngine = loadedEngine.wrappedJSObject; + equal(loadedEngine.alias, KEYWORD, "Keyword not cleared by update"); equal(rawEngine.getAttr("order"), 1, "Order not cleared by update"); Services.obs.removeObserver(obs, TOPIC, false); resolve(); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/search/tests/xpcshell/test_identifiers.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/search/tests/xpcshell/test_identifiers.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/search/tests/xpcshell/test_identifiers.js 2016-11-11 02:02:11.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/search/tests/xpcshell/test_identifiers.js 2016-11-14 02:01:53.000000000 +0000 @@ -31,7 +31,7 @@ let engineTemplateFile = do_get_file("data/engine.xml"); engineTemplateFile.copyTo(engineFile.parent, "test-search-engine.xml"); - let search = Services.search.init(function initComplete(aResult) { + Services.search.init(function initComplete(aResult) { do_print("init'd search service"); do_check_true(Components.isSuccessCode(aResult)); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/search/tests/xpcshell/test_json_cache.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/search/tests/xpcshell/test_json_cache.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/search/tests/xpcshell/test_json_cache.js 2016-11-11 02:02:33.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/search/tests/xpcshell/test_json_cache.js 2016-11-14 02:01:53.000000000 +0000 @@ -58,7 +58,6 @@ uri: "resource://search-plugins/list.json", loadUsingSystemPrincipal: true }); - let visibleDefaultEngines = []; let sis = Cc["@mozilla.org/scriptableinputstream;1"]. createInstance(Ci.nsIScriptableInputStream); sis.init(chan.open2()); @@ -83,7 +82,7 @@ add_test(function test_cached_engine_properties() { do_print("init search service"); - let search = Services.search.init(function initComplete(aResult) { + Services.search.init(function initComplete(aResult) { do_print("init'd search service"); do_check_true(Components.isSuccessCode(aResult)); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/search/tests/xpcshell/test_location_sync.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/search/tests/xpcshell/test_location_sync.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/search/tests/xpcshell/test_location_sync.js 2016-11-11 02:02:33.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/search/tests/xpcshell/test_location_sync.js 2016-11-14 02:01:53.000000000 +0000 @@ -55,7 +55,7 @@ // fetching the engines forces a sync init, and should have caused us to // check the timezone. - let engines = Services.search.getEngines(); + Services.search.getEngines(); ok(Services.search.isInitialized); // a little wait to check we didn't do the xhr thang. diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/search/tests/xpcshell/test_searchSuggest.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/search/tests/xpcshell/test_searchSuggest.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/search/tests/xpcshell/test_searchSuggest.js 2016-11-11 02:02:34.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/search/tests/xpcshell/test_searchSuggest.js 2016-11-14 02:01:54.000000000 +0000 @@ -27,8 +27,8 @@ removeMetadata(); updateAppInfo(); - let httpServer = useHttpServer(); - httpServer.registerContentType("sjs", "sjs"); + let server = useHttpServer(); + server.registerContentType("sjs", "sjs"); do_register_cleanup(() => Task.spawn(function* cleanup() { // Remove added form history entries diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/search/tests/xpcshell/test_sync_migration.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/search/tests/xpcshell/test_sync_migration.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/search/tests/xpcshell/test_sync_migration.js 2016-11-11 02:02:34.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/search/tests/xpcshell/test_sync_migration.js 2016-11-14 02:01:54.000000000 +0000 @@ -15,7 +15,7 @@ add_task(function* test_sync_metadata_migration() { do_check_false(Services.search.isInitialized); - let engines = Services.search.getEngines(); + Services.search.getEngines(); do_check_true(Services.search.isInitialized); yield promiseAfterCache(); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/telemetry/Histograms.json firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/telemetry/Histograms.json --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/telemetry/Histograms.json 2016-11-11 02:02:35.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/telemetry/Histograms.json 2016-11-14 02:01:54.000000000 +0000 @@ -1731,6 +1731,294 @@ "n_values": 12, "description": "Whether the URL gets redirected? (0=200, 1=301, 2=302, 3=304, 4=307, 5=308, 6=400, 7=401, 8=403, 9=404, 10=500, 11=other)" }, + "HTTP_NET_VS_CACHE_ONSTART_ISIMG": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStartRequest) difference (ms) for images. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTART_NOTIMG": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStartRequest) difference (ms) for non-images. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTOP_ISIMG": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStopRequest) difference (ms) for images. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTOP_NOTIMG": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStopRequest) difference (ms) for non-images. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTART_QSMALL_NORMALPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStartRequest) difference (ms) for requests with a normal priority and small queue. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTART_QMED_NORMALPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStartRequest) difference (ms) for requests with a normal priority and medium queue. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTART_QBIG_NORMALPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStartRequest) difference (ms) for requests with a normal priority and large queue. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTART_QSMALL_HIGHPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStartRequest) difference (ms) for requests with a high priority and small queue. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTART_QMED_HIGHPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStartRequest) difference (ms) for requests with a high priority and medium queue. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTART_QBIG_HIGHPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStartRequest) difference (ms) for requests with a high priority and large queue. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTOP_QSMALL_NORMALPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStopRequest) difference (ms) for requests with a normal priority and small queue. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTOP_QMED_NORMALPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStopRequest) difference (ms) for requests with a normal priority and medium queue. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTOP_QBIG_NORMALPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStopRequest) difference (ms) for requests with a normal priority and large queue. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTOP_QSMALL_HIGHPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStopRequest) difference (ms) for requests with a high priority and small queue. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTOP_QMED_HIGHPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStopRequest) difference (ms) for requests with a high priority and medium queue. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTOP_QBIG_HIGHPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStopRequest) difference (ms) for requests with a high priority and large queue. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTART_SMALL_NORMALPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStartRequest) difference (ms) for cache files with a small size (<32K) and normal priority. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTART_MED_NORMALPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStartRequest) difference (ms) for cache files with a medium size (<256K) and normal priority. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTART_LARGE_NORMALPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStartRequest) difference (ms) for cache files with a large size (>256K) and normal priority. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTART_SMALL_HIGHPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStartRequest) difference (ms) for cache files with a small size (<32K) and high priority. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTART_MED_HIGHPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStartRequest) difference (ms) for cache files with a medium size (<256K) and high priority. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTART_LARGE_HIGHPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStartRequest) difference (ms) for cache files with a large size (>256K) and high priority. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTOP_SMALL_NORMALPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStopRequest) difference (ms) for cache files with a small size (<32K) and normal priority. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTOP_MED_NORMALPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStopRequest) difference (ms) for cache files with a medium size (<256K) and normal priority. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTOP_LARGE_NORMALPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStopRequest) difference (ms) for cache files with a large size (>256K) and normal priority. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTOP_SMALL_HIGHPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStopRequest) difference (ms) for cache files with a small size (<32K) and high priority. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTOP_MED_HIGHPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStopRequest) difference (ms) for cache files with a medium size (<256K) and high priority. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTOP_LARGE_HIGHPRI": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStopRequest) difference (ms) for cache files with a large size (>256K) and high priority. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTART_REVALIDATED": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStartRequest) difference (ms) revalidated cache entries. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTART_NOTREVALIDATED": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStartRequest) difference (ms) not revalidated cache entries. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTOP_REVALIDATED": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStopRequest) difference (ms) revalidated cache entries. Offset by 500 ms." + }, + "HTTP_NET_VS_CACHE_ONSTOP_NOTREVALIDATED": { + "expires_in_version": "never", + "alert_emails": ["necko@mozilla.com"], + "bug_numbers": [1313095], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "Network vs cache time load (OnStopRequest) difference (ms) not revalidated cache entries. Offset by 500 ms." + }, "HTTP_AUTH_DIALOG_STATS": { "expires_in_version": "never", "kind": "enumerated", @@ -7899,7 +8187,8 @@ "description": "How often are secure cookies set from non-secure origins, and vice-versa? 0=nonsecure/http, 1=nonsecure/https, 2=secure/http, 3=secure/https" }, "COOKIE_LEAVE_SECURE_ALONE": { - "alert_emails": ["seceng@mozilla.org"], + "alert_emails": ["seceng-telemetry@mozilla.com"], + "bug_numbers": [976073], "expires_in_version": "57", "kind": "enumerated", "n_values": 10, diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/telemetry/histogram-whitelists.json firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/telemetry/histogram-whitelists.json --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/telemetry/histogram-whitelists.json 2016-11-11 02:02:37.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/telemetry/histogram-whitelists.json 2016-11-14 02:02:42.000000000 +0000 @@ -858,7 +858,6 @@ "COMPOSITE_TIME", "CONTENT_DOCUMENTS_DESTROYED", "COOKIE_SCHEME_SECURITY", - "COOKIE_LEAVE_SECURE_ALONE", "CRASH_STORE_COMPRESSED_BYTES", "CYCLE_COLLECTOR", "CYCLE_COLLECTOR_ASYNC_SNOW_WHITE_FREEING", diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/telemetry/tests/unit/test_ChildHistograms.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/telemetry/tests/unit/test_ChildHistograms.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/telemetry/tests/unit/test_ChildHistograms.js 2016-11-11 02:02:52.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/telemetry/tests/unit/test_ChildHistograms.js 2016-11-14 02:02:42.000000000 +0000 @@ -85,7 +85,7 @@ } // Run test in child, don't wait for it to finish. - let childPromise = run_test_in_child("test_ChildHistograms.js"); + run_test_in_child("test_ChildHistograms.js"); yield do_await_remote_message(MESSAGE_CHILD_TEST_DONE); yield ContentTaskUtils.waitForCondition(() => { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/telemetry/tests/unit/test_nsITelemetry.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/telemetry/tests/unit/test_nsITelemetry.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/telemetry/tests/unit/test_nsITelemetry.js 2016-11-11 02:03:02.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/telemetry/tests/unit/test_nsITelemetry.js 2016-11-14 02:02:43.000000000 +0000 @@ -145,10 +145,8 @@ var r = h.snapshot().ranges; // boolean histograms ignore numeric parameters do_check_eq(uneval(r), uneval([0, 1, 2])) - var sum = 0 for (var i=0;i p.id); let checkLoadingPings = Task.async(function*() { for (let data of PINGS) { let ping = yield TelemetryArchive.promiseArchivedPingById(data.id); @@ -263,7 +262,7 @@ Telemetry.getHistogramById("TELEMETRY_ARCHIVE_OLDEST_DIRECTORY_AGE").clear(); // Move the current date 60 days ahead of the first ping. - let now = fakeNow(futureDate(firstDate, 60 * MILLISECONDS_PER_DAY)); + fakeNow(futureDate(firstDate, 60 * MILLISECONDS_PER_DAY)); // Reset TelemetryArchive and TelemetryController to start the startup cleanup. yield TelemetryController.testReset(); // Wait for the cleanup to finish. diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/telemetry/tests/unit/test_TelemetryController.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/telemetry/tests/unit/test_TelemetryController.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/telemetry/tests/unit/test_TelemetryController.js 2016-11-11 02:02:55.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/telemetry/tests/unit/test_TelemetryController.js 2016-11-14 02:02:43.000000000 +0000 @@ -287,9 +287,6 @@ }); add_task(function* test_archivePings() { - const ARCHIVE_PATH = - OS.Path.join(OS.Constants.Path.profileDir, "datareporting", "archived"); - let now = new Date(2009, 10, 18, 12, 0, 0); fakeNow(now); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js 2016-11-11 02:02:55.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js 2016-11-14 02:02:43.000000000 +0000 @@ -944,7 +944,6 @@ // We only expect a single notification for each install, uninstall, enable, disable. const EXPECTED_NOTIFICATIONS = 4; - let deferred = PromiseUtils.defer(); let receivedNotifications = 0; let registerCheckpointPromise = (aExpected) => { @@ -1028,7 +1027,7 @@ } // Find the test plugin. - let plugin = gInstalledPlugins.find(plugin => (plugin.name == PLUGIN2_NAME)); + let plugin = gInstalledPlugins.find(p => (p.name == PLUGIN2_NAME)); Assert.ok(plugin, "The test plugin must exist."); // Remove it from the PluginHost. @@ -1266,7 +1265,6 @@ AddonManager.SIGNEDSTATE_NOT_REQUIRED, }; - let deferred = PromiseUtils.defer(); let receivedNotifications = 0; let registerCheckpointPromise = (aExpected) => { @@ -1397,16 +1395,16 @@ TelemetryEnvironment.registerChangeListener("testWatch_SearchDefault", resolve); }); let engine = yield new Promise((resolve, reject) => { - Services.obs.addObserver(function obs(subject, topic, data) { + Services.obs.addObserver(function obs(obsSubject, obsTopic, obsData) { try { - let engine = subject.QueryInterface(Ci.nsISearchEngine); - do_print("Observed " + data + " for " + engine.name); - if (data != "engine-added" || engine.name != "engine-telemetry") { + let searchEngine = obsSubject.QueryInterface(Ci.nsISearchEngine); + do_print("Observed " + obsData + " for " + searchEngine.name); + if (obsData != "engine-added" || searchEngine.name != "engine-telemetry") { return; } Services.obs.removeObserver(obs, "browser-search-engine-modified"); - resolve(engine); + resolve(searchEngine); } catch (ex) { reject(ex); } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/telemetry/tests/unit/test_TelemetryReportingPolicy.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/telemetry/tests/unit/test_TelemetryReportingPolicy.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/telemetry/tests/unit/test_TelemetryReportingPolicy.js 2016-11-11 02:02:56.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/telemetry/tests/unit/test_TelemetryReportingPolicy.js 2016-11-14 02:02:43.000000000 +0000 @@ -192,7 +192,7 @@ "The default state of the date should have a time of 0 and it should therefore fail"); // Showing the notification bar should make the user notified. - let now = fakeNow(2012, 11, 11); + fakeNow(2012, 11, 11); TelemetryReportingPolicy.testInfobarShown(); Assert.ok(TelemetryReportingPolicy.testIsUserNotified(), "Using the proper API causes user notification to report as true."); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/telemetry/tests/unit/test_TelemetrySend.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/telemetry/tests/unit/test_TelemetrySend.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/telemetry/tests/unit/test_TelemetrySend.js 2016-11-11 02:02:56.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/telemetry/tests/unit/test_TelemetrySend.js 2016-11-14 02:02:43.000000000 +0000 @@ -177,7 +177,7 @@ }); add_task(function* test_sendDateHeader() { - let now = fakeNow(new Date(Date.UTC(2011, 1, 1, 11, 0, 0))); + fakeNow(new Date(Date.UTC(2011, 1, 1, 11, 0, 0))); yield TelemetrySend.reset(); let pingId = yield TelemetryController.submitExternalPing("test-send-date-header", {}); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/telemetry/tests/unit/test_TelemetrySendOldPings.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/telemetry/tests/unit/test_TelemetrySendOldPings.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/telemetry/tests/unit/test_TelemetrySendOldPings.js 2016-11-11 02:02:56.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/telemetry/tests/unit/test_TelemetrySendOldPings.js 2016-11-14 02:02:43.000000000 +0000 @@ -178,7 +178,7 @@ */ add_task(function* test_recent_pings_sent() { let pingTypes = [{ num: RECENT_PINGS }]; - let recentPings = yield createSavedPings(pingTypes); + yield createSavedPings(pingTypes); yield TelemetryController.testReset(); yield TelemetrySend.testWaitOnOutgoingPings(); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js 2016-11-11 02:02:57.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js 2016-11-14 02:02:43.000000000 +0000 @@ -1104,9 +1104,6 @@ return; } - let timerCallback = null; - let timerDelay = null; - yield TelemetryStorage.testClearPendingPings(); PingServer.clearRequests(); @@ -1245,8 +1242,8 @@ // Watch a test preference, trigger and environment change and wait for it to propagate. // _watchPreferences triggers a subsession notification - let now = fakeNow(new Date(2050, 1, 1, 12, 0, 0)); gMonotonicNow = fakeMonotonicNow(gMonotonicNow + 10 * MILLISECONDS_PER_MINUTE); + fakeNow(new Date(2050, 1, 1, 12, 0, 0)); TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH); let changePromise = new Promise(resolve => TelemetryEnvironment.registerChangeListener("test_fake_change", resolve)); @@ -1468,7 +1465,7 @@ "Telemetry must create the aborted session directory when starting."); // Fake now again so that the scheduled aborted-session save takes place. - now = fakeNow(futureDate(now, ABORTED_SESSION_UPDATE_INTERVAL_MS)); + fakeNow(futureDate(now, ABORTED_SESSION_UPDATE_INTERVAL_MS)); // The first aborted session checkpoint must take place right after the initialisation. Assert.ok(!!schedulerTickCallback); // Execute one scheduler tick. @@ -1619,7 +1616,7 @@ TelemetryEnvironment.testWatchPreferences(PREFS_TO_WATCH); // Set the current time at midnight. - let future = fakeNow(futureDate(nowDate, MS_IN_ONE_DAY)); + fakeNow(futureDate(nowDate, MS_IN_ONE_DAY)); gMonotonicNow = fakeMonotonicNow(gMonotonicNow + 10 * MILLISECONDS_PER_MINUTE); // Trigger the environment change. @@ -1906,7 +1903,7 @@ Assert.equal(getSubsessionCount(), 1); // We should get a change notification after the 5min throttling interval. - now = fakeNow(futureDate(now, 5 * MILLISECONDS_PER_MINUTE + 1)); + fakeNow(futureDate(now, 5 * MILLISECONDS_PER_MINUTE + 1)); gMonotonicNow = fakeMonotonicNow(gMonotonicNow + 5 * MILLISECONDS_PER_MINUTE + 1); Preferences.set(PREF_TEST, 2); Assert.equal(getSubsessionCount(), 2); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/thumbnails/PageThumbs.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/thumbnails/PageThumbs.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/thumbnails/PageThumbs.jsm 2016-11-11 02:03:04.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/thumbnails/PageThumbs.jsm 2016-11-14 02:02:44.000000000 +0000 @@ -852,7 +852,6 @@ }, expireThumbnails: function Expiration_expireThumbnails(aURLsToKeep) { - let path = this.path; let keep = aURLsToKeep.map(url => PageThumbsStorage.getLeafNameForURL(url)); let msg = [ PageThumbsStorage.path, diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/thumbnails/test/browser_thumbnails_storage_migrate3.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/thumbnails/test/browser_thumbnails_storage_migrate3.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/thumbnails/test/browser_thumbnails_storage_migrate3.js 2016-11-11 02:03:06.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/thumbnails/test/browser_thumbnails_storage_migrate3.js 2016-11-14 02:02:52.000000000 +0000 @@ -22,14 +22,10 @@ * directory and should just apply to Linux. */ function* runTests() { - let dirSvc = Cc["@mozilla.org/file/directory_service;1"] - .getService(Ci.nsIProperties); - // Prepare a local profile directory. let localProfile = FileUtils.getDir("ProfD", ["local-test"], true); changeLocation("ProfLD", localProfile); - let local = FileUtils.getDir("ProfLD", [THUMBNAIL_DIRECTORY], true); let roaming = FileUtils.getDir("ProfD", [THUMBNAIL_DIRECTORY], true); // Set up some data in the roaming profile. @@ -74,7 +70,7 @@ // function |getFileForURL| points to the same path as // |getFilePathForURL|. if ("getFileForURL" in PageThumbsStorage) { - let file = PageThumbsStorage.getFileForURL(URL); + file = PageThumbsStorage.getFileForURL(URL); is(file.path, PageThumbsStorage.getFilePathForURL(URL), "Deprecated getFileForURL and getFilePathForURL return the same path"); } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/timermanager/nsUpdateTimerManager.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/timermanager/nsUpdateTimerManager.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/timermanager/nsUpdateTimerManager.js 2016-11-11 02:03:25.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/timermanager/nsUpdateTimerManager.js 2016-11-14 02:02:52.000000000 +0000 @@ -93,12 +93,19 @@ minInterval = 500; minFirstInterval = 500; case "profile-after-change": - // Cancel the timer if it has already been initialized. This is primarily - // for tests. this._timerMinimumDelay = Math.max(1000 * getPref("getIntPref", PREF_APP_UPDATE_TIMERMINIMUMDELAY, 120), minInterval); + // Prevent the timer delay between notifications to other consumers from + // being greater than 5 minutes which is 300000 milliseconds. + this._timerMinimumDelay = Math.min(this._timerMinimumDelay, 300000); + // Prevent the first interval from being less than the value of minFirstInterval let firstInterval = Math.max(getPref("getIntPref", PREF_APP_UPDATE_TIMERFIRSTINTERVAL, - this._timerMinimumDelay), minFirstInterval); + 30000), minFirstInterval); + // Prevent the first interval from being greater than 2 minutes which is + // 120000 milliseconds. + firstInterval = Math.min(firstInterval, 120000); + // Cancel the timer if it has already been initialized. This is primarily + // for tests. this._canEnsureTimer = true; this._ensureTimer(firstInterval); break; @@ -171,7 +178,7 @@ while (entries.hasMoreElements()) { let entry = entries.getNext().QueryInterface(Ci.nsISupportsCString).data; let value = catMan.getCategoryEntry(CATEGORY_UPDATE_TIMER, entry); - let [cid, method, timerID, prefInterval, defaultInterval] = value.split(","); + let [cid, method, timerID, prefInterval, defaultInterval, maxInterval] = value.split(","); defaultInterval = parseInt(defaultInterval); // cid and method are validated below when calling notify. @@ -183,6 +190,12 @@ } let interval = getPref("getIntPref", prefInterval, defaultInterval); + // Allow the update-timer category to specify a maximum value to prevent + // values larger than desired. + maxInterval = parseInt(maxInterval); + if (maxInterval && !isNaN(maxInterval)) { + interval = Math.min(interval, maxInterval); + } let prefLastUpdate = PREF_APP_UPDATE_LASTUPDATETIME_FMT.replace(/%ID%/, timerID); // Initialize the last update time to 0 when the preference isn't set so diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/timermanager/tests/unit/consumerNotifications.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/timermanager/tests/unit/consumerNotifications.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/timermanager/tests/unit/consumerNotifications.js 2016-11-11 02:03:25.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/timermanager/tests/unit/consumerNotifications.js 2016-11-14 02:02:52.000000000 +0000 @@ -23,22 +23,31 @@ const CONSUMER_TIMER_INTERVAL = 1; // seconds const TESTS = [ { + desc: "Test Timer Callback 0", + timerID: "test0-update-timer", + defaultInterval: "bogus", + prefInterval: "test0.timer.interval", + contractID: "@mozilla.org/test0/timercallback;1", + method: "createInstance", + classID: Components.ID("9c7ce81f-98bb-4729-adb4-4d0deb0f59e5"), + notified: false +}, { desc: "Test Timer Callback 1", timerID: "test1-update-timer", - defaultInterval: "bogus", + defaultInterval: 86400, prefInterval: "test1.timer.interval", - contractID: "@mozilla.org/test1/timercallback;1", + contractID: "@mozilla.org/test2/timercallback;1", method: "createInstance", - classID: Components.ID("9c7ce81f-98bb-4729-adb4-4d0deb0f59e5"), + classID: Components.ID("512834f3-05bb-46be-84e0-81d881a140b7"), notified: false }, { desc: "Test Timer Callback 2", timerID: "test2-update-timer", - defaultInterval: 86400, + defaultInterval: CONSUMER_TIMER_INTERVAL, prefInterval: "test2.timer.interval", contractID: "@mozilla.org/test2/timercallback;1", method: "createInstance", - classID: Components.ID("512834f3-05bb-46be-84e0-81d881a140b7"), + classID: Components.ID("c8ac5027-8d11-4471-9d7c-fd692501b437"), notified: false }, { desc: "Test Timer Callback 3", @@ -47,7 +56,7 @@ prefInterval: "test3.timer.interval", contractID: "@mozilla.org/test3/timercallback;1", method: "createInstance", - classID: Components.ID("c8ac5027-8d11-4471-9d7c-fd692501b437"), + classID: Components.ID("6b0e79f3-4ab8-414c-8f14-dde10e185727"), notified: false }, { desc: "Test Timer Callback 4", @@ -56,34 +65,35 @@ prefInterval: "test4.timer.interval", contractID: "@mozilla.org/test4/timercallback;1", method: "createInstance", - classID: Components.ID("6b0e79f3-4ab8-414c-8f14-dde10e185727"), + classID: Components.ID("2f6b7b92-e40f-4874-bfbb-eeb2412c959d"), notified: false }, { desc: "Test Timer Callback 5", timerID: "test5-update-timer", - defaultInterval: CONSUMER_TIMER_INTERVAL, + defaultInterval: 86400, prefInterval: "test5.timer.interval", contractID: "@mozilla.org/test5/timercallback;1", method: "createInstance", - classID: Components.ID("2f6b7b92-e40f-4874-bfbb-eeb2412c959d"), + classID: Components.ID("8a95f611-b2ac-4c7e-8b73-9748c4839731"), notified: false }, { desc: "Test Timer Callback 6", timerID: "test6-update-timer", - defaultInterval: 86400, + defaultInterval: CONSUMER_TIMER_INTERVAL, prefInterval: "test6.timer.interval", contractID: "@mozilla.org/test6/timercallback;1", method: "createInstance", - classID: Components.ID("8a95f611-b2ac-4c7e-8b73-9748c4839731"), + classID: Components.ID("2d091020-e23c-11e2-a28f-0800200c9a66"), notified: false }, { desc: "Test Timer Callback 7", timerID: "test7-update-timer", - defaultInterval: CONSUMER_TIMER_INTERVAL, + defaultInterval: 86400, + maxInterval: CONSUMER_TIMER_INTERVAL, prefInterval: "test7.timer.interval", contractID: "@mozilla.org/test7/timercallback;1", method: "createInstance", - classID: Components.ID("2d091020-e23c-11e2-a28f-0800200c9a66"), + classID: Components.ID("8e8633ae-1d70-4a7a-8bea-6e1e6c5d7742"), notified: false }, { desc: "Test Timer Callback 8", @@ -103,8 +113,6 @@ lastUpdateTime: 0 } ]; -const DEBUG_TEST = false; - var gUTM; var gNextFunc; @@ -120,15 +128,35 @@ return Cm.QueryInterface(Ci.nsIComponentRegistrar); }); +const gTest0TimerCallback = { + notify: function T0CB_notify(aTimer) { + // This can happen when another notification fails and this timer having + // time to fire so check other timers are successful. + do_throw("gTest0TimerCallback notify method should not have been called"); + }, + QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback]) +}; + +const gTest0Factory = { + createInstance: function T0F_createInstance(aOuter, aIID) { + if (aOuter == null) { + return gTest0TimerCallback.QueryInterface(aIID); + } + throw Cr.NS_ERROR_NO_AGGREGATION; + } +}; + const gTest1TimerCallback = { notify: function T1CB_notify(aTimer) { + // This can happen when another notification fails and this timer having + // time to fire so check other timers are successful. do_throw("gTest1TimerCallback notify method should not have been called"); }, - QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback]) + QueryInterface: XPCOMUtils.generateQI([Ci.nsITimer]) }; const gTest1Factory = { - createInstance: function (aOuter, aIID) { + createInstance: function T1F_createInstance(aOuter, aIID) { if (aOuter == null) { return gTest1TimerCallback.QueryInterface(aIID); } @@ -138,13 +166,15 @@ const gTest2TimerCallback = { notify: function T2CB_notify(aTimer) { + // This can happen when another notification fails and this timer having + // time to fire so check other timers are successful. do_throw("gTest2TimerCallback notify method should not have been called"); }, - QueryInterface: XPCOMUtils.generateQI([Ci.nsITimer]) + QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback]) }; const gTest2Factory = { - createInstance: function (aOuter, aIID) { + createInstance: function T2F_createInstance(aOuter, aIID) { if (aOuter == null) { return gTest2TimerCallback.QueryInterface(aIID); } @@ -153,14 +183,11 @@ }; const gTest3TimerCallback = { - notify: function T3CB_notify(aTimer) { - do_throw("gTest3TimerCallback notify method should not have been called"); - }, QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback]) }; const gTest3Factory = { - createInstance: function (aOuter, aIID) { + createInstance: function T3F_createInstance(aOuter, aIID) { if (aOuter == null) { return gTest3TimerCallback.QueryInterface(aIID); } @@ -169,11 +196,16 @@ }; const gTest4TimerCallback = { + notify: function T4CB_notify(aTimer) { + gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[4].desc, true); + TESTS[4].notified = true; + finished_test0thru7(); + }, QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback]) }; const gTest4Factory = { - createInstance: function (aOuter, aIID) { + createInstance: function T4F_createInstance(aOuter, aIID) { if (aOuter == null) { return gTest4TimerCallback.QueryInterface(aIID); } @@ -183,15 +215,15 @@ const gTest5TimerCallback = { notify: function T5CB_notify(aTimer) { - gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[4].desc, true); - TESTS[4].notified = true; - finished_test1thru7(); + gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[5].desc, true); + TESTS[5].notified = true; + finished_test0thru7(); }, QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback]) }; const gTest5Factory = { - createInstance: function (aOuter, aIID) { + createInstance: function T5F_createInstance(aOuter, aIID) { if (aOuter == null) { return gTest5TimerCallback.QueryInterface(aIID); } @@ -201,15 +233,15 @@ const gTest6TimerCallback = { notify: function T6CB_notify(aTimer) { - gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[5].desc, true); - TESTS[5].notified = true; - finished_test1thru7(); + gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[6].desc, true); + TESTS[6].notified = true; + finished_test0thru7(); }, QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback]) }; const gTest6Factory = { - createInstance: function (aOuter, aIID) { + createInstance: function T6F_createInstance(aOuter, aIID) { if (aOuter == null) { return gTest6TimerCallback.QueryInterface(aIID); } @@ -219,15 +251,15 @@ const gTest7TimerCallback = { notify: function T7CB_notify(aTimer) { - gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[6].desc, true); - TESTS[6].notified = true; - finished_test1thru7(); + gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[7].desc, true); + TESTS[7].notified = true; + finished_test0thru7(); }, QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback]) }; const gTest7Factory = { - createInstance: function (aOuter, aIID) { + createInstance: function T7F_createInstance(aOuter, aIID) { if (aOuter == null) { return gTest7TimerCallback.QueryInterface(aIID); } @@ -237,17 +269,17 @@ const gTest8TimerCallback = { notify: function T8CB_notify(aTimer) { - TESTS[7].notified = true; - TESTS[7].notifyTime = Date.now(); + TESTS[8].notified = true; + TESTS[8].notifyTime = Date.now(); do_execute_soon(function () { - check_test8(gTest8TimerCallback); + check_test8thru9(gTest8TimerCallback); }); }, QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback]) }; const gTest8Factory = { - createInstance: function (aOuter, aIID) { + createInstance: function T8F_createInstance(aOuter, aIID) { if (aOuter == null) { return gTest8TimerCallback.QueryInterface(aIID); } @@ -257,17 +289,17 @@ const gTest9TimerCallback = { notify: function T9CB_notify(aTimer) { - TESTS[8].notified = true; - TESTS[8].notifyTime = Date.now(); + TESTS[9].notified = true; + TESTS[9].notifyTime = Date.now(); do_execute_soon(function () { - check_test8(gTest9TimerCallback); + check_test8thru9(gTest9TimerCallback); }); }, QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback]) }; const gTest9Factory = { - createInstance: function (aOuter, aIID) { + createInstance: function T9F_createInstance(aOuter, aIID) { if (aOuter == null) { return gTest9TimerCallback.QueryInterface(aIID); } @@ -295,7 +327,7 @@ QueryInterface(Ci.nsIObserver); gUTM.observe(null, "utm-test-init", ""); - do_execute_soon(run_test1thru7); + do_execute_soon(run_test0thru7); } function end_test() { @@ -303,11 +335,11 @@ do_test_finished(); } -function run_test1thru7() { - gNextFunc = check_test1thru7; +function run_test0thru7() { + gNextFunc = check_test0thru7; // bogus default interval gCompReg.registerFactory(TESTS[0].classID, TESTS[0].desc, - TESTS[0].contractID, gTest1Factory); + TESTS[0].contractID, gTest0Factory); gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[0].desc, [TESTS[0].contractID, TESTS[0].method, TESTS[0].timerID, TESTS[0].prefInterval, @@ -315,7 +347,7 @@ // doesn't implement nsITimerCallback gCompReg.registerFactory(TESTS[1].classID, TESTS[1].desc, - TESTS[1].contractID, gTest2Factory); + TESTS[1].contractID, gTest1Factory); gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[1].desc, [TESTS[1].contractID, TESTS[1].method, TESTS[1].timerID, TESTS[1].prefInterval, @@ -325,7 +357,7 @@ let lastUpdateTime = Math.round(Date.now() / 1000) - 43200; gPref.setIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[2].timerID, lastUpdateTime); gCompReg.registerFactory(TESTS[2].classID, TESTS[2].desc, - TESTS[2].contractID, gTest3Factory); + TESTS[2].contractID, gTest2Factory); gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[2].desc, [TESTS[2].contractID, TESTS[2].method, TESTS[2].timerID, TESTS[2].prefInterval, @@ -333,7 +365,7 @@ // doesn't have a notify method gCompReg.registerFactory(TESTS[3].classID, TESTS[3].desc, - TESTS[3].contractID, gTest4Factory); + TESTS[3].contractID, gTest3Factory); gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[3].desc, [TESTS[3].contractID, TESTS[3].method, TESTS[3].timerID, TESTS[3].prefInterval, @@ -342,7 +374,7 @@ // already has a last update time gPref.setIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[4].timerID, 1); gCompReg.registerFactory(TESTS[4].classID, TESTS[4].desc, - TESTS[4].contractID, gTest5Factory); + TESTS[4].contractID, gTest4Factory); gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[4].desc, [TESTS[4].contractID, TESTS[4].method, TESTS[4].timerID, TESTS[4].prefInterval, @@ -351,7 +383,7 @@ // has an interval preference that overrides the default gPref.setIntPref(TESTS[5].prefInterval, CONSUMER_TIMER_INTERVAL); gCompReg.registerFactory(TESTS[5].classID, TESTS[5].desc, - TESTS[5].contractID, gTest6Factory); + TESTS[5].contractID, gTest5Factory); gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[5].desc, [TESTS[5].contractID, TESTS[5].method, TESTS[5].timerID, TESTS[5].prefInterval, @@ -361,149 +393,127 @@ let nextUpdateTime = Math.round(Date.now() / 1000) + 86400; gPref.setIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[6].timerID, nextUpdateTime); gCompReg.registerFactory(TESTS[6].classID, TESTS[6].desc, - TESTS[6].contractID, gTest7Factory); + TESTS[6].contractID, gTest6Factory); gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[6].desc, [TESTS[6].contractID, TESTS[6].method, TESTS[6].timerID, TESTS[6].prefInterval, TESTS[6].defaultInterval].join(","), false, true); + + // has a maximum interval set by the value of MAIN_TIMER_INTERVAL + gPref.setIntPref(TESTS[7].prefInterval, 86400); + gCompReg.registerFactory(TESTS[7].classID, TESTS[7].desc, + TESTS[7].contractID, gTest7Factory); + gCatMan.addCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[7].desc, + [TESTS[7].contractID, TESTS[7].method, + TESTS[7].timerID, TESTS[7].prefInterval, + TESTS[7].defaultInterval, + TESTS[7].maxInterval].join(","), false, true); } -function finished_test1thru7() { - if (TESTS[4].notified && TESTS[5].notified && TESTS[6].notified) { +function finished_test0thru7() { + if (TESTS[4].notified && TESTS[5].notified && TESTS[6].notified && TESTS[7].notified) { do_execute_soon(gNextFunc); } } -function check_test1thru7() { - debugDump("Testing: a category registered timer didn't fire due to an " + - "invalid default interval"); - do_check_false(TESTS[0].notified); - - debugDump("Testing: a category registered timer didn't fire due to not " + - "implementing nsITimerCallback"); - do_check_false(TESTS[1].notified); - - debugDump("Testing: a category registered timer didn't fire due to the " + - "next update time being in the future"); - do_check_false(TESTS[2].notified); - - debugDump("Testing: a category registered timer didn't fire due to not " + - "having a notify method"); - do_check_false(TESTS[3].notified); +function check_test0thru7() { + Assert.ok(!TESTS[0].notified, + "a category registered timer didn't fire due to an invalid " + + "default interval"); + + Assert.ok(!TESTS[1].notified, + "a category registered timer didn't fire due to not implementing " + + "nsITimerCallback"); + + Assert.ok(!TESTS[2].notified, + "a category registered timer didn't fire due to the next update " + + "time being in the future"); + + Assert.ok(!TESTS[3].notified, + "a category registered timer didn't fire due to not having a " + + "notify method"); - debugDump("Testing: a category registered timer has fired"); - do_check_true(TESTS[4].notified); + Assert.ok(TESTS[4].notified, + "a category registered timer has fired"); - debugDump("Testing: a category registered timer fired that has an interval " + + Assert.ok(TESTS[5].notified, + "a category registered timer fired that has an interval " + "preference that overrides a default that wouldn't have fired yet"); - do_check_true(TESTS[5].notified); - debugDump("Testing: a category registered timer has fired due to the next " + - "update time being reset due to a future last update time"); - do_check_true(TESTS[6].notified); - - debugDump("Testing: two category registered timers last update time has " + - "user values"); - do_check_true(gPref.prefHasUserValue(PREF_BRANCH_LAST_UPDATE_TIME + - TESTS[4].timerID)); - do_check_true(gPref.prefHasUserValue(PREF_BRANCH_LAST_UPDATE_TIME + - TESTS[5].timerID)); + Assert.ok(TESTS[6].notified, + "a category registered timer has fired due to the next update " + + "time being reset due to a future last update time"); + + Assert.ok(gPref.prefHasUserValue(PREF_BRANCH_LAST_UPDATE_TIME + + TESTS[4].timerID), + "first of two category registered timers last update time has " + + "a user value"); + Assert.ok(gPref.prefHasUserValue(PREF_BRANCH_LAST_UPDATE_TIME + + TESTS[5].timerID), + "second of two category registered timers last update time has " + + "a user value"); // Remove the category timers that should have failed gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[0].desc, true); gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[1].desc, true); gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[2].desc, true); gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, TESTS[3].desc, true); - let count = 0; let entries = gCatMan.enumerateCategory(CATEGORY_UPDATE_TIMER); while (entries.hasMoreElements()) { let entry = entries.getNext().QueryInterface(Ci.nsISupportsCString).data; gCatMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, entry, false); - count++; } - debugDump("Testing: no " + CATEGORY_UPDATE_TIMER + " categories are still " + + + entries = gCatMan.enumerateCategory(CATEGORY_UPDATE_TIMER); + Assert.ok(!entries.hasMoreElements(), + "no " + CATEGORY_UPDATE_TIMER + " categories should still be " + "registered"); - do_check_eq(count, 0); - do_execute_soon(run_test8); + do_execute_soon(run_test8thru9); } -function run_test8() { - for (let i = 0; i < 2; i++) { - gPref.setIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[7 + i].timerID, 1); - gCompReg.registerFactory(TESTS[7 + i].classID, TESTS[7 + i].desc, - TESTS[7 + i].contractID, eval("gTest" + (8 + i) + "Factory")); - gUTM.registerTimer(TESTS[7 + i].timerID, eval("gTest" + (8 + i) + "TimerCallback"), - TESTS[7 + i].defaultInterval); - } +function run_test8thru9() { + gPref.setIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[8].timerID, 1); + gCompReg.registerFactory(TESTS[8].classID, TESTS[8].desc, + TESTS[8].contractID, gTest8Factory); + gUTM.registerTimer(TESTS[8].timerID, gTest8TimerCallback, + TESTS[8].defaultInterval); + gPref.setIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[9].timerID, 1); + gCompReg.registerFactory(TESTS[9].classID, TESTS[9].desc, + TESTS[9].contractID, gTest9Factory); + gUTM.registerTimer(TESTS[9].timerID, gTest9TimerCallback, + TESTS[9].defaultInterval); } -function check_test8(aTestTimerCallback) { +function check_test8thru9(aTestTimerCallback) { aTestTimerCallback.timesCalled = (aTestTimerCallback.timesCalled || 0) + 1; if (aTestTimerCallback.timesCalled < 2) { return; } - debugDump("Testing: two registerTimer registered timers have fired"); - for (let i = 0; i < 2; i++) { - do_check_true(TESTS[7 + i].notified); - } + Assert.ok(TESTS[8].notified, + "first registerTimer registered timer should have fired"); + + Assert.ok(TESTS[9].notified, + "second registerTimer registered timer should have fired"); // Check that 'staggering' has happened: even though the two events wanted to fire at // the same time, we waited a full MAIN_TIMER_INTERVAL between them. // (to avoid sensitivity to random timing issues, we fudge by a factor of 0.5 here) - do_check_true(Math.abs(TESTS[7].notifyTime - TESTS[8].notifyTime) >= - MAIN_TIMER_INTERVAL * 0.5); + Assert.ok(Math.abs(TESTS[8].notifyTime - TESTS[9].notifyTime) >= + MAIN_TIMER_INTERVAL * 0.5, + "staggering between two timers that want to fire at the same " + + "time should have occured"); + + let time = gPref.getIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[8].timerID); + Assert.notEqual(time, 1, + "first registerTimer registered timer last update time " + + "should have been updated"); + + time = gPref.getIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[9].timerID); + Assert.notEqual(time, 1, + "second registerTimer registered timer last update time " + + "should have been updated"); - debugDump("Testing: two registerTimer registered timers last update time " + - "have been updated"); - for (let i = 0; i < 2; i++) { - do_check_neq(gPref.getIntPref(PREF_BRANCH_LAST_UPDATE_TIME + TESTS[7 + i].timerID), 1); - } end_test(); } - -/** - * Logs TEST-INFO messages. - * - * @param aText - * The text to log. - * @param aCaller (optional) - * An optional Components.stack.caller. If not specified - * Components.stack.caller will be used. - */ -function logTestInfo(aText, aCaller) { - let caller = aCaller ? aCaller : Components.stack.caller; - let now = new Date(); - let hh = now.getHours(); - let mm = now.getMinutes(); - let ss = now.getSeconds(); - let ms = now.getMilliseconds(); - let time = (hh < 10 ? "0" + hh : hh) + ":" + - (mm < 10 ? "0" + mm : mm) + ":" + - (ss < 10 ? "0" + ss : ss) + ":"; - if (ms < 10) { - time += "00"; - } else if (ms < 100) { - time += "0"; - } - time += ms; - let msg = time + " | TEST-INFO | " + caller.filename + " | [" + caller.name + - " : " + caller.lineNumber + "] " + aText; - do_print(msg); -} - -/** - * Logs TEST-INFO messages when DEBUG_TEST evaluates to true. - * - * @param aText - * The text to log. - * @param aCaller (optional) - * An optional Components.stack.caller. If not specified - * Components.stack.caller will be used. - */ -function debugDump(aText, aCaller) { - if (DEBUG_TEST) { - logTestInfo(aText, aCaller); - } -} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/tooltiptext/tests/browser_bug581947.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/tooltiptext/tests/browser_bug581947.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/tooltiptext/tests/browser_bug581947.js 2016-11-11 02:03:26.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/tooltiptext/tests/browser_bug581947.js 2016-11-14 02:02:52.000000000 +0000 @@ -1,6 +1,5 @@ function check(aBrowser, aElementName, aBarred, aType) { return ContentTask.spawn(aBrowser, [aElementName, aBarred, aType], function*([aElementName, aBarred, aType]) { - let doc = content.document; let e = content.document.createElement(aElementName); let contentElement = content.document.getElementById('content'); contentElement.appendChild(e); @@ -39,7 +38,6 @@ function todo_check(aBrowser, aElementName, aBarred) { return ContentTask.spawn(aBrowser, [aElementName, aBarred], function*([aElementName, aBarred]) { - let doc = content.document; let e = content.document.createElement(aElementName); let contentElement = content.document.getElementById('content'); contentElement.appendChild(e); @@ -87,4 +85,3 @@ } }); }); - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/viewsource/content/viewSource-content.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/viewsource/content/viewSource-content.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/viewsource/content/viewSource-content.js 2016-11-11 02:03:29.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/viewsource/content/viewSource-content.js 2016-11-14 02:02:57.000000000 +0000 @@ -237,8 +237,8 @@ let utils = requestor.getInterface(Ci.nsIDOMWindowUtils); let doc = contentWindow.document; - let forcedCharSet = utils.docCharsetIsForced ? doc.characterSet - : null; + forcedCharSet = utils.docCharsetIsForced ? doc.characterSet + : null; } this.loadSource(URL, pageDescriptor, lineNumber, forcedCharSet); @@ -289,7 +289,6 @@ */ loadSource(URL, pageDescriptor, lineNumber, forcedCharSet) { const viewSrcURL = "view-source:" + URL; - let loadFromURL = false; if (forcedCharSet) { docShell.charset = forcedCharSet; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/viewsource/content/viewSourceUtils.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/viewsource/content/viewSourceUtils.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/viewsource/content/viewSourceUtils.js 2016-11-11 02:03:30.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/viewsource/content/viewSourceUtils.js 2016-11-14 02:02:57.000000000 +0000 @@ -127,7 +127,6 @@ message.data.baseURI); } else { - let docUrl = null; window.openDialog("chrome://global/content/viewPartialSource.xul", "_blank", "all,dialog=no", { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/viewsource/test/browser/browser_gotoline.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/viewsource/test/browser/browser_gotoline.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/viewsource/test/browser/browser_gotoline.js 2016-11-11 02:03:30.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/viewsource/test/browser/browser_gotoline.js 2016-11-14 02:02:57.000000000 +0000 @@ -19,7 +19,6 @@ var checkViewSource = Task.async(function* (aWindow) { is(aWindow.gBrowser.contentDocument.body.textContent, content, "Correct content loaded"); - let selection = aWindow.gBrowser.contentWindow.getSelection(); let statusPanel = aWindow.document.getElementById("statusbar-line-col"); is(statusPanel.getAttribute("label"), "", "Correct status bar text"); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/workerloader/require.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/workerloader/require.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/components/workerloader/require.js 2016-11-11 02:03:30.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/components/workerloader/require.js 2016-11-14 02:03:23.000000000 +0000 @@ -121,8 +121,6 @@ } modules.set(path, module); - let name = ":" + path; - let objectURL; try { // Load source of module, synchronously let xhr = new XMLHttpRequest(); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/content/browser-content.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/content/browser-content.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/content/browser-content.js 2016-11-11 02:03:52.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/content/browser-content.js 2016-11-14 02:03:25.000000000 +0000 @@ -1013,7 +1013,11 @@ if (topic === "audio-playback") { if (subject && subject.top == global.content) { let name = "AudioPlayback:"; - name += (data === "active") ? "Start" : "Stop"; + if (data === "block") { + name += "Block"; + } else { + name += (data === "active") ? "Start" : "Stop"; + } sendAsyncMessage(name); } } else if (topic == "AudioFocusChanged" || topic == "MediaControl") { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/content/widgets/autocomplete.xml firefox-trunk-52.0~a1~hg20161113r322177/toolkit/content/widgets/autocomplete.xml --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/content/widgets/autocomplete.xml 2016-11-11 02:04:38.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/content/widgets/autocomplete.xml 2016-11-14 02:04:08.000000000 +0000 @@ -2127,6 +2127,10 @@ titleLooksLikeUrl = true; let visitStr = this._stringBundle.GetStringFromName("visit"); this._setUpDescription(this._actionText, visitStr, true); + } else if (action.type == "extension") { + let content = action.params.content; + displayUrl = content; + this._setUpDescription(this._actionText, content, true); } } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/content/widgets/browser.xml firefox-trunk-52.0~a1~hg20161113r322177/toolkit/content/widgets/browser.xml --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/content/widgets/browser.xml 2016-11-11 02:04:38.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/content/widgets/browser.xml 2016-11-14 02:04:08.000000000 +0000 @@ -690,6 +690,12 @@ let event = document.createEvent("Events"); event.initEvent("DOMAudioPlaybackStarted", true, false); this.dispatchEvent(event); + if (this._audioBlocked) { + this._audioBlocked = false; + event = document.createEvent("Events"); + event.initEvent("DOMAudioPlaybackBlockStopped", true, false); + this.dispatchEvent(event); + } ]]> @@ -704,11 +710,28 @@ + + + + + + false + + false + + @@ -767,8 +791,12 @@ @@ -922,6 +950,7 @@ this.messageManager.addMessageListener("Autoscroll:Cancel", this); this.messageManager.addMessageListener("AudioPlayback:Start", this); this.messageManager.addMessageListener("AudioPlayback:Stop", this); + this.messageManager.addMessageListener("AudioPlayback:Block", this); } ]]> @@ -1008,6 +1037,9 @@ case "AudioPlayback:Stop": this.audioPlaybackStopped(); break; + case "AudioPlayback:Block": + this.audioPlaybackBlocked(); + break; } return undefined; ]]> diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/content/widgets/remote-browser.xml firefox-trunk-52.0~a1~hg20161113r322177/toolkit/content/widgets/remote-browser.xml --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/content/widgets/remote-browser.xml 2016-11-11 02:04:39.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/content/widgets/remote-browser.xml 2016-11-14 02:04:09.000000000 +0000 @@ -469,7 +469,10 @@ let menulist = document.getElementById(this.getAttribute("selectmenulist")); menulist.menupopup.style.direction = data.direction; - this._selectParentHelper.populate(menulist, data.options, data.selectedIndex, this._fullZoom); + + let zoom = Services.prefs.getBoolPref("browser.zoom.full") || + this.isSyntheticDocument ? this._fullZoom : this._textZoom; + this._selectParentHelper.populate(menulist, data.options, data.selectedIndex, zoom); this._selectParentHelper.open(this, menulist, data.rect, data.isOpenedViaTouch); break; } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/.eslintrc.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/.eslintrc.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/.eslintrc.js 2016-11-11 01:55:15.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/.eslintrc.js 2016-11-14 01:53:52.000000000 +0000 @@ -154,7 +154,11 @@ "no-unreachable": "error", // No declaring variables that are never used - // "no-unused-vars": ["error", {"vars": "all", "args": "none"}], + // "no-unused-vars": ["error", { + // "vars": "local", + // "varsIgnorePattern": "^Cc|Ci|Cu|Cr|EXPORTED_SYMBOLS", + // "args": "none", + // }], // No using variables before defined // "no-use-before-define": ["error", "nofunc"], diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/forgetaboutsite/test/unit/test_removeDataFromDomain.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/forgetaboutsite/test/unit/test_removeDataFromDomain.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/forgetaboutsite/test/unit/test_removeDataFromDomain.js 2016-11-11 02:06:04.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/forgetaboutsite/test/unit/test_removeDataFromDomain.js 2016-11-14 02:06:28.000000000 +0000 @@ -64,7 +64,7 @@ function promiseIsURIVisited(aURI) { let deferred = Promise.defer(); - PlacesUtils.asyncHistory.isURIVisited(aURI, function(aURI, aIsVisited) { + PlacesUtils.asyncHistory.isURIVisited(aURI, function(unused, aIsVisited) { deferred.resolve(aIsVisited); }); @@ -459,6 +459,22 @@ do_check_false(yield preference_exists(TEST_URI)); } +function push_registration_exists(aURL, ps) +{ + return new Promise(resolve => { + let ssm = Cc["@mozilla.org/scriptsecuritymanager;1"] + .getService(Ci.nsIScriptSecurityManager); + let principal = ssm.createCodebasePrincipalFromOrigin(aURL); + return ps.getSubscription(aURL, principal, (status, record) => { + if (!Components.isSuccessCode(status)) { + resolve(false); + } else { + resolve(!!record); + } + }); + }); +} + // Push function* test_push_cleared() { @@ -479,28 +495,12 @@ let db = PushServiceWebSocket.newPushDB(); - function push_registration_exists(aURL, ps) - { - return new Promise(resolve => { - let ssm = Cc["@mozilla.org/scriptsecuritymanager;1"] - .getService(Ci.nsIScriptSecurityManager); - let principal = ssm.createCodebasePrincipalFromOrigin(aURL); - return ps.getSubscription(aURL, principal, (status, record) => { - if (!Components.isSuccessCode(status)) { - resolve(false); - } else { - resolve(!!record); - } - }); - }); - } - try { PushService.init({ serverURI: "wss://push.example.org/", db, - makeWebSocket(uri) { - return new MockWebSocket(uri, { + makeWebSocket(uriObj) { + return new MockWebSocket(uriObj, { onHello(request) { this.serverSendMsg(JSON.stringify({ messageType: 'hello', diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/identity/tests/unit/test_crypto_service.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/identity/tests/unit/test_crypto_service.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/identity/tests/unit/test_crypto_service.js 2016-11-11 02:06:12.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/identity/tests/unit/test_crypto_service.js 2016-11-14 02:06:29.000000000 +0000 @@ -59,9 +59,9 @@ // XXX: test that RSA parameters throw the correct error log("about to sign with DSA key"); - keyPair.sign("foo", function (rv, signature) { - log("DSA sign finished ", rv, signature); - do_check_true(Components.isSuccessCode(rv)); + keyPair.sign("foo", function (rv2, signature) { + log("DSA sign finished ", rv2, signature); + do_check_true(Components.isSuccessCode(rv2)); do_check_true(signature.length > 1); // TODO: verify the signature with the public key run_next_test(); @@ -80,9 +80,9 @@ do_check_true(keyPair.hexRSAPublicKeyExponent.length > 1); log("about to sign with RSA key"); - keyPair.sign("foo", function (rv, signature) { - log("RSA sign finished ", rv, signature); - do_check_true(Components.isSuccessCode(rv)); + keyPair.sign("foo", function (rv2, signature) { + log("RSA sign finished ", rv2, signature); + do_check_true(Components.isSuccessCode(rv2)); do_check_true(signature.length > 1); run_next_test(); }); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/identity/tests/unit/test_jwcrypto.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/identity/tests/unit/test_jwcrypto.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/identity/tests/unit/test_jwcrypto.js 2016-11-11 02:06:22.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/identity/tests/unit/test_jwcrypto.js 2016-11-14 02:06:29.000000000 +0000 @@ -52,8 +52,8 @@ jwcrypto.generateKeyPair( "DS160", function(err, kp) { - jwcrypto.generateAssertion("fake-cert", kp, RP_ORIGIN, (err, backedAssertion) => { - do_check_null(err); + jwcrypto.generateAssertion("fake-cert", kp, RP_ORIGIN, (err2, backedAssertion) => { + do_check_null(err2); do_check_eq(backedAssertion.split("~").length, 2); do_check_eq(backedAssertion.split(".").length, 3); @@ -145,8 +145,8 @@ { duration: MINUTE_MS, localtimeOffsetMsec: localtimeOffsetMsec, now: localMsec}, - function(err, backedAssertion) { - do_check_null(err); + function(err2, backedAssertion) { + do_check_null(err2); // properly formed let cert; @@ -178,8 +178,8 @@ function(err, kp) { jwcrypto.generateAssertion("fake-cert", kp, RP_ORIGIN, {duration: MINUTE_MS}, - function(err, backedAssertion) { - do_check_null(err); + function(err2, backedAssertion) { + do_check_null(err2); // properly formed let cert; @@ -212,8 +212,8 @@ function(err, kp) { do_check_null(err); jwcrypto.generateAssertion("fake-cert", kp, audience, - function(err, backedAssertion) { - do_check_null(err); + function(err2, backedAssertion) { + do_check_null(err2); let [cert, assertion] = backedAssertion.split("~"); let components = extractComponents(assertion); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/modules/addons/WebRequest.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/modules/addons/WebRequest.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/modules/addons/WebRequest.jsm 2016-11-11 02:07:12.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/modules/addons/WebRequest.jsm 2016-11-14 02:07:39.000000000 +0000 @@ -195,7 +195,9 @@ } visitHeaders(visitor) { - this.channel.visitRequestHeaders(visitor); + if (this.channel instanceof Ci.nsIHttpChannel) { + this.channel.visitRequestHeaders(visitor); + } } } @@ -219,13 +221,15 @@ } visitHeaders(visitor) { - this.channel.visitResponseHeaders((name, value) => { - if (name.toLowerCase() === "content-type") { - value = getData(this.channel).contentType || value; - } + if (this.channel instanceof Ci.nsIHttpChannel) { + this.channel.visitResponseHeaders((name, value) => { + if (name.toLowerCase() === "content-type") { + value = getData(this.channel).contentType || value; + } - visitor(name, value); - }); + visitor(name, value); + }); + } } } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/modules/subprocess/test/xpcshell/test_subprocess.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/modules/subprocess/test/xpcshell/test_subprocess.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/modules/subprocess/test/xpcshell/test_subprocess.js 2016-11-11 02:07:12.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/modules/subprocess/test/xpcshell/test_subprocess.js 2016-11-14 02:07:42.000000000 +0000 @@ -195,7 +195,7 @@ let now = Date.now(); const COUNT = 1000; - for (let i = 0; i < COUNT; i++) { + for (let j = 0; j < COUNT; j++) { let [output] = yield Promise.all([ read(proc.stdout), proc.stdin.write(LINE), @@ -539,12 +539,12 @@ arguments: ["-u", TEST_SCRIPT, "pwd"], }, options)); - let pwd = read(proc.stdout); + let pwdOutput = read(proc.stdout); let {exitCode} = yield proc.wait(); equal(exitCode, 0, "Got expected exit code"); - return pwd; + return pwdOutput; } let dir = yield pwd({}); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/modules/subprocess/test/xpcshell/test_subprocess_pathSearch.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/modules/subprocess/test/xpcshell/test_subprocess_pathSearch.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/modules/subprocess/test/xpcshell/test_subprocess_pathSearch.js 2016-11-11 02:07:12.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/modules/subprocess/test/xpcshell/test_subprocess_pathSearch.js 2016-11-14 02:07:42.000000000 +0000 @@ -1,8 +1,8 @@ "use strict"; -let env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment); +let envService = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment); -const PYTHON = env.get("PYTHON"); +const PYTHON = envService.get("PYTHON"); const PYTHON_BIN = OS.Path.basename(PYTHON); const PYTHON_DIR = OS.Path.dirname(PYTHON); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/modules/tests/xpcshell/test_GMPInstallManager.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/modules/tests/xpcshell/test_GMPInstallManager.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/modules/tests/xpcshell/test_GMPInstallManager.js 2016-11-11 02:07:13.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/modules/tests/xpcshell/test_GMPInstallManager.js 2016-11-14 02:07:43.000000000 +0000 @@ -142,10 +142,10 @@ * Tests that a xhr abort() works as expected */ add_test(function test_checkForAddons_abort() { - let xhr = overrideXHR(200, "", { dropRequest: true} ); + let overriddenXhr = overrideXHR(200, "", { dropRequest: true} ); let installManager = new GMPInstallManager(); let promise = installManager.checkForAddons(); - xhr.abort(); + overriddenXhr.abort(); promise.then(res => { do_check_true(res.usedFallback); installManager.uninit(); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/modules/tests/xpcshell/test_Log.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/modules/tests/xpcshell/test_Log.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/modules/tests/xpcshell/test_Log.js 2016-11-11 02:07:13.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/modules/tests/xpcshell/test_Log.js 2016-11-14 02:07:43.000000000 +0000 @@ -489,8 +489,8 @@ */ add_task(function* test_log_err_only() { let log = Log.repository.getLogger("error.only"); - let testFormatter = { format: msg => msg }; - let appender = new MockAppender(testFormatter); + let mockFormatter = { format: msg => msg }; + let appender = new MockAppender(mockFormatter); log.addAppender(appender); /* @@ -540,8 +540,8 @@ */ add_task(function* log_message_with_params() { let log = Log.repository.getLogger("error.logger"); - let testFormatter = { format: msg => msg }; - let appender = new MockAppender(testFormatter); + let mockFormatter = { format: msg => msg }; + let appender = new MockAppender(mockFormatter); log.addAppender(appender); let testParams = {a:1, b:2}; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/modules/tests/xpcshell/test_MatchURLFilters.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/modules/tests/xpcshell/test_MatchURLFilters.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/modules/tests/xpcshell/test_MatchURLFilters.js 2016-11-11 02:07:13.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/modules/tests/xpcshell/test_MatchURLFilters.js 2016-11-14 02:07:43.000000000 +0000 @@ -381,13 +381,13 @@ // Run all the the testCases defined above. for (let currentTest of testCases) { let { - shouldThrow, exceptionMessageContains, - shouldFail, url, filters, + exceptionMessageContains, + url, filters, } = currentTest; - if (shouldThrow) { + if (currentTest.shouldThrow) { expectThrow({url, filters, exceptionMessageContains}) - } else if (shouldFail) { + } else if (currentTest.shouldFail) { expectFail({url, filters}); } else { expectPass({url, filters}); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/AddonManager.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/AddonManager.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/AddonManager.jsm 2016-11-11 02:07:14.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/AddonManager.jsm 2016-11-14 02:07:45.000000000 +0000 @@ -67,10 +67,9 @@ const VALID_TYPES_REGEXP = /^[\w\-]+$/; -const WEBAPI_INSTALL_HOSTS = ["addons.mozilla.org", "addons.cdn.mozilla.net", "testpilot.firefox.com"]; +const WEBAPI_INSTALL_HOSTS = ["addons.mozilla.org", "testpilot.firefox.com"]; const WEBAPI_TEST_INSTALL_HOSTS = [ - "addons.allizom.org", "addons-stage-cdn.allizom.org", - "addons-dev.allizom.org", "addons-dev-cdn-allizom.org", + "addons.allizom.org", "addons-dev.allizom.org", "testpilot.stage.mozaws.net", "testpilot.dev.mozaws.net", "example.com", ]; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/internal/E10SAddonsRollout.jsm firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/internal/E10SAddonsRollout.jsm --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/internal/E10SAddonsRollout.jsm 2016-11-11 02:07:15.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/internal/E10SAddonsRollout.jsm 2016-11-14 02:08:27.000000000 +0000 @@ -121,6 +121,8 @@ // Beta testing on 50 "50allmpc": { addons: [], webextensions: true, mpc: true }, + "51alladdons": { addons: [], webextensions: true, alladdons: true }, + "xpcshell-test": { addons: [ADDONS.test1, ADDONS.test2], webextensions: false }, }; @@ -142,6 +144,14 @@ let policy = RolloutPolicy[policyId]; + if (policy.alladdons) { + if (aAddon.multiprocessCompatible === false) { + return false; + } + + return true; + } + if (policy.webextensions && aAddon.type == "webextension") { return true; } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/head_addons.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/head_addons.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/head_addons.js 2016-11-11 02:08:22.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/head_addons.js 2016-11-14 02:10:11.000000000 +0000 @@ -268,10 +268,9 @@ // NOTE: in some of the new tests, we need to received the real objects instead of // their JSON representations, but most of the current tests expect intallPath // and resourceURI to have been converted to strings. - const {installPath, resourceURI} = info.data; info.data = Object.assign({}, subject.wrappedJSObject.data, { - installPath, - resourceURI, + installPath: info.data.installPath, + resourceURI: info.data.resourceURI, }); } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap.js 2016-11-11 02:08:29.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap.js 2016-11-14 02:10:13.000000000 +0000 @@ -810,16 +810,16 @@ do_check_bootstrappedPref(function() { restartManager(); - AddonManager.getAddonByID(ID1, callback_soon(function(b1) { - do_check_neq(b1, null); - do_check_eq(b1.version, "2.0"); - do_check_false(b1.appDisabled); - do_check_true(b1.userDisabled); - do_check_false(b1.isActive); + AddonManager.getAddonByID(ID1, callback_soon(function(b1_2) { + do_check_neq(b1_2, null); + do_check_eq(b1_2.version, "2.0"); + do_check_false(b1_2.appDisabled); + do_check_true(b1_2.userDisabled); + do_check_false(b1_2.isActive); BootstrapMonitor.checkAddonInstalled(ID1, "2.0"); BootstrapMonitor.checkAddonNotStarted(ID1); - b1.uninstall(); + b1_2.uninstall(); run_test_16(); })); @@ -849,14 +849,14 @@ gAppInfo.inSafeMode = true; startupManager(false); - AddonManager.getAddonByID(ID1, callback_soon(function(b1) { + AddonManager.getAddonByID(ID1, callback_soon(function(b1_2) { // Should still be stopped BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); BootstrapMonitor.checkAddonNotStarted(ID1); - do_check_false(b1.isActive); - do_check_eq(b1.iconURL, null); - do_check_eq(b1.aboutURL, null); - do_check_eq(b1.optionsURL, null); + do_check_false(b1_2.isActive); + do_check_eq(b1_2.iconURL, null); + do_check_eq(b1_2.aboutURL, null); + do_check_eq(b1_2.optionsURL, null); shutdownManager(); gAppInfo.inSafeMode = false; @@ -866,8 +866,8 @@ BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); BootstrapMonitor.checkAddonStarted(ID1, "1.0"); - AddonManager.getAddonByID(ID1, function(b1) { - b1.uninstall(); + AddonManager.getAddonByID(ID1, function(b1_3) { + b1_3.uninstall(); do_execute_soon(run_test_17); }); @@ -1080,14 +1080,14 @@ startupManager(); - AddonManager.getAddonByID(ID1, function(b1) { + AddonManager.getAddonByID(ID1, function(b1_2) { // Should have installed and started BootstrapMonitor.checkAddonInstalled(ID1, "2.0"); BootstrapMonitor.checkAddonStarted(ID1, "2.0"); - do_check_neq(b1, null); - do_check_eq(b1.version, "2.0"); - do_check_true(b1.isActive); - do_check_false(b1.isSystem); + do_check_neq(b1_2, null); + do_check_eq(b1_2.version, "2.0"); + do_check_true(b1_2.isActive); + do_check_false(b1_2.isSystem); // This won't be set as the bootstrap script was gone so we couldn't // uninstall it properly @@ -1100,7 +1100,7 @@ do_check_eq(getStartupOldVersion(), undefined); do_check_bootstrappedPref(function() { - b1.uninstall(); + b1_2.uninstall(); run_test_23(); }); @@ -1184,8 +1184,8 @@ do_check_eq(list.length, 0); restartManager(); - AddonManager.getAddonByID(ID1, callback_soon(function(b1) { - b1.uninstall(); + AddonManager.getAddonByID(ID1, callback_soon(function(b1_2) { + b1_2.uninstall(); restartManager(); testserver.stop(run_test_24); @@ -1266,12 +1266,12 @@ do_check_eq(getUninstallNewVersion(), 4); BootstrapMonitor.checkAddonNotStarted(ID1); - AddonManager.getAddonByID(ID1, function(b1) { - do_check_neq(b1, null); - do_check_eq(b1.version, "4.0"); - do_check_true(b1.isActive); - do_check_false(b1.isSystem); - do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); + AddonManager.getAddonByID(ID1, function(b1_2) { + do_check_neq(b1_2, null); + do_check_eq(b1_2.version, "4.0"); + do_check_true(b1_2.isActive); + do_check_false(b1_2.isSystem); + do_check_eq(b1_2.pendingOperations, AddonManager.PENDING_NONE); do_check_bootstrappedPref(run_test_26); }); @@ -1305,12 +1305,12 @@ do_check_eq(getInstallOldVersion(), 4); BootstrapMonitor.checkAddonStarted(ID1, "1.0"); - AddonManager.getAddonByID(ID1, function(b1) { - do_check_neq(b1, null); - do_check_eq(b1.version, "1.0"); - do_check_true(b1.isActive); - do_check_false(b1.isSystem); - do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); + AddonManager.getAddonByID(ID1, function(b1_2) { + do_check_neq(b1_2, null); + do_check_eq(b1_2.version, "1.0"); + do_check_true(b1_2.isActive); + do_check_false(b1_2.isSystem); + do_check_eq(b1_2.pendingOperations, AddonManager.PENDING_NONE); do_check_bootstrappedPref(run_test_27); }); @@ -1337,22 +1337,22 @@ do_check_eq(getUninstallNewVersion(), 4); BootstrapMonitor.checkAddonNotStarted(ID1); - AddonManager.getAddonByID(ID1, callback_soon(function(b1) { - do_check_neq(b1, null); - do_check_eq(b1.version, "4.0"); - do_check_false(b1.isActive); - do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); + AddonManager.getAddonByID(ID1, callback_soon(function(b1_2) { + do_check_neq(b1_2, null); + do_check_eq(b1_2.version, "4.0"); + do_check_false(b1_2.isActive); + do_check_eq(b1_2.pendingOperations, AddonManager.PENDING_NONE); restartManager(); BootstrapMonitor.checkAddonNotInstalled(ID1); BootstrapMonitor.checkAddonNotStarted(ID1); - AddonManager.getAddonByID(ID1, function(b1) { - do_check_neq(b1, null); - do_check_eq(b1.version, "4.0"); - do_check_false(b1.isActive); - do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); + AddonManager.getAddonByID(ID1, function(b1_3) { + do_check_neq(b1_3, null); + do_check_eq(b1_3.version, "4.0"); + do_check_false(b1_3.isActive); + do_check_eq(b1_3.pendingOperations, AddonManager.PENDING_NONE); do_check_bootstrappedPref(run_test_28); }); @@ -1384,14 +1384,14 @@ BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); BootstrapMonitor.checkAddonNotStarted(ID1); - AddonManager.getAddonByID(ID1, function(b1) { - do_check_neq(b1, null); - do_check_true(b1.userDisabled); - b1.userDisabled = false; - do_check_eq(b1.version, "1.0"); - do_check_true(b1.isActive); - do_check_false(b1.isSystem); - do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); + AddonManager.getAddonByID(ID1, function(b1_2) { + do_check_neq(b1_2, null); + do_check_true(b1_2.userDisabled); + b1_2.userDisabled = false; + do_check_eq(b1_2.version, "1.0"); + do_check_true(b1_2.isActive); + do_check_false(b1_2.isSystem); + do_check_eq(b1_2.pendingOperations, AddonManager.PENDING_NONE); BootstrapMonitor.checkAddonInstalled(ID1, "1.0"); BootstrapMonitor.checkAddonStarted(ID1, "1.0"); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_bug324121.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_bug324121.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_bug324121.js 2016-11-11 02:08:42.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_bug324121.js 2016-11-14 02:10:13.000000000 +0000 @@ -138,9 +138,9 @@ installAllFiles(ADDONS.map(a => do_get_addon(a.addon)), function() { restartManager(); - AddonManager.getAddonByID(ADDONS[0].id, callback_soon(function(addon) { - do_check_true(!(!addon)); - addon.userDisabled = true; + AddonManager.getAddonByID(ADDONS[0].id, callback_soon(function(firstAddon) { + do_check_true(firstAddon); + firstAddon.userDisabled = true; restartManager(); AddonManager.getAddonsByTypes(["extension"], function(installedItems) { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_bug371495.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_bug371495.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_bug371495.js 2016-11-11 02:08:43.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_bug371495.js 2016-11-14 02:10:13.000000000 +0000 @@ -23,10 +23,10 @@ do_check_eq(addon.name, "Test theme"); restartManager(); - AddonManager.getAddonByID(ID, callback_soon(function(addon) { - do_check_neq(addon, null); - do_check_eq(addon.optionsURL, null); - do_check_eq(addon.aboutURL, null); + AddonManager.getAddonByID(ID, callback_soon(function(addon2) { + do_check_neq(addon2, null); + do_check_eq(addon2.optionsURL, null); + do_check_eq(addon2.aboutURL, null); do_execute_soon(do_test_finished); })); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_bug563256.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_bug563256.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_bug563256.js 2016-11-11 02:09:04.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_bug563256.js 2016-11-14 02:10:13.000000000 +0000 @@ -236,22 +236,22 @@ do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "classic/1.0"); AddonManager.getAddonsByIDs(["default@tests.mozilla.org", - "alternate@tests.mozilla.org"], function([d, a]) { - do_check_neq(d, null); - do_check_false(d.userDisabled); - do_check_false(d.appDisabled); - do_check_true(d.isActive); - do_check_true(isThemeInAddonsList(profileDir, d.id)); - do_check_false(hasFlag(d.permissions, AddonManager.PERM_CAN_DISABLE)); - do_check_false(hasFlag(d.permissions, AddonManager.PERM_CAN_ENABLE)); + "alternate@tests.mozilla.org"], function([d2, a2]) { + do_check_neq(d2, null); + do_check_false(d2.userDisabled); + do_check_false(d2.appDisabled); + do_check_true(d2.isActive); + do_check_true(isThemeInAddonsList(profileDir, d2.id)); + do_check_false(hasFlag(d2.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_false(hasFlag(d2.permissions, AddonManager.PERM_CAN_ENABLE)); - do_check_neq(a, null); - do_check_true(a.userDisabled); - do_check_false(a.appDisabled); - do_check_false(a.isActive); - do_check_false(isThemeInAddonsList(profileDir, a.id)); - do_check_false(hasFlag(a.permissions, AddonManager.PERM_CAN_DISABLE)); - do_check_true(hasFlag(a.permissions, AddonManager.PERM_CAN_ENABLE)); + do_check_neq(a2, null); + do_check_true(a2.userDisabled); + do_check_false(a2.appDisabled); + do_check_false(a2.isActive); + do_check_false(isThemeInAddonsList(profileDir, a2.id)); + do_check_false(hasFlag(a2.permissions, AddonManager.PERM_CAN_DISABLE)); + do_check_true(hasFlag(a2.permissions, AddonManager.PERM_CAN_ENABLE)); end_test(); }); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_bug564030.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_bug564030.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_bug564030.js 2016-11-11 02:09:04.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_bug564030.js 2016-11-14 02:10:13.000000000 +0000 @@ -49,13 +49,13 @@ restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a) { - do_check_neq(a, null); - do_check_eq(a.version, "2.0"); - do_check_false(a.userDisabled); - do_check_false(a.appDisabled); - do_check_true(a.isActive); - do_check_true(isExtensionInAddonsList(profileDir, a.id)); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a2) { + do_check_neq(a2, null); + do_check_eq(a2.version, "2.0"); + do_check_false(a2.userDisabled); + do_check_false(a2.appDisabled); + do_check_true(a2.isActive); + do_check_true(isExtensionInAddonsList(profileDir, a2.id)); do_execute_soon(do_test_finished); }); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_bug576735.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_bug576735.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_bug576735.js 2016-11-11 02:09:04.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_bug576735.js 2016-11-14 02:10:13.000000000 +0000 @@ -53,12 +53,12 @@ AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", "addon2@tests.mozilla.org"], - function([a1, a2]) { + function([a1_2, a2_2]) { // Addon1 should no longer be installed - do_check_eq(a1, null); + do_check_eq(a1_2, null); // Addon2 should have been detected - do_check_neq(a2, null); + do_check_neq(a2_2, null); do_execute_soon(do_test_finished); }); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_bug587088.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_bug587088.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_bug587088.js 2016-11-11 02:09:04.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_bug587088.js 2016-11-14 02:10:13.000000000 +0000 @@ -96,22 +96,22 @@ restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { - check_addon_upgrading(a1); + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1_2) { + check_addon_upgrading(a1_2); restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { - check_addon_upgrading(a1); + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1_3) { + check_addon_upgrading(a1_3); fstream.close(); restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { - check_addon(a1, "2.0"); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1_4) { + check_addon(a1_4, "2.0"); - a1.uninstall(); + a1_4.uninstall(); do_execute_soon(run_test_2); }); })); @@ -146,20 +146,20 @@ restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { - check_addon_uninstalling(a1, true); + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1_2) { + check_addon_uninstalling(a1_2, true); restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { - check_addon_uninstalling(a1, true); + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1_3) { + check_addon_uninstalling(a1_3, true); fstream.close(); restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { - do_check_eq(a1, null); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1_4) { + do_check_eq(a1_4, null); var dir = profileDir.clone(); dir.append(do_get_expected_addon_name("addon1@tests.mozilla.org")); do_check_false(dir.exists()); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_bug655254.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_bug655254.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_bug655254.js 2016-11-11 02:09:04.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_bug655254.js 2016-11-14 02:10:14.000000000 +0000 @@ -84,11 +84,11 @@ onUpdateFinished: function() { restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) { - do_check_neq(a1, null); - do_check_false(a1.appDisabled); - do_check_true(a1.isActive); - do_check_true(isExtensionInAddonsList(userDir, a1.id)); + AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1_2) { + do_check_neq(a1_2, null); + do_check_false(a1_2.appDisabled); + do_check_true(a1_2.isActive); + do_check_true(isExtensionInAddonsList(userDir, a1_2.id)); shutdownManager(); @@ -103,16 +103,16 @@ startupManager(false); AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", - "addon2@tests.mozilla.org"], function([a1, a2]) { - do_check_neq(a1, null); - do_check_false(a1.appDisabled); - do_check_true(a1.isActive); - do_check_true(isExtensionInAddonsList(userDir, a1.id)); - - do_check_neq(a2, null); - do_check_false(a2.appDisabled); - do_check_true(a2.isActive); - do_check_false(isExtensionInAddonsList(userDir, a2.id)); + "addon2@tests.mozilla.org"], function([a1_3, a2_3]) { + do_check_neq(a1_3, null); + do_check_false(a1_3.appDisabled); + do_check_true(a1_3.isActive); + do_check_true(isExtensionInAddonsList(userDir, a1_3.id)); + + do_check_neq(a2_3, null); + do_check_false(a2_3.appDisabled); + do_check_true(a2_3.isActive); + do_check_false(isExtensionInAddonsList(userDir, a2_3.id)); do_check_eq(Services.prefs.getIntPref("bootstraptest.active_version"), 1); do_execute_soon(run_test_2); @@ -146,16 +146,16 @@ startupManager(false); AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", - "addon2@tests.mozilla.org"], function([a1, a2]) { - do_check_neq(a1, null); - do_check_false(a1.appDisabled); - do_check_true(a1.isActive); - do_check_true(isExtensionInAddonsList(userDir, a1.id)); - - do_check_neq(a2, null); - do_check_true(a2.userDisabled); - do_check_false(a2.isActive); - do_check_false(isExtensionInAddonsList(userDir, a2.id)); + "addon2@tests.mozilla.org"], function([a1_2, a2_2]) { + do_check_neq(a1_2, null); + do_check_false(a1_2.appDisabled); + do_check_true(a1_2.isActive); + do_check_true(isExtensionInAddonsList(userDir, a1_2.id)); + + do_check_neq(a2_2, null); + do_check_true(a2_2.userDisabled); + do_check_false(a2_2.isActive); + do_check_false(isExtensionInAddonsList(userDir, a2_2.id)); do_check_eq(Services.prefs.getIntPref("bootstraptest.active_version"), 0); end_test(); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_bug659772.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_bug659772.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_bug659772.js 2016-11-11 02:09:04.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_bug659772.js 2016-11-14 02:10:14.000000000 +0000 @@ -148,45 +148,45 @@ "addon2@tests.mozilla.org", "addon3@tests.mozilla.org", "addon4@tests.mozilla.org"], - function([a1, a2, a3, a4]) { - do_check_neq(a1, null); - do_check_eq(a1.version, "2.0"); - do_check_false(a1.appDisabled); - do_check_false(a1.userDisabled); - do_check_true(a1.isActive); + function([a1_2, a2_2, a3_2, a4_2]) { + do_check_neq(a1_2, null); + do_check_eq(a1_2.version, "2.0"); + do_check_false(a1_2.appDisabled); + do_check_false(a1_2.userDisabled); + do_check_true(a1_2.isActive); do_check_true(isExtensionInAddonsList(profileDir, addon1.id)); - do_check_neq(a2, null); - do_check_eq(a2.version, "2.0"); - do_check_false(a2.appDisabled); - do_check_false(a2.userDisabled); - do_check_true(a2.isActive); + do_check_neq(a2_2, null); + do_check_eq(a2_2.version, "2.0"); + do_check_false(a2_2.appDisabled); + do_check_false(a2_2.userDisabled); + do_check_true(a2_2.isActive); do_check_true(isExtensionInAddonsList(profileDir, addon2.id)); // Should stay enabled because we migrate the compat info from // the previous version of the DB - do_check_neq(a3, null); - do_check_eq(a3.version, "2.0"); - todo_check_false(a3.appDisabled); // XXX unresolved issue - do_check_false(a3.userDisabled); - todo_check_true(a3.isActive); // XXX same + do_check_neq(a3_2, null); + do_check_eq(a3_2.version, "2.0"); + todo_check_false(a3_2.appDisabled); // XXX unresolved issue + do_check_false(a3_2.userDisabled); + todo_check_true(a3_2.isActive); // XXX same todo_check_true(isExtensionInAddonsList(profileDir, addon3.id)); // XXX same - do_check_neq(a4, null); - do_check_eq(a4.version, "2.0"); - do_check_true(a4.appDisabled); - do_check_false(a4.userDisabled); - do_check_false(a4.isActive); + do_check_neq(a4_2, null); + do_check_eq(a4_2.version, "2.0"); + do_check_true(a4_2.appDisabled); + do_check_false(a4_2.userDisabled); + do_check_false(a4_2.isActive); do_check_false(isExtensionInAddonsList(profileDir, addon4.id)); // Check that install and uninstall haven't been called on the bootstrapped addon do_check_false(Services.prefs.prefHasUserValue("bootstraptest.install_reason")); do_check_false(Services.prefs.prefHasUserValue("bootstraptest.uninstall_reason")); - a1.uninstall(); - a2.uninstall(); - a3.uninstall(); - a4.uninstall(); + a1_2.uninstall(); + a2_2.uninstall(); + a3_2.uninstall(); + a4_2.uninstall(); do_execute_soon(run_test_2); }); }); @@ -290,45 +290,45 @@ "addon2@tests.mozilla.org", "addon3@tests.mozilla.org", "addon4@tests.mozilla.org"], - callback_soon(function([a1, a2, a3, a4]) { - do_check_neq(a1, null); - do_check_eq(a1.version, "2.0"); - do_check_true(a1.appDisabled); - do_check_false(a1.userDisabled); - do_check_false(a1.isActive); + callback_soon(function([a1_2, a2_2, a3_2, a4_2]) { + do_check_neq(a1_2, null); + do_check_eq(a1_2.version, "2.0"); + do_check_true(a1_2.appDisabled); + do_check_false(a1_2.userDisabled); + do_check_false(a1_2.isActive); do_check_false(isExtensionInAddonsList(profileDir, addon1.id)); - do_check_neq(a2, null); - do_check_eq(a2.version, "2.0"); - do_check_false(a2.appDisabled); - do_check_false(a2.userDisabled); - do_check_true(a2.isActive); + do_check_neq(a2_2, null); + do_check_eq(a2_2.version, "2.0"); + do_check_false(a2_2.appDisabled); + do_check_false(a2_2.userDisabled); + do_check_true(a2_2.isActive); do_check_true(isExtensionInAddonsList(profileDir, addon2.id)); // Should become appDisabled because we migrate the compat info from // the previous version of the DB - do_check_neq(a3, null); - do_check_eq(a3.version, "2.0"); - todo_check_true(a3.appDisabled); - do_check_false(a3.userDisabled); - todo_check_false(a3.isActive); + do_check_neq(a3_2, null); + do_check_eq(a3_2.version, "2.0"); + todo_check_true(a3_2.appDisabled); + do_check_false(a3_2.userDisabled); + todo_check_false(a3_2.isActive); todo_check_false(isExtensionInAddonsList(profileDir, addon3.id)); - do_check_neq(a4, null); - do_check_eq(a4.version, "2.0"); - do_check_false(a4.appDisabled); - do_check_false(a4.userDisabled); - do_check_true(a4.isActive); + do_check_neq(a4_2, null); + do_check_eq(a4_2.version, "2.0"); + do_check_false(a4_2.appDisabled); + do_check_false(a4_2.userDisabled); + do_check_true(a4_2.isActive); do_check_true(isExtensionInAddonsList(profileDir, addon4.id)); // Check that install and uninstall haven't been called on the bootstrapped addon do_check_false(Services.prefs.prefHasUserValue("bootstraptest.install_reason")); do_check_false(Services.prefs.prefHasUserValue("bootstraptest.uninstall_reason")); - a1.uninstall(); - a2.uninstall(); - a3.uninstall(); - a4.uninstall(); + a1_2.uninstall(); + a2_2.uninstall(); + a3_2.uninstall(); + a4_2.uninstall(); restartManager(); shutdownManager(); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_cacheflush.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_cacheflush.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_cacheflush.js 2016-11-11 02:09:04.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_cacheflush.js 2016-11-14 02:10:14.000000000 +0000 @@ -88,7 +88,7 @@ function run_test_3() { AddonManager.getInstallForFile(do_get_addon("test_cacheflush2"), function(aInstall) { aInstall.addListener({ - onInstallStarted: function(aInstall) { + onInstallStarted: function() { // We should flush the staged XPI when completing the install gExpectedFile = gProfD.clone(); gExpectedFile.append("extensions"); @@ -96,7 +96,7 @@ gExpectedFile.append("addon2@tests.mozilla.org.xpi"); }, - onInstallEnded: function(aInstall) { + onInstallEnded: function() { do_check_eq(gCacheFlushCount, 1); gExpectedFile = null; gCacheFlushCount = 0; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js 2016-11-11 02:09:04.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js 2016-11-14 02:10:14.000000000 +0000 @@ -265,70 +265,70 @@ "addon7@tests.mozilla.org", "theme1@tests.mozilla.org", "theme2@tests.mozilla.org"], - callback_soon(function([a1, a2, a3, a4, a5, a6, a7, t1, t2]) { + callback_soon(function([a1_2, a2_2, a3_2, a4_2, a5_2, a6_2, a7_2, t1_2, t2_2]) { // Should be correctly recovered - do_check_neq(a1, null); - do_check_true(a1.isActive); - do_check_false(a1.userDisabled); - do_check_false(a1.appDisabled); - do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + do_check_neq(a1_2, null); + do_check_true(a1_2.isActive); + do_check_false(a1_2.userDisabled); + do_check_false(a1_2.appDisabled); + do_check_eq(a1_2.pendingOperations, AddonManager.PENDING_NONE); // Should be correctly recovered - do_check_neq(a2, null); - do_check_false(a2.isActive); - do_check_true(a2.userDisabled); - do_check_false(a2.appDisabled); - do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE); + do_check_neq(a2_2, null); + do_check_false(a2_2.isActive); + do_check_true(a2_2.userDisabled); + do_check_false(a2_2.appDisabled); + do_check_eq(a2_2.pendingOperations, AddonManager.PENDING_NONE); // The compatibility update won't be recovered but it should still be // active for this session - do_check_neq(a3, null); - do_check_true(a3.isActive); - do_check_false(a3.userDisabled); - do_check_false(a3.appDisabled); - do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE); + do_check_neq(a3_2, null); + do_check_true(a3_2.isActive); + do_check_false(a3_2.userDisabled); + do_check_false(a3_2.appDisabled); + do_check_eq(a3_2.pendingOperations, AddonManager.PENDING_NONE); // The compatibility update won't be recovered and with strict // compatibility it would not have been able to tell that it was // previously userDisabled. However, without strict compat, it wasn't // appDisabled, so it knows it must have been userDisabled. - do_check_neq(a4, null); - do_check_false(a4.isActive); - do_check_true(a4.userDisabled); - do_check_false(a4.appDisabled); - do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a5, null); - do_check_true(a5.isActive); - do_check_false(a5.userDisabled); - do_check_false(a5.appDisabled); - do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a6, null); - do_check_true(a6.isActive); - do_check_false(a6.userDisabled); - do_check_false(a6.appDisabled); - do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a7, null); - do_check_false(a7.isActive); - do_check_true(a7.userDisabled); - do_check_false(a7.appDisabled); - do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE); + do_check_neq(a4_2, null); + do_check_false(a4_2.isActive); + do_check_true(a4_2.userDisabled); + do_check_false(a4_2.appDisabled); + do_check_eq(a4_2.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a5_2, null); + do_check_true(a5_2.isActive); + do_check_false(a5_2.userDisabled); + do_check_false(a5_2.appDisabled); + do_check_eq(a5_2.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a6_2, null); + do_check_true(a6_2.isActive); + do_check_false(a6_2.userDisabled); + do_check_false(a6_2.appDisabled); + do_check_eq(a6_2.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a7_2, null); + do_check_false(a7_2.isActive); + do_check_true(a7_2.userDisabled); + do_check_false(a7_2.appDisabled); + do_check_eq(a7_2.pendingOperations, AddonManager.PENDING_NONE); // Should be correctly recovered - do_check_neq(t1, null); - do_check_false(t1.isActive); - do_check_true(t1.userDisabled); - do_check_false(t1.appDisabled); - do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE); + do_check_neq(t1_2, null); + do_check_false(t1_2.isActive); + do_check_true(t1_2.userDisabled); + do_check_false(t1_2.appDisabled); + do_check_eq(t1_2.pendingOperations, AddonManager.PENDING_NONE); // Should be correctly recovered - do_check_neq(t2, null); - do_check_true(t2.isActive); - do_check_false(t2.userDisabled); - do_check_false(t2.appDisabled); - do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE); + do_check_neq(t2_2, null); + do_check_true(t2_2.isActive); + do_check_false(t2_2.userDisabled); + do_check_false(t2_2.appDisabled); + do_check_eq(t2_2.pendingOperations, AddonManager.PENDING_NONE); Assert.throws(shutdownManager); startupManager(false); @@ -342,60 +342,60 @@ "addon7@tests.mozilla.org", "theme1@tests.mozilla.org", "theme2@tests.mozilla.org"], - callback_soon(function([a1, a2, a3, a4, a5, a6, a7, t1, t2]) { - do_check_neq(a1, null); - do_check_true(a1.isActive); - do_check_false(a1.userDisabled); - do_check_false(a1.appDisabled); - do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a2, null); - do_check_false(a2.isActive); - do_check_true(a2.userDisabled); - do_check_false(a2.appDisabled); - do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a3, null); - do_check_true(a3.isActive); - do_check_false(a3.userDisabled); - do_check_false(a3.appDisabled); - do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a4, null); - do_check_false(a4.isActive); - do_check_true(a4.userDisabled); - do_check_false(a4.appDisabled); - do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a5, null); - do_check_true(a5.isActive); - do_check_false(a5.userDisabled); - do_check_false(a5.appDisabled); - do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a6, null); - do_check_true(a6.isActive); - do_check_false(a6.userDisabled); - do_check_false(a6.appDisabled); - do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a7, null); - do_check_false(a7.isActive); - do_check_true(a7.userDisabled); - do_check_false(a7.appDisabled); - do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(t1, null); - do_check_false(t1.isActive); - do_check_true(t1.userDisabled); - do_check_false(t1.appDisabled); - do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(t2, null); - do_check_true(t2.isActive); - do_check_false(t2.userDisabled); - do_check_false(t2.appDisabled); - do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE); + callback_soon(function([a1_3, a2_3, a3_3, a4_3, a5_3, a6_3, a7_3, t1_3, t2_3]) { + do_check_neq(a1_3, null); + do_check_true(a1_3.isActive); + do_check_false(a1_3.userDisabled); + do_check_false(a1_3.appDisabled); + do_check_eq(a1_3.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a2_3, null); + do_check_false(a2_3.isActive); + do_check_true(a2_3.userDisabled); + do_check_false(a2_3.appDisabled); + do_check_eq(a2_3.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a3_3, null); + do_check_true(a3_3.isActive); + do_check_false(a3_3.userDisabled); + do_check_false(a3_3.appDisabled); + do_check_eq(a3_3.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a4_3, null); + do_check_false(a4_3.isActive); + do_check_true(a4_3.userDisabled); + do_check_false(a4_3.appDisabled); + do_check_eq(a4_3.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a5_3, null); + do_check_true(a5_3.isActive); + do_check_false(a5_3.userDisabled); + do_check_false(a5_3.appDisabled); + do_check_eq(a5_3.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a6_3, null); + do_check_true(a6_3.isActive); + do_check_false(a6_3.userDisabled); + do_check_false(a6_3.appDisabled); + do_check_eq(a6_3.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a7_3, null); + do_check_false(a7_3.isActive); + do_check_true(a7_3.userDisabled); + do_check_false(a7_3.appDisabled); + do_check_eq(a7_3.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t1_3, null); + do_check_false(t1_3.isActive); + do_check_true(t1_3.userDisabled); + do_check_false(t1_3.appDisabled); + do_check_eq(t1_3.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t2_3, null); + do_check_true(t2_3.isActive); + do_check_false(t2_3.userDisabled); + do_check_false(t2_3.appDisabled); + do_check_eq(t2_3.pendingOperations, AddonManager.PENDING_NONE); Assert.throws(shutdownManager); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_corrupt_strictcompat.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_corrupt_strictcompat.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_corrupt_strictcompat.js 2016-11-11 02:09:04.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_corrupt_strictcompat.js 2016-11-14 02:10:14.000000000 +0000 @@ -266,68 +266,68 @@ "addon7@tests.mozilla.org", "theme1@tests.mozilla.org", "theme2@tests.mozilla.org"], - callback_soon(function([a1, a2, a3, a4, a5, a6, a7, t1, t2]) { + callback_soon(function([a1_2, a2_2, a3_2, a4_2, a5_2, a6_2, a7_2, t1_2, t2_2]) { // Should be correctly recovered - do_check_neq(a1, null); - do_check_true(a1.isActive); - do_check_false(a1.userDisabled); - do_check_false(a1.appDisabled); - do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); + do_check_neq(a1_2, null); + do_check_true(a1_2.isActive); + do_check_false(a1_2.userDisabled); + do_check_false(a1_2.appDisabled); + do_check_eq(a1_2.pendingOperations, AddonManager.PENDING_NONE); // Should be correctly recovered - do_check_neq(a2, null); - do_check_false(a2.isActive); - do_check_true(a2.userDisabled); - do_check_false(a2.appDisabled); - do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE); + do_check_neq(a2_2, null); + do_check_false(a2_2.isActive); + do_check_true(a2_2.userDisabled); + do_check_false(a2_2.appDisabled); + do_check_eq(a2_2.pendingOperations, AddonManager.PENDING_NONE); // The compatibility update won't be recovered but it should still be // active for this session - do_check_neq(a3, null); - do_check_true(a3.isActive); - do_check_false(a3.userDisabled); - do_check_true(a3.appDisabled); - do_check_eq(a3.pendingOperations, AddonManager.PENDING_DISABLE); + do_check_neq(a3_2, null); + do_check_true(a3_2.isActive); + do_check_false(a3_2.userDisabled); + do_check_true(a3_2.appDisabled); + do_check_eq(a3_2.pendingOperations, AddonManager.PENDING_DISABLE); // The compatibility update won't be recovered and it will not have been // able to tell that it was previously userDisabled - do_check_neq(a4, null); - do_check_false(a4.isActive); - do_check_false(a4.userDisabled); - do_check_true(a4.appDisabled); - do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a5, null); - do_check_false(a5.isActive); - do_check_false(a5.userDisabled); - do_check_true(a5.appDisabled); - do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a6, null); - do_check_true(a6.isActive); - do_check_false(a6.userDisabled); - do_check_false(a6.appDisabled); - do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a7, null); - do_check_false(a7.isActive); - do_check_true(a7.userDisabled); - do_check_false(a7.appDisabled); - do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE); + do_check_neq(a4_2, null); + do_check_false(a4_2.isActive); + do_check_false(a4_2.userDisabled); + do_check_true(a4_2.appDisabled); + do_check_eq(a4_2.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a5_2, null); + do_check_false(a5_2.isActive); + do_check_false(a5_2.userDisabled); + do_check_true(a5_2.appDisabled); + do_check_eq(a5_2.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a6_2, null); + do_check_true(a6_2.isActive); + do_check_false(a6_2.userDisabled); + do_check_false(a6_2.appDisabled); + do_check_eq(a6_2.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a7_2, null); + do_check_false(a7_2.isActive); + do_check_true(a7_2.userDisabled); + do_check_false(a7_2.appDisabled); + do_check_eq(a7_2.pendingOperations, AddonManager.PENDING_NONE); // Should be correctly recovered - do_check_neq(t1, null); - do_check_false(t1.isActive); - do_check_true(t1.userDisabled); - do_check_false(t1.appDisabled); - do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE); + do_check_neq(t1_2, null); + do_check_false(t1_2.isActive); + do_check_true(t1_2.userDisabled); + do_check_false(t1_2.appDisabled); + do_check_eq(t1_2.pendingOperations, AddonManager.PENDING_NONE); // Should be correctly recovered - do_check_neq(t2, null); - do_check_true(t2.isActive); - do_check_false(t2.userDisabled); - do_check_false(t2.appDisabled); - do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE); + do_check_neq(t2_2, null); + do_check_true(t2_2.isActive); + do_check_false(t2_2.userDisabled); + do_check_false(t2_2.appDisabled); + do_check_eq(t2_2.pendingOperations, AddonManager.PENDING_NONE); Assert.throws(shutdownManager); startupManager(false); @@ -341,60 +341,60 @@ "addon7@tests.mozilla.org", "theme1@tests.mozilla.org", "theme2@tests.mozilla.org"], - callback_soon(function([a1, a2, a3, a4, a5, a6, a7, t1, t2]) { - do_check_neq(a1, null); - do_check_true(a1.isActive); - do_check_false(a1.userDisabled); - do_check_false(a1.appDisabled); - do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a2, null); - do_check_false(a2.isActive); - do_check_true(a2.userDisabled); - do_check_false(a2.appDisabled); - do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a3, null); - do_check_false(a3.isActive); - do_check_false(a3.userDisabled); - do_check_true(a3.appDisabled); - do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a4, null); - do_check_false(a4.isActive); - do_check_false(a4.userDisabled); - do_check_true(a4.appDisabled); - do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a5, null); - do_check_false(a5.isActive); - do_check_false(a5.userDisabled); - do_check_true(a5.appDisabled); - do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a6, null); - do_check_true(a6.isActive); - do_check_false(a6.userDisabled); - do_check_false(a6.appDisabled); - do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(a7, null); - do_check_false(a7.isActive); - do_check_true(a7.userDisabled); - do_check_false(a7.appDisabled); - do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(t1, null); - do_check_false(t1.isActive); - do_check_true(t1.userDisabled); - do_check_false(t1.appDisabled); - do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE); - - do_check_neq(t2, null); - do_check_true(t2.isActive); - do_check_false(t2.userDisabled); - do_check_false(t2.appDisabled); - do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE); + callback_soon(function([a1_3, a2_3, a3_3, a4_3, a5_3, a6_3, a7_3, t1_3, t2_3]) { + do_check_neq(a1_3, null); + do_check_true(a1_3.isActive); + do_check_false(a1_3.userDisabled); + do_check_false(a1_3.appDisabled); + do_check_eq(a1_3.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a2_3, null); + do_check_false(a2_3.isActive); + do_check_true(a2_3.userDisabled); + do_check_false(a2_3.appDisabled); + do_check_eq(a2_3.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a3_3, null); + do_check_false(a3_3.isActive); + do_check_false(a3_3.userDisabled); + do_check_true(a3_3.appDisabled); + do_check_eq(a3_3.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a4_3, null); + do_check_false(a4_3.isActive); + do_check_false(a4_3.userDisabled); + do_check_true(a4_3.appDisabled); + do_check_eq(a4_3.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a5_3, null); + do_check_false(a5_3.isActive); + do_check_false(a5_3.userDisabled); + do_check_true(a5_3.appDisabled); + do_check_eq(a5_3.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a6_3, null); + do_check_true(a6_3.isActive); + do_check_false(a6_3.userDisabled); + do_check_false(a6_3.appDisabled); + do_check_eq(a6_3.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(a7_3, null); + do_check_false(a7_3.isActive); + do_check_true(a7_3.userDisabled); + do_check_false(a7_3.appDisabled); + do_check_eq(a7_3.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t1_3, null); + do_check_false(t1_3.isActive); + do_check_true(t1_3.userDisabled); + do_check_false(t1_3.appDisabled); + do_check_eq(t1_3.pendingOperations, AddonManager.PENDING_NONE); + + do_check_neq(t2_3, null); + do_check_true(t2_3.isActive); + do_check_false(t2_3.userDisabled); + do_check_false(t2_3.appDisabled); + do_check_eq(t2_3.pendingOperations, AddonManager.PENDING_NONE); Assert.throws(shutdownManager); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_dataDirectory.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_dataDirectory.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_dataDirectory.js 2016-11-11 02:09:04.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_dataDirectory.js 2016-11-14 02:10:14.000000000 +0000 @@ -11,11 +11,11 @@ addon: "test_data_directory" }; -var expectedDir = gProfD.clone(); -expectedDir.append("extension-data"); -expectedDir.append(ADDON.id); - function run_test() { + var expectedDir = gProfD.clone(); + expectedDir.append("extension-data"); + expectedDir.append(ADDON.id); + do_test_pending(); do_check_false(expectedDir.exists()); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_dictionary.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_dictionary.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_dictionary.js 2016-11-11 02:09:04.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_dictionary.js 2016-11-14 02:10:19.000000000 +0000 @@ -452,10 +452,10 @@ startupManager(false); AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", - callback_soon(function(b1) { + callback_soon(function(b1_2) { // Should still be stopped do_check_false(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); - do_check_false(b1.isActive); + do_check_false(b1_2.isActive); shutdownManager(); gAppInfo.inSafeMode = false; @@ -464,8 +464,8 @@ // Should have started do_check_true(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); - AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) { - b1.uninstall(); + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1_3) { + b1_3.uninstall(); do_execute_soon(run_test_17); }); @@ -583,8 +583,8 @@ do_check_eq(list.length, 0); restartManager(); - AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) { - b1.uninstall(); + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1_2) { + b1_2.uninstall(); do_execute_soon(run_test_25); }); })); @@ -617,11 +617,11 @@ do_check_false(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); - AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) { - do_check_neq(b1, null); - do_check_eq(b1.version, "2.0"); - do_check_true(b1.isActive); - do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1_2) { + do_check_neq(b1_2, null); + do_check_eq(b1_2.version, "2.0"); + do_check_true(b1_2.isActive); + do_check_eq(b1_2.pendingOperations, AddonManager.PENDING_NONE); do_execute_soon(run_test_26); }); @@ -650,14 +650,14 @@ do_check_true(HunspellEngine.isDictionaryEnabled("ab-CD.dic")); - AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) { - do_check_neq(b1, null); - do_check_eq(b1.version, "1.0"); - do_check_true(b1.isActive); - do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE); + AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1_2) { + do_check_neq(b1_2, null); + do_check_eq(b1_2.version, "1.0"); + do_check_true(b1_2.isActive); + do_check_eq(b1_2.pendingOperations, AddonManager.PENDING_NONE); HunspellEngine.deactivate(); - b1.uninstall(); + b1_2.uninstall(); do_execute_soon(run_test_27); }); })); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_distribution.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_distribution.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_distribution.js 2016-11-11 02:09:04.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_distribution.js 2016-11-14 02:10:19.000000000 +0000 @@ -165,8 +165,8 @@ restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { - do_check_eq(a1, null); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1_2) { + do_check_eq(a1_2, null); do_execute_soon(run_test_6); }); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_duplicateplugins.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_duplicateplugins.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_duplicateplugins.js 2016-11-11 02:09:04.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_duplicateplugins.js 2016-11-14 02:10:23.000000000 +0000 @@ -176,10 +176,10 @@ [PLUGINS[0], PLUGINS[1]] = [PLUGINS[1], PLUGINS[0]]; restartManager(); - AddonManager.getAddonByID(gPluginIDs[0], function(p) { - do_check_neq(p, null); - do_check_eq(p.name, "Duplicate Plugin 1"); - do_check_eq(p.description, "A duplicate plugin"); + AddonManager.getAddonByID(gPluginIDs[0], function(p_2) { + do_check_neq(p_2, null); + do_check_eq(p_2.name, "Duplicate Plugin 1"); + do_check_eq(p_2.description, "A duplicate plugin"); do_execute_soon(do_test_finished); }); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js 2016-11-11 02:09:04.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js 2016-11-14 02:10:28.000000000 +0000 @@ -247,9 +247,9 @@ restartManager(); AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", - "addon2@tests.mozilla.org"], function([a1, a2]) { - do_check_eq(a1, null); - do_check_eq(a2, null); + "addon2@tests.mozilla.org"], function([a1_2, a2_2]) { + do_check_eq(a1_2, null); + do_check_eq(a2_2, null); let source = sourceDir.clone(); source.append(addon1.id); @@ -283,8 +283,8 @@ restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { - do_check_eq(a1, null); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1_2) { + do_check_eq(a1_2, null); do_execute_soon(run_test_7); }); @@ -309,11 +309,11 @@ restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { - do_check_neq(a1, null); - do_check_eq(a1.version, "2.0"); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1_2) { + do_check_neq(a1_2, null); + do_check_eq(a1_2.version, "2.0"); - a1.uninstall(); + a1_2.uninstall(); do_execute_soon(run_test_8); }); @@ -336,11 +336,11 @@ restartManager(); - AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { - do_check_neq(a1, null); - do_check_eq(a1.version, "2.0"); + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1_2) { + do_check_neq(a1_2, null); + do_check_eq(a1_2.version, "2.0"); - a1.uninstall(); + a1_2.uninstall(); do_execute_soon(run_test_9); }); @@ -364,8 +364,8 @@ restartManager(); - AddonManager.getAddonByID(addon1.id, function(a1) { - do_check_eq(a1, null); + AddonManager.getAddonByID(addon1.id, function(a1_2) { + do_check_eq(a1_2, null); let pointer = profileDir.clone(); pointer.append(addon1.id); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_getresource.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_getresource.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_getresource.js 2016-11-11 02:09:04.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_getresource.js 2016-11-14 02:10:30.000000000 +0000 @@ -76,9 +76,9 @@ } AddonManager.getInstallForFile(do_get_addon("test_getresource"), - callback_soon(function(aInstall) { + callback_soon(function(aInstall_2) { do_check_false(a1.hasResource("icon.png")); - do_check_true(aInstall.addon.hasResource("icon.png")); + do_check_true(aInstall_2.addon.hasResource("icon.png")); restartManager(); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_install.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_install.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_install.js 2016-11-11 02:09:04.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_install.js 2016-11-14 02:10:30.000000000 +0000 @@ -186,10 +186,10 @@ do_check_true(a1.hasResource("install.rdf")); do_check_false(a1.hasResource("foo.bar")); - let uri = do_get_addon_root_uri(profileDir, "addon1@tests.mozilla.org"); - do_check_eq(a1.getResourceURI("install.rdf").spec, uri + "install.rdf"); - do_check_eq(a1.iconURL, uri + "icon.png"); - do_check_eq(a1.icon64URL, uri + "icon64.png"); + let uri2 = do_get_addon_root_uri(profileDir, "addon1@tests.mozilla.org"); + do_check_eq(a1.getResourceURI("install.rdf").spec, uri2 + "install.rdf"); + do_check_eq(a1.iconURL, uri2 + "icon.png"); + do_check_eq(a1.icon64URL, uri2 + "icon64.png"); // Ensure that extension bundle (or icon if unpacked) has updated // lastModifiedDate. @@ -233,7 +233,7 @@ ], check_test_2); install.addListener({ - onDownloadProgress: function(install) { + onDownloadProgress: function() { do_execute_soon(function() { Components.utils.forceGC(); }); @@ -387,8 +387,8 @@ do_check_eq(installs[0].addon, olda2.pendingUpgrade); restartManager(); - AddonManager.getInstallsByTypes(null, function(installs) { - do_check_eq(installs.length, 0); + AddonManager.getInstallsByTypes(null, function(installs2) { + do_check_eq(installs2.length, 0); AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { do_check_neq(a2, null); @@ -1148,26 +1148,26 @@ do_check_true(a2.userDisabled); do_check_false(a2.isActive); - let url = "http://localhost:" + gPort + "/addons/test_install2_2.xpi"; - AddonManager.getInstallForURL(url, function(aInstall) { - aInstall.addListener({ + let url_2 = "http://localhost:" + gPort + "/addons/test_install2_2.xpi"; + AddonManager.getInstallForURL(url_2, function(aInstall_2) { + aInstall_2.addListener({ onInstallEnded: function() { do_execute_soon(function install2_2_ended() { - do_check_true(aInstall.addon.userDisabled); + do_check_true(aInstall_2.addon.userDisabled); restartManager(); - AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { - do_check_true(a2.userDisabled); - do_check_false(a2.isActive); + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2_2) { + do_check_true(a2_2.userDisabled); + do_check_false(a2_2.isActive); - a2.uninstall(); + a2_2.uninstall(); do_execute_soon(run_test_17); }); }); } }); - aInstall.install(); + aInstall_2.install(); }, "application/x-xpinstall"); }); }); @@ -1194,29 +1194,29 @@ do_check_false(a2.userDisabled); do_check_true(a2.isActive); - let url = "http://localhost:" + gPort + "/addons/test_install2_2.xpi"; - AddonManager.getInstallForURL(url, function(aInstall) { - aInstall.addListener({ + let url_2 = "http://localhost:" + gPort + "/addons/test_install2_2.xpi"; + AddonManager.getInstallForURL(url_2, function(aInstall_2) { + aInstall_2.addListener({ onInstallStarted: function() { - do_check_false(aInstall.addon.userDisabled); - aInstall.addon.userDisabled = true; + do_check_false(aInstall_2.addon.userDisabled); + aInstall_2.addon.userDisabled = true; }, onInstallEnded: function() { do_execute_soon(function install2_2_ended2() { restartManager(); - AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { - do_check_true(a2.userDisabled); - do_check_false(a2.isActive); + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2_2) { + do_check_true(a2_2.userDisabled); + do_check_false(a2_2.isActive); - a2.uninstall(); + a2_2.uninstall(); do_execute_soon(run_test_18); }); }); } }); - aInstall.install(); + aInstall_2.install(); }, "application/x-xpinstall"); }); }); @@ -1246,29 +1246,29 @@ do_check_true(a2.userDisabled); do_check_false(a2.isActive); - let url = "http://localhost:" + gPort + "/addons/test_install2_2.xpi"; - AddonManager.getInstallForURL(url, function(aInstall) { - aInstall.addListener({ + let url_2 = "http://localhost:" + gPort + "/addons/test_install2_2.xpi"; + AddonManager.getInstallForURL(url_2, function(aInstall_2) { + aInstall_2.addListener({ onInstallStarted: function() { - do_check_true(aInstall.addon.userDisabled); - aInstall.addon.userDisabled = false; + do_check_true(aInstall_2.addon.userDisabled); + aInstall_2.addon.userDisabled = false; }, onInstallEnded: function() { do_execute_soon(function install_2_2_ended3() { restartManager(); - AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { - do_check_false(a2.userDisabled); - do_check_true(a2.isActive); + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2_2) { + do_check_false(a2_2.userDisabled); + do_check_true(a2_2.isActive); - a2.uninstall(); + a2_2.uninstall(); do_execute_soon(run_test_18_1); }); }); } }); - aInstall.install(); + aInstall_2.install(); }, "application/x-xpinstall"); }); }); @@ -1292,7 +1292,7 @@ let url = "http://localhost:" + gPort + "/addons/test_install2_1.xpi"; AddonManager.getInstallForURL(url, function(aInstall) { aInstall.addListener({ - onInstallEnded: function(aInstall, aAddon) { + onInstallEnded: function(unused, aAddon) { do_execute_soon(function test18_1_install_ended() { do_check_neq(aAddon.fullDescription, "Repository description"); @@ -1320,7 +1320,7 @@ let url = "http://localhost:" + gPort + "/addons/test_install2_1.xpi"; AddonManager.getInstallForURL(url, function(aInstall) { aInstall.addListener({ - onInstallEnded: function(aInstall, aAddon) { + onInstallEnded: function(unused, aAddon) { do_execute_soon(function test19_install_ended() { do_check_eq(aAddon.fullDescription, "Repository description"); @@ -1346,7 +1346,7 @@ let url = "http://localhost:" + gPort + "/addons/test_install2_1.xpi"; AddonManager.getInstallForURL(url, function(aInstall) { aInstall.addListener({ - onInstallEnded: function(aInstall, aAddon) { + onInstallEnded: function(unused, aAddon) { do_execute_soon(function test20_install_ended() { do_check_eq(aAddon.fullDescription, "Repository description"); @@ -1633,8 +1633,8 @@ let url = "http://localhost:" + gPort + "/redirect?/addons/test_install1.xpi"; AddonManager.getInstallForURL(url, function(aInstall) { aInstall.addListener({ - onDownloadProgress: function(aInstall) { - aInstall.cancel(); + onDownloadProgress: function(aDownloadProgressInstall) { + aDownloadProgressInstall.cancel(); } }); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js 2016-11-11 02:09:04.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js 2016-11-14 02:10:30.000000000 +0000 @@ -177,10 +177,10 @@ do_check_true(a1.hasResource("install.rdf")); do_check_false(a1.hasResource("foo.bar")); - let uri = do_get_addon_root_uri(profileDir, "addon1@tests.mozilla.org"); - do_check_eq(a1.getResourceURI("install.rdf").spec, uri + "install.rdf"); - do_check_eq(a1.iconURL, uri + "icon.png"); - do_check_eq(a1.icon64URL, uri + "icon64.png"); + let root_uri = do_get_addon_root_uri(profileDir, "addon1@tests.mozilla.org"); + do_check_eq(a1.getResourceURI("install.rdf").spec, root_uri + "install.rdf"); + do_check_eq(a1.iconURL, root_uri + "icon.png"); + do_check_eq(a1.icon64URL, root_uri + "icon64.png"); a1.uninstall(); do_execute_soon(function() { run_test_2(a1) }); @@ -216,7 +216,7 @@ ], check_test_2); install.addListener({ - onDownloadProgress: function(install) { + onDownloadProgress: function() { do_execute_soon(function() { Components.utils.forceGC(); }); @@ -369,8 +369,8 @@ do_check_eq(installs[0].addon, olda2.pendingUpgrade); restartManager(); - AddonManager.getInstallsByTypes(null, function(installs) { - do_check_eq(installs.length, 0); + AddonManager.getInstallsByTypes(null, function(installs2) { + do_check_eq(installs2.length, 0); AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { do_check_neq(a2, null); @@ -1129,26 +1129,26 @@ do_check_true(a2.userDisabled); do_check_false(a2.isActive); - let url = "http://localhost:4444/addons/test_install2_2.xpi"; - AddonManager.getInstallForURL(url, function(aInstall) { - aInstall.addListener({ + let url_2 = "http://localhost:4444/addons/test_install2_2.xpi"; + AddonManager.getInstallForURL(url_2, function(aInstall_2) { + aInstall_2.addListener({ onInstallEnded: function() { do_execute_soon(function test16_install2() { - do_check_true(aInstall.addon.userDisabled); + do_check_true(aInstall_2.addon.userDisabled); restartManager(); - AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { - do_check_true(a2.userDisabled); - do_check_false(a2.isActive); + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2_2) { + do_check_true(a2_2.userDisabled); + do_check_false(a2_2.isActive); - a2.uninstall(); + a2_2.uninstall(); do_execute_soon(run_test_17); }); }); } }); - aInstall.install(); + aInstall_2.install(); }, "application/x-xpinstall"); }); }); @@ -1166,7 +1166,7 @@ AddonManager.getInstallForURL(url, function(aInstall) { aInstall.addListener({ onInstallEnded: function() { - do_execute_soon(function test17_install1() { + do_execute_soon(function() { do_check_false(aInstall.addon.userDisabled); restartManager(); @@ -1175,29 +1175,29 @@ do_check_false(a2.userDisabled); do_check_true(a2.isActive); - let url = "http://localhost:4444/addons/test_install2_2.xpi"; - AddonManager.getInstallForURL(url, function(aInstall) { - aInstall.addListener({ + let url_2 = "http://localhost:4444/addons/test_install2_2.xpi"; + AddonManager.getInstallForURL(url_2, function(aInstall_2) { + aInstall_2.addListener({ onInstallStarted: function() { - do_check_false(aInstall.addon.userDisabled); - aInstall.addon.userDisabled = true; + do_check_false(aInstall_2.addon.userDisabled); + aInstall_2.addon.userDisabled = true; }, onInstallEnded: function() { - do_execute_soon(function test17_install1() { + do_execute_soon(function() { restartManager(); - AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { - do_check_true(a2.userDisabled); - do_check_false(a2.isActive); + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2_2) { + do_check_true(a2_2.userDisabled); + do_check_false(a2_2.isActive); - a2.uninstall(); + a2_2.uninstall(); do_execute_soon(run_test_18); }); }); } }); - aInstall.install(); + aInstall_2.install(); }, "application/x-xpinstall"); }); }); @@ -1227,29 +1227,29 @@ do_check_true(a2.userDisabled); do_check_false(a2.isActive); - let url = "http://localhost:4444/addons/test_install2_2.xpi"; - AddonManager.getInstallForURL(url, function(aInstall) { - aInstall.addListener({ + let url_2 = "http://localhost:4444/addons/test_install2_2.xpi"; + AddonManager.getInstallForURL(url_2, function(aInstall_2) { + aInstall_2.addListener({ onInstallStarted: function() { - do_check_true(aInstall.addon.userDisabled); - aInstall.addon.userDisabled = false; + do_check_true(aInstall_2.addon.userDisabled); + aInstall_2.addon.userDisabled = false; }, onInstallEnded: function() { do_execute_soon(function test18_install2() { restartManager(); - AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) { - do_check_false(a2.userDisabled); - do_check_true(a2.isActive); + AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2_2) { + do_check_false(a2_2.userDisabled); + do_check_true(a2_2.isActive); - a2.uninstall(); + a2_2.uninstall(); do_execute_soon(run_test_18_1); }); }); } }); - aInstall.install(); + aInstall_2.install(); }, "application/x-xpinstall"); }); }); @@ -1273,7 +1273,7 @@ let url = "http://localhost:4444/addons/test_install2_1.xpi"; AddonManager.getInstallForURL(url, function(aInstall) { aInstall.addListener({ - onInstallEnded: function(aInstall, aAddon) { + onInstallEnded: function(unused, aAddon) { do_execute_soon(function test18_install() { do_check_neq(aAddon.fullDescription, "Repository description"); @@ -1301,7 +1301,7 @@ let url = "http://localhost:4444/addons/test_install2_1.xpi"; AddonManager.getInstallForURL(url, function(aInstall) { aInstall.addListener({ - onInstallEnded: function(aInstall, aAddon) { + onInstallEnded: function(unused, aAddon) { do_execute_soon(function test19_install() { do_check_eq(aAddon.fullDescription, "Repository description"); @@ -1327,7 +1327,7 @@ let url = "http://localhost:4444/addons/test_install2_1.xpi"; AddonManager.getInstallForURL(url, function(aInstall) { aInstall.addListener({ - onInstallEnded: function(aInstall, aAddon) { + onInstallEnded: function(unused, aAddon) { do_execute_soon(function test20_install() { do_check_eq(aAddon.fullDescription, "Repository description"); @@ -1614,8 +1614,8 @@ let url = "http://localhost:4444/redirect?/addons/test_install1.xpi"; AddonManager.getInstallForURL(url, function(aInstall) { aInstall.addListener({ - onDownloadProgress: function(aInstall) { - aInstall.cancel(); + onDownloadProgress: function(aDownloadProgressInstall) { + aDownloadProgressInstall.cancel(); } }); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_LightweightThemeManager.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_LightweightThemeManager.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_LightweightThemeManager.js 2016-11-11 02:08:22.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_LightweightThemeManager.js 2016-11-14 02:10:12.000000000 +0000 @@ -207,44 +207,44 @@ function roundtripSet(props, modify, test, secure) { props.forEach(function (prop) { - var data = dummy(); - modify(data, prop); - test(roundtrip(data, secure), prop, data); + var theme = dummy(); + modify(theme, prop); + test(roundtrip(theme, secure), prop, theme); }); } - roundtripSet(MANDATORY, function (data, prop) { - delete data[prop]; + roundtripSet(MANDATORY, function (theme, prop) { + delete theme[prop]; }, function (after) { do_check_eq(after, null); }); - roundtripSet(OPTIONAL, function (data, prop) { - delete data[prop]; + roundtripSet(OPTIONAL, function (theme, prop) { + delete theme[prop]; }, function (after) { do_check_neq(after, null); }); - roundtripSet(MANDATORY, function (data, prop) { - data[prop] = ""; + roundtripSet(MANDATORY, function (theme, prop) { + theme[prop] = ""; }, function (after) { do_check_eq(after, null); }); - roundtripSet(OPTIONAL, function (data, prop) { - data[prop] = ""; + roundtripSet(OPTIONAL, function (theme, prop) { + theme[prop] = ""; }, function (after, prop) { do_check_eq(typeof after[prop], "undefined"); }); - roundtripSet(MANDATORY, function (data, prop) { - data[prop] = " "; + roundtripSet(MANDATORY, function (theme, prop) { + theme[prop] = " "; }, function (after) { do_check_eq(after, null); }); - roundtripSet(OPTIONAL, function (data, prop) { - data[prop] = " "; + roundtripSet(OPTIONAL, function (theme, prop) { + theme[prop] = " "; }, function (after, prop) { do_check_neq(after, null); do_check_eq(typeof after[prop], "undefined"); @@ -258,20 +258,20 @@ return props.filter(prop => /URL$/.test(prop)); } - roundtripSet(non_urls(MANDATORY.concat(OPTIONAL)), function (data, prop) { - data[prop] = prop; + roundtripSet(non_urls(MANDATORY.concat(OPTIONAL)), function (theme, prop) { + theme[prop] = prop; }, function (after, prop, before) { do_check_eq(after[prop], before[prop]); }); - roundtripSet(non_urls(MANDATORY.concat(OPTIONAL)), function (data, prop) { - data[prop] = " " + prop + " "; + roundtripSet(non_urls(MANDATORY.concat(OPTIONAL)), function (theme, prop) { + theme[prop] = " " + prop + " "; }, function (after, prop, before) { do_check_eq(after[prop], before[prop].trim()); }); - roundtripSet(urls(MANDATORY.concat(OPTIONAL)), function (data, prop) { - data[prop] = Math.random().toString(); + roundtripSet(urls(MANDATORY.concat(OPTIONAL)), function (theme, prop) { + theme[prop] = Math.random().toString(); }, function (after, prop, before) { if (prop == "updateURL") do_check_eq(typeof after[prop], "undefined"); @@ -279,26 +279,26 @@ do_check_eq(after[prop], "http://lwttest.invalid/" + before[prop]); }); - roundtripSet(urls(MANDATORY.concat(OPTIONAL)), function (data, prop) { - data[prop] = Math.random().toString(); + roundtripSet(urls(MANDATORY.concat(OPTIONAL)), function (theme, prop) { + theme[prop] = Math.random().toString(); }, function (after, prop, before) { do_check_eq(after[prop], "https://lwttest.invalid/" + before[prop]); }, true); - roundtripSet(urls(MANDATORY.concat(OPTIONAL)), function (data, prop) { - data[prop] = "https://sub.lwttest.invalid/" + Math.random().toString(); + roundtripSet(urls(MANDATORY.concat(OPTIONAL)), function (theme, prop) { + theme[prop] = "https://sub.lwttest.invalid/" + Math.random().toString(); }, function (after, prop, before) { do_check_eq(after[prop], before[prop]); }); - roundtripSet(urls(MANDATORY), function (data, prop) { - data[prop] = "ftp://lwttest.invalid/" + Math.random().toString(); + roundtripSet(urls(MANDATORY), function (theme, prop) { + theme[prop] = "ftp://lwttest.invalid/" + Math.random().toString(); }, function (after) { do_check_eq(after, null); }); - roundtripSet(urls(OPTIONAL), function (data, prop) { - data[prop] = "ftp://lwttest.invalid/" + Math.random().toString(); + roundtripSet(urls(OPTIONAL), function (theme, prop) { + theme[prop] = "ftp://lwttest.invalid/" + Math.random().toString(); }, function (after, prop) { do_check_eq(typeof after[prop], "undefined"); }); @@ -546,12 +546,12 @@ do_test_pending(); - AddonManager.getAddonByID("builtInTheme0@personas.mozilla.org", aAddon => { + AddonManager.getAddonByID("builtInTheme0@personas.mozilla.org", builtInThemeAddon => { // App specific theme can't be uninstalled or disabled, // but can be enabled (since it isn't already applied). - do_check_eq(hasPermission(aAddon, "uninstall"), false); - do_check_eq(hasPermission(aAddon, "disable"), false); - do_check_eq(hasPermission(aAddon, "enable"), true); + do_check_eq(hasPermission(builtInThemeAddon, "uninstall"), false); + do_check_eq(hasPermission(builtInThemeAddon, "disable"), false); + do_check_eq(hasPermission(builtInThemeAddon, "enable"), true); ltm.currentTheme = dummy("x0"); do_check_eq([...ltm._builtInThemes].length, 2); @@ -566,12 +566,12 @@ Assert.throws(() => { ltm.addBuiltInTheme("not a theme object") }, "Exception is thrown adding an invalid theme"); - AddonManager.getAddonByID("x0@personas.mozilla.org", aAddon => { + AddonManager.getAddonByID("x0@personas.mozilla.org", x0Addon => { // Currently applied (non-app-specific) can be uninstalled or disabled, // but can't be enabled (since it's already applied). - do_check_eq(hasPermission(aAddon, "uninstall"), true); - do_check_eq(hasPermission(aAddon, "disable"), true); - do_check_eq(hasPermission(aAddon, "enable"), false); + do_check_eq(hasPermission(x0Addon, "uninstall"), true); + do_check_eq(hasPermission(x0Addon, "disable"), true); + do_check_eq(hasPermission(x0Addon, "enable"), false); ltm.forgetUsedTheme("x0"); do_check_eq(ltm.currentTheme, null); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_migrate4.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_migrate4.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_migrate4.js 2016-11-11 02:09:05.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_migrate4.js 2016-11-14 02:10:30.000000000 +0000 @@ -148,11 +148,11 @@ "addon4@tests.mozilla.org", "addon5@tests.mozilla.org", "addon6@tests.mozilla.org"], - function([a1, a2, a3, a4, a5, a6]) { - a3.userDisabled = true; - a4.userDisabled = false; + function([a1_2, a2_2, a3_2, a4_2, a5_2, a6_2]) { + a3_2.userDisabled = true; + a4_2.userDisabled = false; - a5.findUpdates({ + a5_2.findUpdates({ onUpdateFinished: function() { do_execute_soon(perform_migration); } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_migrateAddonRepository.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_migrateAddonRepository.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_migrateAddonRepository.js 2016-11-11 02:09:05.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_migrateAddonRepository.js 2016-11-14 02:10:30.000000000 +0000 @@ -59,21 +59,21 @@ "caption TEXT, " + "PRIMARY KEY (addon_internal_id, num)"); - let stmt = db.createStatement("INSERT INTO addon (id) VALUES (:id)"); - stmt.params.id = "test1@tests.mozilla.org"; - stmt.execute(); - stmt.finalize(); + let insertStmt = db.createStatement("INSERT INTO addon (id) VALUES (:id)"); + insertStmt.params.id = "test1@tests.mozilla.org"; + insertStmt.execute(); + insertStmt.finalize(); - stmt = db.createStatement("INSERT INTO screenshot VALUES " + + insertStmt = db.createStatement("INSERT INTO screenshot VALUES " + "(:addon_internal_id, :num, :url, :thumbnailURL, :caption)"); - stmt.params.addon_internal_id = 1; - stmt.params.num = 0; - stmt.params.url = "http://localhost/full1-1.png"; - stmt.params.thumbnailURL = "http://localhost/thumbnail1-1.png"; - stmt.params.caption = "Caption 1 - 1"; - stmt.execute(); - stmt.finalize(); + insertStmt.params.addon_internal_id = 1; + insertStmt.params.num = 0; + insertStmt.params.url = "http://localhost/full1-1.png"; + insertStmt.params.thumbnailURL = "http://localhost/thumbnail1-1.png"; + insertStmt.params.caption = "Caption 1 - 1"; + insertStmt.execute(); + insertStmt.finalize(); db.schemaVersion = 1; db.close(); @@ -108,15 +108,15 @@ let internalID = db.lastInsertRowID; db.executeSimpleSQL("INSERT INTO compatibility_override (addon_internal_id, num, type) VALUES('" + internalID + "', '1', 'incompatible')"); - let stmt = db.createStatement("SELECT COUNT(*) AS count FROM compatibility_override"); - stmt.executeStep(); - do_check_eq(stmt.row.count, 1); - stmt.reset(); + let selectStmt = db.createStatement("SELECT COUNT(*) AS count FROM compatibility_override"); + selectStmt.executeStep(); + do_check_eq(selectStmt.row.count, 1); + selectStmt.reset(); db.executeSimpleSQL("DELETE FROM addon"); - stmt.executeStep(); - do_check_eq(stmt.row.count, 0); - stmt.finalize(); + selectStmt.executeStep(); + do_check_eq(selectStmt.row.count, 0); + selectStmt.finalize(); db.close(); do_test_finished(); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_plugins.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_plugins.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_plugins.js 2016-11-11 02:09:05.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_plugins.js 2016-11-14 02:10:31.000000000 +0000 @@ -156,14 +156,14 @@ do_check_false(p.appDisabled); do_check_false(p.isActive); - AddonManager.getAddonByID(gID, function(p) { - do_check_neq(p, null); - do_check_true(p.userDisabled); - do_check_false(p.appDisabled); - do_check_false(p.isActive); - do_check_eq(p.name, "Shockwave Flash"); + AddonManager.getAddonByID(gID, function(p2) { + do_check_neq(p2, null); + do_check_true(p2.userDisabled); + do_check_false(p2.appDisabled); + do_check_false(p2.isActive); + do_check_eq(p2.name, "Shockwave Flash"); - run_test_3(p); + run_test_3(p2); }); } @@ -184,12 +184,12 @@ do_check_false(p.appDisabled); do_check_true(p.isActive); - AddonManager.getAddonByID(gID, function(p) { - do_check_neq(p, null); - do_check_false(p.userDisabled); - do_check_false(p.appDisabled); - do_check_true(p.isActive); - do_check_eq(p.name, "Shockwave Flash"); + AddonManager.getAddonByID(gID, function(p2) { + do_check_neq(p2, null); + do_check_false(p2.userDisabled); + do_check_false(p2.appDisabled); + do_check_true(p2.isActive); + do_check_eq(p2.name, "Shockwave Flash"); do_execute_soon(run_test_4); }); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_reload.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_reload.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_reload.js 2016-11-11 02:09:05.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_reload.js 2016-11-14 02:10:31.000000000 +0000 @@ -55,23 +55,23 @@ const onReload = new Promise(resolve => { const listener = { - onUninstalling: (addon) => { - if (addon.id === sampleAddon.id) { + onUninstalling: (addonObj) => { + if (addonObj.id === sampleAddon.id) { receivedOnUninstalling = true; } }, - onUninstalled: (addon) => { - if (addon.id === sampleAddon.id) { + onUninstalled: (addonObj) => { + if (addonObj.id === sampleAddon.id) { receivedOnUninstalled = true; } }, - onInstalling: (addon) => { + onInstalling: (addonObj) => { receivedOnInstalling = true; - equal(addon.id, sampleAddon.id); + equal(addonObj.id, sampleAddon.id); }, - onInstalled: (addon) => { + onInstalled: (addonObj) => { receivedOnInstalled = true; - equal(addon.id, sampleAddon.id); + equal(addonObj.id, sampleAddon.id); // This should be the last event called. AddonManager.removeAddonListener(listener); resolve(); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_sourceURI.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_sourceURI.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_sourceURI.js 2016-11-11 02:09:05.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_sourceURI.js 2016-11-14 02:10:31.000000000 +0000 @@ -54,10 +54,10 @@ backgroundUpdate(function() { restartManager(); - AddonManager.getAddonByID("addon@tests.mozilla.org", function(a) { - do_check_neq(a, null); - do_check_neq(a.sourceURI, null); - do_check_eq(a.sourceURI.spec, "http://www.example.com/testaddon.xpi"); + AddonManager.getAddonByID("addon@tests.mozilla.org", function(a2) { + do_check_neq(a2, null); + do_check_neq(a2.sourceURI, null); + do_check_eq(a2.sourceURI.spec, "http://www.example.com/testaddon.xpi"); do_test_finished(); }); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_startup.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_startup.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_startup.js 2016-11-11 02:09:05.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_startup.js 2016-11-14 02:10:31.000000000 +0000 @@ -868,31 +868,31 @@ "addon3@tests.mozilla.org", "addon4@tests.mozilla.org", "addon5@tests.mozilla.org"], - function([a1, a2, a3, a4, a5]) { - do_check_neq(a1, null); - do_check_false(a1.userDisabled); - do_check_true(a1.seen); - do_check_true(a1.isActive); - - do_check_neq(a2, null); - do_check_false(a2.userDisabled); - do_check_true(a2.seen); - do_check_true(a2.isActive); - - do_check_neq(a3, null); - do_check_true(a3.userDisabled); - do_check_false(a3.seen); - do_check_false(a3.isActive); - - var dest = profileDir.clone(); - dest.append(do_get_expected_addon_name("addon1@tests.mozilla.org")); - dest.remove(true); - dest = userDir.clone(); - dest.append(do_get_expected_addon_name("addon2@tests.mozilla.org")); - dest.remove(true); - dest = globalDir.clone(); - dest.append(do_get_expected_addon_name("addon3@tests.mozilla.org")); - dest.remove(true); + function([a1_2, a2_2, a3_2, a4_2, a5_2]) { + do_check_neq(a1_2, null); + do_check_false(a1_2.userDisabled); + do_check_true(a1_2.seen); + do_check_true(a1_2.isActive); + + do_check_neq(a2_2, null); + do_check_false(a2_2.userDisabled); + do_check_true(a2_2.seen); + do_check_true(a2_2.isActive); + + do_check_neq(a3_2, null); + do_check_true(a3_2.userDisabled); + do_check_false(a3_2.seen); + do_check_false(a3_2.isActive); + + var dest2 = profileDir.clone(); + dest2.append(do_get_expected_addon_name("addon1@tests.mozilla.org")); + dest2.remove(true); + dest2 = userDir.clone(); + dest2.append(do_get_expected_addon_name("addon2@tests.mozilla.org")); + dest2.remove(true); + dest2 = globalDir.clone(); + dest2.append(do_get_expected_addon_name("addon3@tests.mozilla.org")); + dest2.remove(true); restartManager(); @@ -909,21 +909,21 @@ "addon3@tests.mozilla.org", "addon4@tests.mozilla.org", "addon5@tests.mozilla.org"], - function([a1, a2, a3, a4, a5]) { - do_check_neq(a1, null); - do_check_false(a1.userDisabled); - do_check_true(a1.seen); - do_check_true(a1.isActive); - - do_check_neq(a2, null); - do_check_true(a2.userDisabled); - do_check_false(a2.seen); - do_check_false(a2.isActive); - - do_check_neq(a3, null); - do_check_true(a3.userDisabled); - do_check_false(a3.seen); - do_check_false(a3.isActive); + function([a1_3, a2_3, a3_3, a4_3, a5_3]) { + do_check_neq(a1_3, null); + do_check_false(a1_3.userDisabled); + do_check_true(a1_3.seen); + do_check_true(a1_3.isActive); + + do_check_neq(a2_3, null); + do_check_true(a2_3.userDisabled); + do_check_false(a2_3.seen); + do_check_false(a2_3.isActive); + + do_check_neq(a3_3, null); + do_check_true(a3_3.userDisabled); + do_check_false(a3_3.seen); + do_check_false(a3_3.isActive); do_execute_soon(end_test); }); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_switch_os.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_switch_os.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_switch_os.js 2016-11-11 02:09:05.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_switch_os.js 2016-11-14 02:10:31.000000000 +0000 @@ -32,10 +32,10 @@ let jData = loadJSON(gExtensionsJSON); - for (let addon of jData.addons) { - if (addon.id == ID) { + for (let addonInstance of jData.addons) { + if (addonInstance.id == ID) { // Set to something that would be an invalid descriptor for this platform - addon.descriptor = AppConstants.platform == "win" ? "/foo/bar" : "C:\\foo\\bar"; + addonInstance.descriptor = AppConstants.platform == "win" ? "/foo/bar" : "C:\\foo\\bar"; } } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_theme.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_theme.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_theme.js 2016-11-11 02:09:06.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_theme.js 2016-11-14 02:10:31.000000000 +0000 @@ -857,27 +857,27 @@ do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "theme1/1.0"); AddonManager.getAddonsByIDs(["default@tests.mozilla.org", "theme1@tests.mozilla.org"], - callback_soon(function([d, t1]) { - do_check_true(d.userDisabled); - do_check_false(d.appDisabled); - do_check_false(d.isActive); - - do_check_false(t1.userDisabled); - do_check_false(t1.appDisabled); - do_check_true(t1.isActive); + callback_soon(function([d_2, t1_2]) { + do_check_true(d_2.userDisabled); + do_check_false(d_2.appDisabled); + do_check_false(d_2.isActive); + + do_check_false(t1_2.userDisabled); + do_check_false(t1_2.appDisabled); + do_check_true(t1_2.isActive); restartManager("2"); do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "theme1/1.0"); AddonManager.getAddonsByIDs(["default@tests.mozilla.org", - "theme1@tests.mozilla.org"], function([d, t1]) { - do_check_true(d.userDisabled); - do_check_false(d.appDisabled); - do_check_false(d.isActive); - - do_check_false(t1.userDisabled); - do_check_false(t1.appDisabled); - do_check_true(t1.isActive); + "theme1@tests.mozilla.org"], function([d_3, t1_3]) { + do_check_true(d_3.userDisabled); + do_check_false(d_3.appDisabled); + do_check_false(d_3.isActive); + + do_check_false(t1_3.userDisabled); + do_check_false(t1_3.appDisabled); + do_check_true(t1_3.isActive); do_execute_soon(run_test_16); }); @@ -943,14 +943,14 @@ AddonManager.getAddonsByIDs(["default@tests.mozilla.org", "theme1@tests.mozilla.org"], - callback_soon(function([d, t1]) { - do_check_true(d.userDisabled); - do_check_false(d.appDisabled); - do_check_false(d.isActive); - - do_check_false(t1.userDisabled); - do_check_false(t1.appDisabled); - do_check_true(t1.isActive); + callback_soon(function([d_2, t1_2]) { + do_check_true(d_2.userDisabled); + do_check_false(d_2.appDisabled); + do_check_false(d_2.isActive); + + do_check_false(t1_2.userDisabled); + do_check_false(t1_2.appDisabled); + do_check_true(t1_2.isActive); prepare_test({ "theme1@tests.mozilla.org": [ @@ -960,28 +960,28 @@ "onEnabling", ] }); - t1.userDisabled = true; + t1_2.userDisabled = true; ensure_test_completed(); - do_check_false(d.userDisabled); - do_check_false(d.appDisabled); - do_check_false(d.isActive); - - do_check_true(t1.userDisabled); - do_check_false(t1.appDisabled); - do_check_true(t1.isActive); + do_check_false(d_2.userDisabled); + do_check_false(d_2.appDisabled); + do_check_false(d_2.isActive); + + do_check_true(t1_2.userDisabled); + do_check_false(t1_2.appDisabled); + do_check_true(t1_2.isActive); restartManager(); AddonManager.getAddonsByIDs(["default@tests.mozilla.org", - "theme1@tests.mozilla.org"], function([d, t1]) { - do_check_false(d.userDisabled); - do_check_false(d.appDisabled); - do_check_true(d.isActive); - - do_check_true(t1.userDisabled); - do_check_false(t1.appDisabled); - do_check_false(t1.isActive); + "theme1@tests.mozilla.org"], function([d_3, t1_3]) { + do_check_false(d_3.userDisabled); + do_check_false(d_3.appDisabled); + do_check_true(d_3.isActive); + + do_check_true(t1_3.userDisabled); + do_check_false(t1_3.appDisabled); + do_check_false(t1_3.isActive); do_execute_soon(run_test_19); }); @@ -1124,14 +1124,14 @@ restartManager(); AddonManager.getAddonsByIDs(["default@tests.mozilla.org", - "1@personas.mozilla.org"], function([d, p1]) { - do_check_true(d.userDisabled); - do_check_false(d.appDisabled); - do_check_false(d.isActive); - - do_check_false(p1.userDisabled); - do_check_false(p1.appDisabled); - do_check_true(p1.isActive); + "1@personas.mozilla.org"], function([d_2, p1_2]) { + do_check_true(d_2.userDisabled); + do_check_false(d_2.appDisabled); + do_check_false(d_2.isActive); + + do_check_false(p1_2.userDisabled); + do_check_false(p1_2.appDisabled); + do_check_true(p1_2.isActive); end_test(); }); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_update_compatmode.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_update_compatmode.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_update_compatmode.js 2016-11-11 02:09:06.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_update_compatmode.js 2016-11-14 02:10:32.000000000 +0000 @@ -98,7 +98,7 @@ do_throw("Should have seen an available update"); }, - onUpdateAvailable: function(addon, install) { + onUpdateAvailable: function(unused, install) { do_check_eq(install.version, "2.0") }, @@ -124,7 +124,7 @@ do_throw("Should have seen an available update"); }, - onUpdateAvailable: function(addon, install) { + onUpdateAvailable: function(unused, install) { do_check_eq(install.version, "2.0") }, @@ -146,7 +146,7 @@ do_throw("Should have not have seen compatibility information"); }, - onUpdateAvailable: function(addon, install) { + onUpdateAvailable: function() { do_throw("Should not have seen an available update"); }, @@ -172,7 +172,7 @@ do_throw("Should have seen an available update"); }, - onUpdateAvailable: function(addon, install) { + onUpdateAvailable: function(unused, install) { do_check_eq(install.version, "2.0") }, diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_update.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_update.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_update.js 2016-11-11 02:09:06.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_update.js 2016-11-14 02:10:32.000000000 +0000 @@ -54,7 +54,7 @@ for (let test of testParams) { let { updateFile, appId } = test; - add_test(function run_test() { + add_test(function() { writeInstallRDFForExtension({ id: "addon1@tests.mozilla.org", version: "1.0", @@ -145,14 +145,14 @@ // Verify that another update check returns the same AddonInstall a1.findUpdates({ - onNoCompatibilityUpdateAvailable: function(addon) { + onNoCompatibilityUpdateAvailable: function() { ok(false, "Should not have seen onNoCompatibilityUpdateAvailable notification"); }, onUpdateAvailable: function(newAddon, newInstall) { - AddonManager.getAllInstalls(function(aInstalls) { - do_check_eq(aInstalls.length, 1); - do_check_eq(aInstalls[0], install); + AddonManager.getAllInstalls(function(aInstalls2) { + do_check_eq(aInstalls2.length, 1); + do_check_eq(aInstalls2[0], install); do_check_eq(newAddon, addon); do_check_eq(newInstall, install); @@ -164,7 +164,7 @@ }); }, - onNoUpdateAvailable: function(addon) { + onNoUpdateAvailable: function() { ok(false, "Should not have seen onNoUpdateAvailable notification"); } }, AddonManager.UPDATE_WHEN_USER_REQUESTED); @@ -195,7 +195,7 @@ ok(false, "Should not have seen onNoCompatibilityUpdateAvailable notification"); }, - onUpdateAvailable: function(addon, install) { + onUpdateAvailable: function() { ok(false, "Should find no available update when one is already downloading"); }, @@ -593,16 +593,16 @@ "addon4@tests.mozilla.org", "addon5@tests.mozilla.org", "addon6@tests.mozilla.org"], - function([a1, a2, a3, a4, a5, a6]) { + function([a1_2, a2_2, a3_2, a4_2, a5_2, a6_2]) { let count = 6; function next_test() { - a1.uninstall(); - a2.uninstall(); - a3.uninstall(); - a4.uninstall(); - a5.uninstall(); - a6.uninstall(); + a1_2.uninstall(); + a2_2.uninstall(); + a3_2.uninstall(); + a4_2.uninstall(); + a5_2.uninstall(); + a6_2.uninstall(); restartManager(); run_next_test(); @@ -626,12 +626,12 @@ } }; - a1.findUpdates(updateListener, AddonManager.UPDATE_WHEN_USER_REQUESTED); - a2.findUpdates(compatListener, AddonManager.UPDATE_WHEN_ADDON_INSTALLED); - a3.findUpdates(updateListener, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); - a4.findUpdates(updateListener, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, "2"); - a5.findUpdates(compatListener, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); - a6.findUpdates(updateListener, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); + a1_2.findUpdates(updateListener, AddonManager.UPDATE_WHEN_USER_REQUESTED); + a2_2.findUpdates(compatListener, AddonManager.UPDATE_WHEN_ADDON_INSTALLED); + a3_2.findUpdates(updateListener, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); + a4_2.findUpdates(updateListener, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, "2"); + a5_2.findUpdates(compatListener, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); + a6_2.findUpdates(updateListener, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); }); })); }); @@ -975,9 +975,9 @@ do_check_neq(a1.syncGUID, null); let oldGUID = a1.syncGUID; - let url = "http://localhost:" + gPort + "/addons/test_install2_2.xpi"; - AddonManager.getInstallForURL(url, function(aInstall) { - aInstall.addListener({ + let url_2 = "http://localhost:" + gPort + "/addons/test_install2_2.xpi"; + AddonManager.getInstallForURL(url_2, function(aInstall_2) { + aInstall_2.addListener({ onInstallEnded: function() { do_execute_soon(function install_2_2_ended() { restartManager(); @@ -992,7 +992,7 @@ }); } }); - aInstall.install(); + aInstall_2.install(); }, "application/x-xpinstall"); }); }); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js 2016-11-11 02:09:06.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js 2016-11-14 02:10:32.000000000 +0000 @@ -52,7 +52,7 @@ for (let test of testParams) { let { updateFile, appId } = test; - add_test(function run_test() { + add_test(function() { writeInstallRDFForExtension({ id: "addon1@tests.mozilla.org", version: "1.0", @@ -140,14 +140,14 @@ // Verify that another update check returns the same AddonInstall a1.findUpdates({ - onNoCompatibilityUpdateAvailable: function(addon) { + onNoCompatibilityUpdateAvailable: function() { ok(false, "Should not have seen onNoCompatibilityUpdateAvailable notification"); }, onUpdateAvailable: function(newAddon, newInstall) { - AddonManager.getAllInstalls(function(aInstalls) { - do_check_eq(aInstalls.length, 1); - do_check_eq(aInstalls[0], install); + AddonManager.getAllInstalls(function(aInstalls2) { + do_check_eq(aInstalls2.length, 1); + do_check_eq(aInstalls2[0], install); do_check_eq(newAddon, addon); do_check_eq(newInstall, install); @@ -159,7 +159,7 @@ }); }, - onNoUpdateAvailable: function(addon) { + onNoUpdateAvailable: function() { ok(false, "Should not have seen onNoUpdateAvailable notification"); } }, AddonManager.UPDATE_WHEN_USER_REQUESTED); @@ -190,7 +190,7 @@ ok(false, "Should not have seen onNoCompatibilityUpdateAvailable notification"); }, - onUpdateAvailable: function(addon, install) { + onUpdateAvailable: function() { ok(false, "Should find no available update when one is already downloading"); }, @@ -580,16 +580,16 @@ "addon4@tests.mozilla.org", "addon5@tests.mozilla.org", "addon6@tests.mozilla.org"], - function([a1, a2, a3, a4, a5, a6]) { + function([a1_2, a2_2, a3_2, a4_2, a5_2, a6_2]) { let count = 6; function next_test() { - a1.uninstall(); - a2.uninstall(); - a3.uninstall(); - a4.uninstall(); - a5.uninstall(); - a6.uninstall(); + a1_2.uninstall(); + a2_2.uninstall(); + a3_2.uninstall(); + a4_2.uninstall(); + a5_2.uninstall(); + a6_2.uninstall(); restartManager(); run_next_test(); @@ -613,12 +613,12 @@ } }; - a1.findUpdates(updateListener, AddonManager.UPDATE_WHEN_USER_REQUESTED); - a2.findUpdates(compatListener, AddonManager.UPDATE_WHEN_ADDON_INSTALLED); - a3.findUpdates(updateListener, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); - a4.findUpdates(updateListener, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, "2"); - a5.findUpdates(compatListener, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); - a6.findUpdates(updateListener, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); + a1_2.findUpdates(updateListener, AddonManager.UPDATE_WHEN_USER_REQUESTED); + a2_2.findUpdates(compatListener, AddonManager.UPDATE_WHEN_ADDON_INSTALLED); + a3_2.findUpdates(updateListener, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); + a4_2.findUpdates(updateListener, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, "2"); + a5_2.findUpdates(compatListener, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); + a6_2.findUpdates(updateListener, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); }); })); }); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_webextension_icons.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_webextension_icons.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_webextension_icons.js 2016-11-11 02:09:06.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_webextension_icons.js 2016-11-14 02:10:32.000000000 +0000 @@ -51,8 +51,8 @@ let addon = yield promiseAddonByID(ID); do_check_neq(addon, null); - function check_icons(addon) { - deepEqual(addon.icons, { + function check_icons(addon_copy) { + deepEqual(addon_copy.icons, { 16: uri + "icon16.png", 32: uri + "icon32.png", 48: uri + "icon48.png", diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_webextension_install.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_webextension_install.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_webextension_install.js 2016-11-11 02:09:06.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_webextension_install.js 2016-11-14 02:10:32.000000000 +0000 @@ -423,7 +423,7 @@ // * in min will throw an error for (let version of ["0.*", "0.*.0"]) { newId = "strict_min_star@tests.mozilla.org"; - let apps = { + let minStarApps = { applications: { gecko: { id: newId, @@ -432,20 +432,20 @@ }, } - let testManifest = Object.assign(apps, MANIFEST); + let minStarTestManifest = Object.assign(minStarApps, MANIFEST); - let extension = ExtensionTestUtils.loadExtension({ - manifest: testManifest, + let minStarExtension = ExtensionTestUtils.loadExtension({ + manifest: minStarTestManifest, useAddonManager: "temporary", }); yield Assert.rejects( - extension.startup(), + minStarExtension.startup(), /The use of '\*' in strict_min_version is invalid/, "loading an extension with a * in strict_min_version throws an exception"); - let addon = yield promiseAddonByID(newId); - equal(addon, null, "Add-on is not installed"); + let minStarAddon = yield promiseAddonByID(newId); + equal(minStarAddon, null, "Add-on is not installed"); } // incompatible extension but with compatibility checking off diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_webextension.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_webextension.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/extensions/test/xpcshell/test_webextension.js 2016-11-11 02:09:06.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/extensions/test/xpcshell/test_webextension.js 2016-11-14 02:10:32.000000000 +0000 @@ -158,12 +158,12 @@ }); add_task(function* test_manifest_localization() { - const ID = "webextension3@tests.mozilla.org"; + const extensionId = "webextension3@tests.mozilla.org"; yield promiseInstallAllFiles([do_get_addon("webextension_3")], true); yield promiseAddonStartup(); - let addon = yield promiseAddonByID(ID); + let addon = yield promiseAddonByID(extensionId); addon.userDisabled = true; equal(addon.name, "Web Extensiøn foo ☹"); @@ -172,7 +172,7 @@ Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "fr-FR"); yield promiseRestartManager(); - addon = yield promiseAddonByID(ID); + addon = yield promiseAddonByID(extensionId); equal(addon.name, "Web Extensiøn le foo ☺"); equal(addon.description, "Descriptïon le bar ☺ of add-on"); @@ -180,7 +180,7 @@ Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "de"); yield promiseRestartManager(); - addon = yield promiseAddonByID(ID); + addon = yield promiseAddonByID(extensionId); equal(addon.name, "Web Extensiøn foo ☹"); equal(addon.description, "Descriptïon bar ☹ of add-on"); @@ -262,17 +262,17 @@ add_task(function* test_options_ui() { let OPTIONS_RE = /^moz-extension:\/\/[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}\/options\.html$/; - const ID = "webextension@tests.mozilla.org"; + const extensionId = "webextension@tests.mozilla.org"; yield promiseInstallWebExtension({ manifest: { - applications: {gecko: {id: ID}}, + applications: {gecko: {id: extensionId}}, "options_ui": { "page": "options.html", }, }, }); - let addon = yield promiseAddonByID(ID); + let addon = yield promiseAddonByID(extensionId); equal(addon.optionsType, AddonManager.OPTIONS_TYPE_INLINE_BROWSER, "Addon should have an INLINE_BROWSER options type"); @@ -333,10 +333,10 @@ // Experiments are not enabled on release builds. return; - const ID = "meh@experiments.addons.mozilla.org"; + const extensionId = "meh@experiments.addons.mozilla.org"; let addonFile = createTempXPIFile({ - id: ID, + id: extensionId, type: 256, version: "0.1", name: "Meh API", @@ -346,10 +346,10 @@ let addons = yield new Promise(resolve => AddonManager.getAddonsByTypes(["apiextension"], resolve)); let addon = addons.pop(); - equal(addon.id, ID, "Add-on should be installed as an API extension"); + equal(addon.id, extensionId, "Add-on should be installed as an API extension"); addons = yield new Promise(resolve => AddonManager.getAddonsByTypes(["extension"], resolve)); - equal(addons.pop().id, ID, "Add-on type should be aliased to extension"); + equal(addons.pop().id, extensionId, "Add-on type should be aliased to extension"); addon.uninstall(); }); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/update/nsUpdateService.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/update/nsUpdateService.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/update/nsUpdateService.js 2016-11-11 02:09:19.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/update/nsUpdateService.js 2016-11-14 02:11:20.000000000 +0000 @@ -27,12 +27,10 @@ const PREF_APP_UPDATE_CANCELATIONS = "app.update.cancelations"; const PREF_APP_UPDATE_CANCELATIONS_OSX = "app.update.cancelations.osx"; const PREF_APP_UPDATE_CANCELATIONS_OSX_MAX = "app.update.cancelations.osx.max"; -const PREF_APP_UPDATE_CERT_REQUIREBUILTIN = "app.update.cert.requireBuiltIn"; const PREF_APP_UPDATE_ELEVATE_NEVER = "app.update.elevate.never"; const PREF_APP_UPDATE_ELEVATE_VERSION = "app.update.elevate.version"; const PREF_APP_UPDATE_ENABLED = "app.update.enabled"; const PREF_APP_UPDATE_IDLETIME = "app.update.idletime"; -const PREF_APP_UPDATE_INTERVAL = "app.update.interval"; const PREF_APP_UPDATE_LOG = "app.update.log"; const PREF_APP_UPDATE_NOTIFIEDUNSUPPORTED = "app.update.notifiedUnsupported"; const PREF_APP_UPDATE_POSTUPDATE = "app.update.postupdate"; @@ -56,14 +54,11 @@ const URI_UPDATE_PROMPT_DIALOG = "chrome://mozapps/content/update/updates.xul"; const URI_UPDATES_PROPERTIES = "chrome://mozapps/locale/update/updates.properties"; -const KEY_GRED = "GreD"; const KEY_UPDROOT = "UpdRootD"; const KEY_EXECUTABLE = "XREExeF"; // Gonk only const KEY_UPDATE_ARCHIVE_DIR = "UpdArchD"; -const DIR_UPDATED = "updated"; -const DIR_UPDATED_APP = "Updated.app"; const DIR_UPDATES = "updates"; const FILE_ACTIVE_UPDATE_XML = "active-update.xml"; @@ -202,7 +197,6 @@ "{33cb9019-c295-46dd-be21-8c4936574bee}": "xul-window-visible", }; -var gLocale = null; var gUpdateMutexHandle = null; // Gonk only @@ -557,7 +551,7 @@ * @return true if updates can be staged. */ function getCanStageUpdates() { - // If background updates are disabled, then just bail out! + // If staging updates are disabled, then just bail out! if (!getPref("getBoolPref", PREF_APP_UPDATE_STAGING_ENABLED, false)) { LOG("getCanStageUpdates - staging updates is disabled by preference " + PREF_APP_UPDATE_STAGING_ENABLED); @@ -676,18 +670,6 @@ } /** - * Gets the specified directory at the specified hierarchy under the - * update root directory and without creating it if it doesn't exist. - * @param pathArray - * An array of path components to locate beneath the directory - * specified by |key| - * @return nsIFile object for the location specified. - */ -function getUpdateDirNoCreate(pathArray) { - return FileUtils.getDir(KEY_UPDROOT, pathArray, false); -} - -/** * Gets the application base directory. * * @return nsIFile object for the application base directory. @@ -1224,7 +1206,9 @@ let maxCancels = getPref("getIntPref", PREF_APP_UPDATE_CANCELATIONS_OSX_MAX, DEFAULT_CANCELATIONS_OSX_MAX); - if (osxCancelations >= DEFAULT_CANCELATIONS_OSX_MAX) { + // Prevent the preference from setting a value greater than 5. + maxCancels = Math.min(maxCancels, 5); + if (osxCancelations >= maxCancels) { cleanupActiveUpdate(); } else { writeStatusFile(getUpdatesDir(), @@ -1256,7 +1240,8 @@ var maxFail = getPref("getIntPref", PREF_APP_UPDATE_SERVICE_MAXERRORS, DEFAULT_SERVICE_MAX_ERRORS); - + // Prevent the preference from setting a value greater than 10. + maxFail = Math.min(maxFail, 10); // As a safety, when the service reaches maximum failures, it will // disable itself and fallback to using the normal update mechanism // without the service. @@ -1620,7 +1605,7 @@ this.displayVersion = this.appVersion; } - // Don't allow the background interval to be greater than 10 minutes. + // Don't allow the background download interval to be greater than 10 minutes. this.backgroundInterval = Math.min(this.backgroundInterval, 600); // The Update Name is either the string provided by the element, or @@ -2180,8 +2165,8 @@ let errCount = getPref("getIntPref", PREF_APP_UPDATE_BACKGROUNDERRORS, 0); errCount++; Services.prefs.setIntPref(PREF_APP_UPDATE_BACKGROUNDERRORS, errCount); - let maxErrors = getPref("getIntPref", PREF_APP_UPDATE_BACKGROUNDMAXERRORS, - 10); + // Don't allow the preference to set a value greater than 20 for max errors. + let maxErrors = Math.min(getPref("getIntPref", PREF_APP_UPDATE_BACKGROUNDMAXERRORS, 10), 20); if (errCount >= maxErrors) { let prompter = Cc["@mozilla.org/updates/update-prompt;1"]. @@ -2475,8 +2460,7 @@ } } else { let numCancels = getPref("getIntPref", - PREF_APP_UPDATE_CANCELATIONS_OSX, - 0); + PREF_APP_UPDATE_CANCELATIONS_OSX, 0); let rejectedVersion = getPref("getCharPref", PREF_APP_UPDATE_ELEVATE_NEVER, ""); let maxCancels = getPref("getIntPref", @@ -3122,7 +3106,6 @@ if (!update) { return; } - var updateSucceeded = true; var status = readStatusFile(getUpdatesDir()); pingStateAndStatusCodes(update, false, status); var parts = status.split(":"); @@ -3142,7 +3125,6 @@ cleanUpUpdatesDir(false); if (update.state == STATE_FAILED && parts[1]) { - updateSucceeded = false; if (!handleUpdateFailure(update, parts[1])) { handleFallbackToCompleteUpdate(update, true); } @@ -3297,9 +3279,7 @@ this._request = new XMLHttpRequest(); this._request.open("GET", url, true); - var allowNonBuiltIn = !getPref("getBoolPref", - PREF_APP_UPDATE_CERT_REQUIREBUILTIN, true); - this._request.channel.notificationCallbacks = new gCertUtils.BadCertHandler(allowNonBuiltIn); + this._request.channel.notificationCallbacks = new gCertUtils.BadCertHandler(false); // Prevent the request from reading from the cache. this._request.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE; // Prevent the request from writing to the cache. @@ -4030,7 +4010,7 @@ * @param status * Status code containing the reason for the cessation. */ - onStopRequest: function Downloader_onStopRequest(request, context, status) { + onStopRequest: function Downloader_onStopRequest(request, context, status) { if (request instanceof Ci.nsIIncrementalDownload) LOG("Downloader:onStopRequest - original URI spec: " + request.URI.spec + ", final URI spec: " + request.finalURI.spec + ", status: " + status); @@ -4044,8 +4024,12 @@ var deleteActiveUpdate = false; var retryTimeout = getPref("getIntPref", PREF_APP_UPDATE_SOCKET_RETRYTIMEOUT, DEFAULT_SOCKET_RETRYTIMEOUT); + // Prevent the preference from setting a value greater than 10000. + retryTimeout = Math.min(retryTimeout, 10000); var maxFail = getPref("getIntPref", PREF_APP_UPDATE_SOCKET_MAXERRORS, DEFAULT_SOCKET_MAX_ERRORS); + // Prevent the preference from setting a value greater than 20. + maxFail = Math.min(maxFail, 20); LOG("Downloader:onStopRequest - status: " + status + ", " + "current fail: " + this.updateService._consecutiveSocketErrors + ", " + "max fail: " + maxFail + ", " + "retryTimeout: " + retryTimeout); @@ -4467,8 +4451,8 @@ if (page == "updatesavailable") { var idleService = Cc["@mozilla.org/widget/idleservice;1"]. getService(Ci.nsIIdleService); - - const IDLE_TIME = getPref("getIntPref", PREF_APP_UPDATE_IDLETIME, 60); + // Don't allow the preference to set a value greater than 600 seconds for the idle time. + const IDLE_TIME = Math.min(getPref("getIntPref", PREF_APP_UPDATE_IDLETIME, 60), 600); if (idleService.idleTime / 1000 >= IDLE_TIME) { this._showUI(parent, uri, features, name, page, update); return; @@ -4512,7 +4496,8 @@ var idleService = Cc["@mozilla.org/widget/idleservice;1"]. getService(Ci.nsIIdleService); - const IDLE_TIME = getPref("getIntPref", PREF_APP_UPDATE_IDLETIME, 60); + // Don't allow the preference to set a value greater than 600 seconds for the idle time. + const IDLE_TIME = Math.min(getPref("getIntPref", PREF_APP_UPDATE_IDLETIME, 60), 600); if (idleService.idleTime / 1000 >= IDLE_TIME) { this._showUI(parent, uri, features, name, page, update); } else { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/update/nsUpdateService.manifest firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/update/nsUpdateService.manifest --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/update/nsUpdateService.manifest 2016-11-11 02:09:19.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/update/nsUpdateService.manifest 2016-11-14 02:11:20.000000000 +0000 @@ -1,6 +1,6 @@ component {B3C290A6-3943-4B89-8BBE-C01EB7B3B311} nsUpdateService.js contract @mozilla.org/updates/update-service;1 {B3C290A6-3943-4B89-8BBE-C01EB7B3B311} -category update-timer nsUpdateService @mozilla.org/updates/update-service;1,getService,background-update-timer,app.update.interval,86400 +category update-timer nsUpdateService @mozilla.org/updates/update-service;1,getService,background-update-timer,app.update.interval,43200,86400 component {093C2356-4843-4C65-8709-D7DBCBBE7DFB} nsUpdateService.js contract @mozilla.org/updates/update-manager;1 {093C2356-4843-4C65-8709-D7DBCBBE7DFB} component {898CDC9B-E43F-422F-9CC4-2F6291B415A3} nsUpdateService.js diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/update/tests/chrome/utils.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/update/tests/chrome/utils.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/update/tests/chrome/utils.js 2016-11-11 02:09:20.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/update/tests/chrome/utils.js 2016-11-14 02:11:20.000000000 +0000 @@ -922,10 +922,6 @@ Services.prefs.clearUserPref(PREF_APP_UPDATE_BACKGROUNDMAXERRORS); } - if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_CERT_REQUIREBUILTIN)) { - Services.prefs.clearUserPref(PREF_APP_UPDATE_CERT_REQUIREBUILTIN); - } - try { Services.prefs.deleteBranch(PREFBRANCH_APP_UPDATE_NEVER); } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/update/tests/data/shared.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/update/tests/data/shared.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/update/tests/data/shared.js 2016-11-11 02:09:20.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/update/tests/data/shared.js 2016-11-14 02:11:21.000000000 +0000 @@ -11,7 +11,6 @@ const PREF_APP_UPDATE_AUTO = "app.update.auto"; const PREF_APP_UPDATE_BACKGROUNDERRORS = "app.update.backgroundErrors"; const PREF_APP_UPDATE_BACKGROUNDMAXERRORS = "app.update.backgroundMaxErrors"; -const PREF_APP_UPDATE_CERT_REQUIREBUILTIN = "app.update.cert.requireBuiltIn"; const PREF_APP_UPDATE_CHANNEL = "app.update.channel"; const PREF_APP_UPDATE_ENABLED = "app.update.enabled"; const PREF_APP_UPDATE_IDLETIME = "app.update.idletime"; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/update/tests/data/sharedUpdateXML.js firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/update/tests/data/sharedUpdateXML.js --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/mozapps/update/tests/data/sharedUpdateXML.js 2016-11-11 02:09:20.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/mozapps/update/tests/data/sharedUpdateXML.js 2016-11-14 02:11:21.000000000 +0000 @@ -181,7 +181,7 @@ "statusText=\"" + statusText + "\" " + "isCompleteUpdate=\"" + isCompleteUpdate + "\" " + "channel=\"" + channel + "\" " + - "foregroundDownload=\"" + foregroundDownload + "\">" + + "foregroundDownload=\"" + foregroundDownload + "\">" + aPatches + " "; } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/themes/linux/global/menu.css firefox-trunk-52.0~a1~hg20161113r322177/toolkit/themes/linux/global/menu.css --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/themes/linux/global/menu.css 2016-11-11 02:10:05.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/themes/linux/global/menu.css 2016-11-14 02:12:03.000000000 +0000 @@ -185,14 +185,6 @@ menuseparator { -moz-appearance: menuseparator; - margin: 2px 0; - border-top: 1px solid ThreeDShadow; - border-bottom: 1px solid ThreeDHighlight; -} - -menulist > menupopup > menuseparator { - border-top: 1px solid #000000; - border-bottom: none; } /* ::::: autocomplete ::::: */ diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/themes/linux/global/popup.css firefox-trunk-52.0~a1~hg20161113r322177/toolkit/themes/linux/global/popup.css --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/themes/linux/global/popup.css 2016-11-11 02:10:05.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/themes/linux/global/popup.css 2016-11-14 02:12:04.000000000 +0000 @@ -80,8 +80,6 @@ tooltip { -moz-appearance: tooltip; margin-top: 21px; - /* GTK hardcodes this to 4px */ - padding: 4px; max-width: 40em; color: InfoText; font: message-box; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/toolkit/toolkit.mozbuild firefox-trunk-52.0~a1~hg20161113r322177/toolkit/toolkit.mozbuild --- firefox-trunk-52.0~a1~hg20161110r321971/toolkit/toolkit.mozbuild 2016-11-11 02:11:07.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/toolkit/toolkit.mozbuild 2016-11-14 02:12:51.000000000 +0000 @@ -187,14 +187,14 @@ if CONFIG['MOZ_CRASHREPORTER']: DIRS += ['/testing/tools/fileid'] - if CONFIG['MOZ_WEBRTC'] and CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk' and not CONFIG['MOZ_TASK_TRACER']: - DIRS += [ - '/media/webrtc/signaling/test', - '/media/mtransport/test', - ] + if CONFIG['MOZ_MEMORY']: + DIRS += ['/memory/gtest'] + + if CONFIG['MOZ_WEBRTC'] and not CONFIG['MOZ_TASK_TRACER']: + DIRS += [ + '/media/webrtc/signaling/test', + '/media/mtransport/test', + ] if CONFIG['FUZZING']: DIRS += ['/tools/fuzzing'] - -if CONFIG['MOZ_MEMORY']: - DIRS += ['/memory/gtest'] diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/uriloader/base/nsDocLoader.cpp firefox-trunk-52.0~a1~hg20161113r322177/uriloader/base/nsDocLoader.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/uriloader/base/nsDocLoader.cpp 2016-11-11 02:12:23.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/uriloader/base/nsDocLoader.cpp 2016-11-14 02:14:41.000000000 +0000 @@ -356,7 +356,7 @@ mListenerInfoList.Clear(); mListenerInfoList.Compact(); - mDocumentRequest = 0; + mDocumentRequest = nullptr; if (mLoadGroup) mLoadGroup->SetGroupObserver(nullptr); @@ -699,7 +699,7 @@ nsCOMPtr docRequest = mDocumentRequest; - mDocumentRequest = 0; + mDocumentRequest = nullptr; mIsLoadingDocument = false; // Update the progress status state - the document is done diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/uriloader/base/nsURILoader.cpp firefox-trunk-52.0~a1~hg20161113r322177/uriloader/base/nsURILoader.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/uriloader/base/nsURILoader.cpp 2016-11-11 02:12:23.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/uriloader/base/nsURILoader.cpp 2016-11-14 02:14:41.000000000 +0000 @@ -333,7 +333,7 @@ // If this is a multipart stream, we could get another // OnStartRequest after this... reset state. - m_targetStreamListener = 0; + m_targetStreamListener = nullptr; mContentType.Truncate(); listener->OnStopRequest(request, aCtxt, aStatus); } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/uriloader/exthandler/nsExternalProtocolHandler.cpp firefox-trunk-52.0~a1~hg20161113r322177/uriloader/exthandler/nsExternalProtocolHandler.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/uriloader/exthandler/nsExternalProtocolHandler.cpp 2016-11-11 02:12:23.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/uriloader/exthandler/nsExternalProtocolHandler.cpp 2016-11-14 02:14:44.000000000 +0000 @@ -183,7 +183,7 @@ } finish: - mCallbacks = 0; + mCallbacks = nullptr; return rv; } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/widget/cocoa/nsPrintDialogX.mm firefox-trunk-52.0~a1~hg20161113r322177/widget/cocoa/nsPrintDialogX.mm --- firefox-trunk-52.0~a1~hg20161110r321971/widget/cocoa/nsPrintDialogX.mm 2016-11-11 02:13:40.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/widget/cocoa/nsPrintDialogX.mm 2016-11-14 02:16:11.000000000 +0000 @@ -7,6 +7,7 @@ #include "nsPrintDialogX.h" #include "nsIPrintSettings.h" +#include "nsIPrintSettingsService.h" #include "nsPrintSettingsX.h" #include "nsCOMPtr.h" #include "nsQueryObject.h" @@ -49,6 +50,9 @@ if (!settingsX) return NS_ERROR_FAILURE; + nsCOMPtr printSettingsSvc + = do_GetService("@mozilla.org/gfx/printsettings-service;1"); + // Set the print job title char16_t** docTitles; uint32_t titleCount; @@ -68,6 +72,9 @@ titleCount = 0; } + // Read default print settings from prefs + printSettingsSvc->InitPrintSettingsFromPrefs(settingsX, true, + nsIPrintSettings::kInitSaveNativeData); NSPrintInfo* printInfo = settingsX->GetCocoaPrintInfo(); // Put the print info into the current print operation, since that's where @@ -97,8 +104,6 @@ if (!copy) { return NS_ERROR_OUT_OF_MEMORY; } - settingsX->SetCocoaPrintInfo(copy); - [copy release]; [NSPrintOperation setCurrentOperation:nil]; [tmpView release]; @@ -106,9 +111,43 @@ if (button != NSFileHandlingPanelOKButton) return NS_ERROR_ABORT; + settingsX->SetCocoaPrintInfo(copy); + settingsX->InitUnwriteableMargin(); + + // Save settings unless saving is pref'd off + if (Preferences::GetBool("print.save_print_settings", false)) { + printSettingsSvc->SavePrintSettingsToPrefs(settingsX, true, + nsIPrintSettings::kInitSaveNativeData); + } + + // Get coordinate space resolution for converting paper size units to inches + NSWindow *win = [[NSApplication sharedApplication] mainWindow]; + if (win) { + NSDictionary *devDesc = [win deviceDescription]; + if (devDesc) { + NSSize res = [[devDesc objectForKey: NSDeviceResolution] sizeValue]; + float scale = [win backingScaleFactor]; + if (scale > 0) { + settingsX->SetInchesScale(res.width / scale, res.height / scale); + } + } + } + // Export settings. [viewController exportSettings]; + // If "ignore scaling" is checked, overwrite scaling factor with 1. + bool isShrinkToFitChecked; + settingsX->GetShrinkToFit(&isShrinkToFitChecked); + if (isShrinkToFitChecked) { + NSMutableDictionary* dict = [copy dictionary]; + if (dict) { + [dict setObject: [NSNumber numberWithFloat: 1] + forKey: NSPrintScalingFactor]; + } + } + [copy release]; + int16_t pageRange; aSettings->GetPrintRange(&pageRange); if (pageRange != nsIPrintSettings::kRangeSelection) { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/widget/cocoa/nsPrintOptionsX.h firefox-trunk-52.0~a1~hg20161113r322177/widget/cocoa/nsPrintOptionsX.h --- firefox-trunk-52.0~a1~hg20161110r321971/widget/cocoa/nsPrintOptionsX.h 2016-11-11 02:13:40.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/widget/cocoa/nsPrintOptionsX.h 2016-11-14 02:16:11.000000000 +0000 @@ -22,6 +22,13 @@ nsPrintOptionsX(); virtual ~nsPrintOptionsX(); + /* + * These serialize and deserialize methods are not symmetrical in that + * printSettingsX != deserialize(serialize(printSettingsX)). This is because + * the native print settings stored in the nsPrintSettingsX's NSPrintInfo + * object are not fully serialized. Only the values needed for successful + * printing are. + */ NS_IMETHODIMP SerializeToPrintData(nsIPrintSettings* aSettings, nsIWebBrowserPrint* aWBP, mozilla::embedding::PrintData* data); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/widget/cocoa/nsPrintOptionsX.mm firefox-trunk-52.0~a1~hg20161113r322177/widget/cocoa/nsPrintOptionsX.mm --- firefox-trunk-52.0~a1~hg20161110r321971/widget/cocoa/nsPrintOptionsX.mm 2016-11-11 02:13:40.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/widget/cocoa/nsPrintOptionsX.mm 2016-11-14 02:16:11.000000000 +0000 @@ -9,6 +9,19 @@ #include "nsPrintOptionsX.h" #include "nsPrintSettingsX.h" +// The constants for paper orientation were renamed in 10.9. __MAC_10_9 is +// defined on OS X 10.9 and later. Although 10.8 and earlier are not supported +// at this time, this allows for building on those older OS versions. The +// values are consistent across OS versions so the rename does not affect +// runtime, just compilation. +#ifdef __MAC_10_9 +#define NS_PAPER_ORIENTATION_PORTRAIT (NSPaperOrientationPortrait) +#define NS_PAPER_ORIENTATION_LANDSCAPE (NSPaperOrientationLandscape) +#else +#define NS_PAPER_ORIENTATION_PORTRAIT (NSPortraitOrientation) +#define NS_PAPER_ORIENTATION_LANDSCAPE (NSLandscapeOrientation) +#endif + using namespace mozilla::embedding; nsPrintOptionsX::nsPrintOptionsX() @@ -90,6 +103,38 @@ nsCocoaUtils::GetStringForNSString(disposition, data->disposition()); } + NSString* paperName = [dict objectForKey: NSPrintPaperName]; + if (paperName) { + nsCocoaUtils::GetStringForNSString(paperName, data->paperName()); + } + + float scalingFactor = [[dict objectForKey: NSPrintScalingFactor] floatValue]; + data->scalingFactor() = scalingFactor; + + int32_t orientation; + if ([printInfo orientation] == NS_PAPER_ORIENTATION_PORTRAIT) { + orientation = nsIPrintSettings::kPortraitOrientation; + } else { + orientation = nsIPrintSettings::kLandscapeOrientation; + } + data->orientation() = orientation; + + NSSize paperSize = [printInfo paperSize]; + float widthScale, heightScale; + settingsX->GetInchesScale(&widthScale, &heightScale); + if (orientation == nsIPrintSettings::kLandscapeOrientation) { + // switch widths and heights + data->widthScale() = heightScale; + data->heightScale() = widthScale; + data->paperWidth() = paperSize.height / heightScale; + data->paperHeight() = paperSize.width / widthScale; + } else { + data->widthScale() = widthScale; + data->heightScale() = heightScale; + data->paperWidth() = paperSize.width / widthScale; + data->paperHeight() = paperSize.height / heightScale; + } + data->numCopies() = [[dict objectForKey: NSPrintCopies] intValue]; data->printAllPages() = [[dict objectForKey: NSPrintAllPages] boolValue]; data->startPageRange() = [[dict objectForKey: NSPrintFirstPage] intValue]; @@ -168,6 +213,28 @@ [newPrintInfoDict setObject: nsCocoaUtils::ToNSString(data.disposition()) forKey: NSPrintJobDisposition]; + [newPrintInfoDict setObject: nsCocoaUtils::ToNSString(data.paperName()) + forKey: NSPrintPaperName]; + + [newPrintInfoDict setObject: [NSNumber numberWithFloat: data.scalingFactor()] + forKey: NSPrintScalingFactor]; + + CGFloat width = data.paperWidth() * data.widthScale(); + CGFloat height = data.paperHeight() * data.heightScale(); + [newPrintInfoDict setObject: [NSValue valueWithSize:NSMakeSize(width,height)] + forKey: NSPrintPaperSize]; + + int paperOrientation; + if (data.orientation() == nsIPrintSettings::kPortraitOrientation) { + paperOrientation = NS_PAPER_ORIENTATION_PORTRAIT; + settings->SetOrientation(nsIPrintSettings::kPortraitOrientation); + } else { + paperOrientation = NS_PAPER_ORIENTATION_LANDSCAPE; + settings->SetOrientation(nsIPrintSettings::kLandscapeOrientation); + } + [newPrintInfoDict setObject: [NSNumber numberWithInt:paperOrientation] + forKey: NSPrintOrientation]; + [newPrintInfoDict setObject: [NSNumber numberWithShort: data.pagesAcross()] forKey: NSPrintPagesAcross]; [newPrintInfoDict setObject: [NSNumber numberWithShort: data.pagesDown()] diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/widget/cocoa/nsPrintSettingsX.h firefox-trunk-52.0~a1~hg20161113r322177/widget/cocoa/nsPrintSettingsX.h --- firefox-trunk-52.0~a1~hg20161110r321971/widget/cocoa/nsPrintSettingsX.h 2016-11-11 02:13:40.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/widget/cocoa/nsPrintSettingsX.h 2016-11-14 02:16:11.000000000 +0000 @@ -31,6 +31,13 @@ PMPageFormat GetPMPageFormat(); void SetPMPageFormat(PMPageFormat aPageFormat); + // Re-initialize mUnwriteableMargin with values from mPageFormat. + // Should be called whenever mPageFormat is initialized or overwritten. + nsresult InitUnwriteableMargin(); + + void SetInchesScale(float aWidthScale, float aHeightScale); + void GetInchesScale(float *aWidthScale, float *aHeightScale); + protected: virtual ~nsPrintSettingsX(); @@ -40,15 +47,16 @@ nsresult _Clone(nsIPrintSettings **_retval) override; nsresult _Assign(nsIPrintSettings *aPS) override; - // Re-initialize mUnwriteableMargin with values from mPageFormat. - // Should be called whenever mPageFormat is initialized or overwritten. - nsresult InitUnwriteableMargin(); - // The out param has a ref count of 1 on return so caller needs to PMRelase() when done. OSStatus CreateDefaultPageFormat(PMPrintSession aSession, PMPageFormat& outFormat); OSStatus CreateDefaultPrintSettings(PMPrintSession aSession, PMPrintSettings& outSettings); NSPrintInfo* mPrintInfo; + + // Scaling factors used to convert the NSPrintInfo + // paper size units to inches + float mWidthScale; + float mHeightScale; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsPrintSettingsX, NS_PRINTSETTINGSX_IID) diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/widget/cocoa/nsPrintSettingsX.mm firefox-trunk-52.0~a1~hg20161113r322177/widget/cocoa/nsPrintSettingsX.mm --- firefox-trunk-52.0~a1~hg20161110r321971/widget/cocoa/nsPrintSettingsX.mm 2016-11-11 02:13:40.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/widget/cocoa/nsPrintSettingsX.mm 2016-11-14 02:16:11.000000000 +0000 @@ -16,6 +16,7 @@ using namespace mozilla; #define MAC_OS_X_PAGE_SETUP_PREFNAME "print.macosx.pagesetup-2" +#define COCOA_PAPER_UNITS_PER_INCH 72.0 NS_IMPL_ISUPPORTS_INHERITED(nsPrintSettingsX, nsPrintSettings, nsPrintSettingsX) @@ -24,6 +25,8 @@ NS_OBJC_BEGIN_TRY_ABORT_BLOCK; mPrintInfo = [[NSPrintInfo sharedPrintInfo] copy]; + mWidthScale = COCOA_PAPER_UNITS_PER_INCH; + mHeightScale = COCOA_PAPER_UNITS_PER_INCH; NS_OBJC_END_TRY_ABORT_BLOCK; } @@ -200,3 +203,16 @@ [mPrintInfo updateFromPMPageFormat]; } +void +nsPrintSettingsX::SetInchesScale(float aWidthScale, float aHeightScale) +{ + mWidthScale = aWidthScale; + mHeightScale = aHeightScale; +} + +void +nsPrintSettingsX::GetInchesScale(float *aWidthScale, float *aHeightScale) +{ + *aWidthScale = mWidthScale; + *aHeightScale = mHeightScale; +} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/widget/gtk/gtk2drawing.c firefox-trunk-52.0~a1~hg20161113r322177/widget/gtk/gtk2drawing.c --- firefox-trunk-52.0~a1~hg20161110r321971/widget/gtk/gtk2drawing.c 2016-11-11 02:13:43.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/widget/gtk/gtk2drawing.c 2016-11-14 02:17:13.000000000 +0000 @@ -2977,6 +2977,10 @@ ensure_tab_widget(); w = gTabWidget; break; + case MOZ_GTK_TOOLTIP: + // In GTK 2 the spacing between box is set to 4. + *left = *top = *right = *bottom = 4; + return MOZ_GTK_SUCCESS; /* These widgets have no borders, since they are not containers. */ case MOZ_GTK_SPLITTER_HORIZONTAL: case MOZ_GTK_SPLITTER_VERTICAL: @@ -2998,7 +3002,6 @@ case MOZ_GTK_MENUSEPARATOR: /* These widgets have no borders.*/ case MOZ_GTK_SPINBUTTON: - case MOZ_GTK_TOOLTIP: case MOZ_GTK_WINDOW: case MOZ_GTK_RESIZER: case MOZ_GTK_MENUARROW: diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/widget/gtk/gtk3drawing.cpp firefox-trunk-52.0~a1~hg20161113r322177/widget/gtk/gtk3drawing.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/widget/gtk/gtk3drawing.cpp 2016-11-11 02:13:43.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/widget/gtk/gtk3drawing.cpp 2016-11-14 02:17:13.000000000 +0000 @@ -450,6 +450,16 @@ padding.top + padding.bottom; } +static void +moz_gtk_rectangle_inset(GdkRectangle* rect, GtkBorder& aBorder) +{ + MOZ_ASSERT(rect); + rect->x += aBorder.left; + rect->y += aBorder.top; + rect->width -= aBorder.left + aBorder.right; + rect->height -= aBorder.top + aBorder.bottom; +} + /* Subtracting margin is used to inset drawing of element which can have margins, * like scrollbar, scrollbar's trough, thumb and scrollbar's button */ static void @@ -460,10 +470,7 @@ gtk_style_context_get_margin(style, gtk_style_context_get_state(style), &margin); - rect->x += margin.left; - rect->y += margin.top; - rect->width -= margin.right + margin.left; - rect->height -= margin.top + margin.bottom; + moz_gtk_rectangle_inset(rect, margin); } static gint @@ -1247,12 +1254,57 @@ } static gint -moz_gtk_tooltip_paint(cairo_t *cr, GdkRectangle* rect, +moz_gtk_tooltip_paint(cairo_t *cr, const GdkRectangle* aRect, GtkTextDirection direction) { + // Tooltip widget is made in GTK3 as following tree: + // Tooltip window + // Horizontal Box + // Icon (not supported by Firefox) + // Label + // Each element can be fully styled by CSS of GTK theme. + // We have to draw all elements with appropriate offset and right dimensions. + + // Tooltip drawing GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_TOOLTIP, direction); - gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height); - gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height); + GdkRectangle rect = *aRect; + gtk_render_background(style, cr, rect.x, rect.y, rect.width, rect.height); + gtk_render_frame(style, cr, rect.x, rect.y, rect.width, rect.height); + + // Horizontal Box drawing + // + // The box element has hard-coded 6px margin-* GtkWidget properties, which + // are added between the window dimensions and the CSS margin box of the + // horizontal box. The frame of the tooltip window is drawn in the + // 6px margin. + // For drawing Horizontal Box we have to inset drawing area by that 6px + // plus its CSS margin. + GtkStyleContext* boxStyle = + CreateStyleForWidget(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0), style); + + rect.x += 6; + rect.y += 6; + rect.width -= 12; + rect.height -= 12; + + moz_gtk_subtract_margin(boxStyle, &rect); + gtk_render_background(boxStyle, cr, rect.x, rect.y, rect.width, rect.height); + gtk_render_frame(boxStyle, cr, rect.x, rect.y, rect.width, rect.height); + + // Label drawing + GtkBorder padding, border; + gtk_style_context_get_padding(boxStyle, GTK_STATE_FLAG_NORMAL, &padding); + moz_gtk_rectangle_inset(&rect, padding); + gtk_style_context_get_border(boxStyle, GTK_STATE_FLAG_NORMAL, &border); + moz_gtk_rectangle_inset(&rect, border); + + GtkStyleContext* labelStyle = + CreateStyleForWidget(gtk_label_new(nullptr), boxStyle); + moz_gtk_draw_styled_frame(labelStyle, cr, &rect, false); + g_object_unref(labelStyle); + + g_object_unref(boxStyle); + ReleaseStyleContext(style); return MOZ_GTK_SUCCESS; } @@ -2126,8 +2178,28 @@ case MOZ_GTK_TOOLTIP: { style = ClaimStyleContext(MOZ_GTK_TOOLTIP); - moz_gtk_add_style_border(style, left, top, right, bottom); - moz_gtk_add_style_padding(style, left, top, right, bottom); + // In GTK 3 there are 6 pixels of additional margin around the box. + // See details there: + // https://github.com/GNOME/gtk/blob/5ea69a136bd7e4970b3a800390e20314665aaed2/gtk/ui/gtktooltipwindow.ui#L11 + *left = *right = *top = *bottom = 6; + + // We also need to add margin/padding/borders from Tooltip content. + // Tooltip contains horizontal box, where icon and label is put. + // We ignore icon as long as we don't have support for it. + GtkStyleContext* boxStyle = + CreateStyleForWidget(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0), + style); + moz_gtk_add_margin_border_padding(boxStyle, + left, top, right, bottom); + + GtkStyleContext* labelStyle = + CreateStyleForWidget(gtk_label_new(nullptr), boxStyle); + moz_gtk_add_margin_border_padding(labelStyle, + left, top, right, bottom); + + g_object_unref(labelStyle); + g_object_unref(boxStyle); + ReleaseStyleContext(style); return MOZ_GTK_SUCCESS; } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/widget/windows/KeyboardLayout.cpp firefox-trunk-52.0~a1~hg20161113r322177/widget/windows/KeyboardLayout.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/widget/windows/KeyboardLayout.cpp 2016-11-11 02:14:41.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/widget/windows/KeyboardLayout.cpp 2016-11-14 02:18:12.000000000 +0000 @@ -3497,11 +3497,18 @@ sIdleService->ResetIdleTimeOut(0); } -KeyboardLayout::KeyboardLayout() : - mKeyboardLayout(0), mIsOverridden(false), - mIsPendingToRestoreKeyboardLayout(false) +KeyboardLayout::KeyboardLayout() + : mKeyboardLayout(0) + , mIsOverridden(false) + , mIsPendingToRestoreKeyboardLayout(false) { mDeadKeyTableListHead = nullptr; + // A dead key sequence should be made from up to 5 keys. Therefore, 4 is + // enough and makes sense because the item is uint8_t. + // (Although, even if it's possible to be 6 keys or more in a sequence, + // this array will be re-allocated). + mActiveDeadKeys.SetCapacity(4); + mDeadKeyShiftStates.SetCapacity(4); // NOTE: LoadLayout() should be called via OnLayoutChange(). } @@ -3613,8 +3620,7 @@ // If it's in dead key sequence and dead char is inputted as is, we need to // set the previous modifier state which is stored when preceding dead key // is pressed. - UniCharsAndModifiers deadChars = - GetUniCharsAndModifiers(mActiveDeadKey, mDeadKeyShiftState); + UniCharsAndModifiers deadChars = GetDeadUniCharsAndModifiers(); aNativeKey.mCommittedCharsAndModifiers. OverwriteModifiersIfBeginsWith(deadChars); // Finish the dead key sequence. @@ -3622,6 +3628,12 @@ return; } + // If it's a dead key, aNativeKey will be initialized by + // MaybeInitNativeKeyAsDeadKey(). + if (MaybeInitNativeKeyAsDeadKey(aNativeKey, aModKeyState)) { + return; + } + // If the key is not a usual printable key, KeyboardLayout class assume that // it's not cause dead char nor printable char. Therefore, there are nothing // to do here fore such keys (e.g., function keys). @@ -3636,12 +3648,6 @@ MOZ_ASSERT(aNativeKey.mKeyNameIndex == KEY_NAME_INDEX_USE_STRING, "Printable key's key name index must be KEY_NAME_INDEX_USE_STRING"); - // If it's a dead key, aNativeKey will be initialized by - // MaybeInitNativeKeyAsDeadKey(). - if (MaybeInitNativeKeyAsDeadKey(aNativeKey, aModKeyState)) { - return; - } - // If it's in dead key handling and the pressed key causes a composite // character, aNativeKey will be initialized by // MaybeInitNativeKeyWithCompositeChar(). @@ -3659,19 +3665,10 @@ return; } - // Although, this shouldn't occur, if active dead key isn't a printable - // key, we cannot handle it because KeyboardLayout assumes that dead key - // is never mapped to non-printable keys (e.g., F4, etc). Please be aware, - // it's possible, but we've not known such special keyboard layout yet. - if (NS_WARN_IF(!IsPrintableCharKey(mActiveDeadKey))) { - return; - } - // If the key doesn't cause a composite character with preceding dead key, // initialize aNativeKey with the dead-key character followed by current // key's character. - UniCharsAndModifiers deadChars = - GetUniCharsAndModifiers(mActiveDeadKey, mDeadKeyShiftState); + UniCharsAndModifiers deadChars = GetDeadUniCharsAndModifiers(); aNativeKey.mCommittedCharsAndModifiers = deadChars + baseChars; if (aNativeKey.IsKeyDownMessage()) { DeactivateDeadKeyState(); @@ -3683,25 +3680,28 @@ NativeKey& aNativeKey, const ModifierKeyState& aModKeyState) { - if (!IsDeadKey(aNativeKey.mOriginalVirtualKeyCode, aModKeyState)) { + // Only when it's not in dead key sequence, we can trust IsDeadKey() result. + if (!IsInDeadKeySequence() && + !IsDeadKey(aNativeKey.mOriginalVirtualKeyCode, aModKeyState)) { return false; } - // If it's a keydown event but not in dead key sequence or it's a keyup - // event of a dead key which activated current dead key sequence, - // initialize aNativeKey as a dead key event. - if ((aNativeKey.IsKeyDownMessage() && !IsInDeadKeySequence()) || - (!aNativeKey.IsKeyDownMessage() && - mActiveDeadKey == aNativeKey.mOriginalVirtualKeyCode)) { + // When keydown message is followed by a dead char message, it should be + // initialized as dead key. + bool isDeadKeyDownEvent = + aNativeKey.IsKeyDownMessage() && + aNativeKey.IsFollowedByDeadCharMessage(); + + // When keyup message is received, let's check if it's one of preceding + // dead keys because keydown message order and keyup message order may be + // different. + bool isDeadKeyUpEvent = + !aNativeKey.IsKeyDownMessage() && + mActiveDeadKeys.Contains(aNativeKey.mOriginalVirtualKeyCode); + + if (isDeadKeyDownEvent || isDeadKeyUpEvent) { ActivateDeadKeyState(aNativeKey, aModKeyState); -#ifdef DEBUG - UniCharsAndModifiers deadChars = - GetNativeUniCharsAndModifiers(aNativeKey.mOriginalVirtualKeyCode, - aModKeyState); - MOZ_ASSERT(deadChars.Length() == 1, - "dead key must generate only one character"); -#endif - // First dead key event doesn't generate characters. Dead key should + // Any dead key events don't generate characters. So, a dead key should // cause only keydown event and keyup event whose KeyboardEvent.key // values are "Dead". aNativeKey.mCommittedCharsAndModifiers.Clear(); @@ -3720,27 +3720,18 @@ return true; } + // When non-printable key event comes during a dead key sequence, that must + // be a modifier key event. So, such events shouldn't be handled as a part + // of the dead key sequence. + if (!IsDeadKey(aNativeKey.mOriginalVirtualKeyCode, aModKeyState)) { + return false; + } + // FYI: Following code may run when the user doesn't input text actually // but the key sequence is a dead key sequence. For example, // ` -> Ctrl+` with Spanish keyboard layout. Let's keep using this // complicated code for now because this runs really rarely. - if (NS_WARN_IF(!IsPrintableCharKey(mActiveDeadKey))) { -#if defined(DEBUG) || defined(MOZ_CRASHREPORTER) - nsPrintfCString warning("The virtual key index (%d) of mActiveDeadKey " - "(0x%02X) is not a printable key " - "(aNativeKey.mOriginalVirtualKeyCode=0x%02X)", - GetKeyIndex(mActiveDeadKey), mActiveDeadKey, - aNativeKey.mOriginalVirtualKeyCode); - NS_WARNING(warning.get()); -#ifdef MOZ_CRASHREPORTER - CrashReporter::AppendAppNotesToCrashReport( - NS_LITERAL_CSTRING("\n") + warning); -#endif // #ifdef MOZ_CRASHREPORTER -#endif // #if defined(DEBUG) || defined(MOZ_CRASHREPORTER) - MOZ_CRASH("Trying to reference out of range of mVirtualKeys"); - } - // Dead key followed by another dead key may cause a composed character // (e.g., "Russian - Mnemonic" keyboard layout's 's' -> 'c'). if (MaybeInitNativeKeyWithCompositeChar(aNativeKey, aModKeyState)) { @@ -3749,8 +3740,7 @@ // Otherwise, dead key followed by another dead key causes inputting both // character. - UniCharsAndModifiers prevDeadChars = - GetUniCharsAndModifiers(mActiveDeadKey, mDeadKeyShiftState); + UniCharsAndModifiers prevDeadChars = GetDeadUniCharsAndModifiers(); UniCharsAndModifiers newChars = GetUniCharsAndModifiers(aNativeKey.mOriginalVirtualKeyCode, aModKeyState); // But keypress events should be fired for each committed character. @@ -3770,8 +3760,7 @@ return false; } - if (NS_WARN_IF(!IsPrintableCharKey(mActiveDeadKey)) || - NS_WARN_IF(!IsPrintableCharKey(aNativeKey.mOriginalVirtualKeyCode))) { + if (NS_WARN_IF(!IsPrintableCharKey(aNativeKey.mOriginalVirtualKeyCode))) { return false; } @@ -3781,8 +3770,7 @@ return false; } - char16_t compositeChar = - GetCompositeChar(mActiveDeadKey, mDeadKeyShiftState, baseChars.CharAt(0)); + char16_t compositeChar = GetCompositeChar(baseChars.CharAt(0)); if (!compositeChar) { return false; } @@ -3824,16 +3812,43 @@ return mVirtualKeys[key].GetNativeUniChars(shiftState); } +UniCharsAndModifiers +KeyboardLayout::GetDeadUniCharsAndModifiers() const +{ + MOZ_RELEASE_ASSERT(mActiveDeadKeys.Length() == mDeadKeyShiftStates.Length()); + + if (NS_WARN_IF(mActiveDeadKeys.IsEmpty())) { + return UniCharsAndModifiers(); + } + + UniCharsAndModifiers result; + for (size_t i = 0; i < mActiveDeadKeys.Length(); ++i) { + result += + GetUniCharsAndModifiers(mActiveDeadKeys[i], mDeadKeyShiftStates[i]); + } + return result; +} + char16_t -KeyboardLayout::GetCompositeChar(uint8_t aVirtualKeyOfDeadKey, - VirtualKey::ShiftState aShiftStateOfDeadKey, - char16_t aBaseChar) const +KeyboardLayout::GetCompositeChar(char16_t aBaseChar) const { - int32_t key = GetKeyIndex(aVirtualKeyOfDeadKey); + if (NS_WARN_IF(mActiveDeadKeys.IsEmpty())) { + return 0; + } + // XXX Currently, we don't support computing a composite character with + // two or more dead keys since it needs big table for supporting + // long chained dead keys. However, this should be a minor bug + // because this runs only when the latest keydown event does not cause + // WM_(SYS)CHAR messages. So, when user wants to input a character, + // this path never runs. + if (mActiveDeadKeys.Length() > 1) { + return 0; + } + int32_t key = GetKeyIndex(mActiveDeadKeys[0]); if (key < 0) { return 0; } - return mVirtualKeys[key].GetCompositeChar(aShiftStateOfDeadKey, aBaseChar); + return mVirtualKeys[key].GetCompositeChar(mDeadKeyShiftStates[0], aBaseChar); } void @@ -3860,7 +3875,8 @@ // characters. uint16_t shiftStatesWithBaseChars = 0; - mActiveDeadKey = -1; + mActiveDeadKeys.Clear(); + mDeadKeyShiftStates.Clear(); ReleaseDeadKeyTables(); @@ -4099,26 +4115,26 @@ return; } - MOZ_RELEASE_ASSERT(IsPrintableCharKey(aNativeKey.mOriginalVirtualKeyCode)); - - mActiveDeadKey = aNativeKey.mOriginalVirtualKeyCode; - mDeadKeyShiftState = VirtualKey::ModifierKeyStateToShiftState(aModKeyState); + mActiveDeadKeys.AppendElement(aNativeKey.mOriginalVirtualKeyCode); + mDeadKeyShiftStates.AppendElement( + VirtualKey::ModifierKeyStateToShiftState(aModKeyState)); } void KeyboardLayout::DeactivateDeadKeyState() { - if (mActiveDeadKey < 0) { + if (mActiveDeadKeys.IsEmpty()) { return; } BYTE kbdState[256]; memset(kbdState, 0, sizeof(kbdState)); - VirtualKey::FillKbdState(kbdState, mDeadKeyShiftState); - - EnsureDeadKeyActive(false, mActiveDeadKey, kbdState); - mActiveDeadKey = -1; + // Assume that the last dead key can finish dead key sequence. + VirtualKey::FillKbdState(kbdState, mDeadKeyShiftStates.LastElement()); + EnsureDeadKeyActive(false, mActiveDeadKeys.LastElement(), kbdState); + mActiveDeadKeys.Clear(); + mDeadKeyShiftStates.Clear(); } bool diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/widget/windows/KeyboardLayout.h firefox-trunk-52.0~a1~hg20161113r322177/widget/windows/KeyboardLayout.h --- firefox-trunk-52.0~a1~hg20161110r321971/widget/windows/KeyboardLayout.h 2016-11-11 02:14:41.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/widget/windows/KeyboardLayout.h 2016-11-14 02:18:12.000000000 +0000 @@ -694,7 +694,7 @@ * It starts when a dead key is down and ends when another key down causes * inactivating the dead key state. */ - bool IsInDeadKeySequence() const { return mActiveDeadKey >= 0; } + bool IsInDeadKeySequence() const { return !mActiveDeadKeys.IsEmpty(); } /** * IsSysKey() returns true if aVirtualKey with aModKeyState causes WM_SYSKEY* @@ -811,8 +811,14 @@ VirtualKey mVirtualKeys[NS_NUM_OF_KEYS]; DeadKeyTableListEntry* mDeadKeyTableListHead; - int32_t mActiveDeadKey; // -1 = no active dead-key - VirtualKey::ShiftState mDeadKeyShiftState; + // When mActiveDeadKeys is empty, it's not in dead key sequence. + // Otherwise, it contains virtual keycodes which are pressed in current + // dead key sequence. + nsTArray mActiveDeadKeys; + // mDeadKeyShiftStates is always same length as mActiveDeadKeys. + // This stores shift states at pressing each dead key stored in + // mActiveDeadKeys. + nsTArray mDeadKeyShiftStates; bool mIsOverridden; bool mIsPendingToRestoreKeyboardLayout; @@ -884,15 +890,19 @@ VirtualKey::ShiftState aShiftState) const; /** + * GetDeadUniCharsAndModifiers() returns dead chars which are stored in + * current dead key sequence. So, this is stateful. + */ + UniCharsAndModifiers GetDeadUniCharsAndModifiers() const; + + /** * GetCompositeChar() returns a composite character with dead character - * caused by aVirtualKeyOfDeadKey and aShiftStateOfDeadKey and a base - * character (aBaseChar). + * caused by mActiveDeadKeys, mDeadKeyShiftStates and a base character + * (aBaseChar). * If the combination of the dead character and the base character doesn't * cause a composite character, this returns 0. */ - char16_t GetCompositeChar(uint8_t aVirtualKeyOfDeadKey, - VirtualKey::ShiftState aShiftStateOfDeadKey, - char16_t aBaseChar) const; + char16_t GetCompositeChar(char16_t aBaseChar) const; // NativeKey class should access InitNativeKey() directly, but it shouldn't // be available outside of NativeKey. So, let's make NativeKey a friend diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/build/XPCOM.h firefox-trunk-52.0~a1~hg20161113r322177/xpcom/build/XPCOM.h --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/build/XPCOM.h 2016-11-11 02:15:53.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/build/XPCOM.h 2016-11-14 02:19:01.000000000 +0000 @@ -63,7 +63,6 @@ #include "nsIAtomService.h" #include "nsICategoryManager.h" #include "nsIClassInfo.h" -#include "nsICollection.h" #include "nsIComponentManager.h" #include "nsIConsoleListener.h" #include "nsIConsoleMessage.h" diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/build/XPCOMInit.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/build/XPCOMInit.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/build/XPCOMInit.cpp 2016-11-11 02:15:53.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/build/XPCOMInit.cpp 2016-11-14 02:19:01.000000000 +0000 @@ -38,7 +38,24 @@ #include "nsTraceRefcnt.h" #include "nsErrorService.h" +// Disable deprecation warnings generated by nsISupportsArray and associated +// classes. +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#elif defined(_MSC_VER) +#pragma warning (push) +#pragma warning (disable : 4996) +#endif + #include "nsSupportsArray.h" + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#elif defined(_MSC_VER) +#pragma warning (pop) +#endif + #include "nsArray.h" #include "nsINIParserImpl.h" #include "nsSupportsPrimitives.h" diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/ds/nsICollection.idl firefox-trunk-52.0~a1~hg20161113r322177/xpcom/ds/nsICollection.idl --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/ds/nsICollection.idl 2016-11-11 02:15:56.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/ds/nsICollection.idl 2016-11-14 02:19:35.000000000 +0000 @@ -7,7 +7,7 @@ interface nsIEnumerator; -[scriptable, uuid(83b6019c-cbc4-11d2-8cca-0060b0fc14a3)] +[deprecated, scriptable, uuid(83b6019c-cbc4-11d2-8cca-0060b0fc14a3)] interface nsICollection : nsISerializable { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/ds/nsIEnumerator.idl firefox-trunk-52.0~a1~hg20161113r322177/xpcom/ds/nsIEnumerator.idl --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/ds/nsIEnumerator.idl 2016-11-11 02:15:56.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/ds/nsIEnumerator.idl 2016-11-14 02:19:35.000000000 +0000 @@ -16,7 +16,7 @@ * * DON'T MAKE ME COME OVER THERE. */ -[scriptable, uuid(ad385286-cbc4-11d2-8cca-0060b0fc14a3)] +[deprecated, scriptable, uuid(ad385286-cbc4-11d2-8cca-0060b0fc14a3)] interface nsIEnumerator : nsISupports { /** First will reset the list. will return NS_FAILED if no items */ @@ -37,7 +37,7 @@ void isDone(); }; -[uuid(75f158a0-cadd-11d2-8cca-0060b0fc14a3)] +[deprecated, uuid(75f158a0-cadd-11d2-8cca-0060b0fc14a3)] interface nsIBidirectionalEnumerator : nsIEnumerator { /** Last will reset the list to the end. will return NS_FAILED if no items diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/ds/nsISupportsArray.idl firefox-trunk-52.0~a1~hg20161113r322177/xpcom/ds/nsISupportsArray.idl --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/ds/nsISupportsArray.idl 2016-11-11 02:15:56.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/ds/nsISupportsArray.idl 2016-11-14 02:19:36.000000000 +0000 @@ -30,7 +30,7 @@ %} -[scriptable, uuid(241addc8-3608-4e73-8083-2fd6fa09eba2)] +[deprecated, scriptable, uuid(241addc8-3608-4e73-8083-2fd6fa09eba2)] interface nsISupportsArray : nsICollection { [notxpcom] long IndexOf([const] in nsISupports aPossibleElement); diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/ds/nsSupportsArray.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/ds/nsSupportsArray.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/ds/nsSupportsArray.cpp 2016-11-11 02:15:56.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/ds/nsSupportsArray.cpp 2016-11-14 02:19:37.000000000 +0000 @@ -13,6 +13,16 @@ #include "nsSupportsArray.h" #include "nsSupportsArrayEnumerator.h" +// Disable deprecation warnings generated by nsISupportsArray and associated +// classes. +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#elif defined(_MSC_VER) +#pragma warning (push) +#pragma warning (disable : 4996) +#endif + nsresult nsQueryElementAt::operator()(const nsIID& aIID, void** aResult) const { @@ -245,3 +255,10 @@ { return NS_NewArrayEnumerator(aResult, this); } + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#elif defined(_MSC_VER) +#pragma warning (pop) +#endif + diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/ds/nsSupportsArrayEnumerator.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/ds/nsSupportsArrayEnumerator.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/ds/nsSupportsArrayEnumerator.cpp 2016-11-11 02:15:56.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/ds/nsSupportsArrayEnumerator.cpp 2016-11-14 02:19:37.000000000 +0000 @@ -5,6 +5,17 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsSupportsArrayEnumerator.h" + +// Disable deprecation warnings generated by nsISupportsArray and associated +// classes. +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#elif defined(_MSC_VER) +#pragma warning (push) +#pragma warning (disable : 4996) +#endif + #include "nsISupportsArray.h" nsSupportsArrayEnumerator::nsSupportsArrayEnumerator(nsISupportsArray* array) @@ -113,3 +124,8 @@ } } +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#elif defined(_MSC_VER) +#pragma warning (pop) +#endif diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/ds/nsSupportsArrayEnumerator.h firefox-trunk-52.0~a1~hg20161113r322177/xpcom/ds/nsSupportsArrayEnumerator.h --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/ds/nsSupportsArrayEnumerator.h 2016-11-11 02:15:56.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/ds/nsSupportsArrayEnumerator.h 2016-11-14 02:19:37.000000000 +0000 @@ -8,9 +8,20 @@ #define nsSupportsArrayEnumerator_h___ #include "nsCOMPtr.h" -#include "nsIEnumerator.h" #include "mozilla/Attributes.h" +// Disable deprecation warnings generated by nsISupportsArray and associated +// classes. +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#elif defined(_MSC_VER) +#pragma warning (push) +#pragma warning (disable : 4996) +#endif + +#include "nsIEnumerator.h" + class nsISupportsArray; class nsSupportsArrayEnumerator final : public nsIBidirectionalEnumerator @@ -35,5 +46,11 @@ }; +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#elif defined(_MSC_VER) +#pragma warning (pop) +#endif + #endif // __nsSupportsArrayEnumerator_h diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/ds/nsSupportsArray.h firefox-trunk-52.0~a1~hg20161113r322177/xpcom/ds/nsSupportsArray.h --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/ds/nsSupportsArray.h 2016-11-11 02:15:56.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/ds/nsSupportsArray.h 2016-11-14 02:19:37.000000000 +0000 @@ -8,10 +8,22 @@ #define nsSupportsArray_h__ #include "nsIArray.h" -#include "nsISupportsArray.h" #include "nsCOMArray.h" #include "mozilla/Attributes.h" + +// Disable deprecation warnings generated by nsISupportsArray and associated +// classes. +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#elif defined(_MSC_VER) +#pragma warning (push) +#pragma warning (disable : 4996) +#endif + +#include "nsISupportsArray.h" + class nsSupportsArray final : public nsISupportsArray, public nsIArray { @@ -86,4 +98,10 @@ nsCOMArray mArray; }; +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#elif defined(_MSC_VER) +#pragma warning (pop) +#endif + #endif // nsSupportsArray_h__ diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/glue/nsCOMPtr.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/glue/nsCOMPtr.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/glue/nsCOMPtr.cpp 2016-11-11 02:15:57.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/glue/nsCOMPtr.cpp 2016-11-14 02:19:48.000000000 +0000 @@ -49,7 +49,7 @@ { void* newRawPtr; if (NS_FAILED(aQI(aIID, &newRawPtr))) { - newRawPtr = 0; + newRawPtr = nullptr; } assign_assuming_AddRef(static_cast(newRawPtr)); } @@ -60,7 +60,7 @@ { void* newRawPtr; if (NS_FAILED(aQI(aIID, &newRawPtr))) { - newRawPtr = 0; + newRawPtr = nullptr; } assign_assuming_AddRef(static_cast(newRawPtr)); } @@ -71,7 +71,7 @@ { void* newRawPtr; if (NS_FAILED(aGS(aIID, &newRawPtr))) { - newRawPtr = 0; + newRawPtr = nullptr; } assign_assuming_AddRef(static_cast(newRawPtr)); } @@ -82,7 +82,7 @@ { void* newRawPtr; if (NS_FAILED(aGS(aIID, &newRawPtr))) { - newRawPtr = 0; + newRawPtr = nullptr; } assign_assuming_AddRef(static_cast(newRawPtr)); } @@ -93,7 +93,7 @@ { void* newRawPtr; if (NS_FAILED(aGS(aIID, &newRawPtr))) { - newRawPtr = 0; + newRawPtr = nullptr; } assign_assuming_AddRef(static_cast(newRawPtr)); } @@ -104,7 +104,7 @@ { void* newRawPtr; if (NS_FAILED(aGS(aIID, &newRawPtr))) { - newRawPtr = 0; + newRawPtr = nullptr; } assign_assuming_AddRef(static_cast(newRawPtr)); } @@ -115,7 +115,7 @@ { void* newRawPtr; if (NS_FAILED(aHelper(aIID, &newRawPtr))) { - newRawPtr = 0; + newRawPtr = nullptr; } assign_assuming_AddRef(static_cast(newRawPtr)); } @@ -123,6 +123,6 @@ void** nsCOMPtr_base::begin_assignment() { - assign_assuming_AddRef(0); + assign_assuming_AddRef(nullptr); return reinterpret_cast(&mRawPtr); } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/glue/nsCOMPtr.h firefox-trunk-52.0~a1~hg20161113r322177/xpcom/glue/nsCOMPtr.h --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/glue/nsCOMPtr.h 2016-11-11 02:15:57.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/glue/nsCOMPtr.h 2016-11-14 02:19:48.000000000 +0000 @@ -285,7 +285,7 @@ class nsCOMPtr_base { public: - explicit nsCOMPtr_base(nsISupports* aRawPtr = 0) : mRawPtr(aRawPtr) {} + explicit nsCOMPtr_base(nsISupports* aRawPtr = nullptr) : mRawPtr(aRawPtr) {} NS_CONSTRUCTOR_FASTCALL ~nsCOMPtr_base() { @@ -424,10 +424,17 @@ // Constructors nsCOMPtr() - : NSCAP_CTOR_BASE(0) + : NSCAP_CTOR_BASE(nullptr) { assert_validity(); - NSCAP_LOG_ASSIGNMENT(this, 0); + NSCAP_LOG_ASSIGNMENT(this, nullptr); + } + + MOZ_IMPLICIT nsCOMPtr(decltype(nullptr)) + : NSCAP_CTOR_BASE(nullptr) + { + assert_validity(); + NSCAP_LOG_ASSIGNMENT(this, nullptr); } nsCOMPtr(const nsCOMPtr& aSmartPtr) @@ -505,65 +512,65 @@ // Construct from |do_QueryInterface(expr)|. MOZ_IMPLICIT nsCOMPtr(const nsQueryInterface aQI) - : NSCAP_CTOR_BASE(0) + : NSCAP_CTOR_BASE(nullptr) { assert_validity(); - NSCAP_LOG_ASSIGNMENT(this, 0); + NSCAP_LOG_ASSIGNMENT(this, nullptr); assign_from_qi(aQI, NS_GET_TEMPLATE_IID(T)); } // Construct from |do_QueryInterface(expr, &rv)|. MOZ_IMPLICIT nsCOMPtr(const nsQueryInterfaceWithError& aQI) - : NSCAP_CTOR_BASE(0) + : NSCAP_CTOR_BASE(nullptr) { assert_validity(); - NSCAP_LOG_ASSIGNMENT(this, 0); + NSCAP_LOG_ASSIGNMENT(this, nullptr); assign_from_qi_with_error(aQI, NS_GET_TEMPLATE_IID(T)); } // Construct from |do_GetService(cid_expr)|. MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByCID aGS) - : NSCAP_CTOR_BASE(0) + : NSCAP_CTOR_BASE(nullptr) { assert_validity(); - NSCAP_LOG_ASSIGNMENT(this, 0); + NSCAP_LOG_ASSIGNMENT(this, nullptr); assign_from_gs_cid(aGS, NS_GET_TEMPLATE_IID(T)); } // Construct from |do_GetService(cid_expr, &rv)|. MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByCIDWithError& aGS) - : NSCAP_CTOR_BASE(0) + : NSCAP_CTOR_BASE(nullptr) { assert_validity(); - NSCAP_LOG_ASSIGNMENT(this, 0); + NSCAP_LOG_ASSIGNMENT(this, nullptr); assign_from_gs_cid_with_error(aGS, NS_GET_TEMPLATE_IID(T)); } // Construct from |do_GetService(contractid_expr)|. MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByContractID aGS) - : NSCAP_CTOR_BASE(0) + : NSCAP_CTOR_BASE(nullptr) { assert_validity(); - NSCAP_LOG_ASSIGNMENT(this, 0); + NSCAP_LOG_ASSIGNMENT(this, nullptr); assign_from_gs_contractid(aGS, NS_GET_TEMPLATE_IID(T)); } // Construct from |do_GetService(contractid_expr, &rv)|. MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByContractIDWithError& aGS) - : NSCAP_CTOR_BASE(0) + : NSCAP_CTOR_BASE(nullptr) { assert_validity(); - NSCAP_LOG_ASSIGNMENT(this, 0); + NSCAP_LOG_ASSIGNMENT(this, nullptr); assign_from_gs_contractid_with_error(aGS, NS_GET_TEMPLATE_IID(T)); } // And finally, anything else we might need to construct from can exploit the // nsCOMPtr_helper facility. MOZ_IMPLICIT nsCOMPtr(const nsCOMPtr_helper& aHelper) - : NSCAP_CTOR_BASE(0) + : NSCAP_CTOR_BASE(nullptr) { assert_validity(); - NSCAP_LOG_ASSIGNMENT(this, 0); + NSCAP_LOG_ASSIGNMENT(this, nullptr); assign_from_helper(aHelper, NS_GET_TEMPLATE_IID(T)); NSCAP_ASSERT_NO_QUERY_NEEDED(); } @@ -588,6 +595,12 @@ return *this; } + nsCOMPtr& operator=(decltype(nullptr)) + { + assign_assuming_AddRef(nullptr); + return *this; + } + // Assign from |already_AddRefed|. template nsCOMPtr& operator=(already_AddRefed& aRhs) @@ -706,7 +719,7 @@ // already_AddRefed return values. already_AddRefed forget() { - T* temp = 0; + T* temp = nullptr; swap(temp); return already_AddRefed(temp); } @@ -720,7 +733,7 @@ NS_ASSERTION(aRhs, "Null pointer passed to forget!"); NSCAP_LOG_RELEASE(this, mRawPtr); *aRhs = get(); - mRawPtr = 0; + mRawPtr = nullptr; } // Prefer the implicit conversion provided automatically by @@ -752,7 +765,7 @@ T* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN { - MOZ_ASSERT(mRawPtr != 0, + MOZ_ASSERT(mRawPtr != nullptr, "You can't dereference a NULL nsCOMPtr with operator->()."); return get(); } @@ -764,7 +777,7 @@ public: T& operator*() const { - MOZ_ASSERT(mRawPtr != 0, + MOZ_ASSERT(mRawPtr != nullptr, "You can't dereference a NULL nsCOMPtr with operator*()."); return *get(); } @@ -774,7 +787,7 @@ #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT return reinterpret_cast(begin_assignment()); #else - assign_assuming_AddRef(0); + assign_assuming_AddRef(nullptr); return reinterpret_cast(&mRawPtr); #endif } @@ -800,9 +813,15 @@ // Constructors nsCOMPtr() - : nsCOMPtr_base(0) + : nsCOMPtr_base(nullptr) { - NSCAP_LOG_ASSIGNMENT(this, 0); + NSCAP_LOG_ASSIGNMENT(this, nullptr); + } + + MOZ_IMPLICIT nsCOMPtr(decltype(nullptr)) + : nsCOMPtr_base(nullptr) + { + NSCAP_LOG_ASSIGNMENT(this, nullptr); } nsCOMPtr(const nsCOMPtr& aSmartPtr) @@ -839,58 +858,58 @@ // Construct from |do_QueryInterface(expr)|. MOZ_IMPLICIT nsCOMPtr(const nsQueryInterface aQI) - : nsCOMPtr_base(0) + : nsCOMPtr_base(nullptr) { - NSCAP_LOG_ASSIGNMENT(this, 0); + NSCAP_LOG_ASSIGNMENT(this, nullptr); assign_from_qi(aQI, NS_GET_IID(nsISupports)); } // Construct from |do_QueryInterface(expr, &rv)|. MOZ_IMPLICIT nsCOMPtr(const nsQueryInterfaceWithError& aQI) - : nsCOMPtr_base(0) + : nsCOMPtr_base(nullptr) { - NSCAP_LOG_ASSIGNMENT(this, 0); + NSCAP_LOG_ASSIGNMENT(this, nullptr); assign_from_qi_with_error(aQI, NS_GET_IID(nsISupports)); } // Construct from |do_GetService(cid_expr)|. MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByCID aGS) - : nsCOMPtr_base(0) + : nsCOMPtr_base(nullptr) { - NSCAP_LOG_ASSIGNMENT(this, 0); + NSCAP_LOG_ASSIGNMENT(this, nullptr); assign_from_gs_cid(aGS, NS_GET_IID(nsISupports)); } // Construct from |do_GetService(cid_expr, &rv)|. MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByCIDWithError& aGS) - : nsCOMPtr_base(0) + : nsCOMPtr_base(nullptr) { - NSCAP_LOG_ASSIGNMENT(this, 0); + NSCAP_LOG_ASSIGNMENT(this, nullptr); assign_from_gs_cid_with_error(aGS, NS_GET_IID(nsISupports)); } // Construct from |do_GetService(contractid_expr)|. MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByContractID aGS) - : nsCOMPtr_base(0) + : nsCOMPtr_base(nullptr) { - NSCAP_LOG_ASSIGNMENT(this, 0); + NSCAP_LOG_ASSIGNMENT(this, nullptr); assign_from_gs_contractid(aGS, NS_GET_IID(nsISupports)); } // Construct from |do_GetService(contractid_expr, &rv)|. MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByContractIDWithError& aGS) - : nsCOMPtr_base(0) + : nsCOMPtr_base(nullptr) { - NSCAP_LOG_ASSIGNMENT(this, 0); + NSCAP_LOG_ASSIGNMENT(this, nullptr); assign_from_gs_contractid_with_error(aGS, NS_GET_IID(nsISupports)); } // And finally, anything else we might need to construct from can exploit // the |nsCOMPtr_helper| facility MOZ_IMPLICIT nsCOMPtr(const nsCOMPtr_helper& aHelper) - : nsCOMPtr_base(0) + : nsCOMPtr_base(nullptr) { - NSCAP_LOG_ASSIGNMENT(this, 0); + NSCAP_LOG_ASSIGNMENT(this, nullptr); assign_from_helper(aHelper, NS_GET_IID(nsISupports)); } @@ -909,6 +928,12 @@ return *this; } + nsCOMPtr& operator=(decltype(nullptr)) + { + assign_assuming_AddRef(nullptr); + return *this; + } + // Assign from |already_AddRefed|. nsCOMPtr& operator=(already_AddRefed& aRhs) { @@ -999,7 +1024,7 @@ // already_AddRefed return values. already_AddRefed forget() { - nsISupports* temp = 0; + nsISupports* temp = nullptr; swap(temp); return already_AddRefed(temp); } @@ -1010,7 +1035,7 @@ void forget(nsISupports** aRhs) { NS_ASSERTION(aRhs, "Null pointer passed to forget!"); - *aRhs = 0; + *aRhs = nullptr; swap(*aRhs); } @@ -1031,7 +1056,7 @@ nsISupports* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN { - MOZ_ASSERT(mRawPtr != 0, + MOZ_ASSERT(mRawPtr != nullptr, "You can't dereference a NULL nsCOMPtr with operator->()."); return get(); } @@ -1044,7 +1069,7 @@ nsISupports& operator*() const { - MOZ_ASSERT(mRawPtr != 0, + MOZ_ASSERT(mRawPtr != nullptr, "You can't dereference a NULL nsCOMPtr with operator*()."); return *get(); } @@ -1054,7 +1079,7 @@ #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT return reinterpret_cast(begin_assignment()); #else - assign_assuming_AddRef(0); + assign_assuming_AddRef(nullptr); return reinterpret_cast(&mRawPtr); #endif } @@ -1094,7 +1119,7 @@ { void* newRawPtr; if (NS_FAILED(aQI(aIID, &newRawPtr))) { - newRawPtr = 0; + newRawPtr = nullptr; } assign_assuming_AddRef(static_cast(newRawPtr)); } @@ -1106,7 +1131,7 @@ { void* newRawPtr; if (NS_FAILED(aQI(aIID, &newRawPtr))) { - newRawPtr = 0; + newRawPtr = nullptr; } assign_assuming_AddRef(static_cast(newRawPtr)); } @@ -1117,7 +1142,7 @@ { void* newRawPtr; if (NS_FAILED(aGS(aIID, &newRawPtr))) { - newRawPtr = 0; + newRawPtr = nullptr; } assign_assuming_AddRef(static_cast(newRawPtr)); } @@ -1129,7 +1154,7 @@ { void* newRawPtr; if (NS_FAILED(aGS(aIID, &newRawPtr))) { - newRawPtr = 0; + newRawPtr = nullptr; } assign_assuming_AddRef(static_cast(newRawPtr)); } @@ -1141,7 +1166,7 @@ { void* newRawPtr; if (NS_FAILED(aGS(aIID, &newRawPtr))) { - newRawPtr = 0; + newRawPtr = nullptr; } assign_assuming_AddRef(static_cast(newRawPtr)); } @@ -1153,7 +1178,7 @@ { void* newRawPtr; if (NS_FAILED(aGS(aIID, &newRawPtr))) { - newRawPtr = 0; + newRawPtr = nullptr; } assign_assuming_AddRef(static_cast(newRawPtr)); } @@ -1164,7 +1189,7 @@ { void* newRawPtr; if (NS_FAILED(helper(aIID, &newRawPtr))) { - newRawPtr = 0; + newRawPtr = nullptr; } assign_assuming_AddRef(static_cast(newRawPtr)); } @@ -1173,7 +1198,7 @@ void** nsCOMPtr::begin_assignment() { - assign_assuming_AddRef(0); + assign_assuming_AddRef(nullptr); union { T** mT; @@ -1426,7 +1451,7 @@ { void* newRawPtr; if (NS_FAILED(aHelper(NS_GET_TEMPLATE_IID(T), &newRawPtr))) { - newRawPtr = 0; + newRawPtr = nullptr; } mRawPtr = static_cast(newRawPtr); } @@ -1437,7 +1462,7 @@ { void* newRawPtr; if (NS_FAILED(aHelper(NS_GET_TEMPLATE_IID(T), &newRawPtr))) { - newRawPtr = 0; + newRawPtr = nullptr; } assign_assuming_AddRef(static_cast(newRawPtr)); return *this; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/glue/tests/gtest/TestArray.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/glue/tests/gtest/TestArray.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/glue/tests/gtest/TestArray.cpp 2016-11-11 02:16:20.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/glue/tests/gtest/TestArray.cpp 2016-11-14 02:19:50.000000000 +0000 @@ -6,9 +6,20 @@ #include #include -#include "nsISupportsArray.h" #include "gtest/gtest.h" +// Disable deprecation warnings generated by nsISupportsArray and associated +// classes. +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#elif defined(_MSC_VER) +#pragma warning (push) +#pragma warning (disable : 4996) +#endif + +#include "nsISupportsArray.h" + // {9e70a320-be02-11d1-8031-006008159b5a} #define NS_IFOO_IID \ {0x9e70a320, 0xbe02, 0x11d1, \ @@ -150,3 +161,9 @@ NS_RELEASE(array); } } + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#elif defined(_MSC_VER) +#pragma warning (pop) +#endif diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/io/nsInputStreamTee.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/io/nsInputStreamTee.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/io/nsInputStreamTee.cpp 2016-11-11 02:16:28.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/io/nsInputStreamTee.cpp 2016-11-14 02:19:51.000000000 +0000 @@ -179,7 +179,7 @@ NS_WARNING("Write failed (non-fatal)"); // catch possible misuse of the input stream tee NS_ASSERTION(rv != NS_BASE_STREAM_WOULD_BLOCK, "sink must be a blocking stream"); - mSink = 0; + mSink = nullptr; break; } totalBytesWritten += bytesWritten; @@ -217,8 +217,8 @@ return NS_ERROR_NOT_INITIALIZED; } nsresult rv = mSource->Close(); - mSource = 0; - mSink = 0; + mSource = nullptr; + mSink = nullptr; return rv; } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/io/nsLocalFileWin.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/io/nsLocalFileWin.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/io/nsLocalFileWin.cpp 2016-11-11 02:16:29.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/io/nsLocalFileWin.cpp 2016-11-14 02:19:51.000000000 +0000 @@ -180,13 +180,12 @@ HRESULT hr; if (attributes & FILE_ATTRIBUTE_DIRECTORY) { // We have a directory so we should open the directory itself. - ITEMIDLIST* dir = - static_cast(ILCreateFromPathW(mResolvedPath.get())); + LPITEMIDLIST dir = ILCreateFromPathW(mResolvedPath.get()); if (!dir) { return NS_ERROR_FAILURE; } - const ITEMIDLIST* selection[] = { dir }; + LPCITEMIDLIST selection[] = { dir }; UINT count = ArrayLength(selection); //Perform the open of the directory. @@ -204,21 +203,19 @@ PathRemoveFileSpecW(parentDirectoryPath); // We have a file so we should open the parent directory. - ITEMIDLIST* dir = - static_cast(ILCreateFromPathW(parentDirectoryPath)); + LPITEMIDLIST dir = ILCreateFromPathW(parentDirectoryPath); if (!dir) { return NS_ERROR_FAILURE; } // Set the item in the directory to select to the file we want to reveal. - ITEMIDLIST* item = - static_cast(ILCreateFromPathW(mResolvedPath.get())); + LPITEMIDLIST item = ILCreateFromPathW(mResolvedPath.get()); if (!item) { CoTaskMemFree(dir); return NS_ERROR_FAILURE; } - const ITEMIDLIST* selection[] = { item }; + LPCITEMIDLIST selection[] = { item }; UINT count = ArrayLength(selection); //Perform the selection of the file. diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/io/nsPipe3.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/io/nsPipe3.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/io/nsPipe3.cpp 2016-11-11 02:16:29.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/io/nsPipe3.cpp 2016-11-14 02:19:51.000000000 +0000 @@ -1200,7 +1200,7 @@ if (mCallback && !(mCallbackFlags & WAIT_CLOSURE_ONLY)) { aEvents.NotifyInputReady(this, mCallback); - mCallback = 0; + mCallback = nullptr; mCallbackFlags = 0; } else if (mBlocked) { result = NotifyMonitor; @@ -1229,7 +1229,7 @@ if (mCallback) { aEvents.NotifyInputReady(this, mCallback); - mCallback = 0; + mCallback = nullptr; mCallbackFlags = 0; } else if (mBlocked) { result = NotifyMonitor; @@ -1370,7 +1370,7 @@ ReentrantMonitorAutoEnter mon(mPipe->mReentrantMonitor); // replace a pending callback - mCallback = 0; + mCallback = nullptr; mCallbackFlags = 0; if (!aCallback) { @@ -1594,7 +1594,7 @@ if (mCallback && !(mCallbackFlags & WAIT_CLOSURE_ONLY)) { aEvents.NotifyOutputReady(this, mCallback); - mCallback = 0; + mCallback = nullptr; mCallbackFlags = 0; } else if (mBlocked) { result = NotifyMonitor; @@ -1616,7 +1616,7 @@ if (mCallback) { aEvents.NotifyOutputReady(this, mCallback); - mCallback = 0; + mCallback = nullptr; mCallbackFlags = 0; } else if (mBlocked) { result = NotifyMonitor; @@ -1802,7 +1802,7 @@ ReentrantMonitorAutoEnter mon(mPipe->mReentrantMonitor); // replace a pending callback - mCallback = 0; + mCallback = nullptr; mCallbackFlags = 0; if (!aCallback) { diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/gtest/moz.build firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/gtest/moz.build --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/gtest/moz.build 2016-11-11 02:16:45.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/gtest/moz.build 2016-11-14 02:20:48.000000000 +0000 @@ -9,6 +9,8 @@ 'TestAtoms.cpp', 'TestAutoPtr.cpp', 'TestAutoRef.cpp', + 'TestBase64.cpp', + 'TestCallTemplates.cpp', 'TestCloneInputStream.cpp', 'TestCOMArray.cpp', 'TestCOMPtrEq.cpp', @@ -24,6 +26,7 @@ 'TestPipes.cpp', 'TestPLDHash.cpp', 'TestPriorityQueue.cpp', + 'TestRacingServiceManager.cpp', 'TestSlicedInputStream.cpp', 'TestSnappyStreams.cpp', 'TestStateWatching.cpp', @@ -35,6 +38,7 @@ 'TestTArray2.cpp', 'TestTextFormatter.cpp', 'TestThreadPool.cpp', + 'TestThreadPoolListener.cpp', 'TestThreads.cpp', 'TestThreadUtils.cpp', 'TestTimers.cpp', @@ -44,6 +48,19 @@ 'TestXPIDLString.cpp', ] +if CONFIG['MOZ_DEBUG'] and CONFIG['OS_ARCH'] not in ('WINNT') and CONFIG['OS_TARGET'] != 'Android': + # FIXME bug 523392: TestDeadlockDetector doesn't like Windows + # Bug 1054249: Doesn't work on Android + UNIFIED_SOURCES += [ + 'TestDeadlockDetector.cpp', + 'TestDeadlockDetectorScalability.cpp', + ] + +if CONFIG['WRAP_STL_INCLUDES'] and not CONFIG['CLANG_CL']: + UNIFIED_SOURCES += [ + 'TestSTLWrappers.cpp', + ] + # Compile TestAllocReplacement separately so Windows headers don't pollute # the global namespace for other files. SOURCES += [ @@ -51,7 +68,6 @@ 'TestCOMPtr.cpp', # Redefines IFoo and IBar 'TestHashtables.cpp', # Redefines IFoo 'TestNsRefPtr.cpp', # Redefines Foo - #'TestTArray2.cpp', ] LOCAL_INCLUDES += [ diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/gtest/TestBase64.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/gtest/TestBase64.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/gtest/TestBase64.cpp 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/gtest/TestBase64.cpp 2016-11-14 02:20:47.000000000 +0000 @@ -0,0 +1,291 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/Attributes.h" +#include "nsIScriptableBase64Encoder.h" +#include "nsIInputStream.h" +#include "nsString.h" + +#include "gtest/gtest.h" + +struct Chunk { + Chunk(uint32_t l, const char* c) + : mLength(l), mData(c) + {} + + uint32_t mLength; + const char* mData; +}; + +struct Test { + Test(Chunk* c, const char* r) + : mChunks(c), mResult(r) + {} + + Chunk* mChunks; + const char* mResult; +}; + +static Chunk kTest1Chunks[] = +{ + Chunk(9, "Hello sir"), + Chunk(0, nullptr) +}; + +static Chunk kTest2Chunks[] = +{ + Chunk(3, "Hel"), + Chunk(3, "lo "), + Chunk(3, "sir"), + Chunk(0, nullptr) +}; + +static Chunk kTest3Chunks[] = +{ + Chunk(1, "I"), + Chunk(0, nullptr) +}; + +static Chunk kTest4Chunks[] = +{ + Chunk(2, "Hi"), + Chunk(0, nullptr) +}; + +static Chunk kTest5Chunks[] = +{ + Chunk(1, "B"), + Chunk(2, "ob"), + Chunk(0, nullptr) +}; + +static Chunk kTest6Chunks[] = +{ + Chunk(2, "Bo"), + Chunk(1, "b"), + Chunk(0, nullptr) +}; + +static Chunk kTest7Chunks[] = +{ + Chunk(1, "F"), // Carry over 1 + Chunk(4, "iref"), // Carry over 2 + Chunk(2, "ox"), // 1 + Chunk(4, " is "), // 2 + Chunk(2, "aw"), // 1 + Chunk(4, "esom"), // 2 + Chunk(2, "e!"), + Chunk(0, nullptr) +}; + +static Chunk kTest8Chunks[] = +{ + Chunk(5, "ALL T"), + Chunk(1, "H"), + Chunk(4, "ESE "), + Chunk(2, "WO"), + Chunk(21, "RLDS ARE YOURS EXCEPT"), + Chunk(9, " EUROPA. "), + Chunk(25, "ATTEMPT NO LANDING THERE."), + Chunk(0, nullptr) +}; + +static Test kTests[] = + { + // Test 1, test a simple round string in one chunk + Test( + kTest1Chunks, + "SGVsbG8gc2ly" + ), + // Test 2, test a simple round string split into round chunks + Test( + kTest2Chunks, + "SGVsbG8gc2ly" + ), + // Test 3, test a single chunk that's 2 short + Test( + kTest3Chunks, + "SQ==" + ), + // Test 4, test a single chunk that's 1 short + Test( + kTest4Chunks, + "SGk=" + ), + // Test 5, test a single chunk that's 2 short, followed by a chunk of 2 + Test( + kTest5Chunks, + "Qm9i" + ), + // Test 6, test a single chunk that's 1 short, followed by a chunk of 1 + Test( + kTest6Chunks, + "Qm9i" + ), + // Test 7, test alternating carryovers + Test( + kTest7Chunks, + "RmlyZWZveCBpcyBhd2Vzb21lIQ==" + ), + // Test 8, test a longish string + Test( + kTest8Chunks, + "QUxMIFRIRVNFIFdPUkxEUyBBUkUgWU9VUlMgRVhDRVBUIEVVUk9QQS4gQVRURU1QVCBOTyBMQU5ESU5HIFRIRVJFLg==" + ), + // Terminator + Test( + nullptr, + nullptr + ) + }; + +class FakeInputStream final : public nsIInputStream +{ + ~FakeInputStream() {} + +public: + + FakeInputStream() + : mTestNumber(0), + mTest(&kTests[0]), + mChunk(&mTest->mChunks[0]), + mClosed(false) + {} + + NS_DECL_ISUPPORTS + NS_DECL_NSIINPUTSTREAM + + void Reset(); + bool NextTest(); + void CheckTest(nsACString& aResult); + void CheckTest(nsAString& aResult); +private: + uint32_t mTestNumber; + const Test* mTest; + const Chunk* mChunk; + bool mClosed; +}; + +NS_IMPL_ISUPPORTS(FakeInputStream, nsIInputStream) + +NS_IMETHODIMP +FakeInputStream::Close() +{ + mClosed = true; + return NS_OK; +} + +NS_IMETHODIMP +FakeInputStream::Available(uint64_t* aAvailable) +{ + *aAvailable = 0; + + if (mClosed) + return NS_BASE_STREAM_CLOSED; + + const Chunk* chunk = mChunk; + while (chunk->mLength) { + *aAvailable += chunk->mLength; + chunk++; + } + + return NS_OK; +} + +NS_IMETHODIMP +FakeInputStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aOut) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +FakeInputStream::ReadSegments(nsWriteSegmentFun aWriter, + void* aClosure, + uint32_t aCount, + uint32_t* aRead) +{ + *aRead = 0; + + if (mClosed) + return NS_BASE_STREAM_CLOSED; + + while (mChunk->mLength) { + uint32_t written = 0; + + nsresult rv = (*aWriter)(this, aClosure, mChunk->mData, + *aRead, mChunk->mLength, &written); + + *aRead += written; + NS_ENSURE_SUCCESS(rv, rv); + + mChunk++; + } + + return NS_OK; +} + +NS_IMETHODIMP +FakeInputStream::IsNonBlocking(bool* aIsBlocking) +{ + *aIsBlocking = false; + return NS_OK; +} + +void +FakeInputStream::Reset() +{ + mClosed = false; + mChunk = &mTest->mChunks[0]; +} + +bool +FakeInputStream::NextTest() +{ + mTestNumber++; + mTest = &kTests[mTestNumber]; + mChunk = &mTest->mChunks[0]; + mClosed = false; + + return mTest->mChunks ? true : false; +} + +void +FakeInputStream::CheckTest(nsACString& aResult) +{ + ASSERT_STREQ(aResult.BeginReading(), mTest->mResult); +} + +void +FakeInputStream::CheckTest(nsAString& aResult) +{ + ASSERT_TRUE(aResult.EqualsASCII(mTest->mResult)) << + "Actual: " << aResult.BeginReading() << std::endl << + "Expected: " << mTest->mResult; +} + +TEST(Base64, Test) +{ + nsCOMPtr encoder = + do_CreateInstance("@mozilla.org/scriptablebase64encoder;1"); + ASSERT_TRUE(encoder); + + RefPtr stream = new FakeInputStream(); + do { + nsString wideString; + nsCString string; + + nsresult rv; + rv = encoder->EncodeToString(stream, 0, wideString); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + stream->Reset(); + + rv = encoder->EncodeToCString(stream, 0, string); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + stream->CheckTest(wideString); + stream->CheckTest(string); + } while (stream->NextTest()); +} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/gtest/TestCallTemplates.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/gtest/TestCallTemplates.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/gtest/TestCallTemplates.cpp 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/gtest/TestCallTemplates.cpp 2016-11-14 02:20:47.000000000 +0000 @@ -0,0 +1,104 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim:cindent:ts=8:et:sw=4: + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * This test is NOT intended to be run. It's a test to make sure + * a group of functions BUILD correctly. + */ + +#include "nsISupportsUtils.h" +#include "nsIWeakReference.h" +#include "nsIComponentManager.h" +#include "nsIServiceManager.h" +#include "nsWeakReference.h" +#include "nsIInterfaceRequestor.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsComponentManagerUtils.h" +#include "nsServiceManagerUtils.h" +#include "nsAutoPtr.h" +#include "mozilla/Attributes.h" + +#define NS_ITESTSERVICE_IID \ + {0x127b5253, 0x37b1, 0x43c7, \ + { 0x96, 0x2b, 0xab, 0xf1, 0x2d, 0x22, 0x56, 0xae }} + +class NS_NO_VTABLE nsITestService : public nsISupports { + public: + NS_DECLARE_STATIC_IID_ACCESSOR(NS_ITESTSERVICE_IID) +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(nsITestService, NS_ITESTSERVICE_IID) + +class nsTestService final : public nsITestService, + public nsSupportsWeakReference +{ + ~nsTestService() {} + public: + NS_DECL_ISUPPORTS +}; + +NS_IMPL_ISUPPORTS(nsTestService, nsITestService, nsISupportsWeakReference) + +#define NS_TEST_SERVICE_CONTRACTID "@mozilla.org/test/testservice;1" +#define NS_TEST_SERVICE_CID \ + {0xa00c1406, 0x283a, 0x45c9, \ + {0xae, 0xd2, 0x1a, 0xb6, 0xdd, 0xba, 0xfe, 0x53}} +static NS_DEFINE_CID(kTestServiceCID, NS_TEST_SERVICE_CID); + +void JustTestingCompilation() +{ + /* + * NOTE: This does NOT demonstrate how these functions are + * intended to be used. They are intended for filling in out + * parameters that need to be |AddRef|ed. I'm just too lazy + * to write lots of little getter functions for a test program + * when I don't need to. + */ + + NS_NOTREACHED("This test is not intended to run, only to compile!"); + + /* Test CallQueryInterface */ + + nsISupports *mySupportsPtr = reinterpret_cast(0x1000); + + nsITestService *myITestService = nullptr; + CallQueryInterface(mySupportsPtr, &myITestService); + + nsTestService *myTestService = + reinterpret_cast(mySupportsPtr); + nsISupportsWeakReference *mySupportsWeakRef; + CallQueryInterface(myTestService, &mySupportsWeakRef); + + nsCOMPtr mySupportsCOMPtr = mySupportsPtr; + CallQueryInterface(mySupportsCOMPtr, &myITestService); + + RefPtr myTestServiceRefPtr = myTestService; + CallQueryInterface(myTestServiceRefPtr, &mySupportsWeakRef); + + /* Test CallQueryReferent */ + + nsIWeakReference *myWeakRef = + static_cast(mySupportsPtr); + CallQueryReferent(myWeakRef, &myITestService); + + /* Test CallCreateInstance */ + + CallCreateInstance(kTestServiceCID, mySupportsPtr, &myITestService); + CallCreateInstance(kTestServiceCID, &myITestService); + CallCreateInstance(NS_TEST_SERVICE_CONTRACTID, mySupportsPtr, + &myITestService); + CallCreateInstance(NS_TEST_SERVICE_CONTRACTID, &myITestService); + + /* Test CallGetService */ + CallGetService(kTestServiceCID, &myITestService); + CallGetService(NS_TEST_SERVICE_CONTRACTID, &myITestService); + + /* Test CallGetInterface */ + nsIInterfaceRequestor *myInterfaceRequestor = + static_cast(mySupportsPtr); + CallGetInterface(myInterfaceRequestor, &myITestService); +} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/gtest/TestDeadlockDetector.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/gtest/TestDeadlockDetector.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/gtest/TestDeadlockDetector.cpp 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/gtest/TestDeadlockDetector.cpp 2016-11-14 02:20:47.000000000 +0000 @@ -0,0 +1,322 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: sw=4 ts=4 et : + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/ArrayUtils.h" + +#include "prthread.h" + +#include "nsTArray.h" +#include "nsMemory.h" + +#include "mozilla/CondVar.h" +#include "mozilla/ReentrantMonitor.h" +#include "mozilla/Mutex.h" + +#ifdef MOZ_CRASHREPORTER +#include "nsCOMPtr.h" +#include "nsICrashReporter.h" +#include "nsServiceManagerUtils.h" +#endif + +#include "gtest/gtest.h" + +using namespace mozilla; + +static PRThread* +spawn(void (*run)(void*), void* arg) +{ + return PR_CreateThread(PR_SYSTEM_THREAD, + run, + arg, + PR_PRIORITY_NORMAL, + PR_GLOBAL_THREAD, + PR_JOINABLE_THREAD, + 0); +} + +// This global variable is defined in toolkit/xre/nsSigHandlers.cpp. +extern unsigned int _gdb_sleep_duration; + +/** + * Simple test fixture that makes sure the gdb sleep setup in the + * ah crap handler is bypassed during the death tests. + */ +class DeadlockDetectorTest : public ::testing::Test +{ +protected: + void SetUp() final { + mOldSleepDuration = _gdb_sleep_duration; + _gdb_sleep_duration = 0; + } + + void TearDown() final { + _gdb_sleep_duration = mOldSleepDuration; + } + +private: + unsigned int mOldSleepDuration; +}; + +void DisableCrashReporter() +{ +#ifdef MOZ_CRASHREPORTER + nsCOMPtr crashreporter = + do_GetService("@mozilla.org/toolkit/crash-reporter;1"); + if (crashreporter) { + crashreporter->SetEnabled(false); + } +#endif +} + +//----------------------------------------------------------------------------- +// Single-threaded sanity tests + +// Stupidest possible deadlock. +int +Sanity_Child() +{ + DisableCrashReporter(); + + mozilla::Mutex m1("dd.sanity.m1"); + m1.Lock(); + m1.Lock(); + return 0; // not reached +} + +TEST_F(DeadlockDetectorTest, SanityDeathTest) +{ + const char* const regex = + "###!!! ERROR: Potential deadlock detected.*" + "=== Cyclical dependency starts at.*--- Mutex : dd.sanity.m1.*" + "=== Cycle completed at.*--- Mutex : dd.sanity.m1.*" + "###!!! Deadlock may happen NOW!.*" // better catch these easy cases... + "###!!! ASSERTION: Potential deadlock detected.*"; + + ASSERT_DEATH(Sanity_Child(), regex); +} + +// Slightly less stupid deadlock. +int +Sanity2_Child() +{ + DisableCrashReporter(); + + mozilla::Mutex m1("dd.sanity2.m1"); + mozilla::Mutex m2("dd.sanity2.m2"); + m1.Lock(); + m2.Lock(); + m1.Lock(); + return 0; // not reached +} + +TEST_F(DeadlockDetectorTest, Sanity2DeathTest) +{ + const char* const regex = + "###!!! ERROR: Potential deadlock detected.*" + "=== Cyclical dependency starts at.*--- Mutex : dd.sanity2.m1.*" + "--- Next dependency:.*--- Mutex : dd.sanity2.m2.*" + "=== Cycle completed at.*--- Mutex : dd.sanity2.m1.*" + "###!!! Deadlock may happen NOW!.*" // better catch these easy cases... + "###!!! ASSERTION: Potential deadlock detected.*"; + + ASSERT_DEATH(Sanity2_Child(), regex); +} + +int +Sanity3_Child() +{ + DisableCrashReporter(); + + mozilla::Mutex m1("dd.sanity3.m1"); + mozilla::Mutex m2("dd.sanity3.m2"); + mozilla::Mutex m3("dd.sanity3.m3"); + mozilla::Mutex m4("dd.sanity3.m4"); + + m1.Lock(); + m2.Lock(); + m3.Lock(); + m4.Lock(); + m4.Unlock(); + m3.Unlock(); + m2.Unlock(); + m1.Unlock(); + + m4.Lock(); + m1.Lock(); + return 0; +} + +TEST_F(DeadlockDetectorTest, Sanity3DeathTest) +{ + const char* const regex = + "###!!! ERROR: Potential deadlock detected.*" + "=== Cyclical dependency starts at.*--- Mutex : dd.sanity3.m1.*" + "--- Next dependency:.*--- Mutex : dd.sanity3.m2.*" + "--- Next dependency:.*--- Mutex : dd.sanity3.m3.*" + "--- Next dependency:.*--- Mutex : dd.sanity3.m4.*" + "=== Cycle completed at.*--- Mutex : dd.sanity3.m1.*" + "###!!! ASSERTION: Potential deadlock detected.*"; + + ASSERT_DEATH(Sanity3_Child(), regex); +} + +int +Sanity4_Child() +{ + DisableCrashReporter(); + + mozilla::ReentrantMonitor m1("dd.sanity4.m1"); + mozilla::Mutex m2("dd.sanity4.m2"); + m1.Enter(); + m2.Lock(); + m1.Enter(); + return 0; +} + +TEST_F(DeadlockDetectorTest, Sanity4DeathTest) +{ + const char* const regex = + "Re-entering ReentrantMonitor after acquiring other resources.*" + "###!!! ERROR: Potential deadlock detected.*" + "=== Cyclical dependency starts at.*--- ReentrantMonitor : dd.sanity4.m1.*" + "--- Next dependency:.*--- Mutex : dd.sanity4.m2.*" + "=== Cycle completed at.*--- ReentrantMonitor : dd.sanity4.m1.*" + "###!!! ASSERTION: Potential deadlock detected.*"; + ASSERT_DEATH(Sanity4_Child(), regex); +} + +//----------------------------------------------------------------------------- +// Multithreaded tests + +/** + * Helper for passing state to threads in the multithread tests. + */ +struct ThreadState +{ + /** + * Locks to use during the test. This is just a reference and is owned by + * the main test thread. + */ + const nsTArray& locks; + + /** + * Integer argument used to identify each thread. + */ + int id; +}; + +static void +TwoThreads_thread(void* arg) +{ + ThreadState* state = static_cast(arg); + + mozilla::Mutex* ttM1 = state->locks[0]; + mozilla::Mutex* ttM2 = state->locks[1]; + + if (state->id) { + ttM1->Lock(); + ttM2->Lock(); + ttM2->Unlock(); + ttM1->Unlock(); + } + else { + ttM2->Lock(); + ttM1->Lock(); + ttM1->Unlock(); + ttM2->Unlock(); + } +} + +int +TwoThreads_Child() +{ + DisableCrashReporter(); + + nsTArray locks = { + new mozilla::Mutex("dd.twothreads.m1"), + new mozilla::Mutex("dd.twothreads.m2") + }; + + ThreadState state_1 {locks, 0}; + PRThread* t1 = spawn(TwoThreads_thread, &state_1); + PR_JoinThread(t1); + + ThreadState state_2 {locks, 1}; + PRThread* t2 = spawn(TwoThreads_thread, &state_2); + PR_JoinThread(t2); + + for (auto& lock : locks) { + delete lock; + } + + return 0; +} + +TEST_F(DeadlockDetectorTest, TwoThreadsDeathTest) +{ + const char* const regex = + "###!!! ERROR: Potential deadlock detected.*" + "=== Cyclical dependency starts at.*--- Mutex : dd.twothreads.m2.*" + "--- Next dependency:.*--- Mutex : dd.twothreads.m1.*" + "=== Cycle completed at.*--- Mutex : dd.twothreads.m2.*" + "###!!! ASSERTION: Potential deadlock detected.*"; + + ASSERT_DEATH(TwoThreads_Child(), regex); +} + +static void +ContentionNoDeadlock_thread(void* arg) +{ + const uint32_t K = 100000; + + ThreadState* state = static_cast(arg); + int32_t starti = static_cast(state->id); + auto& cndMs = state->locks; + + for (uint32_t k = 0; k < K; ++k) { + for (int32_t i = starti; i < (int32_t)cndMs.Length(); ++i) + cndMs[i]->Lock(); + // comment out the next two lines for deadlocking fun! + for (int32_t i = cndMs.Length() - 1; i >= starti; --i) + cndMs[i]->Unlock(); + + starti = (starti + 1) % 3; + } +} + +int +ContentionNoDeadlock_Child() +{ + const size_t kMutexCount = 4; + + PRThread* threads[3]; + nsTArray locks; + ThreadState states[] = { + { locks, 0 }, + { locks, 1 }, + { locks, 2 } + }; + + for (uint32_t i = 0; i < kMutexCount; ++i) + locks.AppendElement(new mozilla::Mutex("dd.cnd.ms")); + + for (int32_t i = 0; i < (int32_t) ArrayLength(threads); ++i) + threads[i] = spawn(ContentionNoDeadlock_thread, states + i); + + for (uint32_t i = 0; i < ArrayLength(threads); ++i) + PR_JoinThread(threads[i]); + + for (uint32_t i = 0; i < locks.Length(); ++i) + delete locks[i]; + + return 0; +} + +TEST_F(DeadlockDetectorTest, ContentionNoDeadlock) +{ + // Just check that this test runs to completion. + ASSERT_EQ(ContentionNoDeadlock_Child(), 0); +} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/gtest/TestDeadlockDetectorScalability.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/gtest/TestDeadlockDetectorScalability.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/gtest/TestDeadlockDetectorScalability.cpp 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/gtest/TestDeadlockDetectorScalability.cpp 2016-11-14 02:20:47.000000000 +0000 @@ -0,0 +1,170 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: sw=4 ts=4 et : + * 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/. */ + +// Avoid DMD-specific parts of MOZ_DEFINE_MALLOC_SIZE_OF +#undef MOZ_DMD + +#include "nsIMemoryReporter.h" +#include "mozilla/Mutex.h" + +#include "gtest/gtest.h" + +//----------------------------------------------------------------------------- + +static void +AllocLockRecurseUnlockFree(int i) +{ + if (0 == i) + return; + + mozilla::Mutex* lock = new mozilla::Mutex("deadlockDetector.scalability.t1"); + { + mozilla::MutexAutoLock _(*lock); + AllocLockRecurseUnlockFree(i - 1); + } + delete lock; +} + +// This test creates a resource dependency chain N elements long, then +// frees all the resources in the chain. +TEST(DeadlockDetectorScalability, LengthNDepChain) +{ + const int N = 1 << 14; // 16K + AllocLockRecurseUnlockFree(N); + ASSERT_TRUE(true); +} + +//----------------------------------------------------------------------------- + +// This test creates a single lock that is ordered < N resources, then +// repeatedly exercises this order k times. +// +// NB: It takes a minute or two to run so it is disabled by default. +TEST(DeadlockDetectorScalability, DISABLED_OneLockNDeps) +{ + // NB: Using a larger test size to stress our traversal logic. + const int N = 1 << 17; // 131k + const int K = 100; + + mozilla::Mutex* lock = new mozilla::Mutex("deadlockDetector.scalability.t2.master"); + mozilla::Mutex** locks = new mozilla::Mutex*[N]; + if (!locks) + NS_RUNTIMEABORT("couldn't allocate lock array"); + + for (int i = 0; i < N; ++i) + locks[i] = + new mozilla::Mutex("deadlockDetector.scalability.t2.dep"); + + // establish orders + {mozilla::MutexAutoLock m(*lock); + for (int i = 0; i < N; ++i) + mozilla::MutexAutoLock s(*locks[i]); + } + + // exercise order check + {mozilla::MutexAutoLock m(*lock); + for (int i = 0; i < K; ++i) + for (int j = 0; j < N; ++j) + mozilla::MutexAutoLock s(*locks[i]); + } + + for (int i = 0; i < N; ++i) + delete locks[i]; + delete[] locks; + + ASSERT_TRUE(true); +} + +//----------------------------------------------------------------------------- + +// This test creates N resources and adds the theoretical maximum number +// of dependencies, O(N^2). It then repeats that sequence of +// acquisitions k times. Finally, all resources are freed. +// +// It's very difficult to perform well on this test. It's put forth as a +// challenge problem. + +TEST(DeadlockDetectorScalability, MaxDepsNsq) +{ + const int N = 1 << 10; // 1k + const int K = 10; + + mozilla::Mutex** locks = new mozilla::Mutex*[N]; + if (!locks) + NS_RUNTIMEABORT("couldn't allocate lock array"); + + for (int i = 0; i < N; ++i) + locks[i] = new mozilla::Mutex("deadlockDetector.scalability.t3"); + + for (int i = 0; i < N; ++i) { + mozilla::MutexAutoLock al1(*locks[i]); + for (int j = i+1; j < N; ++j) + mozilla::MutexAutoLock al2(*locks[j]); + } + + for (int i = 0; i < K; ++i) { + for (int j = 0; j < N; ++j) { + mozilla::MutexAutoLock al1(*locks[j]); + for (int k = j+1; k < N; ++k) + mozilla::MutexAutoLock al2(*locks[k]); + } + } + + for (int i = 0; i < N; ++i) + delete locks[i]; + delete[] locks; + + ASSERT_TRUE(true); +} + +//----------------------------------------------------------------------------- + +// This test creates a single lock that is ordered < N resources. The +// resources are allocated, exercised K times, and deallocated one at +// a time. + +TEST(DeadlockDetectorScalability, OneLockNDepsUsedSeveralTimes) +{ + const size_t N = 1 << 17; // 131k + const size_t K = 3; + + // Create master lock. + mozilla::Mutex* lock_1 = new mozilla::Mutex("deadlockDetector.scalability.t4.master"); + for (size_t n = 0; n < N; n++) { + // Create child lock. + mozilla::Mutex* lock_2 = new mozilla::Mutex("deadlockDetector.scalability.t4.child"); + + // First lock the master. + mozilla::MutexAutoLock m(*lock_1); + + // Now lock and unlock the child a few times. + for (size_t k = 0; k < K; k++) { + mozilla::MutexAutoLock c(*lock_2); + } + + // Destroy the child lock. + delete lock_2; + } + + // Cleanup the master lock. + delete lock_1; + + ASSERT_TRUE(true); +} + +//----------------------------------------------------------------------------- + +MOZ_DEFINE_MALLOC_SIZE_OF(DeadlockDetectorMallocSizeOf) + +// This is a simple test that exercises the deadlock detector memory reporting +// functionality. +TEST(DeadlockDetectorScalability, SizeOf) +{ + size_t memory_used = mozilla::BlockingResourceBase::SizeOfDeadlockDetector( + DeadlockDetectorMallocSizeOf); + + ASSERT_GT(memory_used, size_t(0)); +} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/gtest/TestEscapeURL.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/gtest/TestEscapeURL.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/gtest/TestEscapeURL.cpp 2016-11-11 02:16:44.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/gtest/TestEscapeURL.cpp 2016-11-14 02:20:47.000000000 +0000 @@ -38,3 +38,32 @@ const char* const kExpected = "data:,Hello%2C%20World!%C4%9F"; EXPECT_STREQ(escaped.BeginReading(), kExpected); } + +TEST(EscapeURL, BadEscapeSequences) +{ + { + char bad[] = "%s\0fa"; + + int32_t count = nsUnescapeCount(bad); + EXPECT_EQ(count, 2); + EXPECT_STREQ(bad, "%s"); + } + { + char bad[] = "%a"; + int32_t count = nsUnescapeCount(bad); + EXPECT_EQ(count, 2); + EXPECT_STREQ(bad, "%a"); + } + { + char bad[] = "%"; + int32_t count = nsUnescapeCount(bad); + EXPECT_EQ(count, 1); + EXPECT_STREQ(bad, "%"); + } + { + char bad[] = "%s/%s"; + int32_t count = nsUnescapeCount(bad); + EXPECT_EQ(count, 5); + EXPECT_STREQ(bad, "%s/%s"); + } +} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/gtest/TestNSPRLogModulesParser.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/gtest/TestNSPRLogModulesParser.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/gtest/TestNSPRLogModulesParser.cpp 2016-11-11 02:16:44.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/gtest/TestNSPRLogModulesParser.cpp 2016-11-14 02:20:47.000000000 +0000 @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "NSPRLogModulesParser.h" +#include "mozilla/ArrayUtils.h" #include "gtest/gtest.h" using namespace mozilla; diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/gtest/TestObserverService.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/gtest/TestObserverService.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/gtest/TestObserverService.cpp 2016-11-11 02:16:45.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/gtest/TestObserverService.cpp 2016-11-14 02:20:47.000000000 +0000 @@ -11,6 +11,7 @@ #include "nsComponentManagerUtils.h" #include "nsCOMPtr.h" +#include "nsString.h" #include "nsWeakReference.h" #include "mozilla/RefPtr.h" diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/gtest/TestRacingServiceManager.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/gtest/TestRacingServiceManager.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/gtest/TestRacingServiceManager.cpp 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/gtest/TestRacingServiceManager.cpp 2016-11-14 02:20:47.000000000 +0000 @@ -0,0 +1,300 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsIFactory.h" +#include "mozilla/Module.h" +#include "nsXULAppAPI.h" +#include "nsIThread.h" +#include "nsIComponentRegistrar.h" + +#include "nsAutoPtr.h" +#include "nsThreadUtils.h" +#include "nsXPCOMCIDInternal.h" +#include "pratom.h" +#include "prmon.h" +#include "mozilla/Assertions.h" +#include "mozilla/Attributes.h" + +#include "mozilla/ReentrantMonitor.h" + +#include "gtest/gtest.h" + +using namespace mozilla; + +/* f93f6bdc-88af-42d7-9d64-1b43c649a3e5 */ +#define FACTORY_CID1 \ +{ \ + 0xf93f6bdc, \ + 0x88af, \ + 0x42d7, \ + { 0x9d, 0x64, 0x1b, 0x43, 0xc6, 0x49, 0xa3, 0xe5 } \ +} +NS_DEFINE_CID(kFactoryCID1, FACTORY_CID1); + +/* ef38ad65-6595-49f0-8048-e819f81d15e2 */ +#define FACTORY_CID2 \ +{ \ + 0xef38ad65, \ + 0x6595, \ + 0x49f0, \ + { 0x80, 0x48, 0xe8, 0x19, 0xf8, 0x1d, 0x15, 0xe2 } \ +} +NS_DEFINE_CID(kFactoryCID2, FACTORY_CID2); + +#define FACTORY_CONTRACTID \ + "TestRacingThreadManager/factory;1" + +namespace TestRacingServiceManager +{ +int32_t gComponent1Count = 0; +int32_t gComponent2Count = 0; + +ReentrantMonitor* gReentrantMonitor = nullptr; + +bool gCreateInstanceCalled = false; +bool gMainThreadWaiting = false; + +class AutoCreateAndDestroyReentrantMonitor +{ +public: + explicit AutoCreateAndDestroyReentrantMonitor(ReentrantMonitor** aReentrantMonitorPtr) + : mReentrantMonitorPtr(aReentrantMonitorPtr) { + *aReentrantMonitorPtr = + new ReentrantMonitor("TestRacingServiceManager::AutoMon"); + MOZ_RELEASE_ASSERT(*aReentrantMonitorPtr, "Out of memory!"); + } + + ~AutoCreateAndDestroyReentrantMonitor() { + if (*mReentrantMonitorPtr) { + delete *mReentrantMonitorPtr; + *mReentrantMonitorPtr = nullptr; + } + } + +private: + ReentrantMonitor** mReentrantMonitorPtr; +}; + +class Factory final : public nsIFactory +{ + ~Factory() {} + +public: + NS_DECL_THREADSAFE_ISUPPORTS + + Factory() : mFirstComponentCreated(false) { } + + NS_IMETHOD CreateInstance(nsISupports* aDelegate, + const nsIID& aIID, + void** aResult) override; + + NS_IMETHOD LockFactory(bool aLock) override { + return NS_OK; + } + + bool mFirstComponentCreated; +}; + +NS_IMPL_ISUPPORTS(Factory, nsIFactory) + +class Component1 final : public nsISupports +{ + ~Component1() {} + +public: + NS_DECL_THREADSAFE_ISUPPORTS + + Component1() { + // This is the real test - make sure that only one instance is ever created. + int32_t count = PR_AtomicIncrement(&gComponent1Count); + MOZ_RELEASE_ASSERT(count == 1, "Too many components created!"); + } +}; + +NS_IMPL_ADDREF(Component1) +NS_IMPL_RELEASE(Component1) + +NS_INTERFACE_MAP_BEGIN(Component1) + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +class Component2 final : public nsISupports +{ + ~Component2() {} + +public: + NS_DECL_THREADSAFE_ISUPPORTS + + Component2() { + // This is the real test - make sure that only one instance is ever created. + int32_t count = PR_AtomicIncrement(&gComponent2Count); + EXPECT_EQ(count, int32_t(1)) << "Too many components created!"; + } +}; + +NS_IMPL_ADDREF(Component2) +NS_IMPL_RELEASE(Component2) + +NS_INTERFACE_MAP_BEGIN(Component2) + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +NS_IMETHODIMP +Factory::CreateInstance(nsISupports* aDelegate, + const nsIID& aIID, + void** aResult) +{ + // Make sure that the second thread beat the main thread to the getService + // call. + MOZ_RELEASE_ASSERT(!NS_IsMainThread(), "Wrong thread!"); + + { + ReentrantMonitorAutoEnter mon(*gReentrantMonitor); + + gCreateInstanceCalled = true; + mon.Notify(); + + mon.Wait(PR_MillisecondsToInterval(3000)); + } + + NS_ENSURE_FALSE(aDelegate, NS_ERROR_NO_AGGREGATION); + NS_ENSURE_ARG_POINTER(aResult); + + nsCOMPtr instance; + + if (!mFirstComponentCreated) { + instance = new Component1(); + } + else { + instance = new Component2(); + } + NS_ENSURE_TRUE(instance, NS_ERROR_OUT_OF_MEMORY); + + nsresult rv = instance->QueryInterface(aIID, aResult); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +class TestRunnable : public Runnable +{ +public: + NS_DECL_NSIRUNNABLE + + TestRunnable() : mFirstRunnableDone(false) { } + + bool mFirstRunnableDone; +}; + +NS_IMETHODIMP +TestRunnable::Run() +{ + { + ReentrantMonitorAutoEnter mon(*gReentrantMonitor); + + while (!gMainThreadWaiting) { + mon.Wait(); + } + } + + nsresult rv; + nsCOMPtr component; + + if (!mFirstRunnableDone) { + component = do_GetService(kFactoryCID1, &rv); + } + else { + component = do_GetService(FACTORY_CONTRACTID, &rv); + } + EXPECT_TRUE(NS_SUCCEEDED(rv)) << "GetService failed!"; + + return NS_OK; +} + +static Factory* gFactory; + +static already_AddRefed +CreateFactory(const mozilla::Module& module, const mozilla::Module::CIDEntry& entry) +{ + if (!gFactory) { + gFactory = new Factory(); + NS_ADDREF(gFactory); + } + nsCOMPtr ret = gFactory; + return ret.forget(); +} + +static const mozilla::Module::CIDEntry kLocalCIDs[] = { + { &kFactoryCID1, false, CreateFactory, nullptr }, + { &kFactoryCID2, false, CreateFactory, nullptr }, + { nullptr } +}; + +static const mozilla::Module::ContractIDEntry kLocalContracts[] = { + { FACTORY_CONTRACTID, &kFactoryCID2 }, + { nullptr } +}; + +static const mozilla::Module kLocalModule = { + mozilla::Module::kVersion, + kLocalCIDs, + kLocalContracts +}; + +TEST(RacingServiceManager, Test) +{ + nsresult rv; + XRE_AddStaticComponent(&kLocalModule); + + AutoCreateAndDestroyReentrantMonitor mon1(&gReentrantMonitor); + + RefPtr runnable = new TestRunnable(); + ASSERT_TRUE(runnable); + + // Run the classID test + nsCOMPtr newThread; + rv = NS_NewThread(getter_AddRefs(newThread), runnable); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + { + ReentrantMonitorAutoEnter mon2(*gReentrantMonitor); + + gMainThreadWaiting = true; + mon2.Notify(); + + while (!gCreateInstanceCalled) { + mon2.Wait(); + } + } + + nsCOMPtr component(do_GetService(kFactoryCID1, &rv)); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + // Reset for the contractID test + gMainThreadWaiting = gCreateInstanceCalled = false; + gFactory->mFirstComponentCreated = runnable->mFirstRunnableDone = true; + component = nullptr; + + rv = newThread->Dispatch(runnable, NS_DISPATCH_NORMAL); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + { + ReentrantMonitorAutoEnter mon3(*gReentrantMonitor); + + gMainThreadWaiting = true; + mon3.Notify(); + + while (!gCreateInstanceCalled) { + mon3.Wait(); + } + } + + component = do_GetService(FACTORY_CONTRACTID, &rv); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + NS_RELEASE(gFactory); +} + +} // namespace TestRacingServiceManager diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/gtest/TestSTLWrappers.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/gtest/TestSTLWrappers.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/gtest/TestSTLWrappers.cpp 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/gtest/TestSTLWrappers.cpp 2016-11-14 02:20:47.000000000 +0000 @@ -0,0 +1,78 @@ +#include + +#include +#ifndef mozilla_algorithm_h +# error "failed to wrap " +#endif + +#include +#ifndef mozilla_vector_h +# error "failed to wrap " +#endif + +#ifdef MOZ_CRASHREPORTER +#include "nsCOMPtr.h" +#include "nsICrashReporter.h" +#include "nsServiceManagerUtils.h" +#endif + +// gcc errors out if we |try ... catch| with -fno-exceptions, but we +// can still test on windows +#ifdef _MSC_VER + // C4530 will be generated whenever try...catch is used without + // enabling exceptions. We know we don't enbale exceptions. +# pragma warning( disable : 4530 ) +# define TRY try +# define CATCH(e) catch (e) +#else +# define TRY +# define CATCH(e) if (0) +#endif + + +#if defined(XP_UNIX) +extern unsigned int _gdb_sleep_duration; +#endif + +void ShouldAbort() +{ +#if defined(XP_UNIX) + _gdb_sleep_duration = 0; +#endif + +#ifdef MOZ_CRASHREPORTER + nsCOMPtr crashreporter = + do_GetService("@mozilla.org/toolkit/crash-reporter;1"); + if (crashreporter) { + crashreporter->SetEnabled(false); + } +#endif + + std::vector v; + int rv = 1; + + TRY { + // v.at(1) on empty v should abort; NOT throw an exception + + // (Do some arithmetic with result of v.at() to avoid + // compiler warnings for unused variable/result.) + rv += v.at(1) ? 1 : 2; + } CATCH(const std::out_of_range&) { + fputs("TEST-FAIL | TestSTLWrappers.cpp | caught an exception?\n", + stderr); + return; + } + + fputs("TEST-FAIL | TestSTLWrappers.cpp | didn't abort()?\n", + stderr); + return; +} + +#ifdef XP_WIN +TEST(STLWrapper, DISABLED_ShouldAbortDeathTest) +#else +TEST(STLWrapper, ShouldAbortDeathTest) +#endif +{ + ASSERT_DEATH(ShouldAbort(), "terminate called after throwing an instance of 'std::out_of_range'|vector::_M_range_check"); +} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/gtest/TestThreadPoolListener.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/gtest/TestThreadPoolListener.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/gtest/TestThreadPoolListener.cpp 1970-01-01 00:00:00.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/gtest/TestThreadPoolListener.cpp 2016-11-14 02:20:48.000000000 +0000 @@ -0,0 +1,209 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsIThread.h" +#include "nsIThreadPool.h" + +#include "nsComponentManagerUtils.h" +#include "nsThreadUtils.h" +#include "nsXPCOMCIDInternal.h" +#include "pratom.h" +#include "prinrval.h" +#include "prmon.h" +#include "prthread.h" +#include "mozilla/Assertions.h" +#include "mozilla/Attributes.h" + +#include "mozilla/ReentrantMonitor.h" + +#include "gtest/gtest.h" + +using namespace mozilla; + +#define NUMBER_OF_THREADS 4 + +// One hour... because test boxes can be slow! +#define IDLE_THREAD_TIMEOUT 3600000 + +namespace TestThreadPoolListener +{ +static nsIThread** gCreatedThreadList = nullptr; +static nsIThread** gShutDownThreadList = nullptr; + +static ReentrantMonitor* gReentrantMonitor = nullptr; + +static bool gAllRunnablesPosted = false; +static bool gAllThreadsCreated = false; +static bool gAllThreadsShutDown = false; + +class Listener final : public nsIThreadPoolListener +{ + ~Listener() {} + +public: + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSITHREADPOOLLISTENER +}; + +NS_IMPL_ISUPPORTS(Listener, nsIThreadPoolListener) + +NS_IMETHODIMP +Listener::OnThreadCreated() +{ + nsCOMPtr current(do_GetCurrentThread()); + EXPECT_TRUE(current) << "Couldn't get current thread!"; + + ReentrantMonitorAutoEnter mon(*gReentrantMonitor); + + while (!gAllRunnablesPosted) { + mon.Wait(); + } + + for (uint32_t i = 0; i < NUMBER_OF_THREADS; i++) { + nsIThread* thread = gCreatedThreadList[i]; + EXPECT_NE(thread, current) << "Saw the same thread twice!"; + + if (!thread) { + gCreatedThreadList[i] = current; + if (i == (NUMBER_OF_THREADS - 1)) { + gAllThreadsCreated = true; + mon.NotifyAll(); + } + return NS_OK; + } + } + + EXPECT_TRUE(false) << "Too many threads!"; + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +Listener::OnThreadShuttingDown() +{ + nsCOMPtr current(do_GetCurrentThread()); + EXPECT_TRUE(current) << "Couldn't get current thread!"; + + ReentrantMonitorAutoEnter mon(*gReentrantMonitor); + + for (uint32_t i = 0; i < NUMBER_OF_THREADS; i++) { + nsIThread* thread = gShutDownThreadList[i]; + EXPECT_NE(thread, current) << "Saw the same thread twice!"; + + if (!thread) { + gShutDownThreadList[i] = current; + if (i == (NUMBER_OF_THREADS - 1)) { + gAllThreadsShutDown = true; + mon.NotifyAll(); + } + return NS_OK; + } + } + + EXPECT_TRUE(false) << "Too many threads!"; + return NS_ERROR_FAILURE; +} + +class AutoCreateAndDestroyReentrantMonitor +{ +public: + explicit AutoCreateAndDestroyReentrantMonitor(ReentrantMonitor** aReentrantMonitorPtr) + : mReentrantMonitorPtr(aReentrantMonitorPtr) { + *aReentrantMonitorPtr = new ReentrantMonitor("TestThreadPoolListener::AutoMon"); + MOZ_RELEASE_ASSERT(*aReentrantMonitorPtr, "Out of memory!"); + } + + ~AutoCreateAndDestroyReentrantMonitor() { + delete *mReentrantMonitorPtr; + *mReentrantMonitorPtr = nullptr; + } + +private: + ReentrantMonitor** mReentrantMonitorPtr; +}; + +TEST(ThreadPoolListener, Test) +{ + nsIThread* createdThreadList[NUMBER_OF_THREADS] = { nullptr }; + gCreatedThreadList = createdThreadList; + + nsIThread* shutDownThreadList[NUMBER_OF_THREADS] = { nullptr }; + gShutDownThreadList = shutDownThreadList; + + AutoCreateAndDestroyReentrantMonitor newMon(&gReentrantMonitor); + ASSERT_TRUE(gReentrantMonitor); + + nsresult rv; + + nsCOMPtr pool = + do_CreateInstance(NS_THREADPOOL_CONTRACTID, &rv); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + rv = pool->SetThreadLimit(NUMBER_OF_THREADS); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + rv = pool->SetIdleThreadLimit(NUMBER_OF_THREADS); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + rv = pool->SetIdleThreadTimeout(IDLE_THREAD_TIMEOUT); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + nsCOMPtr listener = new Listener(); + ASSERT_TRUE(listener); + + rv = pool->SetListener(listener); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + { + ReentrantMonitorAutoEnter mon(*gReentrantMonitor); + + for (uint32_t i = 0; i < NUMBER_OF_THREADS; i++) { + nsCOMPtr runnable = new Runnable(); + ASSERT_TRUE(runnable); + + rv = pool->Dispatch(runnable, NS_DISPATCH_NORMAL); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + } + + gAllRunnablesPosted = true; + mon.NotifyAll(); + } + + { + ReentrantMonitorAutoEnter mon(*gReentrantMonitor); + while (!gAllThreadsCreated) { + mon.Wait(); + } + } + + rv = pool->Shutdown(); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + { + ReentrantMonitorAutoEnter mon(*gReentrantMonitor); + while (!gAllThreadsShutDown) { + mon.Wait(); + } + } + + for (uint32_t i = 0; i < NUMBER_OF_THREADS; i++) { + nsIThread* created = gCreatedThreadList[i]; + ASSERT_TRUE(created); + + bool match = false; + for (uint32_t j = 0; j < NUMBER_OF_THREADS; j++) { + nsIThread* destroyed = gShutDownThreadList[j]; + ASSERT_TRUE(destroyed); + + if (destroyed == created) { + match = true; + break; + } + } + + ASSERT_TRUE(match); + } +} + +} // namespace TestThreadPoolListener diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/Makefile.in firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/Makefile.in --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/Makefile.in 2016-11-11 02:16:42.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/Makefile.in 2016-11-14 02:20:36.000000000 +0000 @@ -11,17 +11,3 @@ libs:: $(INSTALL) $(SIMPLE_PROGRAMS) $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit endif - -ifeq (,$(filter-out WINNT, $(HOST_OS_ARCH))) -getnativepath = $(call normalizepath,$(1)) -else -getnativepath = $(1) -endif - -abs_srcdir = $(abspath $(srcdir)) - -regOrderDir = $(call getnativepath,$(abs_srcdir)/regorder) - -check:: - XPCOM_DEBUG_BREAK=stack-and-abort $(RUN_TEST_PROGRAM) \ - $(DIST)/bin/TestRegistrationOrder$(BIN_SUFFIX) '$(regOrderDir)' diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/moz.build firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/moz.build --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/moz.build 2016-11-11 02:16:45.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/moz.build 2016-11-14 02:20:48.000000000 +0000 @@ -24,27 +24,9 @@ 'TestBlockingProcess', 'TestPRIntN', 'TestQuickReturn', -]) - -GeckoSimplePrograms([ - 'TestCallTemplates', - 'TestINIParser', - 'TestRacingServiceManager', - 'TestRegistrationOrder', - 'TestThreadPoolListener', 'TestUnicodeArguments', ]) -if CONFIG['OS_TARGET'] == 'WINNT': - GeckoSimplePrograms([ - 'TestBase64', - ]) - -if CONFIG['WRAP_STL_INCLUDES'] and not CONFIG['CLANG_CL']: - GeckoSimplePrograms([ - 'TestSTLWrappers', - ]) - XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini'] # FIXME: bug 577500 TestStaticAtoms fails when run in dist/bin @@ -52,14 +34,6 @@ # 'TestStaticAtoms', #] -if CONFIG['MOZ_DEBUG'] and CONFIG['OS_ARCH'] not in ('WINNT'): - # FIXME bug 523392: TestDeadlockDetector doesn't like Windows - # FIXME bug 523378: also fails on OS X - GeckoCppUnitTests([ - 'TestDeadlockDetector', - 'TestDeadlockDetectorScalability', - ]) - if CONFIG['COMPILE_ENVIRONMENT']: TEST_HARNESS_FILES.xpcshell.xpcom.tests.unit += [ '!/dist/bin/components/xpcomtest.xpt', diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/regorder/core/component2.js firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/regorder/core/component2.js --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/regorder/core/component2.js 2016-11-11 02:16:45.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/regorder/core/component2.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* 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 gRegTestCoreComponent = -{ - /* nsISupports implementation. */ - QueryInterface: function (aIID) - { - if (!aIID.equals(Components.interfaces.nsISupports) && - !aIID.equals(Components.interfaces.nsIFactory)) - throw Components.results.NS_ERROR_NO_INTERFACE; - - return this; - }, - - /* nsIFactory implementation. */ - createInstance: function (aOuter, aIID) - { - if (null != aOuter) - throw Components.results.NS_ERROR_NO_AGGREGATION; - - return this.QueryInterface(aIID); - }, - - lockFactory: function (aDoLock) {} -}; - -const kClassID = Components.ID("{d04d1298-6dac-459b-a13b-bcab235730a0}"); - -this.NSGetFactory = - function NSGetFactory(aClassID) { - if (!aClassID.equals(kClassID)) - throw Components.results.NS_ERROR_NOT_IMPLEMENTED; - - return gRegTestCoreComponent; -} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/regorder/core/component.js firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/regorder/core/component.js --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/regorder/core/component.js 2016-11-11 02:16:45.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/regorder/core/component.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* 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 gRegTestCoreComponent = -{ - /* nsISupports implementation. */ - QueryInterface: function (aIID) - { - if (!aIID.equals(Components.interfaces.nsISupports) && - !aIID.equals(Components.interfaces.nsIFactory)) - throw Components.results.NS_ERROR_NO_INTERFACE; - - return this; - }, - - /* nsIFactory implementation. */ - createInstance: function (aOuter, aIID) - { - if (null != aOuter) - throw Components.results.NS_ERROR_NO_AGGREGATION; - - return this.QueryInterface(aIID); - }, - - lockFactory: function (aDoLock) {} -}; - -const kClassID = Components.ID("{56ab1cd4-ac44-4f86-8104-171f8b8f2fc7}"); - -this.NSGetFactory = - function NSGetFactory(aClassID) { - if (!aClassID.equals(kClassID)) - throw Components.results.NS_ERROR_NOT_IMPLEMENTED; - - return gRegTestCoreComponent; -} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/regorder/core/component.manifest firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/regorder/core/component.manifest --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/regorder/core/component.manifest 2016-11-11 02:16:45.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/regorder/core/component.manifest 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -component {56ab1cd4-ac44-4f86-8104-171f8b8f2fc7} component.js -component {d04d1298-6dac-459b-a13b-bcab235730a0} component2.js -contract @mozilla.org/RegTestServiceA;1 {56ab1cd4-ac44-4f86-8104-171f8b8f2fc7} -contract @mozilla.org/RegTestServiceB;1 {d04d1298-6dac-459b-a13b-bcab235730a0} - -contract @mozilla.org/RegTestOrderC;1 {ada15884-bb89-473c-8b50-dcfbb8447ff4} -component {ada15884-bb89-473c-8b50-dcfbb8447ff4} missing.js diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/regorder/extension/extComponent.js firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/regorder/extension/extComponent.js --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/regorder/extension/extComponent.js 2016-11-11 02:16:45.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/regorder/extension/extComponent.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* 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 gRegTestExtComponent = -{ - /* nsISupports implementation. */ - QueryInterface: function (aIID) - { - if (!aIID.equals(Components.interfaces.nsISupports) && - !aIID.equals(Components.interfaces.nsIFactory)) - throw Components.results.NS_ERROR_NO_INTERFACE; - - return this; - }, - - /* nsIFactory implementation. */ - createInstance: function (aOuter, aIID) - { - if (null != aOuter) - throw Components.results.NS_ERROR_NO_AGGREGATION; - - return this.QueryInterface(aIID); - }, - - lockFactory: function (aDoLock) {} -}; - -const kClassID = Components.ID("{fe64efb7-c5ab-41a6-b639-e6c0f483181e}"); -this.NSGetFactory = function NSGetFactory(cid) -{ - if (!cid.equals(kClassID)) - throw Components.results.NS_ERROR_NOT_IMPLEMENTED; - - return gRegTestExtComponent; -} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/regorder/extension/extComponent.manifest firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/regorder/extension/extComponent.manifest --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/regorder/extension/extComponent.manifest 2016-11-11 02:16:45.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/regorder/extension/extComponent.manifest 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -component {fe64efb7-c5ab-41a6-b639-e6c0f483181e} extComponent.js -contract @mozilla.org/RegTestServiceA;1 {fe64efb7-c5ab-41a6-b639-e6c0f483181e} Binary files /tmp/tmp9L0M0q/46_E8nLq7C/firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/regorder/extension2.jar and /tmp/tmp9L0M0q/u5o9iDLrUC/firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/regorder/extension2.jar differ diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/TestBase64.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/TestBase64.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/TestBase64.cpp 2016-11-11 02:16:43.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/TestBase64.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,307 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "TestHarness.h" - -#include "mozilla/Attributes.h" -#include "nsIScriptableBase64Encoder.h" -#include "nsIInputStream.h" -#include "nsAutoPtr.h" -#include "nsStringAPI.h" -#include - -struct Chunk { - Chunk(uint32_t l, const char* c) - : mLength(l), mData(c) - {} - - uint32_t mLength; - const char* mData; -}; - -struct Test { - Test(Chunk* c, const char* r) - : mChunks(c), mResult(r) - {} - - Chunk* mChunks; - const char* mResult; -}; - -static Chunk kTest1Chunks[] = -{ - Chunk(9, "Hello sir"), - Chunk(0, nullptr) -}; - -static Chunk kTest2Chunks[] = -{ - Chunk(3, "Hel"), - Chunk(3, "lo "), - Chunk(3, "sir"), - Chunk(0, nullptr) -}; - -static Chunk kTest3Chunks[] = -{ - Chunk(1, "I"), - Chunk(0, nullptr) -}; - -static Chunk kTest4Chunks[] = -{ - Chunk(2, "Hi"), - Chunk(0, nullptr) -}; - -static Chunk kTest5Chunks[] = -{ - Chunk(1, "B"), - Chunk(2, "ob"), - Chunk(0, nullptr) -}; - -static Chunk kTest6Chunks[] = -{ - Chunk(2, "Bo"), - Chunk(1, "b"), - Chunk(0, nullptr) -}; - -static Chunk kTest7Chunks[] = -{ - Chunk(1, "F"), // Carry over 1 - Chunk(4, "iref"), // Carry over 2 - Chunk(2, "ox"), // 1 - Chunk(4, " is "), // 2 - Chunk(2, "aw"), // 1 - Chunk(4, "esom"), // 2 - Chunk(2, "e!"), - Chunk(0, nullptr) -}; - -static Chunk kTest8Chunks[] = -{ - Chunk(5, "ALL T"), - Chunk(1, "H"), - Chunk(4, "ESE "), - Chunk(2, "WO"), - Chunk(21, "RLDS ARE YOURS EXCEPT"), - Chunk(9, " EUROPA. "), - Chunk(25, "ATTEMPT NO LANDING THERE."), - Chunk(0, nullptr) -}; - -static Test kTests[] = - { - // Test 1, test a simple round string in one chunk - Test( - kTest1Chunks, - "SGVsbG8gc2ly" - ), - // Test 2, test a simple round string split into round chunks - Test( - kTest2Chunks, - "SGVsbG8gc2ly" - ), - // Test 3, test a single chunk that's 2 short - Test( - kTest3Chunks, - "SQ==" - ), - // Test 4, test a single chunk that's 1 short - Test( - kTest4Chunks, - "SGk=" - ), - // Test 5, test a single chunk that's 2 short, followed by a chunk of 2 - Test( - kTest5Chunks, - "Qm9i" - ), - // Test 6, test a single chunk that's 1 short, followed by a chunk of 1 - Test( - kTest6Chunks, - "Qm9i" - ), - // Test 7, test alternating carryovers - Test( - kTest7Chunks, - "RmlyZWZveCBpcyBhd2Vzb21lIQ==" - ), - // Test 8, test a longish string - Test( - kTest8Chunks, - "QUxMIFRIRVNFIFdPUkxEUyBBUkUgWU9VUlMgRVhDRVBUIEVVUk9QQS4gQVRURU1QVCBOTyBMQU5ESU5HIFRIRVJFLg==" - ), - // Terminator - Test( - nullptr, - nullptr - ) - }; - -class FakeInputStream final : public nsIInputStream -{ - ~FakeInputStream() {} - -public: - - FakeInputStream() - : mTestNumber(0), - mTest(&kTests[0]), - mChunk(&mTest->mChunks[0]), - mClosed(false) - {} - - NS_DECL_ISUPPORTS - NS_DECL_NSIINPUTSTREAM - - void Reset(); - bool NextTest(); - bool CheckTest(nsACString& aResult); - bool CheckTest(nsAString& aResult); -private: - uint32_t mTestNumber; - const Test* mTest; - const Chunk* mChunk; - bool mClosed; -}; - -NS_IMPL_ISUPPORTS(FakeInputStream, nsIInputStream) - -NS_IMETHODIMP -FakeInputStream::Close() -{ - mClosed = true; - return NS_OK; -} - -NS_IMETHODIMP -FakeInputStream::Available(uint64_t* aAvailable) -{ - *aAvailable = 0; - - if (mClosed) - return NS_BASE_STREAM_CLOSED; - - const Chunk* chunk = mChunk; - while (chunk->mLength) { - *aAvailable += chunk->mLength; - chunk++; - } - - return NS_OK; -} - -NS_IMETHODIMP -FakeInputStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aOut) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP -FakeInputStream::ReadSegments(nsWriteSegmentFun aWriter, - void* aClosure, - uint32_t aCount, - uint32_t* aRead) -{ - *aRead = 0; - - if (mClosed) - return NS_BASE_STREAM_CLOSED; - - while (mChunk->mLength) { - uint32_t written = 0; - - nsresult rv = (*aWriter)(this, aClosure, mChunk->mData, - *aRead, mChunk->mLength, &written); - - *aRead += written; - NS_ENSURE_SUCCESS(rv, rv); - - mChunk++; - } - - return NS_OK; -} - -NS_IMETHODIMP -FakeInputStream::IsNonBlocking(bool* aIsBlocking) -{ - *aIsBlocking = false; - return NS_OK; -} - -void -FakeInputStream::Reset() -{ - mClosed = false; - mChunk = &mTest->mChunks[0]; -} - -bool -FakeInputStream::NextTest() -{ - mTestNumber++; - mTest = &kTests[mTestNumber]; - mChunk = &mTest->mChunks[0]; - mClosed = false; - - return mTest->mChunks ? true : false; -} - -bool -FakeInputStream::CheckTest(nsACString& aResult) -{ - return !strcmp(aResult.BeginReading(), mTest->mResult) ? true : false; -} - -#ifdef XP_WIN -static inline int NS_tstrcmp(char16ptr_t x, char16ptr_t y) { - return wcscmp(x, y); -} -#else -#define NS_tstrcmp strcmp -#endif - -bool -FakeInputStream::CheckTest(nsAString& aResult) -{ - return !NS_tstrcmp(aResult.BeginReading(), - NS_ConvertASCIItoUTF16(mTest->mResult).BeginReading()) - ? true : false; -} - -int main(int argc, char** argv) -{ - ScopedXPCOM xpcom("Base64"); - NS_ENSURE_FALSE(xpcom.failed(), 1); - - nsCOMPtr encoder = - do_CreateInstance("@mozilla.org/scriptablebase64encoder;1"); - NS_ENSURE_TRUE(encoder, 1); - - RefPtr stream = new FakeInputStream(); - do { - nsString wideString; - nsCString string; - - nsresult rv; - rv = encoder->EncodeToString(stream, 0, wideString); - NS_ENSURE_SUCCESS(rv, 1); - - stream->Reset(); - - rv = encoder->EncodeToCString(stream, 0, string); - NS_ENSURE_SUCCESS(rv, 1); - - if (!stream->CheckTest(wideString) || !stream->CheckTest(string)) - fail("Failed to convert properly\n"); - - } while (stream->NextTest()); - - return 0; -} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/TestBlockingProcess.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/TestBlockingProcess.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/TestBlockingProcess.cpp 2016-11-11 02:16:43.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/TestBlockingProcess.cpp 2016-11-14 02:20:36.000000000 +0000 @@ -1,6 +1,8 @@ -#include +#include int main() { - while(1) PR_Sleep(PR_SecondsToInterval(10)); + char tmp; + fread(&tmp, sizeof(tmp), 1, stdin); + return 0; } diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/TestCallTemplates.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/TestCallTemplates.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/TestCallTemplates.cpp 2016-11-11 02:16:43.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/TestCallTemplates.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,106 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim:cindent:ts=8:et:sw=4: - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* - * This test is NOT intended to be run. It's a test to make sure - * a group of functions BUILD correctly. - */ - -#include "nsISupportsUtils.h" -#include "nsIWeakReference.h" -#include "nsIComponentManager.h" -#include "nsIServiceManager.h" -#include "nsWeakReference.h" -#include "nsIInterfaceRequestor.h" -#include "nsIInterfaceRequestorUtils.h" -#include "nsComponentManagerUtils.h" -#include "nsServiceManagerUtils.h" -#include "nsAutoPtr.h" -#include "mozilla/Attributes.h" - -#define NS_ITESTSERVICE_IID \ - {0x127b5253, 0x37b1, 0x43c7, \ - { 0x96, 0x2b, 0xab, 0xf1, 0x2d, 0x22, 0x56, 0xae }} - -class NS_NO_VTABLE nsITestService : public nsISupports { - public: - NS_DECLARE_STATIC_IID_ACCESSOR(NS_ITESTSERVICE_IID) -}; - -NS_DEFINE_STATIC_IID_ACCESSOR(nsITestService, NS_ITESTSERVICE_IID) - -class nsTestService final : public nsITestService, - public nsSupportsWeakReference -{ - ~nsTestService() {} - public: - NS_DECL_ISUPPORTS -}; - -NS_IMPL_ISUPPORTS(nsTestService, nsITestService, nsISupportsWeakReference) - -#define NS_TEST_SERVICE_CONTRACTID "@mozilla.org/test/testservice;1" -#define NS_TEST_SERVICE_CID \ - {0xa00c1406, 0x283a, 0x45c9, \ - {0xae, 0xd2, 0x1a, 0xb6, 0xdd, 0xba, 0xfe, 0x53}} -static NS_DEFINE_CID(kTestServiceCID, NS_TEST_SERVICE_CID); - -int main() -{ - /* - * NOTE: This does NOT demonstrate how these functions are - * intended to be used. They are intended for filling in out - * parameters that need to be |AddRef|ed. I'm just too lazy - * to write lots of little getter functions for a test program - * when I don't need to. - */ - - NS_NOTREACHED("This test is not intended to run, only to compile!"); - - /* Test CallQueryInterface */ - - nsISupports *mySupportsPtr = reinterpret_cast(0x1000); - - nsITestService *myITestService = nullptr; - CallQueryInterface(mySupportsPtr, &myITestService); - - nsTestService *myTestService = - reinterpret_cast(mySupportsPtr); - nsISupportsWeakReference *mySupportsWeakRef; - CallQueryInterface(myTestService, &mySupportsWeakRef); - - nsCOMPtr mySupportsCOMPtr = mySupportsPtr; - CallQueryInterface(mySupportsCOMPtr, &myITestService); - - RefPtr myTestServiceRefPtr = myTestService; - CallQueryInterface(myTestServiceRefPtr, &mySupportsWeakRef); - - /* Test CallQueryReferent */ - - nsIWeakReference *myWeakRef = - static_cast(mySupportsPtr); - CallQueryReferent(myWeakRef, &myITestService); - - /* Test CallCreateInstance */ - - CallCreateInstance(kTestServiceCID, mySupportsPtr, &myITestService); - CallCreateInstance(kTestServiceCID, &myITestService); - CallCreateInstance(NS_TEST_SERVICE_CONTRACTID, mySupportsPtr, - &myITestService); - CallCreateInstance(NS_TEST_SERVICE_CONTRACTID, &myITestService); - - /* Test CallGetService */ - CallGetService(kTestServiceCID, &myITestService); - CallGetService(NS_TEST_SERVICE_CONTRACTID, &myITestService); - - /* Test CallGetInterface */ - nsIInterfaceRequestor *myInterfaceRequestor = - static_cast(mySupportsPtr); - CallGetInterface(myInterfaceRequestor, &myITestService); - - return 0; -} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/TestDeadlockDetector.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/TestDeadlockDetector.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/TestDeadlockDetector.cpp 2016-11-11 02:16:43.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/TestDeadlockDetector.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,566 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: sw=4 ts=4 et : - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/ArrayUtils.h" - -#include "prenv.h" -#include "prerror.h" -#include "prio.h" -#include "prproces.h" - -#include "nsMemory.h" - -#include "mozilla/CondVar.h" -#include "mozilla/ReentrantMonitor.h" -#include "mozilla/Mutex.h" - -#include "TestHarness.h" - -using namespace mozilla; - -static PRThread* -spawn(void (*run)(void*), void* arg) -{ - return PR_CreateThread(PR_SYSTEM_THREAD, - run, - arg, - PR_PRIORITY_NORMAL, - PR_GLOBAL_THREAD, - PR_JOINABLE_THREAD, - 0); -} - -#define PASS() \ - do { \ - passed(__FUNCTION__); \ - return NS_OK; \ - } while (0) - -#define FAIL(why) \ - do { \ - fail("%s | %s - %s", __FILE__, __FUNCTION__, why); \ - return NS_ERROR_FAILURE; \ - } while (0) - -//----------------------------------------------------------------------------- - -static const char* sPathToThisBinary; -static const char* sAssertBehaviorEnv = "XPCOM_DEBUG_BREAK=abort"; - -class Subprocess -{ -public: - // not available until process finishes - int32_t mExitCode; - nsCString mStdout; - nsCString mStderr; - - explicit Subprocess(const char* aTestName) { - // set up stdio redirection - PRFileDesc* readStdin; PRFileDesc* writeStdin; - PRFileDesc* readStdout; PRFileDesc* writeStdout; - PRFileDesc* readStderr; PRFileDesc* writeStderr; - PRProcessAttr* pattr = PR_NewProcessAttr(); - - NS_ASSERTION(pattr, "couldn't allocate process attrs"); - - NS_ASSERTION(PR_SUCCESS == PR_CreatePipe(&readStdin, &writeStdin), - "couldn't create child stdin pipe"); - NS_ASSERTION(PR_SUCCESS == PR_SetFDInheritable(readStdin, true), - "couldn't set child stdin inheritable"); - PR_ProcessAttrSetStdioRedirect(pattr, PR_StandardInput, readStdin); - - NS_ASSERTION(PR_SUCCESS == PR_CreatePipe(&readStdout, &writeStdout), - "couldn't create child stdout pipe"); - NS_ASSERTION(PR_SUCCESS == PR_SetFDInheritable(writeStdout, true), - "couldn't set child stdout inheritable"); - PR_ProcessAttrSetStdioRedirect(pattr, PR_StandardOutput, writeStdout); - - NS_ASSERTION(PR_SUCCESS == PR_CreatePipe(&readStderr, &writeStderr), - "couldn't create child stderr pipe"); - NS_ASSERTION(PR_SUCCESS == PR_SetFDInheritable(writeStderr, true), - "couldn't set child stderr inheritable"); - PR_ProcessAttrSetStdioRedirect(pattr, PR_StandardError, writeStderr); - - // set up argv with test name to run - char* const newArgv[3] = { - strdup(sPathToThisBinary), - strdup(aTestName), - 0 - }; - - // make sure the child will abort if an assertion fails - NS_ASSERTION(PR_SUCCESS == PR_SetEnv(sAssertBehaviorEnv), - "couldn't set XPCOM_DEBUG_BREAK env var"); - - PRProcess* proc; - NS_ASSERTION(proc = PR_CreateProcess(sPathToThisBinary, - newArgv, - 0, // inherit environment - pattr), - "couldn't create process"); - PR_Close(readStdin); - PR_Close(writeStdout); - PR_Close(writeStderr); - - mProc = proc; - mStdinfd = writeStdin; - mStdoutfd = readStdout; - mStderrfd = readStderr; - - free(newArgv[0]); - free(newArgv[1]); - PR_DestroyProcessAttr(pattr); - } - - void RunToCompletion(uint32_t aWaitMs) - { - PR_Close(mStdinfd); - - PRPollDesc pollfds[2]; - int32_t nfds; - bool stdoutOpen = true, stderrOpen = true; - char buf[4096]; - - PRIntervalTime now = PR_IntervalNow(); - PRIntervalTime deadline = now + PR_MillisecondsToInterval(aWaitMs); - - while ((stdoutOpen || stderrOpen) && now < deadline) { - nfds = 0; - if (stdoutOpen) { - pollfds[nfds].fd = mStdoutfd; - pollfds[nfds].in_flags = PR_POLL_READ; - pollfds[nfds].out_flags = 0; - ++nfds; - } - if (stderrOpen) { - pollfds[nfds].fd = mStderrfd; - pollfds[nfds].in_flags = PR_POLL_READ; - pollfds[nfds].out_flags = 0; - ++nfds; - } - - int32_t rv = PR_Poll(pollfds, nfds, deadline - now); - NS_ASSERTION(0 <= rv, PR_ErrorToName(PR_GetError())); - - if (0 == rv) { // timeout - fputs("(timed out!)\n", stderr); - Finish(false); // abnormal - return; - } - - for (int32_t i = 0; i < nfds; ++i) { - if (!pollfds[i].out_flags) - continue; - - bool isStdout = mStdoutfd == pollfds[i].fd; - int32_t len = 0; - - if (PR_POLL_READ & pollfds[i].out_flags) { - len = PR_Read(pollfds[i].fd, buf, sizeof(buf) - 1); - NS_ASSERTION(0 <= len, PR_ErrorToName(PR_GetError())); - } - else if (!(PR_POLL_HUP & pollfds[i].out_flags)) { - NS_ERROR(PR_ErrorToName(PR_GetError())); - } - - if (0 < len) { - buf[len] = '\0'; - if (isStdout) - mStdout += buf; - else - mStderr += buf; - } - else if (isStdout) { - stdoutOpen = false; - } - else { - stderrOpen = false; - } - } - - now = PR_IntervalNow(); - } - - if (stdoutOpen) - fputs("(stdout still open!)\n", stderr); - if (stderrOpen) - fputs("(stderr still open!)\n", stderr); - if (now > deadline) - fputs("(timed out!)\n", stderr); - - Finish(!stdoutOpen && !stderrOpen && now <= deadline); - } - -private: - void Finish(bool normalExit) { - if (!normalExit) { - PR_KillProcess(mProc); - mExitCode = -1; - int32_t dummy; - PR_WaitProcess(mProc, &dummy); - } - else { - PR_WaitProcess(mProc, &mExitCode); // this had better not block ... - } - - PR_Close(mStdoutfd); - PR_Close(mStderrfd); - } - - PRProcess* mProc; - PRFileDesc* mStdinfd; // writeable - PRFileDesc* mStdoutfd; // readable - PRFileDesc* mStderrfd; // readable -}; - -//----------------------------------------------------------------------------- -// Harness for checking detector errors -bool -CheckForDeadlock(const char* test, const char* const* findTokens) -{ - Subprocess proc(test); - proc.RunToCompletion(5000); - - if (0 == proc.mExitCode) - return false; - - int32_t idx = 0; - for (const char* const* tp = findTokens; *tp; ++tp) { - const char* const token = *tp; -#ifdef MOZILLA_INTERNAL_API - idx = proc.mStderr.Find(token, false, idx); -#else - nsCString tokenCString(token); - idx = proc.mStderr.Find(tokenCString, idx); -#endif - if (-1 == idx) { - printf("(missed token '%s' in output)\n", token); - puts("----------------------------------\n"); - puts(proc.mStderr.get()); - puts("----------------------------------\n"); - return false; - } - idx += strlen(token); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Single-threaded sanity tests - -// Stupidest possible deadlock. -int -Sanity_Child() -{ - mozilla::Mutex m1("dd.sanity.m1"); - m1.Lock(); - m1.Lock(); - return 0; // not reached -} - -nsresult -Sanity() -{ - const char* const tokens[] = { - "###!!! ERROR: Potential deadlock detected", - "=== Cyclical dependency starts at\n--- Mutex : dd.sanity.m1", - "=== Cycle completed at\n--- Mutex : dd.sanity.m1", - "###!!! Deadlock may happen NOW!", // better catch these easy cases... - "###!!! ASSERTION: Potential deadlock detected", - 0 - }; - if (CheckForDeadlock("Sanity", tokens)) { - PASS(); - } else { - FAIL("deadlock not detected"); - } -} - -// Slightly less stupid deadlock. -int -Sanity2_Child() -{ - mozilla::Mutex m1("dd.sanity2.m1"); - mozilla::Mutex m2("dd.sanity2.m2"); - m1.Lock(); - m2.Lock(); - m1.Lock(); - return 0; // not reached -} - -nsresult -Sanity2() -{ - const char* const tokens[] = { - "###!!! ERROR: Potential deadlock detected", - "=== Cyclical dependency starts at\n--- Mutex : dd.sanity2.m1", - "--- Next dependency:\n--- Mutex : dd.sanity2.m2", - "=== Cycle completed at\n--- Mutex : dd.sanity2.m1", - "###!!! Deadlock may happen NOW!", // better catch these easy cases... - "###!!! ASSERTION: Potential deadlock detected", - 0 - }; - if (CheckForDeadlock("Sanity2", tokens)) { - PASS(); - } else { - FAIL("deadlock not detected"); - } -} - - -int -Sanity3_Child() -{ - mozilla::Mutex m1("dd.sanity3.m1"); - mozilla::Mutex m2("dd.sanity3.m2"); - mozilla::Mutex m3("dd.sanity3.m3"); - mozilla::Mutex m4("dd.sanity3.m4"); - - m1.Lock(); - m2.Lock(); - m3.Lock(); - m4.Lock(); - m4.Unlock(); - m3.Unlock(); - m2.Unlock(); - m1.Unlock(); - - m4.Lock(); - m1.Lock(); - return 0; -} - -nsresult -Sanity3() -{ - const char* const tokens[] = { - "###!!! ERROR: Potential deadlock detected", - "=== Cyclical dependency starts at\n--- Mutex : dd.sanity3.m1", - "--- Next dependency:\n--- Mutex : dd.sanity3.m2", - "--- Next dependency:\n--- Mutex : dd.sanity3.m3", - "--- Next dependency:\n--- Mutex : dd.sanity3.m4", - "=== Cycle completed at\n--- Mutex : dd.sanity3.m1", - "###!!! ASSERTION: Potential deadlock detected", - 0 - }; - if (CheckForDeadlock("Sanity3", tokens)) { - PASS(); - } else { - FAIL("deadlock not detected"); - } -} - - -int -Sanity4_Child() -{ - mozilla::ReentrantMonitor m1("dd.sanity4.m1"); - mozilla::Mutex m2("dd.sanity4.m2"); - m1.Enter(); - m2.Lock(); - m1.Enter(); - return 0; -} - -nsresult -Sanity4() -{ - const char* const tokens[] = { - "Re-entering ReentrantMonitor after acquiring other resources", - "###!!! ERROR: Potential deadlock detected", - "=== Cyclical dependency starts at\n--- ReentrantMonitor : dd.sanity4.m1", - "--- Next dependency:\n--- Mutex : dd.sanity4.m2", - "=== Cycle completed at\n--- ReentrantMonitor : dd.sanity4.m1", - "###!!! ASSERTION: Potential deadlock detected", - 0 - }; - if (CheckForDeadlock("Sanity4", tokens)) { - PASS(); - } else { - FAIL("deadlock not detected"); - } -} - -//----------------------------------------------------------------------------- -// Multithreaded tests - -mozilla::Mutex* ttM1; -mozilla::Mutex* ttM2; - -static void -TwoThreads_thread(void* arg) -{ - int32_t m1First = NS_PTR_TO_INT32(arg); - if (m1First) { - ttM1->Lock(); - ttM2->Lock(); - ttM2->Unlock(); - ttM1->Unlock(); - } - else { - ttM2->Lock(); - ttM1->Lock(); - ttM1->Unlock(); - ttM2->Unlock(); - } -} - -int -TwoThreads_Child() -{ - ttM1 = new mozilla::Mutex("dd.twothreads.m1"); - ttM2 = new mozilla::Mutex("dd.twothreads.m2"); - if (!ttM1 || !ttM2) - NS_RUNTIMEABORT("couldn't allocate mutexes"); - - PRThread* t1 = spawn(TwoThreads_thread, (void*) 0); - PR_JoinThread(t1); - - PRThread* t2 = spawn(TwoThreads_thread, (void*) 1); - PR_JoinThread(t2); - - return 0; -} - -nsresult -TwoThreads() -{ - const char* const tokens[] = { - "###!!! ERROR: Potential deadlock detected", - "=== Cyclical dependency starts at\n--- Mutex : dd.twothreads.m2", - "--- Next dependency:\n--- Mutex : dd.twothreads.m1", - "=== Cycle completed at\n--- Mutex : dd.twothreads.m2", - "###!!! ASSERTION: Potential deadlock detected", - 0 - }; - - if (CheckForDeadlock("TwoThreads", tokens)) { - PASS(); - } else { - FAIL("deadlock not detected"); - } -} - - -mozilla::Mutex* cndMs[4]; -const uint32_t K = 100000; - -static void -ContentionNoDeadlock_thread(void* arg) -{ - int32_t starti = NS_PTR_TO_INT32(arg); - - for (uint32_t k = 0; k < K; ++k) { - for (int32_t i = starti; i < (int32_t) ArrayLength(cndMs); ++i) - cndMs[i]->Lock(); - // comment out the next two lines for deadlocking fun! - for (int32_t i = ArrayLength(cndMs) - 1; i >= starti; --i) - cndMs[i]->Unlock(); - - starti = (starti + 1) % 3; - } -} - -int -ContentionNoDeadlock_Child() -{ - PRThread* threads[3]; - - for (uint32_t i = 0; i < ArrayLength(cndMs); ++i) - cndMs[i] = new mozilla::Mutex("dd.cnd.ms"); - - for (int32_t i = 0; i < (int32_t) ArrayLength(threads); ++i) - threads[i] = spawn(ContentionNoDeadlock_thread, NS_INT32_TO_PTR(i)); - - for (uint32_t i = 0; i < ArrayLength(threads); ++i) - PR_JoinThread(threads[i]); - - for (uint32_t i = 0; i < ArrayLength(cndMs); ++i) - delete cndMs[i]; - - return 0; -} - -nsresult -ContentionNoDeadlock() -{ - const char * func = __func__; - Subprocess proc(func); - proc.RunToCompletion(60000); - if (0 != proc.mExitCode) { - printf("(expected 0 == return code, got %d)\n", proc.mExitCode); - puts("(output)\n----------------------------------\n"); - puts(proc.mStdout.get()); - puts("----------------------------------\n"); - puts("(error output)\n----------------------------------\n"); - puts(proc.mStderr.get()); - puts("----------------------------------\n"); - - FAIL("deadlock"); - } - PASS(); -} - - - -//----------------------------------------------------------------------------- - -int -main(int argc, char** argv) -{ - if (1 < argc) { - // XXX can we run w/o scoped XPCOM? - const char* test = argv[1]; - ScopedXPCOM xpcom(test); - if (xpcom.failed()) - return 1; - - // running in a spawned process. call the specificed child function. - if (!strcmp("Sanity", test)) - return Sanity_Child(); - if (!strcmp("Sanity2", test)) - return Sanity2_Child(); - if (!strcmp("Sanity3", test)) - return Sanity3_Child(); - if (!strcmp("Sanity4", test)) - return Sanity4_Child(); - - if (!strcmp("TwoThreads", test)) - return TwoThreads_Child(); - if (!strcmp("ContentionNoDeadlock", test)) - return ContentionNoDeadlock_Child(); - - fail("%s | %s - unknown child test", __FILE__, __FUNCTION__); - return 2; - } - - ScopedXPCOM xpcom("XPCOM deadlock detector correctness (" __FILE__ ")"); - if (xpcom.failed()) - return 1; - - // in the first invocation of this process. we will be the "driver". - int rv = 0; - - sPathToThisBinary = argv[0]; - - if (NS_FAILED(Sanity())) - rv = 1; - if (NS_FAILED(Sanity2())) - rv = 1; - if (NS_FAILED(Sanity3())) - rv = 1; - if (NS_FAILED(Sanity4())) - rv = 1; - - if (NS_FAILED(TwoThreads())) - rv = 1; - if (NS_FAILED(ContentionNoDeadlock())) - rv = 1; - - return rv; -} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/TestDeadlockDetectorScalability.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/TestDeadlockDetectorScalability.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/TestDeadlockDetectorScalability.cpp 2016-11-11 02:16:43.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/TestDeadlockDetectorScalability.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,246 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: sw=4 ts=4 et : - * 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/. */ - -// Avoid DMD-specific parts of MOZ_DEFINE_MALLOC_SIZE_OF -#undef MOZ_DMD - -#include "TestHarness.h" -#include "nsIMemoryReporter.h" - -//#define OLD_API - -#define PASS() \ - do { \ - passed(__FUNCTION__); \ - return NS_OK; \ - } while (0) - -#define FAIL(why) \ - do { \ - fail("%s | %s - %s", __FILE__, __FUNCTION__, why); \ - return NS_ERROR_FAILURE; \ - } while (0) - -#ifdef OLD_API -# include "nsAutoLock.h" - typedef PRLock* moz_lock_t; -# define NEWLOCK(n) nsAutoLock::NewLock(n) -# define DELETELOCK(v) nsAutoLock::DestroyLock(v) -# define AUTOLOCK(v, l) nsAutoLock v(l) -#else -# include "mozilla/Mutex.h" - typedef mozilla::Mutex* moz_lock_t; -# define NEWLOCK(n) new mozilla::Mutex(n) -# define DELETELOCK(v) delete (v) -# define AUTOLOCK(v, l) mozilla::MutexAutoLock v(*l) -#endif - -// def/undef these to run particular tests. -#undef DD_TEST1 -#undef DD_TEST2 -#undef DD_TEST3 -#undef DD_TEST4 - -//----------------------------------------------------------------------------- - -#ifdef DD_TEST1 - -static void -AllocLockRecurseUnlockFree(int i) -{ - if (0 == i) - return; - - moz_lock_t lock = NEWLOCK("deadlockDetector.scalability.t1"); - { - AUTOLOCK(_, lock); - AllocLockRecurseUnlockFree(i - 1); - } - DELETELOCK(lock); -} - -// This test creates a resource dependency chain N elements long, then -// frees all the resources in the chain. -static nsresult -LengthNDepChain(int N) -{ - AllocLockRecurseUnlockFree(N); - PASS(); -} - -#endif - -//----------------------------------------------------------------------------- - -#ifdef DD_TEST2 - -// This test creates a single lock that is ordered < N resources, then -// repeatedly exercises this order k times. -static nsresult -OneLockNDeps(const int N, const int K) -{ - moz_lock_t lock = NEWLOCK("deadlockDetector.scalability.t2.master"); - moz_lock_t* locks = new moz_lock_t[N]; - if (!locks) - NS_RUNTIMEABORT("couldn't allocate lock array"); - - for (int i = 0; i < N; ++i) - locks[i] = - NEWLOCK("deadlockDetector.scalability.t2.dep"); - - // establish orders - {AUTOLOCK(m, lock); - for (int i = 0; i < N; ++i) - AUTOLOCK(s, locks[i]); - } - - // exercise order check - {AUTOLOCK(m, lock); - for (int i = 0; i < K; ++i) - for (int j = 0; j < N; ++j) - AUTOLOCK(s, locks[i]); - } - - for (int i = 0; i < N; ++i) - DELETELOCK(locks[i]); - delete[] locks; - - PASS(); -} - -#endif - -//----------------------------------------------------------------------------- - -#ifdef DD_TEST3 - -// This test creates N resources and adds the theoretical maximum number -// of dependencies, O(N^2). It then repeats that sequence of -// acquisitions k times. Finally, all resources are freed. -// -// It's very difficult to perform well on this test. It's put forth as a -// challenge problem. - -static nsresult -MaxDepsNsq(const int N, const int K) -{ - moz_lock_t* locks = new moz_lock_t[N]; - if (!locks) - NS_RUNTIMEABORT("couldn't allocate lock array"); - - for (int i = 0; i < N; ++i) - locks[i] = NEWLOCK("deadlockDetector.scalability.t3"); - - for (int i = 0; i < N; ++i) { - AUTOLOCK(al1, locks[i]); - for (int j = i+1; j < N; ++j) - AUTOLOCK(al2, locks[j]); - } - - for (int i = 0; i < K; ++i) { - for (int j = 0; j < N; ++j) { - AUTOLOCK(al1, locks[j]); - for (int k = j+1; k < N; ++k) - AUTOLOCK(al2, locks[k]); - } - } - - for (int i = 0; i < N; ++i) - DELETELOCK(locks[i]); - delete[] locks; - - PASS(); -} - -#endif - -//----------------------------------------------------------------------------- - -#ifdef DD_TEST4 - -// This test creates a single lock that is ordered < N resources. The -// resources are allocated, exercised K times, and deallocated one at -// a time. - -static nsresult -OneLockNDepsUsedSeveralTimes(const size_t N, const size_t K) -{ - // Create master lock. - moz_lock_t lock_1 = NEWLOCK("deadlockDetector.scalability.t4.master"); - for (size_t n = 0; n < N; n++) { - // Create child lock. - moz_lock_t lock_2 = NEWLOCK("deadlockDetector.scalability.t4.child"); - - // First lock the master. - AUTOLOCK(m, lock_1); - - // Now lock and unlock the child a few times. - for (size_t k = 0; k < K; k++) { - AUTOLOCK(c, lock_2); - } - - // Destroy the child lock. - DELETELOCK(lock_2); - } - - // Cleanup the master lock. - DELETELOCK(lock_1); - - PASS(); -} - -#endif - -//----------------------------------------------------------------------------- - -MOZ_DEFINE_MALLOC_SIZE_OF(DeadlockDetectorMallocSizeOf) - -int -main(int argc, char** argv) -{ - ScopedXPCOM xpcom("Deadlock detector scalability (" __FILE__ ")"); - if (xpcom.failed()) - return 1; - - int rv = 0; - - // Uncomment these tests to run them. Not expected to be common. - -#ifndef DD_TEST1 - puts("Skipping not-requested LengthNDepChain() test"); -#else - if (NS_FAILED(LengthNDepChain(1 << 14))) // 16K - rv = 1; -#endif - -#ifndef DD_TEST2 - puts("Skipping not-requested OneLockNDeps() test"); -#else - // NB: Using a larger test size to stress our traversal logic. - if (NS_FAILED(OneLockNDeps(1 << 17, 100))) // 131k - rv = 1; -#endif - -#ifndef DD_TEST3 - puts("Skipping not-requested MaxDepsNsq() test"); -#else - if (NS_FAILED(MaxDepsNsq(1 << 10, 10))) // 1k - rv = 1; -#endif - -#ifndef DD_TEST4 - puts("Skipping not-requested OneLockNDepsUsedSeveralTimes() test"); -#else - if (NS_FAILED(OneLockNDepsUsedSeveralTimes(1 << 17, 3))) // 131k - rv = 1; -#endif - - size_t memory_used = mozilla::BlockingResourceBase::SizeOfDeadlockDetector( - DeadlockDetectorMallocSizeOf); - printf_stderr("Used %d bytes\n", (int)memory_used); - - return rv; -} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/TestINIParser.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/TestINIParser.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/TestINIParser.cpp 2016-11-11 02:16:43.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/TestINIParser.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include - -#include "nsXPCOM.h" -#include "nsINIParser.h" -#include "nsIFile.h" - -static bool -StringCB(const char *aKey, const char *aValue, void* aClosure) -{ - printf("%s=%s\n", aKey, aValue); - - return true; -} - -static bool -SectionCB(const char *aSection, void* aClosure) -{ - nsINIParser *ini = reinterpret_cast(aClosure); - - printf("[%s]\n", aSection); - - ini->GetStrings(aSection, StringCB, nullptr); - - printf("\n"); - - return true; -} - -int main(int argc, char **argv) -{ - if (argc < 2) { - fprintf(stderr, "Usage: %s \n", argv[0]); - return 255; - } - - nsCOMPtr lf; - - nsresult rv = NS_NewNativeLocalFile(nsDependentCString(argv[1]), - true, - getter_AddRefs(lf)); - if (NS_FAILED(rv)) { - fprintf(stderr, "Error: NS_NewNativeLocalFile failed\n"); - return 1; - } - - nsINIParser ini; - rv = ini.Init(lf); - if (NS_FAILED(rv)) { - fprintf(stderr, "Error: Init failed."); - return 2; - } - - ini.GetSections(SectionCB, &ini); - - return 0; -} - diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/TestRacingServiceManager.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/TestRacingServiceManager.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/TestRacingServiceManager.cpp 2016-11-11 02:16:43.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/TestRacingServiceManager.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,300 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "TestHarness.h" - -#include "nsIFactory.h" -#include "mozilla/Module.h" -#include "nsXULAppAPI.h" -#include "nsIThread.h" -#include "nsIComponentRegistrar.h" - -#include "nsAutoPtr.h" -#include "nsThreadUtils.h" -#include "nsXPCOMCIDInternal.h" -#include "pratom.h" -#include "prmon.h" -#include "mozilla/Assertions.h" -#include "mozilla/Attributes.h" - -#include "mozilla/ReentrantMonitor.h" -using namespace mozilla; - -/* f93f6bdc-88af-42d7-9d64-1b43c649a3e5 */ -#define FACTORY_CID1 \ -{ \ - 0xf93f6bdc, \ - 0x88af, \ - 0x42d7, \ - { 0x9d, 0x64, 0x1b, 0x43, 0xc6, 0x49, 0xa3, 0xe5 } \ -} -NS_DEFINE_CID(kFactoryCID1, FACTORY_CID1); - -/* ef38ad65-6595-49f0-8048-e819f81d15e2 */ -#define FACTORY_CID2 \ -{ \ - 0xef38ad65, \ - 0x6595, \ - 0x49f0, \ - { 0x80, 0x48, 0xe8, 0x19, 0xf8, 0x1d, 0x15, 0xe2 } \ -} -NS_DEFINE_CID(kFactoryCID2, FACTORY_CID2); - -#define FACTORY_CONTRACTID \ - "TestRacingThreadManager/factory;1" - -int32_t gComponent1Count = 0; -int32_t gComponent2Count = 0; - -ReentrantMonitor* gReentrantMonitor = nullptr; - -bool gCreateInstanceCalled = false; -bool gMainThreadWaiting = false; - -class AutoCreateAndDestroyReentrantMonitor -{ -public: - explicit AutoCreateAndDestroyReentrantMonitor(ReentrantMonitor** aReentrantMonitorPtr) - : mReentrantMonitorPtr(aReentrantMonitorPtr) { - *aReentrantMonitorPtr = - new ReentrantMonitor("TestRacingServiceManager::AutoMon"); - MOZ_RELEASE_ASSERT(*aReentrantMonitorPtr, "Out of memory!"); - } - - ~AutoCreateAndDestroyReentrantMonitor() { - if (*mReentrantMonitorPtr) { - delete *mReentrantMonitorPtr; - *mReentrantMonitorPtr = nullptr; - } - } - -private: - ReentrantMonitor** mReentrantMonitorPtr; -}; - -class Factory final : public nsIFactory -{ - ~Factory() {} - -public: - NS_DECL_THREADSAFE_ISUPPORTS - - Factory() : mFirstComponentCreated(false) { } - - NS_IMETHOD CreateInstance(nsISupports* aDelegate, - const nsIID& aIID, - void** aResult) override; - - NS_IMETHOD LockFactory(bool aLock) override { - return NS_OK; - } - - bool mFirstComponentCreated; -}; - -NS_IMPL_ISUPPORTS(Factory, nsIFactory) - -class Component1 final : public nsISupports -{ - ~Component1() {} - -public: - NS_DECL_THREADSAFE_ISUPPORTS - - Component1() { - // This is the real test - make sure that only one instance is ever created. - int32_t count = PR_AtomicIncrement(&gComponent1Count); - MOZ_RELEASE_ASSERT(count == 1, "Too many components created!"); - } -}; - -NS_IMPL_ADDREF(Component1) -NS_IMPL_RELEASE(Component1) - -NS_INTERFACE_MAP_BEGIN(Component1) - NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -class Component2 final : public nsISupports -{ - ~Component2() {} - -public: - NS_DECL_THREADSAFE_ISUPPORTS - - Component2() { - // This is the real test - make sure that only one instance is ever created. - int32_t count = PR_AtomicIncrement(&gComponent2Count); - MOZ_RELEASE_ASSERT(count == 1, "Too many components created!"); - } -}; - -NS_IMPL_ADDREF(Component2) -NS_IMPL_RELEASE(Component2) - -NS_INTERFACE_MAP_BEGIN(Component2) - NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -NS_IMETHODIMP -Factory::CreateInstance(nsISupports* aDelegate, - const nsIID& aIID, - void** aResult) -{ - // Make sure that the second thread beat the main thread to the getService - // call. - MOZ_RELEASE_ASSERT(!NS_IsMainThread(), "Wrong thread!"); - - { - ReentrantMonitorAutoEnter mon(*gReentrantMonitor); - - gCreateInstanceCalled = true; - mon.Notify(); - - mon.Wait(PR_MillisecondsToInterval(3000)); - } - - NS_ENSURE_FALSE(aDelegate, NS_ERROR_NO_AGGREGATION); - NS_ENSURE_ARG_POINTER(aResult); - - nsCOMPtr instance; - - if (!mFirstComponentCreated) { - instance = new Component1(); - } - else { - instance = new Component2(); - } - NS_ENSURE_TRUE(instance, NS_ERROR_OUT_OF_MEMORY); - - nsresult rv = instance->QueryInterface(aIID, aResult); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; -} - -class TestRunnable : public Runnable -{ -public: - NS_DECL_NSIRUNNABLE - - TestRunnable() : mFirstRunnableDone(false) { } - - bool mFirstRunnableDone; -}; - -NS_IMETHODIMP -TestRunnable::Run() -{ - { - ReentrantMonitorAutoEnter mon(*gReentrantMonitor); - - while (!gMainThreadWaiting) { - mon.Wait(); - } - } - - nsresult rv; - nsCOMPtr component; - - if (!mFirstRunnableDone) { - component = do_GetService(kFactoryCID1, &rv); - } - else { - component = do_GetService(FACTORY_CONTRACTID, &rv); - } - MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv), "GetService failed!"); - - return NS_OK; -} - -static Factory* gFactory; - -static already_AddRefed -CreateFactory(const mozilla::Module& module, const mozilla::Module::CIDEntry& entry) -{ - if (!gFactory) { - gFactory = new Factory(); - NS_ADDREF(gFactory); - } - nsCOMPtr ret = gFactory; - return ret.forget(); -} - -static const mozilla::Module::CIDEntry kLocalCIDs[] = { - { &kFactoryCID1, false, CreateFactory, nullptr }, - { &kFactoryCID2, false, CreateFactory, nullptr }, - { nullptr } -}; - -static const mozilla::Module::ContractIDEntry kLocalContracts[] = { - { FACTORY_CONTRACTID, &kFactoryCID2 }, - { nullptr } -}; - -static const mozilla::Module kLocalModule = { - mozilla::Module::kVersion, - kLocalCIDs, - kLocalContracts -}; - -int main(int argc, char** argv) -{ - nsresult rv; - XRE_AddStaticComponent(&kLocalModule); - - ScopedXPCOM xpcom("RacingServiceManager"); - NS_ENSURE_FALSE(xpcom.failed(), 1); - - AutoCreateAndDestroyReentrantMonitor mon1(&gReentrantMonitor); - - RefPtr runnable = new TestRunnable(); - NS_ENSURE_TRUE(runnable, 1); - - // Run the classID test - nsCOMPtr newThread; - rv = NS_NewThread(getter_AddRefs(newThread), runnable); - NS_ENSURE_SUCCESS(rv, 1); - - { - ReentrantMonitorAutoEnter mon2(*gReentrantMonitor); - - gMainThreadWaiting = true; - mon2.Notify(); - - while (!gCreateInstanceCalled) { - mon2.Wait(); - } - } - - nsCOMPtr component(do_GetService(kFactoryCID1, &rv)); - NS_ENSURE_SUCCESS(rv, 1); - - // Reset for the contractID test - gMainThreadWaiting = gCreateInstanceCalled = false; - gFactory->mFirstComponentCreated = runnable->mFirstRunnableDone = true; - component = nullptr; - - rv = newThread->Dispatch(runnable, NS_DISPATCH_NORMAL); - NS_ENSURE_SUCCESS(rv, 1); - - { - ReentrantMonitorAutoEnter mon3(*gReentrantMonitor); - - gMainThreadWaiting = true; - mon3.Notify(); - - while (!gCreateInstanceCalled) { - mon3.Wait(); - } - } - - component = do_GetService(FACTORY_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, 1); - - NS_RELEASE(gFactory); - - return 0; -} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/TestRegistrationOrder.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/TestRegistrationOrder.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/TestRegistrationOrder.cpp 2016-11-11 02:16:43.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/TestRegistrationOrder.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,195 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "TestHarness.h" -#include "nsIFile.h" -#include "nsIDirectoryService.h" -#include "nsDirectoryServiceDefs.h" -#include "nsCOMArray.h" -#include "nsArrayEnumerator.h" -#include "nsXULAppAPI.h" -#include "nsIComponentRegistrar.h" - -#define SERVICE_A_CONTRACT_ID "@mozilla.org/RegTestServiceA;1" -#define SERVICE_B_CONTRACT_ID "@mozilla.org/RegTestServiceB;1" - -// {56ab1cd4-ac44-4f86-8104-171f8b8f2fc7} -#define CORE_SERVICE_A_CID \ - { 0x56ab1cd4, 0xac44, 0x4f86, \ - { 0x81, 0x04, 0x17, 0x1f, 0x8b, 0x8f, 0x2f, 0xc7} } -NS_DEFINE_CID(kCoreServiceA_CID, CORE_SERVICE_A_CID); - -// {fe64efb7-c5ab-41a6-b639-e6c0f483181e} -#define EXT_SERVICE_A_CID \ - { 0xfe64efb7, 0xc5ab, 0x41a6, \ - { 0xb6, 0x39, 0xe6, 0xc0, 0xf4, 0x83, 0x18, 0x1e} } -NS_DEFINE_CID(kExtServiceA_CID, EXT_SERVICE_A_CID); - -// {d04d1298-6dac-459b-a13b-bcab235730a0} -#define CORE_SERVICE_B_CID \ - { 0xd04d1298, 0x6dac, 0x459b, \ - { 0xa1, 0x3b, 0xbc, 0xab, 0x23, 0x57, 0x30, 0xa0 } } -NS_DEFINE_CID(kCoreServiceB_CID, CORE_SERVICE_B_CID); - -// {e93dadeb-a6f6-4667-bbbc-ac8c6d440b20} -#define EXT_SERVICE_B_CID \ - { 0xe93dadeb, 0xa6f6, 0x4667, \ - { 0xbb, 0xbc, 0xac, 0x8c, 0x6d, 0x44, 0x0b, 0x20 } } -NS_DEFINE_CID(kExtServiceB_CID, EXT_SERVICE_B_CID); - -nsresult execRegOrderTest(const char *aTestName, const char *aContractID, - const nsCID &aCoreCID, const nsCID &aExtCID) -{ - // Make sure the core service loaded (it won't be found using contract ID). - nsresult rv = NS_ERROR_FAILURE; - nsCOMPtr coreService = do_CreateInstance(aCoreCID, &rv); -#ifdef DEBUG_brade - if (rv) fprintf(stderr, "rv: %d (%x)\n", rv, rv); - fprintf(stderr, "coreService: %p\n", coreService.get()); -#endif - if (NS_FAILED(rv)) - { - fail("%s FAILED - cannot create core service\n", aTestName); - return rv; - } - - // Get the extension service. - nsCOMPtr extService = do_CreateInstance(aExtCID, &rv); -#ifdef DEBUG_brade - if (rv) fprintf(stderr, "rv: %d (%x)\n", rv, rv); - fprintf(stderr, "extService: %p\n", extService.get()); -#endif - if (NS_FAILED(rv)) - { - fail("%s FAILED - cannot create extension service\n", aTestName); - return rv; - } - - /* - * Get the service by contract ID and make sure it is the extension - * service (it should be, since the extension directory was registered - * after the core one). - */ - nsCOMPtr service = do_CreateInstance(aContractID, &rv); -#ifdef DEBUG_brade - if (rv) fprintf(stderr, "rv: %d (%x)\n", rv, rv); - fprintf(stderr, "service: %p\n", service.get()); -#endif - if (NS_FAILED(rv)) - { - fail("%s FAILED - cannot create service\n", aTestName); - return rv; - } - - if (service != extService) - { - fail("%s FAILED - wrong service registered\n", aTestName); - return NS_ERROR_FAILURE; - } - - passed(aTestName); - return NS_OK; -} - -nsresult TestRegular() -{ - return execRegOrderTest("TestRegular", SERVICE_A_CONTRACT_ID, - kCoreServiceA_CID, kExtServiceA_CID); -} - -nsresult TestJar() -{ - return execRegOrderTest("TestJar", SERVICE_B_CONTRACT_ID, - kCoreServiceB_CID, kExtServiceB_CID); -} - -bool TestContractFirst() -{ - nsCOMPtr r; - NS_GetComponentRegistrar(getter_AddRefs(r)); - - nsCID* cid = nullptr; - nsresult rv = r->ContractIDToCID("@mozilla.org/RegTestOrderC;1", &cid); - if (NS_FAILED(rv)) { - fail("RegTestOrderC: contract not registered"); - return false; - } - - nsCID goodcid; - goodcid.Parse("{ada15884-bb89-473c-8b50-dcfbb8447ff4}"); - - if (!goodcid.Equals(*cid)) { - fail("RegTestOrderC: CID doesn't match"); - return false; - } - - passed("RegTestOrderC"); - return true; -} - -static already_AddRefed -GetRegDirectory(const char* basename, const char* dirname, const char* leafname) -{ - nsCOMPtr f; - nsresult rv = NS_NewNativeLocalFile(nsDependentCString(basename), true, - getter_AddRefs(f)); - if (NS_FAILED(rv)) - return nullptr; - - f->AppendNative(nsDependentCString(dirname)); - if (leafname) - f->AppendNative(nsDependentCString(leafname)); - return f.forget(); -} - - - -int main(int argc, char** argv) -{ - if (argc < 2) - { - fprintf(stderr, "not enough arguments -- need registration dir path\n"); - return 1; - } - - ScopedLogging logging; - -#ifdef XP_WIN - // On Windows, convert to backslashes - size_t regPathLen = strlen(argv[1]); - char* regPath = new char[regPathLen + 1]; - for (size_t i = 0; i < regPathLen; i++) { - char curr = argv[1][i]; - regPath[i] = (curr == '/') ? '\\' : curr; - } - regPath[regPathLen] = '\0'; -#else - const char *regPath = argv[1]; -#endif - - nsCOMPtr file = - GetRegDirectory(regPath, "core", "component.manifest"); - XRE_AddManifestLocation(NS_EXTENSION_LOCATION, file); - file = GetRegDirectory(regPath, "extension", "extComponent.manifest"); - XRE_AddManifestLocation(NS_EXTENSION_LOCATION, file); - file = GetRegDirectory(regPath, "extension2.jar", nullptr); - XRE_AddJarManifestLocation(NS_EXTENSION_LOCATION, file); - ScopedXPCOM xpcom("RegistrationOrder"); - if (xpcom.failed()) - return 1; - - int rv = 0; - if (NS_FAILED(TestRegular())) - rv = 1; - - if (NS_FAILED(TestJar())) - rv = 1; - - if (!TestContractFirst()) - rv = 1; - - return rv; -} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/TestSTLWrappers.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/TestSTLWrappers.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/TestSTLWrappers.cpp 2016-11-11 02:16:43.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/TestSTLWrappers.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -#include - -#include -#ifndef mozilla_algorithm_h -# error "failed to wrap " -#endif - -#include -#ifndef mozilla_vector_h -# error "failed to wrap " -#endif - -// gcc errors out if we |try ... catch| with -fno-exceptions, but we -// can still test on windows -#ifdef _MSC_VER - // C4530 will be generated whenever try...catch is used without - // enabling exceptions. We know we don't enbale exceptions. -# pragma warning( disable : 4530 ) -# define TRY try -# define CATCH(e) catch (e) -#else -# define TRY -# define CATCH(e) if (0) -#endif - -int main() { - std::vector v; - int rv = 1; - - TRY { - // v.at(1) on empty v should abort; NOT throw an exception - - // (Do some arithmetic with result of v.at() to avoid - // compiler warnings for unused variable/result.) - rv += v.at(1) ? 1 : 2; - } CATCH(const std::out_of_range&) { - fputs("TEST-FAIL | TestSTLWrappers.cpp | caught an exception?\n", - stderr); - return 1; - } - - fputs("TEST-FAIL | TestSTLWrappers.cpp | didn't abort()?\n", - stderr); - return rv; -} diff -Nru firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/TestThreadPoolListener.cpp firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/TestThreadPoolListener.cpp --- firefox-trunk-52.0~a1~hg20161110r321971/xpcom/tests/TestThreadPoolListener.cpp 2016-11-11 02:16:43.000000000 +0000 +++ firefox-trunk-52.0~a1~hg20161113r322177/xpcom/tests/TestThreadPoolListener.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,208 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "TestHarness.h" - -#include "nsIThread.h" -#include "nsIThreadPool.h" - -#include "nsThreadUtils.h" -#include "nsXPCOMCIDInternal.h" -#include "pratom.h" -#include "prinrval.h" -#include "prmon.h" -#include "prthread.h" -#include "mozilla/Assertions.h" -#include "mozilla/Attributes.h" - -#include "mozilla/ReentrantMonitor.h" -using namespace mozilla; - -#define NUMBER_OF_THREADS 4 - -// One hour... because test boxes can be slow! -#define IDLE_THREAD_TIMEOUT 3600000 - -static nsIThread** gCreatedThreadList = nullptr; -static nsIThread** gShutDownThreadList = nullptr; - -static ReentrantMonitor* gReentrantMonitor = nullptr; - -static bool gAllRunnablesPosted = false; -static bool gAllThreadsCreated = false; -static bool gAllThreadsShutDown = false; - -class Listener final : public nsIThreadPoolListener -{ - ~Listener() {} - -public: - NS_DECL_THREADSAFE_ISUPPORTS - NS_DECL_NSITHREADPOOLLISTENER -}; - -NS_IMPL_ISUPPORTS(Listener, nsIThreadPoolListener) - -NS_IMETHODIMP -Listener::OnThreadCreated() -{ - nsCOMPtr current(do_GetCurrentThread()); - MOZ_RELEASE_ASSERT(current, "Couldn't get current thread!"); - - ReentrantMonitorAutoEnter mon(*gReentrantMonitor); - - while (!gAllRunnablesPosted) { - mon.Wait(); - } - - for (uint32_t i = 0; i < NUMBER_OF_THREADS; i++) { - nsIThread* thread = gCreatedThreadList[i]; - MOZ_RELEASE_ASSERT(thread != current, "Saw the same thread twice!"); - - if (!thread) { - gCreatedThreadList[i] = current; - if (i == (NUMBER_OF_THREADS - 1)) { - gAllThreadsCreated = true; - mon.NotifyAll(); - } - return NS_OK; - } - } - - MOZ_RELEASE_ASSERT(false, "Too many threads!"); - return NS_ERROR_FAILURE; -} - -NS_IMETHODIMP -Listener::OnThreadShuttingDown() -{ - nsCOMPtr current(do_GetCurrentThread()); - MOZ_RELEASE_ASSERT(current, "Couldn't get current thread!"); - - ReentrantMonitorAutoEnter mon(*gReentrantMonitor); - - for (uint32_t i = 0; i < NUMBER_OF_THREADS; i++) { - nsIThread* thread = gShutDownThreadList[i]; - MOZ_RELEASE_ASSERT(thread != current, "Saw the same thread twice!"); - - if (!thread) { - gShutDownThreadList[i] = current; - if (i == (NUMBER_OF_THREADS - 1)) { - gAllThreadsShutDown = true; - mon.NotifyAll(); - } - return NS_OK; - } - } - - MOZ_RELEASE_ASSERT(false, "Too many threads!"); - return NS_ERROR_FAILURE; -} - -class AutoCreateAndDestroyReentrantMonitor -{ -public: - explicit AutoCreateAndDestroyReentrantMonitor(ReentrantMonitor** aReentrantMonitorPtr) - : mReentrantMonitorPtr(aReentrantMonitorPtr) { - *aReentrantMonitorPtr = new ReentrantMonitor("TestThreadPoolListener::AutoMon"); - MOZ_RELEASE_ASSERT(*aReentrantMonitorPtr, "Out of memory!"); - } - - ~AutoCreateAndDestroyReentrantMonitor() { - delete *mReentrantMonitorPtr; - *mReentrantMonitorPtr = nullptr; - } - -private: - ReentrantMonitor** mReentrantMonitorPtr; -}; - -int main(int argc, char** argv) -{ - ScopedXPCOM xpcom("ThreadPoolListener"); - NS_ENSURE_FALSE(xpcom.failed(), 1); - - nsIThread* createdThreadList[NUMBER_OF_THREADS] = { nullptr }; - gCreatedThreadList = createdThreadList; - - nsIThread* shutDownThreadList[NUMBER_OF_THREADS] = { nullptr }; - gShutDownThreadList = shutDownThreadList; - - AutoCreateAndDestroyReentrantMonitor newMon(&gReentrantMonitor); - NS_ENSURE_TRUE(gReentrantMonitor, 1); - - nsresult rv; - - nsCOMPtr pool = - do_CreateInstance(NS_THREADPOOL_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, 1); - - rv = pool->SetThreadLimit(NUMBER_OF_THREADS); - NS_ENSURE_SUCCESS(rv, 1); - - rv = pool->SetIdleThreadLimit(NUMBER_OF_THREADS); - NS_ENSURE_SUCCESS(rv, 1); - - rv = pool->SetIdleThreadTimeout(IDLE_THREAD_TIMEOUT); - NS_ENSURE_SUCCESS(rv, 1); - - nsCOMPtr listener = new Listener(); - NS_ENSURE_TRUE(listener, 1); - - rv = pool->SetListener(listener); - NS_ENSURE_SUCCESS(rv, 1); - - { - ReentrantMonitorAutoEnter mon(*gReentrantMonitor); - - for (uint32_t i = 0; i < NUMBER_OF_THREADS; i++) { - nsCOMPtr runnable = new Runnable(); - NS_ENSURE_TRUE(runnable, 1); - - rv = pool->Dispatch(runnable, NS_DISPATCH_NORMAL); - NS_ENSURE_SUCCESS(rv, 1); - } - - gAllRunnablesPosted = true; - mon.NotifyAll(); - } - - { - ReentrantMonitorAutoEnter mon(*gReentrantMonitor); - while (!gAllThreadsCreated) { - mon.Wait(); - } - } - - rv = pool->Shutdown(); - NS_ENSURE_SUCCESS(rv, 1); - - { - ReentrantMonitorAutoEnter mon(*gReentrantMonitor); - while (!gAllThreadsShutDown) { - mon.Wait(); - } - } - - for (uint32_t i = 0; i < NUMBER_OF_THREADS; i++) { - nsIThread* created = gCreatedThreadList[i]; - NS_ENSURE_TRUE(created, 1); - - bool match = false; - for (uint32_t j = 0; j < NUMBER_OF_THREADS; j++) { - nsIThread* destroyed = gShutDownThreadList[j]; - NS_ENSURE_TRUE(destroyed, 1); - - if (destroyed == created) { - match = true; - break; - } - } - - NS_ENSURE_TRUE(match, 1); - } - - return 0; -}