Backed out changeset e8a9d431ea18 (bug 1654731) for devtools failures on browser_rules_class_panel_add.js.

This commit is contained in:
Cosmin Sabou 2022-04-23 15:14:42 +03:00
Родитель 34c0c5a32a
Коммит 2e81bebf42
6 изменённых файлов: 51 добавлений и 141 удалений

Просмотреть файл

@ -38,8 +38,7 @@ class ClassList {
this.inspector.on("markupmutation", this.onMutations);
this.classListProxyNode = this.inspector.panelDoc.createElement("div");
this.previewClasses = [];
this.unresolvedStateChanges = [];
this.previewClasses = "";
}
destroy() {
@ -76,12 +75,7 @@ class ClassList {
this.classListProxyNode.className = this.currentNode.className;
const nodeClasses = [...new Set([...this.classListProxyNode.classList])]
.filter(
className =>
!this.previewClasses.some(
previewClass =>
previewClass.className === className &&
!previewClass.wasAppliedOnNode
)
className => !this.previewClasses.split(" ").includes(className)
)
.map(name => {
return { name, isApplied: true };
@ -102,14 +96,11 @@ class ClassList {
.filter(({ isApplied }) => isApplied)
.map(({ name }) => name);
const previewClasses = this.previewClasses
.filter(previewClass => !currentClasses.includes(previewClass.className))
.filter(item => item !== "")
.map(({ className }) => className);
.split(" ")
.filter(previewClass => !currentClasses.includes(previewClass))
.filter(item => item !== "");
return currentClasses
.concat(previewClasses)
.join(" ")
.trim();
return currentClasses.concat(previewClasses).join(" ");
}
/**
@ -178,13 +169,12 @@ class ClassList {
return Promise.resolve();
}
// Remember which node & className we applied until their mutation event is received, so we
// can filter out dom mutations that are caused by us in onMutations, even in situations when
// a new change is applied before that the event of the previous one has been received yet
this.unresolvedStateChanges.push({
// Remember which node we changed and the className we applied, so we can filter out
// dom mutations that are caused by us in onMutations.
this.lastStateChange = {
node: this.currentNode,
className: this.currentClassesPreview,
});
};
// Apply the change to the node.
const mod = this.currentNode.startModifyingAttributes();
@ -199,19 +189,16 @@ class ClassList {
continue;
}
const isMutationForOurChange = this.unresolvedStateChanges.some(
previousStateChange =>
previousStateChange.node === target &&
previousStateChange.className === target.className
);
const isMutationForOurChange =
this.lastStateChange &&
target === this.lastStateChange.node &&
target.className === this.lastStateChange.className;
if (!isMutationForOurChange) {
CLASSES.delete(target);
if (target === this.currentNode) {
this.emit("current-node-class-changed");
}
} else {
this.removeResolvedStateChanged(target, target.className);
}
}
}
@ -235,18 +222,8 @@ class ClassList {
}
previewClass(inputClasses) {
if (
this.previewClasses
.map(previewClass => previewClass.className)
.join(" ") !== inputClasses
) {
this.previewClasses = [];
inputClasses.split(" ").forEach(className => {
this.previewClasses.push({
className: className,
wasAppliedOnNode: this.isClassAlreadyApplied(className),
});
});
if (this.previewClasses !== inputClasses) {
this.previewClasses = inputClasses;
this.applyClassState();
}
}
@ -254,21 +231,6 @@ class ClassList {
eraseClassPreview() {
this.previewClass("");
}
removeResolvedStateChanged(currentNode, currentClassesPreview) {
this.unresolvedStateChanges.splice(
0,
this.unresolvedStateChanges.findIndex(
previousState =>
previousState.node === currentNode &&
previousState.className === currentClassesPreview
) + 1
);
}
isClassAlreadyApplied(className) {
return this.currentClasses.some(({ name }) => name === className);
}
}
module.exports = ClassList;

Просмотреть файл

@ -72,11 +72,7 @@ add_task(async function() {
for (const key of textEntered.split("")) {
const onPreviewMutation = inspector.once("markupmutation");
EventUtils.synthesizeKey(key, {}, view.styleWindow);
await Promise.race([
onPreviewMutation,
/* eslint-disable mozilla/no-arbitrary-setTimeout */
new Promise(resolve => setTimeout(resolve, 100)),
]);
await onPreviewMutation;
}
info("Submit the change and wait for the textfield to become empty");
@ -85,11 +81,7 @@ add_task(async function() {
if (!expectNoMutation) {
info("Wait for the DOM to change");
await Promise.race([
onMutation,
/* eslint-disable mozilla/no-arbitrary-setTimeout */
new Promise(resolve => setTimeout(resolve, 100)),
]);
await onMutation;
}
await onEmpty;

Просмотреть файл

@ -14,7 +14,6 @@ add_task(async function() {
await addTab(TEST_URI);
const { inspector, view } = await openRuleView();
const { addEl: textInput } = view.classListPreviewer;
await selectNode("#auto-div-id-3", inspector);
info("Open the class panel");
view.showClassPanel();
@ -46,7 +45,7 @@ add_task(async function() {
const { autocompletePopup } = view.classListPreviewer;
let onPopupOpened = autocompletePopup.once("popup-opened");
EventUtils.synthesizeKey("a", {}, view.styleWindow);
await waitForClassApplied("auto-body-class-1", "#auto-div-id-3");
await waitForClassApplied("a");
await onPopupOpened;
await checkAutocompleteItems(
autocompletePopup,
@ -58,7 +57,7 @@ add_task(async function() {
"Test that typing more letters filters the autocomplete popup and uses the cache mechanism"
);
EventUtils.sendString("uto-b", view.styleWindow);
await waitForClassApplied("auto-body-class-1", "#auto-div-id-3");
await waitForClassApplied("auto-b");
await checkAutocompleteItems(
autocompletePopup,
@ -75,16 +74,12 @@ add_task(async function() {
content.document.body.classList.add("auto-body-added-by-script");
});
await onNewMutation;
await waitForClassApplied("auto-body-added-by-script", "body");
// close & reopen the autocomplete so it picks up the added to another element while autocomplete was opened
let onPopupClosed = autocompletePopup.once("popup-closed");
EventUtils.synthesizeKey("KEY_Escape", {}, view.styleWindow);
await onPopupClosed;
await waitForClassApplied("auto-body-added-by-script");
// input is now auto-body
onPopupOpened = autocompletePopup.once("popup-opened");
EventUtils.sendString("ody", view.styleWindow);
await waitForClassApplied("auto-body");
await onPopupOpened;
await checkAutocompleteItems(
autocompletePopup,
@ -99,9 +94,9 @@ add_task(async function() {
"Test that typing a letter that won't match any of the item closes the popup"
);
// input is now auto-bodyy
onPopupClosed = autocompletePopup.once("popup-closed");
let onPopupClosed = autocompletePopup.once("popup-closed");
EventUtils.synthesizeKey("y", {}, view.styleWindow);
await waitForClassApplied("auto-bodyy", "#auto-div-id-3");
await waitForClassApplied("auto-bodyy");
await onPopupClosed;
ok(true, "The popup was closed as expected");
await checkAutocompleteItems(autocompletePopup, [], "The popup was cleared");
@ -114,6 +109,7 @@ add_task(async function() {
onPopupOpened = autocompletePopup.once("popup-opened");
EventUtils.synthesizeKey("a", {}, view.styleWindow);
await waitForClassApplied("a");
await onPopupOpened;
await checkAutocompleteItems(
@ -153,7 +149,7 @@ add_task(async function() {
onPopupClosed = autocompletePopup.once("popup-closed");
EventUtils.synthesizeKey("KEY_ArrowRight", {}, view.styleWindow);
await waitForClassApplied("auto-body-added-by-script", "#auto-div-id-3");
await waitForClassApplied("auto-body-added-by-script");
await onPopupClosed;
is(
textInput.value,
@ -164,7 +160,7 @@ add_task(async function() {
// Backspace to show the list again
onPopupOpened = autocompletePopup.once("popup-opened");
EventUtils.synthesizeKey("KEY_Backspace", {}, view.styleWindow);
await waitForClassApplied("auto-body-added-by-script", "#auto-div-id-3");
await waitForClassApplied("auto-body-added-by-scrip");
await onPopupOpened;
is(
textInput.value,
@ -191,7 +187,7 @@ add_task(async function() {
// Backspace to show again
onPopupOpened = autocompletePopup.once("popup-opened");
EventUtils.synthesizeKey("KEY_Backspace", {}, view.styleWindow);
await waitForClassApplied("auto-body-added-by-script", "#auto-div-id-3");
await waitForClassApplied("auto-body-added-by-scrip");
await onPopupOpened;
is(
textInput.value,
@ -236,17 +232,13 @@ function getAutocompleteItems(autocompletePopup) {
);
}
async function waitForClassApplied(cls, selector) {
async function waitForClassApplied(cls) {
info("Wait for class to be applied: " + cls);
await SpecialPowers.spawn(
gBrowser.selectedBrowser,
[cls, selector],
async (_cls, _selector) => {
await SpecialPowers.spawn(gBrowser.selectedBrowser, [cls], async _cls => {
return ContentTaskUtils.waitForCondition(() =>
content.document.querySelector(_selector).classList.contains(_cls)
);
}
content.document.body.classList.contains(_cls)
);
});
// Wait for debounced functions to be executed
await wait(200);
}
@ -255,10 +247,7 @@ async function waitForClassRemoved(cls) {
info("Wait for class to be removed: " + cls);
await SpecialPowers.spawn(gBrowser.selectedBrowser, [cls], async _cls => {
return ContentTaskUtils.waitForCondition(
() =>
!content.document
.querySelector("#auto-div-id-3")
.classList.contains(_cls)
() => !content.document.body.classList.contains(_cls)
);
});
// Wait for debounced functions to be executed

Просмотреть файл

@ -36,6 +36,5 @@
<body class="auto-body-class-1 auto-body-class-2 auto-bold">
<div id="auto-div-id-1" class="auto-div-class-1 auto-div-class-2 auto-bold"> the ocean </div>
<div id="auto-div-id-2" class="auto-div-class-1 auto-div-class-2 auto-bold"> roaring </div>
<div id="auto-div-id-3"> ahead </div>
</body>
</html>

Просмотреть файл

@ -39,12 +39,6 @@ class ClassListPreviewer {
);
this.onCurrentNodeClassChanged = this.onCurrentNodeClassChanged.bind(this);
this.onNodeFrontWillUnset = this.onNodeFrontWillUnset.bind(this);
this.onAutocompleteClassHovered = debounce(
this.onAutocompleteClassHovered,
75,
this
);
this.onAutocompleteClosed = this.onAutocompleteClosed.bind(this);
// Create the add class text field.
this.addEl = this.doc.createElement("input");
@ -67,7 +61,7 @@ class ClassListPreviewer {
this.autocompletePopup = new AutocompletePopup(this.inspector.toolbox.doc, {
listId: "inspector_classListPreviewer_autocompletePopupListBox",
position: "bottom",
autoSelect: true,
autoSelect: false,
useXulWrapper: true,
input: this.addEl,
onClick: (e, item) => {
@ -78,11 +72,6 @@ class ClassListPreviewer {
this.model.previewClass(item.label);
}
},
onSelect: item => {
if (item) {
this.onAutocompleteClassHovered(item?.label);
}
},
});
// Start listening for interesting events.
@ -93,7 +82,6 @@ class ClassListPreviewer {
);
this.containerEl.addEventListener("input", this.onCheckBoxChanged);
this.model.on("current-node-class-changed", this.onCurrentNodeClassChanged);
this.autocompletePopup.on("popup-closed", this.onAutocompleteClosed);
this.onNewSelection();
}
@ -104,7 +92,6 @@ class ClassListPreviewer {
"node-front-will-unset",
this.onNodeFrontWillUnset
);
this.autocompletePopup.off("popup-closed", this.onAutocompleteClosed);
this.addEl.removeEventListener("keydown", this.onKeyDown);
this.addEl.removeEventListener("input", this.onAddElementInputModified);
this.containerEl.removeEventListener("input", this.onCheckBoxChanged);
@ -228,13 +215,13 @@ class ClassListPreviewer {
async onAddElementInputModified() {
const newValue = this.addEl.value;
this.model.previewClass(newValue);
// if the input is empty, let's close the popup, if it was open.
if (newValue === "") {
if (this.autocompletePopup.isOpen) {
this.autocompletePopup.hidePopup();
this.autocompletePopup.clearItems();
} else {
this.model.previewClass("");
}
return;
}
@ -243,12 +230,11 @@ class ClassListPreviewer {
let items = [];
try {
const classNames = await this.model.getClassNames(newValue);
if (!this.autocompletePopup.isOpen) {
this._previewClassesBeforeAutocompletion = this.model.previewClasses.map(
previewClass => previewClass.className
);
}
items = classNames.map(className => {
items = classNames
.filter(
className => !this.model.previewClasses.split(" ").includes(className)
)
.map(className => {
return {
preLabel: className.substring(0, newValue.length),
label: className,
@ -265,8 +251,7 @@ class ClassListPreviewer {
(items.length == 1 && items[0].label === newValue)
) {
this.autocompletePopup.clearItems();
await this.autocompletePopup.hidePopup();
this.model.previewClass(newValue);
this.autocompletePopup.hidePopup();
} else {
this.autocompletePopup.setItems(items);
this.autocompletePopup.openPopup();
@ -298,17 +283,6 @@ class ClassListPreviewer {
this.model.eraseClassPreview();
this.addEl.value = "";
}
onAutocompleteClassHovered(autocompleteItemLabel = "") {
if (this.autocompletePopup.isOpen) {
this.model.previewClass(autocompleteItemLabel);
}
}
onAutocompleteClosed() {
const inputValue = this.addEl.value;
this.model.previewClass(inputValue);
}
}
module.exports = ClassListPreviewer;

Просмотреть файл

@ -1278,8 +1278,7 @@ var PageStyleActor = protocol.ActorClassWithSpec(pageStyleSpec, {
result,
lcSearch,
attributeType,
targetDocument,
node.rawNode
targetDocument
);
this._collectAttributesFromDocumentStyleSheets(
result,
@ -1299,14 +1298,12 @@ var PageStyleActor = protocol.ActorClassWithSpec(pageStyleSpec, {
* @param {String} search: A string to filter attribute value on.
* @param {String} attributeType: The type of attribute we want to retrieve the values.
* @param {Document} targetDocument: The document the search occurs in.
* @param {Node} currentNode: The current element rawNode
*/
_collectAttributesFromDocumentDOM(
result,
search,
attributeType,
targetDocument,
nodeRawNode
targetDocument
) {
// In order to retrieve attributes from DOM elements in the document, we're going to
// do a query on the root node using attributes selector, to directly get the elements
@ -1321,9 +1318,6 @@ var PageStyleActor = protocol.ActorClassWithSpec(pageStyleSpec, {
const matchingElements = targetDocument.querySelectorAll(selector);
for (const element of matchingElements) {
if (element === nodeRawNode) {
return;
}
// For class attribute, we need to add the elements of the classList that match
// the filter string.
if (attributeType === "class") {