forked from mirrors/gecko-dev
Bug 1771113 - Add chromeOnly StyleSheetRemoved event, emitted when a stylesheet is removed. r=emilio.
This new event will be consumed by DevTools to update style information. As for `StyleSheetApplicableStateChanged`, this event is emitted from the document. It's only enabled when `document.styleSheetChangeEventsEnabled` is set to true. The existing test around the `StyleSheetApplicableStateChanged` is renamed and modified to assert both events when stylesheets are added, modified and removed. Differential Revision: https://phabricator.services.mozilla.com/D147271
This commit is contained in:
parent
1dbe69a36a
commit
f086602a6f
15 changed files with 293 additions and 97 deletions
|
|
@ -66,7 +66,7 @@ dom/xml/test/old/toc/book.css
|
||||||
dom/xml/test/old/toc/toc.css
|
dom/xml/test/old/toc/toc.css
|
||||||
|
|
||||||
# Tests we don't want to modify at this point:
|
# Tests we don't want to modify at this point:
|
||||||
layout/base/tests/bug839103.css
|
layout/base/tests/stylesheet_change_events.css
|
||||||
layout/inspector/tests/bug856317.css
|
layout/inspector/tests/bug856317.css
|
||||||
layout/inspector/tests/chrome/test_bug467669.css
|
layout/inspector/tests/chrome/test_bug467669.css
|
||||||
layout/inspector/tests/chrome/test_bug708874.css
|
layout/inspector/tests/chrome/test_bug708874.css
|
||||||
|
|
|
||||||
|
|
@ -225,6 +225,8 @@
|
||||||
#include "mozilla/dom/StyleSheetApplicableStateChangeEvent.h"
|
#include "mozilla/dom/StyleSheetApplicableStateChangeEvent.h"
|
||||||
#include "mozilla/dom/StyleSheetApplicableStateChangeEventBinding.h"
|
#include "mozilla/dom/StyleSheetApplicableStateChangeEventBinding.h"
|
||||||
#include "mozilla/dom/StyleSheetList.h"
|
#include "mozilla/dom/StyleSheetList.h"
|
||||||
|
#include "mozilla/dom/StyleSheetRemovedEvent.h"
|
||||||
|
#include "mozilla/dom/StyleSheetRemovedEventBinding.h"
|
||||||
#include "mozilla/dom/TimeoutManager.h"
|
#include "mozilla/dom/TimeoutManager.h"
|
||||||
#include "mozilla/dom/ToggleEvent.h"
|
#include "mozilla/dom/ToggleEvent.h"
|
||||||
#include "mozilla/dom/Touch.h"
|
#include "mozilla/dom/Touch.h"
|
||||||
|
|
@ -7450,6 +7452,26 @@ void Document::PostStyleSheetApplicableStateChangeEvent(StyleSheet& aSheet) {
|
||||||
asyncDispatcher->PostDOMEvent();
|
asyncDispatcher->PostDOMEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Document::PostStyleSheetRemovedEvent(StyleSheet& aSheet) {
|
||||||
|
if (!StyleSheetChangeEventsEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StyleSheetRemovedEventInit init;
|
||||||
|
init.mBubbles = true;
|
||||||
|
init.mCancelable = false;
|
||||||
|
init.mStylesheet = &aSheet;
|
||||||
|
|
||||||
|
RefPtr<StyleSheetRemovedEvent> event =
|
||||||
|
StyleSheetRemovedEvent::Constructor(this, u"StyleSheetRemoved"_ns, init);
|
||||||
|
event->SetTrusted(true);
|
||||||
|
event->SetTarget(this);
|
||||||
|
RefPtr<AsyncEventDispatcher> asyncDispatcher =
|
||||||
|
new AsyncEventDispatcher(this, event);
|
||||||
|
asyncDispatcher->mOnlyChromeDispatch = ChromeOnlyDispatch::eYes;
|
||||||
|
asyncDispatcher->PostDOMEvent();
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t FindSheet(const nsTArray<RefPtr<StyleSheet>>& aSheets,
|
static int32_t FindSheet(const nsTArray<RefPtr<StyleSheet>>& aSheets,
|
||||||
nsIURI* aSheetURI) {
|
nsIURI* aSheetURI) {
|
||||||
for (int32_t i = aSheets.Length() - 1; i >= 0; i--) {
|
for (int32_t i = aSheets.Length() - 1; i >= 0; i--) {
|
||||||
|
|
|
||||||
|
|
@ -1687,8 +1687,8 @@ class Document : public nsINode,
|
||||||
* and that observers should be notified and style sets updated
|
* and that observers should be notified and style sets updated
|
||||||
*/
|
*/
|
||||||
void StyleSheetApplicableStateChanged(StyleSheet&);
|
void StyleSheetApplicableStateChanged(StyleSheet&);
|
||||||
|
|
||||||
void PostStyleSheetApplicableStateChangeEvent(StyleSheet&);
|
void PostStyleSheetApplicableStateChangeEvent(StyleSheet&);
|
||||||
|
void PostStyleSheetRemovedEvent(StyleSheet&);
|
||||||
|
|
||||||
enum additionalSheetType {
|
enum additionalSheetType {
|
||||||
eAgentSheet,
|
eAgentSheet,
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,7 @@ void DocumentOrShadowRoot::RemoveStyleSheet(StyleSheet& aSheet) {
|
||||||
mStyleSheets.RemoveElementAt(index);
|
mStyleSheets.RemoveElementAt(index);
|
||||||
RemoveSheetFromStylesIfApplicable(*sheet);
|
RemoveSheetFromStylesIfApplicable(*sheet);
|
||||||
sheet->ClearAssociatedDocumentOrShadowRoot();
|
sheet->ClearAssociatedDocumentOrShadowRoot();
|
||||||
|
AsNode().OwnerDoc()->PostStyleSheetRemovedEvent(aSheet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DocumentOrShadowRoot::RemoveSheetFromStylesIfApplicable(
|
void DocumentOrShadowRoot::RemoveSheetFromStylesIfApplicable(
|
||||||
|
|
|
||||||
17
dom/chrome-webidl/StyleSheetRemovedEvent.webidl
Normal file
17
dom/chrome-webidl/StyleSheetRemovedEvent.webidl
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[ChromeOnly, Exposed=Window]
|
||||||
|
interface StyleSheetRemovedEvent : Event {
|
||||||
|
constructor(DOMString type,
|
||||||
|
optional StyleSheetRemovedEventInit eventInitDict = {});
|
||||||
|
|
||||||
|
readonly attribute CSSStyleSheet? stylesheet;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary StyleSheetRemovedEventInit : EventInit {
|
||||||
|
CSSStyleSheet? stylesheet = null;
|
||||||
|
};
|
||||||
|
|
@ -81,6 +81,8 @@ WEBIDL_FILES = [
|
||||||
"SessionStoreUtils.webidl",
|
"SessionStoreUtils.webidl",
|
||||||
"StripOnShareRule.webidl",
|
"StripOnShareRule.webidl",
|
||||||
"StructuredCloneHolder.webidl",
|
"StructuredCloneHolder.webidl",
|
||||||
|
"StyleSheetApplicableStateChangeEvent.webidl",
|
||||||
|
"StyleSheetRemovedEvent.webidl",
|
||||||
"TelemetryStopwatch.webidl",
|
"TelemetryStopwatch.webidl",
|
||||||
"UserInteraction.webidl",
|
"UserInteraction.webidl",
|
||||||
"WebExtensionContentScript.webidl",
|
"WebExtensionContentScript.webidl",
|
||||||
|
|
@ -92,6 +94,11 @@ WEBIDL_FILES = [
|
||||||
"XULTreeElement.webidl",
|
"XULTreeElement.webidl",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
GENERATED_EVENTS_WEBIDL_FILES = [
|
||||||
|
"StyleSheetApplicableStateChangeEvent.webidl",
|
||||||
|
"StyleSheetRemovedEvent.webidl",
|
||||||
|
]
|
||||||
|
|
||||||
if CONFIG["MOZ_BUILD_APP"] != "mobile/android":
|
if CONFIG["MOZ_BUILD_APP"] != "mobile/android":
|
||||||
WEBIDL_FILES += [
|
WEBIDL_FILES += [
|
||||||
"UniFFI.webidl",
|
"UniFFI.webidl",
|
||||||
|
|
|
||||||
|
|
@ -350,6 +350,11 @@ const kEventConstructors = {
|
||||||
},
|
},
|
||||||
chromeOnly: true,
|
chromeOnly: true,
|
||||||
},
|
},
|
||||||
|
StyleSheetRemovedEvent: { create (aName, aProps) {
|
||||||
|
return new StyleSheetRemovedEvent(aName, aProps);
|
||||||
|
},
|
||||||
|
chromeOnly: true,
|
||||||
|
},
|
||||||
SubmitEvent: { create (aName, aProps) {
|
SubmitEvent: { create (aName, aProps) {
|
||||||
return new SubmitEvent(aName, aProps);
|
return new SubmitEvent(aName, aProps);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1108,7 +1108,6 @@ WEBIDL_FILES += [
|
||||||
"PopStateEvent.webidl",
|
"PopStateEvent.webidl",
|
||||||
"PopupBlockedEvent.webidl",
|
"PopupBlockedEvent.webidl",
|
||||||
"ProgressEvent.webidl",
|
"ProgressEvent.webidl",
|
||||||
"StyleSheetApplicableStateChangeEvent.webidl",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# WebExtensions API.
|
# WebExtensions API.
|
||||||
|
|
@ -1188,7 +1187,6 @@ GENERATED_EVENTS_WEBIDL_FILES = [
|
||||||
"PromiseRejectionEvent.webidl",
|
"PromiseRejectionEvent.webidl",
|
||||||
"ScrollViewChangeEvent.webidl",
|
"ScrollViewChangeEvent.webidl",
|
||||||
"SecurityPolicyViolationEvent.webidl",
|
"SecurityPolicyViolationEvent.webidl",
|
||||||
"StyleSheetApplicableStateChangeEvent.webidl",
|
|
||||||
"SubmitEvent.webidl",
|
"SubmitEvent.webidl",
|
||||||
"TaskPriorityChangeEvent.webidl",
|
"TaskPriorityChangeEvent.webidl",
|
||||||
"TCPServerSocketEvent.webidl",
|
"TCPServerSocketEvent.webidl",
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,3 @@
|
||||||
[browser_bug617076.js]
|
|
||||||
[browser_bug839103.js]
|
|
||||||
support-files =
|
|
||||||
file_bug839103.html
|
|
||||||
bug839103.css
|
|
||||||
[browser_bug1701027-1.js]
|
[browser_bug1701027-1.js]
|
||||||
support-files =
|
support-files =
|
||||||
helper_bug1701027-1.html
|
helper_bug1701027-1.html
|
||||||
|
|
@ -13,6 +8,9 @@ support-files =
|
||||||
run-if = (((os == 'mac') || (os == 'win' && os_version != '6.1' && processor == 'x86_64')) && debug)
|
run-if = (((os == 'mac') || (os == 'win' && os_version != '6.1' && processor == 'x86_64')) && debug)
|
||||||
[browser_bug1787079.js]
|
[browser_bug1787079.js]
|
||||||
run-if = ((os == 'win' && os_version != '6.1' && processor == 'x86_64') && debug)
|
run-if = ((os == 'win' && os_version != '6.1' && processor == 'x86_64') && debug)
|
||||||
|
[browser_bug1791083.js]
|
||||||
|
skip-if = !sessionHistoryInParent
|
||||||
|
[browser_bug617076.js]
|
||||||
[browser_disableDialogs_onbeforeunload.js]
|
[browser_disableDialogs_onbeforeunload.js]
|
||||||
[browser_onbeforeunload_only_after_interaction.js]
|
[browser_onbeforeunload_only_after_interaction.js]
|
||||||
[browser_onbeforeunload_only_after_interaction_in_frame.js]
|
[browser_onbeforeunload_only_after_interaction_in_frame.js]
|
||||||
|
|
@ -20,10 +18,6 @@ run-if = ((os == 'win' && os_version != '6.1' && processor == 'x86_64') && debug
|
||||||
support-files =
|
support-files =
|
||||||
test_scroll_into_view_in_oopif.html
|
test_scroll_into_view_in_oopif.html
|
||||||
scroll_into_view_in_child.html
|
scroll_into_view_in_child.html
|
||||||
[browser_visual_viewport_iframe.js]
|
|
||||||
support-files =
|
|
||||||
test_visual_viewport_in_oopif.html
|
|
||||||
visual_viewport_in_child.html
|
|
||||||
[browser_select_popup_position_in_out_of_process_iframe.js]
|
[browser_select_popup_position_in_out_of_process_iframe.js]
|
||||||
skip-if =
|
skip-if =
|
||||||
(verify && (os == 'mac')) # bug 1627874
|
(verify && (os == 'mac')) # bug 1627874
|
||||||
|
|
@ -32,5 +26,11 @@ skip-if =
|
||||||
support-files =
|
support-files =
|
||||||
!/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
|
!/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
|
||||||
!/browser/base/content/test/forms/head.js
|
!/browser/base/content/test/forms/head.js
|
||||||
[browser_bug1791083.js]
|
[browser_stylesheet_change_events.js]
|
||||||
skip-if = !sessionHistoryInParent
|
support-files =
|
||||||
|
file_stylesheet_change_events.html
|
||||||
|
stylesheet_change_events.css
|
||||||
|
[browser_visual_viewport_iframe.js]
|
||||||
|
support-files =
|
||||||
|
test_visual_viewport_in_oopif.html
|
||||||
|
visual_viewport_in_child.html
|
||||||
|
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
||||||
const gTestRoot = getRootDirectory(gTestPath).replace(
|
|
||||||
"chrome://mochitests/content/",
|
|
||||||
"http://127.0.0.1:8888/"
|
|
||||||
);
|
|
||||||
|
|
||||||
add_task(async function test() {
|
|
||||||
await BrowserTestUtils.withNewTab(
|
|
||||||
{ gBrowser, url: gTestRoot + "file_bug839103.html" },
|
|
||||||
async function (browser) {
|
|
||||||
await SpecialPowers.spawn(browser, [gTestRoot], testBody);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
// This function runs entirely in the content process. It doesn't have access
|
|
||||||
// any free variables in this file.
|
|
||||||
async function testBody(testRoot) {
|
|
||||||
const gStyleSheet = "bug839103.css";
|
|
||||||
|
|
||||||
function unexpectedContentEvent(event) {
|
|
||||||
ok(false, "Received a " + event.type + " event on content");
|
|
||||||
}
|
|
||||||
|
|
||||||
// We've seen the original stylesheet in the document.
|
|
||||||
// Now add a stylesheet on the fly and make sure we see it.
|
|
||||||
let doc = content.document;
|
|
||||||
doc.styleSheetChangeEventsEnabled = true;
|
|
||||||
doc.addEventListener(
|
|
||||||
"StyleSheetApplicableStateChanged",
|
|
||||||
unexpectedContentEvent
|
|
||||||
);
|
|
||||||
doc.defaultView.addEventListener(
|
|
||||||
"StyleSheetApplicableStateChanged",
|
|
||||||
unexpectedContentEvent
|
|
||||||
);
|
|
||||||
|
|
||||||
let link = doc.createElement("link");
|
|
||||||
link.setAttribute("rel", "stylesheet");
|
|
||||||
link.setAttribute("type", "text/css");
|
|
||||||
link.setAttribute("href", testRoot + gStyleSheet);
|
|
||||||
|
|
||||||
let stateChanged = ContentTaskUtils.waitForEvent(
|
|
||||||
docShell.chromeEventHandler,
|
|
||||||
"StyleSheetApplicableStateChanged",
|
|
||||||
true
|
|
||||||
);
|
|
||||||
doc.body.appendChild(link);
|
|
||||||
|
|
||||||
info("waiting for applicable state change event");
|
|
||||||
let evt = await stateChanged;
|
|
||||||
info("received dynamic style sheet applicable state change event");
|
|
||||||
is(
|
|
||||||
evt.type,
|
|
||||||
"StyleSheetApplicableStateChanged",
|
|
||||||
"evt.type has expected value"
|
|
||||||
);
|
|
||||||
is(evt.target, doc, "event targets correct document");
|
|
||||||
is(evt.stylesheet, link.sheet, "evt.stylesheet has the right value");
|
|
||||||
is(evt.applicable, true, "evt.applicable has the right value");
|
|
||||||
|
|
||||||
stateChanged = ContentTaskUtils.waitForEvent(
|
|
||||||
docShell.chromeEventHandler,
|
|
||||||
"StyleSheetApplicableStateChanged",
|
|
||||||
true
|
|
||||||
);
|
|
||||||
link.sheet.disabled = true;
|
|
||||||
|
|
||||||
evt = await stateChanged;
|
|
||||||
is(
|
|
||||||
evt.type,
|
|
||||||
"StyleSheetApplicableStateChanged",
|
|
||||||
"evt.type has expected value"
|
|
||||||
);
|
|
||||||
info(
|
|
||||||
'received dynamic style sheet applicable state change event after media="" changed'
|
|
||||||
);
|
|
||||||
is(evt.target, doc, "event targets correct document");
|
|
||||||
is(evt.stylesheet, link.sheet, "evt.stylesheet has the right value");
|
|
||||||
is(evt.applicable, false, "evt.applicable has the right value");
|
|
||||||
|
|
||||||
doc.body.removeChild(link);
|
|
||||||
}
|
|
||||||
227
layout/base/tests/browser_stylesheet_change_events.js
Normal file
227
layout/base/tests/browser_stylesheet_change_events.js
Normal file
|
|
@ -0,0 +1,227 @@
|
||||||
|
const gTestRoot = getRootDirectory(gTestPath).replace(
|
||||||
|
"chrome://mochitests/content/",
|
||||||
|
"http://127.0.0.1:8888/"
|
||||||
|
);
|
||||||
|
|
||||||
|
add_task(async function test() {
|
||||||
|
await BrowserTestUtils.withNewTab(
|
||||||
|
{ gBrowser, url: gTestRoot + "file_stylesheet_change_events.html" },
|
||||||
|
async function (browser) {
|
||||||
|
await SpecialPowers.spawn(
|
||||||
|
browser,
|
||||||
|
[gTestRoot],
|
||||||
|
testApplicableStateChangeEvent
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// This function runs entirely in the content process. It doesn't have access
|
||||||
|
// any free variables in this file.
|
||||||
|
async function testApplicableStateChangeEvent(testRoot) {
|
||||||
|
// We've seen the original stylesheet in the document.
|
||||||
|
// Now add a stylesheet on the fly and make sure we see it.
|
||||||
|
let doc = content.document;
|
||||||
|
doc.styleSheetChangeEventsEnabled = true;
|
||||||
|
|
||||||
|
const unexpectedContentEvent = event =>
|
||||||
|
ok(false, "Received a " + event.type + " event on content");
|
||||||
|
doc.addEventListener(
|
||||||
|
"StyleSheetApplicableStateChanged",
|
||||||
|
unexpectedContentEvent
|
||||||
|
);
|
||||||
|
doc.defaultView.addEventListener(
|
||||||
|
"StyleSheetApplicableStateChanged",
|
||||||
|
unexpectedContentEvent
|
||||||
|
);
|
||||||
|
doc.addEventListener("StyleSheetRemoved", unexpectedContentEvent);
|
||||||
|
doc.defaultView.addEventListener("StyleSheetRemoved", unexpectedContentEvent);
|
||||||
|
|
||||||
|
function shouldIgnoreEvent(e) {
|
||||||
|
// accessiblecaret.css might be reported, interfering with the test
|
||||||
|
// assertions, so let's ignore it
|
||||||
|
return (
|
||||||
|
e.stylesheet?.href === "resource://content-accessible/accessiblecaret.css"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function waitForStyleApplicableStateChanged() {
|
||||||
|
return ContentTaskUtils.waitForEvent(
|
||||||
|
docShell.chromeEventHandler,
|
||||||
|
"StyleSheetApplicableStateChanged",
|
||||||
|
true,
|
||||||
|
e => !shouldIgnoreEvent(e)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function waitForStyleSheetRemovedEvent() {
|
||||||
|
return ContentTaskUtils.waitForEvent(
|
||||||
|
docShell.chromeEventHandler,
|
||||||
|
"StyleSheetRemoved",
|
||||||
|
true,
|
||||||
|
e => !shouldIgnoreEvent(e)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkApplicableStateChangeEvent(event, { applicable, stylesheet }) {
|
||||||
|
is(
|
||||||
|
event.type,
|
||||||
|
"StyleSheetApplicableStateChanged",
|
||||||
|
"event.type has expected value"
|
||||||
|
);
|
||||||
|
is(event.target, doc, "event targets correct document");
|
||||||
|
is(event.stylesheet, stylesheet, "event.stylesheet has the expected value");
|
||||||
|
is(event.applicable, applicable, "event.applicable has the expected value");
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkStyleSheetRemovedEvent(event, { stylesheet }) {
|
||||||
|
is(event.type, "StyleSheetRemoved", "event.type has expected value");
|
||||||
|
is(event.target, doc, "event targets correct document");
|
||||||
|
is(event.stylesheet, stylesheet, "event.stylesheet has the expected value");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updating the text content will actually create a new StyleSheet instance,
|
||||||
|
// and so we should get one event for the new instance, and another one for
|
||||||
|
// the removal of the "previous"one.
|
||||||
|
function waitForTextContentChange() {
|
||||||
|
return Promise.all([
|
||||||
|
waitForStyleSheetRemovedEvent(),
|
||||||
|
waitForStyleApplicableStateChanged(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
let stateChanged, evt;
|
||||||
|
|
||||||
|
{
|
||||||
|
const gStyleSheet = "stylesheet_change_events.css";
|
||||||
|
|
||||||
|
info("Add <link> and wait for applicable state change event");
|
||||||
|
let linkEl = doc.createElement("link");
|
||||||
|
linkEl.setAttribute("rel", "stylesheet");
|
||||||
|
linkEl.setAttribute("type", "text/css");
|
||||||
|
linkEl.setAttribute("href", testRoot + gStyleSheet);
|
||||||
|
|
||||||
|
stateChanged = waitForStyleApplicableStateChanged();
|
||||||
|
doc.body.appendChild(linkEl);
|
||||||
|
evt = await stateChanged;
|
||||||
|
|
||||||
|
ok(true, "received dynamic style sheet applicable state change event");
|
||||||
|
checkApplicableStateChangeEvent(evt, {
|
||||||
|
stylesheet: linkEl.sheet,
|
||||||
|
applicable: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
stateChanged = waitForStyleApplicableStateChanged();
|
||||||
|
linkEl.sheet.disabled = true;
|
||||||
|
evt = await stateChanged;
|
||||||
|
|
||||||
|
ok(true, "received dynamic style sheet applicable state change event");
|
||||||
|
checkApplicableStateChangeEvent(evt, {
|
||||||
|
stylesheet: linkEl.sheet,
|
||||||
|
applicable: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
info("Remove stylesheet and wait for removed event");
|
||||||
|
const removedStylesheet = linkEl.sheet;
|
||||||
|
const onStyleSheetRemoved = waitForStyleSheetRemovedEvent();
|
||||||
|
doc.body.removeChild(linkEl);
|
||||||
|
const removedStyleSheetEvt = await onStyleSheetRemoved;
|
||||||
|
|
||||||
|
ok(true, "received removed sheet event");
|
||||||
|
checkStyleSheetRemovedEvent(removedStyleSheetEvt, {
|
||||||
|
stylesheet: removedStylesheet,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
info("Add <style> node and wait for applicable state changed event");
|
||||||
|
let styleEl = doc.createElement("style");
|
||||||
|
styleEl.textContent = `body { background: tomato; }`;
|
||||||
|
|
||||||
|
stateChanged = waitForStyleApplicableStateChanged();
|
||||||
|
doc.head.appendChild(styleEl);
|
||||||
|
evt = await stateChanged;
|
||||||
|
|
||||||
|
ok(true, "received dynamic style sheet applicable state change event");
|
||||||
|
checkApplicableStateChangeEvent(evt, {
|
||||||
|
stylesheet: styleEl.sheet,
|
||||||
|
applicable: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
info("Updating <style> text content");
|
||||||
|
stateChanged = waitForTextContentChange();
|
||||||
|
const inlineStyleSheetBeforeChange = styleEl.sheet;
|
||||||
|
|
||||||
|
styleEl.textContent = `body { background: gold; }`;
|
||||||
|
const [inlineRemovedEvt, inlineAddedEvt] = await stateChanged;
|
||||||
|
|
||||||
|
ok(true, "received expected style sheet events");
|
||||||
|
checkStyleSheetRemovedEvent(inlineRemovedEvt, {
|
||||||
|
stylesheet: inlineStyleSheetBeforeChange,
|
||||||
|
});
|
||||||
|
checkApplicableStateChangeEvent(inlineAddedEvt, {
|
||||||
|
stylesheet: styleEl.sheet,
|
||||||
|
applicable: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
info("Remove stylesheet and wait for removed event");
|
||||||
|
const onStyleSheetRemoved = waitForStyleSheetRemovedEvent();
|
||||||
|
|
||||||
|
const removedInlineStylesheet = styleEl.sheet;
|
||||||
|
styleEl.remove();
|
||||||
|
const removedStyleSheetEvt = await onStyleSheetRemoved;
|
||||||
|
|
||||||
|
ok(true, "received removed style sheet event");
|
||||||
|
checkStyleSheetRemovedEvent(removedStyleSheetEvt, {
|
||||||
|
stylesheet: removedInlineStylesheet,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
info(
|
||||||
|
"Create a custom element and check we get an event for its stylesheet"
|
||||||
|
);
|
||||||
|
stateChanged = waitForStyleApplicableStateChanged();
|
||||||
|
const el = doc.createElement("div");
|
||||||
|
const shadowRoot = el.attachShadow({ mode: "open" });
|
||||||
|
doc.body.appendChild(el);
|
||||||
|
shadowRoot.innerHTML = `
|
||||||
|
<span>custom</span>
|
||||||
|
<style>
|
||||||
|
span { color: salmon; }
|
||||||
|
</style>`;
|
||||||
|
evt = await stateChanged;
|
||||||
|
|
||||||
|
ok(true, "received dynamic style sheet applicable state change event");
|
||||||
|
const shadowStyleEl = shadowRoot.querySelector("style");
|
||||||
|
checkApplicableStateChangeEvent(evt, {
|
||||||
|
stylesheet: shadowStyleEl.sheet,
|
||||||
|
applicable: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
info("Updating <style> text content");
|
||||||
|
stateChanged = waitForTextContentChange();
|
||||||
|
const styleSheetBeforeChange = shadowStyleEl.sheet;
|
||||||
|
shadowStyleEl.textContent = `span { color: cyan; }`;
|
||||||
|
const [removedEvt, addedEvt] = await stateChanged;
|
||||||
|
|
||||||
|
ok(true, "received expected style sheet events");
|
||||||
|
checkStyleSheetRemovedEvent(removedEvt, {
|
||||||
|
stylesheet: styleSheetBeforeChange,
|
||||||
|
});
|
||||||
|
checkApplicableStateChangeEvent(addedEvt, {
|
||||||
|
stylesheet: shadowStyleEl.sheet,
|
||||||
|
applicable: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
info("Remove stylesheet and wait for removed event");
|
||||||
|
const onStyleSheetRemoved = waitForStyleSheetRemovedEvent();
|
||||||
|
const removedShadowStylesheet = shadowStyleEl.sheet;
|
||||||
|
shadowStyleEl.remove();
|
||||||
|
const removedStyleSheetEvt = await onStyleSheetRemoved;
|
||||||
|
ok(true, "received removed style sheet event");
|
||||||
|
checkStyleSheetRemovedEvent(removedStyleSheetEvt, {
|
||||||
|
stylesheet: removedShadowStylesheet,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -648,6 +648,7 @@ module.exports = {
|
||||||
StyleSheet: false,
|
StyleSheet: false,
|
||||||
StyleSheetApplicableStateChangeEvent: false,
|
StyleSheetApplicableStateChangeEvent: false,
|
||||||
StyleSheetList: false,
|
StyleSheetList: false,
|
||||||
|
StyleSheetRemovedEvent: false,
|
||||||
SubtleCrypto: false,
|
SubtleCrypto: false,
|
||||||
SyncMessageSender: false,
|
SyncMessageSender: false,
|
||||||
TCPServerSocket: false,
|
TCPServerSocket: false,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue