Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upCalling matchMedia during a MQL change event will panic #14967
Comments
<script>
var m = window.matchMedia("(min-width: 400px)");
m.addListener(function() {
window.matchMedia("(min-width: 200px)");
});
</script>
|
|
@prampey Are you interested in working on this? |
|
@jdm So you want me to handle the error explicitly, instead of letting it panic right? |
|
What does the spec say? I imagine it supports this, but I'm not quite sure what the expected behaviour is. (It looks like the spec uses DOM events now; not sure if our implementation does to.) |
|
https://drafts.csswg.org/cssom-view/#evaluate-media-queries-and-report-changes just says iterate over all the media query list objects for a document and evaluate if their matching status changed. That means we need to support this case by allowing the |
|
@jdm But isn't the Perhaps, we could collect all the events formed during |
|
That sounds like a good solution to me. |
|
@jdm My bad. I didn't realise that in order to fire the events, you still need a reference to |
|
We could store a vector of changed MediaQueryList values and iterate over those using |
|
@jdm Sounds simpler. But does |
|
Yes - it ensures that the elements stored inside of it cannot be GCed, because they are explicitly rooted. |
|
@jdm So how do I store the vector with |
|
@jdm Yeah thanks for that. |
|
You'll want to store the result of JS::from_ref. |
|
@jdm Thanks. It works without errors now. Are there any tests to be written? |
|
An automated test that demonstrates this case working would be ideal. See test/wpt/README.md for instruction on writing new tests, and it can live in tests/wpt/mozilla/tests/mozilla. |
|
@jdm Okay so I decided to automate the MediaQuery matching up to 2 levels deep just to make sure that every instance has its own copy of Media Query lists to deal with. <html>
<head>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
test(function() {
var match1 = window.matchMedia("(min-width: 400px)");
match1.addListener(function() {
var match2 = window.matchMedia("(orientation: landscape)");
assert_not_equals(match2, undefined);
match2.addListener(function() {
var match3 = window.matchMedia("(orientation: portrait)");
assert_not_equals(match2, undefined);
});
window.resizeTo(600, 400);
});
}, "No mql reference borrow clashes found");
</script>
</head>
<body onload="window.resizeTo(600,600)"></body>
</html>The code runs properly. Is this enough? |
|
@prampey Make a PR and we will review it. |
|
@prampey The idea is right, but you will need to use async_test instead of test. I'm pretty sure that right now the test will be declared a success before the match1 listener is invoked. |
|
@jdm Yeah, thanks. I finally found the |
Calling matchMedia during a MQL change event will not panic <!-- Please describe your changes on the following line: --> Calling matchMedia now leads to a new copy of MQL objects to prevent errors when borrowing references from MQL during an MQL change event. --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #14967 (github issue number if applicable). <!-- Either: --> - [X] There are tests for these changes OR - [x] These changes do not require tests because _____ <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/15495) <!-- Reviewable:end -->
Calling matchMedia during a MQL change event will not panic <!-- Please describe your changes on the following line: --> Calling matchMedia now leads to a new copy of MQL objects to prevent errors when borrowing references from MQL during an MQL change event. --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #14967 (github issue number if applicable). <!-- Either: --> - [X] There are tests for these changes OR - [x] These changes do not require tests because _____ <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/15495) <!-- Reviewable:end -->
Calling matchMedia during a MQL change event will not panic <!-- Please describe your changes on the following line: --> Calling matchMedia now leads to a new copy of MQL objects to prevent errors when borrowing references from MQL during an MQL change event. --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #14967 (github issue number if applicable). <!-- Either: --> - [X] There are tests for these changes OR - [x] These changes do not require tests because _____ <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/15495) <!-- Reviewable:end -->
WeakMediaQueryListVec::evaluate_and_report_changescallsborrow()in order to iterate over the list of known media query lists. This dispatches a DOM event for each MQL that needs to report a change, which could end up callingWindow.matchMediawhich callsborrow_mut()on the list of known media query lists. It shouldn't be too difficult to put together a test demonstrating this.