mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Auto merge of #9837 - nox:deterministic-raf, r=mbrubeck
Use a BTreeMap for Document::animation_frame_list (fixes #9834) The callbacks must stay ordered. <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.svg" height="40" alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/9837) <!-- Reviewable:end -->
This commit is contained in:
commit
9ceda7de50
4 changed files with 66 additions and 10 deletions
|
@ -70,7 +70,7 @@ use serde::{Deserialize, Serialize};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::boxed::FnBox;
|
use std::boxed::FnBox;
|
||||||
use std::cell::{Cell, UnsafeCell};
|
use std::cell::{Cell, UnsafeCell};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::hash::{BuildHasher, Hash};
|
use std::hash::{BuildHasher, Hash};
|
||||||
use std::intrinsics::return_address;
|
use std::intrinsics::return_address;
|
||||||
|
@ -246,6 +246,16 @@ impl<K, V, S> JSTraceable for HashMap<K, V, S>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<K: Ord + JSTraceable, V: JSTraceable> JSTraceable for BTreeMap<K, V> {
|
||||||
|
#[inline]
|
||||||
|
fn trace(&self, trc: *mut JSTracer) {
|
||||||
|
for (k, v) in self {
|
||||||
|
k.trace(trc);
|
||||||
|
v.trace(trc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<A: JSTraceable, B: JSTraceable> JSTraceable for (A, B) {
|
impl<A: JSTraceable, B: JSTraceable> JSTraceable for (A, B) {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn trace(&self, trc: *mut JSTracer) {
|
fn trace(&self, trc: *mut JSTracer) {
|
||||||
|
|
|
@ -98,10 +98,10 @@ use std::ascii::AsciiExt;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::boxed::FnBox;
|
use std::boxed::FnBox;
|
||||||
use std::cell::{Cell, Ref, RefMut};
|
use std::cell::{Cell, Ref, RefMut};
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||||
|
use std::collections::{BTreeMap, HashMap};
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::iter::FromIterator;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -185,7 +185,7 @@ pub struct Document {
|
||||||
/// https://html.spec.whatwg.org/multipage/#list-of-animation-frame-callbacks
|
/// https://html.spec.whatwg.org/multipage/#list-of-animation-frame-callbacks
|
||||||
/// List of animation frame callbacks
|
/// List of animation frame callbacks
|
||||||
#[ignore_heap_size_of = "closures are hard"]
|
#[ignore_heap_size_of = "closures are hard"]
|
||||||
animation_frame_list: DOMRefCell<HashMap<u32, Box<FnBox(f64)>>>,
|
animation_frame_list: DOMRefCell<BTreeMap<u32, Box<FnBox(f64)>>>,
|
||||||
/// Tracks all outstanding loads related to this document.
|
/// Tracks all outstanding loads related to this document.
|
||||||
loader: DOMRefCell<DocumentLoader>,
|
loader: DOMRefCell<DocumentLoader>,
|
||||||
/// The current active HTML parser, to allow resuming after interruptions.
|
/// The current active HTML parser, to allow resuming after interruptions.
|
||||||
|
@ -1248,11 +1248,8 @@ impl Document {
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#run-the-animation-frame-callbacks
|
/// https://html.spec.whatwg.org/multipage/#run-the-animation-frame-callbacks
|
||||||
pub fn run_the_animation_frame_callbacks(&self) {
|
pub fn run_the_animation_frame_callbacks(&self) {
|
||||||
let animation_frame_list;
|
let animation_frame_list =
|
||||||
{
|
mem::replace(&mut *self.animation_frame_list.borrow_mut(), BTreeMap::new());
|
||||||
let mut list = self.animation_frame_list.borrow_mut();
|
|
||||||
animation_frame_list = Vec::from_iter(list.drain());
|
|
||||||
}
|
|
||||||
let performance = self.window.Performance();
|
let performance = self.window.Performance();
|
||||||
let performance = performance.r();
|
let performance = performance.r();
|
||||||
let timing = performance.Now();
|
let timing = performance.Now();
|
||||||
|
@ -1590,7 +1587,7 @@ impl Document {
|
||||||
asap_scripts_set: DOMRefCell::new(vec![]),
|
asap_scripts_set: DOMRefCell::new(vec![]),
|
||||||
scripting_enabled: Cell::new(true),
|
scripting_enabled: Cell::new(true),
|
||||||
animation_frame_ident: Cell::new(0),
|
animation_frame_ident: Cell::new(0),
|
||||||
animation_frame_list: DOMRefCell::new(HashMap::new()),
|
animation_frame_list: DOMRefCell::new(BTreeMap::new()),
|
||||||
loader: DOMRefCell::new(doc_loader),
|
loader: DOMRefCell::new(doc_loader),
|
||||||
current_parser: Default::default(),
|
current_parser: Default::default(),
|
||||||
reflow_timeout: Cell::new(None),
|
reflow_timeout: Cell::new(None),
|
||||||
|
|
|
@ -5574,6 +5574,12 @@
|
||||||
"url": "/_mozilla/mozilla/collections.html"
|
"url": "/_mozilla/mozilla/collections.html"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"mozilla/deterministic-raf.html": [
|
||||||
|
{
|
||||||
|
"path": "mozilla/deterministic-raf.html",
|
||||||
|
"url": "/_mozilla/mozilla/deterministic-raf.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
"mozilla/documentElement.html": [
|
"mozilla/documentElement.html": [
|
||||||
{
|
{
|
||||||
"path": "mozilla/documentElement.html",
|
"path": "mozilla/documentElement.html",
|
||||||
|
|
43
tests/wpt/mozilla/tests/mozilla/deterministic-raf.html
Normal file
43
tests/wpt/mozilla/tests/mozilla/deterministic-raf.html
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
<!doctype html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title></title>
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<script>
|
||||||
|
async_test(function (t) {
|
||||||
|
var i = 0;
|
||||||
|
var log = [];
|
||||||
|
var loopB_ended = false;
|
||||||
|
|
||||||
|
var loopA = function () {
|
||||||
|
log.push("A");
|
||||||
|
if (i++ < 5) {
|
||||||
|
requestAnimationFrame(loopA);
|
||||||
|
} else {
|
||||||
|
assert_true(loopB_ended);
|
||||||
|
t.step(function () {
|
||||||
|
assert_array_equals(log,
|
||||||
|
["A", "B", "A", "B", "A", "B", "A", "B", "A", "B", "A"]);
|
||||||
|
});
|
||||||
|
t.done();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var loopB = function () {
|
||||||
|
log.push("B");
|
||||||
|
if (i < 5) {
|
||||||
|
requestAnimationFrame(loopB);
|
||||||
|
} else {
|
||||||
|
assert_false(loopB_ended);
|
||||||
|
loopB_ended = true;
|
||||||
|
t.step(function () {
|
||||||
|
assert_array_equals(log,
|
||||||
|
["A", "B", "A", "B", "A", "B", "A", "B", "A", "B"]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
loopA();
|
||||||
|
loopB();
|
||||||
|
}, "Concurrent requestAnimationFrame loops are deterministic");
|
||||||
|
</script>
|
Loading…
Add table
Add a link
Reference in a new issue