Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
MediaQueryList.matches should update parent document layout for viewp…
…ort-dependent media queries https://bugs.webkit.org/show_bug.cgi?id=189583 Reviewed by Antti Koivisto. This patch makes MediaQueryList::matches update the associated document's owner element's layout if the associated media query set contains a viewport dependent expression. New behavior matches the spec and the behavior of Blink although Blink fails the last test case in the newly introduced W3C style testharness.js test. * LayoutTests/fast/css/media-query-matches-in-iframe-expected.txt: Added. * LayoutTests/fast/css/media-query-matches-in-iframe.html: Added. * LayoutTests/printing/print-with-media-query-destory-expected.txt: Rebaselined. * Source/WebCore/css/MediaQueryEvaluator.cpp: (WebCore::isViewportDependent): Moved to MediaQueryExpression.cpp. (WebCore::MediaQueryEvaluator::evaluate const): * Source/WebCore/css/MediaQueryExpression.cpp: (WebCore::MediaQueryExpression::isViewportDependent const): Moved from MediaQueryEvaluator.cpp. * Source/WebCore/css/MediaQueryExpression.h: * Source/WebCore/css/MediaQueryList.cpp: (WebCore::MediaQueryList::evaluate): This function now dispatches an event on its own instead of having an out argument for MediaQueryMatcher to use. It now takes MediaQueryMatcher::EventMode which specifies whether we should be synchronously dispatching a change event or not. (WebCore::MediaQueryList::matches): Update the layout of the owner element's document if the associated media query set contains a viewport dependent expression. * Source/WebCore/css/MediaQueryList.h: (WebCore::MediaQueryList::m_needsNotification): Added. * Source/WebCore/css/MediaQueryMatcher.cpp: (WebCore::MediaQueryMatcher::evaluateAll): Now takes EventMode which specifies whether we're updating the rendering in which case the event should be dispatched now, or we're updating for viewport dependent expression in one of the media queries. * Source/WebCore/css/MediaQueryMatcher.h: * Source/WebCore/dom/Document.cpp: (WebCore::Document::evaluateMediaQueriesAndReportChanges): Canonical link: https://commits.webkit.org/253123@main
- Loading branch information
Showing
11 changed files
with
189 additions
and
39 deletions.
There are no files selected for viewing
24 changes: 24 additions & 0 deletions
24
LayoutTests/fast/css/media-query-matches-in-iframe-expected.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
|
||
PASS matchMedia('(max-width: 150px)').matches should update immediately | ||
PASS matchMedia('(width: 100px)').matches should update immediately | ||
PASS matchMedia('(orientation: portrait)').matches should update immediately | ||
PASS matchMedia('(aspect-ratio: 1/1)').matches should update immediately | ||
PASS matchMedia('(max-aspect-ratio: 4/3)').matches should update immediately | ||
PASS matchMedia('(height: 100px)').matches should update immediately | ||
PASS matchMedia('(max-height: 150px)').matches should update immediately | ||
PASS matchMedia('(min-aspect-ratio: 3/4)').matches should update immediately | ||
PASS matchMedia('(min-height: 150px)').matches should update immediately | ||
PASS matchMedia('(aspect-ratio: 1/2)').matches should update immediately | ||
PASS matchMedia('(min-width: 150px)').matches should update immediately | ||
PASS matchMedia('(min-aspect-ratio: 4/3)').matches should update immediately | ||
PASS matchMedia('(max-width: 150px)') should not receive a change event until update the rendering step of HTML5 event loop | ||
PASS matchMedia('(width: 100px)') should not receive a change event until update the rendering step of HTML5 event loop | ||
PASS matchMedia('(orientation: portrait)') should not receive a change event until update the rendering step of HTML5 event loop | ||
PASS matchMedia('(aspect-ratio: 1/1)') should not receive a change event until update the rendering step of HTML5 event loop | ||
PASS matchMedia('(max-aspect-ratio: 4/3)') should not receive a change event until update the rendering step of HTML5 event loop | ||
PASS matchMedia('(max-width: 150px)') should receive a change event after resize event on the window but before a requestAnimationFrame callback is called | ||
PASS matchMedia('(width: 100px)') should receive a change event after resize event on the window but before a requestAnimationFrame callback is called | ||
PASS matchMedia('(orientation: portrait)') should receive a change event after resize event on the window but before a requestAnimationFrame callback is called | ||
PASS matchMedia('(aspect-ratio: 1/1)') should receive a change event after resize event on the window but before a requestAnimationFrame callback is called | ||
PASS matchMedia('(max-aspect-ratio: 4/3)') should receive a change event after resize event on the window but before a requestAnimationFrame callback is called | ||
|
103 changes: 103 additions & 0 deletions
103
LayoutTests/fast/css/media-query-matches-in-iframe.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<body> | ||
<script src="../../resources/testharness.js"></script> | ||
<script src="../../resources/testharnessreport.js"></script> | ||
<script> | ||
|
||
async function createFrameAndUpdateLayout(test) { | ||
const iframe = await new Promise((resolve) => { | ||
const iframe = document.createElement('iframe'); | ||
iframe.style.width = '100px'; | ||
iframe.style.height = '100px'; | ||
iframe.onload = () => resolve(iframe); | ||
document.body.appendChild(iframe); | ||
test.add_cleanup(() => iframe.remove()); | ||
}); | ||
iframe.contentDocument.body.innerHTML = '<span>some content</span>'; | ||
window.preventOptimization1 = iframe.getBoundingClientRect(); | ||
window.preventOptimization2 = iframe.contentDocument.querySelector('span').getBoundingClientRect(); | ||
return iframe; | ||
} | ||
|
||
for (const query of ['(max-width: 150px)', '(width: 100px)', '(orientation: portrait)', '(aspect-ratio: 1/1)', '(max-aspect-ratio: 4/3)']) { | ||
promise_test(async function () { | ||
const iframe = await createFrameAndUpdateLayout(this); | ||
const mediaQuery = iframe.contentWindow.matchMedia(query); | ||
assert_true(mediaQuery.matches); | ||
iframe.style.width = '200px'; | ||
assert_false(mediaQuery.matches); | ||
}, `matchMedia('${query}').matches should update immediately`); | ||
} | ||
|
||
for (const query of ['(height: 100px)', '(max-height: 150px)', '(min-aspect-ratio: 3/4)']) { | ||
promise_test(async function () { | ||
const iframe = await createFrameAndUpdateLayout(this); | ||
const mediaQuery = iframe.contentWindow.matchMedia(query); | ||
assert_true(mediaQuery.matches); | ||
iframe.style.height = '200px'; | ||
assert_false(mediaQuery.matches); | ||
}, `matchMedia('${query}').matches should update immediately`); | ||
} | ||
|
||
for (const query of ['(min-height: 150px)', '(aspect-ratio: 1/2)']) { | ||
promise_test(async function () { | ||
const iframe = await createFrameAndUpdateLayout(this); | ||
const mediaQuery = iframe.contentWindow.matchMedia(query); | ||
assert_false(mediaQuery.matches); | ||
iframe.style.height = '200px'; | ||
assert_true(mediaQuery.matches); | ||
}, `matchMedia('${query}').matches should update immediately`); | ||
} | ||
|
||
for (const query of ['(min-width: 150px)', '(min-aspect-ratio: 4/3)']) { | ||
promise_test(async function () { | ||
const iframe = await createFrameAndUpdateLayout(this); | ||
const mediaQuery = iframe.contentWindow.matchMedia(query); | ||
assert_false(mediaQuery.matches); | ||
iframe.style.width = '200px'; | ||
assert_true(mediaQuery.matches); | ||
}, `matchMedia('${query}').matches should update immediately`); | ||
} | ||
|
||
for (const query of ['(max-width: 150px)', '(width: 100px)', '(orientation: portrait)', '(aspect-ratio: 1/1)', '(max-aspect-ratio: 4/3)']) { | ||
promise_test(async function () { | ||
const iframe = await createFrameAndUpdateLayout(this); | ||
const mediaQuery = iframe.contentWindow.matchMedia(query); | ||
let changes = 0; | ||
mediaQuery.addEventListener('change', () => ++changes); | ||
assert_true(mediaQuery.matches); | ||
assert_equals(changes, 0); | ||
iframe.style.width = '200px'; | ||
assert_false(mediaQuery.matches); | ||
assert_equals(changes, 0); | ||
await new Promise(requestAnimationFrame); | ||
await new Promise(setTimeout); | ||
assert_false(mediaQuery.matches); | ||
assert_equals(changes, 1); | ||
}, `matchMedia('${query}') should not receive a change event until update the rendering step of HTML5 event loop`); | ||
} | ||
|
||
for (const query of ['(max-width: 150px)', '(width: 100px)', '(orientation: portrait)', '(aspect-ratio: 1/1)', '(max-aspect-ratio: 4/3)']) { | ||
promise_test(async function () { | ||
const iframe = await createFrameAndUpdateLayout(this); | ||
const mediaQuery = iframe.contentWindow.matchMedia(query); | ||
const events = []; | ||
iframe.contentWindow.addEventListener('resize', () => { | ||
assert_array_equals(events, []); | ||
events.push('resize'); | ||
}); | ||
mediaQuery.addEventListener('change', () => events.push('change')); | ||
assert_true(mediaQuery.matches); | ||
assert_array_equals(events, []); | ||
iframe.style.width = '200px'; | ||
assert_false(mediaQuery.matches); | ||
assert_array_equals(events, []); | ||
await new Promise(requestAnimationFrame); | ||
assert_false(mediaQuery.matches); | ||
assert_array_equals(events, ['resize', 'change']); | ||
}, `matchMedia('${query}') should receive a change event after resize event on the window but before a requestAnimationFrame callback is called`); | ||
} | ||
|
||
</script> | ||
</body> |
1 change: 0 additions & 1 deletion
1
LayoutTests/printing/print-with-media-query-destory-expected.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1 @@ | ||
Pass if no crash or assert | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters