aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock8
-rw-r--r--components/devtools/actors/browsing_context.rs39
-rw-r--r--components/devtools/actors/console.rs1
-rw-r--r--components/devtools/actors/watcher.rs1
-rw-r--r--components/devtools/actors/worker.rs11
-rw-r--r--components/devtools/lib.rs2
-rw-r--r--components/devtools/resource.rs42
-rw-r--r--components/layout/flow/root.rs11
-rw-r--r--components/layout/fragment_tree/box_fragment.rs25
-rw-r--r--components/layout/fragment_tree/fragment.rs31
-rw-r--r--components/layout/fragment_tree/fragment_tree.rs77
-rw-r--r--components/layout/layout_impl.rs68
-rw-r--r--components/layout/query.rs190
-rw-r--r--components/script/dom/bindings/error.rs1
-rw-r--r--components/script/dom/bindings/serializable.rs14
-rw-r--r--components/script/dom/bindings/structuredclone.rs78
-rw-r--r--components/script/dom/bindings/transferable.rs9
-rw-r--r--components/script/dom/blob.rs14
-rw-r--r--components/script/dom/cssstylesheet.rs30
-rw-r--r--components/script/dom/domexception.rs22
-rw-r--r--components/script/dom/dompoint.rs16
-rw-r--r--components/script/dom/dompointreadonly.rs16
-rw-r--r--components/script/dom/messageport.rs12
-rw-r--r--components/script/dom/readablestream.rs12
-rw-r--r--components/script/dom/window.rs5
-rw-r--r--components/script/dom/writablestream.rs12
-rw-r--r--components/script_bindings/error.rs2
-rw-r--r--components/script_bindings/webidls/CSSStyleSheet.webidl1
-rw-r--r--components/shared/script_layout/lib.rs2
-rw-r--r--tests/wpt/meta/css/css-mixins/at-function-parsing.html.ini99
-rw-r--r--tests/wpt/meta/css/css-nesting/nested-declarations-cssom.html.ini30
-rw-r--r--tests/wpt/meta/css/cssom/CSSStyleSheet-constructable-baseURL.html.ini6
-rw-r--r--tests/wpt/meta/css/cssom/CSSStyleSheet-constructable-disabled-regular-sheet-insertion.html.ini4
-rw-r--r--tests/wpt/meta/css/cssom/CSSStyleSheet-constructable.html.ini12
-rw-r--r--tests/wpt/meta/css/cssom/adoptedstylesheets-modify-array-and-sheet.html.ini9
-rw-r--r--tests/wpt/meta/css/cssom/idlharness.html.ini9
36 files changed, 396 insertions, 525 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 9df8210ab64..97046da9bac 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2478,9 +2478,9 @@ dependencies = [
[[package]]
name = "getrandom"
-version = "0.2.15"
+version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
+checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
dependencies = [
"cfg-if",
"libc",
@@ -7791,9 +7791,9 @@ dependencies = [
[[package]]
name = "tokio-util"
-version = "0.7.14"
+version = "0.7.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034"
+checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df"
dependencies = [
"bytes",
"futures-core",
diff --git a/components/devtools/actors/browsing_context.rs b/components/devtools/actors/browsing_context.rs
index c4ead7272bd..5de0855df4a 100644
--- a/components/devtools/actors/browsing_context.rs
+++ b/components/devtools/actors/browsing_context.rs
@@ -31,6 +31,7 @@ use crate::actors::thread::ThreadActor;
use crate::actors::watcher::{SessionContext, SessionContextType, WatcherActor};
use crate::id::{DevtoolsBrowserId, DevtoolsBrowsingContextId, DevtoolsOuterWindowId, IdMap};
use crate::protocol::JsonPacketStream;
+use crate::resource::ResourceAvailable;
use crate::{EmptyReplyMsg, StreamId};
#[derive(Serialize)]
@@ -57,14 +58,6 @@ struct FrameUpdateMsg {
}
#[derive(Serialize)]
-struct ResourceAvailableReply<T: Serialize> {
- from: String,
- #[serde(rename = "type")]
- type_: String,
- array: Vec<(String, Vec<T>)>,
-}
-
-#[derive(Serialize)]
struct TabNavigated {
from: String,
#[serde(rename = "type")]
@@ -152,6 +145,16 @@ pub(crate) struct BrowsingContextActor {
pub watcher: String,
}
+impl ResourceAvailable for BrowsingContextActor {
+ fn actor_name(&self) -> String {
+ self.name.clone()
+ }
+
+ fn get_streams(&self) -> &RefCell<HashMap<StreamId, TcpStream>> {
+ &self.streams
+ }
+}
+
impl Actor for BrowsingContextActor {
fn name(&self) -> String {
self.name.clone()
@@ -358,26 +361,6 @@ impl BrowsingContextActor {
});
}
- pub(crate) fn resource_available<T: Serialize>(&self, resource: T, resource_type: String) {
- self.resources_available(vec![resource], resource_type);
- }
-
- pub(crate) fn resources_available<T: Serialize>(
- &self,
- resources: Vec<T>,
- resource_type: String,
- ) {
- let msg = ResourceAvailableReply::<T> {
- from: self.name(),
- type_: "resources-available-array".into(),
- array: vec![(resource_type, resources)],
- };
-
- for stream in self.streams.borrow_mut().values_mut() {
- let _ = stream.write_json_packet(&msg);
- }
- }
-
pub fn simulate_color_scheme(&self, theme: Theme) -> Result<(), ()> {
self.script_chan
.send(SimulateColorScheme(self.active_pipeline_id.get(), theme))
diff --git a/components/devtools/actors/console.rs b/components/devtools/actors/console.rs
index ecd718e47d4..3897ffa0fce 100644
--- a/components/devtools/actors/console.rs
+++ b/components/devtools/actors/console.rs
@@ -30,6 +30,7 @@ use crate::actors::browsing_context::BrowsingContextActor;
use crate::actors::object::ObjectActor;
use crate::actors::worker::WorkerActor;
use crate::protocol::JsonPacketStream;
+use crate::resource::ResourceAvailable;
use crate::{StreamId, UniqueId};
trait EncodableConsoleMessage {
diff --git a/components/devtools/actors/watcher.rs b/components/devtools/actors/watcher.rs
index 77f82c1023a..d48374fc523 100644
--- a/components/devtools/actors/watcher.rs
+++ b/components/devtools/actors/watcher.rs
@@ -29,6 +29,7 @@ use crate::actors::watcher::thread_configuration::{
ThreadConfigurationActor, ThreadConfigurationActorMsg,
};
use crate::protocol::JsonPacketStream;
+use crate::resource::ResourceAvailable;
use crate::{EmptyReplyMsg, StreamId};
pub mod network_parent;
diff --git a/components/devtools/actors/worker.rs b/components/devtools/actors/worker.rs
index 046befe9dc9..42c9d9a9c28 100644
--- a/components/devtools/actors/worker.rs
+++ b/components/devtools/actors/worker.rs
@@ -17,6 +17,7 @@ use servo_url::ServoUrl;
use crate::StreamId;
use crate::actor::{Actor, ActorMessageStatus, ActorRegistry};
use crate::protocol::JsonPacketStream;
+use crate::resource::ResourceAvailable;
#[derive(Clone, Copy)]
#[allow(dead_code)]
@@ -53,6 +54,16 @@ impl WorkerActor {
}
}
+impl ResourceAvailable for WorkerActor {
+ fn actor_name(&self) -> String {
+ self.name.clone()
+ }
+
+ fn get_streams(&self) -> &RefCell<HashMap<StreamId, TcpStream>> {
+ &self.streams
+ }
+}
+
impl Actor for WorkerActor {
fn name(&self) -> String {
self.name.clone()
diff --git a/components/devtools/lib.rs b/components/devtools/lib.rs
index 74b028d5655..d4c3095b025 100644
--- a/components/devtools/lib.rs
+++ b/components/devtools/lib.rs
@@ -30,6 +30,7 @@ use devtools_traits::{
use embedder_traits::{AllowOrDeny, EmbedderMsg, EmbedderProxy};
use ipc_channel::ipc::{self, IpcSender};
use log::trace;
+use resource::ResourceAvailable;
use serde::Serialize;
use servo_rand::RngCore;
@@ -75,6 +76,7 @@ mod actors {
mod id;
mod network_handler;
mod protocol;
+mod resource;
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
enum UniqueId {
diff --git a/components/devtools/resource.rs b/components/devtools/resource.rs
new file mode 100644
index 00000000000..7cef8188cc8
--- /dev/null
+++ b/components/devtools/resource.rs
@@ -0,0 +1,42 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+use std::cell::RefCell;
+use std::collections::HashMap;
+use std::net::TcpStream;
+
+use serde::Serialize;
+
+use crate::StreamId;
+use crate::protocol::JsonPacketStream;
+
+#[derive(Serialize)]
+pub(crate) struct ResourceAvailableReply<T: Serialize> {
+ pub from: String,
+ #[serde(rename = "type")]
+ pub type_: String,
+ pub array: Vec<(String, Vec<T>)>,
+}
+
+pub(crate) trait ResourceAvailable {
+ fn actor_name(&self) -> String;
+
+ fn get_streams(&self) -> &RefCell<HashMap<StreamId, TcpStream>>;
+
+ fn resource_available<T: Serialize>(&self, resource: T, resource_type: String) {
+ self.resources_available(vec![resource], resource_type);
+ }
+
+ fn resources_available<T: Serialize>(&self, resources: Vec<T>, resource_type: String) {
+ let msg = ResourceAvailableReply::<T> {
+ from: self.actor_name(),
+ type_: "resources-available-array".into(),
+ array: vec![(resource_type, resources)],
+ };
+
+ for stream in self.get_streams().borrow_mut().values_mut() {
+ let _ = stream.write_json_packet(&msg);
+ }
+ }
+}
diff --git a/components/layout/flow/root.rs b/components/layout/flow/root.rs
index 390b4664e60..e8b7b6f5402 100644
--- a/components/layout/flow/root.rs
+++ b/components/layout/flow/root.rs
@@ -428,13 +428,14 @@ impl BoxTree {
acc.union(&child_overflow)
});
- FragmentTree {
+ FragmentTree::new(
+ layout_context,
root_fragments,
scrollable_overflow,
- initial_containing_block: physical_containing_block,
- canvas_background: self.canvas_background.clone(),
- viewport_scroll_sensitivity: self.viewport_scroll_sensitivity,
- }
+ physical_containing_block,
+ self.canvas_background.clone(),
+ self.viewport_scroll_sensitivity,
+ )
}
}
diff --git a/components/layout/fragment_tree/box_fragment.rs b/components/layout/fragment_tree/box_fragment.rs
index 30be154caf1..0e83c0d71a6 100644
--- a/components/layout/fragment_tree/box_fragment.rs
+++ b/components/layout/fragment_tree/box_fragment.rs
@@ -65,6 +65,10 @@ pub(crate) struct BoxFragment {
/// does not include padding, border, or margin -- it only includes content.
pub content_rect: PhysicalRect<Au>,
+ /// This [`BoxFragment`]'s containing block rectangle in coordinates relative to
+ /// the initial containing block, but not taking into account any transforms.
+ pub cumulative_containing_block_rect: PhysicalRect<Au>,
+
pub padding: PhysicalSides<Au>,
pub border: PhysicalSides<Au>,
pub margin: PhysicalSides<Au>,
@@ -120,6 +124,7 @@ impl BoxFragment {
style,
children,
content_rect,
+ cumulative_containing_block_rect: Default::default(),
padding,
border,
margin,
@@ -195,6 +200,8 @@ impl BoxFragment {
self
}
+ /// Get the scrollable overflow for this [`BoxFragment`] relative to its
+ /// containing block.
pub fn scrollable_overflow(&self) -> PhysicalRect<Au> {
let physical_padding_rect = self.padding_rect();
let content_origin = self.content_rect.origin.to_vector();
@@ -205,6 +212,10 @@ impl BoxFragment {
)
}
+ pub fn offset_by_containing_block(&self, rect: &PhysicalRect<Au>) -> PhysicalRect<Au> {
+ rect.translate(self.cumulative_containing_block_rect.origin.to_vector())
+ }
+
pub(crate) fn padding_rect(&self) -> PhysicalRect<Au> {
self.content_rect.outer_rect(self.padding)
}
@@ -278,10 +289,7 @@ impl BoxFragment {
overflow
}
- pub(crate) fn calculate_resolved_insets_if_positioned(
- &self,
- containing_block: &PhysicalRect<Au>,
- ) -> PhysicalSides<AuOrAuto> {
+ pub(crate) fn calculate_resolved_insets_if_positioned(&self) -> PhysicalSides<AuOrAuto> {
let position = self.style.get_box().position;
debug_assert_ne!(
position,
@@ -309,7 +317,10 @@ impl BoxFragment {
// used value. Otherwise the resolved value is the computed value."
// https://drafts.csswg.org/cssom/#resolved-values
let insets = self.style.physical_box_offsets();
- let (cb_width, cb_height) = (containing_block.width(), containing_block.height());
+ let (cb_width, cb_height) = (
+ self.cumulative_containing_block_rect.width(),
+ self.cumulative_containing_block_rect.height(),
+ );
if position == ComputedPosition::Relative {
let get_resolved_axis = |start: &LengthPercentageOrAuto,
end: &LengthPercentageOrAuto,
@@ -394,4 +405,8 @@ impl BoxFragment {
_ => CollapsedBlockMargins::zero(),
}
}
+
+ pub(crate) fn set_containing_block(&mut self, containing_block: &PhysicalRect<Au>) {
+ self.cumulative_containing_block_rect = *containing_block;
+ }
}
diff --git a/components/layout/fragment_tree/fragment.rs b/components/layout/fragment_tree/fragment.rs
index d0d1b9b1104..c08ddae55e9 100644
--- a/components/layout/fragment_tree/fragment.rs
+++ b/components/layout/fragment_tree/fragment.rs
@@ -112,6 +112,7 @@ impl Fragment {
Fragment::Float(fragment) => fragment.borrow().base.clone(),
})
}
+
pub(crate) fn mutate_content_rect(&mut self, callback: impl FnOnce(&mut PhysicalRect<Au>)) {
match self {
Fragment::Box(box_fragment) | Fragment::Float(box_fragment) => {
@@ -124,6 +125,26 @@ impl Fragment {
}
}
+ pub(crate) fn set_containing_block(&self, containing_block: &PhysicalRect<Au>) {
+ match self {
+ Fragment::Box(box_fragment) => box_fragment
+ .borrow_mut()
+ .set_containing_block(containing_block),
+ Fragment::Float(float_fragment) => float_fragment
+ .borrow_mut()
+ .set_containing_block(containing_block),
+ Fragment::Positioning(_) => {},
+ Fragment::AbsoluteOrFixedPositioned(hoisted_shared_fragment) => {
+ if let Some(ref fragment) = hoisted_shared_fragment.borrow().fragment {
+ fragment.set_containing_block(containing_block);
+ }
+ },
+ Fragment::Text(_) => {},
+ Fragment::Image(_) => {},
+ Fragment::IFrame(_) => {},
+ }
+ }
+
pub fn tag(&self) -> Option<Tag> {
self.base().and_then(|base| base.tag)
}
@@ -146,12 +167,12 @@ impl Fragment {
}
}
- pub fn scrolling_area(&self, containing_block: &PhysicalRect<Au>) -> PhysicalRect<Au> {
+ pub fn scrolling_area(&self) -> PhysicalRect<Au> {
match self {
- Fragment::Box(fragment) | Fragment::Float(fragment) => fragment
- .borrow()
- .scrollable_overflow()
- .translate(containing_block.origin.to_vector()),
+ Fragment::Box(fragment) | Fragment::Float(fragment) => {
+ let fragment = fragment.borrow();
+ fragment.offset_by_containing_block(&fragment.scrollable_overflow())
+ },
_ => self.scrollable_overflow(),
}
}
diff --git a/components/layout/fragment_tree/fragment_tree.rs b/components/layout/fragment_tree/fragment_tree.rs
index bb3c659466c..589ae69e8e5 100644
--- a/components/layout/fragment_tree/fragment_tree.rs
+++ b/components/layout/fragment_tree/fragment_tree.rs
@@ -13,6 +13,7 @@ use style::dom::OpaqueNode;
use webrender_api::units;
use super::{ContainingBlockManager, Fragment, Tag};
+use crate::context::LayoutContext;
use crate::display_list::StackingContext;
use crate::flow::CanvasBackground;
use crate::geom::{PhysicalPoint, PhysicalRect};
@@ -44,6 +45,58 @@ pub struct FragmentTree {
}
impl FragmentTree {
+ pub(crate) fn new(
+ layout_context: &LayoutContext,
+ root_fragments: Vec<Fragment>,
+ scrollable_overflow: PhysicalRect<Au>,
+ initial_containing_block: PhysicalRect<Au>,
+ canvas_background: CanvasBackground,
+ viewport_scroll_sensitivity: AxesScrollSensitivity,
+ ) -> Self {
+ let fragment_tree = Self {
+ root_fragments,
+ scrollable_overflow,
+ initial_containing_block,
+ canvas_background,
+ viewport_scroll_sensitivity,
+ };
+
+ // As part of building the fragment tree, we want to stop animating elements and
+ // pseudo-elements that used to be animating or had animating images attached to
+ // them. Create a set of all elements that used to be animating.
+ let mut animations = layout_context.style_context.animations.sets.write();
+ let mut invalid_animating_nodes: FxHashSet<_> = animations.keys().cloned().collect();
+ let mut image_animations = layout_context.node_image_animation_map.write().to_owned();
+ let mut invalid_image_animating_nodes: FxHashSet<_> = image_animations
+ .keys()
+ .cloned()
+ .map(|node| AnimationSetKey::new(node, None))
+ .collect();
+
+ fragment_tree.find(|fragment, _level, containing_block| {
+ if let Some(tag) = fragment.tag() {
+ invalid_animating_nodes.remove(&AnimationSetKey::new(tag.node, tag.pseudo));
+ invalid_image_animating_nodes.remove(&AnimationSetKey::new(tag.node, tag.pseudo));
+ }
+
+ fragment.set_containing_block(containing_block);
+ None::<()>
+ });
+
+ // Cancel animations for any elements and pseudo-elements that are no longer found
+ // in the fragment tree.
+ for node in &invalid_animating_nodes {
+ if let Some(state) = animations.get_mut(node) {
+ state.cancel_all_animations();
+ }
+ }
+ for node in &invalid_image_animating_nodes {
+ image_animations.remove(&node.node);
+ }
+
+ fragment_tree
+ }
+
pub(crate) fn build_display_list(
&self,
builder: &mut crate::display_list::DisplayListBuilder,
@@ -86,14 +139,6 @@ impl FragmentTree {
.find_map(|child| child.find(&info, 0, &mut process_func))
}
- pub fn remove_nodes_in_fragment_tree_from_set(&self, set: &mut FxHashSet<AnimationSetKey>) {
- self.find(|fragment, _, _| {
- let tag = fragment.tag()?;
- set.remove(&AnimationSetKey::new(tag.node, tag.pseudo));
- None::<()>
- });
- }
-
/// Get the vector of rectangles that surrounds the fragments of the node with the given address.
/// This function answers the `getClientRects()` query and the union of the rectangles answers
/// the `getBoundingClientRect()` query.
@@ -173,22 +218,8 @@ impl FragmentTree {
pub fn get_scrolling_area_for_viewport(&self) -> PhysicalRect<Au> {
let mut scroll_area = self.initial_containing_block;
for fragment in self.root_fragments.iter() {
- scroll_area = fragment
- .scrolling_area(&self.initial_containing_block)
- .union(&scroll_area);
+ scroll_area = fragment.scrolling_area().union(&scroll_area);
}
scroll_area
}
-
- pub fn get_scrolling_area_for_node(&self, requested_node: OpaqueNode) -> PhysicalRect<Au> {
- let tag_to_find = Tag::new(requested_node);
- let scroll_area = self.find(|fragment, _, containing_block| {
- if fragment.tag() == Some(tag_to_find) {
- Some(fragment.scrolling_area(containing_block))
- } else {
- None
- }
- });
- scroll_area.unwrap_or_else(PhysicalRect::<Au>::zero)
- }
}
diff --git a/components/layout/layout_impl.rs b/components/layout/layout_impl.rs
index c661f2c2c7b..361760692d2 100644
--- a/components/layout/layout_impl.rs
+++ b/components/layout/layout_impl.rs
@@ -23,7 +23,7 @@ use euclid::{Point2D, Scale, Size2D, Vector2D};
use fnv::FnvHashMap;
use fonts::{FontContext, FontContextWebFontMethods};
use fonts_traits::StylesheetWebFontLoadFinishedCallback;
-use fxhash::{FxHashMap, FxHashSet};
+use fxhash::FxHashMap;
use ipc_channel::ipc::IpcSender;
use log::{debug, error};
use malloc_size_of::{MallocConditionalSizeOf, MallocSizeOf, MallocSizeOfOps};
@@ -37,15 +37,15 @@ use profile_traits::{path, time_profile};
use rayon::ThreadPool;
use script::layout_dom::{ServoLayoutDocument, ServoLayoutElement, ServoLayoutNode};
use script_layout_interface::{
- ImageAnimationState, Layout, LayoutConfig, LayoutFactory, NodesFromPointQueryType,
- OffsetParentResponse, ReflowGoal, ReflowRequest, ReflowResult, TrustedNodeAddress,
+ Layout, LayoutConfig, LayoutFactory, NodesFromPointQueryType, OffsetParentResponse, ReflowGoal,
+ ReflowRequest, ReflowResult, TrustedNodeAddress,
};
use script_traits::{DrawAPaintImageResult, PaintWorkletError, Painter, ScriptThreadMessage};
use servo_arc::Arc as ServoArc;
use servo_config::opts::{self, DebugOptions};
use servo_config::pref;
use servo_url::ServoUrl;
-use style::animation::{AnimationSetKey, DocumentAnimationSet};
+use style::animation::DocumentAnimationSet;
use style::context::{
QuirksMode, RegisteredSpeculativePainter, RegisteredSpeculativePainters, SharedStyleContext,
};
@@ -330,14 +330,7 @@ impl Layout for LayoutThread {
TraversalFlags::empty(),
);
- let fragment_tree = self.fragment_tree.borrow().clone();
- process_resolved_style_request(
- &shared_style_context,
- node,
- &pseudo,
- &property_id,
- fragment_tree,
- )
+ process_resolved_style_request(&shared_style_context, node, &pseudo, &property_id)
}
#[cfg_attr(
@@ -380,7 +373,8 @@ impl Layout for LayoutThread {
feature = "tracing",
tracing::instrument(skip_all, fields(servo_profiling = true), level = "trace")
)]
- fn query_scrolling_area(&self, node: Option<OpaqueNode>) -> UntypedRect<i32> {
+ fn query_scrolling_area(&self, node: Option<TrustedNodeAddress>) -> UntypedRect<i32> {
+ let node = node.map(|node| unsafe { ServoLayoutNode::new(&node) });
process_node_scroll_area_request(node, self.fragment_tree.borrow().clone())
}
@@ -790,18 +784,6 @@ impl LayoutThread {
run_layout()
});
- Self::cancel_animations_for_nodes_not_in_fragment_tree(
- &recalc_style_traversal.context().style_context.animations,
- &fragment_tree,
- );
- Self::cancel_image_animation_for_nodes_not_in_fragment_tree(
- recalc_style_traversal
- .context()
- .node_image_animation_map
- .clone(),
- &fragment_tree,
- );
-
*self.fragment_tree.borrow_mut() = Some(fragment_tree);
if self.debug.dump_style_tree {
@@ -922,42 +904,6 @@ impl LayoutThread {
})
}
- /// Cancel animations for any nodes which have been removed from fragment tree.
- /// TODO(mrobinson): We should look into a way of doing this during flow tree construction.
- /// This also doesn't yet handles nodes that have been reparented.
- fn cancel_animations_for_nodes_not_in_fragment_tree(
- animations: &DocumentAnimationSet,
- root: &FragmentTree,
- ) {
- // Assume all nodes have been removed until proven otherwise.
- let mut animations = animations.sets.write();
- let mut invalid_nodes = animations.keys().cloned().collect();
- root.remove_nodes_in_fragment_tree_from_set(&mut invalid_nodes);
-
- // Cancel animations for any nodes that are no longer in the fragment tree.
- for node in &invalid_nodes {
- if let Some(state) = animations.get_mut(node) {
- state.cancel_all_animations();
- }
- }
- }
-
- fn cancel_image_animation_for_nodes_not_in_fragment_tree(
- image_animation_set: Arc<RwLock<FxHashMap<OpaqueNode, ImageAnimationState>>>,
- root: &FragmentTree,
- ) {
- let mut image_animations = image_animation_set.write().to_owned();
- let mut invalid_nodes: FxHashSet<AnimationSetKey> = image_animations
- .keys()
- .cloned()
- .map(|node| AnimationSetKey::new(node, None))
- .collect();
- root.remove_nodes_in_fragment_tree_from_set(&mut invalid_nodes);
- for node in &invalid_nodes {
- image_animations.remove(&node.node);
- }
- }
-
fn viewport_did_change(&mut self, viewport_details: ViewportDetails) -> bool {
let new_pixel_ratio = viewport_details.hidpi_scale_factor.get();
let new_viewport_size = Size2D::new(
diff --git a/components/layout/query.rs b/components/layout/query.rs
index 08b264deea9..3409f7c1923 100644
--- a/components/layout/query.rs
+++ b/components/layout/query.rs
@@ -83,14 +83,21 @@ pub fn process_node_geometry_request(
}
/// <https://drafts.csswg.org/cssom-view/#scrolling-area>
-pub fn process_node_scroll_area_request(
- requested_node: Option<OpaqueNode>,
+pub fn process_node_scroll_area_request<'dom>(
+ requested_node: Option<impl LayoutNode<'dom> + 'dom>,
fragment_tree: Option<Arc<FragmentTree>>,
) -> Rect<i32> {
- let rect = match (fragment_tree, requested_node) {
- (Some(tree), Some(node)) => tree.get_scrolling_area_for_node(node),
- (Some(tree), None) => tree.get_scrolling_area_for_viewport(),
- _ => return Rect::zero(),
+ let Some(tree) = fragment_tree else {
+ return Rect::zero();
+ };
+
+ let rect = match requested_node {
+ Some(node) => node
+ .fragments_for_pseudo(None)
+ .first()
+ .map(Fragment::scrolling_area)
+ .unwrap_or_default(),
+ None => tree.get_scrolling_area_for_viewport(),
};
Rect::new(
@@ -109,7 +116,6 @@ pub fn process_resolved_style_request<'dom>(
node: impl LayoutNode<'dom> + 'dom,
pseudo: &Option<PseudoElement>,
property: &PropertyId,
- fragment_tree: Option<Arc<FragmentTree>>,
) -> String {
if !node.as_element().unwrap().has_data() {
return process_resolved_style_request_for_unstyled_node(context, node, pseudo, property);
@@ -161,8 +167,6 @@ pub fn process_resolved_style_request<'dom>(
_ => style.computed_value_to_string(PropertyDeclarationId::Longhand(longhand_id)),
};
- let tag_to_find = Tag::new_pseudo(node.opaque(), *pseudo);
-
// https://drafts.csswg.org/cssom/#dom-window-getcomputedstyle
// Here we are trying to conform to the specification that says that getComputedStyle
// should return the used values in certain circumstances. For size and positional
@@ -191,107 +195,87 @@ pub fn process_resolved_style_request<'dom>(
return computed_style(None);
}
- let resolve_for_fragment =
- |fragment: &Fragment, containing_block: Option<&PhysicalRect<Au>>| {
- let (content_rect, margins, padding, specific_layout_info) = match fragment {
- Fragment::Box(box_fragment) | Fragment::Float(box_fragment) => {
- let box_fragment = box_fragment.borrow();
- if style.get_box().position != Position::Static {
- let resolved_insets = || {
- box_fragment
- .calculate_resolved_insets_if_positioned(containing_block.unwrap())
- };
- match longhand_id {
- LonghandId::Top => return resolved_insets().top.to_css_string(),
- LonghandId::Right => {
- return resolved_insets().right.to_css_string();
- },
- LonghandId::Bottom => {
- return resolved_insets().bottom.to_css_string();
- },
- LonghandId::Left => {
- return resolved_insets().left.to_css_string();
- },
- _ => {},
- }
- }
- let content_rect = box_fragment.content_rect;
- let margins = box_fragment.margin;
- let padding = box_fragment.padding;
- let specific_layout_info = box_fragment.specific_layout_info.clone();
- (content_rect, margins, padding, specific_layout_info)
- },
- Fragment::Positioning(positioning_fragment) => {
- let content_rect = positioning_fragment.borrow().rect;
- (
- content_rect,
- SideOffsets2D::zero(),
- SideOffsets2D::zero(),
- None,
- )
- },
- _ => return computed_style(Some(fragment)),
- };
-
- // https://drafts.csswg.org/css-grid/#resolved-track-list
- // > The grid-template-rows and grid-template-columns properties are
- // > resolved value special case properties.
- //
- // > When an element generates a grid container box...
- if display.inside() == DisplayInside::Grid {
- if let Some(SpecificLayoutInfo::Grid(info)) = specific_layout_info {
- if let Some(value) = resolve_grid_template(&info, style, longhand_id) {
- return value;
+ let resolve_for_fragment = |fragment: &Fragment| {
+ let (content_rect, margins, padding, specific_layout_info) = match fragment {
+ Fragment::Box(box_fragment) | Fragment::Float(box_fragment) => {
+ let box_fragment = box_fragment.borrow();
+ if style.get_box().position != Position::Static {
+ let resolved_insets = || box_fragment.calculate_resolved_insets_if_positioned();
+ match longhand_id {
+ LonghandId::Top => return resolved_insets().top.to_css_string(),
+ LonghandId::Right => {
+ return resolved_insets().right.to_css_string();
+ },
+ LonghandId::Bottom => {
+ return resolved_insets().bottom.to_css_string();
+ },
+ LonghandId::Left => {
+ return resolved_insets().left.to_css_string();
+ },
+ _ => {},
}
}
- }
+ let content_rect = box_fragment.content_rect;
+ let margins = box_fragment.margin;
+ let padding = box_fragment.padding;
+ let specific_layout_info = box_fragment.specific_layout_info.clone();
+ (content_rect, margins, padding, specific_layout_info)
+ },
+ Fragment::Positioning(positioning_fragment) => {
+ let content_rect = positioning_fragment.borrow().rect;
+ (
+ content_rect,
+ SideOffsets2D::zero(),
+ SideOffsets2D::zero(),
+ None,
+ )
+ },
+ _ => return computed_style(Some(fragment)),
+ };
- // https://drafts.csswg.org/cssom/#resolved-value-special-case-property-like-height
- // > If the property applies to the element or pseudo-element and the resolved value of the
- // > display property is not none or contents, then the resolved value is the used value.
- // > Otherwise the resolved value is the computed value.
- //
- // However, all browsers ignore that for margin and padding properties, and resolve to a length
- // even if the property doesn't apply: https://github.com/w3c/csswg-drafts/issues/10391
- match longhand_id {
- LonghandId::Width if resolved_size_should_be_used_value(fragment) => {
- content_rect.size.width
- },
- LonghandId::Height if resolved_size_should_be_used_value(fragment) => {
- content_rect.size.height
- },
- LonghandId::MarginBottom => margins.bottom,
- LonghandId::MarginTop => margins.top,
- LonghandId::MarginLeft => margins.left,
- LonghandId::MarginRight => margins.right,
- LonghandId::PaddingBottom => padding.bottom,
- LonghandId::PaddingTop => padding.top,
- LonghandId::PaddingLeft => padding.left,
- LonghandId::PaddingRight => padding.right,
- _ => return computed_style(Some(fragment)),
+ // https://drafts.csswg.org/css-grid/#resolved-track-list
+ // > The grid-template-rows and grid-template-columns properties are
+ // > resolved value special case properties.
+ //
+ // > When an element generates a grid container box...
+ if display.inside() == DisplayInside::Grid {
+ if let Some(SpecificLayoutInfo::Grid(info)) = specific_layout_info {
+ if let Some(value) = resolve_grid_template(&info, style, longhand_id) {
+ return value;
+ }
}
- .to_css_string()
- };
+ }
- if !matches!(
- longhand_id,
- LonghandId::Top | LonghandId::Bottom | LonghandId::Left | LonghandId::Right
- ) {
- if let Some(fragment) = node.fragments_for_pseudo(*pseudo).first() {
- return resolve_for_fragment(fragment, None);
+ // https://drafts.csswg.org/cssom/#resolved-value-special-case-property-like-height
+ // > If the property applies to the element or pseudo-element and the resolved value of the
+ // > display property is not none or contents, then the resolved value is the used value.
+ // > Otherwise the resolved value is the computed value.
+ //
+ // However, all browsers ignore that for margin and padding properties, and resolve to a length
+ // even if the property doesn't apply: https://github.com/w3c/csswg-drafts/issues/10391
+ match longhand_id {
+ LonghandId::Width if resolved_size_should_be_used_value(fragment) => {
+ content_rect.size.width
+ },
+ LonghandId::Height if resolved_size_should_be_used_value(fragment) => {
+ content_rect.size.height
+ },
+ LonghandId::MarginBottom => margins.bottom,
+ LonghandId::MarginTop => margins.top,
+ LonghandId::MarginLeft => margins.left,
+ LonghandId::MarginRight => margins.right,
+ LonghandId::PaddingBottom => padding.bottom,
+ LonghandId::PaddingTop => padding.top,
+ LonghandId::PaddingLeft => padding.left,
+ LonghandId::PaddingRight => padding.right,
+ _ => return computed_style(Some(fragment)),
}
- }
+ .to_css_string()
+ };
- fragment_tree
- .and_then(|fragment_tree| {
- fragment_tree.find(|fragment, _, containing_block| {
- if Some(tag_to_find) == fragment.tag() {
- Some(resolve_for_fragment(fragment, Some(containing_block)))
- } else {
- None
- }
- })
- })
+ node.fragments_for_pseudo(*pseudo)
+ .first()
+ .map(resolve_for_fragment)
.unwrap_or_else(|| computed_style(None))
}
diff --git a/components/script/dom/bindings/error.rs b/components/script/dom/bindings/error.rs
index b0fd301df6a..f5bd03cd8d7 100644
--- a/components/script/dom/bindings/error.rs
+++ b/components/script/dom/bindings/error.rs
@@ -93,6 +93,7 @@ pub(crate) fn throw_dom_exception(
Error::NotReadable => DOMErrorName::NotReadableError,
Error::Data => DOMErrorName::DataError,
Error::Operation => DOMErrorName::OperationError,
+ Error::NotAllowed => DOMErrorName::NotAllowedError,
Error::Type(message) => unsafe {
assert!(!JS_IsExceptionPending(*cx));
throw_type_error(*cx, &message);
diff --git a/components/script/dom/bindings/serializable.rs b/components/script/dom/bindings/serializable.rs
index 4aa1a94a0a4..d0e851b4799 100644
--- a/components/script/dom/bindings/serializable.rs
+++ b/components/script/dom/bindings/serializable.rs
@@ -11,7 +11,7 @@ use base::id::{Index, NamespaceIndex, PipelineNamespaceId};
use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::root::DomRoot;
-use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader};
+use crate::dom::bindings::structuredclone::StructuredData;
use crate::dom::globalscope::GlobalScope;
use crate::script_runtime::CanGc;
@@ -65,13 +65,7 @@ where
/// Returns the field of [StructuredDataReader]/[StructuredDataWriter] that
/// should be used to read/store serialized instances of this type.
- fn serialized_storage(
- data: StructuredData<'_>,
- ) -> &mut Option<HashMap<NamespaceIndex<Self::Index>, Self::Data>>;
-
- /// Returns the field of [StructuredDataReader] that should be used to store
- /// deserialized instances of this type.
- fn deserialized_storage(
- reader: &mut StructuredDataReader,
- ) -> &mut Option<HashMap<StorageKey, DomRoot<Self>>>;
+ fn serialized_storage<'a>(
+ data: StructuredData<'a, '_>,
+ ) -> &'a mut Option<HashMap<NamespaceIndex<Self::Index>, Self::Data>>;
}
diff --git a/components/script/dom/bindings/structuredclone.rs b/components/script/dom/bindings/structuredclone.rs
index 915a4951bb5..c9a49ba00c9 100644
--- a/components/script/dom/bindings/structuredclone.rs
+++ b/components/script/dom/bindings/structuredclone.rs
@@ -16,13 +16,14 @@ use constellation_traits::{
BlobImpl, DomException, DomPoint, MessagePortImpl, Serializable as SerializableInterface,
StructuredSerializedData, Transferrable as TransferrableInterface,
};
+use js::gc::RootedVec;
use js::glue::{
CopyJSStructuredCloneData, DeleteJSAutoStructuredCloneBuffer, GetLengthOfJSStructuredCloneData,
NewJSAutoStructuredCloneBuffer, WriteBytesToJSStructuredCloneData,
};
use js::jsapi::{
- CloneDataPolicy, HandleObject as RawHandleObject, JS_ClearPendingException, JS_ReadUint32Pair,
- JS_STRUCTURED_CLONE_VERSION, JS_WriteUint32Pair, JSContext, JSObject,
+ CloneDataPolicy, HandleObject as RawHandleObject, Heap, JS_ClearPendingException,
+ JS_ReadUint32Pair, JS_STRUCTURED_CLONE_VERSION, JS_WriteUint32Pair, JSContext, JSObject,
JSStructuredCloneCallbacks, JSStructuredCloneReader, JSStructuredCloneWriter,
MutableHandleObject as RawMutableHandleObject, StructuredCloneScope, TransferableOwnership,
};
@@ -93,7 +94,7 @@ fn reader_for_type(
) -> unsafe fn(
&GlobalScope,
*mut JSStructuredCloneReader,
- &mut StructuredDataReader,
+ &mut StructuredDataReader<'_>,
CanGc,
) -> *mut JSObject {
match val {
@@ -107,7 +108,7 @@ fn reader_for_type(
unsafe fn read_object<T: Serializable>(
owner: &GlobalScope,
r: *mut JSStructuredCloneReader,
- sc_reader: &mut StructuredDataReader,
+ sc_reader: &mut StructuredDataReader<'_>,
can_gc: CanGc,
) -> *mut JSObject {
let mut name_space: u32 = 0;
@@ -136,9 +137,8 @@ unsafe fn read_object<T: Serializable>(
}
if let Ok(obj) = T::deserialize(owner, serialized, can_gc) {
- let destination = T::deserialized_storage(sc_reader).get_or_insert_with(HashMap::new);
let reflector = obj.reflector().get_jsobject().get();
- destination.insert(storage_key, obj);
+ sc_reader.roots.push(Heap::boxed(reflector));
return reflector;
}
warn!("Reading structured data failed in {:?}.", owner.get_url());
@@ -191,7 +191,7 @@ unsafe extern "C" fn read_callback(
"tag should be higher than StructuredCloneTags::Min"
);
- let sc_reader = &mut *(closure as *mut StructuredDataReader);
+ let sc_reader = &mut *(closure as *mut StructuredDataReader<'_>);
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
let global = GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof));
for serializable in SerializableInterface::iter() {
@@ -259,7 +259,8 @@ unsafe extern "C" fn write_callback(
fn receiver_for_type(
val: TransferrableInterface,
-) -> fn(&GlobalScope, &mut StructuredDataReader, u64, RawMutableHandleObject) -> Result<(), ()> {
+) -> fn(&GlobalScope, &mut StructuredDataReader<'_>, u64, RawMutableHandleObject) -> Result<(), ()>
+{
match val {
TransferrableInterface::MessagePort => receive_object::<MessagePort>,
TransferrableInterface::ReadableStream => receive_object::<ReadableStream>,
@@ -269,7 +270,7 @@ fn receiver_for_type(
fn receive_object<T: Transferable>(
owner: &GlobalScope,
- sc_reader: &mut StructuredDataReader,
+ sc_reader: &mut StructuredDataReader<'_>,
extra_data: u64,
return_object: RawMutableHandleObject,
) -> Result<(), ()> {
@@ -305,13 +306,12 @@ fn receive_object<T: Transferable>(
);
};
- if let Ok(received) = T::transfer_receive(owner, id, serialized) {
- return_object.set(received.reflector().rootable().get());
- let storage = T::deserialized_storage(sc_reader).get_or_insert_with(Vec::new);
- storage.push(received);
- return Ok(());
- }
- Err(())
+ let Ok(received) = T::transfer_receive(owner, id, serialized) else {
+ return Err(());
+ };
+ return_object.set(received.reflector().rootable().get());
+ sc_reader.roots.push(Heap::boxed(return_object.get()));
+ Ok(())
}
unsafe extern "C" fn read_transfer_callback(
@@ -324,7 +324,7 @@ unsafe extern "C" fn read_transfer_callback(
closure: *mut raw::c_void,
return_object: RawMutableHandleObject,
) -> bool {
- let sc_reader = &mut *(closure as *mut StructuredDataReader);
+ let sc_reader = &mut *(closure as *mut StructuredDataReader<'_>);
let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
let owner = GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof));
@@ -489,8 +489,8 @@ static STRUCTURED_CLONE_CALLBACKS: JSStructuredCloneCallbacks = JSStructuredClon
sabCloned: Some(sab_cloned_callback),
};
-pub(crate) enum StructuredData<'a> {
- Reader(&'a mut StructuredDataReader),
+pub(crate) enum StructuredData<'a, 'b> {
+ Reader(&'a mut StructuredDataReader<'b>),
Writer(&'a mut StructuredDataWriter),
}
@@ -503,19 +503,11 @@ pub(crate) struct DOMErrorRecord {
/// Reader and writer structs for results from, and inputs to, structured-data read/write operations.
/// <https://html.spec.whatwg.org/multipage/#safe-passing-of-structured-data>
#[repr(C)]
-pub(crate) struct StructuredDataReader {
+pub(crate) struct StructuredDataReader<'a> {
/// A struct of error message.
- pub(crate) errors: DOMErrorRecord,
- /// A map of deserialized blobs, stored temporarily here to keep them rooted.
- pub(crate) blobs: Option<HashMap<StorageKey, DomRoot<Blob>>>,
- /// A map of deserialized points, stored temporarily here to keep them rooted.
- pub(crate) points_read_only: Option<HashMap<StorageKey, DomRoot<DOMPointReadOnly>>>,
- pub(crate) dom_points: Option<HashMap<StorageKey, DomRoot<DOMPoint>>>,
- /// A map of deserialized exceptions, stored temporarily here to keep them rooted.
- pub(crate) dom_exceptions: Option<HashMap<StorageKey, DomRoot<DOMException>>>,
- /// A vec of transfer-received DOM ports,
- /// to be made available to script through a message event.
- pub(crate) message_ports: Option<Vec<DomRoot<MessagePort>>>,
+ errors: DOMErrorRecord,
+ /// Rooted copies of every deserialized object to ensure they are not garbage collected.
+ roots: RootedVec<'a, Box<Heap<*mut JSObject>>>,
/// A map of port implementations,
/// used as part of the "transfer-receiving" steps of ports,
/// to produce the DOM ports stored in `message_ports` above.
@@ -528,12 +520,6 @@ pub(crate) struct StructuredDataReader {
pub(crate) points: Option<HashMap<DomPointId, DomPoint>>,
/// A map of serialized exceptions.
pub(crate) exceptions: Option<HashMap<DomExceptionId, DomException>>,
-
- /// <https://streams.spec.whatwg.org/#rs-transfer>
- pub(crate) readable_streams: Option<Vec<DomRoot<ReadableStream>>>,
-
- /// <https://streams.spec.whatwg.org/#ws-transfer>
- pub(crate) writable_streams: Option<Vec<DomRoot<WritableStream>>>,
}
/// A data holder for transferred and serialized objects.
@@ -618,19 +604,14 @@ pub(crate) fn read(
) -> Fallible<Vec<DomRoot<MessagePort>>> {
let cx = GlobalScope::get_cx();
let _ac = enter_realm(global);
+ rooted_vec!(let mut roots);
let mut sc_reader = StructuredDataReader {
- blobs: None,
- message_ports: None,
- points_read_only: None,
- dom_points: None,
- dom_exceptions: None,
+ roots,
port_impls: data.ports.take(),
blob_impls: data.blobs.take(),
points: data.points.take(),
exceptions: data.exceptions.take(),
errors: DOMErrorRecord { message: None },
- readable_streams: None,
- writable_streams: None,
};
let sc_reader_ptr = &mut sc_reader as *mut _;
unsafe {
@@ -666,8 +647,15 @@ pub(crate) fn read(
DeleteJSAutoStructuredCloneBuffer(scbuf);
+ let mut message_ports = vec![];
+ for reflector in sc_reader.roots.iter() {
+ let Ok(message_port) = root_from_object::<MessagePort>(reflector.get(), *cx) else {
+ continue;
+ };
+ message_ports.push(message_port);
+ }
// Any transfer-received port-impls should have been taken out.
assert!(sc_reader.port_impls.is_none());
- Ok(sc_reader.message_ports.take().unwrap_or_default())
+ Ok(message_ports)
}
}
diff --git a/components/script/dom/bindings/transferable.rs b/components/script/dom/bindings/transferable.rs
index b720c05ae37..e6b2f000f3a 100644
--- a/components/script/dom/bindings/transferable.rs
+++ b/components/script/dom/bindings/transferable.rs
@@ -12,7 +12,7 @@ use base::id::NamespaceIndex;
use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::root::DomRoot;
-use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader};
+use crate::dom::bindings::structuredclone::StructuredData;
use crate::dom::globalscope::GlobalScope;
pub(crate) trait Transferable: DomObject
where
@@ -32,8 +32,7 @@ where
serialized: Self::Data,
) -> Result<DomRoot<Self>, ()>;
- fn serialized_storage(
- data: StructuredData<'_>,
- ) -> &mut Option<HashMap<NamespaceIndex<Self::Index>, Self::Data>>;
- fn deserialized_storage(reader: &mut StructuredDataReader) -> &mut Option<Vec<DomRoot<Self>>>;
+ fn serialized_storage<'a>(
+ data: StructuredData<'a, '_>,
+ ) -> &'a mut Option<HashMap<NamespaceIndex<Self::Index>, Self::Data>>;
}
diff --git a/components/script/dom/blob.rs b/components/script/dom/blob.rs
index df2afafd698..27aa382c3fc 100644
--- a/components/script/dom/blob.rs
+++ b/components/script/dom/blob.rs
@@ -24,9 +24,9 @@ use crate::dom::bindings::codegen::UnionTypes::ArrayBufferOrArrayBufferViewOrBlo
use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object_with_proto};
use crate::dom::bindings::root::DomRoot;
-use crate::dom::bindings::serializable::{Serializable, StorageKey};
+use crate::dom::bindings::serializable::Serializable;
use crate::dom::bindings::str::DOMString;
-use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader};
+use crate::dom::bindings::structuredclone::StructuredData;
use crate::dom::globalscope::GlobalScope;
use crate::dom::promise::Promise;
use crate::dom::readablestream::ReadableStream;
@@ -119,18 +119,14 @@ impl Serializable for Blob {
Ok(deserialized_blob)
}
- fn serialized_storage(reader: StructuredData<'_>) -> &mut Option<HashMap<BlobId, Self::Data>> {
+ fn serialized_storage<'a>(
+ reader: StructuredData<'a, '_>,
+ ) -> &'a mut Option<HashMap<BlobId, Self::Data>> {
match reader {
StructuredData::Reader(r) => &mut r.blob_impls,
StructuredData::Writer(w) => &mut w.blobs,
}
}
-
- fn deserialized_storage(
- data: &mut StructuredDataReader,
- ) -> &mut Option<HashMap<StorageKey, DomRoot<Self>>> {
- &mut data.blobs
- }
}
/// Extract bytes from BlobParts, used by Blob and File constructor
diff --git a/components/script/dom/cssstylesheet.rs b/components/script/dom/cssstylesheet.rs
index 421e8f45523..a367c9943de 100644
--- a/components/script/dom/cssstylesheet.rs
+++ b/components/script/dom/cssstylesheet.rs
@@ -24,7 +24,7 @@ use crate::dom::bindings::reflector::{
DomGlobal, reflect_dom_object, reflect_dom_object_with_proto,
};
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
-use crate::dom::bindings::str::DOMString;
+use crate::dom::bindings::str::{DOMString, USVString};
use crate::dom::cssrulelist::{CSSRuleList, RulesSource};
use crate::dom::element::Element;
use crate::dom::medialist::MediaList;
@@ -290,4 +290,32 @@ impl CSSStyleSheetMethods<crate::DomTypeHolder> for CSSStyleSheet {
// > 8. Return -1.
Ok(-1)
}
+
+ /// <https://drafts.csswg.org/cssom/#synchronously-replace-the-rules-of-a-cssstylesheet>
+ fn ReplaceSync(&self, text: USVString) -> Result<(), Error> {
+ // Step 1. If the constructed flag is not set throw a NotAllowedError
+ if !self.is_constructed {
+ return Err(Error::NotAllowed);
+ }
+
+ // Step 2. Let rules be the result of running parse a stylesheet’s contents from text.
+ let global = self.global();
+ let window = global.as_window();
+
+ StyleStyleSheet::update_from_str(
+ &self.style_stylesheet,
+ &text,
+ UrlExtraData(window.get_url().get_arc()),
+ None,
+ window.css_error_reporter(),
+ AllowImportRules::No, // Step 3.If rules contains one or more @import rules, remove those rules from rules.
+ );
+
+ // Step 4. Set sheet’s CSS rules to rules.
+ // We reset our rule list, which will be initialized properly
+ // at the next getter access.
+ self.rulelist.set(None);
+
+ Ok(())
+ }
}
diff --git a/components/script/dom/domexception.rs b/components/script/dom/domexception.rs
index e63c3ff1f53..fbb807b7a95 100644
--- a/components/script/dom/domexception.rs
+++ b/components/script/dom/domexception.rs
@@ -17,9 +17,9 @@ use crate::dom::bindings::reflector::{
Reflector, reflect_dom_object, reflect_dom_object_with_proto,
};
use crate::dom::bindings::root::DomRoot;
-use crate::dom::bindings::serializable::{Serializable, StorageKey};
+use crate::dom::bindings::serializable::Serializable;
use crate::dom::bindings::str::DOMString;
-use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader};
+use crate::dom::bindings::structuredclone::StructuredData;
use crate::dom::globalscope::GlobalScope;
use crate::script_runtime::CanGc;
@@ -53,6 +53,7 @@ pub(crate) enum DOMErrorName {
NotReadableError,
DataError,
OperationError,
+ NotAllowedError,
}
impl DOMErrorName {
@@ -84,6 +85,7 @@ impl DOMErrorName {
"NotReadableError" => Some(DOMErrorName::NotReadableError),
"DataError" => Some(DOMErrorName::DataError),
"OperationError" => Some(DOMErrorName::OperationError),
+ "NotAllowedError" => Some(DOMErrorName::NotAllowedError),
_ => None,
}
}
@@ -135,6 +137,10 @@ impl DOMException {
DOMErrorName::OperationError => {
"The operation failed for an operation-specific reason."
},
+ DOMErrorName::NotAllowedError => {
+ r#"The request is not allowed by the user agent or the platform in the current context,
+ possibly because the user denied permission."#
+ },
};
(
@@ -252,18 +258,12 @@ impl Serializable for DOMException {
))
}
- fn serialized_storage(
- data: StructuredData<'_>,
- ) -> &mut Option<HashMap<DomExceptionId, Self::Data>> {
+ fn serialized_storage<'a>(
+ data: StructuredData<'a, '_>,
+ ) -> &'a mut Option<HashMap<DomExceptionId, Self::Data>> {
match data {
StructuredData::Reader(reader) => &mut reader.exceptions,
StructuredData::Writer(writer) => &mut writer.exceptions,
}
}
-
- fn deserialized_storage(
- reader: &mut StructuredDataReader,
- ) -> &mut Option<HashMap<StorageKey, DomRoot<Self>>> {
- &mut reader.dom_exceptions
- }
}
diff --git a/components/script/dom/dompoint.rs b/components/script/dom/dompoint.rs
index 006abb50def..5e848c43c47 100644
--- a/components/script/dom/dompoint.rs
+++ b/components/script/dom/dompoint.rs
@@ -14,8 +14,8 @@ use crate::dom::bindings::codegen::Bindings::DOMPointReadOnlyBinding::DOMPointRe
use crate::dom::bindings::error::Fallible;
use crate::dom::bindings::reflector::reflect_dom_object_with_proto;
use crate::dom::bindings::root::DomRoot;
-use crate::dom::bindings::serializable::{Serializable, StorageKey};
-use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader};
+use crate::dom::bindings::serializable::Serializable;
+use crate::dom::bindings::structuredclone::StructuredData;
use crate::dom::dompointreadonly::{DOMPointReadOnly, DOMPointWriteMethods};
use crate::dom::globalscope::GlobalScope;
use crate::script_runtime::CanGc;
@@ -163,18 +163,12 @@ impl Serializable for DOMPoint {
))
}
- fn serialized_storage(
- data: StructuredData<'_>,
- ) -> &mut Option<HashMap<DomPointId, Self::Data>> {
+ fn serialized_storage<'a>(
+ data: StructuredData<'a, '_>,
+ ) -> &'a mut Option<HashMap<DomPointId, Self::Data>> {
match data {
StructuredData::Reader(reader) => &mut reader.points,
StructuredData::Writer(writer) => &mut writer.points,
}
}
-
- fn deserialized_storage(
- reader: &mut StructuredDataReader,
- ) -> &mut Option<HashMap<StorageKey, DomRoot<Self>>> {
- &mut reader.dom_points
- }
}
diff --git a/components/script/dom/dompointreadonly.rs b/components/script/dom/dompointreadonly.rs
index 44e4a70b680..eb6bc9b93a9 100644
--- a/components/script/dom/dompointreadonly.rs
+++ b/components/script/dom/dompointreadonly.rs
@@ -15,8 +15,8 @@ use crate::dom::bindings::codegen::Bindings::DOMPointReadOnlyBinding::DOMPointRe
use crate::dom::bindings::error::Fallible;
use crate::dom::bindings::reflector::{Reflector, reflect_dom_object_with_proto};
use crate::dom::bindings::root::DomRoot;
-use crate::dom::bindings::serializable::{Serializable, StorageKey};
-use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader};
+use crate::dom::bindings::serializable::Serializable;
+use crate::dom::bindings::structuredclone::StructuredData;
use crate::dom::globalscope::GlobalScope;
use crate::script_runtime::CanGc;
@@ -172,18 +172,12 @@ impl Serializable for DOMPointReadOnly {
))
}
- fn serialized_storage(
- data: StructuredData<'_>,
- ) -> &mut Option<HashMap<DomPointId, Self::Data>> {
+ fn serialized_storage<'a>(
+ data: StructuredData<'a, '_>,
+ ) -> &'a mut Option<HashMap<DomPointId, Self::Data>> {
match data {
StructuredData::Reader(r) => &mut r.points,
StructuredData::Writer(w) => &mut w.points,
}
}
-
- fn deserialized_storage(
- reader: &mut StructuredDataReader,
- ) -> &mut Option<HashMap<StorageKey, DomRoot<Self>>> {
- &mut reader.points_read_only
- }
}
diff --git a/components/script/dom/messageport.rs b/components/script/dom/messageport.rs
index fe590052db4..85d94c1aa7a 100644
--- a/components/script/dom/messageport.rs
+++ b/components/script/dom/messageport.rs
@@ -23,7 +23,7 @@ use crate::dom::bindings::error::{Error, ErrorResult, ErrorToJsval};
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::{DomGlobal, reflect_dom_object};
use crate::dom::bindings::root::DomRoot;
-use crate::dom::bindings::structuredclone::{self, StructuredData, StructuredDataReader};
+use crate::dom::bindings::structuredclone::{self, StructuredData};
use crate::dom::bindings::trace::RootedTraceableBox;
use crate::dom::bindings::transferable::Transferable;
use crate::dom::bindings::utils::set_dictionary_property;
@@ -268,18 +268,14 @@ impl Transferable for MessagePort {
Ok(transferred_port)
}
- fn serialized_storage(
- data: StructuredData<'_>,
- ) -> &mut Option<HashMap<MessagePortId, Self::Data>> {
+ fn serialized_storage<'a>(
+ data: StructuredData<'a, '_>,
+ ) -> &'a mut Option<HashMap<MessagePortId, Self::Data>> {
match data {
StructuredData::Reader(r) => &mut r.port_impls,
StructuredData::Writer(w) => &mut w.ports,
}
}
-
- fn deserialized_storage(reader: &mut StructuredDataReader) -> &mut Option<Vec<DomRoot<Self>>> {
- &mut reader.message_ports
- }
}
impl MessagePortMethods<crate::DomTypeHolder> for MessagePort {
diff --git a/components/script/dom/readablestream.rs b/components/script/dom/readablestream.rs
index b445fb4b9fc..37899f18fec 100644
--- a/components/script/dom/readablestream.rs
+++ b/components/script/dom/readablestream.rs
@@ -59,7 +59,7 @@ use crate::realms::{enter_realm, InRealm};
use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
use crate::dom::promisenativehandler::{Callback, PromiseNativeHandler};
use crate::dom::bindings::transferable::Transferable;
-use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader};
+use crate::dom::bindings::structuredclone::StructuredData;
use super::bindings::buffer_source::HeapBufferSource;
use super::bindings::codegen::Bindings::ReadableStreamBYOBReaderBinding::ReadableStreamBYOBReaderReadOptions;
@@ -2247,16 +2247,12 @@ impl Transferable for ReadableStream {
}
/// Note: we are relying on the port transfer, so the data returned here are related to the port.
- fn serialized_storage(
- data: StructuredData<'_>,
- ) -> &mut Option<HashMap<MessagePortId, Self::Data>> {
+ fn serialized_storage<'a>(
+ data: StructuredData<'a, '_>,
+ ) -> &'a mut Option<HashMap<MessagePortId, Self::Data>> {
match data {
StructuredData::Reader(r) => &mut r.port_impls,
StructuredData::Writer(w) => &mut w.ports,
}
}
-
- fn deserialized_storage(reader: &mut StructuredDataReader) -> &mut Option<Vec<DomRoot<Self>>> {
- &mut reader.readable_streams
- }
}
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index 96176132b6b..efe61007ef8 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -2281,11 +2281,12 @@ impl Window {
node: Option<&Node>,
can_gc: CanGc,
) -> UntypedRect<i32> {
- let opaque = node.map(|node| node.to_opaque());
if !self.layout_reflow(QueryMsg::ScrollingAreaQuery, can_gc) {
return Rect::zero();
}
- self.layout.borrow().query_scrolling_area(opaque)
+ self.layout
+ .borrow()
+ .query_scrolling_area(node.map(Node::to_trusted_node_address))
}
pub(crate) fn scroll_offset_query(&self, node: &Node) -> Vector2D<f32, LayoutPixel> {
diff --git a/components/script/dom/writablestream.rs b/components/script/dom/writablestream.rs
index 1490fc694ef..e7e9ce906a6 100644
--- a/components/script/dom/writablestream.rs
+++ b/components/script/dom/writablestream.rs
@@ -27,7 +27,7 @@ use crate::dom::bindings::conversions::ConversionResult;
use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object_with_proto};
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
-use crate::dom::bindings::structuredclone::{StructuredData, StructuredDataReader};
+use crate::dom::bindings::structuredclone::StructuredData;
use crate::dom::bindings::transferable::Transferable;
use crate::dom::countqueuingstrategy::{extract_high_water_mark, extract_size_algorithm};
use crate::dom::domexception::{DOMErrorName, DOMException};
@@ -1182,16 +1182,12 @@ impl Transferable for WritableStream {
}
/// Note: we are relying on the port transfer, so the data returned here are related to the port.
- fn serialized_storage(
- data: StructuredData<'_>,
- ) -> &mut Option<HashMap<MessagePortId, Self::Data>> {
+ fn serialized_storage<'a>(
+ data: StructuredData<'a, '_>,
+ ) -> &'a mut Option<HashMap<MessagePortId, Self::Data>> {
match data {
StructuredData::Reader(r) => &mut r.port_impls,
StructuredData::Writer(w) => &mut w.ports,
}
}
-
- fn deserialized_storage(reader: &mut StructuredDataReader) -> &mut Option<Vec<DomRoot<Self>>> {
- &mut reader.writable_streams
- }
}
diff --git a/components/script_bindings/error.rs b/components/script_bindings/error.rs
index 8424ff0fa95..a95d0b0b78c 100644
--- a/components/script_bindings/error.rs
+++ b/components/script_bindings/error.rs
@@ -59,6 +59,8 @@ pub enum Error {
Data,
/// OperationError DOMException
Operation,
+ /// NotAllowedError DOMException
+ NotAllowed,
/// TypeError JavaScript Error
Type(String),
diff --git a/components/script_bindings/webidls/CSSStyleSheet.webidl b/components/script_bindings/webidls/CSSStyleSheet.webidl
index 1241b5c2769..302e7433300 100644
--- a/components/script_bindings/webidls/CSSStyleSheet.webidl
+++ b/components/script_bindings/webidls/CSSStyleSheet.webidl
@@ -11,6 +11,7 @@ interface CSSStyleSheet : StyleSheet {
[Throws, SameObject] readonly attribute CSSRuleList cssRules;
[Throws] unsigned long insertRule(DOMString rule, optional unsigned long index = 0);
[Throws] undefined deleteRule(unsigned long index);
+ [Throws] undefined replaceSync(USVString text);
};
dictionary CSSStyleSheetInit {
diff --git a/components/shared/script_layout/lib.rs b/components/shared/script_layout/lib.rs
index 9b052642c32..69e577e139d 100644
--- a/components/shared/script_layout/lib.rs
+++ b/components/shared/script_layout/lib.rs
@@ -265,7 +265,7 @@ pub trait Layout {
animations: DocumentAnimationSet,
animation_timeline_value: f64,
) -> Option<ServoArc<Font>>;
- fn query_scrolling_area(&self, node: Option<OpaqueNode>) -> Rect<i32>;
+ fn query_scrolling_area(&self, node: Option<TrustedNodeAddress>) -> Rect<i32>;
fn query_text_indext(&self, node: OpaqueNode, point: Point2D<f32>) -> Option<usize>;
}
diff --git a/tests/wpt/meta/css/css-mixins/at-function-parsing.html.ini b/tests/wpt/meta/css/css-mixins/at-function-parsing.html.ini
index de4e8c0d888..439bfaf373b 100644
--- a/tests/wpt/meta/css/css-mixins/at-function-parsing.html.ini
+++ b/tests/wpt/meta/css/css-mixins/at-function-parsing.html.ini
@@ -11,12 +11,6 @@
[@function --foo( --x ) is valid]
expected: FAIL
- [@function --foo () is invalid]
- expected: FAIL
-
- [@function --foo (--x) is invalid]
- expected: FAIL
-
[@function --foo(--x auto) is valid]
expected: FAIL
@@ -113,9 +107,6 @@
[@function --foo(--x <angle>: 10px) is valid]
expected: FAIL
- [@function --foo(--x: 10px !important) is invalid]
- expected: FAIL
-
[@function --foo(--x <length>#) is valid]
expected: FAIL
@@ -131,30 +122,6 @@
[@function --foo(--x <transform-function>+) is valid]
expected: FAIL
- [@function --foo(--x <transform-list>#) is invalid]
- expected: FAIL
-
- [@function --foo(--x <transform-list>+) is invalid]
- expected: FAIL
-
- [@function --foo(--x *) is invalid]
- expected: FAIL
-
- [@function --foo(--x !) is invalid]
- expected: FAIL
-
- [@function --foo(--x 50px) is invalid]
- expected: FAIL
-
- [@function --foo(--x <length> | auto) is invalid]
- expected: FAIL
-
- [@function --foo(--x none | auto) is invalid]
- expected: FAIL
-
- [@function --foo(--x <dino>) is invalid]
- expected: FAIL
-
[@function --foo(--x) returns type(*) is valid]
expected: FAIL
@@ -173,71 +140,5 @@
[@function --foo(--x) returns type(foo | bar) is valid]
expected: FAIL
- [@function --foo(--x) ! is invalid]
- expected: FAIL
-
- [@function --foo(--x) length is invalid]
- expected: FAIL
-
- [@function --foo(--x) returns is invalid]
- expected: FAIL
-
- [@function --foo(--x) returns is invalid]
- expected: FAIL
-
- [@function --foo(--x) returns * is invalid]
- expected: FAIL
-
- [@function --foo(--x) returns <transform-list># is invalid]
- expected: FAIL
-
- [@function --foo(--x) returns <transform-list>+ is invalid]
- expected: FAIL
-
- [@function --foo(--x) returns auto | none is invalid]
- expected: FAIL
-
- [@function --foo(--x): <length> is invalid]
- expected: FAIL
-
- [@function --foo(--x): length is invalid]
- expected: FAIL
-
- [@function --foo(--x) returneth <length> is invalid]
- expected: FAIL
-
[@function --foo(--x:1px, --y, --z:2px) is valid]
expected: FAIL
-
- [@function --foo(!) is invalid]
- expected: FAIL
-
- [@function --foo(--x: !) is invalid]
- expected: FAIL
-
- [@function --foo(--x type(!)) is invalid]
- expected: FAIL
-
- [@function --foo(,) is invalid]
- expected: FAIL
-
- [@function --foo(,,,) is invalid]
- expected: FAIL
-
- [@function --foo(--x, ;) is invalid]
- expected: FAIL
-
- [@function --foo(;) is invalid]
- expected: FAIL
-
- [@function --foo(\]) is invalid]
- expected: FAIL
-
- [@function --foo(, --x\]) is invalid]
- expected: FAIL
-
- [@function --foo(--x) ! <length> is invalid]
- expected: FAIL
-
- [@function --foo(--x) returns <length>! is invalid]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-nesting/nested-declarations-cssom.html.ini b/tests/wpt/meta/css/css-nesting/nested-declarations-cssom.html.ini
index 42ccc3a16cc..28d16a619d3 100644
--- a/tests/wpt/meta/css/css-nesting/nested-declarations-cssom.html.ini
+++ b/tests/wpt/meta/css/css-nesting/nested-declarations-cssom.html.ini
@@ -1,33 +1,3 @@
[nested-declarations-cssom.html]
- [Trailing declarations]
- expected: FAIL
-
- [Mixed declarations]
- expected: FAIL
-
- [CSSNestedDeclarations.style]
- expected: FAIL
-
- [Nested group rule]
- expected: FAIL
-
- [Nested @scope rule]
- expected: FAIL
-
- [Inner rule starting with an ident]
- expected: FAIL
-
- [Inserting a CSSNestedDeclaration rule into style rule]
- expected: FAIL
-
[Inserting a CSSNestedDeclaration rule into nested group rule]
expected: FAIL
-
- [Attempting to insert a CSSNestedDeclaration rule into top-level @media rule]
- expected: FAIL
-
- [Attempting to insert a CSSNestedDeclaration rule, empty block]
- expected: FAIL
-
- [Attempting to insert a CSSNestedDeclaration rule, all invalid declarations]
- expected: FAIL
diff --git a/tests/wpt/meta/css/cssom/CSSStyleSheet-constructable-baseURL.html.ini b/tests/wpt/meta/css/cssom/CSSStyleSheet-constructable-baseURL.html.ini
index a9bad39b1da..f9b211c4a49 100644
--- a/tests/wpt/meta/css/cssom/CSSStyleSheet-constructable-baseURL.html.ini
+++ b/tests/wpt/meta/css/cssom/CSSStyleSheet-constructable-baseURL.html.ini
@@ -1,9 +1,3 @@
[CSSStyleSheet-constructable-baseURL.html]
- [Constructing sheet with custom base URL ueses that URL for CSS rules]
- expected: FAIL
-
- [Constructing sheet with relative URL adds to the constructor document's base URL]
- expected: FAIL
-
[Constructing sheet with invalid base URL throws a NotAllowedError]
expected: FAIL
diff --git a/tests/wpt/meta/css/cssom/CSSStyleSheet-constructable-disabled-regular-sheet-insertion.html.ini b/tests/wpt/meta/css/cssom/CSSStyleSheet-constructable-disabled-regular-sheet-insertion.html.ini
deleted file mode 100644
index d9dd9972f10..00000000000
--- a/tests/wpt/meta/css/cssom/CSSStyleSheet-constructable-disabled-regular-sheet-insertion.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[CSSStyleSheet-constructable-disabled-regular-sheet-insertion.html]
- [Shouldn't crash / assert when inserting a stylesheet after there are disabled constructable sheets]
- expected: FAIL
-
diff --git a/tests/wpt/meta/css/cssom/CSSStyleSheet-constructable.html.ini b/tests/wpt/meta/css/cssom/CSSStyleSheet-constructable.html.ini
index e02c46febe6..b8d885c47bd 100644
--- a/tests/wpt/meta/css/cssom/CSSStyleSheet-constructable.html.ini
+++ b/tests/wpt/meta/css/cssom/CSSStyleSheet-constructable.html.ini
@@ -41,9 +41,6 @@
[Adding non-constructed stylesheet to AdoptedStyleSheets is not allowed when the owner document of the stylesheet and the AdoptedStyleSheets are in different document trees]
expected: FAIL
- [CSSStyleSheet.replaceSync replaces stylesheet text synchronously]
- expected: FAIL
-
[CSSStyleSheet.replaceSync correctly updates the style of its adopters synchronously]
expected: FAIL
@@ -62,9 +59,6 @@
[CSSStyleSheet.replace ignores @import rule but still loads other rules]
expected: FAIL
- [CSSStyleSheet.replaceSync allows, but ignores, import rule inside]
- expected: FAIL
-
[CSSStyleSheet.replace does not reject on failed imports]
expected: FAIL
@@ -73,9 +67,3 @@
[Adopting a shadow host's ancestor will empty adoptedStyleSheets if adopting to a different document]
expected: FAIL
-
- [Modifying an adopted stylesheet on a disconnected shadow root should not crash.]
- expected: FAIL
-
- [Constructing a sheet with the default base URL uses the constructor document's base URL for CSS rules]
- expected: FAIL
diff --git a/tests/wpt/meta/css/cssom/adoptedstylesheets-modify-array-and-sheet.html.ini b/tests/wpt/meta/css/cssom/adoptedstylesheets-modify-array-and-sheet.html.ini
index 97401f0fd7c..f3585fe7abf 100644
--- a/tests/wpt/meta/css/cssom/adoptedstylesheets-modify-array-and-sheet.html.ini
+++ b/tests/wpt/meta/css/cssom/adoptedstylesheets-modify-array-and-sheet.html.ini
@@ -1,2 +1,9 @@
[adoptedstylesheets-modify-array-and-sheet.html]
- expected: ERROR
+ [Add the two sheets. Text should be red.]
+ expected: FAIL
+
+ [Flip the two sheet. Still red.]
+ expected: FAIL
+
+ [Modify the color declaration. Should now be green.]
+ expected: FAIL
diff --git a/tests/wpt/meta/css/cssom/idlharness.html.ini b/tests/wpt/meta/css/cssom/idlharness.html.ini
index 4e3a2cedada..e87e7a353d2 100644
--- a/tests/wpt/meta/css/cssom/idlharness.html.ini
+++ b/tests/wpt/meta/css/cssom/idlharness.html.ini
@@ -395,21 +395,12 @@
[CSSStyleSheet interface: operation replace(USVString)]
expected: FAIL
- [CSSStyleSheet interface: operation replaceSync(USVString)]
- expected: FAIL
-
[CSSStyleSheet interface: sheet must inherit property "replace(USVString)" with the proper type]
expected: FAIL
[CSSStyleSheet interface: calling replace(USVString) on sheet with too few arguments must throw TypeError]
expected: FAIL
- [CSSStyleSheet interface: sheet must inherit property "replaceSync(USVString)" with the proper type]
- expected: FAIL
-
- [CSSStyleSheet interface: calling replaceSync(USVString) on sheet with too few arguments must throw TypeError]
- expected: FAIL
-
[Document interface: attribute adoptedStyleSheets]
expected: FAIL