Auto merge of #15495 - prampey:mql-borrow-error, r=jdm

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 -->
This commit is contained in:
bors-servo 2017-02-19 04:10:04 -08:00 committed by GitHub
commit debdebe8de
3 changed files with 51 additions and 6 deletions

View file

@ -138,9 +138,16 @@ impl WeakMediaQueryListVec {
/// Evaluate media query lists and report changes
/// https://drafts.csswg.org/cssom-view/#evaluate-media-queries-and-report-changes
pub fn evaluate_and_report_changes(&self) {
rooted_vec!(let mut mql_list);
self.cell.borrow_mut().update(|mql| {
let mql = mql.root().unwrap();
if let MediaQueryListMatchState::Changed(_) = mql.evaluate_changes() {
// Recording list of changed Media Queries
mql_list.push(JS::from_ref(&*mql));
}
});
// Sending change events for all changed Media Queries
for mql in mql_list.iter() {
let event = MediaQueryListEvent::new(&mql.global(),
atom!("change"),
false, false,
@ -148,7 +155,6 @@ impl WeakMediaQueryListVec {
mql.Matches());
event.upcast::<Event>().fire(mql.upcast::<EventTarget>());
}
});
}
}

View file

@ -13269,6 +13269,12 @@
{}
]
],
"mozilla/mql_borrow.html": [
[
"/_mozilla/mozilla/mql_borrow.html",
{}
]
],
"mozilla/navigator.html": [
[
"/_mozilla/mozilla/navigator.html",
@ -25854,6 +25860,10 @@
"5513229f79ab37de67eb4d60ea9dd23cd31d133f",
"support"
],
"mozilla/mql_borrow.html": [
"f8f9adebe09f9473a52e5ec4f075540b10b32d7e",
"testharness"
],
"mozilla/navigator.html": [
"939f453fecfb28a36cb93057382b56439b00b136",
"testharness"

View file

@ -0,0 +1,29 @@
<html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<iframe id="frame" height="600" width="600">
</iframe>
</body>
<script>
// Test to make sure matchMedia can be suitably used inside MediaQueryList listeners without any error in borrowing
// mql references
var test = async_test("Using matchMedia inside of a MediaQueryList callback does not panic");
var frame=document.getElementById("frame");
var win=frame.contentWindow;
var match1 = win.matchMedia("(min-width: 400px)");
match1.addListener(test.step_func(function() {
var match2 = win.matchMedia("(orientation: landscape)");
assert_not_equals(match2, undefined);
match2.addListener(test.step_func_done(function() {
var match3 = win.matchMedia("(orientation: portrait)");
assert_not_equals(match3, undefined);
}));
// Resizing frame to trigger match2 listener
frame.height=600;
frame.width=400;
}));
</script>
</html>