Merge autoland to mozilla-central. a=merge

This commit is contained in:
shindli 2018-02-01 00:30:10 +02:00
commit 91bc2053a8
275 changed files with 7627 additions and 44573 deletions

View File

@ -1 +0,0 @@
PURGECACHES_DIRS = $(DIST)/bin/browser

View File

@ -19,6 +19,14 @@ add_task(async function() {
Components.interfaces.nsIDOMWindowUtils.MODIFIER_META :
Components.interfaces.nsIDOMWindowUtils.MODIFIER_CONTROL;
function sendKey(message) {
BrowserTestUtils.synthesizeKey(message.data.key,
{code: message.data.code, accelKey: true},
browser);
}
browser.messageManager.addMessageListener("Test:SendKey", sendKey);
// On windows, HTML clipboard includes extra data.
// The values are from widget/windows/nsDataObj.cpp.
const htmlPrefix = (navigator.platform.indexOf("Win") >= 0) ? "<html><body>\n<!--StartFragment-->" : "";
@ -29,16 +37,6 @@ add_task(async function() {
var main = doc.getElementById("main");
main.focus();
const utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
function sendKey(key) {
if (utils.sendKeyEvent("keydown", key, 0, arg.modifier)) {
utils.sendKeyEvent("keypress", key, key.charCodeAt(0), arg.modifier);
}
utils.sendKeyEvent("keyup", key, 0, arg.modifier);
}
// Select an area of the text.
let selection = doc.getSelection();
selection.modify("move", "left", "line");
@ -56,7 +54,7 @@ add_task(async function() {
resolve();
}, true);
sendKey("c");
sendAsyncMessage("Test:SendKey", { key: "c", code: "KeyC" });
});
selection.modify("move", "right", "line");
@ -74,7 +72,8 @@ add_task(async function() {
Assert.equal(clipboardData.getData("text/plain"), "t Bold", "text/plain value");
resolve();
}, true);
sendKey("v");
sendAsyncMessage("Test:SendKey", {key: "v", code: "KeyV"});
});
Assert.equal(main.innerHTML, "Test <b>Bold</b> After Textt <b>Bold</b>", "Copy and paste html");
@ -92,7 +91,8 @@ add_task(async function() {
event.preventDefault();
resolve();
}, true);
sendKey("x");
sendAsyncMessage("Test:SendKey", {key: "x", code: "KeyX"});
});
selection.modify("move", "left", "line");
@ -110,7 +110,8 @@ add_task(async function() {
Assert.equal(clipboardData.getData("text/plain"), "Some text", "text/plain value 2");
resolve();
}, true);
sendKey("v");
sendAsyncMessage("Test:SendKey", {key: "v", code: "KeyV"});
});
Assert.equal(main.innerHTML, "<i>Italic</i> Test <b>Bold</b> After<b></b>",
@ -154,13 +155,7 @@ add_task(async function() {
resolve();
}, true);
const utils = content.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
if (utils.sendKeyEvent("keydown", "v", 0, arg.modifier)) {
utils.sendKeyEvent("keypress", "v", "v".charCodeAt(0), arg.modifier);
}
utils.sendKeyEvent("keyup", "v", 0, arg.modifier);
sendAsyncMessage("Test:SendKey", {key: "v", code: "KeyV"});
});
// The new content should now include an image.
@ -169,6 +164,8 @@ add_task(async function() {
"Test <b>Bold</b> After<b></b>", "Paste after copy image");
});
browser.messageManager.removeMessageListener("Test:SendKey", sendKey);
gBrowser.removeCurrentTab();
});

View File

@ -5,7 +5,17 @@
add_task(async function testExecuteScript() {
let {MessageChannel} = ChromeUtils.import("resource://gre/modules/MessageChannel.jsm", {});
let messageManagersSize = MessageChannel.messageManagers.size;
// When the first extension is started, ProxyMessenger.init adds MessageChannel
// listeners for Services.mm and Services.ppmm, and they are never unsubscribed.
// We have to exclude them after the extension has been unloaded to get an accurate
// test.
function getMessageManagersSize(messageManagers) {
return Array.from(messageManagers).filter(([mm]) => {
return !([Services.mm, Services.ppmm].includes(mm));
}).length;
}
let messageManagersSize = getMessageManagersSize(MessageChannel.messageManagers);
let responseManagersSize = MessageChannel.responseManagers.size;
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "http://mochi.test:8888/", true);
@ -31,14 +41,14 @@ add_task(async function testExecuteScript() {
},
},
{
background: "rgb(42, 42, 42)",
background: "rgb(43, 43, 43)",
foreground: "rgb(0, 113, 4)",
promise: () => {
return browser.tabs.insertCSS({
code: "* { background: rgb(100, 100, 100) !important }",
cssOrigin: "author",
}).then(r => browser.tabs.insertCSS({
code: "* { background: rgb(42, 42, 42) !important }",
code: "* { background: rgb(43, 43, 43) !important }",
cssOrigin: "author",
}));
},
@ -52,7 +62,7 @@ add_task(async function testExecuteScript() {
code: "* { background: rgb(100, 100, 100) !important }",
cssOrigin: "user",
}).then(r => browser.tabs.insertCSS({
code: "* { background: rgb(42, 42, 42) !important }",
code: "* { background: rgb(44, 44, 44) !important }",
cssOrigin: "author",
}));
},
@ -81,7 +91,7 @@ add_task(async function testExecuteScript() {
browser.test.notifyPass("insertCSS");
} catch (e) {
browser.test.fail(`Error: ${e} :: ${e.stack}`);
browser.test.notifyFailure("insertCSS");
browser.test.notifyFail("insertCSS");
}
}
@ -107,7 +117,52 @@ add_task(async function testExecuteScript() {
// Make sure that we're not holding on to references to closed message
// managers.
is(MessageChannel.messageManagers.size, messageManagersSize, "Message manager count");
is(getMessageManagersSize(MessageChannel.messageManagers), messageManagersSize,
"Message manager count");
is(MessageChannel.responseManagers.size, responseManagersSize, "Response manager count");
is(MessageChannel.pendingResponses.size, 0, "Pending response count");
});
add_task(async function testInsertCSS_cleanup() {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "http://mochi.test:8888/", true);
async function background() {
await browser.tabs.insertCSS({code: "* { background: rgb(42, 42, 42) }"});
await browser.tabs.insertCSS({file: "customize_fg_color.css"});
browser.test.notifyPass("insertCSS");
}
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["http://mochi.test/"],
},
background,
files: {
"customize_fg_color.css": `* { color: rgb(255, 0, 0) }`,
},
});
await extension.startup();
await extension.awaitFinish("insertCSS");
const getTabContentComputedStyle = async () => {
let computedStyle = content.getComputedStyle(content.document.body);
return [computedStyle.backgroundColor, computedStyle.color];
};
const appliedStyles = await ContentTask.spawn(tab.linkedBrowser, null, getTabContentComputedStyle);
is(appliedStyles[0], "rgb(42, 42, 42)", "The injected CSS code has been applied as expected");
is(appliedStyles[1], "rgb(255, 0, 0)", "The injected CSS file has been applied as expected");
await extension.unload();
const unloadedStyles = await ContentTask.spawn(tab.linkedBrowser, null, getTabContentComputedStyle);
is(unloadedStyles[0], "rgba(0, 0, 0, 0)", "The injected CSS code has been removed as expected");
is(unloadedStyles[1], "rgb(0, 0, 0)", "The injected CSS file has been removed as expected");
await BrowserTestUtils.removeTab(tab);
});

View File

@ -91,7 +91,7 @@ add_task(async function testExecuteScript() {
browser.test.notifyPass("removeCSS");
} catch (e) {
browser.test.fail(`Error: ${e} :: ${e.stack}`);
browser.test.notifyFailure("removeCSS");
browser.test.notifyFail("removeCSS");
}
}

View File

@ -13,6 +13,8 @@ ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
Cu.importGlobalProperties(["fetch"]);
XPCOMUtils.defineLazyServiceGetter(this, "WindowsUIUtils", "@mozilla.org/windows-ui-utils;1", "nsIWindowsUIUtils");
XPCOMUtils.defineLazyGetter(this, "WeaveService", () =>
Cc["@mozilla.org/weave/service;1"].getService().wrappedJSObject

View File

@ -532,7 +532,8 @@ var PlacesOrganizer = {
let fpCallback = function fpCallback_done(aResult) {
if (aResult != Ci.nsIFilePicker.returnCancel) {
// There is no OS.File version of the filepicker yet (Bug 937812).
PlacesBackups.saveBookmarksToJSONFile(fp.file.path);
PlacesBackups.saveBookmarksToJSONFile(fp.file.path)
.catch(Cu.reportError);
}
};

View File

@ -103,7 +103,7 @@ add_task(async function test_nested() {
const FORM_DATA = {
children: [{
xpath: {"/xhtml:html/xhtml:body/xhtml:input": "M"},
xpath: {"/xhtml:html/xhtml:body/xhtml:input": "m"},
url: "data:text/html;charset=utf-8,<input%20autofocus=true>"
}]
};
@ -114,7 +114,7 @@ add_task(async function test_nested() {
await promiseBrowserLoaded(browser);
// Modify the input field's value.
await sendMessage(browser, "ss-test:sendKeyEvent", {key: "m", frame: 0});
await BrowserTestUtils.synthesizeKey("m", {code: "KeyM"}, browser);
// Remove the tab and check that we stored form data correctly.
await promiseRemoveTab(tab);
@ -151,7 +151,7 @@ add_task(async function test_design_mode() {
await promiseBrowserLoaded(browser);
// Modify the document content.
await sendMessage(browser, "ss-test:sendKeyEvent", {key: "m"});
await BrowserTestUtils.synthesizeKey("m", {code: "KeyM"}, browser);
// Close and restore the tab.
await promiseRemoveTab(tab);
@ -161,7 +161,7 @@ add_task(async function test_design_mode() {
// Check that the innerHTML value was restored.
let html = await getInnerHTML(browser);
let expected = "<h1>Mmozilla</h1><script>document.designMode='on'</script>";
let expected = "<h1>mmozilla</h1><script>document.designMode='on'</script>";
is(html, expected, "editable document has been restored correctly");
// Close and restore the tab.
@ -172,7 +172,7 @@ add_task(async function test_design_mode() {
// Check that the innerHTML value was restored.
html = await getInnerHTML(browser);
expected = "<h1>Mmozilla</h1><script>document.designMode='on'</script>";
expected = "<h1>mmozilla</h1><script>document.designMode='on'</script>";
is(html, expected, "editable document has been restored correctly");
// Cleanup.

View File

@ -50,23 +50,6 @@ function defineListener(type, cb) {
});
}
defineListener("sendKeyEvent", function(data) {
let frame = content;
if (data.hasOwnProperty("frame")) {
frame = content.frames[data.frame];
}
let ifreq = frame.QueryInterface(Ci.nsIInterfaceRequestor);
let utils = ifreq.getInterface(Ci.nsIDOMWindowUtils);
let keyCode = data.key.charCodeAt(0);
let charCode = Ci.nsIDOMKeyEvent.DOM_VK_A + keyCode - "a".charCodeAt(0);
utils.sendKeyEvent("keydown", keyCode, charCode, null);
utils.sendKeyEvent("keypress", keyCode, charCode, null);
utils.sendKeyEvent("keyup", keyCode, charCode, null);
});
defineListener("getInnerHTML", function(data) {
return queryElement(data).innerHTML;
});

View File

@ -1,4 +1,5 @@
/* import-globals-from ../../../../../testing/mochitest/tests/SimpleTest/SimpleTest.js */
/* import-globals-from ../../../../../testing/mochitest/tests/SimpleTest/EventUtils.js */
/* import-globals-from ../../../../../toolkit/components/satchel/test/satchel_common.js */
/* eslint-disable no-unused-vars */
@ -117,8 +118,8 @@ function triggerAutofillAndCheckProfile(profile) {
promises.push(checkFieldAutofilled);
}
// Press return key and trigger form autofill.
doKey("return");
// Press Enter key and trigger form autofill.
synthesizeKey("KEY_Enter", {code: "Enter"});
return Promise.all(promises);
}
@ -242,10 +243,10 @@ function initPopupListener() {
async function triggerPopupAndHoverItem(fieldSelector, selectIndex) {
await focusAndWaitForFieldsIdentified(fieldSelector);
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
for (let i = 0; i <= selectIndex; i++) {
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
}
await notifySelectedIndex(selectIndex);
}

View File

@ -4,6 +4,7 @@
<meta charset="utf-8">
<title>Test basic autofill</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
<script type="text/javascript" src="formautofill_common.js"></script>
<script type="text/javascript" src="satchel_common.js"></script>
@ -38,7 +39,7 @@ async function setupAddressStorage() {
add_task(async function check_autocomplete_on_autofocus_field() {
await setupAddressStorage();
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(MOCK_STORAGE.map(address =>
JSON.stringify({primary: address.organization, secondary: address["street-address"]})

View File

@ -4,6 +4,7 @@
<meta charset="utf-8">
<title>Test basic autofill</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
<script type="text/javascript" src="formautofill_common.js"></script>
<script type="text/javascript" src="satchel_common.js"></script>
@ -53,7 +54,7 @@ add_task(async function history_only_menu_checking() {
await setupFormHistory();
await setInput("#tel", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(["+1234567890"], false);
});
@ -66,7 +67,7 @@ add_task(async function all_saved_fields_less_than_threshold() {
});
await setInput("#email", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(["foo@mozilla.com"], false);
@ -78,7 +79,7 @@ add_task(async function check_menu_when_both_existed() {
await setupAddressStorage();
await setInput("#organization", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(MOCK_STORAGE.map(address =>
JSON.stringify({
@ -88,7 +89,7 @@ add_task(async function check_menu_when_both_existed() {
));
await setInput("#street-address", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(MOCK_STORAGE.map(address =>
JSON.stringify({
@ -98,7 +99,7 @@ add_task(async function check_menu_when_both_existed() {
));
await setInput("#tel", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(MOCK_STORAGE.map(address =>
JSON.stringify({
@ -108,7 +109,7 @@ add_task(async function check_menu_when_both_existed() {
));
await setInput("#address-line1", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(MOCK_STORAGE.map(address =>
JSON.stringify({
@ -121,7 +122,7 @@ add_task(async function check_menu_when_both_existed() {
// Display history search result if no matched data in addresses.
add_task(async function check_fallback_for_mismatched_field() {
await setInput("#email", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(["foo@mozilla.com"], false);
});
@ -133,7 +134,7 @@ add_task(async function check_search_result_for_pref_off() {
});
await setInput("#tel", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(["+1234567890"], false);
@ -143,7 +144,7 @@ add_task(async function check_search_result_for_pref_off() {
// Autofill the address from dropdown menu.
add_task(async function check_fields_after_form_autofill() {
const focusedInput = await setInput("#organization", "Moz");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(MOCK_STORAGE.map(address =>
JSON.stringify({
@ -151,16 +152,16 @@ add_task(async function check_fields_after_form_autofill() {
secondary: FormAutofillUtils.toOneLineAddress(address["street-address"]),
})
).slice(1));
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await triggerAutofillAndCheckProfile(MOCK_STORAGE[1]);
doKey("escape");
synthesizeKey("KEY_Escape", {code: "Escape"});
is(focusedInput.value, "Mozilla", "Filled field shouldn't be reverted by ESC key");
});
// Fallback to history search after autofill address.
add_task(async function check_fallback_after_form_autofill() {
await setInput("#tel", "", true);
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(["+1234567890"], false);
});
@ -170,7 +171,7 @@ add_task(async function check_form_autofill_resume() {
document.querySelector("#tel").blur();
document.querySelector("#form1").reset();
await setInput("#tel", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(MOCK_STORAGE.map(address =>
JSON.stringify({

View File

@ -4,6 +4,7 @@
<meta charset="utf-8">
<title>Test basic autofill</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
<script type="text/javascript" src="formautofill_common.js"></script>
<script type="text/javascript" src="satchel_common.js"></script>
@ -61,7 +62,7 @@ add_task(async function history_only_menu_checking() {
await setupFormHistory();
await setInput("#cc-exp-year", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(["2023"], false);
});
@ -71,7 +72,7 @@ add_task(async function all_saved_fields_less_than_threshold() {
await addCreditCard(reducedMockRecord);
await setInput("#cc-name", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries([reducedMockRecord].map(patchRecordCCNumber).map(cc => JSON.stringify({
primary: cc["cc-name"],
@ -86,7 +87,7 @@ add_task(async function check_menu_when_both_existed() {
await setupCreditCardStorage();
await setInput("#cc-number", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(MOCK_STORAGE.map(patchRecordCCNumber).map(cc => JSON.stringify({
primaryAffix: cc.ccNumberFmt.affix,
@ -95,7 +96,7 @@ add_task(async function check_menu_when_both_existed() {
})));
await setInput("#cc-name", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(MOCK_STORAGE.map(patchRecordCCNumber).map(cc => JSON.stringify({
primary: cc["cc-name"],
@ -103,7 +104,7 @@ add_task(async function check_menu_when_both_existed() {
})));
await setInput("#cc-exp-year", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(MOCK_STORAGE.map(patchRecordCCNumber).map(cc => JSON.stringify({
primary: cc["cc-exp-year"],
@ -111,7 +112,7 @@ add_task(async function check_menu_when_both_existed() {
})));
await setInput("#cc-exp-month", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(MOCK_STORAGE.map(patchRecordCCNumber).map(cc => JSON.stringify({
primary: cc["cc-exp-month"],
@ -126,7 +127,7 @@ add_task(async function check_fallback_for_mismatched_field() {
await addCreditCard(reducedMockRecord);
await setInput("#cc-exp-year", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(["2023"], false);
@ -142,7 +143,7 @@ add_task(async function check_search_result_for_pref_off() {
});
await setInput("#cc-name", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(["John Smith"], false);
@ -153,21 +154,21 @@ add_task(async function check_search_result_for_pref_off() {
add_task(async function check_fields_after_form_autofill() {
await setInput("#cc-exp-year", 202);
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(MOCK_STORAGE.slice(1).map(patchRecordCCNumber).map(cc => JSON.stringify({
primary: cc["cc-exp-year"],
secondary: cc.ccNumberFmt.affix + cc.ccNumberFmt.label,
})));
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await triggerAutofillAndCheckProfile(MOCK_STORAGE[1]);
});
// Fallback to history search after autofill address.
add_task(async function check_fallback_after_form_autofill() {
await setInput("#cc-name", "", true);
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(["John Smith"], false);
});
@ -178,7 +179,7 @@ add_task(async function check_form_autofill_resume() {
document.querySelector("#form1").reset();
await setInput("#cc-name", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(MOCK_STORAGE.map(patchRecordCCNumber).map(cc => JSON.stringify({
primary: cc["cc-name"],

View File

@ -4,6 +4,7 @@
<meta charset="utf-8">
<title>Test form autofill - clear form button</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
<script type="text/javascript" src="formautofill_common.js"></script>
<script type="text/javascript" src="satchel_common.js"></script>
@ -70,7 +71,7 @@ add_task(async function simple_clear() {
await triggerAutofillAndCheckProfile(MOCK_ADDR_STORAGE[0]);
await triggerPopupAndHoverItem("#tel", 0);
doKey("return");
synthesizeKey("KEY_Enter", {code: "Enter"});
checkIsFormCleared();
});
@ -79,7 +80,7 @@ add_task(async function clear_adapted_record() {
await triggerAutofillAndCheckProfile(MOCK_ADDR_STORAGE[0]);
await triggerPopupAndHoverItem("#street-address", 0);
doKey("return");
synthesizeKey("KEY_Enter", {code: "Enter"});
checkIsFormCleared();
});
@ -90,7 +91,7 @@ add_task(async function clear_modified_form() {
await setInput("#tel", "+1111111111", true);
await triggerPopupAndHoverItem("#street-address", 0);
doKey("return");
synthesizeKey("KEY_Enter", {code: "Enter"});
checkIsFormCleared({tel: "+1111111111"});
});
@ -102,7 +103,7 @@ add_task(async function clear_distinct_section() {
await triggerPopupAndHoverItem("#organization", 0);
await triggerAutofillAndCheckProfile(MOCK_ADDR_STORAGE[0]);
await triggerPopupAndHoverItem("#street-address", 0);
doKey("return");
synthesizeKey("KEY_Enter", {code: "Enter"});
for (const [id, val] of Object.entries(MOCK_CC_STORAGE[0])) {
const element = document.getElementById(id);
@ -114,7 +115,7 @@ add_task(async function clear_distinct_section() {
}
await triggerPopupAndHoverItem("#cc-name", 0);
doKey("return");
synthesizeKey("KEY_Enter", {code: "Enter"});
checkIsFormCleared();
});

View File

@ -4,6 +4,7 @@
<meta charset="utf-8">
<title>Test basic autofill</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
<script type="text/javascript" src="formautofill_common.js"></script>
<script type="text/javascript" src="satchel_common.js"></script>
@ -50,12 +51,12 @@ add_task(async function history_only_menu_checking() {
await setupFormHistory();
await setInput("#cc-number", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(["1234000056780000"], false);
await setInput("#cc-name", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await notExpectPopup();
});
@ -64,7 +65,7 @@ add_task(async function check_menu_when_both_with_autocomplete_off() {
await setupCreditCardStorage();
await setInput("#cc-number", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(MOCK_STORAGE.map(patchRecordCCNumber).map(cc => JSON.stringify({
primaryAffix: cc.ccNumberFmt.affix,
@ -73,7 +74,7 @@ add_task(async function check_menu_when_both_with_autocomplete_off() {
})));
await setInput("#cc-name", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(MOCK_STORAGE.map(patchRecordCCNumber).map(cc => JSON.stringify({
primary: cc["cc-name"],

View File

@ -4,6 +4,7 @@
<meta charset="utf-8">
<title>Test basic autofill</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
<script type="text/javascript" src="formautofill_common.js"></script>
<script type="text/javascript" src="satchel_common.js"></script>
@ -49,7 +50,7 @@ function addInputField(form, className) {
async function checkFormChangeHappened(formId) {
info("expecting form changed");
await focusAndWaitForFieldsIdentified(`#${formId} input[name=tel]`);
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(MOCK_STORAGE.map(address =>
JSON.stringify({primary: address.tel, secondary: address.name})
@ -59,7 +60,7 @@ async function checkFormChangeHappened(formId) {
addInputField(document.querySelector(`#${formId}`), "address-level2");
await focusAndWaitForFieldsIdentified(`#${formId} input[name=name]`);
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(MOCK_STORAGE.map(address =>
JSON.stringify({primary: address.name, secondary: address["address-level2"]})
@ -70,7 +71,7 @@ async function checkFormChangeHappened(formId) {
addInputField(document.querySelector(`#${formId}`), "address-level2");
await focusAndWaitForFieldsIdentified(`#${formId} input[name=address-level2]`, true);
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(MOCK_STORAGE.map(address =>
JSON.stringify({primary: address["address-level2"], secondary: address.name})

View File

@ -4,6 +4,7 @@
<meta charset="utf-8">
<title>Test form autofill - preview and highlight</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
<script type="text/javascript" src="formautofill_common.js"></script>
<script type="text/javascript" src="satchel_common.js"></script>
@ -54,22 +55,22 @@ add_task(async function setup_storage() {
add_task(async function check_preview() {
const focusedInput = await setInput("#organization", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkFormFieldsStyle(null);
for (let i = 0; i < MOCK_STORAGE.length; i++) {
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await notifySelectedIndex(i);
checkFormFieldsStyle(MOCK_STORAGE[i]);
}
// Navigate to the footer
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await notifySelectedIndex(MOCK_STORAGE.length);
checkFormFieldsStyle(null);
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await notifySelectedIndex(-1);
checkFormFieldsStyle(null);

View File

@ -4,6 +4,7 @@
<meta charset="utf-8">
<title>Test basic autofill</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
<script type="text/javascript" src="formautofill_common.js"></script>
<script type="text/javascript" src="satchel_common.js"></script>
@ -88,7 +89,7 @@ function checkFormFilled(selector, address) {
promises.push(...checkElementFilled(element, converted));
}
}
doKey("return");
synthesizeKey("KEY_Enter", {code: "Enter"});
return Promise.all(promises);
}
@ -105,19 +106,19 @@ add_task(async function autofill_with_level1_code() {
await setupAddressStorage();
await setInput("#organization-en", "Mozilla Toronto");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
// Replace address level 1 code with full name in English for test result
let result = Object.assign({}, MOCK_STORAGE[1], {"address-level1": "Ontario"});
await checkFormFilled("#form-en", result);
await setInput("#organization-fr", "Mozilla Vancouver");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
// Replace address level 1 code with full name in French for test result
result = Object.assign({}, MOCK_STORAGE[0], {"address-level1": "Colombie-Britannique"});
await checkFormFilled("#form-fr", result);
@ -128,19 +129,19 @@ add_task(async function autofill_with_level1_code() {
// Autofill the address with address level 1 full name.
add_task(async function autofill_with_level1_full_name() {
await setInput("#organization-en", "ExpoCité");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
// Replace address level 1 code with full name in French for test result
let result = Object.assign({}, MOCK_STORAGE[3], {"address-level1": "Quebec"});
await checkFormFilled("#form-en", result);
await setInput("#organization-fr", "Prince of Wales Northern Heritage");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
// Replace address level 1 code with full name in English for test result
result = Object.assign({}, MOCK_STORAGE[2], {"address-level1": "Territoires du Nord-Ouest"});
await checkFormFilled("#form-fr", result);

View File

@ -33,19 +33,19 @@ add_task(async function setupStorage() {
add_task(async function check_switch_form_popup() {
await setInput("#additional-name", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
// We need an intentional wait here before switching form.
await sleep();
await setInput("#organization", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
const {open: popupOpen} = await getPopupState();
is(popupOpen, false);
await sleep();
await setInput("#given-name", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
});

View File

@ -4,6 +4,7 @@
<meta charset="utf-8">
<title>Test autofill submit</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
<script type="text/javascript" src="formautofill_common.js"></script>
<script type="text/javascript" src="satchel_common.js"></script>
@ -72,7 +73,7 @@ add_task(async function check_storage_after_another_address_submitted() {
ok(matching, "New address saved as expected");
await setInput("#organization", "");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
checkMenuEntries(addressesInMenu.map(address =>
JSON.stringify({primary: address.organization, secondary: address["street-address"]})
@ -107,10 +108,10 @@ add_task(async function check_storage_after_form_submitted() {
TEST_ADDRESSES[1].country = "US";
await setInput("#organization", "Moz");
doKey("down");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
await expectPopup();
doKey("down");
doKey("return");
synthesizeKey("KEY_ArrowDown", {code: "ArrowDown"});
synthesizeKey("KEY_Enter", {code: "Enter"});
clickOnElement("input[type=submit]");
let expectedAddresses = TEST_ADDRESSES.slice(0);

View File

@ -694,7 +694,6 @@
#endif
@RESPATH@/res/fonts/*
@RESPATH@/res/dtd/*
@RESPATH@/res/html/*
@RESPATH@/res/language.properties
#ifdef XP_MACOSX
@RESPATH@/res/MainMenu.nib/

View File

@ -119,6 +119,8 @@ this.SchedulePressure = {
map.delete(window);
}
}
TelemetryStopwatch.cancel("FX_SCHEDULE_PRESSURE_IDLE_SAMPLE_MS", window);
removeFromMapAndCancelTimeout(this._setTimeoutWeakMap, window.clearTimeout);
removeFromMapAndCancelTimeout(this._idleCallbackWeakMap, window.cancelIdleCallback);
removeFromMapAndCancelTimeout(this._telemetryCallbackWeakMap, window.cancelIdleCallback);

View File

@ -56,8 +56,10 @@
#cookiesChildren::-moz-tree-image(domainCol) {
width: 16px;
height: 16px;
margin: 0px 2px;
margin: 0 2px;
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
-moz-context-properties: fill;
fill: currentColor;
}
#linksOpenInBox {

View File

@ -81,6 +81,8 @@ treechildren::-moz-tree-image(noicon) {
treechildren::-moz-tree-image(noicon) {
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
-moz-context-properties: fill;
fill: currentColor;
}
treechildren::-moz-tree-image(container, noicon) {
list-style-image: url("chrome://browser/skin/aboutSessionRestore-window-icon.png");

View File

@ -27,6 +27,8 @@ treechildren::-moz-tree-image(noicon) {
treechildren::-moz-tree-image(noicon) {
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
-moz-context-properties: fill;
fill: currentColor;
}
treechildren::-moz-tree-image(container, noicon) {
list-style-image: url("chrome://browser/skin/aboutSessionRestore-window-icon.png");

View File

@ -1121,6 +1121,8 @@ menuitem.panel-subview-footer@menuStateActive@,
#PanelUI-remotetabs-tabslist > toolbarbutton[itemtype="tab"],
#PanelUI-historyItems > toolbarbutton {
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
-moz-context-properties: fill;
fill: currentColor;
}
#appMenu-fxa-avatar,

View File

@ -2,6 +2,12 @@
* 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/. */
treechildren:-moz-tree-image {
-moz-context-properties: fill, fill-opacity;
fill: -moz-FieldText;
fill-opacity: 0.7;
}
treechildren::-moz-tree-image(title) {
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
padding-inline-end: 2px;
@ -10,12 +16,6 @@ treechildren::-moz-tree-image(title) {
height: 16px;
}
treechildren:-moz-tree-image {
-moz-context-properties: fill, fill-opacity;
fill: -moz-FieldText;
fill-opacity: 0.7;
}
treechildren::-moz-tree-image(title, livemarkItem) {
list-style-image: url("chrome://browser/skin/places/livemark-item.png");
-moz-image-region: rect(0px, 16px, 16px, 0px);

View File

@ -6,6 +6,8 @@
width: 16px;
height: 16px;
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
-moz-context-properties: fill;
fill: currentColor;
}
/**

View File

@ -110,6 +110,8 @@ body {
.item.tab > .item-title-container > .item-icon-container {
background-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
-moz-context-properties: fill;
fill: currentColor;
}
.item-icon-container {

View File

@ -233,9 +233,6 @@ tabbrowser {
.tab-icon-image {
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
}
.tab-icon-image[src^="chrome://"] {
-moz-context-properties: fill;
fill: currentColor;
}
@ -703,6 +700,8 @@ tabbrowser {
.alltabs-item > .menu-iconic-left > .menu-iconic-icon {
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
-moz-context-properties: fill;
fill: currentColor;
}
.alltabs-item[busy] > .menu-iconic-left > .menu-iconic-icon {

View File

@ -63,11 +63,13 @@
width: 16px;
height: 16px;
margin: 0 2px;
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg") !important;
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.svg");
-moz-context-properties: fill;
fill: currentColor;
}
#cookiesChildren::-moz-tree-image(domainCol, container) {
list-style-image: url("chrome://global/skin/icons/folder-item.png") !important;
list-style-image: url("chrome://global/skin/icons/folder-item.png");
-moz-image-region: rect(0, 32px, 16px, 16px);
}

View File

@ -179,12 +179,6 @@ endif
TAR_CREATE_FLAGS = -chf
#
# Personal makefile customizations go in these optional make include files.
#
MY_CONFIG := $(DEPTH)/config/myconfig.mk
MY_RULES := $(DEPTH)/config/myrules.mk
#
# Default command macros; can be overridden in <arch>.mk.
#
@ -296,11 +290,7 @@ endif
endif
endif
#
# Include any personal overrides the user might think are needed.
#
-include $(topsrcdir)/$(MOZ_BUILD_APP)/app-config.mk
-include $(MY_CONFIG)
######################################################################

View File

@ -1341,23 +1341,6 @@ ifneq (,$(MDDEPEND_FILES))
-include $(MDDEPEND_FILES)
endif
#############################################################################
-include $(topsrcdir)/$(MOZ_BUILD_APP)/app-rules.mk
-include $(MY_RULES)
#
# Generate Emacs tags in a file named TAGS if ETAGS was set in $(MY_CONFIG)
# or in $(MY_RULES)
#
ifdef ETAGS
ifneq ($(CSRCS)$(CPPSRCS)$(HEADERS),)
all:: TAGS
TAGS:: $(CSRCS) $(CPPSRCS) $(HEADERS)
$(ETAGS) $(CSRCS) $(CPPSRCS) $(HEADERS)
endif
endif
################################################################################
# Install/copy rules
#
@ -1586,15 +1569,6 @@ CHECK_FROZEN_VARIABLES = $(foreach var,$(FREEZE_VARIABLES), \
libs export::
$(CHECK_FROZEN_VARIABLES)
PURGECACHES_DIRS ?= $(DIST)/bin
PURGECACHES_FILES = $(addsuffix /.purgecaches,$(PURGECACHES_DIRS))
default all:: $(PURGECACHES_FILES)
$(PURGECACHES_FILES):
if test -d $(@D) ; then touch $@ ; fi
.DEFAULT_GOAL := $(or $(OVERRIDE_DEFAULT_GOAL),default)
#############################################################################

File diff suppressed because it is too large Load Diff

View File

@ -123,9 +123,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.21.0"
#define SQLITE_VERSION_NUMBER 3021000
#define SQLITE_SOURCE_ID "2017-10-24 18:55:49 1a584e499906b5c87ec7d43d4abce641fdf017c42125b083109bc77c4de48827"
#define SQLITE_VERSION "3.22.0"
#define SQLITE_VERSION_NUMBER 3022000
#define SQLITE_SOURCE_ID "2018-01-22 18:45:57 0c55d179733b46d8d0ba4d88e01a25e10677046ee3da1d5b1581e86726f2171d"
/*
** CAPI3REF: Run-Time Library Version Numbers
@ -470,6 +470,8 @@ SQLITE_API int sqlite3_exec(
** the most recent error can be obtained using
** [sqlite3_extended_errcode()].
*/
#define SQLITE_ERROR_MISSING_COLLSEQ (SQLITE_ERROR | (1<<8))
#define SQLITE_ERROR_RETRY (SQLITE_ERROR | (2<<8))
#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8))
@ -513,6 +515,8 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
#define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8))
#define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5<<8))
#define SQLITE_READONLY_DIRECTORY (SQLITE_READONLY | (6<<8))
#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8))
#define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8))
#define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8))
@ -1131,12 +1135,18 @@ typedef struct sqlite3_api_routines sqlite3_api_routines;
** in the name of the object stands for "virtual file system". See
** the [VFS | VFS documentation] for further information.
**
** The value of the iVersion field is initially 1 but may be larger in
** future versions of SQLite. Additional fields may be appended to this
** object when the iVersion value is increased. Note that the structure
** of the sqlite3_vfs object changes in the transaction between
** SQLite version 3.5.9 and 3.6.0 and yet the iVersion field was not
** modified.
** The VFS interface is sometimes extended by adding new methods onto
** the end. Each time such an extension occurs, the iVersion field
** is incremented. The iVersion value started out as 1 in
** SQLite [version 3.5.0] on [dateof:3.5.0], then increased to 2
** with SQLite [version 3.7.0] on [dateof:3.7.0], and then increased
** to 3 with SQLite [version 3.7.6] on [dateof:3.7.6]. Additional fields
** may be appended to the sqlite3_vfs object and the iVersion value
** may increase again in future versions of SQLite.
** Note that the structure
** of the sqlite3_vfs object changes in the transition from
** SQLite [version 3.5.9] to [version 3.6.0] on [dateof:3.6.0]
** and yet the iVersion field was not modified.
**
** The szOsFile field is the size of the subclassed [sqlite3_file]
** structure used by this VFS. mxPathname is the maximum length of
@ -2049,7 +2059,6 @@ struct sqlite3_mem_methods {
** into which is written 0 or 1 to indicate whether checkpoints-on-close
** have been disabled - 0 if they are not disabled, 1 if they are.
** </dd>
**
** <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt>
** <dd>^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates
** the [query planner stability guarantee] (QPSG). When the QPSG is active,
@ -2060,7 +2069,16 @@ struct sqlite3_mem_methods {
** the QPSG active, SQLite will always use the same query plan in the field as
** was used during testing in the lab.
** </dd>
**
** <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt>
** <dd> By default, the output of EXPLAIN QUERY PLAN commands does not
** include output for any operations performed by trigger programs. This
** option is used to set or clear (the default) a flag that governs this
** behavior. The first parameter passed to this operation is an integer -
** non-zero to enable output for trigger programs, or zero to disable it.
** The second parameter is a pointer to an integer into which is written
** 0 or 1 to indicate whether output-for-triggers has been disabled - 0 if
** it is not disabled, 1 if it is.
** </dd>
** </dl>
*/
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
@ -2071,7 +2089,8 @@ struct sqlite3_mem_methods {
#define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */
#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */
#define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */
#define SQLITE_DBCONFIG_MAX 1008 /* Largest DBCONFIG */
/*
** CAPI3REF: Enable Or Disable Extended Result Codes
@ -2932,8 +2951,8 @@ SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*,
** KEYWORDS: SQLITE_TRACE
**
** These constants identify classes of events that can be monitored
** using the [sqlite3_trace_v2()] tracing logic. The third argument
** to [sqlite3_trace_v2()] is an OR-ed combination of one or more of
** using the [sqlite3_trace_v2()] tracing logic. The M argument
** to [sqlite3_trace_v2(D,M,X,P)] is an OR-ed combination of one or more of
** the following constants. ^The first argument to the trace callback
** is one of the following constants.
**
@ -4779,6 +4798,9 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
** datatype of the value
** <tr><td><b>sqlite3_value_numeric_type&nbsp;&nbsp;</b>
** <td>&rarr;&nbsp;&nbsp;<td>Best numeric datatype of the value
** <tr><td><b>sqlite3_value_nochange&nbsp;&nbsp;</b>
** <td>&rarr;&nbsp;&nbsp;<td>True if the column is unchanged in an UPDATE
** against a virtual table.
** </table></blockquote>
**
** <b>Details:</b>
@ -4827,6 +4849,19 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
** then the conversion is performed. Otherwise no conversion occurs.
** The [SQLITE_INTEGER | datatype] after conversion is returned.)^
**
** ^Within the [xUpdate] method of a [virtual table], the
** sqlite3_value_nochange(X) interface returns true if and only if
** the column corresponding to X is unchanged by the UPDATE operation
** that the xUpdate method call was invoked to implement and if
** and the prior [xColumn] method call that was invoked to extracted
** the value for that column returned without setting a result (probably
** because it queried [sqlite3_vtab_nochange()] and found that the column
** was unchanging). ^Within an [xUpdate] method, any value for which
** sqlite3_value_nochange(X) is true will in all other respects appear
** to be a NULL value. If sqlite3_value_nochange(X) is invoked anywhere other
** than within an [xUpdate] method call for an UPDATE statement, then
** the return value is arbitrary and meaningless.
**
** Please pay particular attention to the fact that the pointer returned
** from [sqlite3_value_blob()], [sqlite3_value_text()], or
** [sqlite3_value_text16()] can be invalidated by a subsequent call to
@ -4849,6 +4884,7 @@ SQLITE_API int sqlite3_value_bytes(sqlite3_value*);
SQLITE_API int sqlite3_value_bytes16(sqlite3_value*);
SQLITE_API int sqlite3_value_type(sqlite3_value*);
SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
SQLITE_API int sqlite3_value_nochange(sqlite3_value*);
/*
** CAPI3REF: Finding The Subtype Of SQL Values
@ -6951,9 +6987,9 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
** the xFileControl method. ^The return value of the xFileControl
** method becomes the return value of this routine.
**
** ^The SQLITE_FCNTL_FILE_POINTER value for the op parameter causes
** ^The [SQLITE_FCNTL_FILE_POINTER] value for the op parameter causes
** a pointer to the underlying [sqlite3_file] object to be written into
** the space pointed to by the 4th parameter. ^The SQLITE_FCNTL_FILE_POINTER
** the space pointed to by the 4th parameter. ^The [SQLITE_FCNTL_FILE_POINTER]
** case is a short-circuit path which does not actually invoke the
** underlying sqlite3_io_methods.xFileControl method.
**
@ -6965,7 +7001,7 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
** an incorrect zDbName and an SQLITE_ERROR return from the underlying
** xFileControl method.
**
** See also: [SQLITE_FCNTL_LOCKSTATE]
** See also: [file control opcodes]
*/
SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*);
@ -7022,7 +7058,8 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_ISINIT 23
#define SQLITE_TESTCTRL_SORTER_MMAP 24
#define SQLITE_TESTCTRL_IMPOSTER 25
#define SQLITE_TESTCTRL_LAST 25
#define SQLITE_TESTCTRL_PARSER_COVERAGE 26
#define SQLITE_TESTCTRL_LAST 26 /* Largest TESTCTRL */
/*
** CAPI3REF: SQLite Runtime Status
@ -8276,6 +8313,40 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
*/
SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
/*
** CAPI3REF: Determine If Virtual Table Column Access Is For UPDATE
**
** If the sqlite3_vtab_nochange(X) routine is called within the [xColumn]
** method of a [virtual table], then it returns true if and only if the
** column is being fetched as part of an UPDATE operation during which the
** column value will not change. Applications might use this to substitute
** a lighter-weight value to return that the corresponding [xUpdate] method
** understands as a "no-change" value.
**
** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that
** the column is not changed by the UPDATE statement, they the xColumn
** method can optionally return without setting a result, without calling
** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces].
** In that case, [sqlite3_value_nochange(X)] will return true for the
** same column in the [xUpdate] method.
*/
SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*);
/*
** CAPI3REF: Determine The Collation For a Virtual Table Constraint
**
** This function may only be called from within a call to the [xBestIndex]
** method of a [virtual table].
**
** The first argument must be the sqlite3_index_info object that is the
** first parameter to the xBestIndex() method. The second argument must be
** an index into the aConstraint[] array belonging to the sqlite3_index_info
** structure passed to xBestIndex. This function returns a pointer to a buffer
** containing the name of the collation sequence for the corresponding
** constraint.
*/
SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
/*
** CAPI3REF: Conflict resolution modes
** KEYWORDS: {conflict resolution mode}
@ -9003,6 +9074,35 @@ SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect)
**
** SQLITE_OK is returned if the call completes without error. Or, if an error
** occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned.
**
** <h3>Special sqlite_stat1 Handling</h3>
**
** As of SQLite version 3.22.0, the "sqlite_stat1" table is an exception to
** some of the rules above. In SQLite, the schema of sqlite_stat1 is:
** <pre>
** &nbsp; CREATE TABLE sqlite_stat1(tbl,idx,stat)
** </pre>
**
** Even though sqlite_stat1 does not have a PRIMARY KEY, changes are
** recorded for it as if the PRIMARY KEY is (tbl,idx). Additionally, changes
** are recorded for rows for which (idx IS NULL) is true. However, for such
** rows a zero-length blob (SQL value X'') is stored in the changeset or
** patchset instead of a NULL value. This allows such changesets to be
** manipulated by legacy implementations of sqlite3changeset_invert(),
** concat() and similar.
**
** The sqlite3changeset_apply() function automatically converts the
** zero-length blob back to a NULL value when updating the sqlite_stat1
** table. However, if the application calls sqlite3changeset_new(),
** sqlite3changeset_old() or sqlite3changeset_conflict on a changeset
** iterator directly (including on a changeset iterator passed to a
** conflict-handler callback) then the X'' value is returned. The application
** must translate X'' to NULL itself if required.
**
** Legacy (older than 3.22.0) versions of the sessions module cannot capture
** changes made to the sqlite_stat1 table. Legacy versions of the
** sqlite3changeset_apply() function silently ignore any modifications to the
** sqlite_stat1 table that are part of a changeset or patchset.
*/
SQLITE_API int sqlite3session_attach(
sqlite3_session *pSession, /* Session object */

View File

@ -2579,18 +2579,6 @@ Toolbox.prototype = {
// in the initialization process can throw errors.
yield this._initInspector;
// Releasing the walker (if it has been created)
// This can fail, but in any case, we want to continue destroying the
// inspector/highlighter/selection
// FF42+: Inspector actor starts managing Walker actor and auto destroy it.
if (this._walker && !this.walker.traits.autoReleased) {
try {
yield this._walker.release();
} catch (e) {
// Do nothing;
}
}
yield this.highlighterUtils.stopPicker();
yield this._inspector.destroy();
if (this._highlighter) {

View File

@ -186,6 +186,7 @@ skip-if = e10s # Bug 1036409 - The last selected node isn't reselected
[browser_markup_toggle_01.js]
[browser_markup_toggle_02.js]
[browser_markup_toggle_03.js]
[browser_markup_toggle_closing_tag_line.js]
[browser_markup_update-on-navigtion.js]
[browser_markup_void_elements_html.js]
[browser_markup_void_elements_xhtml.js]

View File

@ -0,0 +1,45 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that a closing tag line is displayed when expanding an element container.
// Also check that no closing tag line is displayed for readonly containers (document,
// roots...).
const TEST_URL = `data:text/html;charset=utf8,
<div class="outer-div"><span>test</span></div>
<iframe src="data:text/html;charset=utf8,<div>test</div>"></iframe>`;
add_task(async function () {
let {inspector} = await openInspectorForURL(TEST_URL);
info("Getting the container for .outer-div parent element");
let container = await getContainerForSelector(".outer-div", inspector);
await expandContainer(inspector, container);
let closeTagLine = container.closeTagLine;
ok(closeTagLine && closeTagLine.textContent.includes("div"),
"DIV has a close tag-line with the correct content");
info("Expand the iframe element");
container = await getContainerForSelector("iframe", inspector);
await expandContainer(inspector, container);
ok(container.expanded, "iframe is expanded");
closeTagLine = container.closeTagLine;
ok(closeTagLine && closeTagLine.textContent.includes("iframe"),
"IFRAME has a close tag-line with the correct content");
info("Retrieve the nodefront for the #document root inside the iframe");
let iframe = await getNodeFront("iframe", inspector);
let {nodes} = await inspector.walker.children(iframe);
let documentFront = nodes[0];
ok(documentFront.displayName === "#document", "First child of IFRAME is #document");
info("Expand the iframe's #document node element");
container = getContainerForNodeFront(documentFront, inspector);
await expandContainer(inspector, container);
ok(container.expanded, "#document is expanded");
ok(!container.closeTagLine, "readonly (#document) node has no close tag-line");
});

View File

@ -634,3 +634,16 @@ function* checkDeleteAndSelection(inspector, key, {selector, focusedSelector, ps
node = yield getNodeFront(selector, inspector);
ok(node, "The node is back");
}
/**
* Expand the provided markup container by clicking on the expand arrow and waiting for
* inspector and children to update.
*/
async function expandContainer(inspector, container) {
let onChildren = waitForChildrenUpdated(inspector);
let onUpdated = inspector.once("inspector-updated");
EventUtils.synthesizeMouseAtCenter(container.expander, {},
inspector.markup.doc.defaultView);
await onChildren;
await onUpdated;
}

View File

@ -11,6 +11,12 @@ const {flashElementOn, flashElementOff} =
const DRAG_DROP_MIN_INITIAL_DISTANCE = 10;
const TYPES = {
TEXT_CONTAINER: "textcontainer",
ELEMENT_CONTAINER: "elementcontainer",
READ_ONLY_CONTAINER: "readonlycontainer",
};
/**
* The main structure for storing a document node in the markup
* tree. Manages creation of the editor for the node and
@ -40,18 +46,19 @@ MarkupContainer.prototype = {
* @param {NodeFront} node
* The node to display.
* @param {String} type
* The type of container to build. This can be either 'textcontainer',
* 'readonlycontainer' or 'elementcontainer'.
* The type of container to build. One of TYPES.TEXT_CONTAINER,
* TYPES.ELEMENT_CONTAINER, TYPES.READ_ONLY_CONTAINER
*/
initialize: function (markupView, node, type) {
this.markup = markupView;
this.node = node;
this.type = type;
this.undo = this.markup.undo;
this.win = this.markup._frame.contentWindow;
this.id = "treeitem-" + markupContainerID++;
this.htmlElt = this.win.document.documentElement;
this.buildMarkup(type);
this.buildMarkup();
this.elt.container = this;
@ -70,7 +77,7 @@ MarkupContainer.prototype = {
this.updateIsDisplayed();
},
buildMarkup: function (type) {
buildMarkup: function () {
this.elt = this.win.document.createElement("li");
this.elt.classList.add("child", "collapsed");
this.elt.setAttribute("role", "presentation");
@ -88,7 +95,7 @@ MarkupContainer.prototype = {
this.tagState.setAttribute("role", "presentation");
this.tagLine.appendChild(this.tagState);
if (type !== "textcontainer") {
if (this.type !== TYPES.TEXT_CONTAINER) {
this.expander = this.win.document.createElement("span");
this.expander.classList.add("theme-twisty", "expander");
this.expander.setAttribute("role", "presentation");
@ -303,51 +310,79 @@ MarkupContainer.prototype = {
if (!this.canExpand) {
value = false;
}
if (this.mustExpand) {
value = true;
}
if (value && this.elt.classList.contains("collapsed")) {
// Expanding a node means cloning its "inline" closing tag into a new
// tag-line that the user can interact with and showing the children.
let closingTag = this.elt.querySelector(".close");
if (closingTag) {
if (!this.closeTagLine) {
let line = this.markup.doc.createElement("div");
line.classList.add("tag-line");
// Closing tag is not important for accessibility.
line.setAttribute("role", "presentation");
let tagState = this.markup.doc.createElement("div");
tagState.classList.add("tag-state");
line.appendChild(tagState);
line.appendChild(closingTag.cloneNode(true));
flashElementOff(line);
this.closeTagLine = line;
}
this.elt.appendChild(this.closeTagLine);
}
this.showCloseTagLine();
this.elt.classList.remove("collapsed");
this.expander.setAttribute("open", "");
this.hovered = false;
this.markup.emit("expanded");
} else if (!value) {
if (this.closeTagLine) {
this.elt.removeChild(this.closeTagLine);
this.closeTagLine = undefined;
}
this.hideCloseTagLine();
this.elt.classList.add("collapsed");
this.expander.removeAttribute("open");
this.markup.emit("collapsed");
}
if (this.showExpander) {
this.tagLine.setAttribute("aria-expanded", this.expanded);
}
},
/**
* Expanding a node means cloning its "inline" closing tag into a new
* tag-line that the user can interact with and showing the children.
*/
showCloseTagLine: function () {
// Only element containers display a closing tag line. #document has no closing line.
if (this.type !== TYPES.ELEMENT_CONTAINER) {
return;
}
// Retrieve the closest .close node for this container.
let closingTag = this.elt.querySelector(".close");
if (!closingTag) {
return;
}
// Create the closing tag-line element if not already created.
if (!this.closeTagLine) {
let line = this.markup.doc.createElement("div");
line.classList.add("tag-line");
// Closing tag is not important for accessibility.
line.setAttribute("role", "presentation");
let tagState = this.markup.doc.createElement("div");
tagState.classList.add("tag-state");
line.appendChild(tagState);
line.appendChild(closingTag.cloneNode(true));
flashElementOff(line);
this.closeTagLine = line;
}
this.elt.appendChild(this.closeTagLine);
},
/**
* Hide the closing tag-line element which should only be displayed when the container
* is expanded.
*/
hideCloseTagLine: function () {
if (!this.closeTagLine) {
return;
}
this.elt.removeChild(this.closeTagLine);
this.closeTagLine = undefined;
},
parentContainer: function () {
return this.elt.parentNode ? this.elt.parentNode.container : null;
},

View File

@ -10,7 +10,7 @@
const { Cc, Ci, Cu } = require("chrome");
const {
getRect, getElementFromPoint, getAdjustedQuads, getWindowDimensions
getRect, getAdjustedQuads, getWindowDimensions
} = require("devtools/shared/layout/utils");
const defer = require("devtools/shared/defer");
const {Task} = require("devtools/shared/task");
@ -125,16 +125,6 @@ var testSpec = protocol.generateActorSpec({
},
response: {}
},
assertElementAtPoint: {
request: {
x: Arg(0, "number"),
y: Arg(1, "number"),
selector: Arg(2, "string")
},
response: {
value: RetVal("boolean")
}
},
getAllAdjustedQuads: {
request: {
selector: Arg(0, "string")
@ -473,15 +463,6 @@ var TestActor = exports.TestActor = protocol.ActorClassWithSpec(testSpec, {
});
},
assertElementAtPoint: function (x, y, selector) {
let elementAtPoint = getElementFromPoint(this.content.document, x, y);
if (!elementAtPoint) {
throw new Error("Unable to find element at (" + x + ", " + y + ")");
}
let node = this._querySelector(selector);
return node == elementAtPoint;
},
/**
* Get all box-model regions' adjusted boxquads for the given element
* @param {String} selector The node selector to target a given element

View File

@ -189,18 +189,7 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
return {
actor: this.actorID,
root: this.rootNode.form(),
traits: {
// FF42+ Inspector starts managing the Walker, while the inspector also
// starts cleaning itself up automatically on client disconnection.
// So that there is no need to manually release the walker anymore.
autoReleased: true,
// XXX: It seems silly that we need to tell the front which capabilities
// its actor has in this way when the target can use actorHasMethod. If
// this was ported to the protocol (Bug 1157048) we could call that
// inside of custom front methods and not need to do traits for this.
multiFrameQuerySelectorAll: true,
textSearch: true,
}
traits: {}
};
},
@ -342,28 +331,6 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
this.emit("resize");
},
/**
* This is kept for backward-compatibility reasons with older remote targets.
* Targets prior to bug 916443.
*
* pick/cancelPick are used to pick a node on click on the content
* document. But in their implementation prior to bug 916443, they don't allow
* highlighting on hover.
* The client-side now uses the highlighter actor's pick and cancelPick
* methods instead. The client-side uses the the highlightable trait found in
* the root actor to determine which version of pick to use.
*
* As for highlight, the new highlighter actor is used instead of the walker's
* highlight method. Same here though, the client-side uses the highlightable
* trait to dertermine which to use.
*
* Keeping these actor methods for now allows newer client-side debuggers to
* inspect fxos 1.2 remote targets or older firefox desktop remote targets.
*/
pick: function () {},
cancelPick: function () {},
highlight: function (node) {},
/**
* Ensures that the node is attached and it can be accessed from the root.
*

View File

@ -168,38 +168,6 @@ window.onload = function () {
runNextTest();
});
addAsyncTest(function* testBackwardsCompat() {
info("Simulating a server that doesn't have the new search functionality.");
walkerFront.traits.textSearch = false;
let front = yield walkerFront.querySelector(walkerFront.rootNode, "h1");
let results = yield walkerFront.search("h1");
isDeeply(results, {
node: front,
type: "selector",
resultsIndex: 0,
resultsLength: 1
}, "Only querySelectorAll results being returned");
// Clear search data to remove result state on the front
yield walkerFront.search("");
// Reset the normal textSearch behavior
walkerFront.traits.textSearch = true;
results = yield walkerFront.search("h1");
isDeeply(results, {
node: front,
type: "search",
resultsIndex: 0,
resultsLength: 3
}, "Other results being included");
// Clear search data to remove result state on the front
yield walkerFront.search("");
runNextTest();
});
runNextTest();
};
</script>

View File

@ -5269,13 +5269,19 @@ exports.CSS_PROPERTIES = {
],
"values": [
"-moz-alt-content",
"attr",
"close-quote",
"counter",
"counters",
"inherit",
"initial",
"no-close-quote",
"no-open-quote",
"none",
"normal",
"open-quote",
"unset"
"unset",
"url"
]
},
"counter-increment": {

View File

@ -213,16 +213,9 @@ const WalkerFront = FrontClassWithSpec(walkerSpec, {
let searchData = this.searchData = this.searchData || { };
let selectorOnly = !!options.selectorOnly;
// Backwards compat. Use selector only search if the new
// search functionality isn't implemented, or if the caller (tests)
// want it.
if (selectorOnly || !this.traits.textSearch) {
if (selectorOnly) {
searchType = "selector";
if (this.traits.multiFrameQuerySelectorAll) {
nodeList = yield this.multiFrameQuerySelectorAll(query);
} else {
nodeList = yield this.querySelectorAll(this.rootNode, query);
}
nodeList = yield this.multiFrameQuerySelectorAll(query);
} else {
searchType = "search";
let result = yield this._search(query, options);
@ -444,39 +437,6 @@ const WalkerFront = FrontClassWithSpec(walkerSpec, {
return !!this.conn._transport._serverConnection;
},
// XXX hack during transition to remote inspector: get a proper NodeFront
// for a given local node. Only works locally.
frontForRawNode: function (rawNode) {
if (!this.isLocal()) {
console.warn("Tried to use frontForRawNode on a remote connection.");
return null;
}
const { DebuggerServer } = require("devtools/server/main");
let walkerActor = DebuggerServer.searchAllConnectionsForActor(this.actorID);
if (!walkerActor) {
throw Error("Could not find client side for actor " + this.actorID);
}
let nodeActor = walkerActor._ref(rawNode);
// Pass the node through a read/write pair to create the client side actor.
let nodeType = types.getType("domnode");
let returnNode = nodeType.read(
nodeType.write(nodeActor, walkerActor), this);
let top = returnNode;
let extras = walkerActor.parents(nodeActor, {sameTypeRootTreeItem: true});
for (let extraActor of extras) {
top = nodeType.read(nodeType.write(extraActor, walkerActor), this);
}
if (top !== this.rootNode) {
// Imported an already-orphaned node.
this._orphaned.add(top);
walkerActor._orphaned
.add(DebuggerServer.searchAllConnectionsForActor(top.actorID));
}
return returnNode;
},
removeNode: custom(Task.async(function* (node) {
let previousSibling = yield this.previousSibling(node);
let nextSibling = yield this._removeNode(node);

View File

@ -7,9 +7,8 @@
const { Cc, Ci } = require("chrome");
const Services = require("Services");
const l10n = require("gcli/l10n");
const { DevToolsLoader } = require("resource://devtools/shared/Loader.jsm");
const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.defineModuleGetter(this, "DevToolsLoader",
"resource://devtools/shared/Loader.jsm");
const BRAND_SHORT_NAME = Cc["@mozilla.org/intl/stringbundle;1"]
.getService(Ci.nsIStringBundleService)

View File

@ -438,47 +438,6 @@ function getFrameContentOffset(frame) {
return [borderTop + paddingTop, borderLeft + paddingLeft];
}
/**
* Find an element from the given coordinates. This method descends through
* frames to find the element the user clicked inside frames.
*
* @param {DOMDocument} document
* The document to look into.
* @param {Number} x
* @param {Number} y
* @return {DOMNode}
* the element node found at the given coordinates, or null if no node
* was found
*/
function getElementFromPoint(document, x, y) {
let node = document.elementFromPoint(x, y);
if (node && node.contentDocument) {
if (ChromeUtils.getClassName(node) === "HTMLIFrameElement") {
let rect = node.getBoundingClientRect();
// Gap between the frame and its content window.
let [offsetTop, offsetLeft] = getFrameContentOffset(node);
x -= rect.left + offsetLeft;
y -= rect.top + offsetTop;
if (x < 0 || y < 0) {
// Didn't reach the content document, still over the frame.
return node;
}
}
if (ChromeUtils.getClassName(node) === "HTMLIFrameElement" ||
ChromeUtils.getClassName(node) === "HTMLFrameElement") {
let subnode = getElementFromPoint(node.contentDocument, x, y);
if (subnode) {
node = subnode;
}
}
}
return node;
}
exports.getElementFromPoint = getElementFromPoint;
/**
* Check if a node and its document are still alive
* and attached to the window.

View File

@ -5,6 +5,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=226361
<head>
<title>Test for Bug 226361</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body id="body1">
@ -37,8 +38,7 @@ function setTabFocus() {
var doc = document;
function tab_to(id) {
var wu = SpecialPowers.DOMWindowUtils;
wu.sendKeyEvent('keypress', 9, 0, 0);
synthesizeKey("KEY_Tab", {code: "Tab"});
is(doc.activeElement.id, id, "element with id=" + id + " should have focus");
}

View File

@ -5,7 +5,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=238987
-->
<head>
<title>Test for Bug 238987</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
@ -20,7 +21,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=238987
/** Test for Bug 238987 **/
var shouldStop = false;
var modifier = 0;
var activateShift = false;
var expectedResult = "i1,i2,i3,i4,i5,i6,i7,i8,number,i9,i10,i11,i12";
var forwardFocusArray = expectedResult.split(",");
var backwardFocusArray = expectedResult.split(",");
@ -33,13 +34,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=238987
function handleFocus(e) {
if (e.target.id == "begin") {
// if the modifier is set, the test is coming back from the end.
if (modifier) {
// if the activateShift is set, the test is coming back from the end.
if (activateShift) {
shouldStop = true;
}
} else if (e.target.id == "end") {
modifier = Components.interfaces.nsIDOMEvent.SHIFT_MASK;
} else if (modifier) {
activateShift = true;
} else if (activateShift) {
var expected = backwardFocusArray.pop();
ok(expected == e.target.id,
"(focus) Backward tabbing, expected [" +
@ -66,7 +67,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=238987
function handleBlur(e) {
if (e.target.id == "begin" || e.target.id == "end") {
return;
} else if (modifier) {
} else if (activateShift) {
var expected = backwardBlurArray.pop();
ok(expected == e.target.id,
"(blur) backward tabbing, expected [" +
@ -90,12 +91,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=238987
}
function tab() {
var utils = SpecialPowers.DOMWindowUtils;
// Send tab key events.
var key = Components.interfaces.nsIDOMKeyEvent.DOM_VK_TAB;
utils.sendKeyEvent("keydown", key, 0, modifier);
utils.sendKeyEvent("keypress", key, 0, modifier);
utils.sendKeyEvent("keyup", key, 0, modifier);
synthesizeKey("KEY_Tab", {code: "Tab", shiftKey: activateShift});
if (shouldStop) {
// Did focus handling succeed
is(forwardFocusArray.length, 0,

View File

@ -5,7 +5,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=409604
-->
<head>
<title>Test for Bug 409604</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body id="body">
@ -19,8 +20,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=409604
/** Test for Bug 409604 **/
var modifier = SpecialPowers.Ci.nsIDOMEvent.ALT_MASK |
SpecialPowers.Ci.nsIDOMEvent.SHIFT_MASK;
var expectedFocus = "a,c,d,e,f,g,h,i,j,k,l,m,n,p,x,y";
// XXX the "map" test is causing trouble, see bug 433089
var focusArray = expectedFocus.split(",");
@ -120,10 +119,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=409604
}
function pressAccessKey(key) {
var utils = SpecialPowers.DOMWindowUtils;
utils.sendKeyEvent("keydown", key, key, modifier);
utils.sendKeyEvent("keypress", key, key, modifier);
utils.sendKeyEvent("keyup", key, key, modifier);
synthesizeKey(key.key, {code: key.code, altKey: true, shiftKey: true});
}
function testFocusableElements() {
@ -131,7 +127,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=409604
// XXX the "map" test is causing trouble, see bug 433089
if (code == "b".charCodeAt(0))
continue;
pressAccessKey(code);
var accessChar = String.fromCharCode(code).toUpperCase();
pressAccessKey({key: accessChar, code: "Key" + accessChar});
}
ok(focusArray.length == 0, "(focus) unhandled elements remaining: " + focusArray.join(","));
}
@ -190,7 +187,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=409604
var i, e;
for (i = 0; i < unfocusableTags.length; ++ i) {
createUnfocusableElement(unfocusableTags[i], "z");
pressAccessKey("z".charCodeAt(0));
pressAccessKey({key: "Z", code:"KeyZ"});
destroyUnfocusableElement();
}
for (i = 0; i < invalidElements.length; ++ i) {
@ -199,7 +196,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=409604
e.setAttribute("accesskey", "z");
e.setAttribute("onclick", "handleClick(event.target); event.preventDefault();");
e.setAttribute("onfocus", "handleInvalid(event.target);");
pressAccessKey("z".charCodeAt(0));
pressAccessKey({key: "Z", code:"KeyZ"});
e.removeAttribute("accesskey");
e.removeAttribute("onclick");
e.removeAttribute("onfocus");

View File

@ -5,6 +5,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=450876
<head>
<title>Test for Bug 450876 - Crash [@ nsEventStateManager::GetNextTabbableMapArea] with img usemap and tabindex</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
@ -24,7 +25,7 @@ function doTest() {
document.getElementById('a').focus();
is(document.activeElement, document.getElementById('a'), "link should have focus");
is(document.hasFocus(), true, "document should be focused");
SpecialPowers.DOMWindowUtils.sendKeyEvent('keypress', 9, 0, 0);
synthesizeKey("KEY_Tab", {code: "Tab"});
is(document.activeElement, document.getElementById('a'), "body element should be focused");
is(document.hasFocus(), false, "document should not be focused");

View File

@ -6,6 +6,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=493251
<head>
<title>Test for Bug 493251</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
@ -36,14 +37,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=493251
utils.suppressEventHandling(aSuppress);
}
function dispatchKeyEvent(type) {
var utils = SpecialPowers.getDOMWindowUtils(win);
ok(true, "Dipatching key event: type=" + type);
utils.sendKeyEvent(type,
SpecialPowers.Ci.nsIDOMKeyEvent.DOM_VK_A,
0, 0);
}
function dispatchMouseEvent(aType, aX, aY, aButton, aClickCount, aModifiers) {
var utils = SpecialPowers.getDOMWindowUtils(win);
ok(true, "Dipatching mouse event: aType=" + aType + ", aX=" + aX + ", aY" +
@ -105,18 +98,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=493251
function(e) { dumpEvent(e); ++mouseClick; }, true);
ok(true, "doTest #1...");
dispatchKeyEvent("keydown");
dispatchKeyEvent("keypress");
dispatchKeyEvent("keyup");
synthesizeKey("a", {code: "KeyA"}, win);
is(keyDown, 1, "Wrong number events (1)");
is(keyPress, 1, "Wrong number events (2)");
is(keyUp, 1, "Wrong number events (3)");
ok(true, "doTest #2...");
suppressEventHandling(true);
dispatchKeyEvent("keydown");
dispatchKeyEvent("keypress");
dispatchKeyEvent("keyup");
synthesizeKey("a", {code: "KeyA"}, win);
is(keyDown, 1, "Wrong number events (4)");
is(keyPress, 1, "Wrong number events (5)");
is(keyUp, 1, "Wrong number events (6)");
@ -130,10 +119,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=493251
function continueTest1() {
ok(true, "continueTest1...");
dispatchKeyEvent("keydown");
suppressEventHandling(true);
dispatchKeyEvent("keypress");
dispatchKeyEvent("keyup");
win.addEventListener("keydown", () => { suppressEventHandling(true); }, {once: true});
synthesizeKey("a", {code: "KeyA"}, win);
is(keyDown, 2, "Wrong number events (10)");
is(keyPress, 1, "Wrong number events (11)");
is(keyUp, 1, "Wrong number events (12)");

View File

@ -6,6 +6,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=545268
<head>
<title>Test for Bug 545268</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
@ -33,13 +34,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=545268
var keyPress = 0;
var keyUp = 0;
function dispatchKeyEvent(type) {
var utils = SpecialPowers.getDOMWindowUtils(subwin);
utils.sendKeyEvent(type,
SpecialPowers.Ci.nsIDOMKeyEvent.DOM_VK_A,
0, 0);
}
function doTest() {
var utils = SpecialPowers.getDOMWindowUtils(win);
var f = win.document.getElementById("f");
@ -52,9 +46,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=545268
subwin.addEventListener("mouseup", function(e) { ++mouseUp; }, true);
subwin.addEventListener("click", function(e) { ++mouseClick; }, true);
dispatchKeyEvent("keydown");
dispatchKeyEvent("keypress");
dispatchKeyEvent("keyup");
synthesizeKey("a", {code: "KeyA"}, subwin);
is(keyDown, 1, "Wrong number events (1)");
is(keyPress, 1, "Wrong number events (2)");
is(keyUp, 1, "Wrong number events (3)");
@ -62,9 +54,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=545268
// Test that suppressing events on the parent window prevents key
// events in the subdocument window
utils.suppressEventHandling(true);
dispatchKeyEvent("keydown");
dispatchKeyEvent("keypress");
dispatchKeyEvent("keyup");
synthesizeKey("a", {code: "KeyA"}, subwin);
is(keyDown, 1, "Wrong number events (4)");
is(keyPress, 1, "Wrong number events (5)");
is(keyUp, 1, "Wrong number events (6)");
@ -78,10 +68,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=545268
function continueTest1() {
var utils = SpecialPowers.getDOMWindowUtils(win);
dispatchKeyEvent("keydown");
utils.suppressEventHandling(true);
dispatchKeyEvent("keypress");
dispatchKeyEvent("keyup");
subwin.addEventListener("keydown", () => { utils.suppressEventHandling(true); }, {once: true});
synthesizeKey("a", {code: "KeyA"}, subwin);
is(keyDown, 2, "Wrong number events (10)");
is(keyPress, 1, "Wrong number events (11)");
is(keyUp, 1, "Wrong number events (12)");

View File

@ -60,10 +60,10 @@ function testRegularEvents() {
var timeBeforeEvent = performance.now();
addEventListener("load", function(evt) {
var timeAfterEvent = performance.now();
ok(evt.timeStamp > timeBeforeEvent &&
evt.timeStamp < timeAfterEvent,
"Event timestamp (" + evt.timeStamp + ") is in expected range: (" +
timeBeforeEvent + ", " + timeAfterEvent + ")");
ok(evt.timeStamp >= timeBeforeEvent &&
evt.timeStamp <= timeAfterEvent,
"Event timestamp (" + evt.timeStamp + ") is in expected range: [" +
timeBeforeEvent + ", " + timeAfterEvent + "]");
testWorkerEvents();
});
}
@ -77,8 +77,8 @@ function testWorkerEvents() {
ok(evt.data >= timeBeforeEvent &&
evt.data <= timeAfterEvent,
"Event timestamp in dedicated worker (" + evt.data +
") is in expected range: (" +
timeBeforeEvent + ", " + timeAfterEvent + ")");
") is in expected range: [" +
timeBeforeEvent + ", " + timeAfterEvent + "]");
worker.terminate();
testSharedWorkerEvents();
};

View File

@ -453,23 +453,43 @@ IDBFactory::Open(JSContext* aCx,
{
if (!IsChrome() &&
aOptions.mStorage.WasPassed()) {
switch (aOptions.mStorage.Value()) {
case StorageType::Persistent: {
Telemetry::ScalarAdd(Telemetry::ScalarID::IDB_TYPE_PERSISTENT_COUNT, 1);
break;
bool ignore = false;
// Ignore internal usage on about: pages.
if (NS_IsMainThread()) {
nsCOMPtr<nsIPrincipal> principal = PrincipalInfoToPrincipal(*mPrincipalInfo);
if (principal) {
nsCOMPtr<nsIURI> uri;
nsresult rv = principal->GetURI(getter_AddRefs(uri));
if (NS_SUCCEEDED(rv) && uri) {
bool isAbout;
rv = uri->SchemeIs("about", &isAbout);
if (NS_SUCCEEDED(rv) && isAbout) {
ignore = true;
}
}
}
}
case StorageType::Temporary: {
Telemetry::ScalarAdd(Telemetry::ScalarID::IDB_TYPE_TEMPORARY_COUNT, 1);
break;
if (!ignore) {
switch (aOptions.mStorage.Value()) {
case StorageType::Persistent: {
Telemetry::ScalarAdd(Telemetry::ScalarID::IDB_TYPE_PERSISTENT_COUNT, 1);
break;
}
case StorageType::Temporary: {
Telemetry::ScalarAdd(Telemetry::ScalarID::IDB_TYPE_TEMPORARY_COUNT, 1);
break;
}
case StorageType::Default:
case StorageType::EndGuard_:
break;
default:
MOZ_CRASH("Invalid storage type!");
}
case StorageType::Default:
case StorageType::EndGuard_:
break;
default:
MOZ_CRASH("Invalid storage type!");
}
}

View File

@ -158,7 +158,7 @@ APZCTreeManager::CheckerboardFlushObserver::Observe(nsISupports* aSubject,
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mTreeManager.get());
MutexAutoLock lock(mTreeManager->mTreeLock);
RecursiveMutexAutoLock lock(mTreeManager->mTreeLock);
if (mTreeManager->mRootNode) {
ForEachNode<ReverseIterator>(mTreeManager->mRootNode.get(),
[](HitTestingTreeNode* aNode)
@ -294,7 +294,7 @@ APZCTreeManager::UpdateHitTestingTreeImpl(uint64_t aRootLayerTreeId,
{
APZThreadUtils::AssertOnCompositorThread();
MutexAutoLock lock(mTreeLock);
RecursiveMutexAutoLock lock(mTreeLock);
// For testing purposes, we log some data to the APZTestData associated with
// the layers id that originated this update.
@ -344,7 +344,7 @@ APZCTreeManager::UpdateHitTestingTreeImpl(uint64_t aRootLayerTreeId,
state.mLayersIdsToDestroy.erase(aRootLayerTreeId);
mApzcTreeLog << "[start]\n";
mTreeLock.AssertCurrentThreadOwns();
mTreeLock.AssertCurrentThreadIn();
ForEachNode<ReverseIterator>(aRoot,
[&](ScrollNode aLayerMetrics)
@ -502,7 +502,7 @@ APZCTreeManager::PushStateToWR(wr::TransactionBuilder& aTxn,
{
APZThreadUtils::AssertOnCompositorThread();
MutexAutoLock lock(mTreeLock);
RecursiveMutexAutoLock lock(mTreeLock);
// During the first pass through the tree, we build a cache of guid->HTTN so
// that we can find the relevant APZC instances quickly in subsequent passes,
@ -778,7 +778,7 @@ APZCTreeManager::PrepareNodeForLayer(const ScrollNode& aLayer,
HitTestingTreeNode* aNextSibling,
TreeBuildingState& aState)
{
mTreeLock.AssertCurrentThreadOwns();
mTreeLock.AssertCurrentThreadIn();
bool needsApzc = true;
if (!aMetrics.IsScrollable()) {
@ -1074,7 +1074,7 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
MOZ_ASSERT(mToolbarAnimator);
ScreenPoint scrollOffset;
{
MutexAutoLock lock(mTreeLock);
RecursiveMutexAutoLock lock(mTreeLock);
RefPtr<AsyncPanZoomController> apzc = FindRootContentOrRootApzc();
if (apzc) {
scrollOffset = ViewAs<ScreenPixel>(apzc->GetCurrentAsyncScrollOffset(AsyncPanZoomController::eForHitTesting),
@ -1124,7 +1124,7 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
// When the mouse is outside the window we still want to handle dragging
// but we won't find an APZC. Fallback to root APZC then.
{ // scope lock
MutexAutoLock lock(mTreeLock);
RecursiveMutexAutoLock lock(mTreeLock);
if (!apzc && mRootNode) {
apzc = mRootNode->GetApzc();
}
@ -1739,7 +1739,7 @@ APZCTreeManager::SetupScrollbarDrag(MouseInput& aMouseInput,
// due to async scrolling, so look that up and apply it.
LayerToParentLayerMatrix4x4 thumbTransform;
{
MutexAutoLock lock(mTreeLock);
RecursiveMutexAutoLock lock(mTreeLock);
thumbTransform = ComputeTransformForNode(aScrollThumbNode);
}
// Only consider the translation, since we do not support both
@ -1903,7 +1903,7 @@ void
APZCTreeManager::UpdateZoomConstraints(const ScrollableLayerGuid& aGuid,
const Maybe<ZoomConstraints>& aConstraints)
{
MutexAutoLock lock(mTreeLock);
RecursiveMutexAutoLock lock(mTreeLock);
RefPtr<HitTestingTreeNode> node = GetTargetNode(aGuid, nullptr);
MOZ_ASSERT(!node || node->GetApzc()); // any node returned must have an APZC
@ -1962,8 +1962,7 @@ APZCTreeManager::FlushRepaintsToClearScreenToGeckoTransform()
// matched APZCs is the same. It is simplest to ensure that by flushing the
// pending repaint requests, which makes all of the untransforms empty (and
// therefore equal).
MutexAutoLock lock(mTreeLock);
mTreeLock.AssertCurrentThreadOwns();
RecursiveMutexAutoLock lock(mTreeLock);
ForEachNode<ReverseIterator>(mRootNode.get(),
[](HitTestingTreeNode* aNode)
@ -1987,7 +1986,7 @@ APZCTreeManager::CancelAnimation(const ScrollableLayerGuid &aGuid)
void
APZCTreeManager::AdjustScrollForSurfaceShift(const ScreenPoint& aShift)
{
MutexAutoLock lock(mTreeLock);
RecursiveMutexAutoLock lock(mTreeLock);
RefPtr<AsyncPanZoomController> apzc = FindRootContentOrRootApzc();
if (apzc) {
apzc->AdjustScrollForSurfaceShift(aShift);
@ -2003,7 +2002,7 @@ APZCTreeManager::ClearTree()
APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
"layers::InputQueue::Clear", mInputQueue, &InputQueue::Clear));
MutexAutoLock lock(mTreeLock);
RecursiveMutexAutoLock lock(mTreeLock);
// Collect the nodes into a list, and then destroy each one.
// We can't destroy them as we collect them, because ForEachNode()
@ -2032,7 +2031,7 @@ APZCTreeManager::ClearTree()
RefPtr<HitTestingTreeNode>
APZCTreeManager::GetRootNode() const
{
MutexAutoLock lock(mTreeLock);
RecursiveMutexAutoLock lock(mTreeLock);
return mRootNode;
}
@ -2235,7 +2234,7 @@ APZCTreeManager::HitTestAPZC(const ScreenIntPoint& aPoint)
already_AddRefed<AsyncPanZoomController>
APZCTreeManager::GetTargetAPZC(const ScrollableLayerGuid& aGuid)
{
MutexAutoLock lock(mTreeLock);
RecursiveMutexAutoLock lock(mTreeLock);
RefPtr<HitTestingTreeNode> node = GetTargetNode(aGuid, nullptr);
MOZ_ASSERT(!node || node->GetApzc()); // any node returned must have an APZC
RefPtr<AsyncPanZoomController> apzc = node ? node->GetApzc() : nullptr;
@ -2253,7 +2252,7 @@ already_AddRefed<AsyncPanZoomController>
APZCTreeManager::GetTargetAPZC(const uint64_t& aLayersId,
const FrameMetrics::ViewID& aScrollId)
{
MutexAutoLock lock(mTreeLock);
RecursiveMutexAutoLock lock(mTreeLock);
ScrollableLayerGuid guid(aLayersId, 0, aScrollId);
RefPtr<HitTestingTreeNode> node = GetTargetNode(guid, &GuidComparatorIgnoringPresShell);
MOZ_ASSERT(!node || node->GetApzc()); // any node returned must have an APZC
@ -2265,7 +2264,7 @@ already_AddRefed<HitTestingTreeNode>
APZCTreeManager::GetTargetNode(const ScrollableLayerGuid& aGuid,
GuidComparator aComparator) const
{
mTreeLock.AssertCurrentThreadOwns();
mTreeLock.AssertCurrentThreadIn();
RefPtr<HitTestingTreeNode> target = DepthFirstSearchPostOrder<ReverseIterator>(mRootNode.get(),
[&aGuid, &aComparator](HitTestingTreeNode* node)
{
@ -2288,7 +2287,7 @@ APZCTreeManager::GetTargetAPZC(const ScreenPoint& aPoint,
CompositorHitTestInfo* aOutHitResult,
RefPtr<HitTestingTreeNode>* aOutScrollbarNode)
{
MutexAutoLock lock(mTreeLock);
RecursiveMutexAutoLock lock(mTreeLock);
CompositorHitTestInfo hitResult = CompositorHitTestInfo::eInvisibleToHitTest;
HitTestingTreeNode* scrollbarNode = nullptr;
@ -2385,7 +2384,7 @@ APZCTreeManager::BuildOverscrollHandoffChain(const RefPtr<AsyncPanZoomController
// order in which scroll will be handed off to them.
// Grab tree lock since we'll be walking the APZC tree.
MutexAutoLock lock(mTreeLock);
RecursiveMutexAutoLock lock(mTreeLock);
// Build the chain. If there is a scroll parent link, we use that. This is
// needed to deal with scroll info layers, because they participate in handoff
@ -2459,7 +2458,7 @@ APZCTreeManager::SetLongTapEnabled(bool aLongTapEnabled)
RefPtr<HitTestingTreeNode>
APZCTreeManager::FindScrollThumbNode(const AsyncDragMetrics& aDragMetrics)
{
MutexAutoLock lock(mTreeLock);
RecursiveMutexAutoLock lock(mTreeLock);
return DepthFirstSearch<ReverseIterator>(mRootNode.get(),
[&aDragMetrics](HitTestingTreeNode* aNode) {
@ -2493,7 +2492,7 @@ APZCTreeManager::GetAPZCAtPoint(HitTestingTreeNode* aNode,
CompositorHitTestInfo* aOutHitResult,
HitTestingTreeNode** aOutScrollbarNode)
{
mTreeLock.AssertCurrentThreadOwns();
mTreeLock.AssertCurrentThreadIn();
// This walks the tree in depth-first, reverse order, so that it encounters
// APZCs front-to-back on the screen.
@ -2586,7 +2585,7 @@ APZCTreeManager::GetAPZCAtPoint(HitTestingTreeNode* aNode,
AsyncPanZoomController*
APZCTreeManager::FindRootApzcForLayersId(uint64_t aLayersId) const
{
mTreeLock.AssertCurrentThreadOwns();
mTreeLock.AssertCurrentThreadIn();
HitTestingTreeNode* resultNode = BreadthFirstSearch<ReverseIterator>(mRootNode.get(),
[aLayersId](HitTestingTreeNode* aNode) {
@ -2601,7 +2600,7 @@ APZCTreeManager::FindRootApzcForLayersId(uint64_t aLayersId) const
AsyncPanZoomController*
APZCTreeManager::FindRootContentApzcForLayersId(uint64_t aLayersId) const
{
mTreeLock.AssertCurrentThreadOwns();
mTreeLock.AssertCurrentThreadIn();
HitTestingTreeNode* resultNode = BreadthFirstSearch<ReverseIterator>(mRootNode.get(),
[aLayersId](HitTestingTreeNode* aNode) {
@ -2616,7 +2615,7 @@ APZCTreeManager::FindRootContentApzcForLayersId(uint64_t aLayersId) const
AsyncPanZoomController*
APZCTreeManager::FindRootContentOrRootApzc() const
{
mTreeLock.AssertCurrentThreadOwns();
mTreeLock.AssertCurrentThreadIn();
// Note: this is intended to find the same "root" that would be found
// by AsyncCompositionManager::ApplyAsyncContentTransformToTree inside
@ -2738,7 +2737,7 @@ ScreenToParentLayerMatrix4x4
APZCTreeManager::GetScreenToApzcTransform(const AsyncPanZoomController *aApzc) const
{
Matrix4x4 result;
MutexAutoLock lock(mTreeLock);
RecursiveMutexAutoLock lock(mTreeLock);
// The comments below assume there is a chain of layers L..R with L and P having APZC instances as
// explained in the comment above. This function is called with aApzc at L, and the loop
@ -2779,7 +2778,7 @@ ParentLayerToScreenMatrix4x4
APZCTreeManager::GetApzcToGeckoTransform(const AsyncPanZoomController *aApzc) const
{
Matrix4x4 result;
MutexAutoLock lock(mTreeLock);
RecursiveMutexAutoLock lock(mTreeLock);
// The comments below assume there is a chain of layers L..R with L and P having APZC instances as
// explained in the comment above. This function is called with aApzc at L, and the loop
@ -2814,7 +2813,7 @@ APZCTreeManager::GetCurrentMousePosition() const
already_AddRefed<AsyncPanZoomController>
APZCTreeManager::GetMultitouchTarget(AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const
{
MutexAutoLock lock(mTreeLock);
RecursiveMutexAutoLock lock(mTreeLock);
RefPtr<AsyncPanZoomController> apzc;
// For now, we only ever want to do pinching on the root-content APZC for
// a given layers id.
@ -2838,7 +2837,7 @@ APZCTreeManager::GetMultitouchTarget(AsyncPanZoomController* aApzc1, AsyncPanZoo
already_AddRefed<AsyncPanZoomController>
APZCTreeManager::CommonAncestor(AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const
{
mTreeLock.AssertCurrentThreadOwns();
mTreeLock.AssertCurrentThreadIn();
RefPtr<AsyncPanZoomController> ancestor;
// If either aApzc1 or aApzc2 is null, min(depth1, depth2) will be 0 and this function
@ -2884,7 +2883,7 @@ APZCTreeManager::CommonAncestor(AsyncPanZoomController* aApzc1, AsyncPanZoomCont
LayerToParentLayerMatrix4x4
APZCTreeManager::ComputeTransformForNode(const HitTestingTreeNode* aNode) const
{
mTreeLock.AssertCurrentThreadOwns();
mTreeLock.AssertCurrentThreadIn();
if (AsyncPanZoomController* apzc = aNode->GetApzc()) {
// If the node represents scrollable content, apply the async transform
// from its APZC.

View File

@ -18,7 +18,7 @@
#include "mozilla/layers/IAPZCTreeManager.h" // for IAPZCTreeManager
#include "mozilla/layers/KeyboardMap.h" // for KeyboardMap
#include "mozilla/layers/FocusState.h" // for FocusState
#include "mozilla/Mutex.h" // for Mutex
#include "mozilla/RecursiveMutex.h" // for RecursiveMutex
#include "mozilla/RefPtr.h" // for RefPtr
#include "mozilla/TimeStamp.h" // for mozilla::TimeStamp
#include "nsCOMPtr.h" // for already_AddRefed
@ -649,7 +649,7 @@ private:
* is considered part of the APZC tree management state.
* Finally, the lock needs to be held when accessing mZoomConstraints.
* IMPORTANT: See the note about lock ordering at the top of this file. */
mutable mozilla::Mutex mTreeLock;
mutable mozilla::RecursiveMutex mTreeLock;
RefPtr<HitTestingTreeNode> mRootNode;
/* Holds the zoom constraints for scrollable layers, as determined by the
* the main-thread gecko code. */

View File

@ -1826,6 +1826,9 @@ PresShell::Initialize(nscoord aWidth, nscoord aHeight)
// (Do this in a script runner, since our caller might have a script
// blocker on the stack.)
nsContentUtils::AddScriptRunner(new XBLConstructorRunner(mDocument));
// XBLConstructorRunner might destroy us.
NS_ENSURE_STATE(!mHaveShutDown);
}
NS_ASSERTION(rootFrame, "How did that happen?");

View File

@ -7,6 +7,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=348236
<title>Test for Bug 348236</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<style type="text/css">
#eSelect {
@ -41,25 +42,21 @@ addLoadEvent(function test() {
WinUtils = SpecialPowers.getDOMWindowUtils(window),
sec = netscape.security,
eSelect = $("eSelect"),
IDOMEvent = CI.nsIDOMEvent,
IDOMKeyEvent = CI.nsIDOMKeyEvent,
timeout = 0 // Choose a larger value like 500 ms if you want to see what's happening.
function keypressOnSelect(key, modifiers) {
function keypressOnSelect(key) {
WinUtils.focus(eSelect)
WinUtils.sendKeyEvent("keyup", key, 0, modifiers)
WinUtils.sendKeyEvent("keypress", key, 0, modifiers)
WinUtils.sendKeyEvent("keydown", key, 0, modifiers)
synthesizeKey(key.key, {code: key.code, altKey: key.altKey});
}
function testKey(key, modifiers, keyString, functionToContinue) {
function testKey(key, keyString, functionToContinue) {
var selectGotClick
function clickListener() { selectGotClick = true }
eSelect.selectedIndex = 0
eSelect.onchangeCount = 0
// Drop the SELECT down.
keypressOnSelect(key, modifiers)
keypressOnSelect(key)
// This timeout and the following are necessary to let the sent events take effect.
setTimeout(cont1, timeout)
function cont1() {
@ -69,7 +66,7 @@ addLoadEvent(function test() {
}
function cont2() {
// Close the select.
keypressOnSelect(key, modifiers)
keypressOnSelect(key)
setTimeout(cont3, timeout)
}
function cont3() {
@ -96,19 +93,19 @@ addLoadEvent(function test() {
is(eSelect.selectedIndex, 0, "SELECT selectedIndex should be 0 after load.")
// Check if sending key events works.
keypressOnSelect(IDOMKeyEvent.DOM_VK_DOWN, 0)
keypressOnSelect({key: "KEY_ArrowDown", code: "ArrowDown"});
is(eSelect.value, "2", "SELECT value should be 2 after pressing Down.")
// Test ALT-Down.
testKey(IDOMKeyEvent.DOM_VK_DOWN, IDOMEvent.ALT_MASK, "ALT-Down", nextKey1)
testKey({key: "KEY_ArrowDown", code: "ArrowDown", altKey: true}, "ALT-Down", nextKey1)
function nextKey1() {
// Test ALT-Up.
testKey(IDOMKeyEvent.DOM_VK_UP, IDOMEvent.ALT_MASK, "ALT-Up", nextKey2)
testKey({key: "KEY_ArrowUp", code: "ArrowUp", altKey: true}, "ALT-Up", nextKey2)
}
function nextKey2() {
// Test the F4 key on OS/2 and Windows.
if (/OS\/2|Win/i.test(navigator.platform))
testKey(IDOMKeyEvent.DOM_VK_F4, 0, "F4", finished)
// Test the F4 key on Windows.
if (/Win/i.test(navigator.platform))
testKey({key: "KEY_F4", code: "F4"}, "F4", finished)
else
finished()
}

View File

@ -6,6 +6,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=411236
<head>
<title>Test for Bug 411236</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
@ -24,21 +25,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=411236
window.oTarget = null;
window.fileInputGotClick = false;
function tab() {
var utils = SpecialPowers.DOMWindowUtils;
// Send tab key events.
var key = SpecialPowers.Ci.nsIDOMKeyEvent.DOM_VK_TAB;
utils.sendKeyEvent("keydown", key, 0, 0);
utils.sendKeyEvent("keypress", key, 0, 0);
utils.sendKeyEvent("keyup", key, 0, 0);
}
function test() {
// Try to find the 'Browse...' using tabbing.
var i = 0;
while (!window.oTarget && i < 100) {
++i;
tab();
synthesizeKey("KEY_Tab", {code: "Tab"});
}
if (i >= 100) {

View File

@ -156,11 +156,6 @@ FontSizeInflationListMarginAdjustment(const nsIFrame* aFrame)
return 0;
}
// NOTE: If we ever want to use SizeComputationInput for a flex item or a
// grid item, we need to make it take the containing-block block-size as
// well as the inline-size, since flex items and grid items resolve
// block-direction percent margins and padding against the
// containing-block block-size, rather than its inline-size.
SizeComputationInput::SizeComputationInput(nsIFrame *aFrame,
gfxContext *aRenderingContext,
WritingMode aContainingBlockWritingMode,
@ -169,16 +164,9 @@ SizeComputationInput::SizeComputationInput(nsIFrame *aFrame,
, mRenderingContext(aRenderingContext)
, mWritingMode(aFrame->GetWritingMode())
{
MOZ_ASSERT(!aFrame->IsFlexOrGridItem(),
"We're about to resolve percent margin & padding "
"values against CB inline size, which is incorrect for "
"flex/grid items. "
"Additionally for grid items, this path doesn't handle baseline "
"padding contribution - see SizeComputationInput::InitOffsets");
LogicalSize cbSize(aContainingBlockWritingMode, aContainingBlockISize,
aContainingBlockISize);
ReflowInputFlags flags;
InitOffsets(aContainingBlockWritingMode, cbSize, mFrame->Type(), flags);
InitOffsets(aContainingBlockWritingMode, aContainingBlockISize,
mFrame->Type(), flags);
}
// Initialize a reflow state for a child frame's reflow. Some state
@ -2208,27 +2196,6 @@ IsSideCaption(nsIFrame* aFrame, const nsStyleDisplay* aStyleDisplay,
captionSide == NS_STYLE_CAPTION_SIDE_RIGHT;
}
// Flex/grid items resolve block-axis percentage margin & padding against the
// containing block block-size (also for abs/fixed-pos child frames).
// For everything else: the CSS21 spec requires that margin and padding
// percentage values are calculated with respect to the inline-size of the
// containing block, even for margin & padding in the block axis.
static LogicalSize
OffsetPercentBasis(const nsIFrame* aFrame,
WritingMode aWM,
const LogicalSize& aContainingBlockSize)
{
LogicalSize offsetPercentBasis = aContainingBlockSize;
if (MOZ_LIKELY(!aFrame->GetParent() ||
!aFrame->GetParent()->IsFlexOrGridContainer())) {
offsetPercentBasis.BSize(aWM) = offsetPercentBasis.ISize(aWM);
} else if (offsetPercentBasis.BSize(aWM) == NS_AUTOHEIGHT) {
offsetPercentBasis.BSize(aWM) = 0;
}
return offsetPercentBasis;
}
// XXX refactor this code to have methods for each set of properties
// we are computing: width,height,line-height; margin; offsets
@ -2249,7 +2216,7 @@ ReflowInput::InitConstraints(nsPresContext* aPresContext,
// height equal to the available space
if (nullptr == mParentReflowInput || mFlags.mDummyParentReflowInput) {
// XXXldb This doesn't mean what it used to!
InitOffsets(wm, OffsetPercentBasis(mFrame, wm, aContainingBlockSize),
InitOffsets(wm, aContainingBlockSize.ISize(wm),
aFrameType, mFlags, aBorder, aPadding, mStyleDisplay);
// Override mComputedMargin since reflow roots start from the
// frame's boundary, which is inside the margin.
@ -2307,8 +2274,7 @@ ReflowInput::InitConstraints(nsPresContext* aPresContext,
// For calculating positioning offsets, margins, borders and
// padding, we use the writing mode of the containing block
WritingMode cbwm = cbri->GetWritingMode();
InitOffsets(cbwm, OffsetPercentBasis(mFrame, cbwm,
cbSize.ConvertTo(cbwm, wm)),
InitOffsets(cbwm, cbSize.ConvertTo(cbwm, wm).ISize(cbwm),
aFrameType, mFlags, aBorder, aPadding, mStyleDisplay);
// For calculating the size of this box, we use its own writing mode
@ -2582,7 +2548,7 @@ UpdateProp(nsIFrame* aFrame,
void
SizeComputationInput::InitOffsets(WritingMode aWM,
const LogicalSize& aPercentBasis,
nscoord aPercentBasis,
LayoutFrameType aFrameType,
ReflowInputFlags aFlags,
const nsMargin* aBorder,
@ -2953,7 +2919,7 @@ ReflowInput::CalcLineHeight(nsIContent* aContent,
bool
SizeComputationInput::ComputeMargin(WritingMode aWM,
const LogicalSize& aPercentBasis)
nscoord aPercentBasis)
{
// SVG text frames have no margin.
if (nsSVGUtils::IsInSVGTextSubtree(mFrame)) {
@ -2970,17 +2936,17 @@ SizeComputationInput::ComputeMargin(WritingMode aWM,
// (http://dev.w3.org/csswg/css-writing-modes-3/#orthogonal-flows)
LogicalMargin m(aWM);
m.IStart(aWM) = nsLayoutUtils::
ComputeCBDependentValue(aPercentBasis.ISize(aWM),
ComputeCBDependentValue(aPercentBasis,
styleMargin->mMargin.GetIStart(aWM));
m.IEnd(aWM) = nsLayoutUtils::
ComputeCBDependentValue(aPercentBasis.ISize(aWM),
ComputeCBDependentValue(aPercentBasis,
styleMargin->mMargin.GetIEnd(aWM));
m.BStart(aWM) = nsLayoutUtils::
ComputeCBDependentValue(aPercentBasis.BSize(aWM),
ComputeCBDependentValue(aPercentBasis,
styleMargin->mMargin.GetBStart(aWM));
m.BEnd(aWM) = nsLayoutUtils::
ComputeCBDependentValue(aPercentBasis.BSize(aWM),
ComputeCBDependentValue(aPercentBasis,
styleMargin->mMargin.GetBEnd(aWM));
SetComputedLogicalMargin(aWM, m);
@ -3001,7 +2967,7 @@ SizeComputationInput::ComputeMargin(WritingMode aWM,
bool
SizeComputationInput::ComputePadding(WritingMode aWM,
const LogicalSize& aPercentBasis,
nscoord aPercentBasis,
LayoutFrameType aFrameType)
{
// If style can provide us the padding directly, then use it.
@ -3022,17 +2988,17 @@ SizeComputationInput::ComputePadding(WritingMode aWM,
// clamp negative calc() results to 0
LogicalMargin p(aWM);
p.IStart(aWM) = std::max(0, nsLayoutUtils::
ComputeCBDependentValue(aPercentBasis.ISize(aWM),
ComputeCBDependentValue(aPercentBasis,
stylePadding->mPadding.GetIStart(aWM)));
p.IEnd(aWM) = std::max(0, nsLayoutUtils::
ComputeCBDependentValue(aPercentBasis.ISize(aWM),
ComputeCBDependentValue(aPercentBasis,
stylePadding->mPadding.GetIEnd(aWM)));
p.BStart(aWM) = std::max(0, nsLayoutUtils::
ComputeCBDependentValue(aPercentBasis.BSize(aWM),
ComputeCBDependentValue(aPercentBasis,
stylePadding->mPadding.GetBStart(aWM)));
p.BEnd(aWM) = std::max(0, nsLayoutUtils::
ComputeCBDependentValue(aPercentBasis.BSize(aWM),
ComputeCBDependentValue(aPercentBasis,
stylePadding->mPadding.GetBEnd(aWM)));
SetComputedLogicalPadding(aWM, p);

View File

@ -247,7 +247,7 @@ public:
static void* DisplayInitOffsetsEnter(
nsIFrame* aFrame,
SizeComputationInput* aState,
const mozilla::LogicalSize& aPercentBasis,
nscoord aPercentBasis,
WritingMode aCBWritingMode,
const nsMargin* aBorder,
const nsMargin* aPadding);
@ -263,19 +263,12 @@ private:
*
* @param aWM Writing mode of the containing block
* @param aPercentBasis
* Logical size in the writing mode of the containing block to use
* for resolving percentage margin values in the inline and block
* axes.
* The inline size is usually the containing block inline-size
* (width if writing mode is horizontal, and height if vertical).
* The block size is usually the containing block inline-size, per
* CSS21 sec 8.3 (read in conjunction with CSS Writing Modes sec
* 7.2), but may be the containing block block-size, e.g. in CSS3
* Flexbox and Grid.
* Inline size of the containing block (in its own writing mode), to use
* for resolving percentage margin values in the inline and block axes.
* @return true if the margin is dependent on the containing block size.
*/
bool ComputeMargin(mozilla::WritingMode aWM,
const mozilla::LogicalSize& aPercentBasis);
nscoord aPercentBasis);
/**
* Computes padding values from the specified padding style information, and
@ -283,24 +276,17 @@ private:
*
* @param aWM Writing mode of the containing block
* @param aPercentBasis
* Logical size in the writing mode of the containing block to use
* for resolving percentage padding values in the inline and block
* axes.
* The inline size is usually the containing block inline-size
* (width if writing mode is horizontal, and height if vertical).
* The block size is usually the containing block inline-size, per
* CSS21 sec 8.3 (read in conjunction with CSS Writing Modes sec
* 7.2), but may be the containing block block-size, e.g. in CSS3
* Flexbox and Grid.
* Inline size of the containing block (in its own writing mode), to use
* for resolving percentage padding values in the inline and block axes.
* @return true if the padding is dependent on the containing block size.
*/
bool ComputePadding(mozilla::WritingMode aWM,
const mozilla::LogicalSize& aPercentBasis,
nscoord aPercentBasis,
mozilla::LayoutFrameType aFrameType);
protected:
void InitOffsets(mozilla::WritingMode aWM,
const mozilla::LogicalSize& aPercentBasis,
nscoord aPercentBasis,
mozilla::LayoutFrameType aFrameType,
ReflowInputFlags aFlags,
const nsMargin* aBorder = nullptr,

View File

@ -212,7 +212,7 @@ LOCAL_INCLUDES += [
JAR_MANIFESTS += ['jar.mn']
RESOURCE_FILES.html = [
CONTENT_ACCESSIBLE_FILES.html = [
'folder.png',
]

View File

@ -11563,7 +11563,7 @@ DR_init_constraints_cookie::~DR_init_constraints_cookie()
DR_init_offsets_cookie::DR_init_offsets_cookie(
nsIFrame* aFrame,
SizeComputationInput* aState,
const LogicalSize& aPercentBasis,
nscoord aPercentBasis,
WritingMode aCBWritingMode,
const nsMargin* aMargin,
const nsMargin* aPadding)
@ -12523,7 +12523,7 @@ ReflowInput::DisplayInitConstraintsExit(nsIFrame* aFrame,
/* static */ void*
SizeComputationInput::DisplayInitOffsetsEnter(nsIFrame* aFrame,
SizeComputationInput* aState,
const LogicalSize& aPercentBasis,
nscoord aPercentBasis,
WritingMode aCBWritingMode,
const nsMargin* aBorder,
const nsMargin* aPadding)
@ -12539,13 +12539,9 @@ SizeComputationInput::DisplayInitOffsetsEnter(nsIFrame* aFrame,
if (treeNode && treeNode->mDisplay) {
DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
char horizPctBasisStr[16];
char vertPctBasisStr[16];
DR_state->PrettyUC(aPercentBasis.ISize(aCBWritingMode),
horizPctBasisStr, 16);
DR_state->PrettyUC(aPercentBasis.BSize(aCBWritingMode),
vertPctBasisStr, 16);
printf("InitOffsets pct_basis=%s,%s", horizPctBasisStr, vertPctBasisStr);
char pctBasisStr[16];
DR_state->PrettyUC(aPercentBasis, pctBasisStr, 16);
printf("InitOffsets pct_basis=%s", pctBasisStr);
DR_state->PrintMargin("b", aBorder);
DR_state->PrintMargin("p", aPadding);

View File

@ -835,7 +835,7 @@ public:
struct DR_init_offsets_cookie {
DR_init_offsets_cookie(nsIFrame* aFrame, mozilla::SizeComputationInput* aState,
const mozilla::LogicalSize& aPercentBasis,
nscoord aPercentBasis,
mozilla::WritingMode aCBWritingMode,
const nsMargin* aBorder,
const nsMargin* aPadding);

View File

@ -555,6 +555,13 @@ static void GetOtherValuesForProperty(const uint32_t aParserVariant,
InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-repeating-linear-gradient"));
InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-repeating-radial-gradient"));
}
if (aParserVariant & VARIANT_ATTR) {
InsertNoDuplicates(aArray, NS_LITERAL_STRING("attr"));
}
if (aParserVariant & VARIANT_COUNTER) {
InsertNoDuplicates(aArray, NS_LITERAL_STRING("counter"));
InsertNoDuplicates(aArray, NS_LITERAL_STRING("counters"));
}
}
/* static */ void
@ -691,7 +698,6 @@ PropertySupportsVariant(nsCSSPropertyID aPropertyID, uint32_t aVariant)
supported |= VARIANT_LENGTH;
break;
case eCSSProperty_content:
case eCSSProperty_cursor:
supported |= VARIANT_URL;
break;

View File

@ -208,6 +208,14 @@ function do_test() {
var values = InspectorUtils.getCSSValuesForProperty("clip");
ok(testValues(values, expected), "property clip's values");
// Regression test for bug 1255380.
var expected = [ "normal", "none", "url", "counter", "counters",
"attr", "open-quote", "close-quote", "no-open-quote",
"no-close-quote", "inherit", "initial", "unset",
"-moz-alt-content" ];
var values = InspectorUtils.getCSSValuesForProperty("content");
ok(testValues(values, expected), "property counter's values");
SimpleTest.finish();
}

View File

@ -62,40 +62,31 @@ b40 {
z-index: 1; position:relative;
}
w {
position:absolute;
background: lime;
border-width: 1px 0 0 3px;
border-style: solid;
height:48px;
width:75px;
.h.r {
height: 42px;
width: 42px;
/* This margin-left is 20% of 98px-wide grid area */
margin-left: 19.6px;
/* This padding-bottom is 10% of 98px wide grid area */
/* This padding-left is 30% of 98px wide grid area */
padding: 1px 3px 9.8px 29.4px;
}
.v > w {
border-width: 3px 0 0 1px;
left:-1px; top:-3px;
height:53px;
width:61px;
}
.h.r { margin-left:19px; padding: 1px 15px 37px 30px; }
.v .h > w {
height:48px;
width:45px;
}
.v.r > w {
height:53px;
width:61px;
}
.v .v > w {
height:41px;
width:45px;
.v.r {
height: 42px;
width: 42px;
/* This margin-left is 20% of 54px-wide grid area */
margin-left: 10.8px;
/* This padding-bottom is 10% of 54px wide grid area */
/* This padding-left is 30% of 54px wide grid area */
padding: 1px 3px 5.4px 16.2px;
}
.r { position:relative; }
.t6 { width:46px; }
.t8 { width:118px; }
.t8 { width:118px; height: 102.5px; }
xx {
xx {
display: block;
background: lime;
padding:32px 32px 16px 32px;
@ -114,7 +105,7 @@ xx {
<div class="grid"><span class="v"><x></x></span></div>
<div class="grid t6"><span class="v bb"><x></x></span></div>
<div class="grid"><span class="v"><x></x></span><span class="v"><x></x></span></div>
<div class="grid t8"><span class="v r"><w></w><b40></b40></span></div>
<div class="grid t8"><span class="v r"><b40></b40></span></div>
<div class="grid"><xx class="v"></xx></div>
<div class="grid v"><xx class="h"></xx></div>

View File

@ -30,8 +30,8 @@ body,html { color:black; background:white; font-size:16px; padding:0; margin:0;
}
.p { padding:2px 3px; }
.m { margin:2px 3px; }
.c1.p,.c2.p { padding:5px 9px; }
.c1.m,.c2.m { margin:5px 9px; }
.c1.p,.c2.p { padding:6px 9px; }
.c1.m,.c2.m { margin:6px 9px; }
.b { border:solid black; }
#t1 { width:50px; height: 20px; }

View File

@ -48,8 +48,8 @@ body,html { color:black; background:white; font-size:16px; padding:0; margin:0;
box-sizing: border-box;
}
.p { padding:10% 6%; }
.m { margin:10% 6%; }
.p { padding:4% 6%; }
.m { margin:4% 6%; }
.b { border:solid black; }
</style>

View File

@ -46,8 +46,8 @@ body,html { color:black; background:white; font-size:16px; padding:0; margin:0;
.p { padding:2px 3px; }
.m { margin:2px 3px; }
.c1.p,.c2.p { padding:5px 9px; }
.c1.m,.c2.m { margin:5px 9px; }
.c1.p,.c2.p { padding:6px 9px; }
.c1.m,.c2.m { margin:6px 9px; }
.b { border:solid black; }
</style>

View File

@ -43,7 +43,7 @@ skip-if(Android) fuzzy-if(winWidget,1,32) == grid-placement-auto-implicit-001.ht
== vrl-grid-placement-auto-row-sparse-001.html vrl-grid-placement-auto-row-sparse-001-ref.html
== grid-relpos-items-001.html grid-relpos-items-001-ref.html
== grid-item-sizing-percent-001.html grid-item-sizing-percent-001-ref.html
== grid-item-sizing-percent-002.html grid-item-sizing-percent-002-ref.html
fails == grid-item-sizing-percent-002.html grid-item-sizing-percent-002-ref.html # bug 1434397
== grid-item-sizing-percent-003.html grid-item-sizing-percent-003-ref.html
== grid-item-sizing-percent-004.html grid-item-sizing-percent-004-ref.html
== grid-item-sizing-px-001.html grid-item-sizing-percent-001-ref.html

View File

@ -4,8 +4,7 @@
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!-- Reference case - identical to the testcase, but with with the flex items'
vertical margin and padding values set to 0 by default, and then set to
specific pixel values for the items that have a 50px percent-basis.
margin and padding values set to explicit pixel values.
-->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
@ -21,27 +20,11 @@
}
div.height50 { height: 50px; }
.marginA { margin: 0 8% 0 4%; }
.marginB { margin: 0 10% 0 14%; }
.paddingA { padding: 0 6% 0 2%; }
.paddingB { padding: 0 8% 0 12%; }
.marginA { margin: 20px 16px 12px 8px; }
.marginB { margin: 16px 20px 24px 28px; }
.paddingA { padding: 16px 12px 8px 4px; }
.paddingB { padding: 12px 16px 20px 24px; }
div.height50 > .marginA {
margin-top: 5px;
margin-bottom: 3px;
}
div.height50 > .marginB {
margin-top: 4px;
margin-bottom: 6px;
}
div.height50 > .paddingA {
padding-top: 4px;
padding-bottom: 2px;
}
div.height50 > .paddingB {
padding-top: 3px;
padding-bottom: 5px;
}
div.child1 {
flex: none;

View File

@ -3,19 +3,17 @@
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!-- Testcase with percent-valued padding and/or margin on flex items. The spec
says that percentage values on padding/margin-top and -bottom should be
resolved against the flex container's height (not its width, as would
be the case in a block).
<!-- Testcase with percent-valued padding and/or margin on flex items.
The spec allows these to be resolved against the flex container's
inline size (regardless of which axis the percent padding/margin is in).
-->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>CSS Test: Testing percent-valued padding and margin on flex items</title>
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com"/>
<link rel="help" href="http://www.w3.org/TR/css-flexbox-1/#layout-algorithm"/>
<link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#item-margins"/>
<link rel="match" href="flexbox-mbp-horiz-004-ref.xhtml"/>
<style>
div { border: 0; }
div.flexbox {
width: 200px;
display: flex;
@ -52,8 +50,9 @@
</style>
</head>
<body>
<!-- Flex container is auto-height - vertical margin and padding should
resolve to 0, since they don't have anything to resolve % against. -->
<!-- Flex container is auto-height - this shouldn't impact percent
margin/padding resolution, since they resolve against container's
inline-size, i.e. its width in this case. -->
<div class="flexbox"
><div class="child1 paddingA"><div class="filler"/></div
><div class="child2 paddingB"><div class="filler"/></div
@ -61,8 +60,9 @@
><div class="child2 marginB"></div
></div>
<!-- Flex container has height: 50px - vertical margin and padding should
resolve % values against that. -->
<!-- Flex container has height: 50px - again, this shouldn't impact percent
margin/padding resolution, since they resolve against container's
inline-size, i.e. its width in this case. -->
<div class="flexbox height50"
><div class="child1 paddingA"><div class="filler"/></div
><div class="child2 paddingB"><div class="filler"/></div

View File

@ -1037,6 +1037,21 @@ AttrHasSuffix(Implementor* aElement, nsAtom* aNS, nsAtom* aName,
return DoMatch(aElement, aNS, aName, match);
}
/**
* Returns whether an element contains a class in its class list or not.
*/
template <typename Implementor>
static bool
HasClass(Implementor* aElement, nsAtom* aClass, bool aIgnoreCase)
{
const nsAttrValue* attr = aElement->DoGetClasses();
if (!attr) {
return false;
}
return attr->Contains(aClass, aIgnoreCase ? eIgnoreCase : eCaseMatters);
}
/**
* Gets the class or class list (if any) of the implementor. The calling
* convention here is rather hairy, and is optimized for getting Servo the
@ -1106,53 +1121,58 @@ ClassOrClassList(Implementor* aElement, nsAtom** aClass, nsAtom*** aClassList)
}
#define SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(prefix_, implementor_) \
nsAtom* prefix_##AtomAttrValue(implementor_ aElement, nsAtom* aName) \
nsAtom* prefix_##AtomAttrValue(implementor_ aElement, nsAtom* aName) \
{ \
return AtomAttrValue(aElement, aName); \
} \
nsAtom* prefix_##LangValue(implementor_ aElement) \
nsAtom* prefix_##LangValue(implementor_ aElement) \
{ \
return LangValue(aElement); \
} \
bool prefix_##HasAttr(implementor_ aElement, nsAtom* aNS, nsAtom* aName) \
bool prefix_##HasAttr(implementor_ aElement, nsAtom* aNS, nsAtom* aName) \
{ \
return HasAttr(aElement, aNS, aName); \
} \
bool prefix_##AttrEquals(implementor_ aElement, nsAtom* aNS, \
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) \
bool prefix_##AttrEquals(implementor_ aElement, nsAtom* aNS, \
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) \
{ \
return AttrEquals(aElement, aNS, aName, aStr, aIgnoreCase); \
} \
bool prefix_##AttrDashEquals(implementor_ aElement, nsAtom* aNS, \
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) \
bool prefix_##AttrDashEquals(implementor_ aElement, nsAtom* aNS, \
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) \
{ \
return AttrDashEquals(aElement, aNS, aName, aStr, aIgnoreCase); \
} \
bool prefix_##AttrIncludes(implementor_ aElement, nsAtom* aNS, \
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) \
bool prefix_##AttrIncludes(implementor_ aElement, nsAtom* aNS, \
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) \
{ \
return AttrIncludes(aElement, aNS, aName, aStr, aIgnoreCase); \
} \
bool prefix_##AttrHasSubstring(implementor_ aElement, nsAtom* aNS, \
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase)\
bool prefix_##AttrHasSubstring(implementor_ aElement, nsAtom* aNS, \
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) \
{ \
return AttrHasSubstring(aElement, aNS, aName, aStr, aIgnoreCase); \
} \
bool prefix_##AttrHasPrefix(implementor_ aElement, nsAtom* aNS, \
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) \
bool prefix_##AttrHasPrefix(implementor_ aElement, nsAtom* aNS, \
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) \
{ \
return AttrHasPrefix(aElement, aNS, aName, aStr, aIgnoreCase); \
} \
bool prefix_##AttrHasSuffix(implementor_ aElement, nsAtom* aNS, \
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) \
bool prefix_##AttrHasSuffix(implementor_ aElement, nsAtom* aNS, \
nsAtom* aName, nsAtom* aStr, bool aIgnoreCase) \
{ \
return AttrHasSuffix(aElement, aNS, aName, aStr, aIgnoreCase); \
} \
uint32_t prefix_##ClassOrClassList(implementor_ aElement, nsAtom** aClass, \
nsAtom*** aClassList) \
uint32_t prefix_##ClassOrClassList(implementor_ aElement, nsAtom** aClass, \
nsAtom*** aClassList) \
{ \
return ClassOrClassList(aElement, aClass, aClassList); \
}
} \
bool prefix_##HasClass(implementor_ aElement, nsAtom* aClass, bool aIgnoreCase)\
{ \
return HasClass(aElement, aClass, aIgnoreCase); \
} \
SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_, RawGeckoElementBorrowed)
SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_Snapshot, const ServoElementSnapshot*)

View File

@ -196,24 +196,26 @@ nsIDocument::DocumentTheme Gecko_GetDocumentLWTheme(const nsIDocument* aDocument
// Attributes.
#define SERVO_DECLARE_ELEMENT_ATTR_MATCHING_FUNCTIONS(prefix_, implementor_) \
nsAtom* prefix_##AtomAttrValue(implementor_ element, nsAtom* attribute); \
nsAtom* prefix_##LangValue(implementor_ element); \
bool prefix_##HasAttr(implementor_ element, nsAtom* ns, nsAtom* name); \
bool prefix_##AttrEquals(implementor_ element, nsAtom* ns, nsAtom* name, \
nsAtom* str, bool ignoreCase); \
bool prefix_##AttrDashEquals(implementor_ element, nsAtom* ns, \
nsAtom* name, nsAtom* str, bool ignore_case);\
bool prefix_##AttrIncludes(implementor_ element, nsAtom* ns, \
nsAtom* name, nsAtom* str, bool ignore_case); \
bool prefix_##AttrHasSubstring(implementor_ element, nsAtom* ns, \
nsAtom* name, nsAtom* str, \
nsAtom* prefix_##AtomAttrValue(implementor_ element, nsAtom* attribute); \
nsAtom* prefix_##LangValue(implementor_ element); \
bool prefix_##HasAttr(implementor_ element, nsAtom* ns, nsAtom* name); \
bool prefix_##AttrEquals(implementor_ element, nsAtom* ns, nsAtom* name, \
nsAtom* str, bool ignoreCase); \
bool prefix_##AttrDashEquals(implementor_ element, nsAtom* ns, \
nsAtom* name, nsAtom* str, bool ignore_case); \
bool prefix_##AttrIncludes(implementor_ element, nsAtom* ns, \
nsAtom* name, nsAtom* str, bool ignore_case); \
bool prefix_##AttrHasSubstring(implementor_ element, nsAtom* ns, \
nsAtom* name, nsAtom* str, \
bool ignore_case); \
bool prefix_##AttrHasPrefix(implementor_ element, nsAtom* ns, \
nsAtom* name, nsAtom* str, bool ignore_case); \
bool prefix_##AttrHasSuffix(implementor_ element, nsAtom* ns, \
nsAtom* name, nsAtom* str, bool ignore_case); \
uint32_t prefix_##ClassOrClassList(implementor_ element, nsAtom** class_, \
nsAtom*** classList);
bool prefix_##AttrHasPrefix(implementor_ element, nsAtom* ns, \
nsAtom* name, nsAtom* str, bool ignore_case); \
bool prefix_##AttrHasSuffix(implementor_ element, nsAtom* ns, \
nsAtom* name, nsAtom* str, bool ignore_case); \
uint32_t prefix_##ClassOrClassList(implementor_ element, nsAtom** class_, \
nsAtom*** classList); \
bool prefix_##HasClass(implementor_ element, nsAtom* class_, \
bool ignore_case);
SERVO_DECLARE_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_, RawGeckoElementBorrowed)
SERVO_DECLARE_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_Snapshot,

View File

@ -1552,7 +1552,7 @@ CSS_PROP_CONTENT(
CSS_PROPERTY_PARSE_FUNCTION |
CSS_PROPERTY_START_IMAGE_LOADS,
"",
0,
VARIANT_HMK | VARIANT_NONE | VARIANT_URL | VARIANT_COUNTER | VARIANT_ATTR,
kContentKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_Discrete)

View File

@ -6,6 +6,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=812687
<head>
<title>Test for Bug 812687: focus order of reordered flex items</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<style>
.container { display: flex; }
@ -42,7 +43,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=812687
/** Test for Bug 812687 **/
const gKeyCodeForTab = 9;
const gExpectedFocusedIds = [
"focus1",
"focus2",
@ -60,7 +60,7 @@ function doTest() {
// And then we advance focus across the focusable things in the flex container
// and check that we traverse them in the expected order:
for (let expectedId of gExpectedFocusedIds) {
SpecialPowers.DOMWindowUtils.sendKeyEvent('keypress', gKeyCodeForTab, 0, 0);
synthesizeKey("KEY_Tab", {code: "Tab"});
is(document.activeElement, document.getElementById(expectedId),
"expecting element '#" + expectedId + "' to be focused");
}

View File

@ -52,6 +52,11 @@ SVGContextPaint::IsAllowedForImageFromURI(nsIURI* aURI)
// use this feature because we're not sure that image context paint is a
// good mechanism for wider use, or suitable for specification.)
//
// Because the default favicon used in the browser UI needs context paint, we
// also allow it for page-icon:<page-url>. This exposes context paint to
// 3rd-party favicons, but only for history and bookmark items. Other places
// such as the tab bar don't use the page-icon protocol to load favicons.
//
// One case that is not covered by chrome:// or resource:// are WebExtensions,
// specifically ones that are "ours". WebExtensions are moz-extension://
// regardless if the extension is in-tree or not. Since we don't want
@ -60,7 +65,9 @@ SVGContextPaint::IsAllowedForImageFromURI(nsIURI* aURI)
//
nsAutoCString scheme;
if (NS_SUCCEEDED(aURI->GetScheme(scheme)) &&
(scheme.EqualsLiteral("chrome") || scheme.EqualsLiteral("resource"))) {
(scheme.EqualsLiteral("chrome")
|| scheme.EqualsLiteral("resource")
|| scheme.EqualsLiteral("page-icon"))) {
return true;
}
RefPtr<BasePrincipal> principal = BasePrincipal::CreateCodebasePrincipal(aURI, OriginAttributes());

View File

@ -4343,8 +4343,9 @@ SVGTextFrame::GetStartPositionOfChar(nsIContent* aContent,
// We need to return the start position of the whole glyph.
uint32_t startIndex = it.GlyphStartTextElementCharIndex();
NS_ADDREF(*aResult =
new DOMSVGPoint(ToPoint(mPositions[startIndex].mPosition)));
RefPtr<DOMSVGPoint> point =
new DOMSVGPoint(ToPoint(mPositions[startIndex].mPosition));
point.forget(aResult);
return NS_OK;
}
@ -4388,7 +4389,8 @@ SVGTextFrame::GetEndPositionOfChar(nsIContent* aContent,
Matrix::Translation(ToPoint(mPositions[startIndex].mPosition));
Point p = m.TransformPoint(Point(advance / mFontSizeScaleFactor, 0));
NS_ADDREF(*aResult = new DOMSVGPoint(p));
RefPtr<DOMSVGPoint> point = new DOMSVGPoint(p);
point.forget(aResult);
return NS_OK;
}
@ -4455,7 +4457,8 @@ SVGTextFrame::GetExtentOfChar(nsIContent* aContent,
// Transform the glyph's rect into user space.
gfxRect r = m.TransformBounds(glyphRect);
NS_ADDREF(*aResult = new dom::SVGRect(aContent, r.x, r.y, r.width, r.height));
RefPtr<dom::SVGRect> rect = new dom::SVGRect(aContent, r.x, r.y, r.width, r.height);
rect.forget(aResult);
return NS_OK;
}

View File

@ -468,7 +468,6 @@
@BINPATH@/res/table-remove-row.gif
@BINPATH@/res/grabber.gif
@BINPATH@/res/dtd/*
@BINPATH@/res/html/*
@BINPATH@/res/language.properties
#ifndef MOZ_ANDROID_EXCLUDE_FONTS

View File

@ -57,6 +57,17 @@
*/
#if defined(CHROMIUM_SANDBOX_BUILD) && defined(XP_WIN)
#include "base/win/sdkdecls.h"
#endif
#ifdef __MINGW32__
/*
* MinGW doesn't support __try / __except. There are a few mechanisms available
* to hack around it and pseudo-support it, but these are untested in Firefox.
* What is tested (and works) is replacing them with if(true) and else.
*/
#define __try if(true)
#define __except(x) else
#endif /* __MINGW32__ */
#endif /* defined(CHROMIUM_SANDBOX_BUILD) && defined(XP_WIN) */
#endif /* MOZILLA_CONFIG_H */

View File

@ -351,7 +351,7 @@ nsIndexedToHTML::DoOnStartRequest(nsIRequest* request, nsISupports *aContext,
" vertical-align: middle;\n"
"}\n"
".dir::before {\n"
" content: url(resource://gre/res/html/folder.png);\n"
" content: url(resource://content-accessible/html/folder.png);\n"
"}\n"
"</style>\n"
"<link rel=\"stylesheet\" media=\"screen, projection\" type=\"text/css\""

View File

@ -66,7 +66,7 @@ W32API_VERSION=3.14
GCONF_VERSION=1.2.1
STARTUP_NOTIFICATION_VERSION=0.8
DBUS_VERSION=0.60
SQLITE_VERSION=3.21.0
SQLITE_VERSION=3.22.0
dnl Set various checks
dnl ========================================================

View File

@ -203,6 +203,65 @@ class BuildBackend(LoggingMixin):
"""
return None
def _write_purgecaches(self, config):
"""Write .purgecaches sentinels.
The purgecaches mechanism exists to allow the platform to
invalidate the XUL cache (which includes some JS) at application
startup-time. The application checks for .purgecaches in the
application directory, which varies according to
--enable-application. There's a further wrinkle on macOS, where
the real application directory is part of a Cocoa bundle
produced from the regular application directory by the build
system. In this case, we write to both locations, since the
build system recreates the Cocoa bundle from the contents of the
regular application directory and might remove a sentinel
created here.
"""
app = config.substs['MOZ_BUILD_APP']
if app == 'mobile/android':
# In order to take effect, .purgecaches sentinels would need to be
# written to the Android device file system.
return
root = mozpath.join(config.topobjdir, 'dist', 'bin')
if app == 'browser':
root = mozpath.join(config.topobjdir, 'dist', 'bin', 'browser')
purgecaches_dirs = [root]
if app == 'browser' and 'cocoa' == config.substs['MOZ_WIDGET_TOOLKIT']:
bundledir = mozpath.join(config.topobjdir, 'dist',
config.substs['MOZ_MACBUNDLE_NAME'],
'Contents', 'Resources',
'browser')
purgecaches_dirs.append(bundledir)
for dir in purgecaches_dirs:
with open(mozpath.join(dir, '.purgecaches'), 'wt') as f:
f.write('\n')
def post_build(self, config, output, jobs, verbose, status):
"""Called late during 'mach build' execution, after `build(...)` has finished.
`status` is the status value returned from `build(...)`.
In the case where `build` returns `None`, this is called after
the default `make` command has completed, with the status of
that command.
This should return the status value from `build(...)`, or the
status value of a subprocess, where 0 denotes success and any
other value is an error code.
If an exception is raised, |mach build| will fail with a
non-zero exit code.
"""
self._write_purgecaches(config)
return status
@contextmanager
def _write_file(self, path=None, fh=None, mode='rU'):
"""Context manager to write a file.

View File

@ -1078,6 +1078,23 @@ class BuildDriver(MozbuildObject):
{'count': len(monitor.warnings_database)},
'{count} compiler warnings present.')
# Try to run the active build backend's post-build step, if possible.
try:
config = self.config_environment
active_backend = config.substs.get('BUILD_BACKENDS', [None])[0]
if active_backend:
backend_cls = get_backend_class(active_backend)(config)
new_status = backend_cls.post_build(self, output, jobs, verbose, status)
status = new_status
except Exception as ex:
self.log(logging.DEBUG, 'post_build', {'ex': ex},
"Unable to run active build backend's post-build step; " +
"failing the build due to exception: {ex}.")
if not status:
# If the underlying build provided a failing status, pass
# it through; otherwise, fail.
status = 1
monitor.finish(record_usage=status == 0)
# Print the collected compiler warnings. This is redundant with

View File

@ -0,0 +1,51 @@
# HG changeset patch
# User Tom Ritter <tom@mozilla.com>
# Date 1516389982 21600
# Fri Jan 19 13:26:22 2018 -0600
# Node ID 3ca7306d73ebc1ce47ccdc62ee8cbb69a9bfbb2c
# Parent 6aa6c7d894609140ccde2e9e50eba8c25a9caeb5
Bug 1431803 Disable a specific __try block on MinGW r?bobowen
This function is a technique to name a thread for debugging purposes,
and it always throws an exception (and then continues). On MinGW
we don't want it to throw an exception, so we do nothing.
This means on MinGW we won't get nice thread naming during debugging,
but we'll limp along.
MozReview-Commit-ID: JRKY4wp7sdu
diff --git a/security/sandbox/chromium/base/threading/platform_thread_win.cc b/security/sandbox/chromium/base/threading/platform_thread_win.cc
--- a/security/sandbox/chromium/base/threading/platform_thread_win.cc
+++ b/security/sandbox/chromium/base/threading/platform_thread_win.cc
@@ -32,27 +32,30 @@ typedef struct tagTHREADNAME_INFO {
} THREADNAME_INFO;
// The SetThreadDescription API was brought in version 1607 of Windows 10.
typedef HRESULT(WINAPI* SetThreadDescription)(HANDLE hThread,
PCWSTR lpThreadDescription);
// This function has try handling, so it is separated out of its caller.
void SetNameInternal(PlatformThreadId thread_id, const char* name) {
+ //This function is only used for debugging purposes, as you can find by its caller
+#ifndef __MINGW32__
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = name;
info.dwThreadID = thread_id;
info.dwFlags = 0;
__try {
RaiseException(kVCThreadNameException, 0, sizeof(info)/sizeof(DWORD),
reinterpret_cast<DWORD_PTR*>(&info));
} __except(EXCEPTION_CONTINUE_EXECUTION) {
}
+#endif
}
struct ThreadParams {
PlatformThread::Delegate* delegate;
bool joinable;
ThreadPriority priority;
};

View File

@ -17,4 +17,5 @@ mingw_msvc_requirement_error.patch
mingw_copy_s.patch
mingw_operator_new.patch
mingw_cast_getprocaddress.patch
mingw_capitalization.patch
mingw_capitalization.patch
mingw_disable_one_try.patch

View File

@ -37,6 +37,8 @@ typedef HRESULT(WINAPI* SetThreadDescription)(HANDLE hThread,
// This function has try handling, so it is separated out of its caller.
void SetNameInternal(PlatformThreadId thread_id, const char* name) {
//This function is only used for debugging purposes, as you can find by its caller
#ifndef __MINGW32__
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = name;
@ -48,6 +50,7 @@ void SetNameInternal(PlatformThreadId thread_id, const char* name) {
reinterpret_cast<DWORD_PTR*>(&info));
} __except(EXCEPTION_CONTINUE_EXECUTION) {
}
#endif
}
struct ThreadParams {

View File

@ -868,35 +868,6 @@ add_task(async function test_async_onItemKeywordDeleted() {
}
});
add_task(async function test_onItemPostDataChanged() {
_("Post data changes should be tracked");
try {
await stopTracking();
_("Insert a bookmark");
let fx_id = PlacesUtils.bookmarks.insertBookmark(
PlacesUtils.bookmarks.bookmarksMenuFolder,
CommonUtils.makeURI("http://getfirefox.com"),
PlacesUtils.bookmarks.DEFAULT_INDEX,
"Get Firefox!");
let fx_guid = await PlacesUtils.promiseItemGuid(fx_id);
_(`Firefox GUID: ${fx_guid}`);
await startTracking();
// PlacesUtils.setPostDataForBookmark is deprecated, but still used by
// PlacesTransactions.NewBookmark.
_("Post data for the bookmark should be ignored");
await PlacesUtils.setPostDataForBookmark(fx_id, "postData");
await verifyTrackedItems([]);
Assert.equal(tracker.score, 0);
} finally {
_("Clean up.");
await cleanup();
}
});
add_task(async function test_onItemAnnoChanged() {
_("Item annotations should be tracked");

74
servo/Cargo.lock generated
View File

@ -744,31 +744,6 @@ name = "either"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "embedding"
version = "0.0.1"
dependencies = [
"cocoa 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"compositing 0.0.1",
"devtools 0.0.1",
"euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gleam 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
"glutin_app 0.0.1",
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"libservo 0.0.1",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"msg 0.0.1",
"net_traits 0.0.1",
"objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"script_traits 0.0.1",
"servo_config 0.0.1",
"servo_geometry 0.0.1",
"servo_url 0.0.1",
"style_traits 0.0.1",
"webrender_api 0.57.0 (git+https://github.com/servo/webrender)",
"x11 2.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "encoding_rs"
version = "0.7.1"
@ -1076,34 +1051,6 @@ name = "glob"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "glutin_app"
version = "0.0.1"
dependencies = [
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"compositing 0.0.1",
"euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gleam 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
"libservo 0.0.1",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"msg 0.0.1",
"net_traits 0.0.1",
"osmesa-src 17.3.1-devel (git+https://github.com/servo/osmesa-src)",
"osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"script_traits 0.0.1",
"servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"servo-glutin 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_config 0.0.1",
"servo_geometry 0.0.1",
"servo_url 0.0.1",
"style_traits 0.0.1",
"user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.57.0 (git+https://github.com/servo/webrender)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"x11 2.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "glx"
version = "0.2.2"
@ -2621,11 +2568,30 @@ version = "0.0.1"
dependencies = [
"android_injected_glue 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"browserhtml 0.1.17 (git+https://github.com/browserhtml/browserhtml?branch=crate)",
"glutin_app 0.0.1",
"compositing 0.0.1",
"euclid 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gleam 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
"libservo 0.0.1",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"msg 0.0.1",
"net_traits 0.0.1",
"osmesa-src 17.3.1-devel (git+https://github.com/servo/osmesa-src)",
"osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"script_traits 0.0.1",
"servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"servo-glutin 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_config 0.0.1",
"servo_geometry 0.0.1",
"servo_url 0.0.1",
"sig 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"style_traits 0.0.1",
"user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.57.0 (git+https://github.com/servo/webrender)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"x11 2.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]

View File

@ -5,8 +5,6 @@ members = [
"ports/geckolib",
"ports/geckolib/tests",
"ports/cef",
]
default-members = [
"ports/servo",

View File

@ -32,7 +32,7 @@ use dom::mouseevent::MouseEvent;
use dom::node::{Node, NodeDamage, UnbindContext};
use dom::node::{document_from_node, window_from_node};
use dom::nodelist::NodeList;
use dom::textcontrol::TextControl;
use dom::textcontrol::{TextControlElement, TextControlSelection};
use dom::validation::Validatable;
use dom::validitystate::ValidationFlags;
use dom::virtualmethods::VirtualMethods;
@ -400,11 +400,7 @@ impl LayoutHTMLInputElementHelpers for LayoutDom<HTMLInputElement> {
}
}
impl TextControl for HTMLInputElement {
fn textinput(&self) -> &DomRefCell<TextInput<ScriptToConstellationChan>> {
&self.textinput
}
impl TextControlElement for HTMLInputElement {
// https://html.spec.whatwg.org/multipage/#concept-input-apply
fn selection_api_applies(&self) -> bool {
match self.input_type() {
@ -715,55 +711,53 @@ impl HTMLInputElementMethods for HTMLInputElement {
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-select
fn Select(&self) {
self.dom_select(); // defined in TextControl trait
self.selection().dom_select();
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart
fn GetSelectionStart(&self) -> Option<u32> {
self.get_dom_selection_start()
self.selection().dom_start()
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart
fn SetSelectionStart(&self, start: Option<u32>) -> ErrorResult {
self.set_dom_selection_start(start)
self.selection().set_dom_start(start)
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend
fn GetSelectionEnd(&self) -> Option<u32> {
self.get_dom_selection_end()
self.selection().dom_end()
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend
fn SetSelectionEnd(&self, end: Option<u32>) -> ErrorResult {
self.set_dom_selection_end(end)
self.selection().set_dom_end(end)
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection
fn GetSelectionDirection(&self) -> Option<DOMString> {
self.get_dom_selection_direction()
self.selection().dom_direction()
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection
fn SetSelectionDirection(&self, direction: Option<DOMString>) -> ErrorResult {
self.set_dom_selection_direction(direction)
self.selection().set_dom_direction(direction)
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-setselectionrange
fn SetSelectionRange(&self, start: u32, end: u32, direction: Option<DOMString>) -> ErrorResult {
self.set_dom_selection_range(start, end, direction)
self.selection().set_dom_range(start, end, direction)
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-setrangetext
fn SetRangeText(&self, replacement: DOMString) -> ErrorResult {
// defined in TextControl trait
self.set_dom_range_text(replacement, None, None, Default::default())
self.selection().set_dom_range_text(replacement, None, None, Default::default())
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-setrangetext
fn SetRangeText_(&self, replacement: DOMString, start: u32, end: u32,
selection_mode: SelectionMode) -> ErrorResult {
// defined in TextControl trait
self.set_dom_range_text(replacement, Some(start), Some(end), selection_mode)
self.selection().set_dom_range_text(replacement, Some(start), Some(end), selection_mode)
}
// Select the files based on filepaths passed in,
@ -1104,6 +1098,11 @@ impl HTMLInputElement {
_ => ()
}
}
#[allow(unrooted_must_root)]
fn selection(&self) -> TextControlSelection<Self> {
TextControlSelection::new(&self, &self.textinput)
}
}
impl VirtualMethods for HTMLInputElement {

View File

@ -25,7 +25,7 @@ use dom::keyboardevent::KeyboardEvent;
use dom::node::{ChildrenMutation, Node, NodeDamage, UnbindContext};
use dom::node::{document_from_node, window_from_node};
use dom::nodelist::NodeList;
use dom::textcontrol::TextControl;
use dom::textcontrol::{TextControlElement, TextControlSelection};
use dom::validation::Validatable;
use dom::virtualmethods::VirtualMethods;
use dom_struct::dom_struct;
@ -145,11 +145,7 @@ impl HTMLTextAreaElement {
}
}
impl TextControl for HTMLTextAreaElement {
fn textinput(&self) -> &DomRefCell<TextInput<ScriptToConstellationChan>> {
&self.textinput
}
impl TextControlElement for HTMLTextAreaElement {
fn selection_api_applies(&self) -> bool {
true
}
@ -277,55 +273,53 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement {
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-select
fn Select(&self) {
self.dom_select(); // defined in TextControl trait
self.selection().dom_select();
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart
fn GetSelectionStart(&self) -> Option<u32> {
self.get_dom_selection_start()
self.selection().dom_start()
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart
fn SetSelectionStart(&self, start: Option<u32>) -> ErrorResult {
self.set_dom_selection_start(start)
self.selection().set_dom_start(start)
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend
fn GetSelectionEnd(&self) -> Option<u32> {
self.get_dom_selection_end()
self.selection().dom_end()
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend
fn SetSelectionEnd(&self, end: Option<u32>) -> ErrorResult {
self.set_dom_selection_end(end)
self.selection().set_dom_end(end)
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection
fn GetSelectionDirection(&self) -> Option<DOMString> {
self.get_dom_selection_direction()
self.selection().dom_direction()
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection
fn SetSelectionDirection(&self, direction: Option<DOMString>) -> ErrorResult {
self.set_dom_selection_direction(direction)
self.selection().set_dom_direction(direction)
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-setselectionrange
fn SetSelectionRange(&self, start: u32, end: u32, direction: Option<DOMString>) -> ErrorResult {
self.set_dom_selection_range(start, end, direction)
self.selection().set_dom_range(start, end, direction)
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-setrangetext
fn SetRangeText(&self, replacement: DOMString) -> ErrorResult {
// defined in TextControl trait
self.set_dom_range_text(replacement, None, None, Default::default())
self.selection().set_dom_range_text(replacement, None, None, Default::default())
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-setrangetext
fn SetRangeText_(&self, replacement: DOMString, start: u32, end: u32,
selection_mode: SelectionMode) -> ErrorResult {
// defined in TextControl trait
self.set_dom_range_text(replacement, Some(start), Some(end), selection_mode)
self.selection().set_dom_range_text(replacement, Some(start), Some(end), selection_mode)
}
}
@ -336,6 +330,11 @@ impl HTMLTextAreaElement {
self.SetValue(self.DefaultValue());
self.value_dirty.set(false);
}
#[allow(unrooted_must_root)]
fn selection(&self) -> TextControlSelection<Self> {
TextControlSelection::new(&self, &self.textinput)
}
}

View File

@ -2,6 +2,11 @@
* 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 is an abstraction used by `HTMLInputElement` and `HTMLTextAreaElement` to implement the
//! text control selection DOM API.
//!
//! https://html.spec.whatwg.org/multipage/#textFieldSelection
use dom::bindings::cell::DomRefCell;
use dom::bindings::codegen::Bindings::HTMLFormElementBinding::SelectionMode;
use dom::bindings::conversions::DerivedFrom;
@ -13,43 +18,53 @@ use dom::node::{Node, NodeDamage, window_from_node};
use script_traits::ScriptToConstellationChan;
use textinput::{SelectionDirection, SelectionState, TextInput};
pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> {
fn textinput(&self) -> &DomRefCell<TextInput<ScriptToConstellationChan>>;
pub trait TextControlElement: DerivedFrom<EventTarget> + DerivedFrom<Node> {
fn selection_api_applies(&self) -> bool;
fn has_selectable_text(&self) -> bool;
fn set_dirty_value_flag(&self, value: bool);
}
pub struct TextControlSelection<'a, E: TextControlElement> {
element: &'a E,
textinput: &'a DomRefCell<TextInput<ScriptToConstellationChan>>,
}
impl<'a, E: TextControlElement> TextControlSelection<'a, E> {
pub fn new(element: &'a E, textinput: &'a DomRefCell<TextInput<ScriptToConstellationChan>>) -> Self {
TextControlSelection { element, textinput }
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-select
fn dom_select(&self) {
pub fn dom_select(&self) {
// Step 1
if !self.has_selectable_text() {
if !self.element.has_selectable_text() {
return;
}
// Step 2
self.set_selection_range(Some(0), Some(u32::max_value()), None, None);
self.set_range(Some(0), Some(u32::max_value()), None, None);
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart
fn get_dom_selection_start(&self) -> Option<u32> {
pub fn dom_start(&self) -> Option<u32> {
// Step 1
if !self.selection_api_applies() {
if !self.element.selection_api_applies() {
return None;
}
// Steps 2-3
Some(self.selection_start())
Some(self.start())
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionstart
fn set_dom_selection_start(&self, start: Option<u32>) -> ErrorResult {
pub fn set_dom_start(&self, start: Option<u32>) -> ErrorResult {
// Step 1
if !self.selection_api_applies() {
if !self.element.selection_api_applies() {
return Err(Error::InvalidState);
}
// Step 2
let mut end = self.selection_end();
let mut end = self.end();
// Step 3
if let Some(s) = start {
@ -59,54 +74,54 @@ pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> {
}
// Step 4
self.set_selection_range(start, Some(end), Some(self.selection_direction()), None);
self.set_range(start, Some(end), Some(self.direction()), None);
Ok(())
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend
fn get_dom_selection_end(&self) -> Option<u32> {
pub fn dom_end(&self) -> Option<u32> {
// Step 1
if !self.selection_api_applies() {
if !self.element.selection_api_applies() {
return None;
}
// Steps 2-3
Some(self.selection_end())
Some(self.end())
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectionend
fn set_dom_selection_end(&self, end: Option<u32>) -> ErrorResult {
pub fn set_dom_end(&self, end: Option<u32>) -> ErrorResult {
// Step 1
if !self.selection_api_applies() {
if !self.element.selection_api_applies() {
return Err(Error::InvalidState);
}
// Step 2
self.set_selection_range(Some(self.selection_start()), end, Some(self.selection_direction()), None);
self.set_range(Some(self.start()), end, Some(self.direction()), None);
Ok(())
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection
fn get_dom_selection_direction(&self) -> Option<DOMString> {
pub fn dom_direction(&self) -> Option<DOMString> {
// Step 1
if !self.selection_api_applies() {
if !self.element.selection_api_applies() {
return None;
}
Some(DOMString::from(self.selection_direction()))
Some(DOMString::from(self.direction()))
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-selectiondirection
fn set_dom_selection_direction(&self, direction: Option<DOMString>) -> ErrorResult {
pub fn set_dom_direction(&self, direction: Option<DOMString>) -> ErrorResult {
// Step 1
if !self.selection_api_applies() {
if !self.element.selection_api_applies() {
return Err(Error::InvalidState);
}
// Step 2
self.set_selection_range(
Some(self.selection_start()),
Some(self.selection_end()),
self.set_range(
Some(self.start()),
Some(self.end()),
direction.map(|d| SelectionDirection::from(d)),
None
);
@ -114,31 +129,36 @@ pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> {
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-setselectionrange
fn set_dom_selection_range(&self, start: u32, end: u32, direction: Option<DOMString>) -> ErrorResult {
pub fn set_dom_range(&self, start: u32, end: u32, direction: Option<DOMString>) -> ErrorResult {
// Step 1
if !self.selection_api_applies() {
if !self.element.selection_api_applies() {
return Err(Error::InvalidState);
}
// Step 2
self.set_selection_range(Some(start), Some(end), direction.map(|d| SelectionDirection::from(d)), None);
self.set_range(Some(start), Some(end), direction.map(|d| SelectionDirection::from(d)), None);
Ok(())
}
// https://html.spec.whatwg.org/multipage/#dom-textarea/input-setrangetext
fn set_dom_range_text(&self, replacement: DOMString, start: Option<u32>, end: Option<u32>,
selection_mode: SelectionMode) -> ErrorResult {
pub fn set_dom_range_text(
&self,
replacement: DOMString,
start: Option<u32>,
end: Option<u32>,
selection_mode: SelectionMode
) -> ErrorResult {
// Step 1
if !self.selection_api_applies() {
if !self.element.selection_api_applies() {
return Err(Error::InvalidState);
}
// Step 2
self.set_dirty_value_flag(true);
self.element.set_dirty_value_flag(true);
// Step 3
let mut start = start.unwrap_or_else(|| self.selection_start());
let mut end = end.unwrap_or_else(|| self.selection_end());
let mut start = start.unwrap_or_else(|| self.start());
let mut end = end.unwrap_or_else(|| self.end());
// Step 4
if start > end {
@ -147,9 +167,9 @@ pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> {
// Save the original selection state to later pass to set_selection_range, because we will
// change the selection state in order to replace the text in the range.
let original_selection_state = self.textinput().borrow().selection_state();
let original_selection_state = self.textinput.borrow().selection_state();
let content_length = self.textinput().borrow().len() as u32;
let content_length = self.textinput.borrow().len() as u32;
// Step 5
if start > content_length {
@ -162,10 +182,10 @@ pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> {
}
// Step 7
let mut selection_start = self.selection_start();
let mut selection_start = self.start();
// Step 8
let mut selection_end = self.selection_end();
let mut selection_end = self.end();
// Step 11
// Must come before the textinput.replace_selection() call, as replacement gets moved in
@ -173,7 +193,7 @@ pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> {
let new_length = replacement.len() as u32;
{
let mut textinput = self.textinput().borrow_mut();
let mut textinput = self.textinput.borrow_mut();
// Steps 9-10
textinput.set_selection_range(start, end, SelectionDirection::None);
@ -224,32 +244,31 @@ pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> {
}
// Step 14
self.set_selection_range(
Some(selection_start),
Some(selection_end),
None,
Some(original_selection_state)
);
self.set_range(Some(selection_start), Some(selection_end), None, Some(original_selection_state));
Ok(())
}
fn selection_start(&self) -> u32 {
self.textinput().borrow().selection_start_offset() as u32
fn start(&self) -> u32 {
self.textinput.borrow().selection_start_offset() as u32
}
fn selection_end(&self) -> u32 {
self.textinput().borrow().selection_end_offset() as u32
fn end(&self) -> u32 {
self.textinput.borrow().selection_end_offset() as u32
}
fn selection_direction(&self) -> SelectionDirection {
self.textinput().borrow().selection_direction
fn direction(&self) -> SelectionDirection {
self.textinput.borrow().selection_direction
}
// https://html.spec.whatwg.org/multipage/#set-the-selection-range
fn set_selection_range(&self, start: Option<u32>, end: Option<u32>, direction: Option<SelectionDirection>,
original_selection_state: Option<SelectionState>) {
let mut textinput = self.textinput().borrow_mut();
fn set_range(
&self,
start: Option<u32>,
end: Option<u32>,
direction: Option<SelectionDirection>,
original_selection_state: Option<SelectionState>
) {
let mut textinput = self.textinput.borrow_mut();
let original_selection_state = original_selection_state.unwrap_or_else(|| textinput.selection_state());
// Step 1
@ -263,15 +282,15 @@ pub trait TextControl: DerivedFrom<EventTarget> + DerivedFrom<Node> {
// Step 6
if textinput.selection_state() != original_selection_state {
let window = window_from_node(self);
let window = window_from_node(self.element);
window.user_interaction_task_source().queue_event(
&self.upcast::<EventTarget>(),
&self.element.upcast::<EventTarget>(),
atom!("select"),
EventBubbles::Bubbles,
EventCancelable::NotCancelable,
&window);
}
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
self.element.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
}
}

View File

@ -13,6 +13,7 @@ use style_traits::ParseError;
use stylesheets::UrlExtraData;
/// Errors that can be encountered while parsing CSS.
#[derive(Debug)]
pub enum ContextualParseError<'a> {
/// A property declaration was not recognized.
UnsupportedPropertyDeclaration(&'a str, ParseError<'a>),

View File

@ -724,6 +724,13 @@ extern "C" {
classList: *mut *mut *mut nsAtom,
) -> u32;
}
extern "C" {
pub fn Gecko_HasClass(
element: RawGeckoElementBorrowed,
class_: *mut nsAtom,
ignore_case: bool,
) -> bool;
}
extern "C" {
pub fn Gecko_SnapshotAtomAttrValue(
element: *const ServoElementSnapshot,
@ -801,6 +808,13 @@ extern "C" {
classList: *mut *mut *mut nsAtom,
) -> u32;
}
extern "C" {
pub fn Gecko_SnapshotHasClass(
element: *const ServoElementSnapshot,
class_: *mut nsAtom,
ignore_case: bool,
) -> bool;
}
extern "C" {
pub fn Gecko_GetStyleAttrDeclarationBlock(
element: RawGeckoElementBorrowed,

View File

@ -185,10 +185,12 @@ impl ElementSnapshot for GeckoElementSnapshot {
return false;
}
snapshot_helpers::has_class(self.as_ptr(),
name,
case_sensitivity,
bindings::Gecko_SnapshotClassOrClassList)
snapshot_helpers::has_class(
self.as_ptr(),
name,
case_sensitivity,
bindings::Gecko_SnapshotHasClass,
)
}
#[inline]
@ -200,9 +202,11 @@ impl ElementSnapshot for GeckoElementSnapshot {
return;
}
snapshot_helpers::each_class(self.as_ptr(),
callback,
bindings::Gecko_SnapshotClassOrClassList)
snapshot_helpers::each_class(
self.as_ptr(),
callback,
bindings::Gecko_SnapshotClassOrClassList,
)
}
#[inline]

View File

@ -4,9 +4,7 @@
//! Element an snapshot common logic.
use CaseSensitivityExt;
use gecko_bindings::structs::nsAtom;
use gecko_string_cache::WeakAtom;
use selectors::attr::CaseSensitivity;
use std::{ptr, slice};
use string_cache::Atom;
@ -15,34 +13,27 @@ use string_cache::Atom;
/// class or a class list.
pub type ClassOrClassList<T> = unsafe extern fn (T, *mut *mut nsAtom, *mut *mut *mut nsAtom) -> u32;
/// A function to return whether an element of type `T` has a given class.
///
/// The `bool` argument represents whether it should compare case-insensitively
/// or not.
pub type HasClass<T> = unsafe extern fn (T, *mut nsAtom, bool) -> bool;
/// Given an item `T`, a class name, and a getter function, return whether that
/// element has the class that `name` represents.
#[inline(always)]
pub fn has_class<T>(
item: T,
name: &Atom,
case_sensitivity: CaseSensitivity,
getter: ClassOrClassList<T>,
getter: HasClass<T>,
) -> bool {
unsafe {
let mut class: *mut nsAtom = ptr::null_mut();
let mut list: *mut *mut nsAtom = ptr::null_mut();
let length = getter(item, &mut class, &mut list);
match length {
0 => false,
1 => case_sensitivity.eq_atom(name, WeakAtom::new(class)),
n => {
let classes = slice::from_raw_parts(list, n as usize);
match case_sensitivity {
CaseSensitivity::CaseSensitive => {
classes.iter().any(|ptr| &**name == WeakAtom::new(*ptr))
}
CaseSensitivity::AsciiCaseInsensitive => {
classes.iter().any(|ptr| name.eq_ignore_ascii_case(WeakAtom::new(*ptr)))
}
}
}
}
}
let ignore_case = match case_sensitivity {
CaseSensitivity::CaseSensitive => false,
CaseSensitivity::AsciiCaseInsensitive => true,
};
unsafe { getter(item, name.as_ptr(), ignore_case) }
}

View File

@ -2195,7 +2195,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
self.0,
name,
case_sensitivity,
Gecko_ClassOrClassList,
bindings::Gecko_HasClass,
)
}

View File

@ -23,7 +23,6 @@
//! [cssparser]: ../cssparser/index.html
//! [selectors]: ../selectors/index.html
#![deny(warnings)]
#![deny(missing_docs)]
#![recursion_limit = "500"] // For define_css_keyword_enum! in -moz-appearance

Some files were not shown because too many files have changed in this diff Show More