Showing preview only (5,424K chars total). Download the full file or copy to clipboard to get everything.
Repository: servo/stylo
Branch: main
Commit: 71c42fd1ed99
Files: 375
Total size: 5.1 MB
Directory structure:
gitextract_8xmmvn70/
├── .github/
│ └── workflows/
│ ├── main.yml
│ ├── mirror-to-release-branch.yml
│ └── sync-upstream.yml
├── .gitignore
├── Cargo.toml
├── README.md
├── SYNCING.md
├── commit-from-merge.sh
├── commit-from-squashed.sh
├── malloc_size_of/
│ ├── Cargo.toml
│ ├── LICENSE-APACHE
│ ├── LICENSE-MIT
│ └── lib.rs
├── rustfmt.toml
├── selectors/
│ ├── CHANGES.md
│ ├── Cargo.toml
│ ├── README.md
│ ├── attr.rs
│ ├── bloom.rs
│ ├── build.rs
│ ├── builder.rs
│ ├── context.rs
│ ├── kleene_value.rs
│ ├── lib.rs
│ ├── matching.rs
│ ├── nth_index_cache.rs
│ ├── parser.rs
│ ├── relative_selector/
│ │ ├── cache.rs
│ │ ├── filter.rs
│ │ └── mod.rs
│ ├── sink.rs
│ ├── tree.rs
│ └── visitor.rs
├── servo_arc/
│ ├── Cargo.toml
│ ├── LICENSE-APACHE
│ ├── LICENSE-MIT
│ └── lib.rs
├── shell.nix
├── start-rebase.sh
├── style/
│ ├── Cargo.toml
│ ├── README.md
│ ├── applicable_declarations.rs
│ ├── author_styles.rs
│ ├── bezier.rs
│ ├── bloom.rs
│ ├── build.rs
│ ├── build_gecko.rs
│ ├── color/
│ │ ├── color_function.rs
│ │ ├── component.rs
│ │ ├── convert.rs
│ │ ├── mix.rs
│ │ ├── mod.rs
│ │ ├── parsing.rs
│ │ └── to_css.rs
│ ├── context.rs
│ ├── counter_style/
│ │ ├── mod.rs
│ │ ├── predefined.rs
│ │ └── update_predefined.py
│ ├── custom_properties.rs
│ ├── custom_properties_map.rs
│ ├── data.rs
│ ├── device/
│ │ ├── gecko.rs
│ │ ├── mod.rs
│ │ └── servo.rs
│ ├── dom.rs
│ ├── dom_apis.rs
│ ├── driver.rs
│ ├── error_reporting.rs
│ ├── font_face.rs
│ ├── font_metrics.rs
│ ├── gecko/
│ │ ├── anon_boxes.toml
│ │ ├── arc_types.rs
│ │ ├── conversions.rs
│ │ ├── data.rs
│ │ ├── media_features.rs
│ │ ├── mod.rs
│ │ ├── non_ts_pseudo_class_list.rs
│ │ ├── pseudo_element.rs
│ │ ├── pseudo_element_definition.mako.rs
│ │ ├── pseudo_elements.py
│ │ ├── pseudo_elements.toml
│ │ ├── regen_atoms.py
│ │ ├── restyle_damage.rs
│ │ ├── selector_parser.rs
│ │ ├── snapshot.rs
│ │ ├── snapshot_helpers.rs
│ │ ├── traversal.rs
│ │ ├── url.rs
│ │ └── wrapper.rs
│ ├── gecko_bindings/
│ │ ├── mod.rs
│ │ └── sugar/
│ │ ├── mod.rs
│ │ ├── ns_com_ptr.rs
│ │ ├── ns_compatibility.rs
│ │ ├── ns_style_auto_array.rs
│ │ ├── origin_flags.rs
│ │ ├── ownership.rs
│ │ └── refptr.rs
│ ├── gecko_string_cache/
│ │ ├── mod.rs
│ │ └── namespace.rs
│ ├── global_style_data.rs
│ ├── invalidation/
│ │ ├── element/
│ │ │ ├── document_state.rs
│ │ │ ├── element_wrapper.rs
│ │ │ ├── invalidation_map.rs
│ │ │ ├── invalidator.rs
│ │ │ ├── mod.rs
│ │ │ ├── relative_selector.rs
│ │ │ ├── restyle_hints.rs
│ │ │ └── state_and_attributes.rs
│ │ ├── media_queries.rs
│ │ ├── mod.rs
│ │ ├── stylesheets.rs
│ │ └── viewport_units.rs
│ ├── lib.rs
│ ├── logical_geometry.rs
│ ├── macros.rs
│ ├── matching.rs
│ ├── media_queries/
│ │ ├── media_list.rs
│ │ ├── media_query.rs
│ │ └── mod.rs
│ ├── parallel.rs
│ ├── parser.rs
│ ├── piecewise_linear.rs
│ ├── properties/
│ │ ├── build.py
│ │ ├── cascade.rs
│ │ ├── computed_value_flags.rs
│ │ ├── counted_unknown_properties.py
│ │ ├── counter_style_descriptors.toml
│ │ ├── data.py
│ │ ├── declaration_block.rs
│ │ ├── font_face_descriptors.toml
│ │ ├── gecko.mako.rs
│ │ ├── helpers/
│ │ │ └── animated_properties.mako.rs
│ │ ├── helpers.mako.rs
│ │ ├── longhands.toml
│ │ ├── mod.rs
│ │ ├── properties.html.mako
│ │ ├── properties.mako.rs
│ │ ├── property_descriptors.toml
│ │ ├── shorthands.rs
│ │ ├── shorthands.toml
│ │ ├── vendored_python/
│ │ │ ├── mako-1.3.10-py3-none-any.whl
│ │ │ ├── markupsafe/
│ │ │ │ ├── LICENSE.txt
│ │ │ │ └── __init__.py
│ │ │ └── toml-0.10.2-py2.py3-none-any.whl
│ │ └── view_transition_descriptors.toml
│ ├── properties_and_values/
│ │ ├── mod.rs
│ │ ├── registry.rs
│ │ ├── rule.rs
│ │ ├── syntax/
│ │ │ ├── ascii.rs
│ │ │ ├── data_type.rs
│ │ │ └── mod.rs
│ │ └── value.rs
│ ├── queries/
│ │ ├── condition.rs
│ │ ├── feature.rs
│ │ ├── feature_expression.rs
│ │ ├── mod.rs
│ │ └── values.rs
│ ├── rule_cache.rs
│ ├── rule_collector.rs
│ ├── rule_tree/
│ │ ├── core.rs
│ │ ├── level.rs
│ │ ├── map.rs
│ │ ├── mod.rs
│ │ ├── source.rs
│ │ └── unsafe_box.rs
│ ├── scoped_tls.rs
│ ├── selector_map.rs
│ ├── selector_parser.rs
│ ├── servo/
│ │ ├── animation.rs
│ │ ├── attr.rs
│ │ ├── encoding_support.rs
│ │ ├── media_features.rs
│ │ ├── mod.rs
│ │ ├── restyle_damage.rs
│ │ ├── selector_parser.rs
│ │ ├── shadow_parts.rs
│ │ └── url.rs
│ ├── shared_lock.rs
│ ├── sharing/
│ │ ├── checks.rs
│ │ └── mod.rs
│ ├── simple_buckets_map.rs
│ ├── str.rs
│ ├── style_adjuster.rs
│ ├── style_resolver.rs
│ ├── stylesheet_set.rs
│ ├── stylesheets/
│ │ ├── appearance_base_rule.rs
│ │ ├── container_rule.rs
│ │ ├── counter_style_rule.rs
│ │ ├── document_rule.rs
│ │ ├── font_face_rule.rs
│ │ ├── font_feature_values_rule.rs
│ │ ├── font_palette_values_rule.rs
│ │ ├── import_rule.rs
│ │ ├── keyframes_rule.rs
│ │ ├── layer_rule.rs
│ │ ├── loader.rs
│ │ ├── margin_rule.rs
│ │ ├── media_rule.rs
│ │ ├── mod.rs
│ │ ├── namespace_rule.rs
│ │ ├── nested_declarations_rule.rs
│ │ ├── origin.rs
│ │ ├── page_rule.rs
│ │ ├── position_try_rule.rs
│ │ ├── property_rule.rs
│ │ ├── rule_list.rs
│ │ ├── rule_parser.rs
│ │ ├── rules_iterator.rs
│ │ ├── scope_rule.rs
│ │ ├── starting_style_rule.rs
│ │ ├── style_rule.rs
│ │ ├── stylesheet.rs
│ │ ├── supports_rule.rs
│ │ └── view_transition_rule.rs
│ ├── stylist.rs
│ ├── thread_state.rs
│ ├── traversal.rs
│ ├── traversal_flags.rs
│ ├── typed_om/
│ │ ├── mod.rs
│ │ ├── numeric_declaration.rs
│ │ ├── numeric_values.rs
│ │ └── sum_value.rs
│ ├── use_counters/
│ │ └── mod.rs
│ └── values/
│ ├── animated/
│ │ ├── color.rs
│ │ ├── effects.rs
│ │ ├── font.rs
│ │ ├── grid.rs
│ │ ├── lists.rs
│ │ ├── mod.rs
│ │ ├── svg.rs
│ │ └── transform.rs
│ ├── computed/
│ │ ├── align.rs
│ │ ├── angle.rs
│ │ ├── animation.rs
│ │ ├── background.rs
│ │ ├── basic_shape.rs
│ │ ├── border.rs
│ │ ├── box.rs
│ │ ├── color.rs
│ │ ├── column.rs
│ │ ├── counters.rs
│ │ ├── easing.rs
│ │ ├── effects.rs
│ │ ├── flex.rs
│ │ ├── font.rs
│ │ ├── image.rs
│ │ ├── length.rs
│ │ ├── length_percentage.rs
│ │ ├── list.rs
│ │ ├── mod.rs
│ │ ├── motion.rs
│ │ ├── outline.rs
│ │ ├── page.rs
│ │ ├── percentage.rs
│ │ ├── position.rs
│ │ ├── ratio.rs
│ │ ├── rect.rs
│ │ ├── resolution.rs
│ │ ├── svg.rs
│ │ ├── table.rs
│ │ ├── text.rs
│ │ ├── time.rs
│ │ ├── transform.rs
│ │ ├── ui.rs
│ │ └── url.rs
│ ├── distance.rs
│ ├── generics/
│ │ ├── animation.rs
│ │ ├── background.rs
│ │ ├── basic_shape.rs
│ │ ├── border.rs
│ │ ├── box.rs
│ │ ├── calc.rs
│ │ ├── color.rs
│ │ ├── column.rs
│ │ ├── counters.rs
│ │ ├── easing.rs
│ │ ├── effects.rs
│ │ ├── flex.rs
│ │ ├── font.rs
│ │ ├── grid.rs
│ │ ├── image.rs
│ │ ├── length.rs
│ │ ├── mod.rs
│ │ ├── motion.rs
│ │ ├── page.rs
│ │ ├── position.rs
│ │ ├── ratio.rs
│ │ ├── rect.rs
│ │ ├── size.rs
│ │ ├── svg.rs
│ │ ├── text.rs
│ │ ├── transform.rs
│ │ ├── ui.rs
│ │ └── url.rs
│ ├── mod.rs
│ ├── resolved/
│ │ ├── animation.rs
│ │ ├── color.rs
│ │ ├── counters.rs
│ │ └── mod.rs
│ └── specified/
│ ├── align.rs
│ ├── angle.rs
│ ├── animation.rs
│ ├── background.rs
│ ├── basic_shape.rs
│ ├── border.rs
│ ├── box.rs
│ ├── calc.rs
│ ├── color.rs
│ ├── column.rs
│ ├── counters.rs
│ ├── easing.rs
│ ├── effects.rs
│ ├── flex.rs
│ ├── font.rs
│ ├── grid.rs
│ ├── image.rs
│ ├── intersection_observer.rs
│ ├── length.rs
│ ├── list.rs
│ ├── mod.rs
│ ├── motion.rs
│ ├── outline.rs
│ ├── page.rs
│ ├── percentage.rs
│ ├── position.rs
│ ├── ratio.rs
│ ├── rect.rs
│ ├── resolution.rs
│ ├── source_size_list.rs
│ ├── svg.rs
│ ├── svg_path.rs
│ ├── table.rs
│ ├── text.rs
│ ├── time.rs
│ ├── transform.rs
│ ├── ui.rs
│ └── url.rs
├── style.paths
├── style_derive/
│ ├── Cargo.toml
│ ├── animate.rs
│ ├── cg.rs
│ ├── compute_squared_distance.rs
│ ├── lib.rs
│ ├── parse.rs
│ ├── specified_value_info.rs
│ ├── to_animated_value.rs
│ ├── to_animated_zero.rs
│ ├── to_computed_value.rs
│ ├── to_css.rs
│ ├── to_resolved_value.rs
│ └── to_typed.rs
├── style_traits/
│ ├── Cargo.toml
│ ├── arc_slice.rs
│ ├── dom.rs
│ ├── lib.rs
│ ├── owned_slice.rs
│ ├── owned_str.rs
│ ├── specified_value_info.rs
│ └── values.rs
├── stylo_atoms/
│ ├── Cargo.toml
│ ├── build.rs
│ ├── lib.rs
│ ├── predefined_counter_styles.rs
│ └── static_atoms.txt
├── stylo_dom/
│ ├── Cargo.toml
│ └── lib.rs
├── stylo_static_prefs/
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
├── sync.sh
├── to_shmem/
│ ├── Cargo.toml
│ └── lib.rs
└── to_shmem_derive/
├── Cargo.toml
├── lib.rs
├── to_shmem.rs
└── util.rs
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/main.yml
================================================
name: CI
on:
push:
branches: ["main"]
pull_request:
workflow_dispatch:
merge_group:
types: [checks_requested]
jobs:
linux-debug:
name: Linux (Debug)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Run Tests
run: cargo build --features servo
env:
RUST_BACKTRACE: 1
linux-release:
name: Linux (Release)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Run Tests
run: cargo build --release --features servo
env:
RUST_BACKTRACE: 1
macos-debug:
name: macOS (Debug)
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Run Tests
run: cargo build --features servo
env:
RUST_BACKTRACE: 1
windows-debug:
name: Windows (Debug)
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Run Tests
run: cargo build --features servo
env:
RUST_BACKTRACE: 1
build-result:
name: Result
runs-on: ubuntu-latest
if: ${{ always() }}
needs:
- linux-debug
- linux-release
- macos-debug
- windows-debug
steps:
- name: Success
if: ${{ !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') }}
run: exit 0
- name: Failure
if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
run: exit 1
================================================
FILE: .github/workflows/mirror-to-release-branch.yml
================================================
name: 🪞 Mirror `main`
on:
push:
branches:
- main
jobs:
mirror:
name: Mirror
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get branch name
id: branch-name
run: |
first_commit=$(git log --pretty=\%H --grep='Servo initial downstream commit')
upstream_base="$first_commit~"
echo BRANCH_NAME=$(git log -n1 --pretty='%as' $upstream_base) >> $GITHUB_OUTPUT
- uses: google/mirror-branch-action@v1.0
name: Mirror to ${{ steps.branch-name.outputs.BRANCH_NAME }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
source: main
dest: ${{ steps.branch-name.outputs.BRANCH_NAME }}
================================================
FILE: .github/workflows/sync-upstream.yml
================================================
name: Sync upstream with mozilla-central
on:
schedule:
- cron: '0 13 * * *'
workflow_dispatch:
jobs:
sync:
name: Sync
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 1
- uses: actions/cache@v3
with:
path: _cache/upstream
key: upstream
- run: |
./sync.sh _filtered
git fetch -f --progress ./_filtered main:upstream
git push -fu --progress origin upstream
================================================
FILE: .gitignore
================================================
/_cache/
/_filtered/
/target/
/style/properties/__pycache__/
Cargo.lock
================================================
FILE: Cargo.toml
================================================
[workspace]
resolver = "2"
members = [
"stylo_atoms",
"stylo_dom",
"malloc_size_of",
"rustfmt.toml",
"selectors",
"servo_arc",
"style",
"style_derive",
"stylo_static_prefs",
"style_traits",
"to_shmem",
"to_shmem_derive",
]
default-members = ["style"]
[workspace.package]
version = "0.17.0"
[workspace.dependencies]
# in-repo dependencies (separately versioned)
servo_arc = { version = "0.4.3", path = "./servo_arc" }
selectors = { version = "0.38.0", path = "./selectors" }
to_shmem = { version = "0.4.0", path = "./to_shmem", features = ["servo"] }
to_shmem_derive = { version = "0.1.0", path = "./to_shmem_derive" }
# in-repo dependencies (main version)
malloc_size_of = { version = "0.17.0", path = "./malloc_size_of", package = "stylo_malloc_size_of", features = ["servo"] }
static_prefs = { version = "0.17.0", path = "./stylo_static_prefs", package = "stylo_static_prefs" }
stylo_atoms = { version = "0.17.0", path = "./stylo_atoms" }
dom = { version = "0.17.0", path = "./stylo_dom", package = "stylo_dom" }
style_traits = { version = "0.17.0", path = "./style_traits", features = ["servo"], package = "stylo_traits"}
style_derive = { version = "0.17.0", path = "./style_derive", package = "stylo_derive"}
stylo = { version = "0.17.0", path = "./style" }
================================================
FILE: README.md
================================================
Stylo
=====
**High-Performance CSS Style Engine**
[](https://github.com/servo/stylo/actions)
[](https://crates.io/crates/stylo)
[](https://docs.rs/stylo)

Stylo is a high-performance, browser-grade CSS style engine written in Rust that powers [Servo](https://servo.org) and [Firefox](https://firefox.com). This repo contains Servo’s downstream version of Stylo. The upstream version lives in mozilla-central with the rest of the Gecko/Firefox codebase.
Coordination of Stylo development happens:
- Here in Github Issues
- In the [#stylo](https://servo.zulipchat.com/#narrow/channel/417109-stylo) channel of the [Servo Zulip](https://servo.zulipchat.com/)
- In the [#layout](https://chat.mozilla.org/#/room/#layout:mozilla.org) room of the Mozilla Matrix instance (matrix.mozilla.org)
## High-Level Documentation
- This [Mozilla Hacks article](https://hacks.mozilla.org/2017/08/inside-a-super-fast-css-engine-quantum-css-aka-stylo) contains a high-level overview of the Stylo architecture.
- There is a [chapter](https://book.servo.org/architecture/style.html) in the Servo Book (although it is a little out of date).
## Branches
The branches are as follows:
- [**upstream**](https://github.com/servo/style/tree/upstream) has upstream [mozilla-central](https://searchfox.org/mozilla-central/source/servo) filtered to the paths we care about ([style.paths](style.paths)), but is otherwise unmodified.
- [**main**](https://github.com/servo/style/tree/ci) adds our downstream patches, plus the scripts and workflows for syncing with mozilla-central on top of **upstream**.
> [!WARNING]
> This repo syncs from upstream by creating a new branch and then rebasing our changes on top of it. This means that `git pull` will not work across syncs (you will need to use `git fetch`, `git reset` and `git rebase`).
More information on the syncing process is available in [SYNCING.md](SYNCING.md)
## Crates
A guide to the crates contained within this repo
### Stylo Crates
These crates are largely implementation details of Stylo, although you may need to use some of them directly if you use Stylo.
| Directory | Crate | Notes |
| --- | --- | --- |
| style | [](https://crates.io/crates/stylo) | The main Stylo crate containing the entire CSS engine |
| style_traits | [](https://crates.io/crates/stylo_traits) | Types and traits which allow other code to interoperate with Stylo without depending on the main crate directly. |
| stylo_dom | [](https://crates.io/crates/stylo_dom) | Similar to stylo_traits (but much smaller) |
| stylo_atoms | [](https://crates.io/crates/stylo_atoms) | [Atoms](https://docs.rs/string_cache/latest/string_cache/struct.Atom.html) for CSS and HTML event related strings |
| stylo_static_prefs | [](https://crates.io/crates/stylo_static_prefs) | Configuration for Stylo. Can be used to set runtime preferences (enabling/disabling properties, etc) |
| style_derive | [](https://crates.io/crates/stylo_derive) | Internal derive macro for stylo crate |
### Standalone Crates
These crates form part of Stylo but are also be useful standalone.
| Directory | Crate | Notes |
| --- | --- | --- |
| selectors | [](https://crates.io/crates/selectors) | CSS Selector matching |
| servo_arc | [](https://crates.io/crates/servo_arc) | A variant on `std::Arc` |
You may also be interested in the `cssparser` crate which lives in the [servo/rust-cssparser](https://github.com/servo/rust-cssparser) repo.
### Support Crates
Low-level crates which could technically be used standalone but are unlikely to be generally useful in practice.
| Directory | Crate | Notes |
| --- | --- | --- |
| malloc_size_of | [](https://crates.io/crates/stylo_malloc_size_of) | Heap size measurement for Stylo values |
| to_shmem | [](https://crates.io/crates/to_shmem) | Internal utility crate for sharing memory across processes. |
| to_shmem_derive | [](https://crates.io/crates/to_shmem_derive) | Internal derive macro for to_shmem crate |
## Building Servo Against a Local Copy of Stylo
Assuming your local `servo` and `stylo` directories are siblings, you can build `servo` against `stylo` by adding the following to `servo/Cargo.toml`:
```toml
[patch."https://github.com/servo/stylo"]
selectors = { path = "../stylo/selectors" }
servo_arc = { path = "../stylo/servo_arc" }
stylo = { path = "../stylo/style" }
stylo_atoms = { path = "../stylo/stylo_atoms" }
stylo_dom = { path = "../stylo/stylo_dom" }
stylo_malloc_size_of = { path = "../stylo/malloc_size_of" }
stylo_static_prefs = { path = "../stylo/stylo_static_prefs" }
stylo_traits = { path = "../stylo/style_traits" }
```
## Releases
Releases are made every time this repository rebases its changes on top of the latest version of upstream Stylo. There are a lot of crates here. In order to publish them, they must be done in order. One order that works is:
- selectors
- stylo_static_prefs
- stylo_atoms
- stylo_malloc_size_of
- stylo_dom
- stylo_derive
- stylo_traits
- stylo
## License
Stylo is licensed under MPL 2.0
================================================
FILE: SYNCING.md
================================================
# Syncing
This file documents the process of syncing this repository with the upstream copy of Stylo in mozilla-central.
## Syncing `upstream` with mozilla-central
Start by generating a filtered copy of mozilla-central. This will cache the raw mozilla-central in `_cache/upstream`, storing the result in `_filtered`:
```sh
$ ./sync.sh _filtered
```
If `_filtered` already exists, you will need to delete it and try again:
```sh
$ rm -Rf _filtered
```
Now overwrite our `upstream` with those commits and push:
```sh
$ git fetch -f --progress ./_filtered main:upstream
$ git push -fu --progress origin upstream
```
## Rebasing `main` onto `upstream`
Start by fetching `upstream` into your local repo:
```sh
$ git fetch -f origin upstream:upstream
```
In general, the filtering process is deterministic, yielding the same commit hashes each time, so we can rebase normally:
```sh
$ git rebase upstream
```
But if the filtering config changes or Mozilla moves to GitHub, the commit hashes on `upstream` may change. In this case, we need to tell git where the old upstream ends and our own commits start (notice the `~`):
```sh
$ git log --pretty=\%H --grep='Servo initial downstream commit'
e62d7f0090941496e392e1dc91df103a38e3f488
$ git rebase --onto upstream e62d7f0090941496e392e1dc91df103a38e3f488~
Successfully rebased and updated refs/heads/main.
```
`start-rebase.sh` takes care of this automatically, but you should still use `git rebase` for subsequent steps like `--continue` and `--abort`:
```sh
$ ./start-rebase.sh upstream
$ ./start-rebase.sh upstream -i # interactive
$ git rebase --continue # not ./start-rebase.sh --continue
$ git rebase --abort # not ./start-rebase.sh --abort
```
Or if we aren’t ready to rebase onto the tip of upstream:
```sh
$ ./start-rebase.sh upstream~10 -i
```
================================================
FILE: commit-from-merge.sh
================================================
#!/bin/sh
# Usage: commit-from-merge.sh <path/to/servo/servo> <merge commit> [extra git-commit(1) arguments ...]
# Given a merge commit made by bors, runs git-commit(1) with your local changes
# while borrowing the author name/email from the right-hand parent of the merge,
# and the author date from the committer date of the merge.
set -eu
lookup_repo=$1; shift
merge_commit=$1; shift
author_name_email=$(git -C "$lookup_repo" log -n1 --pretty='%aN <%aE>' "$merge_commit"\^2)
committer_date=$(git -C "$lookup_repo" log -n1 --pretty='%cd' "$merge_commit")
set -- git commit --author="$author_name_email" --date="$committer_date" "$@"
echo "$@"
"$@"
================================================
FILE: commit-from-squashed.sh
================================================
#!/bin/sh
# Usage: commit-from-squashed.sh <squashed commit> [extra git-commit(1) arguments ...]
# Given a squashed commit made by the GitHub merge queue, runs git-commit(1) with your local changes
# while borrowing our author name/email from that commit, our author date from its committer date,
# and our commit message from that commit.
set -eu
squashed_commit=$1; shift
committer_date=$(git log -n1 --pretty='%cd' "$squashed_commit")
# -c is equivalent to --author=$(...'%aN <%aE>') -m $(...'%B'), but allows editing
set -- git commit -c "$squashed_commit" --date="$committer_date" "$@"
echo "$@"
"$@"
================================================
FILE: malloc_size_of/Cargo.toml
================================================
[package]
name = "stylo_malloc_size_of"
version.workspace = true
authors = ["The Servo Project Developers"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/servo/stylo"
description = "An allocator-agnostic crate for measuring the heap size of a value"
edition = "2021"
[lib]
path = "lib.rs"
[features]
gecko = ["thin-vec/gecko-ffi"]
servo = ["string_cache"]
[dependencies]
app_units = "0.7"
cssparser = "0.37"
euclid = "0.22"
selectors = { workspace = true }
servo_arc = { workspace = true }
smallbitvec = "2.3.0"
smallvec = "1.13"
string_cache = { version = "0.9", optional = true }
thin-vec = { version = "0.2.13" }
void = "1.0.2"
================================================
FILE: malloc_size_of/LICENSE-APACHE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: malloc_size_of/LICENSE-MIT
================================================
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
================================================
FILE: malloc_size_of/lib.rs
================================================
// Copyright 2016-2017 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! A crate for measuring the heap usage of data structures in a way that
//! integrates with Firefox's memory reporting, particularly the use of
//! mozjemalloc and DMD. In particular, it has the following features.
//! - It isn't bound to a particular heap allocator.
//! - It provides traits for both "shallow" and "deep" measurement, which gives
//! flexibility in the cases where the traits can't be used.
//! - It allows for measuring blocks even when only an interior pointer can be
//! obtained for heap allocations, e.g. `HashSet` and `HashMap`. (This relies
//! on the heap allocator having suitable support, which mozjemalloc has.)
//! - It allows handling of types like `Rc` and `Arc` by providing traits that
//! are different to the ones for non-graph structures.
//!
//! Suggested uses are as follows.
//! - When possible, use the `MallocSizeOf` trait. (Deriving support is
//! provided by the `malloc_size_of_derive` crate.)
//! - If you need an additional synchronization argument, provide a function
//! that is like the standard trait method, but with the extra argument.
//! - If you need multiple measurements for a type, provide a function named
//! `add_size_of` that takes a mutable reference to a struct that contains
//! the multiple measurement fields.
//! - When deep measurement (via `MallocSizeOf`) cannot be implemented for a
//! type, shallow measurement (via `MallocShallowSizeOf`) in combination with
//! iteration can be a useful substitute.
//! - `Rc` and `Arc` are always tricky, which is why `MallocSizeOf` is not (and
//! should not be) implemented for them.
//! - If an `Rc` or `Arc` is known to be a "primary" reference and can always
//! be measured, it should be measured via the `MallocUnconditionalSizeOf`
//! trait.
//! - If an `Rc` or `Arc` should be measured only if it hasn't been seen
//! before, it should be measured via the `MallocConditionalSizeOf` trait.
//! - Using universal function call syntax is a good idea when measuring boxed
//! fields in structs, because it makes it clear that the Box is being
//! measured as well as the thing it points to. E.g.
//! `<Box<_> as MallocSizeOf>::size_of(field, ops)`.
//!
//! Note: WebRender has a reduced fork of this crate, so that we can avoid
//! publishing this crate on crates.io.
use std::hash::{BuildHasher, Hash};
use std::mem::size_of;
use std::ops::Range;
use std::ops::{Deref, DerefMut};
use std::os::raw::c_void;
use void::Void;
/// A C function that takes a pointer to a heap allocation and returns its size.
type VoidPtrToSizeFn = unsafe extern "C" fn(ptr: *const c_void) -> usize;
/// A closure implementing a stateful predicate on pointers.
type VoidPtrToBoolFnMut = dyn FnMut(*const c_void) -> bool;
/// Operations used when measuring heap usage of data structures.
pub struct MallocSizeOfOps {
/// A function that returns the size of a heap allocation.
size_of_op: VoidPtrToSizeFn,
/// Like `size_of_op`, but can take an interior pointer. Optional because
/// not all allocators support this operation. If it's not provided, some
/// memory measurements will actually be computed estimates rather than
/// real and accurate measurements.
enclosing_size_of_op: Option<VoidPtrToSizeFn>,
/// Check if a pointer has been seen before, and remember it for next time.
/// Useful when measuring `Rc`s and `Arc`s. Optional, because many places
/// don't need it.
have_seen_ptr_op: Option<Box<VoidPtrToBoolFnMut>>,
}
impl MallocSizeOfOps {
pub fn new(
size_of: VoidPtrToSizeFn,
malloc_enclosing_size_of: Option<VoidPtrToSizeFn>,
have_seen_ptr: Option<Box<VoidPtrToBoolFnMut>>,
) -> Self {
MallocSizeOfOps {
size_of_op: size_of,
enclosing_size_of_op: malloc_enclosing_size_of,
have_seen_ptr_op: have_seen_ptr,
}
}
/// Check if an allocation is empty. This relies on knowledge of how Rust
/// handles empty allocations, which may change in the future.
fn is_empty<T: ?Sized>(ptr: *const T) -> bool {
// The correct condition is this:
// `ptr as usize <= ::std::mem::align_of::<T>()`
// But we can't call align_of() on a ?Sized T. So we approximate it
// with the following. 256 is large enough that it should always be
// larger than the required alignment, but small enough that it is
// always in the first page of memory and therefore not a legitimate
// address.
return ptr as *const usize as usize <= 256;
}
/// Call `size_of_op` on `ptr`, first checking that the allocation isn't
/// empty, because some types (such as `Vec`) utilize empty allocations.
pub unsafe fn malloc_size_of<T: ?Sized>(&self, ptr: *const T) -> usize {
if MallocSizeOfOps::is_empty(ptr) {
0
} else {
(self.size_of_op)(ptr as *const c_void)
}
}
/// Is an `enclosing_size_of_op` available?
pub fn has_malloc_enclosing_size_of(&self) -> bool {
self.enclosing_size_of_op.is_some()
}
/// Call `enclosing_size_of_op`, which must be available, on `ptr`, which
/// must not be empty.
pub unsafe fn malloc_enclosing_size_of<T>(&self, ptr: *const T) -> usize {
assert!(!MallocSizeOfOps::is_empty(ptr));
(self.enclosing_size_of_op.unwrap())(ptr as *const c_void)
}
/// Call `have_seen_ptr_op` on `ptr`.
pub fn have_seen_ptr<T>(&mut self, ptr: *const T) -> bool {
let have_seen_ptr_op = self
.have_seen_ptr_op
.as_mut()
.expect("missing have_seen_ptr_op");
have_seen_ptr_op(ptr as *const c_void)
}
}
/// Trait for measuring the "deep" heap usage of a data structure. This is the
/// most commonly-used of the traits.
pub trait MallocSizeOf {
/// Measure the heap usage of all descendant heap-allocated structures, but
/// not the space taken up by the value itself.
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
}
/// Trait for measuring the "shallow" heap usage of a container.
pub trait MallocShallowSizeOf {
/// Measure the heap usage of immediate heap-allocated descendant
/// structures, but not the space taken up by the value itself. Anything
/// beyond the immediate descendants must be measured separately, using
/// iteration.
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
}
/// Like `MallocSizeOf`, but with a different name so it cannot be used
/// accidentally with derive(MallocSizeOf). For use with types like `Rc` and
/// `Arc` when appropriate (e.g. when measuring a "primary" reference).
pub trait MallocUnconditionalSizeOf {
/// Measure the heap usage of all heap-allocated descendant structures, but
/// not the space taken up by the value itself.
fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
}
/// `MallocUnconditionalSizeOf` combined with `MallocShallowSizeOf`.
pub trait MallocUnconditionalShallowSizeOf {
/// `unconditional_size_of` combined with `shallow_size_of`.
fn unconditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
}
/// Like `MallocSizeOf`, but only measures if the value hasn't already been
/// measured. For use with types like `Rc` and `Arc` when appropriate (e.g.
/// when there is no "primary" reference).
pub trait MallocConditionalSizeOf {
/// Measure the heap usage of all heap-allocated descendant structures, but
/// not the space taken up by the value itself, and only if that heap usage
/// hasn't already been measured.
fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
}
/// `MallocConditionalSizeOf` combined with `MallocShallowSizeOf`.
pub trait MallocConditionalShallowSizeOf {
/// `conditional_size_of` combined with `shallow_size_of`.
fn conditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
}
impl MallocSizeOf for String {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
unsafe { ops.malloc_size_of(self.as_ptr()) }
}
}
impl<'a, T: ?Sized> MallocSizeOf for &'a T {
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
// Zero makes sense for a non-owning reference.
0
}
}
impl<T: ?Sized> MallocShallowSizeOf for Box<T> {
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
unsafe { ops.malloc_size_of(&**self) }
}
}
impl<T: MallocSizeOf + ?Sized> MallocSizeOf for Box<T> {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
self.shallow_size_of(ops) + (**self).size_of(ops)
}
}
impl MallocSizeOf for () {
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
0
}
}
impl<T1, T2> MallocSizeOf for (T1, T2)
where
T1: MallocSizeOf,
T2: MallocSizeOf,
{
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
self.0.size_of(ops) + self.1.size_of(ops)
}
}
impl<T1, T2, T3> MallocSizeOf for (T1, T2, T3)
where
T1: MallocSizeOf,
T2: MallocSizeOf,
T3: MallocSizeOf,
{
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
self.0.size_of(ops) + self.1.size_of(ops) + self.2.size_of(ops)
}
}
impl<T1, T2, T3, T4> MallocSizeOf for (T1, T2, T3, T4)
where
T1: MallocSizeOf,
T2: MallocSizeOf,
T3: MallocSizeOf,
T4: MallocSizeOf,
{
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
self.0.size_of(ops) + self.1.size_of(ops) + self.2.size_of(ops) + self.3.size_of(ops)
}
}
impl<T: MallocSizeOf> MallocSizeOf for Option<T> {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
if let Some(val) = self.as_ref() {
val.size_of(ops)
} else {
0
}
}
}
impl<T: MallocSizeOf, E: MallocSizeOf> MallocSizeOf for Result<T, E> {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
match *self {
Ok(ref x) => x.size_of(ops),
Err(ref e) => e.size_of(ops),
}
}
}
impl<T: MallocSizeOf + Copy> MallocSizeOf for std::cell::Cell<T> {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
self.get().size_of(ops)
}
}
impl<T: MallocSizeOf> MallocSizeOf for std::cell::RefCell<T> {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
self.borrow().size_of(ops)
}
}
impl<'a, B: ?Sized + ToOwned> MallocSizeOf for std::borrow::Cow<'a, B>
where
B::Owned: MallocSizeOf,
{
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
match *self {
std::borrow::Cow::Borrowed(_) => 0,
std::borrow::Cow::Owned(ref b) => b.size_of(ops),
}
}
}
impl<T: MallocSizeOf> MallocSizeOf for [T] {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
let mut n = 0;
for elem in self.iter() {
n += elem.size_of(ops);
}
n
}
}
impl<T> MallocShallowSizeOf for Vec<T> {
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
unsafe { ops.malloc_size_of(self.as_ptr()) }
}
}
impl<T: MallocSizeOf> MallocSizeOf for Vec<T> {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
let mut n = self.shallow_size_of(ops);
for elem in self.iter() {
n += elem.size_of(ops);
}
n
}
}
impl<T> MallocShallowSizeOf for std::collections::VecDeque<T> {
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
if ops.has_malloc_enclosing_size_of() {
if let Some(front) = self.front() {
// The front element is an interior pointer.
unsafe { ops.malloc_enclosing_size_of(&*front) }
} else {
// This assumes that no memory is allocated when the VecDeque is empty.
0
}
} else {
// An estimate.
self.capacity() * size_of::<T>()
}
}
}
impl<T: MallocSizeOf> MallocSizeOf for std::collections::VecDeque<T> {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
let mut n = self.shallow_size_of(ops);
for elem in self.iter() {
n += elem.size_of(ops);
}
n
}
}
impl<A: smallvec::Array> MallocShallowSizeOf for smallvec::SmallVec<A> {
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
if self.spilled() {
unsafe { ops.malloc_size_of(self.as_ptr()) }
} else {
0
}
}
}
impl<A> MallocSizeOf for smallvec::SmallVec<A>
where
A: smallvec::Array,
A::Item: MallocSizeOf,
{
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
let mut n = self.shallow_size_of(ops);
for elem in self.iter() {
n += elem.size_of(ops);
}
n
}
}
impl<T> MallocShallowSizeOf for thin_vec::ThinVec<T> {
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
if self.capacity() == 0 {
// If it's the singleton we might not be a heap pointer.
return 0;
}
assert_eq!(
std::mem::size_of::<Self>(),
std::mem::size_of::<*const ()>()
);
unsafe { ops.malloc_size_of(*(self as *const Self as *const *const ())) }
}
}
impl<T: MallocSizeOf> MallocSizeOf for thin_vec::ThinVec<T> {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
let mut n = self.shallow_size_of(ops);
for elem in self.iter() {
n += elem.size_of(ops);
}
n
}
}
macro_rules! malloc_size_of_hash_set {
($ty:ty) => {
impl<T, S> MallocShallowSizeOf for $ty
where
T: Eq + Hash,
S: BuildHasher,
{
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
if ops.has_malloc_enclosing_size_of() {
// The first value from the iterator gives us an interior pointer.
// `ops.malloc_enclosing_size_of()` then gives us the storage size.
// This assumes that the `HashSet`'s contents (values and hashes)
// are all stored in a single contiguous heap allocation.
self.iter()
.next()
.map_or(0, |t| unsafe { ops.malloc_enclosing_size_of(t) })
} else {
// An estimate.
self.capacity() * (size_of::<T>() + size_of::<usize>())
}
}
}
impl<T, S> MallocSizeOf for $ty
where
T: Eq + Hash + MallocSizeOf,
S: BuildHasher,
{
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
let mut n = self.shallow_size_of(ops);
for t in self.iter() {
n += t.size_of(ops);
}
n
}
}
};
}
malloc_size_of_hash_set!(std::collections::HashSet<T, S>);
macro_rules! malloc_size_of_hash_map {
($ty:ty) => {
impl<K, V, S> MallocShallowSizeOf for $ty
where
K: Eq + Hash,
S: BuildHasher,
{
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
// See the implementation for std::collections::HashSet for details.
if ops.has_malloc_enclosing_size_of() {
self.values()
.next()
.map_or(0, |v| unsafe { ops.malloc_enclosing_size_of(v) })
} else {
self.capacity() * (size_of::<V>() + size_of::<K>() + size_of::<usize>())
}
}
}
impl<K, V, S> MallocSizeOf for $ty
where
K: Eq + Hash + MallocSizeOf,
V: MallocSizeOf,
S: BuildHasher,
{
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
let mut n = self.shallow_size_of(ops);
for (k, v) in self.iter() {
n += k.size_of(ops);
n += v.size_of(ops);
}
n
}
}
};
}
malloc_size_of_hash_map!(std::collections::HashMap<K, V, S>);
impl<K, V> MallocShallowSizeOf for std::collections::BTreeMap<K, V>
where
K: Eq + Hash,
{
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
if ops.has_malloc_enclosing_size_of() {
self.values()
.next()
.map_or(0, |v| unsafe { ops.malloc_enclosing_size_of(v) })
} else {
self.len() * (size_of::<V>() + size_of::<K>() + size_of::<usize>())
}
}
}
impl<K, V> MallocSizeOf for std::collections::BTreeMap<K, V>
where
K: Eq + Hash + MallocSizeOf,
V: MallocSizeOf,
{
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
let mut n = self.shallow_size_of(ops);
for (k, v) in self.iter() {
n += k.size_of(ops);
n += v.size_of(ops);
}
n
}
}
// PhantomData is always 0.
impl<T> MallocSizeOf for std::marker::PhantomData<T> {
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
0
}
}
// XXX: we don't want MallocSizeOf to be defined for Rc and Arc. If negative
// trait bounds are ever allowed, this code should be uncommented.
// (We do have a compile-fail test for this:
// rc_arc_must_not_derive_malloc_size_of.rs)
//impl<T> !MallocSizeOf for Arc<T> { }
//impl<T> !MallocShallowSizeOf for Arc<T> { }
impl<T> MallocUnconditionalShallowSizeOf for servo_arc::Arc<T> {
fn unconditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
unsafe { ops.malloc_size_of(self.heap_ptr()) }
}
}
impl<T: MallocSizeOf> MallocUnconditionalSizeOf for servo_arc::Arc<T> {
fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
self.unconditional_shallow_size_of(ops) + (**self).size_of(ops)
}
}
impl<T> MallocConditionalShallowSizeOf for servo_arc::Arc<T> {
fn conditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
if ops.have_seen_ptr(self.heap_ptr()) {
0
} else {
self.unconditional_shallow_size_of(ops)
}
}
}
impl<T: MallocSizeOf> MallocConditionalSizeOf for servo_arc::Arc<T> {
fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
if ops.have_seen_ptr(self.heap_ptr()) {
0
} else {
self.unconditional_size_of(ops)
}
}
}
/// If a mutex is stored directly as a member of a data type that is being measured,
/// it is the unique owner of its contents and deserves to be measured.
///
/// If a mutex is stored inside of an Arc value as a member of a data type that is being measured,
/// the Arc will not be automatically measured so there is no risk of overcounting the mutex's
/// contents.
impl<T: MallocSizeOf> MallocSizeOf for std::sync::Mutex<T> {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
(*self.lock().unwrap()).size_of(ops)
}
}
impl MallocSizeOf for smallbitvec::SmallBitVec {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
if let Some(ptr) = self.heap_ptr() {
unsafe { ops.malloc_size_of(ptr) }
} else {
0
}
}
}
impl<T: MallocSizeOf, Unit> MallocSizeOf for euclid::Length<T, Unit> {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
self.0.size_of(ops)
}
}
impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Scale<T, Src, Dst> {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
self.0.size_of(ops)
}
}
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Point2D<T, U> {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
self.x.size_of(ops) + self.y.size_of(ops)
}
}
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Rect<T, U> {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
self.origin.size_of(ops) + self.size.size_of(ops)
}
}
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::SideOffsets2D<T, U> {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
self.top.size_of(ops)
+ self.right.size_of(ops)
+ self.bottom.size_of(ops)
+ self.left.size_of(ops)
}
}
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Size2D<T, U> {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
self.width.size_of(ops) + self.height.size_of(ops)
}
}
impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Transform2D<T, Src, Dst> {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
self.m11.size_of(ops)
+ self.m12.size_of(ops)
+ self.m21.size_of(ops)
+ self.m22.size_of(ops)
+ self.m31.size_of(ops)
+ self.m32.size_of(ops)
}
}
impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Transform3D<T, Src, Dst> {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
self.m11.size_of(ops)
+ self.m12.size_of(ops)
+ self.m13.size_of(ops)
+ self.m14.size_of(ops)
+ self.m21.size_of(ops)
+ self.m22.size_of(ops)
+ self.m23.size_of(ops)
+ self.m24.size_of(ops)
+ self.m31.size_of(ops)
+ self.m32.size_of(ops)
+ self.m33.size_of(ops)
+ self.m34.size_of(ops)
+ self.m41.size_of(ops)
+ self.m42.size_of(ops)
+ self.m43.size_of(ops)
+ self.m44.size_of(ops)
}
}
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Vector2D<T, U> {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
self.x.size_of(ops) + self.y.size_of(ops)
}
}
impl MallocSizeOf for selectors::parser::AncestorHashes {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
let selectors::parser::AncestorHashes { ref packed_hashes } = *self;
packed_hashes.size_of(ops)
}
}
impl<Impl: selectors::parser::SelectorImpl> MallocUnconditionalSizeOf
for selectors::parser::Selector<Impl>
where
Impl::NonTSPseudoClass: MallocSizeOf,
Impl::PseudoElement: MallocSizeOf,
{
fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
let mut n = 0;
// It's OK to measure this ThinArc directly because it's the
// "primary" reference. (The secondary references are on the
// Stylist.)
n += unsafe { ops.malloc_size_of(self.thin_arc_heap_ptr()) };
for component in self.iter_raw_match_order() {
n += component.size_of(ops);
}
n
}
}
impl<Impl: selectors::parser::SelectorImpl> MallocUnconditionalSizeOf
for selectors::parser::SelectorList<Impl>
where
Impl::NonTSPseudoClass: MallocSizeOf,
Impl::PseudoElement: MallocSizeOf,
{
fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
let mut n = 0;
// It's OK to measure this ThinArc directly because it's the "primary" reference. (The
// secondary references are on the Stylist.)
n += unsafe { ops.malloc_size_of(self.thin_arc_heap_ptr()) };
if self.len() > 1 {
for selector in self.slice().iter() {
n += selector.size_of(ops);
}
}
n
}
}
impl<Impl: selectors::parser::SelectorImpl> MallocUnconditionalSizeOf
for selectors::parser::Component<Impl>
where
Impl::NonTSPseudoClass: MallocSizeOf,
Impl::PseudoElement: MallocSizeOf,
{
fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
use selectors::parser::Component;
match self {
Component::AttributeOther(ref attr_selector) => attr_selector.size_of(ops),
Component::Negation(ref components) => components.unconditional_size_of(ops),
Component::NonTSPseudoClass(ref pseudo) => (*pseudo).size_of(ops),
Component::Slotted(ref selector) | Component::Host(Some(ref selector)) => {
selector.unconditional_size_of(ops)
},
Component::Is(ref list) | Component::Where(ref list) => list.unconditional_size_of(ops),
Component::Has(ref relative_selectors) => relative_selectors.size_of(ops),
Component::NthOf(ref nth_of_data) => nth_of_data.size_of(ops),
Component::PseudoElement(ref pseudo) => (*pseudo).size_of(ops),
Component::Combinator(..)
| Component::ExplicitAnyNamespace
| Component::ExplicitNoNamespace
| Component::DefaultNamespace(..)
| Component::Namespace(..)
| Component::ExplicitUniversalType
| Component::LocalName(..)
| Component::ID(..)
| Component::Part(..)
| Component::Class(..)
| Component::AttributeInNoNamespaceExists { .. }
| Component::AttributeInNoNamespace { .. }
| Component::Root
| Component::Empty
| Component::Scope
| Component::ImplicitScope
| Component::ParentSelector
| Component::Nth(..)
| Component::Host(None)
| Component::RelativeSelectorAnchor
| Component::Invalid(..) => 0,
}
}
}
impl<Impl: selectors::parser::SelectorImpl> MallocSizeOf
for selectors::attr::AttrSelectorWithOptionalNamespace<Impl>
{
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
0
}
}
impl MallocSizeOf for selectors::parser::AnPlusB {
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
0
}
}
impl MallocSizeOf for Void {
#[inline]
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
void::unreachable(*self)
}
}
#[cfg(feature = "servo")]
impl<Static: string_cache::StaticAtomSet> MallocSizeOf for string_cache::Atom<Static> {
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
0
}
}
/// For use on types where size_of() returns 0.
#[macro_export]
macro_rules! malloc_size_of_is_0(
($($ty:ty),+) => (
$(
impl $crate::MallocSizeOf for $ty {
#[inline(always)]
fn size_of(&self, _: &mut $crate::MallocSizeOfOps) -> usize {
0
}
}
)+
);
($($ty:ident<$($gen:ident),+>),+) => (
$(
impl<$($gen: $crate::MallocSizeOf),+> $crate::MallocSizeOf for $ty<$($gen),+> {
#[inline(always)]
fn size_of(&self, _: &mut $crate::MallocSizeOfOps) -> usize {
0
}
}
)+
);
);
malloc_size_of_is_0!(bool, char, str);
malloc_size_of_is_0!(u8, u16, u32, u64, u128, usize);
malloc_size_of_is_0!(i8, i16, i32, i64, i128, isize);
malloc_size_of_is_0!(f32, f64);
malloc_size_of_is_0!(std::sync::atomic::AtomicBool);
malloc_size_of_is_0!(std::sync::atomic::AtomicIsize);
malloc_size_of_is_0!(std::sync::atomic::AtomicU32);
malloc_size_of_is_0!(std::sync::atomic::AtomicUsize);
malloc_size_of_is_0!(std::num::NonZeroUsize);
malloc_size_of_is_0!(std::num::NonZeroU64);
malloc_size_of_is_0!(Range<u8>, Range<u16>, Range<u32>, Range<u64>, Range<usize>);
malloc_size_of_is_0!(Range<i8>, Range<i16>, Range<i32>, Range<i64>, Range<isize>);
malloc_size_of_is_0!(Range<f32>, Range<f64>);
malloc_size_of_is_0!(app_units::Au);
malloc_size_of_is_0!(
cssparser::TokenSerializationType,
cssparser::SourceLocation,
cssparser::SourcePosition,
cssparser::UnicodeRange
);
malloc_size_of_is_0!(selectors::OpaqueElement);
/// Measurable that defers to inner value and used to verify MallocSizeOf implementation in a
/// struct.
#[derive(Clone)]
pub struct Measurable<T: MallocSizeOf>(pub T);
impl<T: MallocSizeOf> Deref for Measurable<T> {
type Target = T;
fn deref(&self) -> &T {
&self.0
}
}
impl<T: MallocSizeOf> DerefMut for Measurable<T> {
fn deref_mut(&mut self) -> &mut T {
&mut self.0
}
}
================================================
FILE: rustfmt.toml
================================================
match_block_trailing_comma = true
reorder_imports = true
================================================
FILE: selectors/CHANGES.md
================================================
- `parser.rs` no longer wraps values in quotes (`"..."`) but expects their `to_css` impl to already wrap it ([Gecko Bug 1854809](https://bugzilla.mozilla.org/show_bug.cgi?id=1854809))
================================================
FILE: selectors/Cargo.toml
================================================
[package]
name = "selectors"
version = "0.38.0"
authors = ["The Servo Project Developers"]
documentation = "https://docs.rs/selectors/"
description = "CSS Selectors matching for Rust"
repository = "https://github.com/servo/stylo"
readme = "README.md"
keywords = ["css", "selectors"]
license = "MPL-2.0"
edition = "2021"
build = "build.rs"
[lib]
name = "selectors"
path = "lib.rs"
[features]
bench = []
to_shmem = ["dep:to_shmem", "dep:to_shmem_derive"]
[dependencies]
bitflags = "2"
cssparser = "0.37"
derive_more = { version = "2", features = ["add", "add_assign"] }
rustc-hash = "2.1.1"
log = "0.4"
phf = "0.13"
precomputed-hash = "0.1"
servo_arc = { workspace = true }
smallvec = "1.0"
to_shmem = { workspace = true, optional = true }
to_shmem_derive = { workspace = true, optional = true }
new_debug_unreachable = "1"
[build-dependencies]
phf_codegen = "0.13"
================================================
FILE: selectors/README.md
================================================
rust-selectors
==============
* [](https://github.com/servo/stylo/actions)
* [Documentation](https://docs.rs/selectors)
* [crates.io](https://crates.io/crates/selectors)
CSS Selectors library for Rust.
Includes parsing and serilization of selectors,
as well as matching against a generic tree of elements.
Pseudo-elements and most pseudo-classes are generic as well.
**Warning:** breaking changes are made to this library fairly frequently
(13 times in 2016, for example).
However you can use this crate without updating it that often,
old versions stay available on crates.io and Cargo will only automatically update
to versions that are numbered as compatible.
To see how to use this library with your own tree representation,
see [Kuchiki’s `src/select.rs`](https://github.com/kuchiki-rs/kuchiki/blob/master/src/select.rs).
(Note however that Kuchiki is not always up to date with the latest rust-selectors version,
so that code may need to be tweaked.)
If you don’t already have a tree data structure,
consider using [Kuchiki](https://github.com/kuchiki-rs/kuchiki) itself.
================================================
FILE: selectors/attr.rs
================================================
/* 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 crate::parser::SelectorImpl;
use cssparser::ToCss;
use std::fmt;
#[cfg(feature = "to_shmem")]
use to_shmem_derive::ToShmem;
#[derive(Clone, Eq, PartialEq)]
#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
#[cfg_attr(feature = "to_shmem", shmem(no_bounds))]
pub struct AttrSelectorWithOptionalNamespace<Impl: SelectorImpl> {
#[cfg_attr(feature = "to_shmem", shmem(field_bound))]
pub namespace: Option<NamespaceConstraint<(Impl::NamespacePrefix, Impl::NamespaceUrl)>>,
#[cfg_attr(feature = "to_shmem", shmem(field_bound))]
pub local_name: Impl::LocalName,
pub local_name_lower: Impl::LocalName,
#[cfg_attr(feature = "to_shmem", shmem(field_bound))]
pub operation: ParsedAttrSelectorOperation<Impl::AttrValue>,
}
impl<Impl: SelectorImpl> AttrSelectorWithOptionalNamespace<Impl> {
pub fn namespace(&self) -> Option<NamespaceConstraint<&Impl::NamespaceUrl>> {
self.namespace.as_ref().map(|ns| match ns {
NamespaceConstraint::Any => NamespaceConstraint::Any,
NamespaceConstraint::Specific((_, ref url)) => NamespaceConstraint::Specific(url),
})
}
}
#[derive(Clone, Eq, PartialEq)]
#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
pub enum NamespaceConstraint<NamespaceUrl> {
Any,
/// Empty string for no namespace
Specific(NamespaceUrl),
}
#[derive(Clone, Eq, PartialEq)]
#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
pub enum ParsedAttrSelectorOperation<AttrValue> {
Exists,
WithValue {
operator: AttrSelectorOperator,
case_sensitivity: ParsedCaseSensitivity,
value: AttrValue,
},
}
#[derive(Clone, Eq, PartialEq)]
pub enum AttrSelectorOperation<AttrValue> {
Exists,
WithValue {
operator: AttrSelectorOperator,
case_sensitivity: CaseSensitivity,
value: AttrValue,
},
}
impl<AttrValue> AttrSelectorOperation<AttrValue> {
pub fn eval_str(&self, element_attr_value: &str) -> bool
where
AttrValue: AsRef<str>,
{
match *self {
AttrSelectorOperation::Exists => true,
AttrSelectorOperation::WithValue {
operator,
case_sensitivity,
ref value,
} => operator.eval_str(element_attr_value, value.as_ref(), case_sensitivity),
}
}
}
#[derive(Clone, Copy, Eq, PartialEq)]
#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
pub enum AttrSelectorOperator {
Equal,
Includes,
DashMatch,
Prefix,
Substring,
Suffix,
}
impl ToCss for AttrSelectorOperator {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where
W: fmt::Write,
{
// https://drafts.csswg.org/cssom/#serializing-selectors
// See "attribute selector".
dest.write_str(match *self {
AttrSelectorOperator::Equal => "=",
AttrSelectorOperator::Includes => "~=",
AttrSelectorOperator::DashMatch => "|=",
AttrSelectorOperator::Prefix => "^=",
AttrSelectorOperator::Substring => "*=",
AttrSelectorOperator::Suffix => "$=",
})
}
}
impl AttrSelectorOperator {
pub fn eval_str(
self,
element_attr_value: &str,
attr_selector_value: &str,
case_sensitivity: CaseSensitivity,
) -> bool {
let e = element_attr_value.as_bytes();
let s = attr_selector_value.as_bytes();
let case = case_sensitivity;
match self {
AttrSelectorOperator::Equal => case.eq(e, s),
AttrSelectorOperator::Prefix => {
!s.is_empty() && e.len() >= s.len() && case.eq(&e[..s.len()], s)
},
AttrSelectorOperator::Suffix => {
!s.is_empty() && e.len() >= s.len() && case.eq(&e[(e.len() - s.len())..], s)
},
AttrSelectorOperator::Substring => {
!s.is_empty() && case.contains(element_attr_value, attr_selector_value)
},
AttrSelectorOperator::Includes => {
!s.is_empty()
&& element_attr_value
.split(SELECTOR_WHITESPACE)
.any(|part| case.eq(part.as_bytes(), s))
},
AttrSelectorOperator::DashMatch => {
case.eq(e, s) || (e.get(s.len()) == Some(&b'-') && case.eq(&e[..s.len()], s))
},
}
}
}
/// The definition of whitespace per CSS Selectors Level 3 § 4.
pub static SELECTOR_WHITESPACE: &[char] = &[' ', '\t', '\n', '\r', '\x0C'];
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
pub enum ParsedCaseSensitivity {
/// 's' was specified.
ExplicitCaseSensitive,
/// 'i' was specified.
AsciiCaseInsensitive,
/// No flags were specified and HTML says this is a case-sensitive attribute.
CaseSensitive,
/// No flags were specified and HTML says this is a case-insensitive attribute.
AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CaseSensitivity {
CaseSensitive,
AsciiCaseInsensitive,
}
impl CaseSensitivity {
pub fn eq(self, a: &[u8], b: &[u8]) -> bool {
match self {
CaseSensitivity::CaseSensitive => a == b,
CaseSensitivity::AsciiCaseInsensitive => a.eq_ignore_ascii_case(b),
}
}
pub fn contains(self, haystack: &str, needle: &str) -> bool {
match self {
CaseSensitivity::CaseSensitive => haystack.contains(needle),
CaseSensitivity::AsciiCaseInsensitive => {
if let Some((&n_first_byte, n_rest)) = needle.as_bytes().split_first() {
haystack.bytes().enumerate().any(|(i, byte)| {
if !byte.eq_ignore_ascii_case(&n_first_byte) {
return false;
}
let after_this_byte = &haystack.as_bytes()[i + 1..];
match after_this_byte.get(..n_rest.len()) {
None => false,
Some(haystack_slice) => haystack_slice.eq_ignore_ascii_case(n_rest),
}
})
} else {
// any_str.contains("") == true,
// though these cases should be handled with *NeverMatches and never go here.
true
}
},
}
}
}
================================================
FILE: selectors/bloom.rs
================================================
/* 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/. */
//! Counting and non-counting Bloom filters tuned for use as ancestor filters
//! for selector matching.
use std::fmt::{self, Debug};
// The top 8 bits of the 32-bit hash value are not used by the bloom filter.
// Consumers may rely on this to pack hashes more efficiently.
pub const BLOOM_HASH_MASK: u32 = 0x00ffffff;
const KEY_SIZE: usize = 12;
const ARRAY_SIZE: usize = 1 << KEY_SIZE;
const KEY_MASK: u32 = (1 << KEY_SIZE) - 1;
/// A counting Bloom filter with 8-bit counters.
pub type BloomFilter = CountingBloomFilter<BloomStorageU8>;
/// A counting Bloom filter with parameterized storage to handle
/// counters of different sizes. For now we assume that having two hash
/// functions is enough, but we may revisit that decision later.
///
/// The filter uses an array with 2**KeySize entries.
///
/// Assuming a well-distributed hash function, a Bloom filter with
/// array size M containing N elements and
/// using k hash function has expected false positive rate exactly
///
/// $ (1 - (1 - 1/M)^{kN})^k $
///
/// because each array slot has a
///
/// $ (1 - 1/M)^{kN} $
///
/// chance of being 0, and the expected false positive rate is the
/// probability that all of the k hash functions will hit a nonzero
/// slot.
///
/// For reasonable assumptions (M large, kN large, which should both
/// hold if we're worried about false positives) about M and kN this
/// becomes approximately
///
/// $$ (1 - \exp(-kN/M))^k $$
///
/// For our special case of k == 2, that's $(1 - \exp(-2N/M))^2$,
/// or in other words
///
/// $$ N/M = -0.5 * \ln(1 - \sqrt(r)) $$
///
/// where r is the false positive rate. This can be used to compute
/// the desired KeySize for a given load N and false positive rate r.
///
/// If N/M is assumed small, then the false positive rate can
/// further be approximated as 4*N^2/M^2. So increasing KeySize by
/// 1, which doubles M, reduces the false positive rate by about a
/// factor of 4, and a false positive rate of 1% corresponds to
/// about M/N == 20.
///
/// What this means in practice is that for a few hundred keys using a
/// KeySize of 12 gives false positive rates on the order of 0.25-4%.
///
/// Similarly, using a KeySize of 10 would lead to a 4% false
/// positive rate for N == 100 and to quite bad false positive
/// rates for larger N.
#[derive(Clone, Default)]
pub struct CountingBloomFilter<S>
where
S: BloomStorage,
{
storage: S,
}
impl<S> CountingBloomFilter<S>
where
S: BloomStorage,
{
/// Creates a new bloom filter.
#[inline]
pub fn new() -> Self {
Default::default()
}
#[inline]
pub fn clear(&mut self) {
self.storage = Default::default();
}
// Slow linear accessor to make sure the bloom filter is zeroed. This should
// never be used in release builds.
#[cfg(debug_assertions)]
pub fn is_zeroed(&self) -> bool {
self.storage.is_zeroed()
}
#[cfg(not(debug_assertions))]
pub fn is_zeroed(&self) -> bool {
unreachable!()
}
/// Inserts an item with a particular hash into the bloom filter.
#[inline]
pub fn insert_hash(&mut self, hash: u32) {
self.storage.adjust_first_slot(hash, true);
self.storage.adjust_second_slot(hash, true);
}
/// Removes an item with a particular hash from the bloom filter.
#[inline]
pub fn remove_hash(&mut self, hash: u32) {
self.storage.adjust_first_slot(hash, false);
self.storage.adjust_second_slot(hash, false);
}
/// Check whether the filter might contain an item with the given hash.
/// This can sometimes return true even if the item is not in the filter,
/// but will never return false for items that are actually in the filter.
#[inline]
pub fn might_contain_hash(&self, hash: u32) -> bool {
!self.storage.first_slot_is_empty(hash) && !self.storage.second_slot_is_empty(hash)
}
}
impl<S> Debug for CountingBloomFilter<S>
where
S: BloomStorage,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut slots_used = 0;
for i in 0..ARRAY_SIZE {
if !self.storage.slot_is_empty(i) {
slots_used += 1;
}
}
write!(f, "BloomFilter({}/{})", slots_used, ARRAY_SIZE)
}
}
pub trait BloomStorage: Clone + Default {
fn slot_is_empty(&self, index: usize) -> bool;
fn adjust_slot(&mut self, index: usize, increment: bool);
fn is_zeroed(&self) -> bool;
#[inline]
fn first_slot_is_empty(&self, hash: u32) -> bool {
self.slot_is_empty(Self::first_slot_index(hash))
}
#[inline]
fn second_slot_is_empty(&self, hash: u32) -> bool {
self.slot_is_empty(Self::second_slot_index(hash))
}
#[inline]
fn adjust_first_slot(&mut self, hash: u32, increment: bool) {
self.adjust_slot(Self::first_slot_index(hash), increment)
}
#[inline]
fn adjust_second_slot(&mut self, hash: u32, increment: bool) {
self.adjust_slot(Self::second_slot_index(hash), increment)
}
#[inline]
fn first_slot_index(hash: u32) -> usize {
hash1(hash) as usize
}
#[inline]
fn second_slot_index(hash: u32) -> usize {
hash2(hash) as usize
}
}
/// Storage class for a CountingBloomFilter that has 8-bit counters.
pub struct BloomStorageU8 {
counters: [u8; ARRAY_SIZE],
}
impl BloomStorage for BloomStorageU8 {
#[inline]
fn adjust_slot(&mut self, index: usize, increment: bool) {
let slot = &mut self.counters[index];
if *slot != 0xff {
// full
if increment {
*slot += 1;
} else {
*slot -= 1;
}
}
}
#[inline]
fn slot_is_empty(&self, index: usize) -> bool {
self.counters[index] == 0
}
#[inline]
fn is_zeroed(&self) -> bool {
self.counters.iter().all(|x| *x == 0)
}
}
impl Default for BloomStorageU8 {
fn default() -> Self {
BloomStorageU8 {
counters: [0; ARRAY_SIZE],
}
}
}
impl Clone for BloomStorageU8 {
fn clone(&self) -> Self {
BloomStorageU8 {
counters: self.counters,
}
}
}
/// Storage class for a CountingBloomFilter that has 1-bit counters.
pub struct BloomStorageBool {
counters: [u8; ARRAY_SIZE / 8],
}
impl BloomStorage for BloomStorageBool {
#[inline]
fn adjust_slot(&mut self, index: usize, increment: bool) {
let bit = 1 << (index % 8);
let byte = &mut self.counters[index / 8];
// Since we have only one bit for storage, decrementing it
// should never do anything. Assert against an accidental
// decrementing of a bit that was never set.
assert!(
increment || (*byte & bit) != 0,
"should not decrement if slot is already false"
);
if increment {
*byte |= bit;
}
}
#[inline]
fn slot_is_empty(&self, index: usize) -> bool {
let bit = 1 << (index % 8);
(self.counters[index / 8] & bit) == 0
}
#[inline]
fn is_zeroed(&self) -> bool {
self.counters.iter().all(|x| *x == 0)
}
}
impl Default for BloomStorageBool {
fn default() -> Self {
BloomStorageBool {
counters: [0; ARRAY_SIZE / 8],
}
}
}
impl Clone for BloomStorageBool {
fn clone(&self) -> Self {
BloomStorageBool {
counters: self.counters,
}
}
}
#[inline]
fn hash1(hash: u32) -> u32 {
hash & KEY_MASK
}
#[inline]
fn hash2(hash: u32) -> u32 {
(hash >> KEY_SIZE) & KEY_MASK
}
#[test]
fn create_and_insert_some_stuff() {
use rustc_hash::FxHasher;
use std::hash::{Hash, Hasher};
use std::mem::transmute;
fn hash_as_str(i: usize) -> u32 {
let mut hasher = FxHasher::default();
let s = i.to_string();
s.hash(&mut hasher);
let hash: u64 = hasher.finish();
(hash >> 32) as u32 ^ (hash as u32)
}
let mut bf = BloomFilter::new();
// Statically assert that ARRAY_SIZE is a multiple of 8, which
// BloomStorageBool relies on.
unsafe {
transmute::<[u8; ARRAY_SIZE % 8], [u8; 0]>([]);
}
for i in 0_usize..1000 {
bf.insert_hash(hash_as_str(i));
}
for i in 0_usize..1000 {
assert!(bf.might_contain_hash(hash_as_str(i)));
}
let false_positives = (1001_usize..2000)
.filter(|i| bf.might_contain_hash(hash_as_str(*i)))
.count();
assert!(false_positives < 190, "{} is not < 190", false_positives); // 19%.
for i in 0_usize..100 {
bf.remove_hash(hash_as_str(i));
}
for i in 100_usize..1000 {
assert!(bf.might_contain_hash(hash_as_str(i)));
}
let false_positives = (0_usize..100)
.filter(|i| bf.might_contain_hash(hash_as_str(*i)))
.count();
assert!(false_positives < 20, "{} is not < 20", false_positives); // 20%.
bf.clear();
for i in 0_usize..2000 {
assert!(!bf.might_contain_hash(hash_as_str(i)));
}
}
#[cfg(feature = "bench")]
#[cfg(test)]
mod bench {
extern crate test;
use super::BloomFilter;
#[derive(Default)]
struct HashGenerator(u32);
impl HashGenerator {
fn next(&mut self) -> u32 {
// Each hash is split into two twelve-bit segments, which are used
// as an index into an array. We increment each by 64 so that we
// hit the next cache line, and then another 1 so that our wrapping
// behavior leads us to different entries each time.
//
// Trying to simulate cold caches is rather difficult with the cargo
// benchmarking setup, so it may all be moot depending on the number
// of iterations that end up being run. But we might as well.
self.0 += (65) + (65 << super::KEY_SIZE);
self.0
}
}
#[bench]
fn create_insert_1000_remove_100_lookup_100(b: &mut test::Bencher) {
b.iter(|| {
let mut gen1 = HashGenerator::default();
let mut gen2 = HashGenerator::default();
let mut bf = BloomFilter::new();
for _ in 0_usize..1000 {
bf.insert_hash(gen1.next());
}
for _ in 0_usize..100 {
bf.remove_hash(gen2.next());
}
for _ in 100_usize..200 {
test::black_box(bf.might_contain_hash(gen2.next()));
}
});
}
#[bench]
fn might_contain_10(b: &mut test::Bencher) {
let bf = BloomFilter::new();
let mut gen = HashGenerator::default();
b.iter(|| {
for _ in 0..10 {
test::black_box(bf.might_contain_hash(gen.next()));
}
});
}
#[bench]
fn clear(b: &mut test::Bencher) {
let mut bf = Box::new(BloomFilter::new());
b.iter(|| test::black_box(&mut bf).clear());
}
#[bench]
fn insert_10(b: &mut test::Bencher) {
let mut bf = BloomFilter::new();
let mut gen = HashGenerator::default();
b.iter(|| {
for _ in 0..10 {
test::black_box(bf.insert_hash(gen.next()));
}
});
}
#[bench]
fn remove_10(b: &mut test::Bencher) {
let mut bf = BloomFilter::new();
let mut gen = HashGenerator::default();
// Note: this will underflow, and that's ok.
b.iter(|| {
for _ in 0..10 {
bf.remove_hash(gen.next())
}
});
}
}
================================================
FILE: selectors/build.rs
================================================
/* 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/. */
extern crate phf_codegen;
use std::env;
use std::fs::File;
use std::io::{BufWriter, Write};
use std::path::Path;
fn main() {
let path = Path::new(&env::var_os("OUT_DIR").unwrap())
.join("ascii_case_insensitive_html_attributes.rs");
let mut file = BufWriter::new(File::create(&path).unwrap());
let mut set = phf_codegen::Set::new();
for name in ASCII_CASE_INSENSITIVE_HTML_ATTRIBUTES.split_whitespace() {
set.entry(name);
}
write!(
&mut file,
"{{ static SET: ::phf::Set<&'static str> = {}; &SET }}",
set.build(),
)
.unwrap();
}
/// <https://html.spec.whatwg.org/multipage/#selectors>
static ASCII_CASE_INSENSITIVE_HTML_ATTRIBUTES: &str = r#"
accept
accept-charset
align
alink
axis
bgcolor
charset
checked
clear
codetype
color
compact
declare
defer
dir
direction
disabled
enctype
face
frame
hreflang
http-equiv
lang
language
link
media
method
multiple
nohref
noresize
noshade
nowrap
readonly
rel
rev
rules
scope
scrolling
selected
shape
target
text
type
valign
valuetype
vlink
"#;
================================================
FILE: selectors/builder.rs
================================================
/* 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/. */
//! Helper module to build up a selector safely and efficiently.
//!
//! Our selector representation is designed to optimize matching, and has
//! several requirements:
//! * All simple selectors and combinators are stored inline in the same buffer as Component
//! instances.
//! * We store the top-level compound selectors from right to left, i.e. in matching order.
//! * We store the simple selectors for each combinator from left to right, so that we match the
//! cheaper simple selectors first.
//!
//! For example, the selector:
//!
//! .bar:hover > .baz:nth-child(2) + .qux
//!
//! Gets stored as:
//!
//! [.qux, + , .baz, :nth-child(2), > , .bar, :hover]
//!
//! Meeting all these constraints without extra memmove traffic during parsing is non-trivial. This
//! module encapsulates those details and presents an easy-to-use API for the parser.
use crate::parser::{
Combinator, Component, ParseRelative, RelativeSelector, Selector, SelectorData, SelectorImpl,
};
use crate::sink::Push;
use bitflags::bitflags;
use derive_more::{Add, AddAssign};
use servo_arc::Arc;
use smallvec::SmallVec;
use std::cmp;
use std::slice;
#[cfg(feature = "to_shmem")]
use to_shmem_derive::ToShmem;
/// Top-level SelectorBuilder struct. This should be stack-allocated by the consumer and never
/// moved (because it contains a lot of inline data that would be slow to memmove).
///
/// After instantiation, callers may call the push_simple_selector() and push_combinator() methods
/// to append selector data as it is encountered (from left to right). Once the process is
/// complete, callers should invoke build(), which transforms the contents of the SelectorBuilder
/// into a heap- allocated Selector and leaves the builder in a drained state.
#[derive(Debug)]
pub struct SelectorBuilder<Impl: SelectorImpl> {
/// The entire sequence of components. We make this large because the result of parsing a
/// selector is fed into a new Arc-ed allocation, so any spilled vec would be a wasted
/// allocation. Also, Components are large enough that we don't have much cache locality
/// benefit from reserving stack space for fewer of them.
components: SmallVec<[Component<Impl>; 32]>,
last_compound_start: Option<usize>,
}
impl<Impl: SelectorImpl> Push<Component<Impl>> for SelectorBuilder<Impl> {
fn push(&mut self, value: Component<Impl>) {
self.push_simple_selector(value);
}
}
impl<Impl: SelectorImpl> SelectorBuilder<Impl> {
/// Pushes a simple selector onto the current compound selector.
#[inline(always)]
pub fn push_simple_selector(&mut self, ss: Component<Impl>) {
debug_assert!(!ss.is_combinator());
self.components.push(ss);
}
/// Completes the current compound selector and starts a new one, delimited by the given
/// combinator.
#[inline(always)]
pub fn push_combinator(&mut self, c: Combinator) {
self.reverse_last_compound();
self.components.push(Component::Combinator(c));
self.last_compound_start = Some(self.components.len());
}
fn reverse_last_compound(&mut self) {
let start = self.last_compound_start.unwrap_or(0);
self.components[start..].reverse();
}
/// Returns true if combinators have ever been pushed to this builder.
#[inline(always)]
pub fn has_combinators(&self) -> bool {
self.last_compound_start.is_some()
}
/// Consumes the builder, producing a Selector.
#[inline(always)]
pub fn build(&mut self, parse_relative: ParseRelative) -> SelectorData<Impl> {
// Compute the specificity and flags.
let sf = specificity_and_flags(
self.components.iter(),
/* for_nesting_parent = */ false,
);
self.build_with_specificity_and_flags(sf, parse_relative)
}
/// Builds with an explicit SpecificityAndFlags. This is separated from build() so that unit
/// tests can pass an explicit specificity.
#[inline(always)]
pub(crate) fn build_with_specificity_and_flags(
&mut self,
mut spec: SpecificityAndFlags,
parse_relative: ParseRelative,
) -> SelectorData<Impl> {
let implicit_addition = match parse_relative {
ParseRelative::ForNesting if !spec.flags.intersects(SelectorFlags::HAS_PARENT) => {
Some((Component::ParentSelector, SelectorFlags::HAS_PARENT))
},
ParseRelative::ForScope
if !spec
.flags
.intersects(SelectorFlags::HAS_SCOPE | SelectorFlags::HAS_PARENT) =>
{
Some((Component::ImplicitScope, SelectorFlags::HAS_SCOPE))
},
_ => None,
};
let implicit_selector_and_combinator;
let implicit_selector = if let Some((component, flag)) = implicit_addition {
spec.flags.insert(flag);
implicit_selector_and_combinator =
[Component::Combinator(Combinator::Descendant), component];
&implicit_selector_and_combinator[..]
} else {
&[]
};
// As an optimization, for a selector without combinators, we can just keep the order
// as-is.
if self.last_compound_start.is_none() {
return Arc::from_header_and_iter(
spec,
ExactChain(self.components.drain(..), implicit_selector.iter().cloned()),
);
}
self.reverse_last_compound();
Arc::from_header_and_iter(
spec,
ExactChain(
self.components.drain(..).rev(),
implicit_selector.iter().cloned(),
),
)
}
}
impl<Impl: SelectorImpl> Default for SelectorBuilder<Impl> {
#[inline(always)]
fn default() -> Self {
SelectorBuilder {
components: SmallVec::new(),
last_compound_start: None,
}
}
}
// This is effectively a Chain<>, but Chain isn't an ExactSizeIterator, see
// https://github.com/rust-lang/rust/issues/34433
struct ExactChain<A, B>(A, B);
impl<A, B, Item> ExactSizeIterator for ExactChain<A, B>
where
A: ExactSizeIterator<Item = Item>,
B: ExactSizeIterator<Item = Item>,
{
fn len(&self) -> usize {
self.0.len() + self.1.len()
}
}
impl<A, B, Item> Iterator for ExactChain<A, B>
where
A: ExactSizeIterator<Item = Item>,
B: ExactSizeIterator<Item = Item>,
{
type Item = Item;
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
self.0.next().or_else(|| self.1.next())
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len();
(len, Some(len))
}
}
/// Flags that indicate at which point of parsing a selector are we.
#[derive(Clone, Copy, Default, Eq, PartialEq)]
#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
pub(crate) struct SelectorFlags(u8);
bitflags! {
impl SelectorFlags: u8 {
const HAS_PSEUDO = 1 << 0;
const HAS_SLOTTED = 1 << 1;
const HAS_PART = 1 << 2;
const HAS_PARENT = 1 << 3;
const HAS_HOST = 1 << 4;
const HAS_SCOPE = 1 << 5;
}
}
impl core::fmt::Debug for SelectorFlags {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
if self.is_empty() {
write!(f, "{:#x}", Self::empty().bits())
} else {
bitflags::parser::to_writer(self, f)
}
}
}
impl SelectorFlags {
/// When you nest a pseudo-element with something like:
///
/// ::before { & { .. } }
///
/// It is not supposed to work, because :is(::before) is invalid. We can't propagate the
/// pseudo-flags from inner to outer selectors, to avoid breaking our invariants.
pub(crate) fn forbidden_for_nesting() -> Self {
Self::HAS_PSEUDO | Self::HAS_SLOTTED | Self::HAS_PART
}
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
pub struct SpecificityAndFlags {
/// There are two free bits here, since we use ten bits for each specificity
/// kind (id, class, element).
pub(crate) specificity: u32,
/// There's padding after this field due to the size of the flags.
pub(crate) flags: SelectorFlags,
}
const MAX_10BIT: u32 = (1u32 << 10) - 1;
#[derive(Add, AddAssign, Clone, Copy, Default, Eq, Ord, PartialEq, PartialOrd)]
pub(crate) struct Specificity {
id_selectors: u32,
class_like_selectors: u32,
element_selectors: u32,
}
impl Specificity {
// Return the specficity of a single class-like selector.
#[inline]
pub fn single_class_like() -> Self {
Specificity {
id_selectors: 0,
class_like_selectors: 1,
element_selectors: 0,
}
}
}
impl From<u32> for Specificity {
#[inline]
fn from(value: u32) -> Specificity {
assert!(value <= MAX_10BIT << 20 | MAX_10BIT << 10 | MAX_10BIT);
Specificity {
id_selectors: value >> 20,
class_like_selectors: (value >> 10) & MAX_10BIT,
element_selectors: value & MAX_10BIT,
}
}
}
impl From<Specificity> for u32 {
#[inline]
fn from(specificity: Specificity) -> u32 {
cmp::min(specificity.id_selectors, MAX_10BIT) << 20
| cmp::min(specificity.class_like_selectors, MAX_10BIT) << 10
| cmp::min(specificity.element_selectors, MAX_10BIT)
}
}
fn specificity_and_flags<Impl>(
iter: slice::Iter<Component<Impl>>,
for_nesting_parent: bool,
) -> SpecificityAndFlags
where
Impl: SelectorImpl,
{
fn component_specificity<Impl>(
simple_selector: &Component<Impl>,
specificity: &mut Specificity,
flags: &mut SelectorFlags,
for_nesting_parent: bool,
) where
Impl: SelectorImpl,
{
match *simple_selector {
Component::Combinator(..) => {},
Component::ParentSelector => flags.insert(SelectorFlags::HAS_PARENT),
Component::Part(..) => {
flags.insert(SelectorFlags::HAS_PART);
if !for_nesting_parent {
specificity.element_selectors += 1
}
},
Component::PseudoElement(ref pseudo) => {
use crate::parser::PseudoElement;
flags.insert(SelectorFlags::HAS_PSEUDO);
if !for_nesting_parent {
specificity.element_selectors += pseudo.specificity_count();
}
},
Component::LocalName(..) => specificity.element_selectors += 1,
Component::Slotted(ref selector) => {
flags.insert(SelectorFlags::HAS_SLOTTED);
if !for_nesting_parent {
specificity.element_selectors += 1;
// Note that due to the way ::slotted works we only compete with
// other ::slotted rules, so the above rule doesn't really
// matter, but we do it still for consistency with other
// pseudo-elements.
//
// See: https://github.com/w3c/csswg-drafts/issues/1915
*specificity += Specificity::from(selector.specificity());
}
flags.insert(selector.flags());
},
Component::Host(ref selector) => {
flags.insert(SelectorFlags::HAS_HOST);
specificity.class_like_selectors += 1;
if let Some(ref selector) = *selector {
// See: https://github.com/w3c/csswg-drafts/issues/1915
*specificity += Specificity::from(selector.specificity());
flags.insert(selector.flags());
}
},
Component::ID(..) => {
specificity.id_selectors += 1;
},
Component::Class(..)
| Component::AttributeInNoNamespace { .. }
| Component::AttributeInNoNamespaceExists { .. }
| Component::AttributeOther(..)
| Component::Root
| Component::Empty
| Component::Nth(..)
| Component::NonTSPseudoClass(..) => {
specificity.class_like_selectors += 1;
},
Component::Scope | Component::ImplicitScope => {
flags.insert(SelectorFlags::HAS_SCOPE);
if matches!(*simple_selector, Component::Scope) {
specificity.class_like_selectors += 1;
}
},
Component::NthOf(ref nth_of_data) => {
// https://drafts.csswg.org/selectors/#specificity-rules:
//
// The specificity of the :nth-last-child() pseudo-class,
// like the :nth-child() pseudo-class, combines the
// specificity of a regular pseudo-class with that of its
// selector argument S.
specificity.class_like_selectors += 1;
let sf = selector_list_specificity_and_flags(
nth_of_data.selectors().iter(),
for_nesting_parent,
);
*specificity += Specificity::from(sf.specificity);
flags.insert(sf.flags);
},
// https://drafts.csswg.org/selectors/#specificity-rules:
//
// The specificity of an :is(), :not(), or :has() pseudo-class
// is replaced by the specificity of the most specific complex
// selector in its selector list argument.
Component::Where(ref list)
| Component::Negation(ref list)
| Component::Is(ref list) => {
let sf = selector_list_specificity_and_flags(
list.slice().iter(),
/* nested = */ true,
);
if !matches!(*simple_selector, Component::Where(..)) {
*specificity += Specificity::from(sf.specificity);
}
flags.insert(sf.flags);
},
Component::Has(ref relative_selectors) => {
let sf = relative_selector_list_specificity_and_flags(
relative_selectors,
for_nesting_parent,
);
*specificity += Specificity::from(sf.specificity);
flags.insert(sf.flags);
},
Component::ExplicitUniversalType
| Component::ExplicitAnyNamespace
| Component::ExplicitNoNamespace
| Component::DefaultNamespace(..)
| Component::Namespace(..)
| Component::RelativeSelectorAnchor
| Component::Invalid(..) => {
// Does not affect specificity
},
}
}
let mut specificity = Default::default();
let mut flags = Default::default();
for simple_selector in iter {
component_specificity(
&simple_selector,
&mut specificity,
&mut flags,
for_nesting_parent,
);
}
SpecificityAndFlags {
specificity: specificity.into(),
flags,
}
}
/// Finds the maximum specificity of elements in the list and returns it.
pub(crate) fn selector_list_specificity_and_flags<'a, Impl: SelectorImpl>(
itr: impl Iterator<Item = &'a Selector<Impl>>,
for_nesting_parent: bool,
) -> SpecificityAndFlags {
let mut specificity = 0;
let mut flags = SelectorFlags::empty();
for selector in itr {
let selector_flags = selector.flags();
let selector_specificity = if for_nesting_parent
&& selector_flags.intersects(SelectorFlags::forbidden_for_nesting())
{
// In this case we need to re-compute the specificity.
specificity_and_flags(selector.iter_raw_match_order(), for_nesting_parent).specificity
} else {
selector.specificity()
};
specificity = std::cmp::max(specificity, selector_specificity);
flags.insert(selector.flags());
}
SpecificityAndFlags { specificity, flags }
}
pub(crate) fn relative_selector_list_specificity_and_flags<Impl: SelectorImpl>(
list: &[RelativeSelector<Impl>],
for_nesting_parent: bool,
) -> SpecificityAndFlags {
selector_list_specificity_and_flags(list.iter().map(|rel| &rel.selector), for_nesting_parent)
}
================================================
FILE: selectors/context.rs
================================================
/* 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 crate::attr::CaseSensitivity;
use crate::bloom::BloomFilter;
use crate::nth_index_cache::{NthIndexCache, NthIndexCacheInner};
use crate::parser::{Selector, SelectorImpl};
use crate::relative_selector::cache::RelativeSelectorCache;
use crate::relative_selector::filter::RelativeSelectorFilterMap;
use crate::tree::{Element, OpaqueElement};
/// What kind of selector matching mode we should use.
///
/// There are two modes of selector matching. The difference is only noticeable
/// in presence of pseudo-elements.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum MatchingMode {
/// Don't ignore any pseudo-element selectors.
Normal,
/// Ignores any stateless pseudo-element selectors in the rightmost sequence
/// of simple selectors.
///
/// This is useful, for example, to match against ::before when you aren't a
/// pseudo-element yourself.
///
/// For example, in presence of `::before:hover`, it would never match, but
/// `::before` would be ignored as in "matching".
///
/// It's required for all the selectors you match using this mode to have a
/// pseudo-element.
ForStatelessPseudoElement,
}
/// The mode to use when matching unvisited and visited links.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum VisitedHandlingMode {
/// All links are matched as if they are unvisted.
AllLinksUnvisited,
/// All links are matched as if they are visited and unvisited (both :link
/// and :visited match).
///
/// This is intended to be used from invalidation code, to be conservative
/// about whether we need to restyle a link.
AllLinksVisitedAndUnvisited,
/// A element's "relevant link" is the element being matched if it is a link
/// or the nearest ancestor link. The relevant link is matched as though it
/// is visited, and all other links are matched as if they are unvisited.
RelevantLinkVisited,
}
impl VisitedHandlingMode {
#[inline]
pub fn matches_visited(&self) -> bool {
matches!(
*self,
VisitedHandlingMode::RelevantLinkVisited
| VisitedHandlingMode::AllLinksVisitedAndUnvisited
)
}
#[inline]
pub fn matches_unvisited(&self) -> bool {
matches!(
*self,
VisitedHandlingMode::AllLinksUnvisited
| VisitedHandlingMode::AllLinksVisitedAndUnvisited
)
}
}
/// Whether we need to set selector invalidation flags on elements for this
/// match request.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum NeedsSelectorFlags {
No,
Yes,
}
/// Whether we're matching in the contect of invalidation.
#[derive(Clone, Copy, PartialEq)]
pub enum MatchingForInvalidation {
No,
Yes,
YesForComparison,
}
impl MatchingForInvalidation {
/// Are we matching for invalidation?
pub fn is_for_invalidation(&self) -> bool {
matches!(*self, Self::Yes | Self::YesForComparison)
}
}
/// Which quirks mode is this document in.
///
/// See: https://quirks.spec.whatwg.org/
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum QuirksMode {
/// Quirks mode.
Quirks,
/// Limited quirks mode.
LimitedQuirks,
/// No quirks mode.
NoQuirks,
}
impl QuirksMode {
#[inline]
pub fn classes_and_ids_case_sensitivity(self) -> CaseSensitivity {
match self {
QuirksMode::NoQuirks | QuirksMode::LimitedQuirks => CaseSensitivity::CaseSensitive,
QuirksMode::Quirks => CaseSensitivity::AsciiCaseInsensitive,
}
}
}
/// Set of caches (And cache-likes) that speed up expensive selector matches.
#[derive(Default)]
pub struct SelectorCaches {
/// A cache to speed up nth-index-like selectors.
pub nth_index: NthIndexCache,
/// A cache to speed up relative selector matches. See module documentation.
pub relative_selector: RelativeSelectorCache,
/// A map of bloom filters to fast-reject relative selector matches.
pub relative_selector_filter_map: RelativeSelectorFilterMap,
}
/// Data associated with the matching process for a element. This context is
/// used across many selectors for an element, so it's not appropriate for
/// transient data that applies to only a single selector.
pub struct MatchingContext<'a, Impl>
where
Impl: SelectorImpl,
{
/// Input with the matching mode we should use when matching selectors.
matching_mode: MatchingMode,
/// Input with the bloom filter used to fast-reject selectors.
pub bloom_filter: Option<&'a BloomFilter>,
/// The element which is going to match :scope pseudo-class. It can be
/// either one :scope element, or the scoping element.
///
/// Note that, although in theory there can be multiple :scope elements,
/// in current specs, at most one is specified, and when there is one,
/// scoping element is not relevant anymore, so we use a single field for
/// them.
///
/// When this is None, :scope will match the root element.
///
/// See https://drafts.csswg.org/selectors-4/#scope-pseudo
pub scope_element: Option<OpaqueElement>,
/// The current shadow host we're collecting :host rules for.
pub current_host: Option<OpaqueElement>,
/// Controls how matching for links is handled.
visited_handling: VisitedHandlingMode,
/// Whether we're currently matching a featureless element.
pub featureless: bool,
/// The current nesting level of selectors that we're matching.
nesting_level: usize,
/// Whether we're inside a negation or not.
in_negation: bool,
/// An optional hook function for checking whether a pseudo-element
/// should match when matching_mode is ForStatelessPseudoElement.
pub pseudo_element_matching_fn: Option<&'a dyn Fn(&Impl::PseudoElement) -> bool>,
/// Extra implementation-dependent matching data.
pub extra_data: Impl::ExtraMatchingData<'a>,
/// The current element we're anchoring on for evaluating the relative selector.
current_relative_selector_anchor: Option<OpaqueElement>,
quirks_mode: QuirksMode,
needs_selector_flags: NeedsSelectorFlags,
/// Whether we're matching in the context of invalidation.
matching_for_invalidation: MatchingForInvalidation,
/// Whether we're matching in the context of revalidation.
matching_for_revalidation: bool,
/// Caches to speed up expensive selector matches.
pub selector_caches: &'a mut SelectorCaches,
classes_and_ids_case_sensitivity: CaseSensitivity,
_impl: ::std::marker::PhantomData<Impl>,
}
impl<'a, Impl> MatchingContext<'a, Impl>
where
Impl: SelectorImpl,
{
/// Constructs a new `MatchingContext`.
pub fn new(
matching_mode: MatchingMode,
bloom_filter: Option<&'a BloomFilter>,
selector_caches: &'a mut SelectorCaches,
quirks_mode: QuirksMode,
needs_selector_flags: NeedsSelectorFlags,
matching_for_invalidation: MatchingForInvalidation,
) -> Self {
Self::new_internal(
matching_mode,
bloom_filter,
selector_caches,
VisitedHandlingMode::AllLinksUnvisited,
quirks_mode,
needs_selector_flags,
matching_for_invalidation,
false,
)
}
/// Constructs a new `MatchingContext` for revalidation.
pub fn new_for_revalidation(
bloom_filter: Option<&'a BloomFilter>,
selector_caches: &'a mut SelectorCaches,
quirks_mode: QuirksMode,
needs_selector_flags: NeedsSelectorFlags,
) -> Self {
Self::new_internal(
// NB: `MatchingMode` doesn't really matter, given we don't share style
// between pseudos.
MatchingMode::Normal,
bloom_filter,
selector_caches,
VisitedHandlingMode::AllLinksUnvisited,
quirks_mode,
needs_selector_flags,
MatchingForInvalidation::No,
true,
)
}
/// Constructs a new `MatchingContext` for use in visited matching.
pub fn new_for_visited(
matching_mode: MatchingMode,
bloom_filter: Option<&'a BloomFilter>,
selector_caches: &'a mut SelectorCaches,
visited_handling: VisitedHandlingMode,
quirks_mode: QuirksMode,
needs_selector_flags: NeedsSelectorFlags,
matching_for_invalidation: MatchingForInvalidation,
) -> Self {
Self::new_internal(
matching_mode,
bloom_filter,
selector_caches,
visited_handling,
quirks_mode,
needs_selector_flags,
matching_for_invalidation,
false,
)
}
fn new_internal(
matching_mode: MatchingMode,
bloom_filter: Option<&'a BloomFilter>,
selector_caches: &'a mut SelectorCaches,
visited_handling: VisitedHandlingMode,
quirks_mode: QuirksMode,
needs_selector_flags: NeedsSelectorFlags,
matching_for_invalidation: MatchingForInvalidation,
matching_for_revalidation: bool,
) -> Self {
Self {
matching_mode,
bloom_filter,
visited_handling,
quirks_mode,
classes_and_ids_case_sensitivity: quirks_mode.classes_and_ids_case_sensitivity(),
needs_selector_flags,
matching_for_invalidation,
matching_for_revalidation,
scope_element: None,
current_host: None,
featureless: false,
nesting_level: 0,
in_negation: false,
pseudo_element_matching_fn: None,
extra_data: Default::default(),
current_relative_selector_anchor: None,
selector_caches,
_impl: ::std::marker::PhantomData,
}
}
// Grab a reference to the appropriate cache.
#[inline]
pub fn nth_index_cache(
&mut self,
is_of_type: bool,
is_from_end: bool,
selectors: &[Selector<Impl>],
) -> &mut NthIndexCacheInner {
self.selector_caches
.nth_index
.get(is_of_type, is_from_end, selectors)
}
/// Whether we're matching a nested selector.
#[inline]
pub fn is_nested(&self) -> bool {
self.nesting_level != 0
}
/// Whether we're matching inside a :not(..) selector.
#[inline]
pub fn in_negation(&self) -> bool {
self.in_negation
}
/// The quirks mode of the document.
#[inline]
pub fn quirks_mode(&self) -> QuirksMode {
self.quirks_mode
}
/// The matching-mode for this selector-matching operation.
#[inline]
pub fn matching_mode(&self) -> MatchingMode {
self.matching_mode
}
/// Whether we need to set selector flags.
#[inline]
pub fn needs_selector_flags(&self) -> bool {
self.needs_selector_flags == NeedsSelectorFlags::Yes
}
/// Whether or not we're matching to invalidate.
#[inline]
pub fn matching_for_invalidation(&self) -> bool {
self.matching_for_invalidation.is_for_invalidation()
}
/// Whether or not we're matching to revalidate.
#[inline]
pub fn matching_for_revalidation(&self) -> bool {
self.matching_for_revalidation
}
/// Whether or not we're comparing for invalidation, if we are matching for invalidation.
#[inline]
pub fn matching_for_invalidation_comparison(&self) -> Option<bool> {
match self.matching_for_invalidation {
MatchingForInvalidation::No => None,
MatchingForInvalidation::Yes => Some(false),
MatchingForInvalidation::YesForComparison => Some(true),
}
}
/// Run the given matching function for before/after invalidation comparison.
#[inline]
pub fn for_invalidation_comparison<F, R>(&mut self, f: F) -> R
where
F: FnOnce(&mut Self) -> R,
{
debug_assert!(
self.matching_for_invalidation(),
"Not matching for invalidation?"
);
let prev = self.matching_for_invalidation;
self.matching_for_invalidation = MatchingForInvalidation::YesForComparison;
let result = f(self);
self.matching_for_invalidation = prev;
result
}
/// The case-sensitivity for class and ID selectors
#[inline]
pub fn classes_and_ids_case_sensitivity(&self) -> CaseSensitivity {
self.classes_and_ids_case_sensitivity
}
/// Runs F with a deeper nesting level.
#[inline]
pub fn nest<F, R>(&mut self, f: F) -> R
where
F: FnOnce(&mut Self) -> R,
{
self.nesting_level += 1;
let result = f(self);
self.nesting_level -= 1;
result
}
/// Runs F with a deeper nesting level, and marking ourselves in a negation,
/// for a :not(..) selector, for example.
#[inline]
pub fn nest_for_negation<F, R>(&mut self, f: F) -> R
where
F: FnOnce(&mut Self) -> R,
{
let old_in_negation = self.in_negation;
self.in_negation = !self.in_negation;
let result = self.nest(f);
self.in_negation = old_in_negation;
result
}
#[inline]
pub fn visited_handling(&self) -> VisitedHandlingMode {
self.visited_handling
}
/// Runs F with a different featureless element flag.
#[inline]
pub fn with_featureless<F, R>(&mut self, featureless: bool, f: F) -> R
where
F: FnOnce(&mut Self) -> R,
{
let orig = self.featureless;
self.featureless = featureless;
let result = f(self);
self.featureless = orig;
result
}
/// Returns whether the currently matching element is acting as a featureless element (e.g.,
/// because we've crossed a shadow boundary). This is used to implement the :host selector
/// rules properly.
#[inline]
pub fn featureless(&self) -> bool {
self.featureless
}
/// Runs F with a different VisitedHandlingMode.
#[inline]
pub fn with_visited_handling_mode<F, R>(
&mut self,
handling_mode: VisitedHandlingMode,
f: F,
) -> R
where
F: FnOnce(&mut Self) -> R,
{
let original_handling_mode = self.visited_handling;
self.visited_handling = handling_mode;
let result = f(self);
self.visited_handling = original_handling_mode;
result
}
/// Runs F with a given shadow host which is the root of the tree whose
/// rules we're matching.
#[inline]
pub fn with_shadow_host<F, E, R>(&mut self, host: Option<E>, f: F) -> R
where
E: Element,
F: FnOnce(&mut Self) -> R,
{
let original_host = self.current_host.take();
self.current_host = host.map(|h| h.opaque());
let result = f(self);
self.current_host = original_host;
result
}
/// Returns the current shadow host whose shadow root we're matching rules
/// against.
#[inline]
pub fn shadow_host(&self) -> Option<OpaqueElement> {
self.current_host
}
/// Runs F with a deeper nesting level, with the given element as the anchor,
/// for a :has(...) selector, for example.
#[inline]
pub fn nest_for_relative_selector<F, R>(&mut self, anchor: OpaqueElement, f: F) -> R
where
F: FnOnce(&mut Self) -> R,
{
debug_assert!(
self.current_relative_selector_anchor.is_none(),
"Nesting should've been rejected at parse time"
);
self.current_relative_selector_anchor = Some(anchor);
let result = self.nest(f);
self.current_relative_selector_anchor = None;
result
}
/// Runs F with a deeper nesting level, with the given element as the scope.
#[inline]
pub fn nest_for_scope<F, R>(&mut self, scope: Option<OpaqueElement>, f: F) -> R
where
F: FnOnce(&mut Self) -> R,
{
let original_scope_element = self.scope_element;
self.scope_element = scope;
let result = f(self);
self.scope_element = original_scope_element;
result
}
/// Runs F with a deeper nesting level, with the given element as the scope, for
/// matching `scope-start` and/or `scope-end` conditions.
#[inline]
pub fn nest_for_scope_condition<F, R>(&mut self, scope: Option<OpaqueElement>, f: F) -> R
where
F: FnOnce(&mut Self) -> R,
{
let original_matching_mode = self.matching_mode;
// We may as well be matching for a pseudo-element inside `@scope`, but
// the scope-defining selectors wouldn't be matching them.
self.matching_mode = MatchingMode::Normal;
let result = self.nest_for_scope(scope, f);
self.matching_mode = original_matching_mode;
result
}
/// Returns the current anchor element to evaluate the relative selector against.
#[inline]
pub fn relative_selector_anchor(&self) -> Option<OpaqueElement> {
self.current_relative_selector_anchor
}
}
================================================
FILE: selectors/kleene_value.rs
================================================
/* 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/. */
//! Kleen logic: https://en.wikipedia.org/wiki/Three-valued_logic#Kleene_and_Priest_logics
/// A "trilean" value based on Kleen logic.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum KleeneValue {
/// False
False = 0,
/// True
True = 1,
/// Either true or false, but we’re not sure which yet.
Unknown,
}
impl From<bool> for KleeneValue {
fn from(b: bool) -> Self {
if b {
Self::True
} else {
Self::False
}
}
}
impl KleeneValue {
/// Turns this Kleene value to a bool, taking the unknown value as an
/// argument.
pub fn to_bool(self, unknown: bool) -> bool {
match self {
Self::True => true,
Self::False => false,
Self::Unknown => unknown,
}
}
/// Return true if any result of f() is definitely true.
/// Otherwise, return the `or` of all values.
/// Returns false if empty, like that of `Iterator`.
#[inline(always)]
pub fn any<T>(iter: impl Iterator<Item = T>, f: impl FnMut(T) -> Self) -> Self {
Self::any_value(iter, Self::True, Self::False, |a, b| a | b, f)
}
/// Return false if any results of f() is definitely false.
/// Otherwise, return the `and` of all values.
/// Returns true if empty, opposite of `Iterator`.
#[inline(always)]
pub fn any_false<T>(iter: impl Iterator<Item = T>, f: impl FnMut(T) -> Self) -> Self {
Self::any_value(iter, Self::False, Self::True, |a, b| a & b, f)
}
#[inline(always)]
fn any_value<T>(
iter: impl Iterator<Item = T>,
value: Self,
on_empty: Self,
op: impl Fn(Self, Self) -> Self,
mut f: impl FnMut(T) -> Self,
) -> Self {
let mut result = None;
for item in iter {
let r = f(item);
if r == value {
return r;
}
if let Some(v) = result.as_mut() {
*v = op(*v, r);
} else {
result = Some(r);
}
}
result.unwrap_or(on_empty)
}
}
impl std::ops::Not for KleeneValue {
type Output = Self;
fn not(self) -> Self {
match self {
Self::True => Self::False,
Self::False => Self::True,
Self::Unknown => Self::Unknown,
}
}
}
// Implements the logical and operation.
impl std::ops::BitAnd for KleeneValue {
type Output = Self;
fn bitand(self, other: Self) -> Self {
if self == Self::False || other == Self::False {
return Self::False;
}
if self == Self::Unknown || other == Self::Unknown {
return Self::Unknown;
}
Self::True
}
}
// Implements the logical or operation.
impl std::ops::BitOr for KleeneValue {
type Output = Self;
fn bitor(self, other: Self) -> Self {
if self == Self::True || other == Self::True {
return Self::True;
}
if self == Self::Unknown || other == Self::Unknown {
return Self::Unknown;
}
Self::False
}
}
impl std::ops::BitOrAssign for KleeneValue {
fn bitor_assign(&mut self, other: Self) {
*self = *self | other;
}
}
impl std::ops::BitAndAssign for KleeneValue {
fn bitand_assign(&mut self, other: Self) {
*self = *self & other;
}
}
================================================
FILE: selectors/lib.rs
================================================
/* 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/. */
// Make |cargo bench| work.
#![cfg_attr(feature = "bench", feature(test))]
pub mod attr;
pub mod bloom;
mod builder;
pub mod context;
pub mod kleene_value;
pub mod matching;
mod nth_index_cache;
pub mod parser;
pub mod relative_selector;
pub mod sink;
mod tree;
pub mod visitor;
pub use crate::nth_index_cache::NthIndexCache;
pub use crate::parser::{Parser, SelectorImpl, SelectorList};
pub use crate::tree::{Element, OpaqueElement};
================================================
FILE: selectors/matching.rs
================================================
/* 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 crate::attr::{
AttrSelectorOperation, AttrSelectorWithOptionalNamespace, CaseSensitivity, NamespaceConstraint,
ParsedAttrSelectorOperation, ParsedCaseSensitivity,
};
use crate::bloom::{BloomFilter, BLOOM_HASH_MASK};
use crate::kleene_value::KleeneValue;
use crate::parser::{
AncestorHashes, Combinator, Component, LocalName, MatchesFeaturelessHost, NthSelectorData,
RelativeSelectorMatchHint,
};
use crate::parser::{
NonTSPseudoClass, RelativeSelector, Selector, SelectorImpl, SelectorIter, SelectorList,
};
use crate::relative_selector::cache::RelativeSelectorCachedMatch;
use crate::tree::Element;
use bitflags::bitflags;
use debug_unreachable::debug_unreachable;
use log::debug;
use smallvec::SmallVec;
use std::borrow::Borrow;
pub use crate::context::*;
// The bloom filter for descendant CSS selectors will have a <1% false
// positive rate until it has this many selectors in it, then it will
// rapidly increase.
pub static RECOMMENDED_SELECTOR_BLOOM_FILTER_SIZE: usize = 4096;
bitflags! {
/// Set of flags that are set on either the element or its parent (depending
/// on the flag) if the element could potentially match a selector.
#[derive(Clone, Copy)]
pub struct ElementSelectorFlags: usize {
/// When a child is added or removed from the parent, all the children
/// must be restyled, because they may match :nth-last-child,
/// :last-of-type, :nth-last-of-type, or :only-of-type.
const HAS_SLOW_SELECTOR = 1 << 0;
/// When a child is added or removed from the parent, any later
/// children must be restyled, because they may match :nth-child,
/// :first-of-type, or :nth-of-type.
const HAS_SLOW_SELECTOR_LATER_SIBLINGS = 1 << 1;
/// HAS_SLOW_SELECTOR* was set by the presence of :nth (But not of).
const HAS_SLOW_SELECTOR_NTH = 1 << 2;
/// When a DOM mutation occurs on a child that might be matched by
/// :nth-last-child(.. of <selector list>), earlier children must be
/// restyled, and HAS_SLOW_SELECTOR will be set (which normally
/// indicates that all children will be restyled).
///
/// Similarly, when a DOM mutation occurs on a child that might be
/// matched by :nth-child(.. of <selector list>), later children must be
/// restyled, and HAS_SLOW_SELECTOR_LATER_SIBLINGS will be set.
const HAS_SLOW_SELECTOR_NTH_OF = 1 << 3;
/// When a child is added or removed from the parent, the first and
/// last children must be restyled, because they may match :first-child,
/// :last-child, or :only-child.
const HAS_EDGE_CHILD_SELECTOR = 1 << 4;
/// The element has an empty selector, so when a child is appended we
/// might need to restyle the parent completely.
const HAS_EMPTY_SELECTOR = 1 << 5;
/// The element may anchor a relative selector.
const ANCHORS_RELATIVE_SELECTOR = 1 << 6;
/// The element may anchor a relative selector that is not the subject
/// of the whole selector.
const ANCHORS_RELATIVE_SELECTOR_NON_SUBJECT = 1 << 7;
/// The element is reached by a relative selector search in the sibling direction.
const RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING = 1 << 8;
/// The element is reached by a relative selector search in the ancestor direction.
const RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR = 1 << 9;
// The element is reached by a relative selector search in both sibling and ancestor directions.
const RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR_SIBLING =
Self::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING.bits() |
Self::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR.bits();
}
}
impl ElementSelectorFlags {
/// Returns the subset of flags that apply to the element.
pub fn for_self(self) -> ElementSelectorFlags {
self & (ElementSelectorFlags::HAS_EMPTY_SELECTOR
| ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR
| ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR_NON_SUBJECT
| ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING
| ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR)
}
/// Returns the subset of flags that apply to the parent.
pub fn for_parent(self) -> ElementSelectorFlags {
self & (ElementSelectorFlags::HAS_SLOW_SELECTOR
| ElementSelectorFlags::HAS_SLOW_SELECTOR_LATER_SIBLINGS
| ElementSelectorFlags::HAS_SLOW_SELECTOR_NTH
| ElementSelectorFlags::HAS_SLOW_SELECTOR_NTH_OF
| ElementSelectorFlags::HAS_EDGE_CHILD_SELECTOR)
}
}
/// Holds per-compound-selector data.
struct LocalMatchingContext<'a, 'b: 'a, Impl: SelectorImpl> {
shared: &'a mut MatchingContext<'b, Impl>,
rightmost: SubjectOrPseudoElement,
quirks_data: Option<SelectorIter<'a, Impl>>,
}
#[inline(always)]
pub fn matches_selector_list<E>(
selector_list: &SelectorList<E::Impl>,
element: &E,
context: &mut MatchingContext<E::Impl>,
) -> bool
where
E: Element,
{
// This is pretty much any(..) but manually inlined because the compiler
// refuses to do so from querySelector / querySelectorAll.
for selector in selector_list.slice() {
let matches = matches_selector(selector, 0, None, element, context);
if matches {
return true;
}
}
false
}
/// Given the ancestor hashes from a selector, see if the current element,
/// represented by the bloom filter, has a chance of matching at all.
#[inline(always)]
pub fn selector_may_match(hashes: &AncestorHashes, bf: &BloomFilter) -> bool {
// Check the first three hashes. Note that we can check for zero before
// masking off the high bits, since if any of the first three hashes is
// zero the fourth will be as well. We also take care to avoid the
// special-case complexity of the fourth hash until we actually reach it,
// because we usually don't.
//
// To be clear: this is all extremely hot.
for i in 0..3 {
let packed = hashes.packed_hashes[i];
if packed == 0 {
// No more hashes left - unable to fast-reject.
return true;
}
if !bf.might_contain_hash(packed & BLOOM_HASH_MASK) {
// Hooray! We fast-rejected on this hash.
return false;
}
}
// Now do the slighty-more-complex work of synthesizing the fourth hash,
// and check it against the filter if it exists.
let fourth = hashes.fourth_hash();
fourth == 0 || bf.might_contain_hash(fourth)
}
/// A result of selector matching, includes 3 failure types,
///
/// NotMatchedAndRestartFromClosestLaterSibling
/// NotMatchedAndRestartFromClosestDescendant
/// NotMatchedGlobally
///
/// When NotMatchedGlobally appears, stop selector matching completely since
/// the succeeding selectors never matches.
/// It is raised when
/// Child combinator cannot find the candidate element.
/// Descendant combinator cannot find the candidate element.
///
/// When NotMatchedAndRestartFromClosestDescendant appears, the selector
/// matching does backtracking and restarts from the closest Descendant
/// combinator.
/// It is raised when
/// NextSibling combinator cannot find the candidate element.
/// LaterSibling combinator cannot find the candidate element.
/// Child combinator doesn't match on the found element.
///
/// When NotMatchedAndRestartFromClosestLaterSibling appears, the selector
/// matching does backtracking and restarts from the closest LaterSibling
/// combinator.
/// It is raised when
/// NextSibling combinator doesn't match on the found element.
///
/// For example, when the selector "d1 d2 a" is provided and we cannot *find*
/// an appropriate ancestor element for "d1", this selector matching raises
/// NotMatchedGlobally since even if "d2" is moved to more upper element, the
/// candidates for "d1" becomes less than before and d1 .
///
/// The next example is siblings. When the selector "b1 + b2 ~ d1 a" is
/// provided and we cannot *find* an appropriate brother element for b1,
/// the selector matching raises NotMatchedAndRestartFromClosestDescendant.
/// The selectors ("b1 + b2 ~") doesn't match and matching restart from "d1".
///
/// The additional example is child and sibling. When the selector
/// "b1 + c1 > b2 ~ d1 a" is provided and the selector "b1" doesn't match on
/// the element, this "b1" raises NotMatchedAndRestartFromClosestLaterSibling.
/// However since the selector "c1" raises
/// NotMatchedAndRestartFromClosestDescendant. So the selector
/// "b1 + c1 > b2 ~ " doesn't match and restart matching from "d1".
///
/// There is also the unknown result, which is used during invalidation when
/// specific selector is being tested for before/after comparison. More specifically,
/// selectors that are too expensive to correctly compute during invalidation may
/// return unknown, as the computation will be thrown away and only to be recomputed
/// during styling. For most cases, the unknown result can be treated as matching.
/// This is because a compound of selectors acts like &&, and unknown && matched
/// == matched and unknown && not-matched == not-matched. However, some selectors,
/// like `:is()`, behave like || i.e. `:is(.a, .b)` == a || b. Treating unknown
/// == matching then causes these selectors to always return matching, which undesired
/// for before/after comparison. Coercing to not-matched doesn't work since each
/// inner selector may have compounds: e.g. Toggling `.foo` in `:is(.foo:has(..))`
/// with coersion to not-matched would result in an invalid before/after comparison
/// of not-matched/not-matched.
#[derive(Clone, Copy, Eq, PartialEq)]
enum SelectorMatchingResult {
Matched,
NotMatchedAndRestartFromClosestLaterSibling,
NotMatchedAndRestartFromClosestDescendant,
NotMatchedGlobally,
Unknown,
}
impl From<SelectorMatchingResult> for KleeneValue {
#[inline]
fn from(value: SelectorMatchingResult) -> Self {
match value {
SelectorMatchingResult::Matched => KleeneValue::True,
SelectorMatchingResult::Unknown => KleeneValue::Unknown,
SelectorMatchingResult::NotMatchedAndRestartFromClosestLaterSibling
| SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant
| SelectorMatchingResult::NotMatchedGlobally => KleeneValue::False,
}
}
}
/// Matches a selector, fast-rejecting against a bloom filter.
///
/// We accept an offset to allow consumers to represent and match against
/// partial selectors (indexed from the right). We use this API design, rather
/// than having the callers pass a SelectorIter, because creating a SelectorIter
/// requires dereferencing the selector to get the length, which adds an
/// unnecessary cache miss for cases when we can fast-reject with AncestorHashes
/// (which the caller can store inline with the selector pointer).
#[inline(always)]
pub fn matches_selector<E>(
selector: &Selector<E::Impl>,
offset: usize,
hashes: Option<&AncestorHashes>,
element: &E,
context: &mut MatchingContext<E::Impl>,
) -> bool
where
E: Element,
{
let result = matches_selector_kleene(selector, offset, hashes, element, context);
if cfg!(debug_assertions) && result == KleeneValue::Unknown {
debug_assert!(
context
.matching_for_invalidation_comparison()
.unwrap_or(false),
"How did we return unknown?"
);
}
result.to_bool(true)
}
/// Same as matches_selector, but returns the Kleene value as-is.
#[inline(always)]
pub fn matches_selector_kleene<E>(
selector: &Selector<E::Impl>,
offset: usize,
hashes: Option<&AncestorHashes>,
element: &E,
context: &mut MatchingContext<E::Impl>,
) -> KleeneValue
where
E: Element,
{
// Use the bloom filter to fast-reject.
if let Some(hashes) = hashes {
if let Some(filter) = context.bloom_filter {
if !selector_may_match(hashes, filter) {
return KleeneValue::False;
}
}
}
matches_complex_selector(
selector.iter_from(offset),
element,
context,
if selector.is_rightmost(offset) {
SubjectOrPseudoElement::Yes
} else {
SubjectOrPseudoElement::No
},
)
}
/// Whether a compound selector matched, and whether it was the rightmost
/// selector inside the complex selector.
pub enum CompoundSelectorMatchingResult {
/// The selector was fully matched.
FullyMatched,
/// The compound selector matched, and the next combinator offset is
/// `next_combinator_offset`.
Matched { next_combinator_offset: usize },
/// The selector didn't match.
NotMatched,
}
fn complex_selector_early_reject_by_local_name<E: Element>(
list: &SelectorList<E::Impl>,
element: &E,
) -> bool {
list.slice()
.iter()
.all(|s| early_reject_by_local_name(s, 0, element))
}
/// Returns true if this compound would not match the given element by due
/// to a local name selector (If one exists).
pub fn early_reject_by_local_name<E: Element>(
selector: &Selector<E::Impl>,
from_offset: usize,
element: &E,
) -> bool {
let iter = selector.iter_from(from_offset);
for component in iter {
if match component {
Component::LocalName(name) => !matches_local_name(element, name),
Component::Is(list) | Component::Where(list) => {
complex_selector_early_reject_by_local_name(list, element)
},
_ => continue,
} {
return true;
}
}
false
}
/// Matches a compound selector belonging to `selector`, starting at offset
/// `from_offset`, matching left to right.
///
/// Requires that `from_offset` points to a `Combinator`.
///
/// NOTE(emilio): This doesn't allow to match in the leftmost sequence of the
/// complex selector, but it happens to be the case we don't need it.
pub fn matches_compound_selector_from<E>(
selector: &Selector<E::Impl>,
mut from_offset: usize,
context: &mut MatchingContext<E::Impl>,
element: &E,
) -> CompoundSelectorMatchingResult
where
E: Element,
{
debug_assert!(
!context
.matching_for_invalidation_comparison()
.unwrap_or(false),
"CompoundSelectorMatchingResult doesn't support unknown"
);
if cfg!(debug_assertions) && from_offset != 0 {
selector.combinator_at_parse_order(from_offset - 1); // This asserts.
}
let mut local_context = LocalMatchingContext {
shared: context,
// We have no info if this is an outer selector. This function is called in
// an invalidation context, which only calls this for non-subject (i.e.
// Non-rightmost) positions.
rightmost: SubjectOrPseudoElement::No,
quirks_data: None,
};
// Find the end of the selector or the next combinator, then match
// backwards, so that we match in the same order as
// matches_complex_selector, which is usually faster.
let start_offset = from_offset;
for component in selector.iter_raw_parse_order_from(from_offset) {
if matches!(*component, Component::Combinator(..)) {
debug_assert_ne!(from_offset, 0, "Selector started with a combinator?");
break;
}
from_offset += 1;
}
debug_assert!(from_offset >= 1);
debug_assert!(from_offset <= selector.len());
let iter = selector.iter_from(selector.len() - from_offset);
debug_assert!(
iter.clone().next().is_some() || from_offset != selector.len(),
"Got the math wrong: {:?} | {:?} | {} {}",
selector,
selector.iter_raw_match_order().as_slice(),
from_offset,
start_offset
);
debug_assert!(
!local_context.shared.featureless(),
"Invalidating featureless element somehow?"
);
for component in iter {
let result = matches_simple_selector(component, element, &mut local_context);
debug_assert!(
result != KleeneValue::Unknown,
"Returned unknown in non invalidation context?"
);
if !result.to_bool(true) {
return CompoundSelectorMatchingResult::NotMatched;
}
}
if from_offset != selector.len() {
return CompoundSelectorMatchingResult::Matched {
next_combinator_offset: from_offset,
};
}
CompoundSelectorMatchingResult::FullyMatched
}
/// Matches a complex selector.
#[inline(always)]
fn matches_complex_selector<E>(
mut iter: SelectorIter<E::Impl>,
element: &E,
context: &mut MatchingContext<E::Impl>,
rightmost: SubjectOrPseudoElement,
) -> KleeneValue
where
E: Element,
{
// If this is the special pseudo-element mode, consume the ::pseudo-element
// before proceeding, since the caller has already handled that part.
if context.matching_mode() == MatchingMode::ForStatelessPseudoElement && !context.is_nested() {
// Consume the pseudo.
match *iter.next().unwrap() {
Component::PseudoElement(ref pseudo) => {
if let Some(ref f) = context.pseudo_element_matching_fn {
if !f(pseudo) {
return KleeneValue::False;
}
}
},
ref other => {
debug_assert!(
false,
"Used MatchingMode::ForStatelessPseudoElement \
in a non-pseudo selector {:?}",
other
);
return KleeneValue::False;
},
}
if !iter.matches_for_stateless_pseudo_element() {
return KleeneValue::False;
}
// Advance to the non-pseudo-element part of the selector.
let next_sequence = iter.next_sequence().unwrap();
debug_assert_eq!(next_sequence, Combinator::PseudoElement);
}
matches_complex_selector_internal(
iter,
element,
context,
rightmost,
SubjectOrPseudoElement::Yes,
)
.into()
}
/// Matches each selector of a list as a complex selector
fn matches_complex_selector_list<E: Element>(
list: &[Selector<E::Impl>],
element: &E,
context: &mut MatchingContext<E::Impl>,
rightmost: SubjectOrPseudoElement,
) -> KleeneValue {
KleeneValue::any(list.iter(), |selector| {
matches_complex_selector(selector.iter(), element, context, rightmost)
})
}
fn matches_relative_selector<E: Element>(
relative_selector: &RelativeSelector<E::Impl>,
element: &E,
context: &mut MatchingContext<E::Impl>,
rightmost: SubjectOrPseudoElement,
) -> bool {
// Overall, we want to mark the path that we've traversed so that when an element
// is invalidated, we early-reject unnecessary relative selector invalidations.
if relative_selector.match_hint.is_descendant_direction() {
if context.needs_selector_flags() {
element.apply_selector_flags(
ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
);
}
let mut next_element = element.first_element_child();
while let Some(el) = next_element {
if context.needs_selector_flags() {
el.apply_selector_flags(
ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
);
}
let mut matched = matches_complex_selector(
relative_selector.selector.iter(),
&el,
context,
rightmost,
)
.to_bool(true);
if !matched && relative_selector.match_hint.is_subtree() {
matched = matches_relative_selector_subtree(
&relative_selector.selector,
&el,
context,
rightmost,
);
}
if matched {
return true;
}
next_element = el.next_sibling_element();
}
} else {
debug_assert!(
matches!(
relative_selector.match_hint,
RelativeSelectorMatchHint::InNextSibling
| RelativeSelectorMatchHint::InNextSiblingSubtree
| RelativeSelectorMatchHint::InSibling
| RelativeSelectorMatchHint::InSiblingSubtree
),
"Not descendant direction, but also not sibling direction?"
);
if context.needs_selector_flags() {
element.apply_selector_flags(
ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
);
}
let sibling_flag = if relative_selector.match_hint.is_subtree() {
ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR_SIBLING
} else {
ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING
};
let mut next_element = element.next_sibling_element();
while let Some(el) = next_element {
if context.needs_selector_flags() {
el.apply_selector_flags(sibling_flag);
}
let matched = if relative_selector.match_hint.is_subtree() {
matches_relative_selector_subtree(
&relative_selector.selector,
&el,
context,
rightmost,
)
} else {
matches_complex_selector(relative_selector.selector.iter(), &el, context, rightmost)
.to_bool(true)
};
if matched {
return true;
}
if relative_selector.match_hint.is_next_sibling() {
break;
}
next_element = el.next_sibling_element();
}
}
return false;
}
fn relative_selector_match_early<E: Element>(
selector: &RelativeSelector<E::Impl>,
element: &E,
context: &mut MatchingContext<E::Impl>,
) -> Option<bool> {
// See if we can return a cached result.
if let Some(cached) = context
.selector_caches
.relative_selector
.lookup(element.opaque(), selector)
{
return Some(cached.matched());
}
// See if we can fast-reject.
if context
.selector_caches
.relative_selector_filter_map
.fast_reject(element, selector, context.quirks_mode())
{
// Alright, add as unmatched to cache.
context.selector_caches.relative_selector.add(
element.opaque(),
selector,
RelativeSelectorCachedMatch::NotMatched,
);
return Some(false);
}
None
}
fn match_relative_selectors<E: Element>(
selectors: &[RelativeSelector<E::Impl>],
element: &E,
context: &mut MatchingContext<E::Impl>,
rightmost: SubjectOrPseudoElement,
) -> KleeneValue {
if context.relative_selector_anchor().is_some() {
// FIXME(emilio): This currently can happen with nesting, and it's not fully
// correct, arguably. But the ideal solution isn't super-clear either. For now,
// cope with it and explicitly reject it at match time. See [1] for discussion.
//
// [1]: https://github.com/w3c/csswg-drafts/issues/9600
return KleeneValue::False;
}
if let Some(may_return_unknown) = context.matching_for_invalidation_comparison() {
// In the context of invalidation, :has is expensive, especially because we
// can't use caching/filtering due to now/then matches. DOM structure also
// may have changed.
return if may_return_unknown {
KleeneValue::Unknown
} else {
KleeneValue::from(!context.in_negation())
};
}
context
.nest_for_relative_selector(element.opaque(), |context| {
do_match_relative_selectors(selectors, element, context, rightmost)
})
.into()
}
/// Matches a relative selector in a list of relative selectors.
fn do_match_relative_selectors<E: Element>(
selectors: &[RelativeSelector<E::Impl>],
element: &E,
context: &mut MatchingContext<E::Impl>,
rightmost: SubjectOrPseudoElement,
) -> bool {
// Due to style sharing implications (See style sharing code), we mark the current styling context
// to mark elements considered for :has matching. Additionally, we want to mark the elements themselves,
// since we don't want to indiscriminately invalidate every element as a potential anchor.
if rightmost == SubjectOrPseudoElement::Yes {
if context.needs_selector_flags() {
element.apply_selector_flags(ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR);
}
} else {
if context.needs_selector_flags() {
element
.apply_selector_flags(ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR_NON_SUBJECT);
}
}
for relative_selector in selectors.iter() {
if let Some(result) = relative_selector_match_early(relative_selector, element, context) {
if result {
return true;
}
// Early return indicates no match, continue to next selector.
continue;
}
let matched = matches_relative_selector(relative_selector, element, context, rightmost);
context.selector_caches.relative_selector.add(
element.opaque(),
relative_selector,
if matched {
RelativeSelectorCachedMatch::Matched
} else {
RelativeSelectorCachedMatch::NotMatched
},
);
if matched {
return true;
}
}
false
}
fn matches_relative_selector_subtree<E: Element>(
selector: &Selector<E::Impl>,
element: &E,
context: &mut MatchingContext<E::Impl>,
rightmost: SubjectOrPseudoElement,
) -> bool {
let mut current = element.first_element_child();
while let Some(el) = current {
if context.needs_selector_flags() {
el.apply_selector_flags(
ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
);
}
if matches_complex_selector(selector.iter(), &el, context, rightmost).to_bool(true) {
return true;
}
if matches_relative_selector_subtree(selector, &el, context, rightmost) {
return true;
}
current = el.next_sibling_element();
}
false
}
/// Whether the :hover and :active quirk applies.
///
/// https://quirks.spec.whatwg.org/#the-active-and-hover-quirk
fn hover_and_active_quirk_applies<Impl: SelectorImpl>(
selector_iter: &SelectorIter<Impl>,
context: &MatchingContext<Impl>,
rightmost: SubjectOrPseudoElement,
) -> bool {
debug_assert_eq!(context.quirks_mode(), QuirksMode::Quirks);
if context.is_nested() {
return false;
}
// This compound selector had a pseudo-element to the right that we
// intentionally skipped.
if rightmost == SubjectOrPseudoElement::Yes
&& context.matching_mode() == MatchingMode::ForStatelessPseudoElement
{
return false;
}
selector_iter.clone().all(|simple| match *simple {
Component::NonTSPseudoClass(ref pseudo_class) => pseudo_class.is_active_or_hover(),
_ => false,
})
}
#[derive(Clone, Copy, PartialEq)]
enum SubjectOrPseudoElement {
Yes,
No,
}
fn host_for_part<E>(element: &E, context: &MatchingContext<E::Impl>) -> Option<E>
where
E: Element,
{
let scope = context.current_host;
let mut curr = element.containing_shadow_host()?;
if scope == Some(curr.opaque()) {
return Some(curr);
}
loop {
let parent = curr.containing_shadow_host();
if parent.as_ref().map(|h| h.opaque()) == scope {
return Some(curr);
}
curr = parent?;
}
}
fn assigned_slot<E>(element: &E, context: &MatchingContext<E::Impl>) -> Option<E>
where
E: Element,
{
debug_assert!(element
.assigned_slot()
.map_or(true, |s| s.is_html_slot_element()));
let scope = context.current_host?;
let mut current_slot = element.assigned_slot()?;
while current_slot.containing_shadow_host().unwrap().opaque() != scope {
current_slot = current_slot.assigned_slot()?;
}
Some(current_slot)
}
struct NextElement<E> {
next_element: Option<E>,
featureless: bool,
}
impl<E> NextElement<E> {
#[inline(always)]
fn new(next_element: Option<E>, featureless: bool) -> Self {
Self {
next_element,
featureless,
}
}
}
#[inline(always)]
fn next_element_for_combinator<E>(
element: &E,
combinator: Combinator,
context: &MatchingContext<E::Impl>,
) -> NextElement<E>
where
E: Element,
{
match combinator {
Combinator::NextSibling | Combinator::LaterSibling => {
NextElement::new(element.prev_sibling_element(), false)
},
Combinator::Child | Combinator::Descendant => {
if let Some(parent) = element.parent_element() {
return NextElement::new(Some(parent), false);
}
let element = if element.parent_node_is_shadow_root() {
element.containing_shadow_host()
} else {
None
};
NextElement::new(element, true)
},
Combinator::Part => NextElement::new(host_for_part(element, context), false),
Combinator::SlotAssignment => NextElement::new(assigned_slot(element, context), false),
Combinator::PseudoElement => {
NextElement::new(element.pseudo_element_originating_element(), false)
},
}
}
fn matches_complex_selector_internal<E>(
mut selector_iter: SelectorIter<E::Impl>,
element: &E,
context: &mut MatchingContext<E::Impl>,
mut rightmost: SubjectOrPseudoElement,
mut first_subject_compound: SubjectOrPseudoElement,
) -> SelectorMatchingResult
where
E: Element,
{
debug!(
"Matching complex selector {:?} for {:?}",
selector_iter, element
);
let matches_compound_selector =
matches_compound_selector(&mut selector_iter, element, context, rightmost);
let Some(combinator) = selector_iter.next_sequence() else {
return match matches_compound_selector {
KleeneValue::True => SelectorMatchingResult::Matched,
KleeneValue::Unknown => SelectorMatchingResult::Unknown,
KleeneValue::False => {
SelectorMatchingResult::NotMatchedAndRestartFromClosestLaterSibling
},
};
};
let is_pseudo_combinator = combinator.is_pseudo_element();
if context.featureless() && !is_pseudo_combinator {
// A featureless element shouldn't match any further combinator.
// TODO(emilio): Maybe we could avoid the compound matching more eagerly.
return SelectorMatchingResult::NotMatchedGlobally;
}
let is_sibling_combinator = combinator.is_sibling();
if is_sibling_combinator && context.needs_selector_flags() {
// We need the flags even if we don't match.
element.apply_selector_flags(ElementSelectorFlags::HAS_SLOW_SELECTOR_LATER_SIBLINGS);
}
if matches_compound_selector == KleeneValue::False {
// We don't short circuit unknown here, since the rest of the selector
// to the left of this compound may still return false.
return SelectorMatchingResult::NotMatchedAndRestartFromClosestLaterSibling;
}
if !is_pseudo_combinator {
rightmost = SubjectOrPseudoElement::No;
first_subject_compound = SubjectOrPseudoElement::No;
}
// Stop matching :visited as soon as we find a link, or a combinator for
// something that isn't an ancestor.
let mut visited_handling = if is_sibling_combinator {
VisitedHandlingMode::AllLinksUnvisited
} else {
context.visited_handling()
};
let candidate_not_found = if is_sibling_combinator {
SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant
} else {
SelectorMatchingResult::NotMatchedGlobally
};
let mut element = element.clone();
loop {
if element.is_link() {
visited_handling = VisitedHandlingMode::AllLinksUnvisited;
}
let NextElement {
next_element,
featureless,
} = next_element_for_combinator(&element, combinator, &context);
element = match next_element {
None => return candidate_not_found,
Some(e) => e,
};
let result = context.with_visited_handling_mode(visited_handling, |context| {
context.with_featureless(featureless, |context| {
matches_complex_selector_internal(
selector_iter.clone(),
&element,
context,
rightmost,
first_subject_compound,
)
})
});
// Return the status immediately if it is one of the global states.
match result {
SelectorMatchingResult::Matched => {
debug_assert!(
matches_compound_selector.to_bool(true),
"Compound didn't match?"
);
if !matches_compound_selector.to_bool(false) {
return SelectorMatchingResult::Unknown;
}
return result;
},
SelectorMatchingResult::Unknown | SelectorMatchingResult::NotMatchedGlobally => {
return result
},
_ => {},
}
match combinator {
Combinator::Descendant => {
// The Descendant combinator and the status is
// NotMatchedAndRestartFromClosestLaterSibling or
// NotMatchedAndRestartFromClosestDescendant, or the LaterSibling combinator and
// the status is NotMatchedAndRestartFromClosestDescendant, we can continue to
// matching on the next candidate element.
},
Combinator::Child => {
// Upgrade the failure status to NotMatchedAndRestartFromClosestDescendant.
return SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant;
},
Combinator::LaterSibling => {
// If the failure status is NotMatchedAndRestartFromClosestDescendant and combinator is
// LaterSibling, give up this LaterSibling matching and restart from the closest
// descendant combinator.
if matches!(
result,
SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant
) {
return result;
}
},
Combinator::NextSibling
| Combinator::PseudoElement
| Combinator::Part
| Combinator::SlotAssignment => {
// NOTE(emilio): Conceptually, PseudoElement / Part / SlotAssignment should return
// `candidate_not_found`, but it doesn't matter in practice since they don't have
// sibling / descendant combinators to the right of them. This hopefully saves one
// branch.
return result;
},
}
if featureless {
// A featureless element didn't match the selector, we can stop matching now rather
// than looking at following elements for our combinator.
return candidate_not_found;
}
}
}
#[inline]
fn matches_local_name<E>(element: &E, local_name: &LocalName<E::Impl>) -> bool
where
E: Element,
{
let name = select_name(element, &local_name.name, &local_name.lower_name).borrow();
element.has_local_name(name)
}
fn matches_part<E>(
element: &E,
parts: &[<E::Impl as SelectorImpl>::Identifier],
context: &mut MatchingContext<E::Impl>,
) -> bool
where
E: Element,
{
let mut hosts = SmallVec::<[E; 4]>::new();
let mut host = match element.containing_shadow_host() {
Some(h) => h,
None => return false,
};
let current_host = context.current_host;
if current_host != Some(host.opaque()) {
loop {
let outer_host = host.containing_shadow_host();
if outer_host.as_ref().map(|h| h.opaque()) == current_host {
break;
}
let outer_host = match outer_host {
Some(h) => h,
None => return false,
};
// TODO(emilio): if worth it, we could early return if
// host doesn't have the exportparts attribute.
hosts.push(host);
host = outer_host;
}
}
// Translate the part into the right scope.
parts.iter().all(|part| {
let mut part = part.clone();
for host in hosts.iter().rev() {
part = match host.imported_part(&part) {
Some(p) => p,
None => return false,
};
}
element.is_part(&part)
})
}
fn matches_host<E>(
element: &E,
selector: Option<&Selector<E::Impl>>,
context: &mut MatchingContext<E::Impl>,
rightmost: SubjectOrPseudoElement,
) -> KleeneValue
where
E: Element,
{
let host = match context.shadow_host() {
Some(h) => h,
None => return KleeneValue::False,
};
if host != element.opaque() {
return KleeneValue::False;
}
let Some(selector) = selector else {
return KleeneValue::True;
};
context.nest(|context| {
context.with_featureless(false, |context| {
matches_complex_selector(selector.iter(), element, context, rightmost)
})
})
}
fn matches_slotted<E>(
element: &E,
selector: &Selector<E::Impl>,
context: &mut MatchingContext<E::Impl>,
rightmost: SubjectOrPseudoElement,
) -> KleeneValue
where
E: Element,
{
// <slots> are never flattened tree slottables.
if element.is_html_slot_element() {
return KleeneValue::False;
}
context.nest(|context| matches_complex_selector(selector.iter(), element, context, rightmost))
}
fn matches_rare_attribute_selector<E>(
element: &E,
attr_sel: &AttrSelectorWithOptionalNamespace<E::Impl>,
) -> bool
where
E: Element,
{
let empty_string;
let namespace = match attr_sel.namespace() {
Some(ns) => ns,
None => {
empty_string = crate::parser::namespace_empty_string::<E::Impl>();
NamespaceConstraint::Specific(&empty_string)
},
};
element.attr_matches(
&namespace,
select_name(element, &attr_sel.local_name, &attr_sel.local_name_lower),
&match attr_sel.operation {
ParsedAttrSelectorOperation::Exists => AttrSelectorOperation::Exists,
ParsedAttrSelectorOperation::WithValue {
operator,
case_sensitivity,
ref value,
} => AttrSelectorOperation::WithValue {
operator,
case_sensitivity: to_unconditional_case_sensitivity(case_sensitivity, element),
value,
},
},
)
}
/// There are relatively few selectors in a given compound that may match a featureless element.
/// Instead of adding a check to every selector that may not match, we handle it here in an out of
/// line path.
pub(crate) fn compound_matches_featureless_host<Impl: SelectorImpl>(
iter: &mut SelectorIter<Impl>,
scope_matches_featureless_host: bool,
) -> MatchesFeaturelessHost {
let mut matches = MatchesFeaturelessHost::Only;
for component in iter {
match component {
Component::Scope | Component::ImplicitScope if scope_matches_featureless_host => {},
// :host only matches featureless elements.
Component::Host(..) => {},
// Pseudo-elements are allowed to match as well.
Component::PseudoElement(..) => {},
// We allow logical pseudo-classes, but we'll fail matching of the inner selectors if
// necessary.
Component::Is(ref l) | Component::Where(ref l) => {
let mut any_yes = false;
let mut any_no = false;
for selector in l.slice() {
match selector.matches_featureless_host(scope_matches_featureless_host) {
MatchesFeaturelessHost::Never => {
any_no = true;
},
MatchesFeaturelessHost::Yes => {
any_yes = true;
any_no = true;
},
MatchesFeaturelessHost::Only => {
any_yes = true;
},
}
}
if !any_yes {
return MatchesFeaturelessHost::Never;
}
if any_no {
// Potentially downgrade since we might match non-featureless elements too.
matches = MatchesFeaturelessHost::Yes;
}
},
Component::Negation(ref l) => {
// For now preserving behavior, see
// https://github.com/w3c/csswg-drafts/issues/10179 for existing resolutions that
// tweak this behavior.
for selector in l.slice() {
if selector.matches_featureless_host(scope_matches_featureless_host)
!= MatchesFeaturelessHost::Only
{
return MatchesFeaturelessHost::Never;
}
}
},
// Other components don't match the host scope.
_ => return MatchesFeaturelessHost::Never,
}
}
matches
}
/// Determines whether the given element matches the given compound selector.
#[inline]
fn matches_compound_selector<E>(
selector_iter: &mut SelectorIter<E::Impl>,
element: &E,
context: &mut MatchingContext<E::Impl>,
rightmost: SubjectOrPseudoElement,
) -> KleeneValue
where
E: Element,
{
if context.featureless()
&& compound_matches_featureless_host(
&mut selector_iter.clone(),
/* scope_matches_featureless_host = */ true,
) == MatchesFeaturelessHost::Never
{
return KleeneValue::False;
}
let quirks_data = if context.quirks_mode() == QuirksMode::Quirks {
Some(selector_iter.clone())
} else {
None
};
let mut local_context = LocalMatchingContext {
shared: context,
rightmost,
quirks_data,
};
KleeneValue::any_false(selector_iter, |simple| {
matches_simple_selector(simple, element, &mut local_context)
})
}
/// Determines whether the given element matches the given single selector.
fn matches_simple_selector<E>(
selector: &Component<E::Impl>,
element: &E,
context: &mut LocalMatchingContext<E::Impl>,
) -> KleeneValue
where
E: Element,
{
debug_assert!(context.shared.is_nested() || !context.shared.in_negation());
let rightmost = context.rightmost;
KleeneValue::from(match *selector {
Component::ID(ref id) => {
element.has_id(id, context.shared.classes_and_ids_case_sensitivity())
},
Component::Class(ref class) => {
element.has_class(class, context.shared.classes_and_ids_case_sensitivity())
},
Component::LocalName(ref local_name) => matches_local_name(element, local_name),
Component::AttributeInNoNamespaceExists {
ref local_name,
ref local_name_lower,
} => element.has_attr_in_no_namespace(select_name(element, local_name, local_name_lower)),
Component::AttributeInNoNamespace {
ref local_name,
ref value,
operator,
case_sensitivity,
} => element.attr_matches(
&NamespaceConstraint::Specific(&crate::parser::namespace_empty_string::<E::Impl>()),
local_name,
&AttrSelectorOperation::WithValue {
operator,
case_sensitivity: to_unconditional_case_sensitivity(case_sensitivity, element),
value,
},
),
Component::AttributeOther(ref attr_sel) => {
matches_rare_attribute_selector(element, attr_sel)
},
Component::Part(ref parts) => matches_part(element, parts, &mut context.shared),
Component::Slotted(ref selector) => {
return matches_slotted(element, selector, &mut context.shared, rightmost);
},
Component::PseudoElement(ref pseudo) => {
element.match_pseudo_element(pseudo, context.shared)
},
Component::ExplicitUniversalType | Component::ExplicitAnyNamespace => true,
Component::Namespace(_, ref url) | Component::DefaultNamespace(ref url) => {
element.has_namespace(&url.borrow())
},
Component::ExplicitNoNamespace => {
let ns = crate::parser::namespace_empty_string::<E::Impl>();
element.has_namespace(&ns.borrow())
},
Component::NonTSPseudoClass(ref pc) => {
if let Some(ref iter) = context.quirks_data {
if pc.is_active_or_hover()
&& !element.is_link()
&& hover_and_active_quirk_applies(iter, context.shared, context.rightmost)
{
return KleeneValue::False;
}
}
element.match_non_ts_pseudo_class(pc, &mut context.shared)
},
Component::Root => element.is_root(),
Component::Empty => {
if context.shared.needs_selector_flags() {
element.apply_selector_flags(ElementSelectorFlags::HAS_EMPTY_SELECTOR);
}
element.is_empty()
},
Component::Host(ref selector) => {
return matches_host(element, selector.as_ref(), &mut context.shared, rightmost);
},
Component::ParentSelector => match context.shared.scope_element {
Some(ref scope_element) => element.opaque() == *scope_element,
None => element.is_root(),
},
Component::Scope | Component::ImplicitScope => {
let matching_for_invalidation = context.shared.matching_for_invalidation_comparison();
if context.shared.matching_for_revalidation() || matching_for_invalidation.is_some() {
let may_return_unknown = matching_for_invalidation.unwrap_or(false);
return if may_return_unknown {
KleeneValue::Unknown
} else {
KleeneValue::from(!context.shared.in_negation())
};
}
match context.shared.scope_element {
Some(ref scope_element) => element.opaque() == *scope_element,
None => element.is_root(),
}
},
Component::Nth(ref nth_data) => {
return matches_generic_nth_child(element, context.shared, nth_data, &[], rightmost);
},
Component::NthOf(ref nth_of_data) => {
return context.shared.nest(|context| {
matches_generic_nth_child(
element,
context,
nth_of_data.nth_data(),
nth_of_data.selectors(),
rightmost,
)
})
},
Component::Is(ref list) | Component::Where(ref list) => {
return context.shared.nest(|context| {
matches_complex_selector_list(list.slice(), element, context, rightmost)
})
},
Component::Negation(ref list) => {
return context.shared.nest_for_negation(|context| {
!matches_complex_selector_list(list.slice(), element, context, rightmost)
})
},
Component::Has(ref relative_selectors) => {
return match_relative_selectors(
relative_selectors,
element,
context.shared,
rightmost,
);
},
Component::Combinator(_) => unsafe {
debug_unreachable!("Shouldn't try to selector-match combinators")
},
Component::RelativeSelectorAnchor => {
let anchor = context.shared.relative_selector_anchor();
// We may match inner relative selectors, in which case we want to always match.
anchor.map_or(true, |a| a == element.opaque())
},
Component::Invalid(..) => false,
})
}
#[inline(always)]
pub fn select_name<'a, E: Element, T: PartialEq>(
element: &E,
local_name: &'a T,
local_name_lower: &'a T,
) -> &'a T {
if local_name == local_name_lower || element.is_html_element_in_html_document() {
local_name_lower
} else {
local_name
}
}
#[inline(always)]
pub fn to_unconditional_case_sensitivity<'a, E: Element>(
parsed: ParsedCaseSensitivity,
element: &E,
) -> CaseSensitivity {
match parsed {
ParsedCaseSensitivity::CaseSensitive | ParsedCaseSensitivity::ExplicitCaseSensitive => {
CaseSensitivity::CaseSensitive
},
ParsedCaseSensitivity::AsciiCaseInsensitive => CaseSensitivity::AsciiCaseInsensitive,
ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {
if element.is_html_element_in_html_document() {
CaseSensitivity::AsciiCaseInsensitive
} else {
CaseSensitivity::CaseSensitive
}
},
}
}
fn matches_generic_nth_child<E>(
element: &E,
context: &mut MatchingContext<E::Impl>,
nth_data: &NthSelectorData,
selectors: &[Selector<E::Impl>],
rightmost: SubjectOrPseudoElement,
) -> KleeneValue
where
E: Element,
{
if element.ignores_nth_child_selectors() {
return KleeneValue::False;
}
let has_selectors = !selectors.is_empty();
let selectors_match = !has_selectors
|| matches_complex_selector_list(selectors, element, context, rightmost).to_bool(true);
if let Some(may_return_unknown) = context.matching_for_invalidation_comparison() {
// Skip expensive indexing math in invalidation.
return if selectors_match && may_return_unknown {
KleeneValue::Unknown
} else {
KleeneValue::from(selectors_match && !context.in_negation())
};
}
let NthSelectorData { ty, an_plus_b, .. } = *nth_data;
let is_of_type = ty.is_of_type();
if ty.is_only() {
debug_assert!(
!has_selectors,
":only-child and :only-of-type cannot have a selector list!"
);
return KleeneValue::from(
matches_generic_nth_child(
element,
context,
&NthSelectorData::first(is_of_type),
selectors,
rightmost,
)
.to_bool(true)
&& matches_generic_nth_child(
element,
context,
&NthSelectorData::last(is_of_type),
selectors,
rightmost,
)
.to_bool(true),
);
}
let is_from_end = ty.is_from_end();
// It's useful to know whether this can only select the first/last element
// child for optimization purposes, see the `HAS_EDGE_CHILD_SELECTOR` flag.
let is_edge_child_selector = nth_data.is_simple_edge() && !has_selectors;
if context.needs_selector_flags() {
let mut flags = if is_edge_child_selector {
ElementSelectorFlags::HAS_EDGE_CHILD_SELECTOR
} else if is_from_end {
ElementSelectorFlags::HAS_SLOW_SELECTOR
} else {
ElementSelectorFlags::HAS_SLOW_SELECTOR_LATER_SIBLINGS
};
flags |= if has_selectors {
ElementSelectorFlags::HAS_SLOW_SELECTOR_NTH_OF
} else {
ElementSelectorFlags::HAS_SLOW_SELECTOR_NTH
};
element.apply_selector_flags(flags);
}
if !selectors_match {
return KleeneValue::False;
}
// :first/last-child are rather trivial to match, don't bother with the
// cache.
if is_edge_child_selector {
return if is_from_end {
element.next_sibling_element()
} else {
element.prev_sibling_element()
}
.is_none()
.into();
}
// Lookup or compute the index.
let index = if let Some(i) = context
.nth_index_cache(is_of_type, is_from_end, selectors)
.lookup(element.opaque())
{
i
} else {
let i = nth_child_index(
element,
context,
selectors,
is_of_type,
is_from_end,
/* check_cache = */ true,
rightmost,
);
context
.nth_index_cache(is_of_type, is_from_end, selectors)
.insert(element.opaque(), i);
i
};
debug_assert_eq!(
index,
nth_child_index(
element,
context,
selectors,
is_of_type,
is_from_end,
/* check_cache = */ false,
rightmost,
),
"invalid cache"
);
an_plus_b.matches_index(index).into()
}
#[inline]
fn nth_child_index<E>(
element: &E,
context: &mut MatchingContext<E::Impl>,
selectors: &[Selector<E::Impl>],
is_of_type: bool,
is_from_end: bool,
check_cache: bool,
rightmost: SubjectOrPseudoElement,
) -> i32
where
E: Element,
{
// The traversal mostly processes siblings left to right. So when we walk
// siblings to the right when computing NthLast/NthLastOfType we're unlikely
// to get cache hits along the way. As such, we take the hit of walking the
// siblings to the left checking the cache in the is_from_end case (this
// matches what Gecko does). The indices-from-the-left is handled during the
// regular look further below.
if check_cache
&& is_from_end
&& !context
.nth_index_cache(is_of_type, is_from_end, selectors)
.is_empty()
{
let mut index: i32 = 1;
let mut curr = element.clone();
while let Some(e) = curr.prev_sibling_element() {
curr = e;
let matches = if is_of_type {
element.is_same_type(&curr)
} else if !selectors.is_empty() {
matches_complex_selector_list(selectors, &curr, context, rightmost).to_bool(true)
} else {
true
};
if !matches {
continue;
}
if let Some(i) = context
.nth_index_cache(is_of_type, is_from_end, selectors)
.lookup(curr.opaque())
{
return i - index;
}
index += 1;
}
}
let mut index: i32 = 1;
let mut curr = element.clone();
let next = |e: E| {
if is_from_end {
e.next_sibling_element()
} else {
e.prev_sibling_element()
}
};
while let Some(e) = next(curr) {
curr = e;
let matches = if is_of_type {
element.is_same_type(&curr)
} else if !selectors.is_empty() {
matches_complex_selector_list(selectors, &curr, context, rightmost).to_bool(true)
} else {
true
};
if !matches {
continue;
}
// If we're computing indices from the left, check each element in the
// cache. We handle the indices-from-the-right case at the top of this
// function.
if !is_from_end && check_cache {
if let Some(i) = context
.nth_index_cache(is_of_type, is_from_end, selectors)
.lookup(curr.opaque())
{
return i + index;
}
}
index += 1;
}
index
}
================================================
FILE: selectors/nth_index_cache.rs
================================================
/* 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::hash::Hash;
use crate::{parser::Selector, tree::OpaqueElement, SelectorImpl};
use rustc_hash::FxHashMap;
/// A cache to speed up matching of nth-index-like selectors.
///
/// See [1] for some discussion around the design tradeoffs.
///
/// [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1401855#c3
#[derive(Default)]
pub struct NthIndexCache {
nth: NthIndexCacheInner,
nth_of_selectors: NthIndexOfSelectorsCaches,
nth_last: NthIndexCacheInner,
nth_last_of_selectors: NthIndexOfSelectorsCaches,
nth_of_type: NthIndexCacheInner,
nth_last_of_type: NthIndexCacheInner,
}
impl NthIndexCache {
/// Gets the appropriate cache for the given parameters.
pub fn get<Impl: SelectorImpl>(
&mut self,
is_of_type: bool,
is_from_end: bool,
selectors: &[Selector<Impl>],
) -> &mut NthIndexCacheInner {
if is_of_type {
return if is_from_end {
&mut self.nth_last_of_type
} else {
&mut self.nth_of_type
};
}
if !selectors.is_empty() {
return if is_from_end {
self.nth_last_of_selectors.lookup(selectors)
} else {
self.nth_of_selectors.lookup(selectors)
};
}
if is_from_end {
&mut self.nth_last
} else {
&mut self.nth
}
}
}
#[derive(Hash, Eq, PartialEq)]
struct SelectorListCacheKey(usize);
/// Use the selector list's pointer as the cache key
impl SelectorListCacheKey {
// :nth-child of selectors are reference-counted with `ThinArc`, so we know their pointers are stable.
fn new<Impl: SelectorImpl>(selectors: &[Selector<Impl>]) -> Self {
Self(selectors.as_ptr() as usize)
}
}
/// Use a different map of cached indices per :nth-child's or :nth-last-child's selector list
#[derive(Default)]
pub struct NthIndexOfSelectorsCaches(FxHashMap<SelectorListCacheKey, NthIndexCacheInner>);
/// Get or insert a map of cached incides for the selector list of this
/// particular :nth-child or :nth-last-child pseudoclass
impl NthIndexOfSelectorsCaches {
pub fn lookup<Impl: SelectorImpl>(
&mut self,
selectors: &[Selector<Impl>],
) -> &mut NthIndexCacheInner {
self.0
.entry(SelectorListCacheKey::new(selectors))
.or_default()
}
}
/// The concrete per-pseudo-class cache.
#[derive(Default)]
pub struct NthIndexCacheInner(FxHashMap<OpaqueElement, i32>);
impl NthIndexCacheInner {
/// Does a lookup for a given element in the cache.
pub fn lookup(&mut self, el: OpaqueElement) -> Option<i32> {
self.0.get(&el).copied()
}
/// Inserts an entry into the cache.
pub fn insert(&mut self, element: OpaqueElement, index: i32) {
self.0.insert(element, index);
}
/// Returns whether the cache is empty.
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
================================================
FILE: selectors/parser.rs
================================================
/* 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 crate::attr::{AttrSelectorOperator, AttrSelectorWithOptionalNamespace};
use crate::attr::{NamespaceConstraint, ParsedAttrSelectorOperation, ParsedCaseSensitivity};
use crate::bloom::BLOOM_HASH_MASK;
use crate::builder::{
relative_selector_list_specificity_and_flags, selector_list_specificity_and_flags,
SelectorBuilder, SelectorFlags, Specificity, SpecificityAndFlags,
};
use crate::context::QuirksMode;
use crate::sink::Push;
use crate::visitor::SelectorListKind;
pub use crate::visitor::SelectorVisitor;
use bitflags::bitflags;
use cssparser::match_ignore_ascii_case;
use cssparser::parse_nth;
use cssparser::{BasicParseError, BasicParseErrorKind, ParseError, ParseErrorKind};
use cssparser::{CowRcStr, Delimiter, SourceLocation};
use cssparser::{Parser as CssParser, ToCss, Token};
use debug_unreachable::debug_unreachable;
use precomputed_hash::PrecomputedHash;
use servo_arc::{Arc, ArcUnionBorrow, ThinArc, ThinArcUnion, UniqueArc};
use smallvec::SmallVec;
use std::borrow::{Borrow, Cow};
use std::fmt::{self, Debug};
use std::iter::Rev;
use std::slice;
#[cfg(feature = "to_shmem")]
use to_shmem_derive::ToShmem;
/// A trait that represents a pseudo-element.
pub trait PseudoElement: Sized + ToCss {
/// The `SelectorImpl` this pseudo-element is used for.
type Impl: SelectorImpl;
/// Whether the pseudo-element supports a given state selector to the right
/// of it.
fn accepts_state_pseudo_classes(&self) -> bool {
false
}
/// Whether this pseudo-element is valid after a ::slotted(..) pseudo.
fn valid_after_slotted(&self) -> bool {
false
}
/// Whether this pseudo-element is valid when directly after a ::before/::after pseudo.
fn valid_after_before_or_after(&self) -> bool {
false
}
/// Whether this pseudo-element is element-backed.
/// https://drafts.csswg.org/css-pseudo-4/#element-like
fn parses_as_element_backed(&self) -> bool {
false
}
/// Whether this pseudo-element is ::before or ::after pseudo element,
/// which are treated specially when deciding what can come after them.
/// https://drafts.csswg.org/css-pseudo-4/#generated-content
fn is_before_or_after(&self) -> bool {
false
}
/// The count we contribute to the specificity from this pseudo-element.
fn specificity_count(&self) -> u32 {
1
}
/// Whether this pseudo-element is in a pseudo-element tree (excluding the pseudo-element
/// root).
/// https://drafts.csswg.org/css-view-transitions-1/#pseudo-root
fn is_in_pseudo_element_tree(&self) -> bool {
false
}
}
/// A trait that represents a pseudo-class.
pub trait NonTSPseudoClass: Sized + ToCss {
/// The `SelectorImpl` this pseudo-element is used for.
type Impl: SelectorImpl;
/// Whether this pseudo-class is :active or :hover.
fn is_active_or_hover(&self) -> bool;
/// Whether this pseudo-class belongs to:
///
/// https://drafts.csswg.org/selectors-4/#useraction-pseudos
fn is_user_action_state(&self) -> bool;
fn visit<V>(&self, _visitor: &mut V) -> bool
where
V: SelectorVisitor<Impl = Self::Impl>,
{
true
}
}
/// Returns a Cow::Borrowed if `s` is already ASCII lowercase, and a
/// Cow::Owned if `s` had to be converted into ASCII lowercase.
fn to_ascii_lowercase(s: &str) -> Cow<'_, str> {
if let Some(first_uppercase) = s.bytes().position(|byte| byte >= b'A' && byte <= b'Z') {
let mut string = s.to_owned();
string[first_uppercase..].make_ascii_lowercase();
string.into()
} else {
s.into()
}
}
bitflags! {
/// Flags that indicate at which point of parsing a selector are we.
#[derive(Copy, Clone)]
struct SelectorParsingState: u16 {
/// Whether we should avoid adding default namespaces to selectors that
/// aren't type or universal selectors.
const SKIP_DEFAULT_NAMESPACE = 1 << 0;
/// Whether we've parsed a ::slotted() pseudo-element already.
///
/// If so, then we can only parse a subset of pseudo-elements, and
/// whatever comes after them if so.
const AFTER_SLOTTED = 1 << 1;
/// Whether we've parsed a ::part() or element-backed pseudo-element already.
///
/// If so, then we can only parse a subset of pseudo-elements, and
/// whatever comes after them if so.
const AFTER_PART_LIKE = 1 << 2;
/// Whether we've parsed a non-element-backed pseudo-element (as in, an
/// `Impl::PseudoElement` thus not accounting for `::slotted` or
/// `::part`) already.
///
/// If so, then other pseudo-elements and most other selectors are
/// disallowed.
const AFTER_NON_ELEMENT_BACKED_PSEUDO = 1 << 3;
/// Whether we've parsed a non-stateful pseudo-element (again, as-in
/// `Impl::PseudoElement`) already. If so, then other pseudo-classes are
/// disallowed. If this flag is set, `AFTER_NON_ELEMENT_BACKED_PSEUDO` must be set
/// as well.
const AFTER_NON_STATEFUL_PSEUDO_ELEMENT = 1 << 4;
// Whether we've parsed a generated pseudo-element (as in ::before, ::after).
// If so then some other pseudo elements are disallowed (e.g. another generated pseudo)
// while others allowed (e.g. ::marker).
const AFTER_BEFORE_OR_AFTER_PSEUDO = 1 << 5;
/// Whether we are after any of the pseudo-like things.
const AFTER_PSEUDO = Self::AFTER_PART_LIKE.bits() | Self::AFTER_SLOTTED.bits() | Self::AFTER_NON_ELEMENT_BACKED_PSEUDO.bits() | Self::AFTER_BEFORE_OR_AFTER_PSEUDO.bits();
/// Whether we explicitly disallow combinators.
const DISALLOW_COMBINATORS = 1 << 6;
/// Whether we explicitly disallow pseudo-element-like things.
const DISALLOW_PSEUDOS = 1 << 7;
/// Whether we explicitly disallow relative selectors (i.e. `:has()`).
const DISALLOW_RELATIVE_SELECTOR = 1 << 8;
/// Whether we've parsed a pseudo-element which is in a pseudo-element tree (i.e. it is a
/// descendant pseudo of a pseudo-element root).
const IN_PSEUDO_ELEMENT_TREE = 1 << 9;
}
}
impl SelectorParsingState {
#[inline]
fn allows_slotted(self) -> bool {
!self.intersects(Self::AFTER_PSEUDO | Self::DISALLOW_PSEUDOS)
}
#[inline]
fn allows_part(self) -> bool {
!self.intersects(Self::AFTER_PSEUDO | Self::DISALLOW_PSEUDOS)
}
#[inline]
fn allows_non_functional_pseudo_classes(self) -> bool {
!self.intersects(Self::AFTER_SLOTTED | Self::AFTER_NON_STATEFUL_PSEUDO_ELEMENT)
}
#[inline]
fn allows_tree_structural_pseudo_classes(self) -> bool {
!self.intersects(Self::AFTER_PSEUDO) || self.intersects(Self::IN_PSEUDO_ELEMENT_TREE)
}
#[inline]
fn allows_combinators(self) -> bool {
!self.intersects(Self::DISALLOW_COMBINATORS)
}
#[inline]
fn allows_only_child_pseudo_class_only(self) -> bool {
self.intersects(Self::IN_PSEUDO_ELEMENT_TREE)
}
}
pub type SelectorParseError<'i> = ParseError<'i, SelectorParseErrorKind<'i>>;
#[derive(Clone, Debug, PartialEq)]
pub enum SelectorParseErrorKind<'i> {
NoQualifiedNameInAttributeSelector(Token<'i>),
EmptySelector,
DanglingCombinator,
NonCompoundSelector,
NonPseudoElementAfterSlotted,
InvalidPseudoElementAfterSlotted,
InvalidPseudoElementInsideWhere,
InvalidState,
UnexpectedTokenInAttributeSelector(Token<'i>),
PseudoElementExpectedColon(Token<'i>),
PseudoElementExpectedIdent(Token<'i>),
NoIdentForPseudo(Token<'i>),
UnsupportedPseudoClassOrElement(CowRcStr<'i>),
UnexpectedIdent(CowRcStr<'i>),
ExpectedNamespace(CowRcStr<'i>),
ExpectedBarInAttr(Token<'i>),
BadValueInAttr(Token<'i>),
InvalidQualNameInAttr(Token<'i>),
ExplicitNamespaceUnexpectedToken(Token<'i>),
ClassNeedsIdent(Token<'i>),
}
macro_rules! with_all_bounds {
(
[ $( $InSelector: tt )* ]
[ $( $CommonBounds: tt )* ]
[ $( $FromStr: tt )* ]
) => {
/// This trait allows to define the parser implementation in regards
/// of pseudo-classes/elements
///
/// NB: We need Clone so that we can derive(Clone) on struct with that
/// are parameterized on SelectorImpl. See
/// <https://github.com/rust-lang/rust/issues/26925>
pub trait SelectorImpl: Clone + Debug + Sized + 'static {
type ExtraMatchingData<'a>: Sized + Default;
type AttrValue: $($InSelector)*;
type Identifier: $($InSelector)* + PrecomputedHash;
type LocalName: $($InSelector)* + Borrow<Self::BorrowedLocalName> + PrecomputedHash;
type NamespaceUrl: $($CommonBounds)* + Default + Borrow<Self::BorrowedNamespaceUrl> + PrecomputedHash;
type NamespacePrefix: $($InSelector)* + Default;
type BorrowedNamespaceUrl: ?Sized + Eq;
type BorrowedLocalName: ?Sized + Eq;
/// non tree-structural pseudo-classes
/// (see: https://drafts.csswg.org/selectors/#structural-pseudos)
type NonTSPseudoClass: $($CommonBounds)* + NonTSPseudoClass<Impl = Self>;
/// pseudo-elements
type PseudoElement: $($CommonBounds)* + PseudoElement<Impl = Self>;
/// Whether attribute hashes should be collected for filtering
/// purposes.
fn should_collect_attr_hash(_name: &Self::LocalName) -> bool {
false
}
}
}
}
macro_rules! with_bounds {
( [ $( $CommonBounds: tt )* ] [ $( $FromStr: tt )* ]) => {
with_all_bounds! {
[$($CommonBounds)* + $($FromStr)* + ToCss]
[$($CommonBounds)*]
[$($FromStr)*]
}
}
}
with_bounds! {
[Clone + Eq]
[for<'a> From<&'a str>]
}
pub trait Parser<'i> {
type Impl: SelectorImpl;
type Error: 'i + From<SelectorParseErrorKind<'i>>;
/// Whether to parse the `::slotted()` pseudo-element.
fn parse_slotted(&self) -> bool {
false
}
/// Whether to parse the `::part()` pseudo-element.
fn parse_part(&self) -> bool {
false
}
/// Whether to parse the selector list of nth-child() or nth-last-child().
fn parse_nth_child_of(&self) -> bool {
false
}
/// Whether to parse `:is` and `:where` pseudo-classes.
fn parse_is_and_where(&self) -> bool {
false
}
/// Whether to parse the :has pseudo-class.
fn parse_has(&self) -> bool {
false
}
/// Whether to parse the '&' delimiter as a parent selector.
fn parse_parent_selector(&self) -> bool {
false
}
/// Whether the given function name is an alias for the `:is()` function.
fn is_is_alias(&self, _name: &str) -> bool {
false
}
/// Whether to parse the `:host` pseudo-class.
fn parse_host(&self) -> bool {
false
}
/// Whether to allow forgiving selector-list parsing.
fn allow_forgiving_selectors(&self) -> bool {
true
}
/// This function can return an "Err" pseudo-element in order to support CSS2.1
/// pseudo-elements.
fn parse_non_ts_pseudo_class(
&self,
location: SourceLocation,
name: CowRcStr<'i>,
) -> Result<<Self::Impl as SelectorImpl>::NonTSPseudoClass, ParseError<'i, Self::Error>> {
Err(
location.new_custom_error(SelectorParseErrorKind::UnsupportedPseudoClassOrElement(
name,
)),
)
}
fn parse_non_ts_functional_pseudo_class<'t>(
&self,
name: CowRcStr<'i>,
parser: &mut CssParser<'i, 't>,
_after_part: bool,
) -> Result<<Self::Impl as SelectorImpl>::NonTSPseudoClass, ParseError<'i, Self::Error>> {
Err(
parser.new_custom_error(SelectorParseErrorKind::UnsupportedPseudoClassOrElement(
name,
)),
)
}
fn parse_pseudo_element(
&self,
location: SourceLocation,
name: CowRcStr<'i>,
) -> Result<<Self::Impl as SelectorImpl>::PseudoElement, ParseError<'i, Self::Error>> {
Err(
location.new_custom_error(SelectorParseErrorKind::UnsupportedPseudoClassOrElement(
name,
)),
)
}
fn parse_functional_pseudo_element<'t>(
&self,
name: CowRcStr<'i>,
arguments: &mut CssParser<'i, 't>,
) -> Result<<Self::Impl as SelectorImpl>::PseudoElement, ParseError<'i, Self::Error>> {
Err(
arguments.new_custom_error(SelectorParseErrorKind::UnsupportedPseudoClassOrElement(
name,
)),
)
}
fn default_namespace(&self) -> Option<<Self::Impl as SelectorImpl>::NamespaceUrl> {
None
}
fn namespace_for_prefix(
&self,
_prefix: &<Self::Impl as SelectorImpl>::NamespacePrefix,
) -> Option<<Self::Impl as SelectorImpl>::NamespaceUrl> {
None
}
}
/// A selector list is a tagged pointer with either a single selector, or a ThinArc<()> of multiple
/// selectors.
#[derive(Clone, Eq, Debug, PartialEq)]
#[cfg_attr(feature = "to_shmem", derive(ToShmem))]
#[cfg_attr(feature = "to_shmem", shmem(no_bounds))]
pub struct SelectorList<Impl: SelectorImpl>(
#[cfg_attr(feature = "to_shmem", shmem(field_bound))]
ThinArcUnion<SpecificityAndFlags, Component<Impl>, (), Selector<Impl>>,
);
impl<Impl: SelectorImpl> SelectorList<Impl> {
/// See Arc::mark_as_intentionally_leaked
pub fn mark_as_intentionally_leaked(&self) {
if let ArcUnionBorrow::Second(ref list) = self.0.borrow() {
list.with_arc(|list| list.mark_as_intentionally_leaked())
}
self.slice()
.iter()
.for_each(|s| s.mark_as_intentionally_leaked())
}
pub fn from_one(selector: Selector<Impl>) -> Self {
#[cfg(debug_assertions)]
let selector_repr = unsafe { *(&selector as *const _ as *const usize) };
let list = Self(ThinArcUnion::from_first(selector.into_data()));
#[cfg(debug_assertions)]
debug_assert_eq!(
selector_repr,
unsafe { *(&list as *const _ as *const usize) },
"We rely on the same bit representation for the single selector variant"
);
list
}
pub fn from_iter(mut iter: impl ExactSizeIterator<Item = Selector<Impl>>) -> Self {
if iter.len() == 1 {
Self::from_one(iter.next().unwrap())
} else {
Self(ThinArcUnion::from_second(ThinArc::from_header_and_iter(
(),
iter,
)))
}
}
#[inline]
pub fn slice(&self) -> &[Selector<Impl>] {
match self.0.borrow() {
ArcUnionBorrow::First(..) => {
// SAFETY: see from_one.
let selector: &Selector<Impl> = unsafe { std::mem::transmute(self) };
std::slice::from_ref(selector)
},
ArcUnionBorrow::Second(list) => list.get().slice(),
}
}
#[inline]
pub fn len(&self) -> usize {
match self.0.borrow() {
ArcUnionBorrow::First(..) => 1,
ArcUnionBorrow::Second(list) => list.len(),
}
}
/// Returns the address on the heap of the ThinArc for memory reporting.
pub fn thin_arc_heap_ptr(&self) -> *const ::std::os::raw::c_void {
match self.0.borrow() {
ArcUnionBorrow::First(s) => s.with_arc(|a| a.heap_ptr()),
ArcUnionBorrow::Second(s) => s.with_arc(|a| a.heap_ptr()),
}
}
}
/// Uniquely identify a selector based on its components, which is behind ThinArc and
/// is therefore stable.
#[derive(Clone, Copy, Hash, Eq, PartialEq)]
pub struct SelectorKey(usize);
impl SelectorKey {
/// Create a new key based on the given selector.
pub fn new<Impl: SelectorImpl>(selector: &Selector<Impl>) -> Self {
Self(selector.0.slice().as_ptr() as usize)
}
}
/// Whether or not we're using forgiving parsing mode
#[derive(PartialEq)]
enum ForgivingParsing {
/// Discard the entire selector list upon encountering any invalid selector.
/// This is the default behavior for almost all of CSS.
No,
/// Ignore invalid selectors, potentially creating an empty selector list.
///
/// This is the error recovery mode of :is() and :where()
Yes,
}
/// Flag indicating if we're parsing relative selectors.
#[derive(Copy, Clone, PartialEq)]
pub enum ParseRelative {
/// Expect selectors to start with a combinator, assuming descendant combinator if not present.
ForHas,
/// Allow selectors to start with a combinator, prepending a parent selector if so. Do nothing
/// otherwise
ForNesting,
/// Allow selectors to start with a combinator, prepending a scope selector if so. Do nothing
/// otherwise
ForScope,
/// Treat as parse error if any selector begins with a combinator.
No,
}
impl<Impl: SelectorImpl> SelectorList<Impl> {
/// Returns a selector list with a single `:scope` selector (with specificity)
pub fn scope() -> Self {
Self::from_one(Selector::scope())
}
/// Returns a selector list with a single implicit `:scope` selector (no specificity)
pub fn implicit_scope() -> Self {
Self::from_one(Selector::implicit_scope())
}
/// Parse a comma-separated list of Selectors.
/// <https://drafts.csswg.org/selectors/#grouping>
///
/// Return the Selectors or Err if there is an invalid selector.
pub fn parse<'i, 't, P>(
parser: &P,
input: &mut CssParser<'i, 't>,
parse_relative: ParseRelative,
) -> Result<Self, ParseError<'i, P::Error>>
where
P: Parser<'i, Impl = Impl>,
{
Self::parse_with_state(
parser,
input,
SelectorParsingState::empty(),
ForgivingParsing::No,
parse_relative,
)
}
/// Same as `parse`, but disallow parsing of pseudo-elements.
pub fn parse_disallow_pseudo<'i, 't, P>(
parser: &P,
input: &mut CssParser<'i, 't>,
parse_relative: ParseRelative,
) -> Result<Self, ParseError<'i, P::Error>>
where
P: Parser<'i, Impl = Impl>,
{
Self::parse_with_state(
parser,
input,
SelectorParsingState::DISALLOW_PSEUDOS,
ForgivingParsing::No,
parse_relative,
)
}
pub fn parse_forgiving<'i, 't, P>(
parser: &P,
input: &mut CssParser<'i, 't>,
parse_relative: ParseRelative,
) -> Result<Self, ParseError<'i, P::Error>>
where
P: Parser<'i, Impl = Impl>,
{
Self::parse_with_state(
parser,
input,
SelectorParsingState::empty(),
ForgivingParsing::Yes,
parse_relative,
)
}
#[inline]
fn parse_with_state<'i, 't, P>(
parser: &P,
input: &mut CssParser<'i, 't>,
state: SelectorParsingState,
recovery: ForgivingParsing,
parse_relative: ParseRelative,
) -> Result<Self, ParseError<'i, P::Error>>
where
P: Parser<'i, Impl = Impl>,
{
let mut values = SmallVec::<[_; 4]>::new();
let forgiving = recovery == ForgivingParsing::Yes && parser.allow_forgiving_selectors();
loop {
let selector = input.parse_until_before(Delimiter::Comma, |input| {
let start = input.position();
let mut selector = parse_selector(parser, input, state, parse_relative);
if forgiving && (selector.is_err()
gitextract_8xmmvn70/
├── .github/
│ └── workflows/
│ ├── main.yml
│ ├── mirror-to-release-branch.yml
│ └── sync-upstream.yml
├── .gitignore
├── Cargo.toml
├── README.md
├── SYNCING.md
├── commit-from-merge.sh
├── commit-from-squashed.sh
├── malloc_size_of/
│ ├── Cargo.toml
│ ├── LICENSE-APACHE
│ ├── LICENSE-MIT
│ └── lib.rs
├── rustfmt.toml
├── selectors/
│ ├── CHANGES.md
│ ├── Cargo.toml
│ ├── README.md
│ ├── attr.rs
│ ├── bloom.rs
│ ├── build.rs
│ ├── builder.rs
│ ├── context.rs
│ ├── kleene_value.rs
│ ├── lib.rs
│ ├── matching.rs
│ ├── nth_index_cache.rs
│ ├── parser.rs
│ ├── relative_selector/
│ │ ├── cache.rs
│ │ ├── filter.rs
│ │ └── mod.rs
│ ├── sink.rs
│ ├── tree.rs
│ └── visitor.rs
├── servo_arc/
│ ├── Cargo.toml
│ ├── LICENSE-APACHE
│ ├── LICENSE-MIT
│ └── lib.rs
├── shell.nix
├── start-rebase.sh
├── style/
│ ├── Cargo.toml
│ ├── README.md
│ ├── applicable_declarations.rs
│ ├── author_styles.rs
│ ├── bezier.rs
│ ├── bloom.rs
│ ├── build.rs
│ ├── build_gecko.rs
│ ├── color/
│ │ ├── color_function.rs
│ │ ├── component.rs
│ │ ├── convert.rs
│ │ ├── mix.rs
│ │ ├── mod.rs
│ │ ├── parsing.rs
│ │ └── to_css.rs
│ ├── context.rs
│ ├── counter_style/
│ │ ├── mod.rs
│ │ ├── predefined.rs
│ │ └── update_predefined.py
│ ├── custom_properties.rs
│ ├── custom_properties_map.rs
│ ├── data.rs
│ ├── device/
│ │ ├── gecko.rs
│ │ ├── mod.rs
│ │ └── servo.rs
│ ├── dom.rs
│ ├── dom_apis.rs
│ ├── driver.rs
│ ├── error_reporting.rs
│ ├── font_face.rs
│ ├── font_metrics.rs
│ ├── gecko/
│ │ ├── anon_boxes.toml
│ │ ├── arc_types.rs
│ │ ├── conversions.rs
│ │ ├── data.rs
│ │ ├── media_features.rs
│ │ ├── mod.rs
│ │ ├── non_ts_pseudo_class_list.rs
│ │ ├── pseudo_element.rs
│ │ ├── pseudo_element_definition.mako.rs
│ │ ├── pseudo_elements.py
│ │ ├── pseudo_elements.toml
│ │ ├── regen_atoms.py
│ │ ├── restyle_damage.rs
│ │ ├── selector_parser.rs
│ │ ├── snapshot.rs
│ │ ├── snapshot_helpers.rs
│ │ ├── traversal.rs
│ │ ├── url.rs
│ │ └── wrapper.rs
│ ├── gecko_bindings/
│ │ ├── mod.rs
│ │ └── sugar/
│ │ ├── mod.rs
│ │ ├── ns_com_ptr.rs
│ │ ├── ns_compatibility.rs
│ │ ├── ns_style_auto_array.rs
│ │ ├── origin_flags.rs
│ │ ├── ownership.rs
│ │ └── refptr.rs
│ ├── gecko_string_cache/
│ │ ├── mod.rs
│ │ └── namespace.rs
│ ├── global_style_data.rs
│ ├── invalidation/
│ │ ├── element/
│ │ │ ├── document_state.rs
│ │ │ ├── element_wrapper.rs
│ │ │ ├── invalidation_map.rs
│ │ │ ├── invalidator.rs
│ │ │ ├── mod.rs
│ │ │ ├── relative_selector.rs
│ │ │ ├── restyle_hints.rs
│ │ │ └── state_and_attributes.rs
│ │ ├── media_queries.rs
│ │ ├── mod.rs
│ │ ├── stylesheets.rs
│ │ └── viewport_units.rs
│ ├── lib.rs
│ ├── logical_geometry.rs
│ ├── macros.rs
│ ├── matching.rs
│ ├── media_queries/
│ │ ├── media_list.rs
│ │ ├── media_query.rs
│ │ └── mod.rs
│ ├── parallel.rs
│ ├── parser.rs
│ ├── piecewise_linear.rs
│ ├── properties/
│ │ ├── build.py
│ │ ├── cascade.rs
│ │ ├── computed_value_flags.rs
│ │ ├── counted_unknown_properties.py
│ │ ├── counter_style_descriptors.toml
│ │ ├── data.py
│ │ ├── declaration_block.rs
│ │ ├── font_face_descriptors.toml
│ │ ├── gecko.mako.rs
│ │ ├── helpers/
│ │ │ └── animated_properties.mako.rs
│ │ ├── helpers.mako.rs
│ │ ├── longhands.toml
│ │ ├── mod.rs
│ │ ├── properties.html.mako
│ │ ├── properties.mako.rs
│ │ ├── property_descriptors.toml
│ │ ├── shorthands.rs
│ │ ├── shorthands.toml
│ │ ├── vendored_python/
│ │ │ ├── mako-1.3.10-py3-none-any.whl
│ │ │ ├── markupsafe/
│ │ │ │ ├── LICENSE.txt
│ │ │ │ └── __init__.py
│ │ │ └── toml-0.10.2-py2.py3-none-any.whl
│ │ └── view_transition_descriptors.toml
│ ├── properties_and_values/
│ │ ├── mod.rs
│ │ ├── registry.rs
│ │ ├── rule.rs
│ │ ├── syntax/
│ │ │ ├── ascii.rs
│ │ │ ├── data_type.rs
│ │ │ └── mod.rs
│ │ └── value.rs
│ ├── queries/
│ │ ├── condition.rs
│ │ ├── feature.rs
│ │ ├── feature_expression.rs
│ │ ├── mod.rs
│ │ └── values.rs
│ ├── rule_cache.rs
│ ├── rule_collector.rs
│ ├── rule_tree/
│ │ ├── core.rs
│ │ ├── level.rs
│ │ ├── map.rs
│ │ ├── mod.rs
│ │ ├── source.rs
│ │ └── unsafe_box.rs
│ ├── scoped_tls.rs
│ ├── selector_map.rs
│ ├── selector_parser.rs
│ ├── servo/
│ │ ├── animation.rs
│ │ ├── attr.rs
│ │ ├── encoding_support.rs
│ │ ├── media_features.rs
│ │ ├── mod.rs
│ │ ├── restyle_damage.rs
│ │ ├── selector_parser.rs
│ │ ├── shadow_parts.rs
│ │ └── url.rs
│ ├── shared_lock.rs
│ ├── sharing/
│ │ ├── checks.rs
│ │ └── mod.rs
│ ├── simple_buckets_map.rs
│ ├── str.rs
│ ├── style_adjuster.rs
│ ├── style_resolver.rs
│ ├── stylesheet_set.rs
│ ├── stylesheets/
│ │ ├── appearance_base_rule.rs
│ │ ├── container_rule.rs
│ │ ├── counter_style_rule.rs
│ │ ├── document_rule.rs
│ │ ├── font_face_rule.rs
│ │ ├── font_feature_values_rule.rs
│ │ ├── font_palette_values_rule.rs
│ │ ├── import_rule.rs
│ │ ├── keyframes_rule.rs
│ │ ├── layer_rule.rs
│ │ ├── loader.rs
│ │ ├── margin_rule.rs
│ │ ├── media_rule.rs
│ │ ├── mod.rs
│ │ ├── namespace_rule.rs
│ │ ├── nested_declarations_rule.rs
│ │ ├── origin.rs
│ │ ├── page_rule.rs
│ │ ├── position_try_rule.rs
│ │ ├── property_rule.rs
│ │ ├── rule_list.rs
│ │ ├── rule_parser.rs
│ │ ├── rules_iterator.rs
│ │ ├── scope_rule.rs
│ │ ├── starting_style_rule.rs
│ │ ├── style_rule.rs
│ │ ├── stylesheet.rs
│ │ ├── supports_rule.rs
│ │ └── view_transition_rule.rs
│ ├── stylist.rs
│ ├── thread_state.rs
│ ├── traversal.rs
│ ├── traversal_flags.rs
│ ├── typed_om/
│ │ ├── mod.rs
│ │ ├── numeric_declaration.rs
│ │ ├── numeric_values.rs
│ │ └── sum_value.rs
│ ├── use_counters/
│ │ └── mod.rs
│ └── values/
│ ├── animated/
│ │ ├── color.rs
│ │ ├── effects.rs
│ │ ├── font.rs
│ │ ├── grid.rs
│ │ ├── lists.rs
│ │ ├── mod.rs
│ │ ├── svg.rs
│ │ └── transform.rs
│ ├── computed/
│ │ ├── align.rs
│ │ ├── angle.rs
│ │ ├── animation.rs
│ │ ├── background.rs
│ │ ├── basic_shape.rs
│ │ ├── border.rs
│ │ ├── box.rs
│ │ ├── color.rs
│ │ ├── column.rs
│ │ ├── counters.rs
│ │ ├── easing.rs
│ │ ├── effects.rs
│ │ ├── flex.rs
│ │ ├── font.rs
│ │ ├── image.rs
│ │ ├── length.rs
│ │ ├── length_percentage.rs
│ │ ├── list.rs
│ │ ├── mod.rs
│ │ ├── motion.rs
│ │ ├── outline.rs
│ │ ├── page.rs
│ │ ├── percentage.rs
│ │ ├── position.rs
│ │ ├── ratio.rs
│ │ ├── rect.rs
│ │ ├── resolution.rs
│ │ ├── svg.rs
│ │ ├── table.rs
│ │ ├── text.rs
│ │ ├── time.rs
│ │ ├── transform.rs
│ │ ├── ui.rs
│ │ └── url.rs
│ ├── distance.rs
│ ├── generics/
│ │ ├── animation.rs
│ │ ├── background.rs
│ │ ├── basic_shape.rs
│ │ ├── border.rs
│ │ ├── box.rs
│ │ ├── calc.rs
│ │ ├── color.rs
│ │ ├── column.rs
│ │ ├── counters.rs
│ │ ├── easing.rs
│ │ ├── effects.rs
│ │ ├── flex.rs
│ │ ├── font.rs
│ │ ├── grid.rs
│ │ ├── image.rs
│ │ ├── length.rs
│ │ ├── mod.rs
│ │ ├── motion.rs
│ │ ├── page.rs
│ │ ├── position.rs
│ │ ├── ratio.rs
│ │ ├── rect.rs
│ │ ├── size.rs
│ │ ├── svg.rs
│ │ ├── text.rs
│ │ ├── transform.rs
│ │ ├── ui.rs
│ │ └── url.rs
│ ├── mod.rs
│ ├── resolved/
│ │ ├── animation.rs
│ │ ├── color.rs
│ │ ├── counters.rs
│ │ └── mod.rs
│ └── specified/
│ ├── align.rs
│ ├── angle.rs
│ ├── animation.rs
│ ├── background.rs
│ ├── basic_shape.rs
│ ├── border.rs
│ ├── box.rs
│ ├── calc.rs
│ ├── color.rs
│ ├── column.rs
│ ├── counters.rs
│ ├── easing.rs
│ ├── effects.rs
│ ├── flex.rs
│ ├── font.rs
│ ├── grid.rs
│ ├── image.rs
│ ├── intersection_observer.rs
│ ├── length.rs
│ ├── list.rs
│ ├── mod.rs
│ ├── motion.rs
│ ├── outline.rs
│ ├── page.rs
│ ├── percentage.rs
│ ├── position.rs
│ ├── ratio.rs
│ ├── rect.rs
│ ├── resolution.rs
│ ├── source_size_list.rs
│ ├── svg.rs
│ ├── svg_path.rs
│ ├── table.rs
│ ├── text.rs
│ ├── time.rs
│ ├── transform.rs
│ ├── ui.rs
│ └── url.rs
├── style.paths
├── style_derive/
│ ├── Cargo.toml
│ ├── animate.rs
│ ├── cg.rs
│ ├── compute_squared_distance.rs
│ ├── lib.rs
│ ├── parse.rs
│ ├── specified_value_info.rs
│ ├── to_animated_value.rs
│ ├── to_animated_zero.rs
│ ├── to_computed_value.rs
│ ├── to_css.rs
│ ├── to_resolved_value.rs
│ └── to_typed.rs
├── style_traits/
│ ├── Cargo.toml
│ ├── arc_slice.rs
│ ├── dom.rs
│ ├── lib.rs
│ ├── owned_slice.rs
│ ├── owned_str.rs
│ ├── specified_value_info.rs
│ └── values.rs
├── stylo_atoms/
│ ├── Cargo.toml
│ ├── build.rs
│ ├── lib.rs
│ ├── predefined_counter_styles.rs
│ └── static_atoms.txt
├── stylo_dom/
│ ├── Cargo.toml
│ └── lib.rs
├── stylo_static_prefs/
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
├── sync.sh
├── to_shmem/
│ ├── Cargo.toml
│ └── lib.rs
└── to_shmem_derive/
├── Cargo.toml
├── lib.rs
├── to_shmem.rs
└── util.rs
Showing preview only (716K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (8600 symbols across 306 files)
FILE: malloc_size_of/lib.rs
type VoidPtrToSizeFn (line 57) | type VoidPtrToSizeFn = unsafe extern "C" fn(ptr: *const c_void) -> usize;
type VoidPtrToBoolFnMut (line 60) | type VoidPtrToBoolFnMut = dyn FnMut(*const c_void) -> bool;
type MallocSizeOfOps (line 63) | pub struct MallocSizeOfOps {
method new (line 80) | pub fn new(
method is_empty (line 94) | fn is_empty<T: ?Sized>(ptr: *const T) -> bool {
method malloc_size_of (line 107) | pub unsafe fn malloc_size_of<T: ?Sized>(&self, ptr: *const T) -> usize {
method has_malloc_enclosing_size_of (line 116) | pub fn has_malloc_enclosing_size_of(&self) -> bool {
method malloc_enclosing_size_of (line 122) | pub unsafe fn malloc_enclosing_size_of<T>(&self, ptr: *const T) -> usi...
method have_seen_ptr (line 128) | pub fn have_seen_ptr<T>(&mut self, ptr: *const T) -> bool {
type MallocSizeOf (line 139) | pub trait MallocSizeOf {
method size_of (line 142) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
method size_of (line 186) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 192) | fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 205) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 211) | fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 221) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 232) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 244) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 250) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 260) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 269) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 275) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 284) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 293) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 309) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 336) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 360) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 385) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 494) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 506) | fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 557) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 563) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 573) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 579) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 585) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 591) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 597) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 606) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 612) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 623) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 644) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 650) | fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 746) | fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 752) | fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 759) | fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
method size_of (line 766) | fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
type MallocShallowSizeOf (line 146) | pub trait MallocShallowSizeOf {
method shallow_size_of (line 151) | fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
method shallow_size_of (line 199) | fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method shallow_size_of (line 303) | fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method shallow_size_of (line 319) | fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method shallow_size_of (line 346) | fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method shallow_size_of (line 370) | fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method shallow_size_of (line 478) | fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
type MallocUnconditionalSizeOf (line 157) | pub trait MallocUnconditionalSizeOf {
method unconditional_size_of (line 160) | fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
method unconditional_size_of (line 525) | fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method unconditional_size_of (line 662) | fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method unconditional_size_of (line 683) | fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
method unconditional_size_of (line 704) | fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
type MallocUnconditionalShallowSizeOf (line 164) | pub trait MallocUnconditionalShallowSizeOf {
method unconditional_shallow_size_of (line 166) | fn unconditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> ...
method unconditional_shallow_size_of (line 519) | fn unconditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> ...
type MallocConditionalSizeOf (line 172) | pub trait MallocConditionalSizeOf {
method conditional_size_of (line 176) | fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
method conditional_size_of (line 541) | fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
type MallocConditionalShallowSizeOf (line 180) | pub trait MallocConditionalShallowSizeOf {
method conditional_shallow_size_of (line 182) | fn conditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> us...
method conditional_shallow_size_of (line 531) | fn conditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> us...
type Measurable (line 826) | pub struct Measurable<T: MallocSizeOf>(pub T);
type Target (line 829) | type Target = T;
method deref (line 831) | fn deref(&self) -> &T {
method deref_mut (line 837) | fn deref_mut(&mut self) -> &mut T {
FILE: selectors/attr.rs
type AttrSelectorWithOptionalNamespace (line 15) | pub struct AttrSelectorWithOptionalNamespace<Impl: SelectorImpl> {
function namespace (line 26) | pub fn namespace(&self) -> Option<NamespaceConstraint<&Impl::NamespaceUr...
type NamespaceConstraint (line 36) | pub enum NamespaceConstraint<NamespaceUrl> {
type ParsedAttrSelectorOperation (line 45) | pub enum ParsedAttrSelectorOperation<AttrValue> {
type AttrSelectorOperation (line 55) | pub enum AttrSelectorOperation<AttrValue> {
function eval_str (line 65) | pub fn eval_str(&self, element_attr_value: &str) -> bool
type AttrSelectorOperator (line 82) | pub enum AttrSelectorOperator {
method eval_str (line 110) | pub fn eval_str(
method to_css (line 92) | fn to_css<W>(&self, dest: &mut W) -> fmt::Result
type ParsedCaseSensitivity (line 148) | pub enum ParsedCaseSensitivity {
type CaseSensitivity (line 160) | pub enum CaseSensitivity {
method eq (line 166) | pub fn eq(self, a: &[u8], b: &[u8]) -> bool {
method contains (line 173) | pub fn contains(self, haystack: &str, needle: &str) -> bool {
FILE: selectors/bloom.rs
constant BLOOM_HASH_MASK (line 12) | pub const BLOOM_HASH_MASK: u32 = 0x00ffffff;
constant KEY_SIZE (line 13) | const KEY_SIZE: usize = 12;
constant ARRAY_SIZE (line 15) | const ARRAY_SIZE: usize = 1 << KEY_SIZE;
constant KEY_MASK (line 16) | const KEY_MASK: u32 = (1 << KEY_SIZE) - 1;
type BloomFilter (line 19) | pub type BloomFilter = CountingBloomFilter<BloomStorageU8>;
type CountingBloomFilter (line 68) | pub struct CountingBloomFilter<S>
function new (line 81) | pub fn new() -> Self {
function clear (line 86) | pub fn clear(&mut self) {
function is_zeroed (line 93) | pub fn is_zeroed(&self) -> bool {
function is_zeroed (line 98) | pub fn is_zeroed(&self) -> bool {
function insert_hash (line 104) | pub fn insert_hash(&mut self, hash: u32) {
function remove_hash (line 111) | pub fn remove_hash(&mut self, hash: u32) {
function might_contain_hash (line 120) | pub fn might_contain_hash(&self, hash: u32) -> bool {
method fmt (line 129) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
type BloomStorage (line 140) | pub trait BloomStorage: Clone + Default {
method slot_is_empty (line 141) | fn slot_is_empty(&self, index: usize) -> bool;
method adjust_slot (line 142) | fn adjust_slot(&mut self, index: usize, increment: bool);
method is_zeroed (line 143) | fn is_zeroed(&self) -> bool;
method first_slot_is_empty (line 146) | fn first_slot_is_empty(&self, hash: u32) -> bool {
method second_slot_is_empty (line 151) | fn second_slot_is_empty(&self, hash: u32) -> bool {
method adjust_first_slot (line 156) | fn adjust_first_slot(&mut self, hash: u32, increment: bool) {
method adjust_second_slot (line 161) | fn adjust_second_slot(&mut self, hash: u32, increment: bool) {
method first_slot_index (line 166) | fn first_slot_index(hash: u32) -> usize {
method second_slot_index (line 171) | fn second_slot_index(hash: u32) -> usize {
method adjust_slot (line 183) | fn adjust_slot(&mut self, index: usize, increment: bool) {
method slot_is_empty (line 196) | fn slot_is_empty(&self, index: usize) -> bool {
method is_zeroed (line 201) | fn is_zeroed(&self) -> bool {
method adjust_slot (line 229) | fn adjust_slot(&mut self, index: usize, increment: bool) {
method slot_is_empty (line 247) | fn slot_is_empty(&self, index: usize) -> bool {
method is_zeroed (line 253) | fn is_zeroed(&self) -> bool {
type BloomStorageU8 (line 177) | pub struct BloomStorageU8 {
method default (line 207) | fn default() -> Self {
method clone (line 215) | fn clone(&self) -> Self {
type BloomStorageBool (line 223) | pub struct BloomStorageBool {
method default (line 259) | fn default() -> Self {
method clone (line 267) | fn clone(&self) -> Self {
function hash1 (line 275) | fn hash1(hash: u32) -> u32 {
function hash2 (line 280) | fn hash2(hash: u32) -> u32 {
function create_and_insert_some_stuff (line 285) | fn create_and_insert_some_stuff() {
type HashGenerator (line 348) | struct HashGenerator(u32);
method next (line 351) | fn next(&mut self) -> u32 {
function create_insert_1000_remove_100_lookup_100 (line 366) | fn create_insert_1000_remove_100_lookup_100(b: &mut test::Bencher) {
function might_contain_10 (line 384) | fn might_contain_10(b: &mut test::Bencher) {
function clear (line 395) | fn clear(b: &mut test::Bencher) {
function insert_10 (line 401) | fn insert_10(b: &mut test::Bencher) {
function remove_10 (line 412) | fn remove_10(b: &mut test::Bencher) {
FILE: selectors/build.rs
function main (line 12) | fn main() {
FILE: selectors/builder.rs
type SelectorBuilder (line 48) | pub struct SelectorBuilder<Impl: SelectorImpl> {
function push (line 58) | fn push(&mut self, value: Component<Impl>) {
function push_simple_selector (line 66) | pub fn push_simple_selector(&mut self, ss: Component<Impl>) {
function push_combinator (line 74) | pub fn push_combinator(&mut self, c: Combinator) {
function reverse_last_compound (line 80) | fn reverse_last_compound(&mut self) {
function has_combinators (line 87) | pub fn has_combinators(&self) -> bool {
function build (line 93) | pub fn build(&mut self, parse_relative: ParseRelative) -> SelectorData<I...
function build_with_specificity_and_flags (line 105) | pub(crate) fn build_with_specificity_and_flags(
method default (line 155) | fn default() -> Self {
type ExactChain (line 165) | struct ExactChain<A, B>(A, B);
method len (line 172) | fn len(&self) -> usize {
type Item (line 182) | type Item = Item;
method next (line 185) | fn next(&mut self) -> Option<Self::Item> {
method size_hint (line 189) | fn size_hint(&self) -> (usize, Option<usize>) {
type SelectorFlags (line 198) | pub(crate) struct SelectorFlags(u8);
method fmt (line 212) | fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
method forbidden_for_nesting (line 228) | pub(crate) fn forbidden_for_nesting() -> Self {
type SpecificityAndFlags (line 235) | pub struct SpecificityAndFlags {
constant MAX_10BIT (line 243) | const MAX_10BIT: u32 = (1u32 << 10) - 1;
type Specificity (line 246) | pub(crate) struct Specificity {
method single_class_like (line 255) | pub fn single_class_like() -> Self {
method from (line 266) | fn from(value: u32) -> Specificity {
function from (line 278) | fn from(specificity: Specificity) -> u32 {
function specificity_and_flags (line 285) | fn specificity_and_flags<Impl>(
function selector_list_specificity_and_flags (line 428) | pub(crate) fn selector_list_specificity_and_flags<'a, Impl: SelectorImpl>(
function relative_selector_list_specificity_and_flags (line 450) | pub(crate) fn relative_selector_list_specificity_and_flags<Impl: Selecto...
FILE: selectors/context.rs
type MatchingMode (line 18) | pub enum MatchingMode {
type VisitedHandlingMode (line 38) | pub enum VisitedHandlingMode {
method matches_visited (line 55) | pub fn matches_visited(&self) -> bool {
method matches_unvisited (line 64) | pub fn matches_unvisited(&self) -> bool {
type NeedsSelectorFlags (line 76) | pub enum NeedsSelectorFlags {
type MatchingForInvalidation (line 83) | pub enum MatchingForInvalidation {
method is_for_invalidation (line 91) | pub fn is_for_invalidation(&self) -> bool {
type QuirksMode (line 100) | pub enum QuirksMode {
method classes_and_ids_case_sensitivity (line 111) | pub fn classes_and_ids_case_sensitivity(self) -> CaseSensitivity {
type SelectorCaches (line 121) | pub struct SelectorCaches {
type MatchingContext (line 133) | pub struct MatchingContext<'a, Impl>
function new (line 200) | pub fn new(
function new_for_revalidation (line 221) | pub fn new_for_revalidation(
function new_for_visited (line 242) | pub fn new_for_visited(
function new_internal (line 263) | fn new_internal(
function nth_index_cache (line 297) | pub fn nth_index_cache(
function is_nested (line 310) | pub fn is_nested(&self) -> bool {
function in_negation (line 316) | pub fn in_negation(&self) -> bool {
function quirks_mode (line 322) | pub fn quirks_mode(&self) -> QuirksMode {
function matching_mode (line 328) | pub fn matching_mode(&self) -> MatchingMode {
function needs_selector_flags (line 334) | pub fn needs_selector_flags(&self) -> bool {
function matching_for_invalidation (line 340) | pub fn matching_for_invalidation(&self) -> bool {
function matching_for_revalidation (line 346) | pub fn matching_for_revalidation(&self) -> bool {
function matching_for_invalidation_comparison (line 352) | pub fn matching_for_invalidation_comparison(&self) -> Option<bool> {
function for_invalidation_comparison (line 362) | pub fn for_invalidation_comparison<F, R>(&mut self, f: F) -> R
function classes_and_ids_case_sensitivity (line 379) | pub fn classes_and_ids_case_sensitivity(&self) -> CaseSensitivity {
function nest (line 385) | pub fn nest<F, R>(&mut self, f: F) -> R
function nest_for_negation (line 398) | pub fn nest_for_negation<F, R>(&mut self, f: F) -> R
function visited_handling (line 410) | pub fn visited_handling(&self) -> VisitedHandlingMode {
function with_featureless (line 416) | pub fn with_featureless<F, R>(&mut self, featureless: bool, f: F) -> R
function featureless (line 431) | pub fn featureless(&self) -> bool {
function with_visited_handling_mode (line 437) | pub fn with_visited_handling_mode<F, R>(
function with_shadow_host (line 455) | pub fn with_shadow_host<F, E, R>(&mut self, host: Option<E>, f: F) -> R
function shadow_host (line 470) | pub fn shadow_host(&self) -> Option<OpaqueElement> {
function nest_for_relative_selector (line 477) | pub fn nest_for_relative_selector<F, R>(&mut self, anchor: OpaqueElement...
function nest_for_scope (line 493) | pub fn nest_for_scope<F, R>(&mut self, scope: Option<OpaqueElement>, f: ...
function nest_for_scope_condition (line 507) | pub fn nest_for_scope_condition<F, R>(&mut self, scope: Option<OpaqueEle...
function relative_selector_anchor (line 522) | pub fn relative_selector_anchor(&self) -> Option<OpaqueElement> {
FILE: selectors/kleene_value.rs
type KleeneValue (line 9) | pub enum KleeneValue {
method from (line 19) | fn from(b: bool) -> Self {
method to_bool (line 31) | pub fn to_bool(self, unknown: bool) -> bool {
method any (line 43) | pub fn any<T>(iter: impl Iterator<Item = T>, f: impl FnMut(T) -> Self)...
method any_false (line 51) | pub fn any_false<T>(iter: impl Iterator<Item = T>, f: impl FnMut(T) ->...
method any_value (line 56) | fn any_value<T>(
type Output (line 80) | type Output = Self;
method not (line 82) | fn not(self) -> Self {
type Output (line 93) | type Output = Self;
method bitand (line 95) | fn bitand(self, other: Self) -> Self {
type Output (line 108) | type Output = Self;
method bitor (line 110) | fn bitor(self, other: Self) -> Self {
method bitor_assign (line 122) | fn bitor_assign(&mut self, other: Self) {
method bitand_assign (line 128) | fn bitand_assign(&mut self, other: Self) {
FILE: selectors/matching.rs
method for_self (line 92) | pub fn for_self(self) -> ElementSelectorFlags {
method for_parent (line 101) | pub fn for_parent(self) -> ElementSelectorFlags {
type LocalMatchingContext (line 111) | struct LocalMatchingContext<'a, 'b: 'a, Impl: SelectorImpl> {
function matches_selector_list (line 118) | pub fn matches_selector_list<E>(
function selector_may_match (line 141) | pub fn selector_may_match(hashes: &AncestorHashes, bf: &BloomFilter) -> ...
type SelectorMatchingResult (line 225) | enum SelectorMatchingResult {
method from (line 235) | fn from(value: SelectorMatchingResult) -> Self {
function matches_selector (line 255) | pub fn matches_selector<E>(
function matches_selector_kleene (line 279) | pub fn matches_selector_kleene<E>(
type CompoundSelectorMatchingResult (line 311) | pub enum CompoundSelectorMatchingResult {
function complex_selector_early_reject_by_local_name (line 321) | fn complex_selector_early_reject_by_local_name<E: Element>(
function early_reject_by_local_name (line 332) | pub fn early_reject_by_local_name<E: Element>(
function matches_compound_selector_from (line 359) | pub fn matches_compound_selector_from<E>(
function matches_complex_selector (line 440) | fn matches_complex_selector<E>(
function matches_complex_selector_list (line 492) | fn matches_complex_selector_list<E: Element>(
function matches_relative_selector (line 503) | fn matches_relative_selector<E: Element>(
function relative_selector_match_early (line 593) | fn relative_selector_match_early<E: Element>(
function match_relative_selectors (line 623) | fn match_relative_selectors<E: Element>(
function do_match_relative_selectors (line 655) | fn do_match_relative_selectors<E: Element>(
function matches_relative_selector_subtree (line 702) | fn matches_relative_selector_subtree<E: Element>(
function hover_and_active_quirk_applies (line 733) | fn hover_and_active_quirk_applies<Impl: SelectorImpl>(
type SubjectOrPseudoElement (line 759) | enum SubjectOrPseudoElement {
function host_for_part (line 764) | fn host_for_part<E>(element: &E, context: &MatchingContext<E::Impl>) -> ...
function assigned_slot (line 782) | fn assigned_slot<E>(element: &E, context: &MatchingContext<E::Impl>) -> ...
type NextElement (line 797) | struct NextElement<E> {
function new (line 804) | fn new(next_element: Option<E>, featureless: bool) -> Self {
function next_element_for_combinator (line 813) | fn next_element_for_combinator<E>(
function matches_complex_selector_internal (line 845) | fn matches_complex_selector_internal<E>(
function matches_local_name (line 1000) | fn matches_local_name<E>(element: &E, local_name: &LocalName<E::Impl>) -...
function matches_part (line 1008) | fn matches_part<E>(
function matches_host (line 1054) | fn matches_host<E>(
function matches_slotted (line 1080) | fn matches_slotted<E>(
function matches_rare_attribute_selector (line 1096) | fn matches_rare_attribute_selector<E>(
function compound_matches_featureless_host (line 1132) | pub(crate) fn compound_matches_featureless_host<Impl: SelectorImpl>(
function matches_compound_selector (line 1192) | fn matches_compound_selector<E>(
function matches_simple_selector (line 1225) | fn matches_simple_selector<E>(
function select_name (line 1364) | pub fn select_name<'a, E: Element, T: PartialEq>(
function to_unconditional_case_sensitivity (line 1377) | pub fn to_unconditional_case_sensitivity<'a, E: Element>(
function matches_generic_nth_child (line 1396) | fn matches_generic_nth_child<E>(
function nth_child_index (line 1525) | fn nth_child_index<E>(
FILE: selectors/nth_index_cache.rs
type NthIndexCache (line 16) | pub struct NthIndexCache {
method get (line 27) | pub fn get<Impl: SelectorImpl>(
type SelectorListCacheKey (line 56) | struct SelectorListCacheKey(usize);
method new (line 61) | fn new<Impl: SelectorImpl>(selectors: &[Selector<Impl>]) -> Self {
type NthIndexOfSelectorsCaches (line 68) | pub struct NthIndexOfSelectorsCaches(FxHashMap<SelectorListCacheKey, Nth...
method lookup (line 73) | pub fn lookup<Impl: SelectorImpl>(
type NthIndexCacheInner (line 85) | pub struct NthIndexCacheInner(FxHashMap<OpaqueElement, i32>);
method lookup (line 89) | pub fn lookup(&mut self, el: OpaqueElement) -> Option<i32> {
method insert (line 94) | pub fn insert(&mut self, element: OpaqueElement, index: i32) {
method is_empty (line 99) | pub fn is_empty(&self) -> bool {
FILE: selectors/parser.rs
type PseudoElement (line 35) | pub trait PseudoElement: Sized + ToCss {
method accepts_state_pseudo_classes (line 41) | fn accepts_state_pseudo_classes(&self) -> bool {
method valid_after_slotted (line 46) | fn valid_after_slotted(&self) -> bool {
method valid_after_before_or_after (line 51) | fn valid_after_before_or_after(&self) -> bool {
method parses_as_element_backed (line 57) | fn parses_as_element_backed(&self) -> bool {
method is_before_or_after (line 64) | fn is_before_or_after(&self) -> bool {
method specificity_count (line 69) | fn specificity_count(&self) -> u32 {
method is_in_pseudo_element_tree (line 76) | fn is_in_pseudo_element_tree(&self) -> bool {
type Impl (line 3789) | type Impl = DummySelectorImpl;
method accepts_state_pseudo_classes (line 3791) | fn accepts_state_pseudo_classes(&self) -> bool {
method valid_after_slotted (line 3795) | fn valid_after_slotted(&self) -> bool {
method valid_after_before_or_after (line 3799) | fn valid_after_before_or_after(&self) -> bool {
method is_before_or_after (line 3803) | fn is_before_or_after(&self) -> bool {
method parses_as_element_backed (line 3807) | fn parses_as_element_backed(&self) -> bool {
type NonTSPseudoClass (line 82) | pub trait NonTSPseudoClass: Sized + ToCss {
method is_active_or_hover (line 87) | fn is_active_or_hover(&self) -> bool;
method is_user_action_state (line 92) | fn is_user_action_state(&self) -> bool;
method visit (line 94) | fn visit<V>(&self, _visitor: &mut V) -> bool
function to_ascii_lowercase (line 104) | fn to_ascii_lowercase(s: &str) -> Cow<'_, str> {
method allows_slotted (line 169) | fn allows_slotted(self) -> bool {
method allows_part (line 174) | fn allows_part(self) -> bool {
method allows_non_functional_pseudo_classes (line 179) | fn allows_non_functional_pseudo_classes(self) -> bool {
method allows_tree_structural_pseudo_classes (line 184) | fn allows_tree_structural_pseudo_classes(self) -> bool {
method allows_combinators (line 189) | fn allows_combinators(self) -> bool {
method allows_only_child_pseudo_class_only (line 194) | fn allows_only_child_pseudo_class_only(self) -> bool {
type SelectorParseError (line 199) | pub type SelectorParseError<'i> = ParseError<'i, SelectorParseErrorKind<...
type SelectorParseErrorKind (line 202) | pub enum SelectorParseErrorKind<'i> {
type Parser (line 278) | pub trait Parser<'i> {
method parse_slotted (line 283) | fn parse_slotted(&self) -> bool {
method parse_part (line 288) | fn parse_part(&self) -> bool {
method parse_nth_child_of (line 293) | fn parse_nth_child_of(&self) -> bool {
method parse_is_and_where (line 298) | fn parse_is_and_where(&self) -> bool {
method parse_has (line 303) | fn parse_has(&self) -> bool {
method parse_parent_selector (line 308) | fn parse_parent_selector(&self) -> bool {
method is_is_alias (line 313) | fn is_is_alias(&self, _name: &str) -> bool {
method parse_host (line 318) | fn parse_host(&self) -> bool {
method allow_forgiving_selectors (line 323) | fn allow_forgiving_selectors(&self) -> bool {
method parse_non_ts_pseudo_class (line 329) | fn parse_non_ts_pseudo_class(
method parse_non_ts_functional_pseudo_class (line 341) | fn parse_non_ts_functional_pseudo_class<'t>(
method parse_pseudo_element (line 354) | fn parse_pseudo_element(
method parse_functional_pseudo_element (line 366) | fn parse_functional_pseudo_element<'t>(
method default_namespace (line 378) | fn default_namespace(&self) -> Option<<Self::Impl as SelectorImpl>::Na...
method namespace_for_prefix (line 382) | fn namespace_for_prefix(
type SelectorList (line 395) | pub struct SelectorList<Impl: SelectorImpl>(
function mark_as_intentionally_leaked (line 402) | pub fn mark_as_intentionally_leaked(&self) {
function from_one (line 411) | pub fn from_one(selector: Selector<Impl>) -> Self {
function from_iter (line 424) | pub fn from_iter(mut iter: impl ExactSizeIterator<Item = Selector<Impl>>...
function slice (line 436) | pub fn slice(&self) -> &[Selector<Impl>] {
function len (line 448) | pub fn len(&self) -> usize {
function thin_arc_heap_ptr (line 456) | pub fn thin_arc_heap_ptr(&self) -> *const ::std::os::raw::c_void {
type SelectorKey (line 467) | pub struct SelectorKey(usize);
method new (line 471) | pub fn new<Impl: SelectorImpl>(selector: &Selector<Impl>) -> Self {
type ForgivingParsing (line 478) | enum ForgivingParsing {
type ParseRelative (line 490) | pub enum ParseRelative {
function scope (line 505) | pub fn scope() -> Self {
function implicit_scope (line 509) | pub fn implicit_scope() -> Self {
function parse (line 517) | pub fn parse<'i, 't, P>(
function parse_disallow_pseudo (line 535) | pub fn parse_disallow_pseudo<'i, 't, P>(
function parse_forgiving (line 552) | pub fn parse_forgiving<'i, 't, P>(
function parse_with_state (line 570) | fn parse_with_state<'i, 't, P>(
function replace_parent_selector (line 605) | pub fn replace_parent_selector(&self, parent: &SelectorList<Impl>) -> Se...
function from_vec (line 615) | pub(crate) fn from_vec(v: Vec<Selector<Impl>>) -> Self {
function parse_inner_compound_selector (line 621) | fn parse_inner_compound_selector<'i, 't, P, Impl>(
type AncestorHashes (line 654) | pub struct AncestorHashes {
method new (line 761) | pub fn new<Impl: SelectorImpl>(selector: &Selector<Impl>, quirks_mode:...
method fourth_hash (line 783) | pub fn fourth_hash(&self) -> u32 {
function collect_selector_hashes (line 658) | pub(crate) fn collect_selector_hashes<'a, Impl: SelectorImpl, Iter>(
function collect_ancestor_hashes (line 749) | fn collect_ancestor_hashes<Impl: SelectorImpl>(
function namespace_empty_string (line 791) | pub fn namespace_empty_string<Impl: SelectorImpl>() -> Impl::NamespaceUrl {
type SelectorData (line 796) | pub(super) type SelectorData<Impl> = ThinArc<SpecificityAndFlags, Compon...
type MatchesFeaturelessHost (line 801) | pub enum MatchesFeaturelessHost {
method may_match (line 813) | pub fn may_match(self) -> bool {
type Selector (line 836) | pub struct Selector<Impl: SelectorImpl>(
function mark_as_intentionally_leaked (line 842) | pub fn mark_as_intentionally_leaked(&self) {
function scope (line 846) | fn scope() -> Self {
function implicit_scope (line 857) | fn implicit_scope() -> Self {
function specificity (line 868) | pub fn specificity(&self) -> u32 {
function flags (line 873) | pub(crate) fn flags(&self) -> SelectorFlags {
function has_pseudo_element (line 878) | pub fn has_pseudo_element(&self) -> bool {
function has_parent_selector (line 883) | pub fn has_parent_selector(&self) -> bool {
function has_scope_selector (line 888) | pub fn has_scope_selector(&self) -> bool {
function is_slotted (line 893) | pub fn is_slotted(&self) -> bool {
function is_part (line 898) | pub fn is_part(&self) -> bool {
function parts (line 903) | pub fn parts(&self) -> Option<&[Impl::Identifier]> {
function pseudo_element (line 928) | pub fn pseudo_element(&self) -> Option<&Impl::PseudoElement> {
function pseudo_elements (line 944) | pub fn pseudo_elements(&self) -> SmallVec<[&Impl::PseudoElement; 3]> {
function is_universal (line 973) | pub fn is_universal(&self) -> bool {
function matches_featureless_host (line 988) | pub fn matches_featureless_host(
function iter (line 1025) | pub fn iter(&self) -> SelectorIter<'_, Impl> {
function iter_skip_relative_selector_anchor (line 1034) | pub fn iter_skip_relative_selector_anchor(&self) -> SelectorIter<'_, Imp...
function iter_from (line 1059) | pub fn iter_from(&self, offset: usize) -> SelectorIter<'_, Impl> {
function combinator_at_match_order (line 1070) | pub fn combinator_at_match_order(&self, index: usize) -> Combinator {
function iter_raw_match_order (line 1083) | pub fn iter_raw_match_order(&self) -> slice::Iter<'_, Component<Impl>> {
function combinator_at_parse_order (line 1090) | pub fn combinator_at_parse_order(&self, index: usize) -> Combinator {
function iter_raw_parse_order_from (line 1104) | pub fn iter_raw_parse_order_from(
function from_vec (line 1113) | pub(crate) fn from_vec(
function into_data (line 1131) | fn into_data(self) -> SelectorData<Impl> {
function replace_parent_selector (line 1135) | pub fn replace_parent_selector(&self, parent: &SelectorList<Impl>) -> Se...
function len (line 1355) | pub fn len(&self) -> usize {
function thin_arc_heap_ptr (line 1360) | pub fn thin_arc_heap_ptr(&self) -> *const ::std::os::raw::c_void {
function visit (line 1382) | pub fn visit<V>(&self, visitor: &mut V) -> bool
function parse (line 1410) | pub fn parse<'i, 't, P>(
function new_invalid (line 1425) | pub fn new_invalid(s: &str) -> Self {
function is_rightmost (line 1470) | pub fn is_rightmost(&self, offset: usize) -> bool {
type SelectorIter (line 1482) | pub struct SelectorIter<'a, Impl: 'a + SelectorImpl> {
function next_sequence (line 1491) | pub fn next_sequence(&mut self) -> Option<Combinator> {
function matches_for_stateless_pseudo_element (line 1496) | pub(crate) fn matches_for_stateless_pseudo_element(&mut self) -> bool {
function matches_for_stateless_pseudo_element_internal (line 1507) | fn matches_for_stateless_pseudo_element_internal(&mut self, first: &Comp...
function selector_length (line 1524) | pub fn selector_length(&self) -> usize {
type Item (line 1530) | type Item = &'a Component<Impl>;
method next (line 1533) | fn next(&mut self) -> Option<Self::Item> {
function fmt (line 1549) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
type CombinatorIter (line 1559) | struct CombinatorIter<'a, Impl: 'a + SelectorImpl>(SelectorIter<'a, Impl>);
function new (line 1561) | fn new(inner: SelectorIter<'a, Impl>) -> Self {
function consume_non_combinators (line 1567) | fn consume_non_combinators(&mut self) {
type Item (line 1573) | type Item = Combinator;
method next (line 1574) | fn next(&mut self) -> Option<Self::Item> {
type AncestorIter (line 1582) | struct AncestorIter<'a, Impl: 'a + SelectorImpl>(SelectorIter<'a, Impl>);
function new (line 1586) | fn new(inner: SelectorIter<'a, Impl>) -> Self {
function skip_until_ancestor (line 1594) | fn skip_until_ancestor(&mut self) {
type Item (line 1610) | type Item = &'a Component<Impl>;
method next (line 1611) | fn next(&mut self) -> Option<Self::Item> {
type Combinator (line 1631) | pub enum Combinator {
method is_ancestor (line 1654) | pub fn is_ancestor(&self) -> bool {
method is_pseudo_element (line 1666) | pub fn is_pseudo_element(&self) -> bool {
method is_sibling (line 1672) | pub fn is_sibling(&self) -> bool {
method to_css_internal (line 2557) | fn to_css_internal<W>(&self, dest: &mut W, prefix_space: bool) -> fmt:...
method to_css_relative (line 2581) | fn to_css_relative<W>(&self, dest: &mut W) -> fmt::Result
type NthType (line 1681) | pub enum NthType {
method is_only (line 1691) | pub fn is_only(self) -> bool {
method is_of_type (line 1695) | pub fn is_of_type(self) -> bool {
method is_from_end (line 1699) | pub fn is_from_end(self) -> bool {
type AnPlusB (line 1708) | pub struct AnPlusB(pub i32, pub i32);
method matches_index (line 1712) | pub fn matches_index(&self, i: i32) -> bool {
method to_css (line 1728) | fn to_css<W>(&self, dest: &mut W) -> fmt::Result
type NthSelectorData (line 1753) | pub struct NthSelectorData {
method only (line 1762) | pub const fn only(of_type: bool) -> Self {
method first (line 1776) | pub const fn first(of_type: bool) -> Self {
method last (line 1790) | pub const fn last(of_type: bool) -> Self {
method is_simple_edge (line 1804) | pub fn is_simple_edge(&self) -> bool {
method write_start (line 1813) | fn write_start<W: fmt::Write>(&self, dest: &mut W) -> fmt::Result {
method write_affine (line 1829) | fn write_affine<W: fmt::Write>(&self, dest: &mut W) -> fmt::Result {
type NthOfSelectorData (line 1840) | pub struct NthOfSelectorData<Impl: SelectorImpl>(
function new (line 1847) | pub fn new<I>(nth_data: &NthSelectorData, selectors: I) -> Self
function nth_data (line 1856) | pub fn nth_data(&self) -> &NthSelectorData {
function selectors (line 1862) | pub fn selectors(&self) -> &[Selector<Impl>] {
type RelativeSelectorMatchHint (line 1870) | pub enum RelativeSelectorMatchHint {
method new (line 1887) | pub fn new(
method is_descendant_direction (line 1932) | pub fn is_descendant_direction(&self) -> bool {
method is_next_sibling (line 1937) | pub fn is_next_sibling(&self) -> bool {
method is_subtree (line 1942) | pub fn is_subtree(&self) -> bool {
type RelativeSelectorCombinatorCount (line 1952) | pub struct RelativeSelectorCombinatorCount {
method new (line 1960) | pub fn new<Impl: SelectorImpl>(relative_selector: &RelativeSelector<Im...
method get_match_hint (line 1988) | pub fn get_match_hint(&self) -> RelativeSelectorMatchHint {
type RelativeSelector (line 2001) | pub struct RelativeSelector<Impl: SelectorImpl> {
method for_relative_selector (line 2019) | fn for_relative_selector<Impl: SelectorImpl>(inner_selector: &Selector<I...
function from_selector_list (line 2042) | fn from_selector_list(selector_list: SelectorList<Impl>) -> Box<[Self]> {
type Component (line 2086) | pub enum Component<Impl: SelectorImpl> {
function is_combinator (line 2196) | pub fn is_combinator(&self) -> bool {
function is_host (line 2202) | pub fn is_host(&self) -> bool {
function as_combinator (line 2207) | pub fn as_combinator(&self) -> Option<Combinator> {
function matches_for_stateless_pseudo_element (line 2217) | fn matches_for_stateless_pseudo_element(&self) -> bool {
function visit (line 2235) | pub fn visit<V>(&self, visitor: &mut V) -> bool
function has_indexed_selector_in_subject (line 2325) | pub fn has_indexed_selector_in_subject(&self) -> bool {
type LocalName (line 2350) | pub struct LocalName<Impl: SelectorImpl> {
method fmt (line 2357) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method fmt (line 2370) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method fmt (line 2375) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method fmt (line 2380) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
function serialize_selector_list (line 2385) | fn serialize_selector_list<'a, Impl, I, W>(iter: I, dest: &mut W) -> fmt...
method to_css (line 2403) | fn to_css<W>(&self, dest: &mut W) -> fmt::Result
method to_css (line 2412) | fn to_css<W>(&self, dest: &mut W) -> fmt::Result
method to_css (line 2590) | fn to_css<W>(&self, dest: &mut W) -> fmt::Result
method to_css (line 2599) | fn to_css<W>(&self, dest: &mut W) -> fmt::Result
method to_css (line 2734) | fn to_css<W>(&self, dest: &mut W) -> fmt::Result
method to_css (line 2771) | fn to_css<W>(&self, dest: &mut W) -> fmt::Result
function parse_selector (line 2783) | fn parse_selector<'i, 't, P, Impl>(
function try_parse_combinator (line 2860) | fn try_parse_combinator<'i, 't>(input: &mut CssParser<'i, 't>) -> Result...
function parse_type_selector (line 2891) | fn parse_type_selector<'i, 't, P, Impl, S>(
type SimpleSelectorParseResult (line 2961) | enum SimpleSelectorParseResult<Impl: SelectorImpl> {
type QNamePrefix (line 2969) | enum QNamePrefix<Impl: SelectorImpl> {
type OptionalQName (line 2978) | enum OptionalQName<'i, Impl: SelectorImpl> {
function parse_qualified_name (line 2987) | fn parse_qualified_name<'i, 't, P, Impl>(
function parse_attribute_selector (line 3082) | fn parse_attribute_selector<'i, 't, P, Impl>(
type AttributeFlags (line 3205) | enum AttributeFlags {
method to_case_sensitivity (line 3215) | fn to_case_sensitivity(
function parse_attribute_flags (line 3240) | fn parse_attribute_flags<'i, 't>(
function parse_negation (line 3268) | fn parse_negation<'i, 't, P, Impl>(
function parse_compound_selector (line 3296) | fn parse_compound_selector<'i, 't, P, Impl>(
function parse_is_where (line 3399) | fn parse_is_where<'i, 't, P, Impl>(
function parse_has (line 3427) | fn parse_has<'i, 't, P, Impl>(
function parse_functional_pseudo_class (line 3459) | fn parse_functional_pseudo_class<'i, 't, P, Impl>(
function parse_nth_pseudo_class (line 3504) | fn parse_nth_pseudo_class<'i, 't, P, Impl>(
function is_css2_pseudo_element (line 3551) | pub fn is_css2_pseudo_element(name: &str) -> bool {
function parse_one_simple_selector (line 3564) | fn parse_one_simple_selector<'i, 't, P, Impl>(
function parse_simple_pseudo_class (line 3707) | fn parse_simple_pseudo_class<'i, P, Impl>(
type PseudoClass (line 3773) | pub enum PseudoClass {
type Impl (line 3813) | type Impl = DummySelectorImpl;
method is_active_or_hover (line 3816) | fn is_active_or_hover(&self) -> bool {
method is_user_action_state (line 3821) | fn is_user_action_state(&self) -> bool {
type PseudoElement (line 3780) | pub enum PseudoElement {
method accepts_state_pseudo_classes (line 41) | fn accepts_state_pseudo_classes(&self) -> bool {
method valid_after_slotted (line 46) | fn valid_after_slotted(&self) -> bool {
method valid_after_before_or_after (line 51) | fn valid_after_before_or_after(&self) -> bool {
method parses_as_element_backed (line 57) | fn parses_as_element_backed(&self) -> bool {
method is_before_or_after (line 64) | fn is_before_or_after(&self) -> bool {
method specificity_count (line 69) | fn specificity_count(&self) -> u32 {
method is_in_pseudo_element_tree (line 76) | fn is_in_pseudo_element_tree(&self) -> bool {
type Impl (line 3789) | type Impl = DummySelectorImpl;
method accepts_state_pseudo_classes (line 3791) | fn accepts_state_pseudo_classes(&self) -> bool {
method valid_after_slotted (line 3795) | fn valid_after_slotted(&self) -> bool {
method valid_after_before_or_after (line 3799) | fn valid_after_before_or_after(&self) -> bool {
method is_before_or_after (line 3803) | fn is_before_or_after(&self) -> bool {
method parses_as_element_backed (line 3807) | fn parses_as_element_backed(&self) -> bool {
method to_css (line 3827) | fn to_css<W>(&self, dest: &mut W) -> fmt::Result
method to_css (line 3844) | fn to_css<W>(&self, dest: &mut W) -> fmt::Result
type DummySelectorImpl (line 3863) | pub struct DummySelectorImpl;
type DummyParser (line 3866) | pub struct DummyParser {
method default_with_namespace (line 3872) | fn default_with_namespace(default_ns: DummyAtom) -> DummyParser {
type Impl (line 3946) | type Impl = DummySelectorImpl;
type Error (line 3947) | type Error = SelectorParseErrorKind<'i>;
method parse_slotted (line 3949) | fn parse_slotted(&self) -> bool {
method parse_nth_child_of (line 3953) | fn parse_nth_child_of(&self) -> bool {
method parse_is_and_where (line 3957) | fn parse_is_and_where(&self) -> bool {
method parse_has (line 3961) | fn parse_has(&self) -> bool {
method parse_parent_selector (line 3965) | fn parse_parent_selector(&self) -> bool {
method parse_part (line 3969) | fn parse_part(&self) -> bool {
method parse_host (line 3973) | fn parse_host(&self) -> bool {
method parse_non_ts_pseudo_class (line 3977) | fn parse_non_ts_pseudo_class(
method parse_non_ts_functional_pseudo_class (line 3994) | fn parse_non_ts_functional_pseudo_class<'t>(
method parse_pseudo_element (line 4014) | fn parse_pseudo_element(
method parse_functional_pseudo_element (line 4033) | fn parse_functional_pseudo_element<'t>(
method default_namespace (line 4049) | fn default_namespace(&self) -> Option<DummyAtom> {
method namespace_for_prefix (line 4053) | fn namespace_for_prefix(&self, prefix: &DummyAtom) -> Option<DummyAtom> {
type ExtraMatchingData (line 3881) | type ExtraMatchingData<'a> = std::marker::PhantomData<&'a ()>;
type AttrValue (line 3882) | type AttrValue = DummyAttrValue;
type Identifier (line 3883) | type Identifier = DummyAtom;
type LocalName (line 3884) | type LocalName = DummyAtom;
type NamespaceUrl (line 3885) | type NamespaceUrl = DummyAtom;
type NamespacePrefix (line 3886) | type NamespacePrefix = DummyAtom;
type BorrowedLocalName (line 3887) | type BorrowedLocalName = DummyAtom;
type BorrowedNamespaceUrl (line 3888) | type BorrowedNamespaceUrl = DummyAtom;
type NonTSPseudoClass (line 3889) | type NonTSPseudoClass = PseudoClass;
type PseudoElement (line 3890) | type PseudoElement = PseudoElement;
type DummyAttrValue (line 3894) | pub struct DummyAttrValue(String);
method from (line 3910) | fn from(string: &'a str) -> Self {
method to_css (line 3897) | fn to_css<W>(&self, dest: &mut W) -> fmt::Result
type DummyAtom (line 3916) | pub struct DummyAtom(String);
method from (line 3928) | fn from(string: String) -> Self {
method from (line 3934) | fn from(string: &'a str) -> Self {
method to_css (line 3919) | fn to_css<W>(&self, dest: &mut W) -> fmt::Result
method precomputed_hash (line 3940) | fn precomputed_hash(&self) -> u32 {
function parse (line 4058) | fn parse<'i>(
function parse_relative (line 4064) | fn parse_relative<'i>(
function parse_expected (line 4071) | fn parse_expected<'i, 'a>(
function parse_relative_expected (line 4078) | fn parse_relative_expected<'i, 'a>(
function parse_ns (line 4086) | fn parse_ns<'i>(
function parse_ns_relative (line 4093) | fn parse_ns_relative<'i>(
function parse_ns_expected (line 4101) | fn parse_ns_expected<'i, 'a>(
function parse_ns_relative_expected (line 4109) | fn parse_ns_relative_expected<'i, 'a>(
function specificity (line 4136) | fn specificity(a: u32, b: u32, c: u32) -> u32 {
function test_empty (line 4141) | fn test_empty() {
constant MATHML (line 4151) | const MATHML: &str = "http://www.w3.org/1998/Math/MathML";
constant SVG (line 4152) | const SVG: &str = "http://www.w3.org/2000/svg";
function test_parsing (line 4155) | fn test_parsing() {
function parent_selector (line 4630) | fn parent_selector() {
function test_pseudo_iter (line 4672) | fn test_pseudo_iter() {
function test_pseudo_before_marker (line 4696) | fn test_pseudo_before_marker() {
function test_pseudo_duplicate_before_after_or_marker (line 4719) | fn test_pseudo_duplicate_before_after_or_marker() {
function test_pseudo_on_element_backed_pseudo (line 4726) | fn test_pseudo_on_element_backed_pseudo() {
function test_universal (line 4749) | fn test_universal() {
function test_empty_pseudo_iter (line 4760) | fn test_empty_pseudo_iter() {
function test_parse_implicit_scope (line 4776) | fn test_parse_implicit_scope() {
type TestVisitor (line 4832) | struct TestVisitor {
type Impl (line 4837) | type Impl = DummySelectorImpl;
method visit_simple_selector (line 4839) | fn visit_simple_selector(&mut self, s: &Component<DummySelectorImpl>) ->...
function visitor (line 4848) | fn visitor() {
FILE: selectors/relative_selector/cache.rs
type RelativeSelectorCachedMatch (line 24) | pub enum RelativeSelectorCachedMatch {
method matched (line 33) | pub fn matched(&self) -> bool {
type Key (line 39) | struct Key {
method new (line 45) | pub fn new<Impl: SelectorImpl>(
type RelativeSelectorCache (line 58) | pub struct RelativeSelectorCache {
method add (line 64) | pub fn add<Impl: SelectorImpl>(
method lookup (line 74) | pub fn lookup<Impl: SelectorImpl>(
FILE: selectors/relative_selector/filter.rs
type Entry (line 14) | enum Entry {
type TraversalKind (line 25) | enum TraversalKind {
function add_to_filter (line 30) | fn add_to_filter<E: Element>(element: &E, filter: &mut BloomFilter, kind...
type Key (line 47) | struct Key(OpaqueElement, TraversalKind);
type RelativeSelectorFilterMap (line 51) | pub struct RelativeSelectorFilterMap {
method get_filter (line 87) | fn get_filter<E: Element>(&mut self, element: &E, kind: TraversalKind)...
method fast_reject (line 116) | pub fn fast_reject<Impl: SelectorImpl, E: Element>(
function fast_reject (line 55) | fn fast_reject<Impl: SelectorImpl>(
FILE: selectors/sink.rs
type Push (line 16) | pub trait Push<T> {
method push (line 18) | fn push(&mut self, value: T);
function push (line 22) | fn push(&mut self, value: T) {
function push (line 28) | fn push(&mut self, value: A::Item) {
FILE: selectors/tree.rs
type OpaqueElement (line 17) | pub struct OpaqueElement(NonNull<()>);
method new (line 26) | pub fn new<T>(ptr: &T) -> Self {
method from_non_null_ptr (line 35) | pub fn from_non_null_ptr(ptr: NonNull<()>) -> Self {
method as_const_ptr (line 41) | pub unsafe fn as_const_ptr<T>(&self) -> *const T {
type Element (line 46) | pub trait Element: Sized + Clone + Debug {
method opaque (line 50) | fn opaque(&self) -> OpaqueElement;
method parent_element (line 52) | fn parent_element(&self) -> Option<Self>;
method parent_node_is_shadow_root (line 55) | fn parent_node_is_shadow_root(&self) -> bool;
method containing_shadow_host (line 58) | fn containing_shadow_host(&self) -> Option<Self>;
method pseudo_element_originating_element (line 64) | fn pseudo_element_originating_element(&self) -> Option<Self> {
method is_pseudo_element (line 70) | fn is_pseudo_element(&self) -> bool;
method prev_sibling_element (line 73) | fn prev_sibling_element(&self) -> Option<Self>;
method next_sibling_element (line 76) | fn next_sibling_element(&self) -> Option<Self>;
method first_element_child (line 79) | fn first_element_child(&self) -> Option<Self>;
method is_html_element_in_html_document (line 81) | fn is_html_element_in_html_document(&self) -> bool;
method has_local_name (line 83) | fn has_local_name(&self, local_name: &<Self::Impl as SelectorImpl>::Bo...
method has_namespace (line 86) | fn has_namespace(&self, ns: &<Self::Impl as SelectorImpl>::BorrowedNam...
method is_same_type (line 89) | fn is_same_type(&self, other: &Self) -> bool;
method attr_matches (line 91) | fn attr_matches(
method has_attr_in_no_namespace (line 98) | fn has_attr_in_no_namespace(
method match_non_ts_pseudo_class (line 109) | fn match_non_ts_pseudo_class(
method match_pseudo_element (line 115) | fn match_pseudo_element(
method apply_selector_flags (line 124) | fn apply_selector_flags(&self, flags: ElementSelectorFlags);
method is_link (line 127) | fn is_link(&self) -> bool;
method is_html_slot_element (line 130) | fn is_html_slot_element(&self) -> bool;
method assigned_slot (line 135) | fn assigned_slot(&self) -> Option<Self> {
method has_id (line 139) | fn has_id(
method has_class (line 145) | fn has_class(
method has_custom_state (line 151) | fn has_custom_state(&self, name: &<Self::Impl as SelectorImpl>::Identi...
method imported_part (line 155) | fn imported_part(
method is_part (line 160) | fn is_part(&self, name: &<Self::Impl as SelectorImpl>::Identifier) -> ...
method is_empty (line 166) | fn is_empty(&self) -> bool;
method is_root (line 173) | fn is_root(&self) -> bool;
method ignores_nth_child_selectors (line 177) | fn ignores_nth_child_selectors(&self) -> bool {
method add_element_unique_hashes (line 183) | fn add_element_unique_hashes(&self, filter: &mut BloomFilter) -> bool;
FILE: selectors/visitor.rs
type SelectorVisitor (line 17) | pub trait SelectorVisitor: Sized {
method visit_attribute_selector (line 24) | fn visit_attribute_selector(
method visit_simple_selector (line 34) | fn visit_simple_selector(&mut self, _: &Component<Self::Impl>) -> bool {
method visit_relative_selector_list (line 42) | fn visit_relative_selector_list(&mut self, _list: &[RelativeSelector<S...
method visit_selector_list (line 50) | fn visit_selector_list(
method visit_complex_selector (line 67) | fn visit_complex_selector(&mut self, _combinator_to_right: Option<Comb...
method from_component (line 92) | pub fn from_component<Impl: SelectorImpl>(component: &Component<Impl>) -...
method in_negation (line 103) | pub fn in_negation(&self) -> bool {
method in_is (line 108) | pub fn in_is(&self) -> bool {
method in_where (line 113) | pub fn in_where(&self) -> bool {
method in_nth_of (line 119) | pub fn in_nth_of(&self) -> bool {
method in_has (line 124) | pub fn in_has(&self) -> bool {
method relevant_to_nth_of_dependencies (line 129) | pub fn relevant_to_nth_of_dependencies(&self) -> bool {
FILE: servo_arc/lib.rs
constant MAX_REFCOUNT (line 50) | const MAX_REFCOUNT: usize = (isize::MAX) as usize;
constant STATIC_REFCOUNT (line 54) | const STATIC_REFCOUNT: usize = usize::MAX;
type Arc (line 69) | pub struct Arc<T: ?Sized> {
type UniqueArc (line 100) | pub struct UniqueArc<T: ?Sized>(Arc<T>);
function new (line 105) | pub fn new(data: T) -> Self {
function new_uninit (line 111) | pub fn new_uninit() -> UniqueArc<mem::MaybeUninit<T>> {
function shareable (line 136) | pub fn shareable(self) -> Arc<T> {
function assume_init (line 144) | pub unsafe fn assume_init(this: Self) -> UniqueArc<T> {
type Target (line 153) | type Target = T;
method deref (line 154) | fn deref(&self) -> &T {
method deref_mut (line 160) | fn deref_mut(&mut self) -> &mut T {
type ArcInner (line 176) | struct ArcInner<T: ?Sized> {
function data_offset (line 195) | fn data_offset<T>() -> usize {
function new (line 205) | pub fn new(data: T) -> Self {
function new_leaked (line 239) | pub fn new_leaked(data: T) -> Self {
function into_raw (line 249) | pub fn into_raw(this: Self) -> *const T {
function from_raw (line 260) | pub unsafe fn from_raw(ptr: *const T) -> Self {
function from_raw_addrefed (line 272) | pub unsafe fn from_raw_addrefed(ptr: *const T) -> Self {
function new_static (line 286) | pub unsafe fn new_static<F>(alloc: F, data: T) -> Arc<T>
function borrow_arc (line 313) | pub fn borrow_arc<'a>(&'a self) -> ArcBorrow<'a, T> {
function heap_ptr (line 321) | pub fn heap_ptr(&self) -> *const c_void {
function inner (line 332) | fn inner(&self) -> &ArcInner<T> {
function record_drop (line 342) | fn record_drop(&self) {
function mark_as_intentionally_leaked (line 355) | pub fn mark_as_intentionally_leaked(&self) {
function drop_slow (line 362) | unsafe fn drop_slow(&mut self) {
function ptr_eq (line 377) | pub fn ptr_eq(this: &Self, other: &Self) -> bool {
function ptr (line 381) | fn ptr(&self) -> *mut ArcInner<T> {
function raw_ptr (line 386) | pub fn raw_ptr(&self) -> ptr::NonNull<()> {
function NS_LogCtor (line 393) | fn NS_LogCtor(
function NS_LogDtor (line 398) | fn NS_LogDtor(
method clone (line 407) | fn clone(&self) -> Self {
type Target (line 451) | type Target = T;
method deref (line 454) | fn deref(&self) -> &T {
function make_mut (line 474) | pub fn make_mut(this: &mut Self) -> &mut T {
function get_mut (line 494) | pub fn get_mut(this: &mut Self) -> Option<&mut T> {
function is_static (line 507) | pub fn is_static(&self) -> bool {
function is_unique (line 516) | pub fn is_unique(&self) -> bool {
method drop (line 526) | fn drop(&mut self) {
method eq (line 568) | fn eq(&self, other: &Arc<T>) -> bool {
method ne (line 572) | fn ne(&self, other: &Arc<T>) -> bool {
method partial_cmp (line 578) | fn partial_cmp(&self, other: &Arc<T>) -> Option<Ordering> {
method lt (line 582) | fn lt(&self, other: &Arc<T>) -> bool {
method le (line 586) | fn le(&self, other: &Arc<T>) -> bool {
method gt (line 590) | fn gt(&self, other: &Arc<T>) -> bool {
method ge (line 594) | fn ge(&self, other: &Arc<T>) -> bool {
method cmp (line 599) | fn cmp(&self, other: &Arc<T>) -> Ordering {
function fmt (line 606) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
function fmt (line 612) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
function fmt (line 618) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method default (line 624) | fn default() -> Arc<T> {
method hash (line 630) | fn hash<H: Hasher>(&self, state: &mut H) {
function from (line 637) | fn from(t: T) -> Self {
function borrow (line 644) | fn borrow(&self) -> &T {
function as_ref (line 651) | fn as_ref(&self) -> &T {
function deserialize (line 661) | fn deserialize<D>(deserializer: D) -> Result<Arc<T>, D::Error>
method serialize (line 671) | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
type HeaderSlice (line 686) | pub struct HeaderSlice<H, T> {
method eq (line 698) | fn eq(&self, other: &Self) -> bool {
method drop (line 704) | fn drop(&mut self) {
function fmt (line 716) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
function slice (line 727) | pub fn slice(&self) -> &[T] {
function data (line 732) | fn data(&self) -> *const T {
function data_mut (line 737) | fn data_mut(&mut self) -> *mut T {
function slice_mut (line 743) | pub fn slice_mut(&mut self) -> &mut [T] {
function len (line 749) | pub fn len(&self) -> usize {
function from_header_and_iter_alloc (line 767) | pub fn from_header_and_iter_alloc<F, I>(
function from_header_and_iter_with_size (line 855) | pub fn from_header_and_iter_with_size<I>(header: H, items: I, num_items:...
function from_header_and_iter (line 871) | pub fn from_header_and_iter<I>(header: H, items: I) -> Self
type ThinArc (line 887) | pub type ThinArc<H, T> = Arc<HeaderSlice<H, T>>;
type ThinArcUnion (line 890) | pub type ThinArcUnion<H1, T1, H2, T2> = ArcUnion<HeaderSlice<H1, T1>, He...
function from_header_and_iter (line 894) | pub fn from_header_and_iter<I>(header: H, items: I) -> Self
function from_header_and_iter_with_size (line 902) | pub fn from_header_and_iter_with_size<I>(header: H, items: I, num_items:...
function header_mut (line 912) | pub fn header_mut(&mut self) -> &mut H {
function data_mut (line 918) | pub fn data_mut(&mut self) -> &mut [T] {
type ArcBorrow (line 939) | pub struct ArcBorrow<'a, T: 'a>(&'a T);
method clone (line 944) | fn clone(&self) -> Self {
function clone_arc (line 952) | pub fn clone_arc(&self) -> Arc<T> {
function from_ref (line 962) | pub unsafe fn from_ref(r: &'a T) -> Self {
function ptr_eq (line 968) | pub fn ptr_eq(this: &Self, other: &Self) -> bool {
function with_arc (line 975) | pub fn with_arc<F, U>(&self, f: F) -> U
function get (line 993) | pub fn get(&self) -> &'a T {
type Target (line 999) | type Target = T;
method deref (line 1002) | fn deref(&self) -> &T {
type ArcUnion (line 1016) | pub struct ArcUnion<A, B> {
method eq (line 1026) | fn eq(&self, other: &Self) -> bool {
type ArcUnionBorrow (line 1040) | pub enum ArcUnionBorrow<'a, A: 'a, B: 'a> {
function new (line 1046) | unsafe fn new(ptr: *mut ()) -> Self {
function ptr_eq (line 1056) | pub fn ptr_eq(this: &Self, other: &Self) -> bool {
function ptr (line 1061) | pub fn ptr(&self) -> ptr::NonNull<()> {
function borrow (line 1067) | pub fn borrow(&self) -> ArcUnionBorrow<'_, A, B> {
function from_first (line 1080) | pub fn from_first(other: Arc<A>) -> Self {
function from_second (line 1087) | pub fn from_second(other: Arc<B>) -> Self {
function is_first (line 1094) | pub fn is_first(&self) -> bool {
function is_second (line 1099) | pub fn is_second(&self) -> bool {
function as_first (line 1104) | pub fn as_first(&self) -> Option<ArcBorrow<'_, A>> {
function as_second (line 1112) | pub fn as_second(&self) -> Option<ArcBorrow<'_, B>> {
method clone (line 1121) | fn clone(&self) -> Self {
method drop (line 1130) | fn drop(&mut self) {
function fmt (line 1143) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
type Canary (line 1157) | struct Canary(*mut atomic::AtomicUsize);
method drop (line 1160) | fn drop(&mut self) {
function empty_thin (line 1168) | fn empty_thin() {
function thin_assert_padding (line 1175) | fn thin_assert_padding() {
function slices_and_thin (line 1191) | fn slices_and_thin() {
FILE: style/applicable_declarations.rs
type ApplicableDeclarationList (line 22) | pub type ApplicableDeclarationList = SmallVec<[ApplicableDeclarationBloc...
constant SOURCE_ORDER_BITS (line 35) | const SOURCE_ORDER_BITS: usize = 24;
constant SOURCE_ORDER_MAX (line 36) | const SOURCE_ORDER_MAX: u32 = (1 << SOURCE_ORDER_BITS) - 1;
constant SOURCE_ORDER_MASK (line 37) | const SOURCE_ORDER_MASK: u32 = SOURCE_ORDER_MAX;
type CascadePriority (line 41) | pub struct CascadePriority {
method new (line 100) | pub fn new(
method flags (line 114) | pub fn flags(&self) -> RuleCascadeFlags {
method set_flags (line 120) | pub fn set_flags(&mut self, flags: RuleCascadeFlags) {
method layer_order (line 126) | pub fn layer_order(&self) -> LayerOrder {
method cascade_level (line 132) | pub fn cascade_level(&self) -> CascadeLevel {
method allows_when_reverted (line 140) | pub fn allows_when_reverted(&self, other: &Self, kind: RevertKind) -> ...
method unimportant (line 153) | pub fn unimportant(&self) -> Self {
method important (line 162) | pub fn important(&self) -> Self {
method same_tree_author_normal_at_root_layer (line 171) | pub fn same_tree_author_normal_at_root_layer() -> Self {
method partial_cmp (line 54) | fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
method cmp (line 60) | fn cmp(&self, other: &Self) -> std::cmp::Ordering {
type RevertKind (line 89) | pub enum RevertKind {
type ScopeProximity (line 184) | pub struct ScopeProximity(u16);
method new (line 206) | pub fn new(proximity: usize) -> Self {
method infinity (line 214) | pub fn infinity() -> Self {
method get (line 219) | pub fn get(&self) -> Option<u16> {
method partial_cmp (line 188) | fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
method cmp (line 194) | fn cmp(&self, other: &Self) -> std::cmp::Ordering {
constant PROXIMITY_INFINITY (line 202) | const PROXIMITY_INFINITY: u16 = u16::MAX;
type ApplicableDeclarationBlock (line 230) | pub struct ApplicableDeclarationBlock {
method from_declarations (line 250) | pub fn from_declarations(
method new (line 266) | pub fn new(
method source_order (line 286) | pub fn source_order(&self) -> u32 {
method level (line 292) | pub fn level(&self) -> CascadeLevel {
method layer_order (line 298) | pub fn layer_order(&self) -> LayerOrder {
method scope_proximity (line 304) | pub fn scope_proximity(&self) -> ScopeProximity {
method for_rule_tree (line 311) | pub fn for_rule_tree(self) -> (StyleSource, CascadePriority) {
method sort_key (line 317) | pub fn sort_key(&self) -> (LayerOrder, u32, ScopeProximity, u32) {
FILE: style/author_styles.rs
type GenericAuthorStyles (line 21) | pub struct GenericAuthorStyles<S>
function new (line 44) | pub fn new() -> Self {
function flush (line 53) | pub fn flush(
FILE: style/bezier.rs
constant NEWTON_METHOD_ITERATIONS (line 13) | const NEWTON_METHOD_ITERATIONS: u8 = 8;
type Bezier (line 16) | pub struct Bezier {
method calculate_bezier_output (line 33) | pub fn calculate_bezier_output(
method new (line 84) | fn new(x1: CSSFloat, y1: CSSFloat, x2: CSSFloat, y2: CSSFloat) -> Bezi...
method sample_curve_x (line 102) | fn sample_curve_x(&self, t: f64) -> f64 {
method sample_curve_y (line 108) | fn sample_curve_y(&self, t: f64) -> f64 {
method sample_curve_derivative_x (line 113) | fn sample_curve_derivative_x(&self, t: f64) -> f64 {
method solve_curve_x (line 118) | fn solve_curve_x(&self, x: f64, epsilon: f64) -> f64 {
method solve (line 162) | fn solve(&self, x: f64, epsilon: f64) -> f64 {
type ApproxEq (line 167) | trait ApproxEq {
method approx_eq (line 168) | fn approx_eq(self, value: Self, epsilon: Self) -> bool;
method approx_eq (line 173) | fn approx_eq(self, value: f64, epsilon: f64) -> bool {
FILE: style/bloom.rs
type StyleBloom (line 63) | pub struct StyleBloom<E: TElement> {
constant MEMSET_CLEAR_THRESHOLD (line 86) | const MEMSET_CLEAR_THRESHOLD: usize = 25;
type PushedElement (line 88) | struct PushedElement<E: TElement> {
function new (line 97) | fn new(el: E, num_hashes: usize) -> Self {
function is_attr_name_excluded_from_filter (line 110) | pub fn is_attr_name_excluded_from_filter(name: &LocalName) -> bool {
function each_relevant_element_hash (line 115) | pub fn each_relevant_element_hash<E, F>(element: E, mut f: F)
method drop (line 137) | fn drop(&mut self) {
function new (line 153) | pub fn new() -> Self {
function filter (line 167) | pub fn filter(&self) -> &BloomFilter {
function push (line 173) | pub fn push(&mut self, element: E) {
function push_internal (line 184) | fn push_internal(&mut self, element: E) {
function pop (line 196) | fn pop(&mut self) -> Option<E> {
function matching_depth (line 221) | pub fn matching_depth(&self) -> usize {
function clear (line 226) | pub fn clear(&mut self) {
function rebuild (line 241) | pub fn rebuild(&mut self, mut element: E) {
function assert_complete (line 259) | pub fn assert_complete(&self, mut element: E) {
function current_parent (line 278) | pub fn current_parent(&self) -> Option<E> {
function insert_parents_recovering (line 290) | pub fn insert_parents_recovering(&mut self, element: E, element_depth: u...
FILE: style/build.rs
function generate (line 16) | pub fn generate() {}
function generate_properties (line 43) | fn generate_properties(engine: &str) {
function main (line 75) | fn main() {
FILE: style/build_gecko.rs
constant STRUCTS_FILE (line 25) | const STRUCTS_FILE: &'static str = "structs.rs";
function read_config (line 27) | fn read_config(path: &PathBuf) -> Table {
function get_modified_time (line 73) | fn get_modified_time(file: &Path) -> Option<SystemTime> {
function update_last_modified (line 77) | fn update_last_modified(file: &Path) {
function search_include (line 83) | fn search_include(name: &str) -> Option<PathBuf> {
function add_headers_recursively (line 94) | fn add_headers_recursively(path: PathBuf, added_paths: &mut HashSet<Path...
function add_include (line 110) | fn add_include(name: &str) -> String {
type BuilderExt (line 121) | trait BuilderExt {
method get_initial_builder (line 122) | fn get_initial_builder() -> Builder;
method include (line 123) | fn include<T: Into<String>>(self, file: T) -> Builder;
method get_initial_builder (line 127) | fn get_initial_builder() -> Builder {
method include (line 157) | fn include<T: Into<String>>(self, file: T) -> Builder {
type Fixup (line 162) | struct Fixup {
function write_binding_file (line 167) | fn write_binding_file(builder: Builder, file: &str, fixups: &[Fixup]) {
type BuilderWithConfig (line 202) | struct BuilderWithConfig<'a> {
function new (line 208) | fn new(builder: Builder, config: &'a Table) -> Self {
function handle_list (line 216) | fn handle_list<F>(self, key: &'static str, func: F) -> BuilderWithConfig...
function handle_items (line 233) | fn handle_items<F>(self, key: &'static str, mut func: F) -> BuilderWithC...
function handle_str_items (line 239) | fn handle_str_items<F>(self, key: &'static str, mut func: F) -> BuilderW...
function handle_table_items (line 245) | fn handle_table_items<F>(self, key: &'static str, mut func: F) -> Builde...
function handle_common (line 251) | fn handle_common(self, fixups: &mut Vec<Fixup>) -> BuilderWithConfig<'a> {
function get_builder (line 264) | fn get_builder(self) -> Builder {
function generate_structs (line 274) | fn generate_structs() {
function setup_logging (line 319) | fn setup_logging() -> bool {
function generate_atoms (line 370) | fn generate_atoms() {
function generate (line 386) | pub fn generate() {
FILE: style/color/color_function.rs
type ColorFunction (line 25) | pub enum ColorFunction<OriginColor> {
function resolve_to_absolute (line 95) | pub fn resolve_to_absolute(&self) -> Result<AbsoluteColor, ()> {
function has_origin_color (line 357) | pub fn has_origin_color(&self) -> bool {
function resolve_to_absolute (line 372) | pub fn resolve_to_absolute(&self) -> Result<AbsoluteColor, ()> {
function map_origin_color (line 381) | pub fn map_origin_color<U>(
function resolve_to_absolute (line 426) | pub fn resolve_to_absolute(&self, current_color: &AbsoluteColor) -> Abso...
function to_css (line 445) | fn to_css<W>(&self, dest: &mut style_traits::CssWriter<W>) -> std::fmt::...
FILE: style/color/component.rs
type ColorComponent (line 28) | pub enum ColorComponent<ValueType> {
function is_none (line 44) | pub fn is_none(&self) -> bool {
type ColorComponentType (line 51) | pub trait ColorComponentType: Sized + Clone {
method from_value (line 56) | fn from_value(value: f32) -> Self;
method units (line 59) | fn units() -> CalcUnits;
method try_from_token (line 62) | fn try_from_token(token: &Token) -> Result<Self, ()>;
method try_from_leaf (line 66) | fn try_from_leaf(leaf: &Leaf) -> Result<Self, ()>;
function parse (line 71) | pub fn parse<'i, 't>(
function resolve (line 112) | pub fn resolve(&self, origin_color: Option<&AbsoluteColor>) -> Result<Op...
method to_css (line 158) | fn to_css<W>(&self, dest: &mut style_traits::CssWriter<W>) -> std::fmt::...
type AnimatedValue (line 183) | type AnimatedValue = Self;
method to_animated_value (line 185) | fn to_animated_value(self, _context: &crate::values::animated::Context) ...
method from_animated_value (line 189) | fn from_animated_value(animated: Self::AnimatedValue) -> Self {
FILE: style/color/convert.rs
type Transform (line 18) | type Transform = euclid::default::Transform3D<f32>;
type Vector (line 19) | type Vector = euclid::default::Vector3D<f32>;
function normalize_hue (line 23) | pub fn normalize_hue(hue: f32) -> f32 {
function rgb_to_hue_min_max (line 30) | fn rgb_to_hue_min_max(red: f32, green: f32, blue: f32) -> (f32, f32, f32) {
function hsl_to_rgb (line 54) | pub fn hsl_to_rgb(from: &ColorComponents) -> ColorComponents {
function rgb_to_hsl (line 90) | pub fn rgb_to_hsl(from: &ColorComponents) -> ColorComponents {
function hwb_to_rgb (line 114) | pub fn hwb_to_rgb(from: &ColorComponents) -> ColorComponents {
function rgb_to_hwb (line 133) | pub fn rgb_to_hwb(from: &ColorComponents) -> ColorComponents {
function epsilon_for_range (line 146) | pub fn epsilon_for_range(min: f32, max: f32) -> f32 {
function orthogonal_to_polar (line 154) | pub fn orthogonal_to_polar(from: &ColorComponents, e: f32) -> ColorCompo...
function polar_to_orthogonal (line 179) | pub fn polar_to_orthogonal(from: &ColorComponents) -> ColorComponents {
function transform (line 195) | fn transform(from: &ColorComponents, mat: &Transform) -> ColorComponents {
function xyz_d65_to_xyz_d50 (line 200) | fn xyz_d65_to_xyz_d50(from: &ColorComponents) -> ColorComponents {
function xyz_d50_to_xyz_d65 (line 212) | fn xyz_d50_to_xyz_d65(from: &ColorComponents) -> ColorComponents {
type WhitePoint (line 225) | pub enum WhitePoint {
method values (line 233) | const fn values(&self) -> ColorComponents {
function convert_white_point (line 244) | fn convert_white_point(from: WhitePoint, to: WhitePoint, components: &mu...
type ColorSpaceConversion (line 263) | pub trait ColorSpaceConversion {
constant WHITE_POINT (line 265) | const WHITE_POINT: WhitePoint;
method to_linear_light (line 269) | fn to_linear_light(from: &ColorComponents) -> ColorComponents;
method to_xyz (line 273) | fn to_xyz(from: &ColorComponents) -> ColorComponents;
method from_xyz (line 277) | fn from_xyz(from: &ColorComponents) -> ColorComponents;
method to_gamma_encoded (line 281) | fn to_gamma_encoded(from: &ColorComponents) -> ColorComponents;
constant WHITE_POINT (line 337) | const WHITE_POINT: WhitePoint = WhitePoint::D65;
method to_linear_light (line 339) | fn to_linear_light(from: &ColorComponents) -> ColorComponents {
method to_xyz (line 351) | fn to_xyz(from: &ColorComponents) -> ColorComponents {
method from_xyz (line 355) | fn from_xyz(from: &ColorComponents) -> ColorComponents {
method to_gamma_encoded (line 359) | fn to_gamma_encoded(from: &ColorComponents) -> ColorComponents {
constant WHITE_POINT (line 376) | const WHITE_POINT: WhitePoint = Srgb::WHITE_POINT;
method to_linear_light (line 378) | fn to_linear_light(from: &ColorComponents) -> ColorComponents {
method to_xyz (line 383) | fn to_xyz(from: &ColorComponents) -> ColorComponents {
method from_xyz (line 388) | fn from_xyz(from: &ColorComponents) -> ColorComponents {
method to_gamma_encoded (line 392) | fn to_gamma_encoded(from: &ColorComponents) -> ColorComponents {
constant WHITE_POINT (line 401) | const WHITE_POINT: WhitePoint = Srgb::WHITE_POINT;
method to_linear_light (line 403) | fn to_linear_light(from: &ColorComponents) -> ColorComponents {
method to_xyz (line 408) | fn to_xyz(from: &ColorComponents) -> ColorComponents {
method from_xyz (line 413) | fn from_xyz(from: &ColorComponents) -> ColorComponents {
method to_gamma_encoded (line 417) | fn to_gamma_encoded(from: &ColorComponents) -> ColorComponents {
constant WHITE_POINT (line 427) | const WHITE_POINT: WhitePoint = Srgb::WHITE_POINT;
method to_linear_light (line 429) | fn to_linear_light(from: &ColorComponents) -> ColorComponents {
method to_xyz (line 434) | fn to_xyz(from: &ColorComponents) -> ColorComponents {
method from_xyz (line 438) | fn from_xyz(from: &ColorComponents) -> ColorComponents {
method to_gamma_encoded (line 442) | fn to_gamma_encoded(from: &ColorComponents) -> ColorComponents {
constant WHITE_POINT (line 471) | const WHITE_POINT: WhitePoint = WhitePoint::D65;
method to_linear_light (line 473) | fn to_linear_light(from: &ColorComponents) -> ColorComponents {
method to_xyz (line 477) | fn to_xyz(from: &ColorComponents) -> ColorComponents {
method from_xyz (line 481) | fn from_xyz(from: &ColorComponents) -> ColorComponents {
method to_gamma_encoded (line 485) | fn to_gamma_encoded(from: &ColorComponents) -> ColorComponents {
constant WHITE_POINT (line 493) | const WHITE_POINT: WhitePoint = DisplayP3::WHITE_POINT;
method to_linear_light (line 495) | fn to_linear_light(from: &ColorComponents) -> ColorComponents {
method to_xyz (line 499) | fn to_xyz(from: &ColorComponents) -> ColorComponents {
method from_xyz (line 503) | fn from_xyz(from: &ColorComponents) -> ColorComponents {
method to_gamma_encoded (line 507) | fn to_gamma_encoded(from: &ColorComponents) -> ColorComponents {
constant WHITE_POINT (line 535) | const WHITE_POINT: WhitePoint = WhitePoint::D65;
method to_linear_light (line 537) | fn to_linear_light(from: &ColorComponents) -> ColorComponents {
method to_xyz (line 541) | fn to_xyz(from: &ColorComponents) -> ColorComponents {
method from_xyz (line 545) | fn from_xyz(from: &ColorComponents) -> ColorComponents {
method to_gamma_encoded (line 549) | fn to_gamma_encoded(from: &ColorComponents) -> ColorComponents {
constant WHITE_POINT (line 578) | const WHITE_POINT: WhitePoint = WhitePoint::D50;
method to_linear_light (line 580) | fn to_linear_light(from: &ColorComponents) -> ColorComponents {
method to_xyz (line 594) | fn to_xyz(from: &ColorComponents) -> ColorComponents {
method from_xyz (line 598) | fn from_xyz(from: &ColorComponents) -> ColorComponents {
method to_gamma_encoded (line 602) | fn to_gamma_encoded(from: &ColorComponents) -> ColorComponents {
constant WHITE_POINT (line 642) | const WHITE_POINT: WhitePoint = WhitePoint::D65;
method to_linear_light (line 644) | fn to_linear_light(from: &ColorComponents) -> ColorComponents {
method to_xyz (line 656) | fn to_xyz(from: &ColorComponents) -> ColorComponents {
method from_xyz (line 660) | fn from_xyz(from: &ColorComponents) -> ColorComponents {
method to_gamma_encoded (line 664) | fn to_gamma_encoded(from: &ColorComponents) -> ColorComponents {
constant WHITE_POINT (line 682) | const WHITE_POINT: WhitePoint = WhitePoint::D50;
method to_linear_light (line 684) | fn to_linear_light(from: &ColorComponents) -> ColorComponents {
method to_xyz (line 688) | fn to_xyz(from: &ColorComponents) -> ColorComponents {
method from_xyz (line 692) | fn from_xyz(from: &ColorComponents) -> ColorComponents {
method to_gamma_encoded (line 696) | fn to_gamma_encoded(from: &ColorComponents) -> ColorComponents {
constant WHITE_POINT (line 706) | const WHITE_POINT: WhitePoint = WhitePoint::D65;
method to_linear_light (line 708) | fn to_linear_light(from: &ColorComponents) -> ColorComponents {
method to_xyz (line 712) | fn to_xyz(from: &ColorComponents) -> ColorComponents {
method from_xyz (line 716) | fn from_xyz(from: &ColorComponents) -> ColorComponents {
method to_gamma_encoded (line 720) | fn to_gamma_encoded(from: &ColorComponents) -> ColorComponents {
constant WHITE_POINT (line 735) | const WHITE_POINT: WhitePoint = WhitePoint::D50;
method to_linear_light (line 737) | fn to_linear_light(from: &ColorComponents) -> ColorComponents {
method to_xyz (line 746) | fn to_xyz(from: &ColorComponents) -> ColorComponents {
method from_xyz (line 781) | fn from_xyz(from: &ColorComponents) -> ColorComponents {
method to_gamma_encoded (line 800) | fn to_gamma_encoded(from: &ColorComponents) -> ColorComponents {
constant WHITE_POINT (line 811) | const WHITE_POINT: WhitePoint = Lab::WHITE_POINT;
method to_linear_light (line 813) | fn to_linear_light(from: &ColorComponents) -> ColorComponents {
method to_xyz (line 818) | fn to_xyz(from: &ColorComponents) -> ColorComponents {
method from_xyz (line 826) | fn from_xyz(from: &ColorComponents) -> ColorComponents {
method to_gamma_encoded (line 834) | fn to_gamma_encoded(from: &ColorComponents) -> ColorComponents {
constant WHITE_POINT (line 879) | const WHITE_POINT: WhitePoint = WhitePoint::D65;
method to_linear_light (line 881) | fn to_linear_light(from: &ColorComponents) -> ColorComponents {
method to_xyz (line 886) | fn to_xyz(from: &ColorComponents) -> ColorComponents {
method from_xyz (line 892) | fn from_xyz(from: &ColorComponents) -> ColorComponents {
method to_gamma_encoded (line 898) | fn to_gamma_encoded(from: &ColorComponents) -> ColorComponents {
constant WHITE_POINT (line 909) | const WHITE_POINT: WhitePoint = Oklab::WHITE_POINT;
method to_linear_light (line 911) | fn to_linear_light(from: &ColorComponents) -> ColorComponents {
method to_xyz (line 916) | fn to_xyz(from: &ColorComponents) -> ColorComponents {
method from_xyz (line 924) | fn from_xyz(from: &ColorComponents) -> ColorComponents {
method to_gamma_encoded (line 932) | fn to_gamma_encoded(from: &ColorComponents) -> ColorComponents {
function to_xyz (line 286) | pub fn to_xyz<From: ColorSpaceConversion>(from: &ColorComponents) -> (Co...
function from_xyz (line 297) | pub fn from_xyz<To: ColorSpaceConversion>(
type Srgb (line 316) | pub struct Srgb;
constant TO_XYZ (line 320) | const TO_XYZ: Transform = Transform::new(
constant FROM_XYZ (line 328) | const FROM_XYZ: Transform = Transform::new(
type Hsl (line 373) | pub struct Hsl;
type Hwb (line 398) | pub struct Hwb;
type SrgbLinear (line 424) | pub struct SrgbLinear;
type DisplayP3 (line 450) | pub struct DisplayP3;
constant TO_XYZ (line 454) | const TO_XYZ: Transform = Transform::new(
constant FROM_XYZ (line 462) | const FROM_XYZ: Transform = Transform::new(
type DisplayP3Linear (line 491) | pub struct DisplayP3Linear;
type A98Rgb (line 514) | pub struct A98Rgb;
constant TO_XYZ (line 518) | const TO_XYZ: Transform = Transform::new(
constant FROM_XYZ (line 526) | const FROM_XYZ: Transform = Transform::new(
type ProphotoRgb (line 557) | pub struct ProphotoRgb;
constant TO_XYZ (line 561) | const TO_XYZ: Transform = Transform::new(
constant FROM_XYZ (line 569) | const FROM_XYZ: Transform = Transform::new(
type Rec2020 (line 618) | pub struct Rec2020;
constant ALPHA (line 621) | const ALPHA: f32 = 1.09929682680944;
constant BETA (line 622) | const BETA: f32 = 0.018053968510807;
constant TO_XYZ (line 625) | const TO_XYZ: Transform = Transform::new(
constant FROM_XYZ (line 633) | const FROM_XYZ: Transform = Transform::new(
type XyzD50 (line 679) | pub struct XyzD50;
type XyzD65 (line 703) | pub struct XyzD65;
type Lab (line 727) | pub struct Lab;
constant KAPPA (line 730) | const KAPPA: f32 = 24389.0 / 27.0;
constant EPSILON (line 731) | const EPSILON: f32 = 216.0 / 24389.0;
type Lch (line 808) | pub struct Lch;
type Oklab (line 842) | pub struct Oklab;
constant XYZ_TO_LMS (line 846) | const XYZ_TO_LMS: Transform = Transform::new(
constant LMS_TO_OKLAB (line 854) | const LMS_TO_OKLAB: Transform = Transform::new(
constant LMS_TO_XYZ (line 862) | const LMS_TO_XYZ: Transform = Transform::new(
constant OKLAB_TO_LMS (line 870) | const OKLAB_TO_LMS: Transform = Transform::new(
type Oklch (line 906) | pub struct Oklch;
FILE: style/color/mix.rs
type HueInterpolationMethod (line 34) | pub enum HueInterpolationMethod {
type ColorInterpolationMethod (line 61) | pub struct ColorInterpolationMethod {
method srgb (line 70) | pub const fn srgb() -> Self {
method oklab (line 79) | pub const fn oklab() -> Self {
method is_default (line 87) | pub fn is_default(&self) -> bool {
method best_interpolation_between (line 93) | pub fn best_interpolation_between(left: &AbsoluteColor, right: &Absolu...
method default (line 106) | fn default() -> Self {
method parse (line 112) | fn parse<'i, 't>(
method to_css (line 137) | fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
type ColorMixItem (line 153) | pub struct ColorMixItem {
method new (line 163) | pub fn new(color: AbsoluteColor, weight: f32) -> Self {
function mix_many (line 169) | pub fn mix_many(
type ComponentMixOutcome (line 268) | enum ComponentMixOutcome {
method from_colors (line 280) | fn from_colors(
method carry_forward_analogous_missing_components (line 301) | fn carry_forward_analogous_missing_components(&mut self, source: &Absolu...
function mix_with_weights (line 371) | fn mix_with_weights(
function convert_for_mix (line 407) | fn convert_for_mix(color: &AbsoluteColor, color_space: ColorSpace) -> Ab...
function interpolate_premultiplied_component (line 413) | fn interpolate_premultiplied_component(
function normalize_hue (line 426) | fn normalize_hue(v: f32) -> f32 {
function adjust_hue (line 430) | fn adjust_hue(left: &mut f32, right: &mut f32, hue_interpolation: HueInt...
function interpolate_hue (line 492) | fn interpolate_hue(
type InterpolatedAlpha (line 503) | struct InterpolatedAlpha {
function interpolate_alpha (line 514) | fn interpolate_alpha(
function interpolate_premultiplied (line 560) | fn interpolate_premultiplied(
FILE: style/color/mod.rs
constant PRE_ALLOCATED_COLOR_MIX_ITEMS (line 23) | pub const PRE_ALLOCATED_COLOR_MIX_ITEMS: usize = 3;
type ColorMixItemList (line 26) | pub type ColorMixItemList<T> = smallvec::SmallVec<[T; PRE_ALLOCATED_COLO...
type ColorComponents (line 32) | pub struct ColorComponents(pub f32, pub f32, pub f32);
method map (line 37) | pub fn map(self, f: impl Fn(f32) -> f32) -> Self {
type Output (line 43) | type Output = Self;
method mul (line 45) | fn mul(self, rhs: Self) -> Self::Output {
type Output (line 51) | type Output = Self;
method div (line 53) | fn div(self, rhs: Self) -> Self::Output {
type ColorSpace (line 77) | pub enum ColorSpace {
method is_rectangular (line 139) | pub fn is_rectangular(&self) -> bool {
method is_polar (line 145) | pub fn is_polar(&self) -> bool {
method is_rgb_or_xyz_like (line 151) | pub fn is_rgb_or_xyz_like(&self) -> bool {
method hue_index (line 169) | pub fn hue_index(&self) -> Option<usize> {
method from (line 700) | fn from(value: PredefinedColorSpace) -> Self {
type ColorFlags (line 186) | pub struct ColorFlags(u8);
type AbsoluteColor (line 209) | pub struct AbsoluteColor {
constant TRANSPARENT_BLACK (line 333) | pub const TRANSPARENT_BLACK: Self = Self {
constant BLACK (line 341) | pub const BLACK: Self = Self {
constant WHITE (line 349) | pub const WHITE: Self = Self {
method new (line 358) | pub fn new(
method into_srgb_legacy (line 415) | pub fn into_srgb_legacy(self) -> Self {
method srgb_legacy (line 430) | pub fn srgb_legacy(red: u8, green: u8, blue: u8, alpha: f32) -> Self {
method raw_components (line 438) | pub fn raw_components(&self) -> &[f32; 4] {
method is_legacy_syntax (line 444) | pub fn is_legacy_syntax(&self) -> bool {
method is_transparent (line 455) | pub fn is_transparent(&self) -> bool {
method c0 (line 461) | pub fn c0(&self) -> Option<f32> {
method c1 (line 471) | pub fn c1(&self) -> Option<f32> {
method c2 (line 481) | pub fn c2(&self) -> Option<f32> {
method alpha (line 491) | pub fn alpha(&self) -> Option<f32> {
method get_component_by_channel_keyword (line 500) | pub fn get_component_by_channel_keyword(
method to_color_space (line 571) | pub fn to_color_space(&self, color_space: ColorSpace) -> Self {
method to_nscolor (line 675) | pub fn to_nscolor(&self) -> u32 {
method from_nscolor (line 686) | pub fn from_nscolor(color: u32) -> Self {
method eq (line 222) | fn eq(&self, other: &Self) -> bool {
type ComponentDetails (line 276) | pub struct ComponentDetails {
method from (line 282) | fn from(value: f32) -> Self {
method from (line 291) | fn from(value: u8) -> Self {
method from (line 300) | fn from(value: Option<f32>) -> Self {
method from (line 316) | fn from(value: ColorComponent<f32>) -> Self {
function from_nscolor_should_be_in_legacy_syntax (line 693) | fn from_nscolor_should_be_in_legacy_syntax() {
FILE: style/color/parsing.rs
function rcs_enabled (line 30) | pub fn rcs_enabled() -> bool {
type ChannelKeyword (line 37) | pub enum ChannelKeyword {
function parse_color_keyword (line 72) | pub fn parse_color_keyword(ident: &str) -> Result<SpecifiedColor, ()> {
function parse_color_with (line 87) | pub fn parse_color_with<'i, 't>(
function parse_color_function (line 125) | fn parse_color_function<'i, 't>(
function parse_origin_color (line 163) | fn parse_origin_color<'i, 't>(
function parse_rgb (line 184) | fn parse_rgb<'i, 't>(
function parse_hsl (line 228) | fn parse_hsl<'i, 't>(
function parse_hwb (line 267) | fn parse_hwb<'i, 't>(
type IntoLabFn (line 287) | type IntoLabFn<Output> = fn(
function parse_lab_like (line 296) | fn parse_lab_like<'i, 't>(
type IntoLchFn (line 311) | type IntoLchFn<Output> = fn(
function parse_lch_like (line 320) | fn parse_lch_like<'i, 't>(
function parse_color_with_color_space (line 343) | fn parse_color_with_color_space<'i, 't>(
type NumberOrPercentageComponent (line 369) | pub enum NumberOrPercentageComponent {
method to_number (line 380) | pub fn to_number(&self, percentage_basis: f32) -> f32 {
method from_value (line 389) | fn from_value(value: f32) -> Self {
method units (line 393) | fn units() -> CalcUnits {
method try_from_token (line 397) | fn try_from_token(token: &Token) -> Result<Self, ()> {
method try_from_leaf (line 407) | fn try_from_leaf(leaf: &Leaf) -> Result<Self, ()> {
type NumberOrAngleComponent (line 419) | pub enum NumberOrAngleComponent {
method degrees (line 430) | pub fn degrees(&self) -> f32 {
method from_value (line 439) | fn from_value(value: f32) -> Self {
method units (line 443) | fn units() -> CalcUnits {
method try_from_token (line 447) | fn try_from_token(token: &Token) -> Result<Self, ()> {
method try_from_leaf (line 465) | fn try_from_leaf(leaf: &Leaf) -> Result<Self, ()> {
method from_value (line 476) | fn from_value(value: f32) -> Self {
method units (line 480) | fn units() -> CalcUnits {
method try_from_token (line 484) | fn try_from_token(token: &Token) -> Result<Self, ()> {
method try_from_leaf (line 492) | fn try_from_leaf(leaf: &Leaf) -> Result<Self, ()> {
function parse_number_or_angle (line 502) | fn parse_number_or_angle<'i, 't>(
function parse_percentage (line 511) | fn parse_percentage<'i, 't>(
function parse_number (line 527) | fn parse_number<'i, 't>(
function parse_number_or_percentage (line 544) | fn parse_number_or_percentage<'i, 't>(
function parse_legacy_alpha (line 552) | fn parse_legacy_alpha<'i, 't>(
function parse_modern_alpha (line 564) | fn parse_modern_alpha<'i, 't>(
function could_be_number (line 579) | fn could_be_number(&self) -> bool {
function could_be_percentage (line 599) | fn could_be_percentage(&self) -> bool {
FILE: style/color/to_css.rs
type ModernComponent (line 18) | struct ModernComponent<'a>(&'a Option<f32>);
method to_css (line 21) | fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
method to_css (line 45) | fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
method to_css (line 60) | fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
method to_css (line 75) | fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
method write_author_preferred_value (line 172) | pub fn write_author_preferred_value<W>(&self, dest: &mut CssWriter<W>) -...
FILE: style/context.rs
type StyleSystemOptions (line 52) | pub struct StyleSystemOptions {
function get_env_bool (line 63) | fn get_env_bool(name: &str) -> bool {
constant DEFAULT_STATISTICS_THRESHOLD (line 71) | const DEFAULT_STATISTICS_THRESHOLD: usize = 50;
function get_env_usize (line 74) | fn get_env_usize(name: &str) -> Option<usize> {
method default (line 98) | fn default() -> Self {
method default (line 110) | fn default() -> Self {
type SharedStyleContext (line 124) | pub struct SharedStyleContext<'a> {
function viewport_size (line 161) | pub fn viewport_size(&self) -> Size2D<Au> {
function device_pixel_ratio (line 166) | pub fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
function quirks_mode (line 171) | pub fn quirks_mode(&self) -> QuirksMode {
type CascadeInputs (line 184) | pub struct CascadeInputs {
method new_from_style (line 204) | pub fn new_from_style(style: &ComputedValues) -> Self {
type EagerPseudoCascadeInputs (line 217) | pub struct EagerPseudoCascadeInputs(Option<[Option<CascadeInputs>; EAGER...
method new_from_style (line 237) | fn new_from_style(styles: &EagerPseudoStyles) -> Self {
method into_array (line 248) | pub fn into_array(self) -> Option<[Option<CascadeInputs>; EAGER_PSEUDO...
method clone (line 222) | fn clone(&self) -> Self {
type ElementCascadeInputs (line 261) | pub struct ElementCascadeInputs {
method new_from_element_data (line 271) | pub fn new_from_element_data(data: &ElementData) -> Self {
type PerThreadTraversalStatistics (line 284) | pub struct PerThreadTraversalStatistics {
type TraversalStatistics (line 301) | pub struct TraversalStatistics {
method fmt (line 325) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method new (line 379) | pub fn new<E, D>(
type SequentialTask (line 439) | pub enum SequentialTask<E: TElement> {
function execute (line 462) | pub fn execute(self) {
function update_animations (line 481) | pub fn update_animations(
type SequentialTaskList (line 496) | pub struct SequentialTaskList<E>(Vec<SequentialTask<E>>)
type Target (line 504) | type Target = Vec<SequentialTask<E>>;
function deref (line 506) | fn deref(&self) -> &Self::Target {
function deref_mut (line 515) | fn deref_mut(&mut self) -> &mut Self::Target {
method drop (line 524) | fn drop(&mut self) {
type StackLimitChecker (line 534) | pub struct StackLimitChecker {
method new (line 542) | pub fn new(stack_size_limit: usize) -> Self {
method limit_exceeded (line 550) | pub fn limit_exceeded(&self) -> bool {
method get_sp (line 590) | fn get_sp() -> usize {
type ThreadLocalStyleContext (line 601) | pub struct ThreadLocalStyleContext<E: TElement> {
function new (line 627) | pub fn new() -> Self {
type StyleContext (line 644) | pub struct StyleContext<'a, E: TElement + 'a> {
type RegisteredSpeculativePainter (line 653) | pub trait RegisteredSpeculativePainter: SpeculativePainter {
method name (line 655) | fn name(&self) -> Atom;
method properties (line 657) | fn properties(&self) -> &FxHashMap<Atom, PropertyId>;
type RegisteredSpeculativePainters (line 662) | pub trait RegisteredSpeculativePainters: Sync {
method get (line 664) | fn get(&self, name: &Atom) -> Option<&dyn RegisteredSpeculativePainter>;
FILE: style/counter_style/mod.rs
type SymbolsType (line 47) | pub enum SymbolsType {
type CounterStyle (line 63) | pub enum CounterStyle {
method disc (line 88) | pub fn disc() -> Self {
method decimal (line 93) | pub fn decimal() -> Self {
method is_bullet (line 99) | pub fn is_bullet(&self) -> bool {
method parse (line 126) | pub fn parse<'i, 't>(
function is_symbolic (line 82) | fn is_symbolic(symbols_type: &SymbolsType) -> bool {
method collect_completion_keywords (line 173) | fn collect_completion_keywords(f: KeywordsCollectFn) {
function parse_counter_style_name (line 188) | fn parse_counter_style_name<'i>(input: &mut Parser<'i, '_>) -> Result<Cu...
function counter_style_name_from_ident (line 195) | fn counter_style_name_from_ident<'i>(
function is_valid_name_definition (line 221) | fn is_valid_name_definition(ident: &CustomIdent) -> bool {
function parse_counter_style_name_definition (line 231) | pub fn parse_counter_style_name_definition<'i, 't>(
type CounterStyleRule (line 245) | pub struct CounterStyleRule {
method empty (line 331) | fn empty(name: CustomIdent, source_location: SourceLocation) -> Self {
method descriptors (line 342) | pub fn descriptors(&self) -> &Descriptors {
method set_descriptor (line 347) | pub fn set_descriptor<'i>(
method check_system (line 396) | fn check_system(&self, value: &System) -> bool {
method check_symbols (line 400) | fn check_symbols(&self, value: &Symbols) -> bool {
method name (line 411) | pub fn name(&self) -> &CustomIdent {
method set_name (line 417) | pub fn set_name(&mut self, name: CustomIdent) {
method generation (line 423) | pub fn generation(&self) -> u32 {
method resolved_system (line 429) | pub fn resolved_system(&self) -> &System {
function parse_counter_style_body (line 254) | pub fn parse_counter_style_body<'i, 't>(
method to_css (line 319) | fn to_css(&self, _guard: &SharedRwLockReadGuard, dest: &mut CssStringWri...
type System (line 439) | pub enum System {
method parse (line 460) | fn parse<'i, 't>(
method to_css (line 483) | fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
type Symbol (line 514) | pub enum Symbol {
method is_allowed_in_symbols (line 540) | pub fn is_allowed_in_symbols(&self) -> bool {
method parse (line 525) | fn parse<'i, 't>(
type Negative (line 551) | pub struct Negative(pub Symbol, pub Option<Symbol>);
method parse (line 554) | fn parse<'i, 't>(
type CounterRange (line 567) | pub struct CounterRange {
type CounterRanges (line 579) | pub struct CounterRanges(#[css(iterable, if_empty = "auto")] pub crate::...
type CounterBound (line 583) | pub enum CounterBound {
method parse (line 591) | fn parse<'i, 't>(
function parse_bound (line 617) | fn parse_bound<'i, 't>(
type Pad (line 630) | pub struct Pad(pub Integer, pub Symbol);
method parse (line 633) | fn parse<'i, 't>(
type Fallback (line 646) | pub struct Fallback(pub CustomIdent);
method parse (line 649) | fn parse<'i, 't>(
type Symbols (line 662) | pub struct Symbols(
method parse (line 669) | fn parse<'i, 't>(
type AdditiveSymbols (line 687) | pub struct AdditiveSymbols(#[css(iterable)] pub crate::OwnedSlice<Additi...
method parse (line 690) | fn parse<'i, 't>(
type AdditiveTuple (line 708) | pub struct AdditiveTuple {
type S (line 716) | type S = Comma;
method parse (line 720) | fn parse<'i, 't>(
type SpeakAs (line 733) | pub enum SpeakAs {
method parse (line 749) | fn parse<'i, 't>(
FILE: style/counter_style/update_predefined.py
function main (line 12) | def main(filename):
FILE: style/custom_properties.rs
type CssEnvironment (line 58) | pub struct CssEnvironment;
method get (line 209) | fn get(&self, name: &Atom, device: &Device, url_data: &UrlExtraData) -...
type EnvironmentEvaluator (line 60) | type EnvironmentEvaluator = fn(device: &Device, url_data: &UrlExtraData)...
type EnvironmentVariable (line 62) | struct EnvironmentVariable {
function get_safearea_inset_top (line 76) | fn get_safearea_inset_top(device: &Device, url_data: &UrlExtraData) -> V...
function get_safearea_inset_bottom (line 80) | fn get_safearea_inset_bottom(device: &Device, url_data: &UrlExtraData) -...
function get_safearea_inset_left (line 84) | fn get_safearea_inset_left(device: &Device, url_data: &UrlExtraData) -> ...
function get_safearea_inset_right (line 88) | fn get_safearea_inset_right(device: &Device, url_data: &UrlExtraData) ->...
function get_content_preferred_color_scheme (line 93) | fn get_content_preferred_color_scheme(device: &Device, url_data: &UrlExt...
function get_content_preferred_color_scheme (line 111) | fn get_content_preferred_color_scheme(_device: &Device, url_data: &UrlEx...
function get_scrollbar_inline_size (line 116) | fn get_scrollbar_inline_size(device: &Device, url_data: &UrlExtraData) -...
function get_hairline (line 120) | fn get_hairline(device: &Device, url_data: &UrlExtraData) -> VariableVal...
function eval_gtk_csd_titlebar_radius (line 162) | fn eval_gtk_csd_titlebar_radius(device: &Device, url_data: &UrlExtraData...
type Name (line 226) | pub type Name = Atom;
function parse_name (line 231) | pub fn parse_name(s: &str) -> Result<&str, ()> {
type VariableValue (line 244) | pub struct VariableValue {
method empty (line 769) | fn empty(url_data: &UrlExtraData) -> Self {
method new (line 781) | pub fn new(
method push (line 796) | fn push<'i>(
method parse (line 844) | pub fn parse<'i, 't>(
method is_attr_tainted (line 887) | pub fn is_attr_tainted(&self) -> bool {
method integer (line 892) | fn integer(number: i32, url_data: &UrlExtraData) -> Self {
method ident (line 904) | fn ident(ident: &'static str, url_data: &UrlExtraData) -> Self {
method pixels (line 909) | fn pixels(number: f32, url_data: &UrlExtraData) -> Self {
method int_ms (line 925) | fn int_ms(number: i32, url_data: &UrlExtraData) -> Self {
method int_pixels (line 938) | fn int_pixels(number: i32, url_data: &UrlExtraData) -> Self {
method from_token (line 950) | fn from_token(token: Token, url_data: &UrlExtraData) -> Self {
method css_text (line 965) | pub fn css_text(&self) -> &str {
method has_references (line 971) | pub fn has_references(&self) -> bool {
function compute_variable_value (line 261) | pub fn compute_variable_value(
method eq (line 281) | fn eq(&self, other: &Self) -> bool {
method to_css (line 289) | fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
method to_typed (line 298) | fn to_typed(&self, dest: &mut ThinVec<TypedValue>) -> Result<(), ()> {
function reify_variable_value (line 305) | fn reify_variable_value(value: &VariableValue) -> Result<UnparsedValue, ...
function reify_variable_value_range (line 322) | fn reify_variable_value_range(
type ComputedCustomProperties (line 395) | pub struct ComputedCustomProperties {
method is_empty (line 405) | pub fn is_empty(&self) -> bool {
method property_at (line 410) | pub fn property_at(&self, index: usize) -> Option<(&Name, &Option<Comp...
method insert (line 420) | pub(crate) fn insert(
method remove (line 431) | pub(crate) fn remove(&mut self, registration: &PropertyDescriptors, na...
method shrink_to_fit (line 436) | fn shrink_to_fit(&mut self) {
method map_mut (line 441) | fn map_mut(&mut self, registration: &PropertyDescriptors) -> &mut Cust...
method get (line 450) | pub fn get(
type SpecifiedValue (line 465) | pub type SpecifiedValue = VariableValue;
type ComputedValue (line 468) | pub type ComputedValue = VariableValue;
type NonCustomReferences (line 472) | struct NonCustomReferences(u8);
method for_each (line 492) | fn for_each<F>(&self, mut f: F)
method from_unit (line 508) | fn from_unit(value: &CowRcStr) -> Self {
type SingleNonCustomReference (line 540) | enum SingleNonCustomReference {
type NonCustomReferenceMap (line 547) | struct NonCustomReferenceMap<T>([Option<T>; 4]);
method default (line 550) | fn default() -> Self {
type Output (line 556) | type Output = Option<T>;
function index (line 558) | fn index(&self, reference: SingleNonCustomReference) -> &Self::Output {
function index_mut (line 564) | fn index_mut(&mut self, reference: SingleNonCustomReference) -> &mut Sel...
type DeferFontRelativeCustomPropertyResolution (line 572) | pub enum DeferFontRelativeCustomPropertyResolution {
type SubstitutionFunctionKind (line 579) | pub enum SubstitutionFunctionKind {
type ComputedSubstitutionFunctions (line 592) | pub struct ComputedSubstitutionFunctions {
method new (line 603) | pub fn new(
method insert_var (line 614) | fn insert_var(
method insert_attr (line 624) | fn insert_attr(&mut self, name: &Name, value: ComputedRegisteredValue) {
method remove_var (line 629) | fn remove_var(&mut self, registration: &PropertyDescriptors, name: &Na...
method remove_attr (line 634) | fn remove_attr(&mut self, name: &Name) {
method get_var (line 639) | fn get_var(
method get_attr (line 648) | fn get_attr(&self, name: &Name) -> Option<&ComputedRegisteredValue> {
type AttributeType (line 654) | enum AttributeType {
type AttributeData (line 662) | struct AttributeData {
type AttrTaintedRange (line 669) | pub struct AttrTaintedRange {
method new (line 679) | pub fn new(start: usize, end: usize) -> Self {
type AttrTaint (line 690) | pub struct AttrTaint(SmallVec<[AttrTaintedRange; 1]>);
method should_disallow_urls_in_range (line 696) | pub fn should_disallow_urls_in_range(&self, range: &AttrTaintedRange) ...
method is_empty (line 704) | pub fn is_empty(&self) -> bool {
method new_fully_tainted (line 709) | fn new_fully_tainted(end: usize) -> Self {
method push (line 716) | fn push(&mut self, start: usize, end: usize) {
type VariableFallback (line 722) | struct VariableFallback {
type SubstitutionFunctionReference (line 732) | struct SubstitutionFunctionReference {
type References (line 746) | struct References {
method has_references (line 755) | fn has_references(&self) -> bool {
method non_custom_references (line 759) | fn non_custom_references(&self, is_root_element: bool) -> NonCustomRef...
function parse_declaration_value (line 977) | fn parse_declaration_value<'i, 't>(
function parse_declaration_value_block (line 996) | fn parse_declaration_value_block<'i, 't>(
function parse_attr_type (line 1250) | fn parse_attr_type<'i, 't>(input: &mut Parser<'i, 't>) -> AttributeType {
function parse_attribute_value (line 1278) | fn parse_attribute_value(
type SeenSubstitutionFunctions (line 1301) | struct SeenSubstitutionFunctions<'a> {
type CustomPropertiesBuilder (line 1307) | pub struct CustomPropertiesBuilder<'a, 'b: 'a> {
function find_non_custom_references (line 1318) | fn find_non_custom_references(
function new_with_properties (line 1348) | pub fn new_with_properties(
function new (line 1369) | pub fn new(stylist: &'a Stylist, context: &'a mut computed::Context<'b>)...
function cascade (line 1393) | pub fn cascade(
function might_have_non_custom_or_attr_dependency (line 1505) | pub fn might_have_non_custom_or_attr_dependency(
function maybe_note_non_custom_dependency (line 1521) | pub fn maybe_note_non_custom_dependency(
function value_may_affect_style (line 1607) | fn value_may_affect_style(&self, name: &Name, value: &CustomDeclarationV...
function update_attributes_map (line 1724) | pub fn update_attributes_map(
function build (line 1768) | pub fn build(
function build_deferred (line 1836) | pub fn build_deferred(
function substitute_all (line 1870) | fn substitute_all(
function handle_invalid_at_computed_value_time (line 2348) | fn handle_invalid_at_computed_value_time(
function substitute_references_if_needed_and_apply (line 2388) | fn substitute_references_if_needed_and_apply(
type Substitution (line 2510) | struct Substitution<'a> {
function from_value (line 2518) | fn from_value(v: VariableValue, attr_tainted: bool) -> Self {
function into_value (line 2527) | fn into_value(
function new (line 2557) | fn new(
type SubstitutionResult (line 2574) | pub struct SubstitutionResult<'a> {
function compute_value (line 2581) | fn compute_value(
function remove_and_insert_initial_value (line 2605) | fn remove_and_insert_initial_value(
function do_substitute_chunk (line 2617) | fn do_substitute_chunk<'a>(
function quoted_css_string (line 2706) | fn quoted_css_string(src: &str) -> String {
function substitute_one_reference (line 2712) | fn substitute_one_reference<'a>(
function substitute_internal (line 2863) | fn substitute_internal<'a>(
function substitute (line 2889) | pub fn substitute<'a>(
FILE: style/custom_properties_map.rs
type CustomPropertiesMap (line 19) | pub struct CustomPropertiesMap(Arc<Inner>);
method is_empty (line 154) | pub fn is_empty(&self) -> bool {
method len (line 159) | pub fn len(&self) -> usize {
method get_index (line 164) | pub fn get_index(&self, index: usize) -> Option<(&Name, &Option<Comput...
method get (line 173) | pub fn get(&self, name: &Name) -> Option<&ComputedRegisteredValue> {
method do_insert (line 177) | fn do_insert(&mut self, name: &Name, value: Option<ComputedRegisteredV...
method insert (line 201) | pub fn insert(&mut self, name: &Name, value: ComputedRegisteredValue) {
method remove (line 206) | pub fn remove(&mut self, name: &Name) {
method shrink_to_fit (line 211) | pub fn shrink_to_fit(&mut self) {
method iter (line 218) | pub fn iter(&self) -> Iter<'_> {
method default (line 22) | fn default() -> Self {
type OwnMap (line 28) | pub type OwnMap =
type Inner (line 41) | struct Inner {
method iter (line 112) | fn iter(&self) -> Iter<'_> {
method is_empty (line 120) | fn is_empty(&self) -> bool {
method len (line 124) | fn len(&self) -> usize {
method get (line 128) | fn get(&self, name: &Name) -> Option<&ComputedRegisteredValue> {
method insert (line 135) | fn insert(&mut self, name: &Name, value: Option<ComputedRegisteredValu...
method should_expand_chain (line 143) | fn should_expand_chain(&self) -> bool {
constant ANCESTOR_COUNT_LIMIT (line 52) | const ANCESTOR_COUNT_LIMIT: usize = 4;
type Iter (line 55) | pub struct Iter<'a> {
type Item (line 62) | type Item = (&'a Name, &'a Option<ComputedRegisteredValue>);
method next (line 64) | fn next(&mut self) -> Option<Self::Item> {
method eq (line 88) | fn eq(&self, other: &Self) -> bool {
type AllSubstitutionFunctions (line 225) | pub struct AllSubstitutionFunctions(IndexMap<Key, ComputedRegisteredValu...
method is_empty (line 242) | pub fn is_empty(&self) -> bool {
method get (line 248) | pub fn get(
method insert (line 259) | pub fn insert(
method iter (line 272) | pub fn iter(
type Key (line 228) | struct Key(Name, SubstitutionFunctionKind);
type KeyRef (line 231) | struct KeyRef<'a>(&'a Name, SubstitutionFunctionKind);
function equivalent (line 234) | fn equivalent(&self, key: &Key) -> bool {
FILE: style/data.rs
type EagerPseudoStyles (line 60) | pub struct EagerPseudoStyles(Option<Arc<EagerPseudoArray>>);
method is_empty (line 116) | pub fn is_empty(&self) -> bool {
method as_optional_array (line 121) | pub fn as_optional_array(&self) -> Option<&EagerPseudoArrayInner> {
method as_array (line 130) | pub fn as_array(&self) -> &EagerPseudoArrayInner {
method get (line 135) | pub fn get(&self, pseudo: &PseudoElement) -> Option<&Arc<ComputedValue...
method set (line 143) | pub fn set(&mut self, pseudo: &PseudoElement, value: Arc<ComputedValue...
type EagerPseudoArray (line 63) | struct EagerPseudoArray(EagerPseudoArrayInner);
method fmt (line 94) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
type EagerPseudoArrayInner (line 64) | type EagerPseudoArrayInner = [Option<Arc<ComputedValues>>; EAGER_PSEUDO_...
type Target (line 67) | type Target = EagerPseudoArrayInner;
method deref (line 68) | fn deref(&self) -> &Self::Target {
method deref_mut (line 74) | fn deref_mut(&mut self) -> &mut Self::Target {
method clone (line 82) | fn clone(&self) -> Self {
constant EMPTY_PSEUDO_ARRAY (line 112) | const EMPTY_PSEUDO_ARRAY: &'static EagerPseudoArrayInner = &[None, None,...
type ElementStyles (line 155) | pub struct ElementStyles {
method get_primary (line 180) | pub fn get_primary(&self) -> Option<&Arc<ComputedValues>> {
method primary (line 185) | pub fn primary(&self) -> &Arc<ComputedValues> {
method is_display_none (line 190) | pub fn is_display_none(&self) -> bool {
method viewport_unit_usage (line 195) | pub fn viewport_unit_usage(&self) -> ViewportUnitUsage {
method size_of_excluding_cvs (line 228) | fn size_of_excluding_cvs(&self, _ops: &mut MallocSizeOfOps) -> usize {
method fmt (line 243) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
type ViewportUnitUsage (line 167) | pub enum ViewportUnitUsage {
type ElementData (line 259) | pub struct ElementData {
method invalidate_style_if_needed (line 391) | pub fn invalidate_style_if_needed<'a, E: TElement>(
method has_styles (line 435) | pub fn has_styles(&self) -> bool {
method share_styles (line 440) | pub fn share_styles(&self) -> ResolvedElementStyles {
method share_primary_style (line 448) | pub fn share_primary_style(&self) -> PrimaryStyle {
method clone_style_with_flags (line 461) | pub fn clone_style_with_flags(&self, flags: ComputedValueFlags) -> Res...
method set_styles (line 474) | pub fn set_styles(&mut self, new_styles: ResolvedElementStyles) -> Ele...
method restyle_kind (line 484) | pub fn restyle_kind(&self, shared_context: &SharedStyleContext) -> Opt...
method restyle_kind_for_animation (line 526) | fn restyle_kind_for_animation(
method clear_restyle_state (line 571) | pub fn clear_restyle_state(&mut self) {
method clear_restyle_flags_and_damage (line 578) | pub fn clear_restyle_flags_and_damage(&mut self) {
method set_restyled (line 585) | pub fn set_restyled(&mut self) {
method is_restyle (line 593) | pub fn is_restyle(&self) -> bool {
method set_traversed_without_styling (line 598) | pub fn set_traversed_without_styling(&mut self) {
method contains_restyle_data (line 605) | pub fn contains_restyle_data(&self) -> bool {
method safe_for_cousin_sharing (line 627) | pub fn safe_for_cousin_sharing(&self) -> bool {
method size_of_excluding_cvs (line 648) | pub fn size_of_excluding_cvs(&self, ops: &mut MallocSizeOfOps) -> usize {
type ElementDataWrapper (line 277) | pub struct ElementDataWrapper {
method borrow (line 303) | pub fn borrow(&self) -> ElementDataRef<'_> {
method borrow_mut (line 315) | pub fn borrow_mut(&self) -> ElementDataMut<'_> {
type ElementDataMut (line 286) | pub struct ElementDataMut<'a> {
type ElementDataRef (line 294) | pub struct ElementDataRef<'a> {
type Target (line 327) | type Target = ElementData;
method deref (line 329) | fn deref(&self) -> &Self::Target {
type Target (line 335) | type Target = ElementData;
method deref (line 337) | fn deref(&self) -> &Self::Target {
method deref_mut (line 343) | fn deref_mut(&mut self) -> &mut Self::Target {
type RestyleKind (line 353) | pub enum RestyleKind {
function needs_to_match_self (line 365) | fn needs_to_match_self(hint: RestyleHint, style: &ComputedValues) -> bool {
FILE: style/device/gecko.rs
type ExtraDeviceData (line 37) | pub(super) struct ExtraDeviceData {
method new (line 48) | pub fn new(document: *const structs::Document) -> Self {
method calc_line_height (line 80) | pub fn calc_line_height(
method animation_name_may_be_referenced (line 102) | pub fn animation_name_may_be_referenced(&self, name: &KeyframesName) -> ...
method quirks_mode (line 114) | pub fn quirks_mode(&self) -> QuirksMode {
method base_size_for_generic (line 119) | pub fn base_size_for_generic(&self, language: &Atom, generic: GenericFon...
method scrollbar_inline_size (line 124) | pub fn scrollbar_inline_size(&self) -> Length {
method query_font_metrics (line 134) | pub fn query_font_metrics(
method document (line 184) | pub fn document(&self) -> &structs::Document {
method pres_context (line 190) | pub fn pres_context(&self) -> Option<&structs::nsPresContext> {
method pref_sheet_prefs (line 203) | pub fn pref_sheet_prefs(&self) -> &structs::PreferenceSheet_Prefs {
method reset_computed_values (line 208) | pub fn reset_computed_values(&mut self) {
method rebuild_cached_data (line 213) | pub fn rebuild_cached_data(&mut self) {
method reset (line 228) | pub fn reset(&mut self) {
method is_print_preview (line 233) | pub fn is_print_preview(&self) -> bool {
method media_type (line 242) | pub fn media_type(&self) -> MediaType {
method page_size_minus_default_margin (line 261) | fn page_size_minus_default_margin(&self, pc: &structs::nsPresContext) ->...
method au_viewport_size (line 271) | pub fn au_viewport_size(&self) -> Size2D<Au> {
method au_viewport_size_for_viewport_unit_resolution (line 287) | pub fn au_viewport_size_for_viewport_unit_resolution(
method visited_styles_enabled (line 343) | pub fn visited_styles_enabled(&self) -> bool {
method app_units_per_device_pixel (line 348) | pub fn app_units_per_device_pixel(&self) -> i32 {
method app_units_per_device_pixel_at_unit_full_zoom (line 356) | fn app_units_per_device_pixel_at_unit_full_zoom(&self) -> i32 {
method device_pixel_ratio_ignoring_full_zoom (line 364) | pub fn device_pixel_ratio_ignoring_full_zoom(&self) -> Scale<f32, CSSPix...
method device_pixel_ratio (line 370) | pub fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
method forced_colors (line 387) | pub fn forced_colors(&self) -> ForcedColors {
method system_nscolor (line 393) | pub(crate) fn system_nscolor(
method is_dark_color_scheme (line 402) | pub(crate) fn is_dark_color_scheme(&self, color_scheme: ColorSchemeFlags...
method default_background_color (line 410) | pub fn default_background_color(&self) -> AbsoluteColor {
method default_color (line 419) | pub fn default_color(&self) -> AbsoluteColor {
method text_zoom (line 427) | fn text_zoom(&self) -> f32 {
method zoom_text (line 437) | pub fn zoom_text(&self, size: Length) -> Length {
method unzoom_text (line 443) | pub fn unzoom_text(&self, size: Length) -> Length {
method safe_area_insets (line 448) | pub fn safe_area_insets(&self) -> SideOffsets2D<f32, CSSPixel> {
method is_supported_mime_type (line 464) | pub fn is_supported_mime_type(&self, mime_type: &str) -> bool {
method chrome_rules_enabled_for_document (line 475) | pub fn chrome_rules_enabled_for_document(&self) -> bool {
method fmt (line 481) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
FILE: style/device/mod.rs
type Device (line 42) | pub struct Device {
method environment (line 97) | pub fn environment(&self) -> &CssEnvironment {
method default_computed_values (line 103) | pub fn default_computed_values(&self) -> &ComputedValues {
method default_computed_values_arc (line 108) | pub fn default_computed_values_arc(&self) -> &Arc<ComputedValues> {
method set_root_style (line 114) | pub fn set_root_style(&self, style: &Arc<ComputedValues>) {
method root_font_size (line 119) | pub fn root_font_size(&self) -> Length {
method set_root_font_size (line 125) | pub fn set_root_font_size(&self, size: f32) {
method root_line_height (line 130) | pub fn root_line_height(&self) -> Length {
method set_root_line_height (line 138) | pub fn set_root_line_height(&self, size: f32) {
method root_font_metrics_ex (line 144) | pub fn root_font_metrics_ex(&self) -> Length {
method set_root_font_metrics_ex (line 152) | pub fn set_root_font_metrics_ex(&self, size: f32) -> bool {
method root_font_metrics_cap (line 159) | pub fn root_font_metrics_cap(&self) -> Length {
method set_root_font_metrics_cap (line 167) | pub fn set_root_font_metrics_cap(&self, size: f32) -> bool {
method root_font_metrics_ch (line 174) | pub fn root_font_metrics_ch(&self) -> Length {
method set_root_font_metrics_ch (line 182) | pub fn set_root_font_metrics_ch(&self, size: f32) -> bool {
method root_font_metrics_ic (line 189) | pub fn root_font_metrics_ic(&self) -> Length {
method set_root_font_metrics_ic (line 197) | pub fn set_root_font_metrics_ic(&self, size: f32) -> bool {
method ensure_root_font_metrics_updated (line 203) | fn ensure_root_font_metrics_updated(&self) {
method update_root_font_metrics (line 213) | pub fn update_root_font_metrics(&self) -> bool {
method used_root_font_size (line 253) | pub fn used_root_font_size(&self) -> bool {
method used_root_line_height (line 258) | pub fn used_root_line_height(&self) -> bool {
method used_root_font_metrics (line 263) | pub fn used_root_font_metrics(&self) -> bool {
method used_viewport_size (line 268) | pub fn used_viewport_size(&self) -> bool {
method used_dynamic_viewport_size (line 273) | pub fn used_dynamic_viewport_size(&self) -> bool {
method used_font_metrics (line 278) | pub fn used_font_metrics(&self) -> bool {
method body_text_color (line 283) | pub fn body_text_color(&self) -> AbsoluteColor {
method set_body_text_color (line 290) | pub fn set_body_text_color(&self, color: AbsoluteColor) {
FILE: style/device/servo.rs
type FontMetricsProvider (line 40) | pub trait FontMetricsProvider: Debug + Sync {
method query_font_metrics (line 42) | fn query_font_metrics(
method base_size_for_generic (line 50) | fn base_size_for_generic(&self, generic: GenericFontFamily) -> Length;
type ExtraDeviceData (line 54) | pub(super) struct ExtraDeviceData {
method new (line 74) | pub fn new(
method calc_line_height (line 115) | pub fn calc_line_height(
method quirks_mode (line 131) | pub fn quirks_mode(&self) -> QuirksMode {
method base_size_for_generic (line 136) | pub fn base_size_for_generic(&self, generic: GenericFontFamily) -> Length {
method animation_name_may_be_referenced (line 143) | pub fn animation_name_may_be_referenced(&self, _: &KeyframesName) -> bool {
method viewport_size (line 149) | pub fn viewport_size(&self) -> Size2D<f32, CSSPixel> {
method set_viewport_size (line 158) | pub fn set_viewport_size(&mut self, viewport_size: Size2D<f32, CSSPixel>) {
method au_viewport_size (line 165) | pub fn au_viewport_size(&self) -> UntypedSize2D<Au> {
method au_viewport_size_for_viewport_unit_resolution (line 173) | pub fn au_viewport_size_for_viewport_unit_resolution(
method app_units_per_device_pixel (line 184) | pub fn app_units_per_device_pixel(&self) -> i32 {
method device_pixel_ratio_ignoring_full_zoom (line 189) | pub fn device_pixel_ratio_ignoring_full_zoom(&self) -> Scale<f32, CSSPix...
method device_pixel_ratio (line 194) | pub fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
method set_device_pixel_ratio (line 203) | pub fn set_device_pixel_ratio(
method scrollbar_inline_size (line 211) | pub fn scrollbar_inline_size(&self) -> CSSPixelLength {
method query_font_metrics (line 217) | pub fn query_font_metrics(
method media_type (line 234) | pub fn media_type(&self) -> MediaType {
method forced_colors (line 239) | pub fn forced_colors(&self) -> ForcedColors {
method default_background_color (line 244) | pub fn default_background_color(&self) -> AbsoluteColor {
method default_color (line 249) | pub fn default_color(&self) -> AbsoluteColor {
method set_color_scheme (line 258) | pub fn set_color_scheme(&mut self, new_color_scheme: PrefersColorScheme) {
method color_scheme (line 263) | pub fn color_scheme(&self) -> PrefersColorScheme {
method is_dark_color_scheme (line 267) | pub(crate) fn is_dark_color_scheme(&self, _: ColorSchemeFlags) -> bool {
method system_color (line 271) | pub(crate) fn system_color(
method safe_area_insets (line 387) | pub fn safe_area_insets(&self) -> SideOffsets2D<f32, CSSPixel> {
method is_supported_mime_type (line 392) | pub fn is_supported_mime_type(&self, mime_type: &str) -> bool {
method chrome_rules_enabled_for_document (line 410) | pub fn chrome_rules_enabled_for_document(&self) -> bool {
FILE: style/dom.rs
type NodeInfo (line 42) | pub trait NodeInfo {
method is_element (line 44) | fn is_element(&self) -> bool;
method is_text_node (line 46) | fn is_text_node(&self) -> bool;
type LayoutIterator (line 50) | pub struct LayoutIterator<T>(pub T);
type Item (line 57) | type Item = N;
method next (line 59) | fn next(&mut self) -> Option<N> {
type DomChildren (line 71) | pub struct DomChildren<N>(Option<N>);
type Item (line 76) | type Item = N;
method next (line 78) | fn next(&mut self) -> Option<N> {
type DomDescendants (line 86) | pub struct DomDescendants<N> {
function next_skipping_children (line 97) | pub fn next_skipping_children(&mut self) -> Option<N> {
type Item (line 108) | type Item = N;
method next (line 111) | fn next(&mut self) -> Option<N> {
type TDocument (line 119) | pub trait TDocument: Sized + Copy + Clone {
method as_node (line 124) | fn as_node(&self) -> Self::ConcreteNode;
method is_html_document (line 127) | fn is_html_document(&self) -> bool;
method quirks_mode (line 130) | fn quirks_mode(&self) -> QuirksMode;
method elements_with_id (line 137) | fn elements_with_id<'a>(
method shared_lock (line 148) | fn shared_lock(&self) -> &SharedRwLock;
type TNode (line 153) | pub trait TNode: Sized + Copy + Clone + Debug + NodeInfo + PartialEq {
method parent_node (line 164) | fn parent_node(&self) -> Option<Self>;
method first_child (line 167) | fn first_child(&self) -> Option<Self>;
method last_child (line 170) | fn last_child(&self) -> Option<Self>;
method prev_sibling (line 173) | fn prev_sibling(&self) -> Option<Self>;
method next_sibling (line 176) | fn next_sibling(&self) -> Option<Self>;
method owner_doc (line 179) | fn owner_doc(&self) -> Self::ConcreteDocument;
method dom_children (line 183) | fn dom_children(&self) -> DomChildren<Self> {
method is_in_document (line 188) | fn is_in_document(&self) -> bool;
method dom_descendants (line 192) | fn dom_descendants(&self) -> DomDescendants<Self> {
method next_in_preorder (line 202) | fn next_in_preorder(&self, scoped_to: Self) -> Option<Self> {
method next_in_preorder_skipping_children (line 214) | fn next_in_preorder_skipping_children(&self, scoped_to: Self) -> Optio...
method depth (line 234) | fn depth(&self) -> usize {
method traversal_parent (line 246) | fn traversal_parent(&self) -> Option<Self::ConcreteElement>;
method parent_element (line 249) | fn parent_element(&self) -> Option<Self::ConcreteElement> {
method parent_element_or_host (line 254) | fn parent_element_or_host(&self) -> Option<Self::ConcreteElement> {
method opaque (line 266) | fn opaque(&self) -> OpaqueNode;
method debug_id (line 269) | fn debug_id(self) -> usize;
method as_element (line 272) | fn as_element(&self) -> Option<Self::ConcreteElement>;
method as_document (line 275) | fn as_document(&self) -> Option<Self::ConcreteDocument>;
method as_shadow_root (line 278) | fn as_shadow_root(&self) -> Option<Self::ConcreteShadowRoot>;
type ShowSubtree (line 283) | pub struct ShowSubtree<N: TNode>(pub N);
method fmt (line 285) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
type ShowSubtreeData (line 293) | pub struct ShowSubtreeData<N: TNode>(pub N);
method fmt (line 295) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
type ShowSubtreeDataAndPrimaryValues (line 304) | pub struct ShowSubtreeDataAndPrimaryValues<N: TNode>(pub N);
method fmt (line 307) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
function fmt_with_data (line 313) | fn fmt_with_data<N: TNode>(f: &mut fmt::Formatter, n: N) -> fmt::Result {
function fmt_with_data_and_primary_values (line 329) | fn fmt_with_data_and_primary_values<N: TNode>(f: &mut fmt::Formatter, n:...
function fmt_subtree (line 345) | fn fmt_subtree<F, N: TNode>(f: &mut fmt::Formatter, stringify: &F, n: N,...
type TShadowRoot (line 364) | pub trait TShadowRoot: Sized + Copy + Clone + Debug + PartialEq {
method as_node (line 369) | fn as_node(&self) -> Self::ConcreteNode;
method host (line 372) | fn host(&self) -> <Self::ConcreteNode as TNode>::ConcreteElement;
method style_data (line 375) | fn style_data<'a>(&self) -> Option<&'a CascadeData>
method parts (line 380) | fn parts<'a>(&self) -> &[<Self::ConcreteNode as TNode>::ConcreteElement]
method elements_with_id (line 392) | fn elements_with_id<'a>(
method implicit_scope_for_sheet (line 403) | fn implicit_scope_for_sheet(&self, _sheet_index: usize) -> Option<Impl...
type TElement (line 409) | pub trait TElement:
method as_node (line 430) | fn as_node(&self) -> Self::ConcreteNode;
method owner_doc_matches_for_testing (line 437) | fn owner_doc_matches_for_testing(&self, _: &Device) -> bool {
method matches_user_and_content_rules (line 444) | fn matches_user_and_content_rules(&self) -> bool {
method traversal_parent (line 450) | fn traversal_parent(&self) -> Option<Self> {
method traversal_children (line 455) | fn traversal_children(&self) -> LayoutIterator<Self::TraversalChildren...
method inheritance_parent (line 463) | fn inheritance_parent(&self) -> Option<Self> {
method each_anonymous_content_child (line 469) | fn each_anonymous_content_child<F>(&self, _f: F)
method is_html_element (line 476) | fn is_html_element(&self) -> bool;
method is_mathml_element (line 479) | fn is_mathml_element(&self) -> bool;
method is_svg_element (line 482) | fn is_svg_element(&self) -> bool;
method is_xul_element (line 485) | fn is_xul_element(&self) -> bool {
method subtree_bloom_filter (line 497) | fn subtree_bloom_filter(&self) -> u64 {
method bloom_may_have_hash (line 502) | fn bloom_may_have_hash(&self, bloom_hash: u64) -> bool {
method hash_for_bloom_filter (line 509) | fn hash_for_bloom_filter(hash: u32) -> u64 {
method slotted_nodes (line 525) | fn slotted_nodes(&self) -> &[Self::ConcreteNode] {
method style_attribute (line 530) | fn style_attribute(&self) -> Option<ArcBorrow<'_, Locked<PropertyDecla...
method unset_dirty_style_attribute (line 534) | fn unset_dirty_style_attribute(&self) {}
method smil_override (line 537) | fn smil_override(&self) -> Option<ArcBorrow<'_, Locked<PropertyDeclara...
method animation_declarations (line 544) | fn animation_declarations(&self, context: &SharedStyleContext) -> Anim...
method animation_rule (line 556) | fn animation_rule(
method transition_rule (line 562) | fn transition_rule(
method state (line 568) | fn state(&self) -> ElementState;
method has_part_attr (line 571) | fn has_part_attr(&self) -> bool;
method exports_any_part (line 574) | fn exports_any_part(&self) -> bool;
method id (line 577) | fn id(&self) -> Option<&WeakAtom>;
method each_class (line 580) | fn each_class<F>(&self, callback: F)
method each_custom_state (line 585) | fn each_custom_state<F>(&self, callback: F)
method each_part (line 590) | fn each_part<F>(&self, _callback: F)
method each_attr_name (line 597) | fn each_attr_name<F>(&self, callback: F)
method each_exported_part (line 603) | fn each_exported_part<F>(&self, _name: &AtomIdent, _callback: F)
method may_generate_pseudo (line 615) | fn may_generate_pseudo(&self, pseudo: &PseudoElement, _primary_style: ...
method has_dirty_descendants (line 636) | fn has_dirty_descendants(&self) -> bool;
method has_snapshot (line 641) | fn has_snapshot(&self) -> bool;
method handled_snapshot (line 644) | fn handled_snapshot(&self) -> bool;
method set_handled_snapshot (line 647) | unsafe fn set_handled_snapshot(&self);
method has_current_styles (line 651) | fn has_current_styles(&self, data: &ElementData) -> bool {
method set_dirty_descendants (line 674) | unsafe fn set_dirty_descendants(&self);
method unset_dirty_descendants (line 679) | unsafe fn unset_dirty_descendants(&self);
method has_animation_only_dirty_descendants (line 683) | fn has_animation_only_dirty_descendants(&self) -> bool {
method set_animation_only_dirty_descendants (line 691) | unsafe fn set_animation_only_dirty_descendants(&self) {}
method unset_animation_only_dirty_descendants (line 696) | unsafe fn unset_animation_only_dirty_descendants(&self) {}
method clear_descendant_bits (line 703) | unsafe fn clear_descendant_bits(&self) {
method is_visited_link (line 710) | fn is_visited_link(&self) -> bool {
method implemented_pseudo_element (line 722) | fn implemented_pseudo_element(&self) -> Option<PseudoElement> {
method store_children_to_process (line 728) | fn store_children_to_process(&self, n: isize);
method did_process_child (line 732) | fn did_process_child(&self) -> isize;
method ensure_data (line 738) | unsafe fn ensure_data(&self) -> ElementDataMut<'_>;
method clear_data (line 743) | unsafe fn clear_data(&self);
method has_data (line 746) | fn has_data(&self) -> bool;
method borrow_data (line 749) | fn borrow_data(&self) -> Option<ElementDataRef<'_>>;
method mutate_data (line 752) | fn mutate_data(&self) -> Option<ElementDataMut<'_>>;
method skip_item_display_fixup (line 757) | fn skip_item_display_fixup(&self) -> bool;
method may_have_animations (line 762) | fn may_have_animations(&self) -> bool;
method update_animations (line 766) | fn update_animations(
method has_animations (line 775) | fn has_animations(&self, context: &SharedStyleContext) -> bool;
method has_css_animations (line 780) | fn has_css_animations(
method has_css_transitions (line 789) | fn has_css_transitions(
method has_animation_restyle_hints (line 796) | fn has_animation_restyle_hints(&self) -> bool {
method note_highlight_pseudo_style_invalidated (line 807) | fn note_highlight_pseudo_style_invalidated(&self) {}
method shadow_root (line 810) | fn shadow_root(&self) -> Option<<Self::ConcreteNode as TNode>::Concret...
method containing_shadow (line 813) | fn containing_shadow(&self) -> Option<<Self::ConcreteNode as TNode>::C...
method rule_hash_target (line 821) | fn rule_hash_target(&self) -> Self {
method each_applicable_non_document_style_rule_data (line 841) | fn each_applicable_non_document_style_rule_data<'a, F>(&self, mut f: F...
method needs_transitions_update (line 916) | fn needs_transitions_update(
method lang_attr (line 924) | fn lang_attr(&self) -> Option<AttrValue>;
method match_element_lang (line 931) | fn match_element_lang(&self, override_lang: Option<Option<AttrValue>>,...
method is_html_document_body_element (line 935) | fn is_html_document_body_element(&self) -> bool;
method synthesize_presentational_hints_for_legacy_attributes (line 939) | fn synthesize_presentational_hints_for_legacy_attributes<V>(
method synthesize_view_transition_dynamic_rules (line 949) | fn synthesize_view_transition_dynamic_rules<V>(&self, _rules: &mut V)
method local_name (line 956) | fn local_name(&self) -> &<SelectorImpl as selectors::parser::SelectorI...
method namespace (line 959) | fn namespace(&self)
method query_container_size (line 965) | fn query_container_size(
method has_selector_flags (line 971) | fn has_selector_flags(&self, flags: ElementSelectorFlags) -> bool;
method relative_selector_search_direction (line 974) | fn relative_selector_search_direction(&self) -> ElementSelectorFlags;
method implicit_scope_for_sheet_in_shadow_root (line 977) | fn implicit_scope_for_sheet_in_shadow_root(
method compute_layout_damage (line 985) | fn compute_layout_damage(_old: &ComputedValues, _new: &ComputedValues)...
type AttributeProvider (line 991) | pub trait AttributeProvider {
method get_attr (line 993) | fn get_attr(&self, attr: &LocalName, namespace: &Namespace) -> Option<...
method get_attr (line 1050) | fn get_attr(&self, _attr: &LocalName, _namespace: &Namespace) -> Optio...
type AttributeReferences (line 997) | pub type AttributeReferences = Option<Box<PrecomputedHashMap<LocalName, ...
type AttributeTracker (line 1000) | pub struct AttributeTracker<'a> {
function new (line 1009) | pub fn new(provider: &'a dyn AttributeProvider) -> Self {
function new_dummy (line 1017) | pub fn new_dummy() -> Self {
function finalize (line 1025) | pub fn finalize(self) -> AttributeReferences {
function query (line 1030) | pub fn query(&mut self, name: &LocalName, namespace: &Namespace) -> Opti...
type DummyAttributeProvider (line 1047) | struct DummyAttributeProvider;
type SendNode (line 1062) | pub struct SendNode<N: TNode>(N);
function new (line 1066) | pub unsafe fn new(node: N) -> Self {
type Target (line 1071) | type Target = N;
method deref (line 1072) | fn deref(&self) -> &N {
type SendElement (line 1080) | pub struct SendElement<E: TElement>(E);
function new (line 1084) | pub unsafe fn new(el: E) -> Self {
type Target (line 1089) | type Target = E;
method deref (line 1090) | fn deref(&self) -> &E {
FILE: style/dom_apis.rs
function element_matches (line 28) | pub fn element_matches<E>(
function element_closest (line 52) | pub fn element_closest<E>(
type SelectorQuery (line 86) | pub trait SelectorQuery<E: TElement> {
method should_stop_after_first_match (line 91) | fn should_stop_after_first_match() -> bool;
method append_element (line 94) | fn append_element(output: &mut Self::Output, element: E);
method is_empty (line 97) | fn is_empty(output: &Self::Output) -> bool;
type QuerySelectorAllResult (line 101) | pub type QuerySelectorAllResult<E> = SmallVec<[E; 128]>;
type QueryAll (line 104) | pub struct QueryAll;
type Output (line 107) | type Output = QuerySelectorAllResult<E>;
method should_stop_after_first_match (line 109) | fn should_stop_after_first_match() -> bool {
method append_element (line 113) | fn append_element(output: &mut Self::Output, element: E) {
method is_empty (line 117) | fn is_empty(output: &Self::Output) -> bool {
type QueryFirst (line 123) | pub struct QueryFirst;
type Output (line 126) | type Output = Option<E>;
method should_stop_after_first_match (line 128) | fn should_stop_after_first_match() -> bool {
method append_element (line 132) | fn append_element(output: &mut Self::Output, element: E) {
method is_empty (line 138) | fn is_empty(output: &Self::Output) -> bool {
type QuerySelectorProcessor (line 143) | struct QuerySelectorProcessor<'a, 'b, E, Q>
function light_tree_only (line 161) | fn light_tree_only(&self) -> bool {
function check_outer_dependency (line 165) | fn check_outer_dependency(&mut self, _: &Dependency, _: E, _: Option<Opa...
function collect_invalidations (line 173) | fn collect_invalidations(
function matching_context (line 212) | fn matching_context(&mut self) -> &mut MatchingContext<'b, E::Impl> {
function sibling_traversal_map (line 216) | fn sibling_traversal_map(&self) -> &SiblingTraversalMap<E> {
function should_process_descendants (line 220) | fn should_process_descendants(&mut self, _: E) -> bool {
function invalidated_self (line 228) | fn invalidated_self(&mut self, e: E) {
function invalidated_sibling (line 232) | fn invalidated_sibling(&mut self, e: E, _of: E) {
function recursion_limit_exceeded (line 236) | fn recursion_limit_exceeded(&mut self, _e: E) {}
function invalidated_descendants (line 237) | fn invalidated_descendants(&mut self, _e: E, _child: E) {}
type Operation (line 240) | enum Operation {
method from (line 248) | fn from(matches: bool) -> Self {
function collect_all_elements (line 257) | fn collect_all_elements<E, Q, F>(root: E::ConcreteNode, results: &mut Q:...
function connected_element_is_descendant_of (line 296) | fn connected_element_is_descendant_of<E>(element: E, root: E::ConcreteNo...
function fast_connected_elements_with_id (line 334) | fn fast_connected_elements_with_id<'a, N>(
function collect_elements_with_id (line 362) | fn collect_elements_with_id<E, Q, F>(
function has_attr (line 402) | fn has_attr<E>(element: E, local_name: &crate::LocalName) -> bool
function local_name_matches (line 412) | fn local_name_matches<E>(element: E, local_name: &LocalName<E::Impl>) ->...
function get_attr_name (line 430) | fn get_attr_name(component: &Component<SelectorImpl>) -> Option<&crate::...
function get_id (line 447) | fn get_id(component: &Component<SelectorImpl>) -> Option<&AtomIdent> {
function query_selector_single_query (line 470) | fn query_selector_single_query<E, Q>(
type SimpleFilter (line 593) | enum SimpleFilter<'a> {
function query_selector_fast (line 608) | fn query_selector_fast<E, Q>(
function query_selector_slow (line 815) | fn query_selector_slow<E, Q>(
type MayUseInvalidation (line 835) | pub enum MayUseInvalidation {
function query_selector (line 843) | pub fn query_selector<E, Q>(
FILE: style/driver.rs
function should_report_statistics (line 20) | fn should_report_statistics() -> bool {
function should_report_statistics (line 25) | fn should_report_statistics() -> bool {
function report_statistics (line 30) | fn report_statistics(_stats: &PerThreadTraversalStatistics) {
function report_statistics (line 35) | fn report_statistics(stats: &PerThreadTraversalStatistics) {
function with_pool_in_place_scope (line 49) | fn with_pool_in_place_scope<'scope>(
function work_unit_max (line 75) | fn work_unit_max() -> usize {
function traverse_dom (line 88) | pub fn traverse_dom<E, D>(
FILE: style/error_reporting.rs
type ContextualParseError (line 20) | pub enum ContextualParseError<'a> {
function fmt (line 64) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
type ParseErrorReporter (line 245) | pub trait ParseErrorReporter {
method report_error (line 250) | fn report_error(
method report_error (line 269) | fn report_error(
type RustLogReporter (line 265) | pub struct RustLogReporter;
type SelectorWarningKind (line 291) | pub enum SelectorWarningKind {
method from_selector (line 302) | pub fn from_selector(selector: &Selector<SelectorImpl>) -> Vec<Self> {
type PerCompoundState (line 315) | struct PerCompoundState {
method new (line 325) | fn new(in_relative_selector: bool) -> Self {
type UnconstrainedRelativeSelectorVisitor (line 335) | struct UnconstrainedRelativeSelectorVisitor {
method new (line 340) | fn new(in_relative_selector: bool) -> Self {
method has_warning (line 346) | fn has_warning(
type Impl (line 388) | type Impl = SelectorImpl;
method visit_simple_selector (line 390) | fn visit_simple_selector(&mut self, c: &Component<Self::Impl>) -> bool {
method visit_selector_list (line 403) | fn visit_selector_list(
method visit_relative_selector_list (line 448) | fn visit_relative_selector_list(&mut self, list: &[RelativeSelector<Self...
type SiblingCombinatorAfterScopeSelectorVisitor (line 466) | struct SiblingCombinatorAfterScopeSelectorVisitor {
method new (line 472) | fn new(right_combinator_is_sibling: bool) -> Self {
method has_warning (line 478) | fn has_warning(selector: &Selector<SelectorImpl>) -> bool {
method find_never_matching_scope_selector (line 486) | fn find_never_matching_scope_selector(mut self, selector: &Selector<Se...
type Impl (line 493) | type Impl = SelectorImpl;
method visit_simple_selector (line 495) | fn visit_simple_selector(&mut self, c: &Component<Self::Impl>) -> bool {
method visit_selector_list (line 506) | fn visit_selector_list(
method visit_complex_selector (line 518) | fn visit_complex_selector(&mut self, combinator_to_right: Option<Combina...
FILE: style/font_face.rs
type Source (line 30) | pub enum Source {
type SourceList (line 41) | pub struct SourceList(#[css(iterable)] pub Vec<Source>);
method parse (line 47) | fn parse<'i, 't>(
type FontFaceSourceFormatKeyword (line 75) | pub enum FontFaceSourceFormatKeyword {
type FontFaceSourceTechFlags (line 94) | pub struct FontFaceSourceTechFlags(u16);
method parse_one (line 124) | pub fn parse_one<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, P...
method parse (line 142) | fn parse<'i, 't>(
method to_css (line 165) | fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
type FontFaceRule (line 202) | pub struct FontFaceRule {
method empty (line 211) | pub fn empty(source_location: SourceLocation) -> Self {
type FontFaceSourceListComponent (line 227) | pub enum FontFaceSourceListComponent {
type FontFaceSourceFormat (line 242) | pub enum FontFaceSourceFormat {
type UrlSource (line 253) | pub struct UrlSource {
method to_css (line 263) | fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
type FontDisplay (line 291) | pub enum FontDisplay {
type FontWeightRange (line 333) | pub struct FontWeightRange(pub AbsoluteFontWeight, pub AbsoluteFontWeight);
method compute (line 355) | pub fn compute(&self) -> ComputedFontWeightRange {
type ComputedFontWeightRange (line 342) | pub struct ComputedFontWeightRange(f32, f32);
function sort_range (line 345) | fn sort_range<T: PartialOrd>(a: T, b: T) -> (T, T) {
type FontStretchRange (line 365) | pub struct FontStretchRange(pub SpecifiedFontStretch, pub SpecifiedFontS...
method compute (line 376) | pub fn compute(&self) -> ComputedFontStretchRange {
type ComputedFontStretchRange (line 372) | pub struct ComputedFontStretchRange(FontStretch, FontStretch);
type FontStyle (line 395) | pub enum FontStyle {
method compute (line 467) | pub fn compute(&self) -> ComputedFontStyleDescriptor {
type ComputedFontStyleDescriptor (line 404) | pub enum ComputedFontStyleDescriptor {
method parse (line 410) | fn parse<'i, 't>(
method to_css (line 438) | fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
function parse_font_face_block (line 484) | pub fn parse_font_face_block(
method parse (line 509) | fn parse<'i, 't>(
method to_css (line 562) | fn to_css(&self, _guard: &SharedRwLockReadGuard, dest: &mut CssStringWri...
FILE: style/font_metrics.rs
type FontMetrics (line 14) | pub struct FontMetrics {
method x_height_or_default (line 49) | pub fn x_height_or_default(&self, reference_font_size: Length) -> Leng...
method zero_advance_measure_or_default (line 62) | pub fn zero_advance_measure_or_default(
method cap_height_or_default (line 89) | pub fn cap_height_or_default(&self) -> Length {
method ic_width_or_default (line 100) | pub fn ic_width_or_default(&self, reference_font_size: Length) -> Leng...
method default (line 34) | fn default() -> Self {
type FontMetricsOrientation (line 115) | pub enum FontMetricsOrientation {
FILE: style/gecko/conversions.rs
method from (line 18) | fn from(other: RulesMutateError) -> Self {
method from (line 29) | fn from(m: &'a Matrix4x4Components) -> Matrix3D {
method from (line 52) | fn from(matrix: Matrix3D) -> Self {
FILE: style/gecko/data.rs
type GeckoStyleSheet (line 30) | pub struct GeckoStyleSheet(*const DomStyleSheet);
method fmt (line 43) | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
method new (line 56) | pub unsafe fn new(s: *const DomStyleSheet) -> Self {
method from_addrefed (line 65) | pub unsafe fn from_addrefed(s: *const DomStyleSheet) -> Self {
method hack_is_null (line 73) | pub fn hack_is_null(&self) -> bool {
method raw (line 78) | pub fn raw(&self) -> &DomStyleSheet {
method inner (line 82) | fn inner(&self) -> &StyleSheetInfo {
method raw_contents (line 86) | fn raw_contents(&self) -> &StylesheetContents {
method drop (line 93) | fn drop(&mut self) {
method clone (line 99) | fn clone(&self) -> Self {
method media (line 106) | fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a M...
method enabled (line 121) | fn enabled(&self) -> bool {
method contents (line 126) | fn contents<'a>(&'a self, _: &'a SharedRwLockReadGuard) -> &'a Styleshee...
method implicit_scope_root (line 130) | fn implicit_scope_root(&self) -> Option<ImplicitScopeRoot> {
type PerDocumentStyleDataImpl (line 159) | pub struct PerDocumentStyleDataImpl {
method flush_stylesheets (line 201) | pub fn flush_stylesheets(
method default_computed_values (line 209) | pub fn default_computed_values(&self) -> &Arc<ComputedValues> {
method add_size_of (line 214) | pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut Servo...
type PerDocumentStyleData (line 173) | pub struct PerDocumentStyleData(AtomicRefCell<PerDocumentStyleDataImpl>);
method new (line 177) | pub fn new(document: *const structs::Document) -> Self {
method borrow (line 189) | pub fn borrow(&self) -> AtomicRef<'_, PerDocumentStyleDataImpl> {
method borrow_mut (line 194) | pub fn borrow_mut(&self) -> AtomicRefMut<'_, PerDocumentStyleDataImpl> {
type AuthorStyles (line 220) | pub type AuthorStyles = crate::author_styles::AuthorStyles<GeckoStyleShe...
FILE: style/gecko/media_features.rs
function device_size (line 20) | fn device_size(device: &Device) -> Size2D<Au> {
function eval_width (line 30) | fn eval_width(context: &Context) -> CSSPixelLength {
function eval_device_width (line 35) | fn eval_device_width(context: &Context) -> CSSPixelLength {
function eval_height (line 40) | fn eval_height(context: &Context) -> CSSPixelLength {
function eval_device_height (line 45) | fn eval_device_height(context: &Context) -> CSSPixelLength {
function eval_aspect_ratio_for (line 49) | fn eval_aspect_ratio_for<F>(context: &Context, get_size: F) -> Ratio
function eval_aspect_ratio (line 58) | fn eval_aspect_ratio(context: &Context) -> Ratio {
function eval_device_aspect_ratio (line 63) | fn eval_device_aspect_ratio(context: &Context) -> Ratio {
function eval_device_pixel_ratio (line 68) | fn eval_device_pixel_ratio(context: &Context) -> f32 {
function eval_orientation (line 73) | fn eval_orientation(context: &Context, value: Option<Orientation>) -> bo...
function eval_device_orientation (line 78) | fn eval_device_orientation(context: &Context, value: Option<Orientation>...
function document_picture_in_picture_enabled (line 82) | fn document_picture_in_picture_enabled(context: &ParserContext) -> bool {
type DisplayMode (line 90) | pub enum DisplayMode {
function eval_display_mode (line 100) | fn eval_display_mode(context: &Context, query_value: Option<DisplayMode>...
function eval_grid (line 112) | fn eval_grid(_: &Context) -> bool {
function eval_transform_3d (line 119) | fn eval_transform_3d(_: &Context) -> bool {
type Scan (line 125) | enum Scan {
function eval_scan (line 131) | fn eval_scan(_: &Context, _: Option<Scan>) -> bool {
function eval_color (line 138) | fn eval_color(context: &Context) -> i32 {
function eval_color_index (line 143) | fn eval_color_index(_: &Context) -> i32 {
function eval_monochrome (line 149) | fn eval_monochrome(context: &Context) -> i32 {
type ColorGamut (line 159) | pub enum ColorGamut {
function eval_color_gamut (line 169) | fn eval_color_gamut(context: &Context, query_value: Option<ColorGamut>) ...
function eval_resolution (line 181) | fn eval_resolution(context: &Context) -> Resolution {
type PrefersReducedMotion (line 189) | enum PrefersReducedMotion {
type PrefersReducedTransparency (line 196) | enum PrefersReducedTransparency {
type DynamicRange (line 208) | pub enum DynamicRange {
function eval_prefers_reduced_motion (line 214) | fn eval_prefers_reduced_motion(
function eval_prefers_reduced_transparency (line 232) | fn eval_prefers_reduced_transparency(
type PrefersContrast (line 254) | pub enum PrefersContrast {
function eval_prefers_contrast (line 266) | fn eval_prefers_contrast(context: &Context, query_value: Option<PrefersC...
function eval_forced_colors (line 276) | fn eval_forced_colors(context: &Context, query_value: Option<ForcedColor...
type InvertedColors (line 288) | enum InvertedColors {
function eval_inverted_colors (line 296) | fn eval_inverted_colors(context: &Context, query_value: Option<InvertedC...
type OverflowBlock (line 312) | enum OverflowBlock {
function eval_overflow_block (line 319) | fn eval_overflow_block(context: &Context, query_value: Option<OverflowBl...
type OverflowInline (line 342) | enum OverflowInline {
function eval_overflow_inline (line 348) | fn eval_overflow_inline(context: &Context, query_value: Option<OverflowI...
type Update (line 364) | enum Update {
function eval_update (line 371) | fn eval_update(context: &Context, query_value: Option<Update>) -> bool {
function do_eval_prefers_color_scheme (line 390) | fn do_eval_prefers_color_scheme(
function eval_prefers_color_scheme (line 405) | fn eval_prefers_color_scheme(context: &Context, query_value: Option<Pref...
function eval_content_prefers_color_scheme (line 409) | fn eval_content_prefers_color_scheme(
function eval_dynamic_range (line 417) | fn eval_dynamic_range(context: &Context, query_value: Option<DynamicRang...
function eval_video_dynamic_range (line 426) | fn eval_video_dynamic_range(context: &Context, query_value: Option<Dynam...
function primary_pointer_capabilities (line 444) | fn primary_pointer_capabilities(context: &Context) -> PointerCapabilities {
function all_pointer_capabilities (line 450) | fn all_pointer_capabilities(context: &Context) -> PointerCapabilities {
type Pointer (line 458) | enum Pointer {
function eval_pointer_capabilities (line 464) | fn eval_pointer_capabilities(
function eval_pointer (line 481) | fn eval_pointer(context: &Context, query_value: Option<Pointer>) -> bool {
function eval_any_pointer (line 486) | fn eval_any_pointer(context: &Context, query_value: Option<Pointer>) -> ...
type Hover (line 492) | enum Hover {
function eval_hover_capabilities (line 497) | fn eval_hover_capabilities(
function eval_hover (line 514) | fn eval_hover(context: &Context, query_value: Option<Hover>) -> bool {
function eval_any_hover (line 519) | fn eval_any_hover(context: &Context, query_value: Option<Hover>) -> bool {
function eval_moz_is_glyph (line 523) | fn eval_moz_is_glyph(context: &Context) -> bool {
function eval_moz_in_android_pip_mode (line 527) | fn eval_moz_in_android_pip_mode(context: &Context) -> bool {
function eval_moz_print_preview (line 531) | fn eval_moz_print_preview(context: &Context) -> bool {
function eval_moz_is_resource_document (line 539) | fn eval_moz_is_resource_document(context: &Context) -> bool {
type Platform (line 546) | pub enum Platform {
function eval_moz_platform (line 562) | fn eval_moz_platform(_: &Context, query_value: Option<Platform>) -> bool {
type GtkThemeFamily (line 574) | pub enum GtkThemeFamily {
function eval_gtk_theme_family (line 585) | fn eval_gtk_theme_family(_: &Context, query_value: Option<GtkThemeFamily...
type Scripting (line 597) | pub enum Scripting {
function eval_scripting (line 610) | fn eval_scripting(context: &Context, query_value: Option<Scripting>) -> ...
function eval_moz_overlay_scrollbars (line 618) | fn eval_moz_overlay_scrollbars(context: &Context) -> bool {
function eval_moz_mac_rtl (line 622) | fn eval_moz_mac_rtl(context: &Context) -> bool {
function eval_moz_native_theme (line 626) | fn eval_moz_native_theme(context: &Context) -> bool {
function get_lnf_int (line 633) | fn get_lnf_int(int_id: i32) -> i32 {
function get_lnf_int_as_bool (line 637) | fn get_lnf_int_as_bool(int_id: i32) -> bool {
FILE: style/gecko/pseudo_element.rs
type Target (line 75) | pub enum Target {
type PtNameAndClassSelector (line 99) | pub struct PtNameAndClassSelector(thin_vec::ThinVec<Atom>);
method from_name (line 103) | pub fn from_name(name: Atom) -> Self {
method name (line 108) | pub fn name(&self) -> &Atom {
method classes (line 114) | pub fn classes(&self) -> &[Atom] {
method name_and_classes (line 120) | pub fn name_and_classes(&self) -> &thin_vec::ThinVec<Atom> {
method parse (line 130) | pub fn parse<'i, 't>(
method to_css (line 197) | fn to_css<W>(&self, dest: &mut W) -> fmt::Result
type Impl (line 219) | type Impl = SelectorImpl;
method valid_after_slotted (line 225) | fn valid_after_slotted(&self) -> bool {
method valid_after_before_or_after (line 233) | fn valid_after_before_or_after(&self) -> bool {
method accepts_state_pseudo_classes (line 238) | fn accepts_state_pseudo_classes(&self) -> bool {
method specificity_count (line 245) | fn specificity_count(&self) -> u32 {
method is_in_pseudo_element_tree (line 250) | fn is_in_pseudo_element_tree(&self) -> bool {
method parses_as_element_backed (line 256) | fn parses_as_element_backed(&self) -> bool {
method is_before_or_after (line 263) | fn is_before_or_after(&self) -> bool {
method is_element_backed (line 272) | pub fn is_element_backed(&self) -> bool {
method cascade_type (line 284) | pub fn cascade_type(&self) -> PseudoElementCascadeType {
method index (line 299) | pub fn index(&self) -> usize {
method discriminant (line 304) | fn discriminant(&self) -> u8 {
method is_unknown_webkit_pseudo_element (line 312) | pub fn is_unknown_webkit_pseudo_element(&self) -> bool {
method is_anon_box (line 318) | pub fn is_anon_box(&self) -> bool {
method is_eager (line 324) | pub fn is_eager(&self) -> bool {
method eager_index (line 330) | pub fn eager_index(&self) -> usize {
method from_eager_index (line 339) | pub fn from_eager_index(i: usize) -> Self {
method animations_stored_in_parent (line 346) | pub fn animations_stored_in_parent(&self) -> bool {
method is_before (line 355) | pub fn is_before(&self) -> bool {
method is_after (line 361) | pub fn is_after(&self) -> bool {
method is_marker (line 367) | pub fn is_marker(&self) -> bool {
method is_selection (line 373) | pub fn is_selection(&self) -> bool {
method is_first_letter (line 379) | pub fn is_first_letter(&self) -> bool {
method is_first_line (line 385) | pub fn is_first_line(&self) -> bool {
method is_lazy (line 391) | pub fn is_lazy(&self) -> bool {
method highlight_name (line 396) | pub fn highlight_name(&self) -> Option<&AtomIdent> {
method is_highlight (line 404) | pub fn is_highlight(&self) -> bool {
method is_target_text (line 410) | pub fn is_target_text(&self) -> bool {
method is_lazy_painted_highlight_pseudo (line 418) | pub fn is_lazy_painted_highlight_pseudo(&self) -> bool {
method is_named_view_transition (line 423) | pub fn is_named_view_transition(&self) -> bool {
method specificity_count (line 434) | pub fn specificity_count(&self) -> u32 {
method supports_user_action_state (line 456) | pub fn supports_user_action_state(&self) -> bool {
method enabled_in_content (line 462) | pub fn enabled_in_content(&self) -> bool {
method enabled_in_ua_sheets (line 467) | pub fn enabled_in_ua_sheets(&self) -> bool {
method enabled_in_chrome (line 472) | pub fn enabled_in_chrome(&self) -> bool {
method skip_item_display_fixup (line 480) | pub fn skip_item_display_fixup(&self) -> bool {
method is_precomputed (line 488) | pub fn is_precomputed(&self) -> bool {
method property_restriction (line 494) | pub fn property_restriction(&self) -> Option<PropertyFlags> {
method should_exist (line 507) | pub fn should_exist(&self, style: &ComputedValues) -> bool {
method parse_ignore_enabled_state (line 524) | pub fn parse_ignore_enabled_state<'i, 't>(
method matches_named_view_transition_pseudo_element (line 572) | pub fn matches_named_view_transition_pseudo_element(
FILE: style/gecko/pseudo_element_definition.mako.rs
type AtomThinVec (line 7) | type AtomThinVec = thin_vec::ThinVec<Atom>;
constant PSEUDO_COUNT (line 35) | pub const PSEUDO_COUNT: usize = ${len(PSEUDOS)};
constant EAGER_PSEUDOS (line 38) | pub const EAGER_PSEUDOS: [PseudoElement; EAGER_PSEUDO_COUNT] = [
function matches (line 224) | pub fn matches(
method to_css (line 243) | fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
FILE: style/gecko/pseudo_elements.py
class Pseudo (line 18) | class Pseudo(object):
method __init__ (line 19) | def __init__(self, name, argument, enabled_in, pref):
method is_pseudo_element (line 27) | def is_pseudo_element(self):
method is_anon_box (line 30) | def is_anon_box(self):
method is_non_inheriting_anon_box (line 33) | def is_non_inheriting_anon_box(self):
method is_inheriting_anon_box (line 36) | def is_inheriting_anon_box(self):
method flags (line 39) | def flags(self):
class AnonBox (line 76) | class AnonBox(Pseudo):
method __init__ (line 77) | def __init__(self, name, wrapper=False, inherits=True):
class PseudoElement (line 83) | class PseudoElement(Pseudo):
method __init__ (line 84) | def __init__(
class PseudoElementData (line 114) | class PseudoElementData:
method __init__ (line 115) | def __init__(self):
method all_pseudos (line 132) | def all_pseudos(self):
FILE: style/gecko/regen_atoms.py
function map_atom (line 25) | def map_atom(ident):
class Atom (line 42) | class Atom:
method __init__ (line 43) | def __init__(self, ident, value, hash):
function collect_atoms (line 50) | def collect_atoms(objdir):
class FileAvoidWrite (line 67) | class FileAvoidWrite(BytesIO):
method __init__ (line 70) | def __init__(self, filename):
method write (line 74) | def write(self, buf):
method close (line 79) | def close(self):
method __enter__ (line 93) | def __enter__(self):
method __exit__ (line 96) | def __exit__(self, type, value, traceback):
function write_atom_macro (line 130) | def write_atom_macro(atoms, file_name):
function generate_atoms (line 140) | def generate_atoms(dist, out):
function generate_pseudo_elements (line 145) | def generate_pseudo_elements(dist, out):
FILE: style/gecko/restyle_damage.rs
type GeckoRestyleDamage (line 17) | pub struct GeckoRestyleDamage(nsChangeHint);
method new (line 22) | pub fn new(raw: nsChangeHint) -> Self {
method as_change_hint (line 28) | pub fn as_change_hint(&self) -> nsChangeHint {
method empty (line 34) | pub fn empty() -> Self {
method is_empty (line 40) | pub fn is_empty(&self) -> bool {
method compute_style_difference (line 46) | pub fn compute_style_difference(
method contains (line 85) | pub fn contains(self, other: Self) -> bool {
method reconstruct (line 91) | pub fn reconstruct() -> Self {
method default (line 97) | fn default() -> Self {
type Output (line 103) | type Output = Self;
method bitor (line 104) | fn bitor(self, other: Self) -> Self {
method bitor_assign (line 110) | fn bitor_assign(&mut self, other: Self) {
type Output (line 116) | type Output = Self;
method bitand (line 117) | fn bitand(self, other: Self) -> Self {
type Output (line 123) | type Output = Self;
method not (line 124) | fn not(self) -> Self {
FILE: style/gecko/selector_parser.rs
type Lang (line 43) | pub struct Lang(#[css(iterable)] pub ThinVec<AtomIdent>);
type CustomState (line 47) | pub struct CustomState(pub AtomIdent);
type HeadingSelectorData (line 52) | pub struct HeadingSelectorData(pub ThinVec<CSSInteger>);
method matches_state (line 58) | pub fn matches_state(&self, state: ElementState) -> bool {
method to_css (line 104) | fn to_css<W>(&self, dest: &mut W) -> fmt::Result
method parse_non_functional (line 172) | pub fn parse_non_functional(name: &str) -> Option<Self> {
method has_any_flag (line 193) | fn has_any_flag(&self, flags: NonTSPseudoClassFlag) -> bool {
method is_enabled_in_content (line 220) | fn is_enabled_in_content(&self) -> bool {
method state_flag (line 246) | pub fn state_flag(&self) -> ElementState {
method document_state_flag (line 272) | pub fn document_state_flag(&self) -> DocumentState {
method needs_cache_revalidation (line 286) | pub fn needs_cache_revalidation(&self) -> bool {
type Impl (line 308) | type Impl = SelectorImpl;
method is_active_or_hover (line 311) | fn is_active_or_hover(&self) -> bool {
method is_user_action_state (line 317) | fn is_user_action_state(&self) -> bool {
type SelectorImpl (line 327) | pub struct SelectorImpl;
type ExtraMatchingData (line 346) | type ExtraMatchingData<'a> = ExtraMatchingData<'a>;
type AttrValue (line 347) | type AttrValue = AtomString;
type Identifier (line 348) | type Identifier = AtomIdent;
type LocalName (line 349) | type LocalName = AtomIdent;
type NamespacePrefix (line 350) | type NamespacePrefix = AtomIdent;
type NamespaceUrl (line 351) | type NamespaceUrl = Namespace;
type BorrowedNamespaceUrl (line 352) | type BorrowedNamespaceUrl = WeakNamespace;
type BorrowedLocalName (line 353) | type BorrowedLocalName = WeakAtom;
type PseudoElement (line 355) | type PseudoElement = PseudoElement;
type NonTSPseudoClass (line 356) | type NonTSPseudoClass = NonTSPseudoClass;
method should_collect_attr_hash (line 358) | fn should_collect_attr_hash(name: &AtomIdent) -> bool {
method each_eagerly_cascaded_pseudo_element (line 641) | pub fn each_eagerly_cascaded_pseudo_element<F>(mut fun: F)
type ExtraMatchingData (line 332) | pub struct ExtraMatchingData<'a> {
function is_pseudo_class_enabled (line 364) | fn is_pseudo_class_enabled(&self, pseudo_class: &NonTSPseudoClass) -> bo...
function is_pseudo_element_enabled (line 388) | fn is_pseudo_element_enabled(&self, pseudo_element: &PseudoElement) -> b...
function parse_functional_pseudo_element_with_name (line 406) | pub fn parse_functional_pseudo_element_with_name<'i, 't>(
type Impl (line 472) | type Impl = SelectorImpl;
type Error (line 473) | type Error = StyleParseErrorKind<'i>;
function parse_parent_selector (line 476) | fn parse_parent_selector(&self) -> bool {
function parse_slotted (line 481) | fn parse_slotted(&self) -> bool {
function parse_host (line 486) | fn parse_host(&self) -> bool {
function parse_nth_child_of (line 491) | fn parse_nth_child_of(&self) -> bool {
function parse_is_and_where (line 496) | fn parse_is_and_where(&self) -> bool {
function parse_has (line 501) | fn parse_has(&self) -> bool {
function parse_part (line 506) | fn parse_part(&self) -> bool {
function is_is_alias (line 511) | fn is_is_alias(&self, function: &str) -> bool {
function allow_forgiving_selectors (line 516) | fn allow_forgiving_selectors(&self) -> bool {
function parse_non_ts_pseudo_class (line 520) | fn parse_non_ts_pseudo_class(
function parse_non_ts_functional_pseudo_class (line 537) | fn parse_non_ts_functional_pseudo_class<'t>(
function parse_pseudo_element (line 592) | fn parse_pseudo_element(
function parse_functional_pseudo_element (line 611) | fn parse_functional_pseudo_element<'t>(
function default_namespace (line 628) | fn default_namespace(&self) -> Option<Namespace> {
function namespace_for_prefix (line 632) | fn namespace_for_prefix(&self, prefix: &AtomIdent) -> Option<Namespace> {
FILE: style/gecko/snapshot.rs
type GeckoElementSnapshot (line 25) | pub type GeckoElementSnapshot = ServoElementSnapshot;
method has_any (line 52) | fn has_any(&self, flags: Flags) -> bool {
method has_other_pseudo_class_state (line 59) | pub fn has_other_pseudo_class_state(&self) -> bool {
method id_changed (line 65) | pub fn id_changed(&self) -> bool {
method class_changed (line 71) | pub fn class_changed(&self) -> bool {
method each_attr_changed (line 77) | pub fn each_attr_changed<F>(&self, mut callback: F)
method attr_matches (line 87) | pub fn attr_matches(
type SnapshotMap (line 28) | pub type SnapshotMap = ServoElementSnapshotTable;
method get (line 40) | pub fn get<E: TElement>(&self, element: &E) -> Option<&GeckoElementSna...
method debug_list_attributes (line 98) | fn debug_list_attributes(&self) -> String {
method state (line 107) | fn state(&self) -> Option<ElementState> {
method has_attrs (line 116) | fn has_attrs(&self) -> bool {
method id_attr (line 121) | fn id_attr(&self) -> Option<&WeakAtom> {
method is_part (line 130) | fn is_part(&self, name: &AtomIdent) -> bool {
method imported_part (line 140) | fn imported_part(&self, name: &AtomIdent) -> Option<AtomIdent> {
method has_class (line 145) | fn has_class(&self, name: &AtomIdent, case_sensitivity: CaseSensitivity)...
method each_class (line 154) | fn each_class<F>(&self, callback: F)
method lang_attr (line 166) | fn lang_attr(&self) -> Option<AtomString> {
method has_custom_states (line 177) | fn has_custom_states(&self) -> bool {
method has_custom_state (line 183) | fn has_custom_state(&self, state: &AtomIdent) -> bool {
method each_custom_state (line 192) | fn each_custom_state<F>(&self, mut callback: F)
FILE: style/gecko/snapshot_helpers.rs
type Class (line 23) | enum Class<'a> {
function base_type (line 30) | fn base_type(attr: &structs::nsAttrValue) -> structs::nsAttrValue_ValueB...
function ptr (line 35) | unsafe fn ptr<T>(attr: &structs::nsAttrValue) -> *const T {
function get_class_or_part_from_attr (line 40) | unsafe fn get_class_or_part_from_attr(attr: &structs::nsAttrValue) -> Cl...
function get_id_from_attr (line 69) | unsafe fn get_id_from_attr(attr: &structs::nsAttrValue) -> &WeakAtom {
function is_nodeinfo (line 79) | fn is_nodeinfo(&self) -> bool {
function as_nodeinfo (line 84) | unsafe fn as_nodeinfo(&self) -> &structs::NodeInfo {
function namespace_id (line 90) | fn namespace_id(&self) -> i32 {
function name (line 99) | pub fn name(&self) -> *const nsAtom {
function find_attr (line 110) | pub fn find_attr<'a>(
function get_id (line 122) | pub fn get_id(attrs: &[structs::AttrArray_InternalAttr]) -> Option<&Weak...
function each_exported_part (line 127) | pub(super) fn each_exported_part(
function imported_part (line 150) | pub(super) fn imported_part(
function has_class_or_part (line 165) | pub fn has_class_or_part(
function each_class_or_part (line 190) | pub fn each_class_or_part<F>(attr: &structs::nsAttrValue, mut callback: F)
function classes_changed (line 209) | pub fn classes_changed<E: TElement>(element: &E, snapshots: &SnapshotMap...
function attr_matches (line 233) | pub(crate) fn attr_matches(
function attr_matches_checked_name (line 261) | fn attr_matches_checked_name(
FILE: style/gecko/traversal.rs
type RecalcStyleOnly (line 14) | pub struct RecalcStyleOnly<'a> {
function new (line 20) | pub fn new(shared: SharedStyleContext<'a>) -> Self {
function process_preorder (line 26) | fn process_preorder<F>(
function process_postorder (line 41) | fn process_postorder(&self, _: &mut StyleContext<GeckoElement<'le>>, _: ...
function needs_postorder_traversal (line 46) | fn needs_postorder_traversal() -> bool {
function shared_context (line 50) | fn shared_context(&self) -> &SharedStyleContext<'recalc> {
FILE: style/gecko/url.rs
type CssUrl (line 28) | pub struct CssUrl(pub Arc<CssUrlData>);
method parse_with_cors_mode (line 107) | pub fn parse_with_cors_mode<'i, 't>(
method parse_from_string (line 129) | pub fn parse_from_string<'i>(
method new_from_untainted_string (line 150) | pub fn new_from_untainted_string(
method new_from_string (line 159) | fn new_from_string(url: String, context: &ParserContext, cors_mode: Co...
method is_invalid (line 195) | pub fn is_invalid(&self) -> bool {
method is_fragment (line 202) | pub fn is_fragment(&self) -> bool {
method as_str (line 209) | pub fn as_str(&self) -> &str {
type CssUrlData (line 36) | pub struct CssUrlData {
method is_fragment (line 217) | pub fn is_fragment(&self) -> bool {
method as_str (line 227) | pub fn as_str(&self) -> &str {
method eq (line 56) | fn eq(&self, other: &Self) -> bool {
type NonLocalUriDependency (line 69) | pub enum NonLocalUriDependency {
method scan (line 84) | fn scan(specified: &str) -> Self {
method parse (line 233) | fn parse<'i, 't>(
method size_of (line 244) | fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
type LoadDataKey (line 256) | struct LoadDataKey(*const LoadDataSource);
type LoadData (line 283) | pub struct LoadData {
method drop (line 297) | fn drop(&mut self) {
method default (line 303) | fn default() -> Self {
type LoadDataSource (line 322) | pub enum LoadDataSource {
method get (line 334) | pub unsafe fn get(&self) -> *const LoadData {
method to_shmem (line 355) | fn to_shmem(&self, _builder: &mut SharedMemoryBuilder) -> to_shmem::Resu...
type SpecifiedUrl (line 364) | pub type SpecifiedUrl = CssUrl;
function shutdown (line 369) | pub fn shutdown() {
type ComputedValue (line 374) | type ComputedValue = ComputedUrl;
method to_computed_value (line 377) | fn to_computed_value(&self, _: &Context) -> Self::ComputedValue {
method from_computed_value (line 382) | fn from_computed_value(computed: &Self::ComputedValue) -> Self {
type ComputedUrl (line 393) | pub struct ComputedUrl(pub SpecifiedUrl);
method serialize_with (line 396) | fn serialize_with<W>(
method to_css (line 415) | fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
FILE: style/gecko/wrapper.rs
function elements_with_id (line 92) | fn elements_with_id<'a, 'le>(
type GeckoDocument (line 112) | pub struct GeckoDocument<'ld>(pub &'ld structs::Document);
type ConcreteNode (line 115) | type ConcreteNode = GeckoNode<'ld>;
method as_node (line 118) | fn as_node(&self) -> Self::ConcreteNode {
method is_html_document (line 123) | fn is_html_document(&self) -> bool {
method quirks_mode (line 128) | fn quirks_mode(&self) -> QuirksMode {
method elements_with_id (line 133) | fn elements_with_id<'a>(&self, id: &AtomIdent) -> Result<&'a [GeckoEleme...
method shared_lock (line 142) | fn shared_lock(&self) -> &SharedRwLock {
type GeckoShadowRoot (line 149) | pub struct GeckoShadowRoot<'lr>(pub &'lr structs::ShadowRoot);
function fmt (line 152) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method eq (line 160) | fn eq(&self, other: &Self) -> bool {
type ConcreteNode (line 166) | type ConcreteNode = GeckoNode<'lr>;
method as_node (line 169) | fn as_node(&self) -> Self::ConcreteNode {
method host (line 174) | fn host(&self) -> GeckoElement<'lr> {
method style_data (line 179) | fn style_data<'a>(&self) -> Option<&'a CascadeData>
method elements_with_id (line 188) | fn elements_with_id<'a>(&self, id: &AtomIdent) -> Result<&'a [GeckoEleme...
method parts (line 198) | fn parts<'a>(&self) -> &[<Self::ConcreteNode as TNode>::ConcreteElement]
method implicit_scope_for_sheet (line 213) | fn implicit_scope_for_sheet(&self, sheet_index: usize) -> Option<Implici...
type GeckoNode (line 231) | pub struct GeckoNode<'ln>(pub &'ln RawGeckoNode);
method eq (line 235) | fn eq(&self, other: &Self) -> bool {
function fmt (line 241) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
function is_document (line 264) | fn is_document(&self) -> bool {
function is_shadow_root (line 271) | fn is_shadow_root(&self) -> bool {
function from_content (line 276) | fn from_content(content: &'ln nsIContent) -> Self {
function set_flags (line 281) | fn set_flags(&self, flags: u32) {
function flags_atomic_for (line 285) | fn flags_atomic_for(flags: &Cell<u32>) -> &AtomicU32 {
function flags_atomic (line 297) | fn flags_atomic(&self) -> &AtomicU32 {
function flags (line 302) | fn flags(&self) -> u32 {
function may_have_element_children (line 307) | fn may_have_element_children(&self) -> bool {
function selector_flags_atomic (line 312) | fn selector_flags_atomic(&self) -> &AtomicU32 {
function selector_flags (line 317) | fn selector_flags(&self) -> u32 {
function set_selector_flags (line 322) | fn set_selector_flags(&self, flags: u32) {
function node_info (line 328) | fn node_info(&self) -> &structs::NodeInfo {
function bool_flags (line 336) | fn bool_flags(&self) -> u32 {
function bool_flags (line 342) | fn bool_flags(&self) -> u32 {
function get_bool_flag (line 347) | fn get_bool_flag(&self, flag: nsINode_BooleanFlag) -> bool {
function is_in_shadow_tree (line 353) | fn is_in_shadow_tree(&self) -> bool {
function flattened_tree_parent_is_parent (line 365) | fn flattened_tree_parent_is_parent(&self) -> bool {
function flattened_tree_parent (line 391) | fn flattened_tree_parent(&self) -> Option<Self> {
function contains_non_whitespace_content (line 414) | fn contains_non_whitespace_content(&self) -> bool {
function prev_sibling_element (line 420) | pub fn prev_sibling_element(&self) -> Option<GeckoElement<'ln>> {
function next_sibling_element (line 436) | pub fn next_sibling_element(&self) -> Option<GeckoElement<'ln>> {
function last_child_element (line 452) | pub fn last_child_element(&self) -> Option<GeckoElement<'ln>> {
method is_element (line 466) | fn is_element(&self) -> bool {
method is_text_node (line 470) | fn is_text_node(&self) -> bool {
type ConcreteDocument (line 478) | type ConcreteDocument = GeckoDocument<'ln>;
type ConcreteShadowRoot (line 479) | type ConcreteShadowRoot = GeckoShadowRoot<'ln>;
type ConcreteElement (line 480) | type ConcreteElement = GeckoElement<'ln>;
method parent_node (line 483) | fn parent_node(&self) -> Option<Self> {
method first_child (line 488) | fn first_child(&self) -> Option<Self> {
method last_child (line 499) | fn last_child(&self) -> Option<Self> {
method prev_sibling (line 504) | fn prev_sibling(&self) -> Option<Self> {
method next_sibling (line 515) | fn next_sibling(&self) -> Option<Self> {
method owner_doc (line 526) | fn owner_doc(&self) -> Self::ConcreteDocument {
method is_in_document (line 532) | fn is_in_document(&self) -> bool {
method traversal_parent (line 536) | fn traversal_parent(&self) -> Option<GeckoElement<'ln>> {
method opaque (line 541) | fn opaque(&self) -> OpaqueNode {
method debug_id (line 546) | fn debug_id(self) -> usize {
method as_element (line 551) | fn as_element(&self) -> Option<GeckoElement<'ln>> {
method as_document (line 562) | fn as_document(&self) -> Option<Self::ConcreteDocument> {
method as_shadow_root (line 572) | fn as_shadow_root(&self) -> Option<Self::ConcreteShadowRoot> {
type GeckoChildrenIterator (line 595) | pub enum GeckoChildrenIterator<'a> {
method drop (line 604) | fn drop(&mut self) {
type Item (line 614) | type Item = GeckoNode<'a>;
method next (line 615) | fn next(&mut self) -> Option<GeckoNode<'a>> {
type GeckoElement (line 638) | pub struct GeckoElement<'le>(pub &'le RawGeckoElement);
function fmt (line 641) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
function get_data (line 658) | pub fn get_data(&self) -> Option<&ElementDataWrapper> {
function has_any_animation (line 664) | pub fn has_any_animation(&self) -> bool {
function has_attr_impl (line 670) | fn has_attr_impl(&self) -> bool {
function attrs (line 676) | fn attrs(&self) -> &[structs::AttrArray_InternalAttr] {
function get_part_attr (line 689) | fn get_part_attr(&self) -> Option<&structs::nsAttrValue> {
function get_class_attr (line 697) | fn get_class_attr(&self) -> Option<&structs::nsAttrValue> {
function may_have_anonymous_children (line 713) | fn may_have_anonymous_children(&self) -> bool {
function flags (line 719) | fn flags(&self) -> u32 {
function set_flags (line 724) | fn set_flags(&self, flags: u32) {
function unset_flags (line 729) | unsafe fn unset_flags(&self, flags: u32) {
function descendants_need_frames (line 737) | pub fn descendants_need_frames(&self) -> bool {
function needs_frame (line 743) | pub fn needs_frame(&self) -> bool {
function dom_slots (line 749) | fn dom_slots(&self) -> Option<&structs::FragmentOrElement_nsDOMSlots> {
function extended_slots (line 756) | fn extended_slots(&self) -> Option<&structs::FragmentOrElement_nsExtende...
function namespace_id (line 766) | fn namespace_id(&self) -> i32 {
function has_id (line 771) | fn has_id(&self) -> bool {
function state_internal (line 777) | fn state_internal(&self) -> u64 {
function document_state (line 788) | fn document_state(&self) -> DocumentState {
function may_have_class (line 793) | fn may_have_class(&self) -> bool {
function has_properties (line 799) | fn has_properties(&self) -> bool {
function may_have_style_attribute (line 806) | fn may_have_style_attribute(&self) -> bool {
function note_explicit_hints (line 818) | pub unsafe fn note_explicit_hints(&self, restyle_hint: RestyleHint, chan...
function is_root_of_native_anonymous_subtree (line 850) | fn is_root_of_native_anonymous_subtree(&self) -> bool {
function in_native_anonymous_subtree (line 856) | fn in_native_anonymous_subtree(&self) -> bool {
function in_ua_widget (line 862) | fn in_ua_widget(&self) -> bool {
function css_transitions_info (line 866) | fn css_transitions_info(&self) -> FxHashMap<OwnedPropertyDeclarationId, ...
function needs_transitions_update_per_property (line 883) | fn needs_transitions_update_per_property(
function slow_selector_flags (line 921) | pub fn slow_selector_flags(&self) -> ElementSelectorFlags {
function is_html_media_element (line 927) | pub fn is_html_media_element(&self) -> bool {
function slow_selector_flags_from_node_selector_flags (line 935) | pub fn slow_selector_flags_from_node_selector_flags(flags: u32) -> Eleme...
function selector_flags_to_node_flags (line 950) | fn selector_flags_to_node_flags(flags: ElementSelectorFlags) -> u32 {
function get_animation_rule (line 987) | fn get_animation_rule(
function namespace_id_to_atom (line 1014) | pub unsafe fn namespace_id_to_atom(id: i32) -> *mut nsAtom {
type ConcreteNode (line 1022) | type ConcreteNode = GeckoNode<'le>;
type TraversalChildrenIterator (line 1023) | type TraversalChildrenIterator = GeckoChildrenIterator<'le>;
method implicit_scope_for_sheet_in_shadow_root (line 1025) | fn implicit_scope_for_sheet_in_shadow_root(
method inheritance_parent (line 1046) | fn inheritance_parent(&self) -> Option<Self> {
method traversal_children (line 1058) | fn traversal_children(&self) -> LayoutIterator<GeckoChildrenIterator<'le...
method is_html_element (line 1080) | fn is_html_element(&self) -> bool {
method is_mathml_element (line 1085) | fn is_mathml_element(&self) -> bool {
method is_svg_element (line 1090) | fn is_svg_element(&self) -> bool {
method is_xul_element (line 1095) | fn is_xul_element(&self) -> bool {
method subtree_bloom_filter (line 1100) | fn subtree_bloom_filter(&self) -> u64 {
method local_name (line 1105) | fn local_name(&self) -> &WeakAtom {
method namespace (line 1110) | fn namespace(&self) -> &WeakNamespace {
method query_container_size (line 1115) | fn query_container_size(&self, display: &Display) -> Size2D<Option<Au>> {
method slotted_nodes (line 1136) | fn slotted_nodes(&self) -> &[Self::ConcreteNode] {
method shadow_root (line 1160) | fn shadow_root(&self) -> Option<GeckoShadowRoot<'le>> {
method note_highlight_pseudo_style_invalidated (line 1165) | fn note_highlight_pseudo_style_invalidated(&self) {
method containing_shadow (line 1173) | fn containing_shadow(&self) -> Option<GeckoShadowRoot<'le>> {
method each_anonymous_content_child (line 1181) | fn each_anonymous_content_child<F>(&self, mut f: F)
method as_node (line 1204) | fn as_node(&self) -> Self::ConcreteNode {
method owner_doc_matches_for_testing (line 1208) | fn owner_doc_matches_for_testing(&self, device: &Device) -> bool {
method style_attribute (line 1212) | fn style_attribute(&self) -> Option<ArcBorrow<'_, Locked<PropertyDeclara...
method unset_dirty_style_attribute (line 1223) | fn unset_dirty_style_attribute(&self) {
method smil_override (line 1231) | fn smil_override(&self) -> Option<ArcBorrow<'_, Locked<PropertyDeclarati...
method animation_rule (line 1243) | fn animation_rule(
method transition_rule (line 1250) | fn transition_rule(
method state (line 1258) | fn state(&self) -> ElementState {
method has_part_attr (line 1263) | fn has_part_attr(&self) -> bool {
method exports_any_part (line 1269) | fn exports_any_part(&self) -> bool {
method id (line 1275) | fn id(&self) -> Option<&WeakAtom> {
method each_attr_name (line 1282) | fn each_attr_name<F>(&self, mut callback: F)
method each_class (line 1291) | fn each_class<F>(&self, callback: F)
method each_custom_state (line 1304) | fn each_custom_state<F>(&self, mut callback: F)
method each_exported_part (line 1318) | fn each_exported_part<F>(&self, name: &AtomIdent, callback: F)
method each_part (line 1325) | fn each_part<F>(&self, callback: F)
method has_snapshot (line 1338) | fn has_snapshot(&self) -> bool {
method handled_snapshot (line 1343) | fn handled_snapshot(&self) -> bool {
method set_handled_snapshot (line 1347) | unsafe fn set_handled_snapshot(&self) {
method has_dirty_descendants (line 1353) | fn has_dirty_descendants(&self) -> bool {
method set_dirty_descendants (line 1357) | unsafe fn set_dirty_descendants(&self) {
method unset_dirty_descendants (line 1363) | unsafe fn unset_dirty_descendants(&self) {
method has_animation_only_dirty_descendants (line 1368) | fn has_animation_only_dirty_descendants(&self) -> bool {
method set_animation_only_dirty_descendants (line 1372) | unsafe fn set_animation_only_dirty_descendants(&self) {
method unset_animation_only_dirty_descendants (line 1376) | unsafe fn unset_animation_only_dirty_descendants(&self) {
method clear_descendant_bits (line 1380) | unsafe fn clear_descendant_bits(&self) {
method is_visited_link (line 1388) | fn is_visited_link(&self) -> bool {
method matches_user_and_content_rules (line 1396) | fn matches_user_and_content_rules(&self) -> bool {
method implemented_pseudo_element (line 1401) | fn implemented_pseudo_element(&self) -> Option<PseudoElement> {
method store_children_to_process (line 1422) | fn store_children_to_process(&self, _: isize) {
method did_process_child (line 1426) | fn did_process_child(&self) -> isize {
method ensure_data (line 1430) | unsafe fn ensure_data(&self) -> ElementDataMut<'_> {
method clear_data (line 1439) | unsafe fn clear_data(&self) {
method skip_item_display_fixup (line 1461) | fn skip_item_display_fixup(&self) -> bool {
method may_have_animations (line 1470) | fn may_have_animations(&self) -> bool {
method update_animations (line 1487) | fn update_animations(
method has_animations (line 1514) | fn has_animations(&self, _: &SharedStyleContext) -> bool {
method has_css_animations (line 1518) | fn has_css_animations(&self, _: &SharedStyleContext, _: Option<PseudoEle...
method has_css_transitions (line 1522) | fn has_css_transitions(&self, _: &SharedStyleContext, _: Option<PseudoEl...
method needs_transitions_update (line 1536) | fn needs_transitions_update(
method has_data (line 1578) | fn has_data(&self) -> bool {
method borrow_data (line 1583) | fn borrow_data(&self) -> Option<ElementDataRef<'_>> {
method mutate_data (line 1588) | fn mutate_data(&self) -> Option<ElementDataMut<'_>> {
method lang_attr (line 1593) | fn lang_attr(&self) -> Option<AttrValue> {
method match_element_lang (line 1602) | fn match_element_lang(&self, override_lang: Option<Option<AttrValue>>, v...
method is_html_document_body_element (line 1619) | fn is_html_document_body_element(&self) -> bool {
method synthesize_view_transition_dynamic_rules (line 1631) | fn synthesize_view_transition_dynamic_rules<V>(&self, rules: &mut V)
method synthesize_presentational_hints_for_legacy_attributes (line 1646) | fn synthesize_presentational_hints_for_legacy_attributes<V>(
method has_selector_flags (line 1803) | fn has_selector_flags(&self, flags: ElementSelectorFlags) -> bool {
method relative_selector_search_direction (line 1808) | fn relative_selector_search_direction(&self) -> ElementSelectorFlags {
method get_attr (line 1824) | fn get_attr(&self, attr: &LocalName, namespace: &Namespace) -> Option<St...
method eq (line 1844) | fn eq(&self, other: &Self) -> bool {
method hash (line 1853) | fn hash<H: Hasher>(&self, state: &mut H) {
type Impl (line 1859) | type Impl = SelectorImpl;
function opaque (line 1862) | fn opaque(&self) -> OpaqueElement {
function parent_element (line 1867) | fn parent_element(&self) -> Option<Self> {
function parent_node_is_shadow_root (line 1873) | fn parent_node_is_shadow_root(&self) -> bool {
function containing_shadow_host (line 1880) | fn containing_shadow_host(&self) -> Option<Self> {
function is_pseudo_element (line 1886) | fn is_pseudo_element(&self) -> bool {
function pseudo_element_originating_element (line 1891) | fn pseudo_element_originating_element(&self) -> Option<Self> {
function assigned_slot (line 1908) | fn assigned_slot(&self) -> Option<Self> {
function prev_sibling_element (line 1915) | fn prev_sibling_element(&self) -> Option<Self> {
function next_sibling_element (line 1927) | fn next_sibling_element(&self) -> Option<Self> {
function first_element_child (line 1939) | fn first_element_child(&self) -> Option<Self> {
function apply_selector_flags (line 1950) | fn apply_selector_flags(&self, flags: ElementSelectorFlags) {
function has_attr_in_no_namespace (line 1969) | fn has_attr_in_no_namespace(&self, local_name: &LocalName) -> bool {
function attr_matches (line 1978) | fn attr_matches(
function is_root (line 1988) | fn is_root(&self) -> bool {
function is_empty (line 2008) | fn is_empty(&self) -> bool {
function has_local_name (line 2016) | fn has_local_name(&self, name: &WeakAtom) -> bool {
function has_namespace (line 2021) | fn has_namespace(&self, ns: &WeakNamespace) -> bool {
function is_same_type (line 2026) | fn is_same_type(&self, other: &Self) -> bool {
function match_non_ts_pseudo_class (line 2030) | fn match_non_ts_pseudo_class(
function match_pseudo_element (line 2186) | fn match_pseudo_element(
function is_link (line 2203) | fn is_link(&self) -> bool {
function has_id (line 2208) | fn has_id(&self, id: &AtomIdent, case_sensitivity: CaseSensitivity) -> b...
function is_part (line 2222) | fn is_part(&self, name: &AtomIdent) -> bool {
function imported_part (line 2232) | fn imported_part(&self, name: &AtomIdent) -> Option<AtomIdent> {
function has_class (line 2237) | fn has_class(&self, name: &AtomIdent, case_sensitivity: CaseSensitivity)...
function has_custom_state (line 2247) | fn has_custom_state(&self, state: &AtomIdent) -> bool {
function is_html_element_in_html_document (line 2261) | fn is_html_element_in_html_document(&self) -> bool {
function is_html_slot_element (line 2266) | fn is_html_slot_element(&self) -> bool {
function ignores_nth_child_selectors (line 2271) | fn ignores_nth_child_selectors(&self) -> bool {
function add_element_unique_hashes (line 2275) | fn add_element_unique_hashes(&self, filter: &mut BloomFilter) -> bool {
FILE: style/gecko_bindings/sugar/ns_com_ptr.rs
function raw (line 12) | pub fn raw(&self) -> *mut T {
FILE: style/gecko_bindings/sugar/ns_compatibility.rs
method from (line 12) | fn from(mode: nsCompatibility) -> QuirksMode {
FILE: style/gecko_bindings/sugar/ns_style_auto_array.rs
type Output (line 19) | type Output = T;
function index (line 20) | fn index(&self, index: usize) -> &T {
function index_mut (line 29) | fn index_mut(&mut self, index: usize) -> &mut T {
function iter_mut (line 39) | pub fn iter_mut(&mut self) -> Chain<Once<&mut T>, IterMut<'_, T>> {
function iter (line 44) | pub fn iter(&self) -> Chain<Once<&T>, Iter<'_, T>> {
function len (line 52) | pub fn len(&self) -> usize {
function ensure_len (line 59) | pub fn ensure_len(&mut self, len: usize) {
function ensure_len (line 71) | pub fn ensure_len(&mut self, len: usize) {
function ensure_len (line 83) | pub fn ensure_len(&mut self, len: usize) {
function ensure_len (line 95) | pub fn ensure_len(&mut self, len: usize) {
type Item (line 106) | type Item = &'a mut T;
type IntoIter (line 107) | type IntoIter = Chain<Once<&'a mut T>, IterMut<'a, T>>;
method into_iter (line 108) | fn into_iter(self) -> Self::IntoIter {
FILE: style/gecko_bindings/sugar/origin_flags.rs
function assert_flags_match (line 11) | pub fn assert_flags_match() {
method from (line 22) | fn from(flags: OriginFlags) -> Self {
method from (line 28) | fn from(set: OriginSet) -> Self {
FILE: style/gecko_bindings/sugar/ownership.rs
type Strong (line 19) | pub struct Strong<GeckoType> {
function from (line 25) | fn from(arc: Arc<T>) -> Self {
function from (line 34) | fn from(arc: Option<Arc<T>>) -> Self {
function is_null (line 45) | pub fn is_null(&self) -> bool {
function null (line 51) | pub fn null() -> Self {
type Target (line 60) | type Target = T;
method deref (line 61) | fn deref(&self) -> &Self::Target {
method deref_mut (line 67) | fn deref_mut<'a>(&'a mut self) -> &'a mut T {
FILE: style/gecko_bindings/sugar/refptr.rs
type RefCounted (line 17) | pub unsafe trait RefCounted {
method addref (line 19) | fn addref(&self);
method release (line 21) | unsafe fn release(&self);
type ThreadSafeRefCounted (line 25) | pub unsafe trait ThreadSafeRefCounted: RefCounted {}
type RefPtr (line 29) | pub struct RefPtr<T: RefCounted> {
function fmt (line 35) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
function from_addrefed (line 46) | pub unsafe fn from_addrefed(ptr: *mut T) -> Self {
function is_null (line 55) | pub fn is_null(&self) -> bool {
function null (line 60) | pub fn null() -> Self {
function new (line 70) | pub unsafe fn new(ptr: *mut T) -> Self {
function forget (line 82) | pub fn forget(self) -> structs::RefPtr<T> {
function get (line 92) | pub fn get(&self) -> *mut T {
function addref (line 97) | pub fn addref(&self) {
function release (line 108) | pub unsafe fn release(&self) {
type Target (line 116) | type Target = T;
method deref (line 117) | fn deref(&self) -> &T {
function to_safe (line 127) | pub unsafe fn to_safe(&self) -> RefPtr<T> {
function into_safe (line 137) | pub unsafe fn into_safe(self) -> RefPtr<T> {
function set (line 152) | pub unsafe fn set(&mut self, other: &Self) {
function clear (line 163) | pub unsafe fn clear(&mut self) {
function set_move (line 175) | pub fn set_move(&mut self, other: RefPtr<T>) {
function null (line 187) | pub fn null() -> Self {
function from_arc (line 195) | pub fn from_arc(s: Arc<T>) -> Self {
function set_arc (line 203) | pub fn set_arc(&mut self, other: Arc<T>) {
method drop (line 214) | fn drop(&mut self) {
method clone (line 220) | fn clone(&self) -> Self {
method eq (line 230) | fn eq(&self, other: &Self) -> bool {
function addref_atom (line 281) | unsafe fn addref_atom(atom: *mut structs::nsAtom) {
function release_atom (line 286) | unsafe fn release_atom(atom: *mut structs::nsAtom) {
FILE: style/gecko_string_cache/mod.rs
type Atom (line 55) | pub struct Atom(NonZeroUsize);
method deserialize (line 84) | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
method borrow (line 127) | fn borrow(&self) -> &WeakAtom {
method is_static (line 379) | fn is_static(&self) -> bool {
method with (line 384) | pub unsafe fn with<F, R>(ptr: *const nsAtom, callback: F) -> R
method from_index_unchecked (line 397) | pub const unsafe fn from_index_unchecked(index: u16) -> Self {
method from_raw (line 404) | pub unsafe fn from_raw(ptr: *mut nsAtom) -> Self {
method from_addrefed (line 415) | pub unsafe fn from_addrefed(ptr: *mut nsAtom) -> Self {
method into_addrefed (line 422) | pub fn into_addrefed(self) -> *mut nsAtom {
method fmt (line 479) | fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
method fmt (line 485) | fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
method from (line 492) | fn from(string: &str) -> Atom {
method from (line 505) | fn from(slice: &[u16]) -> Atom {
method from (line 512) | fn from(string: &nsAString) -> Atom {
method from (line 519) | fn from(string: Cow<'a, str>) -> Atom {
method from (line 526) | fn from(string: String) -> Atom {
method serialize (line 58) | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
type AtomStrVisitor (line 67) | struct AtomStrVisitor;
type Value (line 69) | type Value = Atom;
method expecting (line 71) | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
method visit_str (line 75) | fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
type WeakAtom (line 96) | pub struct WeakAtom(nsAtom);
method eq (line 157) | fn eq(&self, other: &Atom) -> bool {
method new (line 169) | pub unsafe fn new<'a>(atom: *const nsAtom) -> &'a mut Self {
method clone (line 175) | pub fn clone(&self) -> Atom {
method get_hash (line 181) | pub fn get_hash(&self) -> u32 {
method as_slice (line 187) | pub fn as_slice(&self) -> &[u16] {
method chars (line 206) | fn chars(&self) -> DecodeUtf16<Cloned<slice::Iter<'_, u16>>> {
method with_str (line 214) | pub fn with_str<F, Output>(&self, cb: F) -> Output
method is_static (line 252) | pub fn is_static(&self) -> bool {
method is_ascii_lowercase (line 258) | fn is_ascii_lowercase(&self) -> bool {
method len (line 264) | pub fn len(&self) -> u32 {
method is_empty (line 270) | pub fn is_empty(&self) -> bool {
method as_ptr (line 276) | pub fn as_ptr(&self) -> *mut nsAtom {
method to_ascii_lowercase (line 282) | pub fn to_ascii_lowercase(&self) -> Atom {
method eq_ignore_ascii_case (line 308) | pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
method eq_ignore_ascii_case_slow (line 323) | fn eq_ignore_ascii_case_slow(&self, other: &Self) -> bool {
method fmt (line 342) | fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
method fmt (line 348) | fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
constant STATIC_ATOM_COUNT (line 99) | const STATIC_ATOM_COUNT: usize = GkAtoms_Atoms_AtomsCount as usize;
type Target (line 102) | type Target = WeakAtom;
method deref (line 105) | fn deref(&self) -> &WeakAtom {
method precomputed_hash (line 120) | fn precomputed_hash(&self) -> u32 {
method to_shmem (line 133) | fn to_shmem(&self, _builder: &mut SharedMemoryBuilder) -> to_shmem::Resu...
method eq (line 148) | fn eq(&self, other: &Self) -> bool {
function make_handle (line 357) | unsafe fn make_handle(ptr: *const nsAtom) -> NonZeroUsize {
function make_static_handle (line 367) | unsafe fn make_static_handle(ptr: *const nsStaticAtom) -> NonZeroUsize {
method hash (line 430) | fn hash<H>(&self, state: &mut H)
method hash (line 439) | fn hash<H>(&self, state: &mut H)
method clone (line 449) | fn clone(&self) -> Atom {
method drop (line 462) | fn drop(&mut self) {
method default (line 473) | fn default() -> Self {
FILE: style/gecko_string_cache/namespace.rs
type Namespace (line 41) | pub struct Namespace(pub Atom);
method from (line 65) | fn from(s: &'a str) -> Self {
method fmt (line 71) | fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
method borrow (line 78) | fn borrow(&self) -> &WeakNamespace {
method precomputed_hash (line 45) | fn precomputed_hash(&self) -> u32 {
type WeakNamespace (line 52) | pub struct WeakNamespace(WeakAtom);
method new (line 86) | pub unsafe fn new<'a>(atom: *mut nsAtom) -> &'a Self {
method clone (line 93) | pub fn clone(&self) -> Namespace {
type Target (line 55) | type Target = WeakNamespace;
method deref (line 58) | fn deref(&self) -> &WeakNamespace {
method eq (line 101) | fn eq(&self, other: &Self) -> bool {
FILE: style/global_style_data.rs
type PlatformThreadHandle (line 23) | pub type PlatformThreadHandle = RawPthread;
type PlatformThreadHandle (line 26) | pub type PlatformThreadHandle = RawHandle;
type DummyThreadHandle (line 31) | pub struct DummyThreadHandle;
method join (line 35) | pub fn join(&self) {
type PlatformThreadHandle (line 41) | pub type PlatformThreadHandle = DummyThreadHandle;
type GlobalStyleData (line 44) | pub struct GlobalStyleData {
type StyleThreadPool (line 53) | pub struct StyleThreadPool {
method shutdown (line 110) | pub fn shutdown() {
method pool (line 131) | pub fn pool(&self) -> RwLockReadGuard<'_, Option<rayon::ThreadPool>> {
method get_thread_handles (line 136) | pub fn get_thread_handles(handles: &mut ThinVec<PlatformThreadHandle>) {
function thread_name (line 64) | fn thread_name(index: usize) -> String {
function thread_spawn (line 77) | fn thread_spawn(options: rayon::ThreadBuilder) -> io::Result<()> {
function thread_startup (line 90) | fn thread_startup(_index: usize) {
function thread_shutdown (line 100) | fn thread_shutdown(_: usize) {
function stylo_threads_pref (line 158) | fn stylo_threads_pref() -> i32 {
function stylo_threads_pref (line 163) | fn stylo_threads_pref() -> i32 {
constant STYLO_MAX_THREADS (line 169) | pub(crate) const STYLO_MAX_THREADS: usize = 6;
FILE: style/invalidation/element/document_state.rs
type InvalidationMatchingData (line 25) | pub struct InvalidationMatchingData {
method default (line 32) | fn default() -> Self {
type DocumentStateInvalidationProcessor (line 41) | pub struct DocumentStateInvalidationProcessor<'a, 'b, E: TElement, I> {
function new (line 52) | pub fn new(
function check_outer_dependency (line 86) | fn check_outer_dependency(&mut self, _: &Dependency, _: E, _: Option<Opa...
function collect_invalidations (line 94) | fn collect_invalidations(
function matching_context (line 126) | fn matching_context(&mut self) -> &mut MatchingContext<'a, E::Impl> {
function sibling_traversal_map (line 130) | fn sibling_traversal_map(&self) -> &SiblingTraversalMap<E> {
function recursion_limit_exceeded (line 134) | fn recursion_limit_exceeded(&mut self, _: E) {
function should_process_descendants (line 138) | fn should_process_descendants(&mut self, element: E) -> bool {
function invalidated_descendants (line 145) | fn invalidated_descendants(&mut self, element: E, child: E) {
function invalidated_self (line 149) | fn invalidated_self(&mut self, element: E) {
function invalidated_sibling (line 153) | fn invalidated_sibling(&mut self, sibling: E, of: E) {
FILE: style/invalidation/element/element_wrapper.rs
type ElementSnapshot (line 41) | pub trait ElementSnapshot: Sized {
method state (line 43) | fn state(&self) -> Option<ElementState>;
method has_attrs (line 46) | fn has_attrs(&self) -> bool;
method debug_list_attributes (line 51) | fn debug_list_attributes(&self) -> String {
method id_attr (line 57) | fn id_attr(&self) -> Option<&WeakAtom>;
method has_class (line 61) | fn has_class(&self, name: &AtomIdent, case_sensitivity: CaseSensitivit...
method is_part (line 65) | fn is_part(&self, name: &AtomIdent) -> bool;
method imported_part (line 68) | fn imported_part(&self, name: &AtomIdent) -> Option<AtomIdent>;
method each_class (line 72) | fn each_class<F>(&self, _: F)
method has_custom_states (line 77) | fn has_custom_states(&self) -> bool;
method has_custom_state (line 80) | fn has_custom_state(&self, state: &AtomIdent) -> bool;
method each_custom_state (line 83) | fn each_custom_state<F>(&self, callback: F)
method lang_attr (line 88) | fn lang_attr(&self) -> Option<AttrValue>;
type ElementWrapper (line 94) | pub struct ElementWrapper<'a, E>
function new (line 108) | pub fn new(el: E, snapshot_map: &'a SnapshotMap) -> Self {
function snapshot (line 117) | pub fn snapshot(&self) -> Option<&'a Snapshot> {
function state_changes (line 135) | pub fn state_changes(&self) -> ElementState {
function get_lang (line 150) | fn get_lang(&self) -> Option<AttrValue> {
function fmt (line 169) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
type Impl (line 179) | type Impl = SelectorImpl;
method match_non_ts_pseudo_class (line 181) | fn match_non_ts_pseudo_class(
method apply_selector_flags (line 257) | fn apply_selector_flags(&self, _flags: ElementSelectorFlags) {
method match_pseudo_element (line 261) | fn match_pseudo_element(
method is_link (line 269) | fn is_link(&self) -> bool {
method opaque (line 276) | fn opaque(&self) -> OpaqueElement {
method parent_element (line 280) | fn parent_element(&self) -> Option<Self> {
method parent_node_is_shadow_root (line 285) | fn parent_node_is_shadow_root(&self) -> bool {
method containing_shadow_host (line 289) | fn containing_shadow_host(&self) -> Option<Self> {
method prev_sibling_element (line 294) | fn prev_sibling_element(&self) -> Option<Self> {
method next_sibling_element (line 299) | fn next_sibli
Condensed preview — 375 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (5,558K chars).
[
{
"path": ".github/workflows/main.yml",
"chars": 1782,
"preview": "name: CI\n\non:\n push:\n branches: [\"main\"]\n pull_request:\n workflow_dispatch:\n merge_group:\n types: [checks_requ"
},
{
"path": ".github/workflows/mirror-to-release-branch.yml",
"chars": 730,
"preview": "name: 🪞 Mirror `main`\non:\n push:\n branches:\n - main\n\njobs:\n mirror:\n name: Mirror\n runs-on: ubuntu-lates"
},
{
"path": ".github/workflows/sync-upstream.yml",
"chars": 500,
"preview": "name: Sync upstream with mozilla-central\n\non:\n schedule:\n - cron: '0 13 * * *'\n workflow_dispatch:\n\njobs:\n sync:\n "
},
{
"path": ".gitignore",
"chars": 72,
"preview": "/_cache/\n/_filtered/\n/target/\n/style/properties/__pycache__/\nCargo.lock\n"
},
{
"path": "Cargo.toml",
"chars": 1371,
"preview": "[workspace]\nresolver = \"2\"\nmembers = [\n \"stylo_atoms\",\n \"stylo_dom\",\n \"malloc_size_of\",\n \"rustfmt.toml\",\n "
},
{
"path": "README.md",
"chars": 7394,
"preview": "Stylo\n=====\n\n**High-Performance CSS Style Engine**\n\n[ arguments ...]\n# Given"
},
{
"path": "commit-from-squashed.sh",
"chars": 608,
"preview": "#!/bin/sh\n# Usage: commit-from-squashed.sh <squashed commit> [extra git-commit(1) arguments ...]\n# Given a squashed comm"
},
{
"path": "malloc_size_of/Cargo.toml",
"chars": 651,
"preview": "[package]\nname = \"stylo_malloc_size_of\"\nversion.workspace = true\nauthors = [\"The Servo Project Developers\"]\nlicense = \"M"
},
{
"path": "malloc_size_of/LICENSE-APACHE",
"chars": 10847,
"preview": " Apache License\n Version 2.0, January 2004\n http"
},
{
"path": "malloc_size_of/LICENSE-MIT",
"chars": 1023,
"preview": "Permission is hereby granted, free of charge, to any\nperson obtaining a copy of this software and associated\ndocumentati"
},
{
"path": "malloc_size_of/lib.rs",
"chars": 28520,
"preview": "// Copyright 2016-2017 The Servo Project Developers. See the COPYRIGHT\n// file at the top-level directory of this distri"
},
{
"path": "rustfmt.toml",
"chars": 57,
"preview": "match_block_trailing_comma = true\nreorder_imports = true\n"
},
{
"path": "selectors/CHANGES.md",
"chars": 184,
"preview": "- `parser.rs` no longer wraps values in quotes (`\"...\"`) but expects their `to_css` impl to already wrap it ([Gecko Bug "
},
{
"path": "selectors/Cargo.toml",
"chars": 868,
"preview": "[package]\nname = \"selectors\"\nversion = \"0.38.0\"\nauthors = [\"The Servo Project Developers\"]\ndocumentation = \"https://docs"
},
{
"path": "selectors/README.md",
"chars": 1166,
"preview": "rust-selectors\n==============\n\n* []("
},
{
"path": "selectors/attr.rs",
"chars": 6685,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "selectors/bloom.rs",
"chars": 11810,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "selectors/build.rs",
"chars": 1446,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "selectors/builder.rs",
"chars": 16711,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "selectors/context.rs",
"chars": 17280,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "selectors/kleene_value.rs",
"chars": 3575,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "selectors/lib.rs",
"chars": 643,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "selectors/matching.rs",
"chars": 56962,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "selectors/nth_index_cache.rs",
"chars": 3176,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "selectors/parser.rs",
"chars": 176499,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "selectors/relative_selector/cache.rs",
"chars": 2743,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "selectors/relative_selector/filter.rs",
"chars": 6078,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "selectors/relative_selector/mod.rs",
"chars": 238,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "selectors/sink.rs",
"chars": 950,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "selectors/tree.rs",
"chars": 6347,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "selectors/visitor.rs",
"chars": 4884,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "servo_arc/Cargo.toml",
"chars": 569,
"preview": "[package]\nname = \"servo_arc\"\nversion = \"0.4.3\"\nauthors = [\"The Servo Project Developers\"]\nlicense = \"MIT OR Apache-2.0\"\n"
},
{
"path": "servo_arc/LICENSE-APACHE",
"chars": 10847,
"preview": " Apache License\n Version 2.0, January 2004\n http"
},
{
"path": "servo_arc/LICENSE-MIT",
"chars": 1023,
"preview": "Permission is hereby granted, free of charge, to any\nperson obtaining a copy of this software and associated\ndocumentati"
},
{
"path": "servo_arc/lib.rs",
"chars": 39440,
"preview": "// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT\n// file at the top-level directory of this distrib"
},
{
"path": "shell.nix",
"chars": 201,
"preview": "with import (builtins.fetchTarball {\n url = \"https://github.com/NixOS/nixpkgs/archive/46ae0210ce163b3cba6c7da08840c1d63"
},
{
"path": "start-rebase.sh",
"chars": 333,
"preview": "#!/bin/sh\n# Usage: start-rebase.sh <new base> [extra git-rebase(1) arguments ...]\n# Equivalent to git rebase --onto <new"
},
{
"path": "style/Cargo.toml",
"chars": 2846,
"preview": "[package]\nname = \"stylo\"\nversion.workspace = true\nauthors = [\"The Servo Project Developers\"]\nlicense = \"MPL-2.0\"\nreposit"
},
{
"path": "style/README.md",
"chars": 195,
"preview": "servo-style\n===========\n\nStyle system for Servo, using [rust-cssparser](https://github.com/servo/rust-cssparser) for par"
},
{
"path": "style/applicable_declarations.rs",
"chars": 10944,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/author_styles.rs",
"chars": 2272,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/bezier.rs",
"chars": 4873,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/bloom.rs",
"chars": 14443,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/build.rs",
"chars": 2759,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/build_gecko.rs",
"chars": 13159,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/color/color_function.rs",
"chars": 23454,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/color/component.rs",
"chars": 7559,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/color/convert.rs",
"chars": 29743,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/color/mix.rs",
"chars": 20546,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/color/mod.rs",
"chars": 25889,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/color/parsing.rs",
"chars": 20020,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/color/to_css.rs",
"chars": 10626,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/context.rs",
"chars": 24822,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/counter_style/mod.rs",
"chars": 26044,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/counter_style/predefined.rs",
"chars": 1286,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/counter_style/update_predefined.py",
"chars": 1094,
"preview": "#!/usr/bin/env python\n\n# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a cop"
},
{
"path": "style/custom_properties.rs",
"chars": 113999,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/custom_properties_map.rs",
"chars": 9027,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/data.rs",
"chars": 23574,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/device/gecko.rs",
"chars": 18197,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/device/mod.rs",
"chars": 11988,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/device/servo.rs",
"chars": 17030,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/dom.rs",
"chars": 38233,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/dom_apis.rs",
"chars": 30153,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/driver.rs",
"chars": 6484,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/error_reporting.rs",
"chars": 21162,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/font_face.rs",
"chars": 19181,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/font_metrics.rs",
"chars": 4722,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko/anon_boxes.toml",
"chars": 2954,
"preview": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not di"
},
{
"path": "style/gecko/arc_types.rs",
"chars": 5543,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko/conversions.rs",
"chars": 1979,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko/data.rs",
"chars": 7639,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko/media_features.rs",
"chars": 31449,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko/mod.rs",
"chars": 534,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko/non_ts_pseudo_class_list.rs",
"chars": 6538,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko/pseudo_element.rs",
"chars": 22903,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko/pseudo_element_definition.mako.rs",
"chars": 10419,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko/pseudo_elements.py",
"chars": 4518,
"preview": "#!/usr/bin/env python\n\n# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a cop"
},
{
"path": "style/gecko/pseudo_elements.toml",
"chars": 5989,
"preview": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not di"
},
{
"path": "style/gecko/regen_atoms.py",
"chars": 4278,
"preview": "#!/usr/bin/env python\n\n# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a cop"
},
{
"path": "style/gecko/restyle_damage.rs",
"chars": 4029,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko/selector_parser.rs",
"chars": 24724,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko/snapshot.rs",
"chars": 6327,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko/snapshot_helpers.rs",
"chars": 10386,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko/traversal.rs",
"chars": 1749,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko/url.rs",
"chars": 13714,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko/wrapper.rs",
"chars": 79259,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko_bindings/mod.rs",
"chars": 929,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko_bindings/sugar/mod.rs",
"chars": 384,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko_bindings/sugar/ns_com_ptr.rs",
"chars": 432,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko_bindings/sugar/ns_compatibility.rs",
"chars": 733,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko_bindings/sugar/ns_style_auto_array.rs",
"chars": 3698,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko_bindings/sugar/origin_flags.rs",
"chars": 985,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko_bindings/sugar/ownership.rs",
"chars": 1632,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko_bindings/sugar/refptr.rs",
"chars": 7903,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko_string_cache/mod.rs",
"chars": 15084,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/gecko_string_cache/namespace.rs",
"chars": 2460,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/global_style_data.rs",
"chars": 7939,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/invalidation/element/document_state.rs",
"chars": 5314,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/invalidation/element/element_wrapper.rs",
"chars": 14390,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/invalidation/element/invalidation_map.rs",
"chars": 60232,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/invalidation/element/invalidator.rs",
"chars": 54334,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/invalidation/element/mod.rs",
"chars": 454,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/invalidation/element/relative_selector.rs",
"chars": 55753,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/invalidation/element/restyle_hints.rs",
"chars": 8505,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/invalidation/element/state_and_attributes.rs",
"chars": 27200,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/invalidation/media_queries.rs",
"chars": 4414,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/invalidation/mod.rs",
"chars": 351,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/invalidation/stylesheets.rs",
"chars": 26170,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/invalidation/viewport_units.rs",
"chars": 2105,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/lib.rs",
"chars": 9183,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/logical_geometry.rs",
"chars": 53249,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/macros.rs",
"chars": 2052,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/matching.rs",
"chars": 44347,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/media_queries/media_list.rs",
"chars": 5935,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/media_queries/media_query.rs",
"chars": 6424,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/media_queries/mod.rs",
"chars": 436,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/parallel.rs",
"chars": 8009,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/parser.rs",
"chars": 8608,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/piecewise_linear.rs",
"chars": 10178,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/properties/build.py",
"chars": 3720,
"preview": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not di"
},
{
"path": "style/properties/cascade.rs",
"chars": 56538,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/properties/computed_value_flags.rs",
"chars": 7701,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/properties/counted_unknown_properties.py",
"chars": 3261,
"preview": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not di"
},
{
"path": "style/properties/counter_style_descriptors.toml",
"chars": 1249,
"preview": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not di"
},
{
"path": "style/properties/data.py",
"chars": 47435,
"preview": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not di"
},
{
"path": "style/properties/declaration_block.rs",
"chars": 62393,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/properties/font_face_descriptors.toml",
"chars": 923,
"preview": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not di"
},
{
"path": "style/properties/gecko.mako.rs",
"chars": 58832,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/properties/helpers/animated_properties.mako.rs",
"chars": 29835,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/properties/helpers.mako.rs",
"chars": 29777,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/properties/longhands.toml",
"chars": 122101,
"preview": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not di"
},
{
"path": "style/properties/mod.rs",
"chars": 59900,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/properties/properties.html.mako",
"chars": 1006,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width"
},
{
"path": "style/properties/properties.mako.rs",
"chars": 117943,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/properties/property_descriptors.toml",
"chars": 629,
"preview": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not di"
},
{
"path": "style/properties/shorthands.rs",
"chars": 158158,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/properties/shorthands.toml",
"chars": 18154,
"preview": "[margin]\nsub_properties = [\"margin-top\", \"margin-right\", \"margin-bottom\", \"margin-left\"]\nspec = \"https://drafts.csswg.or"
},
{
"path": "style/properties/vendored_python/markupsafe/LICENSE.txt",
"chars": 1474,
"preview": "Copyright 2010 Pallets\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted p"
},
{
"path": "style/properties/vendored_python/markupsafe/__init__.py",
"chars": 13096,
"preview": "# Vendored from https://github.com/pallets/markupsafe/blob/1251593f6b0e3b45f2cc8aba662622bc22d6a5e2/src/markupsafe/__ini"
},
{
"path": "style/properties/view_transition_descriptors.toml",
"chars": 320,
"preview": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not di"
},
{
"path": "style/properties_and_values/mod.rs",
"chars": 365,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/properties_and_values/registry.rs",
"chars": 2588,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/properties_and_values/rule.rs",
"chars": 12334,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/properties_and_values/syntax/ascii.rs",
"chars": 1527,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/properties_and_values/syntax/data_type.rs",
"chars": 5242,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/properties_and_values/syntax/mod.rs",
"chars": 13925,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/properties_and_values/value.rs",
"chars": 26988,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/queries/condition.rs",
"chars": 35675,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/queries/feature.rs",
"chars": 7376,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/queries/feature_expression.rs",
"chars": 42667,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/queries/mod.rs",
"chars": 662,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/queries/values.rs",
"chars": 1400,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/rule_cache.rs",
"chars": 8417,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/rule_collector.rs",
"chars": 18279,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/rule_tree/core.rs",
"chars": 28141,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/rule_tree/level.rs",
"chars": 10716,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/rule_tree/map.rs",
"chars": 6120,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/rule_tree/mod.rs",
"chars": 17065,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/rule_tree/source.rs",
"chars": 1963,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/rule_tree/unsafe_box.rs",
"chars": 1970,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/scoped_tls.rs",
"chars": 2973,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/selector_map.rs",
"chars": 29426,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/selector_parser.rs",
"chars": 10085,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/servo/animation.rs",
"chars": 72375,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/servo/attr.rs",
"chars": 20892,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/servo/encoding_support.rs",
"chars": 2662,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/servo/media_features.rs",
"chars": 2693,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/servo/mod.rs",
"chars": 493,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/servo/restyle_damage.rs",
"chars": 8440,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/servo/selector_parser.rs",
"chars": 35119,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/servo/shadow_parts.rs",
"chars": 7488,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/servo/url.rs",
"chars": 10362,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/shared_lock.rs",
"chars": 11995,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/sharing/checks.rs",
"chars": 7013,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/sharing/mod.rs",
"chars": 36626,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/simple_buckets_map.rs",
"chars": 1759,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/str.rs",
"chars": 4716,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/style_adjuster.rs",
"chars": 42232,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/style_resolver.rs",
"chars": 21333,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/stylesheet_set.rs",
"chars": 21531,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/stylesheets/appearance_base_rule.rs",
"chars": 1922,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/stylesheets/container_rule.rs",
"chars": 23570,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/stylesheets/counter_style_rule.rs",
"chars": 280,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/stylesheets/document_rule.rs",
"chars": 11141,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/stylesheets/font_face_rule.rs",
"chars": 272,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/stylesheets/font_feature_values_rule.rs",
"chars": 18228,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/stylesheets/font_palette_values_rule.rs",
"chars": 9872,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/stylesheets/import_rule.rs",
"chars": 8531,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/stylesheets/keyframes_rule.rs",
"chars": 23343,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/stylesheets/layer_rule.rs",
"chars": 7033,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/stylesheets/loader.rs",
"chars": 1094,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/stylesheets/margin_rule.rs",
"chars": 7195,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/stylesheets/media_rule.rs",
"chars": 7137,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/stylesheets/mod.rs",
"chars": 36009,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/stylesheets/namespace_rule.rs",
"chars": 1440,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/stylesheets/nested_declarations_rule.rs",
"chars": 1763,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
},
{
"path": "style/stylesheets/origin.rs",
"chars": 7020,
"preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
}
]
// ... and 175 more files (download for full content)
About this extraction
This page contains the full source code of the servo/stylo GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 375 files (5.1 MB), approximately 1.4M tokens, and a symbol index with 8600 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.