2016-01-19 11:49:10 +03:00
|
|
|
/* 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 http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
use app_units::Au;
|
2016-11-07 08:26:08 +03:00
|
|
|
use cssparser::Parser;
|
2016-11-24 02:47:18 +03:00
|
|
|
use cssparser::ToCss as ParserToCss;
|
2016-05-05 04:37:26 +03:00
|
|
|
use env_logger;
|
2016-01-19 11:49:10 +03:00
|
|
|
use euclid::Size2D;
|
2016-10-04 19:58:56 +03:00
|
|
|
use parking_lot::RwLock;
|
2016-11-25 20:00:44 +03:00
|
|
|
use selectors::Element;
|
2016-11-18 00:34:47 +03:00
|
|
|
use servo_url::ServoUrl;
|
2016-12-18 05:22:10 +03:00
|
|
|
use std::borrow::Cow;
|
2016-11-04 07:42:06 +03:00
|
|
|
use std::fmt::Write;
|
servo: Merge #12515 - Make the style crate more concrete (from servo:concrete-style); r=bholley
Background:
The changes to Servo code to support Stylo began in the `selectors` crate with making pseudo-elements generic, defined be the user, so that different users (such as Servo and Gecko/Stylo) could have a different set of pseudo-elements supported and parsed. Adding a trait makes sense there since `selectors` is in its own repository and has others users (or at least [one](https://github.com/SimonSapin/kuchiki)).
Then we kind of kept going with the same pattern and added a bunch of traits in the `style` crate to make everything generic, allowing Servo and Gecko/Stylo to do things differently. But we’ve also added a `gecko` Cargo feature to do conditional compilation, at first to enable or disable some CSS properties and values in the Mako templates. Since we’re doing conditional compilation anyway, it’s often easier and simpler to do it more (with `#[cfg(feature = "gecko")]` and `#[cfg(feature = "servo")]`) that to keep adding traits and making everything generic. When a type is generic, any method that we want to call on it needs to be part of some trait.
----
The first several commits move some code around, mostly from `geckolib` to `style` (with `#[cfg(feature = "gecko")]`) but otherwise don’t change much.
The following commits remove some traits and many type parameters through the `style` crate, replacing them with pairs of conditionally-compiled API-compatible items (types, methods, …).
Simplifying code is nice to make it more maintainable, but this is motivated by another change described in https://github.com/servo/servo/pull/12391#issuecomment-232183942. (Porting Servo for that change proved difficult because some code in the `style` crate was becoming generic over `String` vs `Atom`, and this PR will help make that concrete. That change, in turn, is motivated by removing geckolib’s `[replace]` override for string-cache, in order to enable using a single Cargo "workspace" in this repository.)
r? @bholley
---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [x] These changes do not require new tests because refactoring
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: 2d01d41a506bcbc7f26a2284b9f42390d6ef96ab
--HG--
rename : servo/ports/geckolib/selector_impl.rs => servo/components/style/gecko_selector_impl.rs
rename : servo/ports/geckolib/values.rs => servo/components/style/gecko_values.rs
rename : servo/ports/geckolib/properties.mako.rs => servo/components/style/properties/gecko.mako.rs
2016-07-20 10:58:34 +03:00
|
|
|
use std::mem::transmute;
|
2016-11-25 20:00:44 +03:00
|
|
|
use std::ptr;
|
2016-02-04 20:55:09 +03:00
|
|
|
use std::sync::{Arc, Mutex};
|
2016-07-11 15:11:48 +03:00
|
|
|
use style::arc_ptr_eq;
|
2016-11-25 20:00:44 +03:00
|
|
|
use style::atomic_refcell::AtomicRefMut;
|
2016-12-21 22:11:12 +03:00
|
|
|
use style::context::{QuirksMode, ReflowGoal, SharedStyleContext, StyleContext};
|
|
|
|
use style::context::{ThreadLocalStyleContext, ThreadLocalStyleContextCreationInfo};
|
2016-12-26 05:13:30 +03:00
|
|
|
use style::data::{ElementData, ElementStyles, RestyleData};
|
2016-12-13 06:13:03 +03:00
|
|
|
use style::dom::{ShowSubtreeData, TElement, TNode};
|
2016-01-19 11:49:10 +03:00
|
|
|
use style::error_reporting::StdoutErrorReporter;
|
2016-11-25 20:00:44 +03:00
|
|
|
use style::gecko::data::{NUM_THREADS, PerDocumentStyleData, PerDocumentStyleDataImpl};
|
|
|
|
use style::gecko::restyle_damage::GeckoRestyleDamage;
|
2016-11-22 19:44:03 +03:00
|
|
|
use style::gecko::selector_parser::{SelectorImpl, PseudoElement};
|
2016-09-26 10:36:05 +03:00
|
|
|
use style::gecko::traversal::RecalcStyleOnly;
|
2016-10-18 08:51:14 +03:00
|
|
|
use style::gecko::wrapper::DUMMY_BASE_URL;
|
2016-11-25 20:00:44 +03:00
|
|
|
use style::gecko::wrapper::GeckoElement;
|
2016-10-18 08:51:14 +03:00
|
|
|
use style::gecko_bindings::bindings::{RawServoDeclarationBlockBorrowed, RawServoDeclarationBlockStrong};
|
2016-11-24 02:47:18 +03:00
|
|
|
use style::gecko_bindings::bindings::{RawServoStyleRuleBorrowed, RawServoStyleRuleStrong};
|
2016-09-26 10:36:05 +03:00
|
|
|
use style::gecko_bindings::bindings::{RawServoStyleSetBorrowed, RawServoStyleSetOwned};
|
|
|
|
use style::gecko_bindings::bindings::{RawServoStyleSheetBorrowed, ServoComputedValuesBorrowed};
|
|
|
|
use style::gecko_bindings::bindings::{RawServoStyleSheetStrong, ServoComputedValuesStrong};
|
2016-11-24 02:47:18 +03:00
|
|
|
use style::gecko_bindings::bindings::{ServoCssRulesBorrowed, ServoCssRulesStrong};
|
2016-11-04 07:42:06 +03:00
|
|
|
use style::gecko_bindings::bindings::{nsACString, nsAString};
|
2016-11-25 20:00:44 +03:00
|
|
|
use style::gecko_bindings::bindings::RawGeckoElementBorrowed;
|
2016-12-31 06:12:55 +03:00
|
|
|
use style::gecko_bindings::bindings::RawServoImportRuleBorrowed;
|
2016-10-18 08:51:14 +03:00
|
|
|
use style::gecko_bindings::bindings::ServoComputedValuesBorrowedOrNull;
|
2016-11-24 02:47:18 +03:00
|
|
|
use style::gecko_bindings::bindings::nsTArrayBorrowed_uintptr_t;
|
2016-11-25 20:00:44 +03:00
|
|
|
use style::gecko_bindings::structs;
|
2016-12-18 05:22:10 +03:00
|
|
|
use style::gecko_bindings::structs::{SheetParsingMode, nsIAtom, nsCSSPropertyID};
|
2016-12-05 14:52:16 +03:00
|
|
|
use style::gecko_bindings::structs::{ThreadSafePrincipalHolder, ThreadSafeURIHolder};
|
2016-11-25 20:00:44 +03:00
|
|
|
use style::gecko_bindings::structs::{nsRestyleHint, nsChangeHint};
|
2016-12-31 06:12:55 +03:00
|
|
|
use style::gecko_bindings::structs::Loader;
|
|
|
|
use style::gecko_bindings::structs::ServoStyleSheet;
|
2016-12-01 08:54:46 +03:00
|
|
|
use style::gecko_bindings::structs::nsresult;
|
2016-09-26 10:36:05 +03:00
|
|
|
use style::gecko_bindings::sugar::ownership::{FFIArcHelpers, HasArcFFI, HasBoxFFI};
|
|
|
|
use style::gecko_bindings::sugar::ownership::{HasSimpleFFI, Strong};
|
2016-10-14 06:31:20 +03:00
|
|
|
use style::gecko_bindings::sugar::refptr::{GeckoArcPrincipal, GeckoArcURI};
|
2016-02-04 20:55:09 +03:00
|
|
|
use style::parallel;
|
2016-10-09 16:53:28 +03:00
|
|
|
use style::parser::{ParserContext, ParserContextExtraData};
|
2016-10-27 04:14:04 +03:00
|
|
|
use style::properties::{CascadeFlags, ComputedValues, Importance, PropertyDeclaration};
|
2016-12-10 12:16:26 +03:00
|
|
|
use style::properties::{PropertyDeclarationParseResult, PropertyDeclarationBlock, PropertyId};
|
2016-11-06 01:11:24 +03:00
|
|
|
use style::properties::{apply_declarations, parse_one_declaration};
|
2016-11-25 20:00:44 +03:00
|
|
|
use style::restyle_hints::RestyleHint;
|
2016-11-20 18:21:52 +03:00
|
|
|
use style::selector_parser::PseudoElementCascadeType;
|
2016-07-06 04:55:36 +03:00
|
|
|
use style::sequential;
|
2016-09-26 10:36:05 +03:00
|
|
|
use style::string_cache::Atom;
|
2016-12-31 06:12:55 +03:00
|
|
|
use style::stylesheets::{CssRule, CssRules, Origin, Stylesheet, StyleRule, ImportRule};
|
|
|
|
use style::stylesheets::StylesheetLoader as StyleStylesheetLoader;
|
2016-11-21 17:16:36 +03:00
|
|
|
use style::thread_state;
|
2016-07-20 21:38:31 +03:00
|
|
|
use style::timer::Timer;
|
2016-12-28 06:55:01 +03:00
|
|
|
use style::traversal::{resolve_style, DomTraversal};
|
2016-11-07 08:26:08 +03:00
|
|
|
use style_traits::ToCss;
|
2016-12-16 20:43:19 +03:00
|
|
|
use stylesheet_loader::StylesheetLoader;
|
2016-09-26 10:36:05 +03:00
|
|
|
|
2016-01-19 11:49:10 +03:00
|
|
|
/*
|
|
|
|
* For Gecko->Servo function calls, we need to redeclare the same signature that was declared in
|
|
|
|
* the C header in Gecko. In order to catch accidental mismatches, we run rust-bindgen against
|
|
|
|
* those signatures as well, giving us a second declaration of all the Servo_* functions in this
|
|
|
|
* crate. If there's a mismatch, LLVM will assert and abort, which is a rather awful thing to
|
|
|
|
* depend on but good enough for our purposes.
|
|
|
|
*/
|
|
|
|
|
2016-05-05 04:37:26 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_Initialize() -> () {
|
|
|
|
// Enable standard Rust logging.
|
|
|
|
//
|
|
|
|
// See https://doc.rust-lang.org/log/env_logger/index.html for instructions.
|
|
|
|
env_logger::init().unwrap();
|
2016-08-04 04:20:21 +03:00
|
|
|
|
|
|
|
// Allocate our default computed values.
|
|
|
|
unsafe { ComputedValues::initialize(); }
|
2016-11-21 17:16:36 +03:00
|
|
|
|
|
|
|
// Pretend that we're a Servo Layout thread, to make some assertions happy.
|
|
|
|
thread_state::initialize(thread_state::LAYOUT);
|
2016-08-04 04:20:21 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_Shutdown() -> () {
|
|
|
|
// Destroy our default computed values.
|
|
|
|
unsafe { ComputedValues::shutdown(); }
|
2016-11-25 20:00:44 +03:00
|
|
|
}
|
2016-04-04 17:41:29 +03:00
|
|
|
|
2016-12-26 05:13:30 +03:00
|
|
|
fn create_shared_context(per_doc_data: &PerDocumentStyleDataImpl) -> SharedStyleContext {
|
2016-07-02 00:12:54 +03:00
|
|
|
let local_context_data =
|
2016-12-16 22:38:27 +03:00
|
|
|
ThreadLocalStyleContextCreationInfo::new(per_doc_data.new_animations_sender.clone());
|
2016-01-19 11:49:10 +03:00
|
|
|
|
2016-11-25 20:00:44 +03:00
|
|
|
SharedStyleContext {
|
2016-10-09 16:53:28 +03:00
|
|
|
// FIXME (bug 1303229): Use the actual viewport size here
|
2016-01-19 11:49:10 +03:00
|
|
|
viewport_size: Size2D::new(Au(0), Au(0)),
|
|
|
|
screen_size_changed: false,
|
|
|
|
goal: ReflowGoal::ForScriptQuery,
|
2016-07-02 00:12:54 +03:00
|
|
|
stylist: per_doc_data.stylist.clone(),
|
|
|
|
running_animations: per_doc_data.running_animations.clone(),
|
|
|
|
expired_animations: per_doc_data.expired_animations.clone(),
|
2016-01-19 11:49:10 +03:00
|
|
|
error_reporter: Box::new(StdoutErrorReporter),
|
2016-07-02 00:12:54 +03:00
|
|
|
local_context_creation_data: Mutex::new(local_context_data),
|
2016-07-20 21:38:31 +03:00
|
|
|
timer: Timer::new(),
|
2016-12-18 00:25:06 +03:00
|
|
|
// FIXME Find the real QuirksMode information for this document
|
|
|
|
quirks_mode: QuirksMode::NoQuirks,
|
2016-11-25 20:00:44 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn traverse_subtree(element: GeckoElement, raw_data: RawServoStyleSetBorrowed,
|
2016-12-13 06:13:03 +03:00
|
|
|
unstyled_children_only: bool) {
|
2016-11-25 20:00:44 +03:00
|
|
|
// Force the creation of our lazily-constructed initial computed values on
|
|
|
|
// the main thread, since it's not safe to call elsewhere.
|
|
|
|
//
|
|
|
|
// FIXME(bholley): this should move into Servo_Initialize as soon as we get
|
|
|
|
// rid of the HackilyFindSomeDeviceContext stuff that happens during
|
|
|
|
// initial_values computation, since that stuff needs to be called further
|
|
|
|
// along in startup than the sensible place to call Servo_Initialize.
|
|
|
|
ComputedValues::initial_values();
|
2016-01-19 11:49:10 +03:00
|
|
|
|
2016-11-25 20:00:44 +03:00
|
|
|
// When new content is inserted in a display:none subtree, we will call into
|
|
|
|
// servo to try to style it. Detect that here and bail out.
|
|
|
|
if let Some(parent) = element.parent_element() {
|
2016-12-15 06:41:12 +03:00
|
|
|
if parent.borrow_data().map_or(true, |d| d.styles().is_display_none()) {
|
2016-11-25 20:00:44 +03:00
|
|
|
debug!("{:?} has unstyled parent - ignoring call to traverse_subtree", parent);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-10 04:01:05 +03:00
|
|
|
let mut per_doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
|
|
|
|
2016-12-13 06:13:03 +03:00
|
|
|
let token = RecalcStyleOnly::pre_traverse(element, &per_doc_data.stylist, unstyled_children_only);
|
2016-12-10 04:01:05 +03:00
|
|
|
if !token.should_traverse() {
|
2016-11-25 20:00:44 +03:00
|
|
|
error!("Unnecessary call to traverse_subtree");
|
2016-10-26 14:36:06 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-12-13 06:13:03 +03:00
|
|
|
debug!("Traversing subtree:");
|
|
|
|
debug!("{:?}", ShowSubtreeData(element.as_node()));
|
|
|
|
|
2016-12-26 05:13:30 +03:00
|
|
|
let shared_style_context = create_shared_context(&per_doc_data);
|
2016-12-16 22:38:27 +03:00
|
|
|
let traversal = RecalcStyleOnly::new(shared_style_context);
|
2016-11-28 21:30:19 +03:00
|
|
|
let known_depth = None;
|
|
|
|
|
2016-08-26 09:46:16 +03:00
|
|
|
if per_doc_data.num_threads == 1 || per_doc_data.work_queue.is_none() {
|
2016-12-16 22:38:27 +03:00
|
|
|
sequential::traverse_dom(&traversal, element, token);
|
2016-07-28 01:56:26 +03:00
|
|
|
} else {
|
2016-12-16 22:38:27 +03:00
|
|
|
parallel::traverse_dom(&traversal, element, known_depth, token,
|
|
|
|
per_doc_data.work_queue.as_mut().unwrap());
|
2016-01-19 11:49:10 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-26 00:26:11 +03:00
|
|
|
#[no_mangle]
|
2016-11-25 20:00:44 +03:00
|
|
|
pub extern "C" fn Servo_TraverseSubtree(root: RawGeckoElementBorrowed,
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
2016-12-13 06:13:03 +03:00
|
|
|
behavior: structs::TraversalRootBehavior) -> () {
|
2016-11-25 20:00:44 +03:00
|
|
|
let element = GeckoElement(root);
|
|
|
|
debug!("Servo_TraverseSubtree: {:?}", element);
|
2016-12-13 06:13:03 +03:00
|
|
|
traverse_subtree(element, raw_data,
|
|
|
|
behavior == structs::TraversalRootBehavior::UnstyledChildrenOnly);
|
2016-05-26 00:26:11 +03:00
|
|
|
}
|
|
|
|
|
2016-10-09 16:53:28 +03:00
|
|
|
#[no_mangle]
|
2016-10-18 08:51:14 +03:00
|
|
|
pub extern "C" fn Servo_RestyleWithAddedDeclaration(declarations: RawServoDeclarationBlockBorrowed,
|
2016-10-09 16:53:28 +03:00
|
|
|
previous_style: ServoComputedValuesBorrowed)
|
|
|
|
-> ServoComputedValuesStrong
|
|
|
|
{
|
2016-11-06 01:11:24 +03:00
|
|
|
let previous_style = ComputedValues::as_arc(&previous_style);
|
2016-10-18 08:51:14 +03:00
|
|
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
2016-11-06 01:11:24 +03:00
|
|
|
|
|
|
|
let guard = declarations.read();
|
|
|
|
|
|
|
|
let declarations = || {
|
|
|
|
guard.declarations.iter().rev().map(|&(ref decl, _importance)| decl)
|
2016-10-18 08:51:14 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
// FIXME (bug 1303229): Use the actual viewport size here
|
2016-11-06 01:11:24 +03:00
|
|
|
let computed = apply_declarations(Size2D::new(Au(0), Au(0)),
|
|
|
|
/* is_root_element = */ false,
|
|
|
|
declarations,
|
|
|
|
previous_style,
|
|
|
|
None,
|
|
|
|
Box::new(StdoutErrorReporter),
|
2016-11-13 13:55:02 +03:00
|
|
|
None,
|
2016-11-06 01:11:24 +03:00
|
|
|
CascadeFlags::empty());
|
2016-10-18 08:51:14 +03:00
|
|
|
Arc::new(computed).into_strong()
|
2016-10-09 16:53:28 +03:00
|
|
|
}
|
|
|
|
|
2016-07-06 04:55:36 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleWorkerThreadCount() -> u32 {
|
|
|
|
*NUM_THREADS as u32
|
|
|
|
}
|
|
|
|
|
2016-01-19 11:49:10 +03:00
|
|
|
#[no_mangle]
|
2016-11-25 20:00:44 +03:00
|
|
|
pub extern "C" fn Servo_Element_ClearData(element: RawGeckoElementBorrowed) -> () {
|
|
|
|
GeckoElement(element).clear_data();
|
2016-01-19 11:49:10 +03:00
|
|
|
}
|
2016-02-04 20:55:09 +03:00
|
|
|
|
2016-12-03 09:58:49 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_Element_ShouldTraverse(element: RawGeckoElementBorrowed) -> bool {
|
|
|
|
let element = GeckoElement(element);
|
|
|
|
if let Some(data) = element.get_data() {
|
|
|
|
debug_assert!(!element.has_dirty_descendants(),
|
|
|
|
"only call Servo_Element_ShouldTraverse if you know the element \
|
|
|
|
does not have dirty descendants");
|
|
|
|
match *data.borrow() {
|
|
|
|
ElementData::Initial(None) |
|
|
|
|
ElementData::Restyle(..) => true,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-10 21:56:48 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleSheet_Empty(mode: SheetParsingMode) -> RawServoStyleSheetStrong {
|
2016-11-18 00:34:47 +03:00
|
|
|
let url = ServoUrl::parse("about:blank").unwrap();
|
2016-11-10 21:56:48 +03:00
|
|
|
let extra_data = ParserContextExtraData::default();
|
|
|
|
let origin = match mode {
|
|
|
|
SheetParsingMode::eAuthorSheetFeatures => Origin::Author,
|
|
|
|
SheetParsingMode::eUserSheetFeatures => Origin::User,
|
|
|
|
SheetParsingMode::eAgentSheetFeatures => Origin::UserAgent,
|
|
|
|
};
|
2016-11-22 04:33:57 +03:00
|
|
|
let sheet = Arc::new(Stylesheet::from_str(
|
2016-12-31 06:12:55 +03:00
|
|
|
"", url, origin, Default::default(), None,
|
2016-12-16 20:43:19 +03:00
|
|
|
Box::new(StdoutErrorReporter), extra_data));
|
2016-11-10 21:56:48 +03:00
|
|
|
unsafe {
|
|
|
|
transmute(sheet)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-04 20:55:09 +03:00
|
|
|
#[no_mangle]
|
2016-12-31 06:12:55 +03:00
|
|
|
pub extern "C" fn Servo_StyleSheet_FromUTF8Bytes(loader: *mut Loader,
|
|
|
|
stylesheet: *mut ServoStyleSheet,
|
|
|
|
data: *const nsACString,
|
2016-10-25 12:09:19 +03:00
|
|
|
mode: SheetParsingMode,
|
|
|
|
base_url: *const nsACString,
|
|
|
|
base: *mut ThreadSafeURIHolder,
|
|
|
|
referrer: *mut ThreadSafeURIHolder,
|
|
|
|
principal: *mut ThreadSafePrincipalHolder)
|
|
|
|
-> RawServoStyleSheetStrong {
|
|
|
|
let input = unsafe { data.as_ref().unwrap().as_str_unchecked() };
|
2016-02-04 20:55:09 +03:00
|
|
|
|
2016-04-30 00:27:16 +03:00
|
|
|
let origin = match mode {
|
|
|
|
SheetParsingMode::eAuthorSheetFeatures => Origin::Author,
|
|
|
|
SheetParsingMode::eUserSheetFeatures => Origin::User,
|
|
|
|
SheetParsingMode::eAgentSheetFeatures => Origin::UserAgent,
|
|
|
|
};
|
|
|
|
|
2016-10-25 12:09:19 +03:00
|
|
|
let base_str = unsafe { base_url.as_ref().unwrap().as_str_unchecked() };
|
2016-11-18 00:34:47 +03:00
|
|
|
let url = ServoUrl::parse(base_str).unwrap();
|
2016-10-14 06:31:20 +03:00
|
|
|
let extra_data = unsafe { ParserContextExtraData {
|
2016-05-25 00:41:04 +03:00
|
|
|
base: Some(GeckoArcURI::new(base)),
|
|
|
|
referrer: Some(GeckoArcURI::new(referrer)),
|
|
|
|
principal: Some(GeckoArcPrincipal::new(principal)),
|
2016-10-14 06:31:20 +03:00
|
|
|
}};
|
2016-12-31 06:12:55 +03:00
|
|
|
let loader = if loader.is_null() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(StylesheetLoader::new(loader, stylesheet))
|
|
|
|
};
|
|
|
|
|
|
|
|
// FIXME(emilio): loader.as_ref() doesn't typecheck for some reason?
|
|
|
|
let loader: Option<&StyleStylesheetLoader> = match loader {
|
|
|
|
None => None,
|
|
|
|
Some(ref s) => Some(s),
|
|
|
|
};
|
|
|
|
|
2016-11-22 04:33:57 +03:00
|
|
|
let sheet = Arc::new(Stylesheet::from_str(
|
2016-12-31 06:12:55 +03:00
|
|
|
input, url, origin, Default::default(), loader,
|
2016-12-16 20:43:19 +03:00
|
|
|
Box::new(StdoutErrorReporter), extra_data));
|
2016-02-04 20:55:09 +03:00
|
|
|
unsafe {
|
|
|
|
transmute(sheet)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-31 06:12:55 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleSheet_ClearAndUpdate(stylesheet: RawServoStyleSheetBorrowed,
|
|
|
|
loader: *mut Loader,
|
|
|
|
gecko_stylesheet: *mut ServoStyleSheet,
|
|
|
|
data: *const nsACString,
|
|
|
|
base: *mut ThreadSafeURIHolder,
|
|
|
|
referrer: *mut ThreadSafeURIHolder,
|
|
|
|
principal: *mut ThreadSafePrincipalHolder)
|
|
|
|
{
|
|
|
|
let input = unsafe { data.as_ref().unwrap().as_str_unchecked() };
|
|
|
|
let extra_data = unsafe { ParserContextExtraData {
|
|
|
|
base: Some(GeckoArcURI::new(base)),
|
|
|
|
referrer: Some(GeckoArcURI::new(referrer)),
|
|
|
|
principal: Some(GeckoArcPrincipal::new(principal)),
|
|
|
|
}};
|
|
|
|
|
|
|
|
let loader = if loader.is_null() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(StylesheetLoader::new(loader, gecko_stylesheet))
|
|
|
|
};
|
|
|
|
|
|
|
|
// FIXME(emilio): loader.as_ref() doesn't typecheck for some reason?
|
|
|
|
let loader: Option<&StyleStylesheetLoader> = match loader {
|
|
|
|
None => None,
|
|
|
|
Some(ref s) => Some(s),
|
|
|
|
};
|
|
|
|
|
|
|
|
let sheet = Stylesheet::as_arc(&stylesheet);
|
|
|
|
sheet.rules.write().0.clear();
|
|
|
|
|
|
|
|
Stylesheet::update_from_str(&sheet, input, loader,
|
|
|
|
Box::new(StdoutErrorReporter), extra_data);
|
|
|
|
}
|
|
|
|
|
2016-02-04 20:55:09 +03:00
|
|
|
#[no_mangle]
|
2016-10-11 20:03:29 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_AppendStyleSheet(raw_data: RawServoStyleSetBorrowed,
|
2016-12-26 05:13:30 +03:00
|
|
|
raw_sheet: RawServoStyleSheetBorrowed,
|
|
|
|
flush: bool) {
|
2016-10-11 20:03:29 +03:00
|
|
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
2016-09-03 06:42:21 +03:00
|
|
|
let sheet = HasArcFFI::as_arc(&raw_sheet);
|
|
|
|
data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
|
|
|
|
data.stylesheets.push(sheet.clone());
|
|
|
|
data.stylesheets_changed = true;
|
2016-12-26 05:13:30 +03:00
|
|
|
if flush {
|
|
|
|
data.flush_stylesheets();
|
|
|
|
}
|
2016-02-04 20:55:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2016-10-11 20:03:29 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_PrependStyleSheet(raw_data: RawServoStyleSetBorrowed,
|
2016-12-26 05:13:30 +03:00
|
|
|
raw_sheet: RawServoStyleSheetBorrowed,
|
|
|
|
flush: bool) {
|
2016-10-11 20:03:29 +03:00
|
|
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
2016-09-03 06:42:21 +03:00
|
|
|
let sheet = HasArcFFI::as_arc(&raw_sheet);
|
|
|
|
data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
|
|
|
|
data.stylesheets.insert(0, sheet.clone());
|
|
|
|
data.stylesheets_changed = true;
|
2016-12-26 05:13:30 +03:00
|
|
|
if flush {
|
|
|
|
data.flush_stylesheets();
|
|
|
|
}
|
2016-02-04 20:55:09 +03:00
|
|
|
}
|
|
|
|
|
2016-04-29 08:37:40 +03:00
|
|
|
#[no_mangle]
|
2016-10-11 20:03:29 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_InsertStyleSheetBefore(raw_data: RawServoStyleSetBorrowed,
|
2016-08-24 16:16:05 +03:00
|
|
|
raw_sheet: RawServoStyleSheetBorrowed,
|
2016-12-26 05:13:30 +03:00
|
|
|
raw_reference: RawServoStyleSheetBorrowed,
|
|
|
|
flush: bool) {
|
2016-10-11 20:03:29 +03:00
|
|
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
2016-09-03 06:42:21 +03:00
|
|
|
let sheet = HasArcFFI::as_arc(&raw_sheet);
|
|
|
|
let reference = HasArcFFI::as_arc(&raw_reference);
|
|
|
|
data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
|
|
|
|
let index = data.stylesheets.iter().position(|x| arc_ptr_eq(x, reference)).unwrap();
|
|
|
|
data.stylesheets.insert(index, sheet.clone());
|
|
|
|
data.stylesheets_changed = true;
|
2016-12-26 05:13:30 +03:00
|
|
|
if flush {
|
|
|
|
data.flush_stylesheets();
|
|
|
|
}
|
2016-04-29 08:37:40 +03:00
|
|
|
}
|
|
|
|
|
2016-02-04 20:55:09 +03:00
|
|
|
#[no_mangle]
|
2016-10-11 20:03:29 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_RemoveStyleSheet(raw_data: RawServoStyleSetBorrowed,
|
2016-12-26 05:13:30 +03:00
|
|
|
raw_sheet: RawServoStyleSheetBorrowed,
|
|
|
|
flush: bool) {
|
2016-10-11 20:03:29 +03:00
|
|
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
2016-09-03 06:42:21 +03:00
|
|
|
let sheet = HasArcFFI::as_arc(&raw_sheet);
|
|
|
|
data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
|
|
|
|
data.stylesheets_changed = true;
|
2016-12-26 05:13:30 +03:00
|
|
|
if flush {
|
|
|
|
data.flush_stylesheets();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleSet_FlushStyleSheets(raw_data: RawServoStyleSetBorrowed) {
|
|
|
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
|
|
|
data.flush_stylesheets();
|
2016-02-04 20:55:09 +03:00
|
|
|
}
|
|
|
|
|
2016-12-19 08:49:28 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleSet_NoteStyleSheetsChanged(raw_data: RawServoStyleSetBorrowed) {
|
|
|
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
|
|
|
data.stylesheets_changed = true;
|
|
|
|
}
|
|
|
|
|
2016-02-04 20:55:09 +03:00
|
|
|
#[no_mangle]
|
2016-08-24 16:16:05 +03:00
|
|
|
pub extern "C" fn Servo_StyleSheet_HasRules(raw_sheet: RawServoStyleSheetBorrowed) -> bool {
|
2016-11-29 14:26:46 +03:00
|
|
|
!Stylesheet::as_arc(&raw_sheet).rules.read().0.is_empty()
|
2016-02-04 20:55:09 +03:00
|
|
|
}
|
|
|
|
|
2016-11-24 02:47:18 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleSheet_GetRules(sheet: RawServoStyleSheetBorrowed) -> ServoCssRulesStrong {
|
2016-11-29 14:26:46 +03:00
|
|
|
Stylesheet::as_arc(&sheet).rules.clone().into_strong()
|
2016-11-24 02:47:18 +03:00
|
|
|
}
|
|
|
|
|
2016-03-25 00:57:33 +03:00
|
|
|
#[no_mangle]
|
2016-08-24 16:16:05 +03:00
|
|
|
pub extern "C" fn Servo_StyleSheet_AddRef(sheet: RawServoStyleSheetBorrowed) -> () {
|
2016-08-17 15:35:43 +03:00
|
|
|
unsafe { Stylesheet::addref(sheet) };
|
2016-03-25 00:57:33 +03:00
|
|
|
}
|
2016-02-04 20:55:09 +03:00
|
|
|
|
|
|
|
#[no_mangle]
|
2016-08-24 16:16:05 +03:00
|
|
|
pub extern "C" fn Servo_StyleSheet_Release(sheet: RawServoStyleSheetBorrowed) -> () {
|
2016-08-17 15:35:43 +03:00
|
|
|
unsafe { Stylesheet::release(sheet) };
|
2016-03-25 00:57:33 +03:00
|
|
|
}
|
|
|
|
|
2016-11-24 02:47:18 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_CssRules_ListTypes(rules: ServoCssRulesBorrowed,
|
|
|
|
result: nsTArrayBorrowed_uintptr_t) -> () {
|
2016-11-29 14:26:46 +03:00
|
|
|
let rules = RwLock::<CssRules>::as_arc(&rules).read();
|
|
|
|
let iter = rules.0.iter().map(|rule| rule.rule_type() as usize);
|
2016-11-24 02:47:18 +03:00
|
|
|
let (size, upper) = iter.size_hint();
|
|
|
|
debug_assert_eq!(size, upper.unwrap());
|
|
|
|
unsafe { result.set_len(size as u32) };
|
|
|
|
result.iter_mut().zip(iter).fold((), |_, (r, v)| *r = v);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_CssRules_GetStyleRuleAt(rules: ServoCssRulesBorrowed, index: u32)
|
|
|
|
-> RawServoStyleRuleStrong {
|
2016-11-29 14:26:46 +03:00
|
|
|
let rules = RwLock::<CssRules>::as_arc(&rules).read();
|
|
|
|
match rules.0[index as usize] {
|
2016-11-24 02:47:18 +03:00
|
|
|
CssRule::Style(ref rule) => rule.clone().into_strong(),
|
|
|
|
_ => {
|
|
|
|
unreachable!("GetStyleRuleAt should only be called on a style rule");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-01 08:54:46 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_CssRules_InsertRule(rules: ServoCssRulesBorrowed, sheet: RawServoStyleSheetBorrowed,
|
|
|
|
rule: *const nsACString, index: u32, nested: bool,
|
|
|
|
rule_type: *mut u16) -> nsresult {
|
|
|
|
let rules = RwLock::<CssRules>::as_arc(&rules);
|
|
|
|
let sheet = Stylesheet::as_arc(&sheet);
|
|
|
|
let rule = unsafe { rule.as_ref().unwrap().as_str_unchecked() };
|
|
|
|
match rules.write().insert_rule(rule, sheet, index as usize, nested) {
|
|
|
|
Ok(new_rule) => {
|
|
|
|
*unsafe { rule_type.as_mut().unwrap() } = new_rule.rule_type() as u16;
|
|
|
|
nsresult::NS_OK
|
|
|
|
}
|
|
|
|
Err(err) => err.into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_CssRules_DeleteRule(rules: ServoCssRulesBorrowed, index: u32) -> nsresult {
|
|
|
|
let rules = RwLock::<CssRules>::as_arc(&rules);
|
|
|
|
match rules.write().remove_rule(index as usize) {
|
|
|
|
Ok(_) => nsresult::NS_OK,
|
|
|
|
Err(err) => err.into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-24 02:47:18 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_CssRules_AddRef(rules: ServoCssRulesBorrowed) -> () {
|
2016-11-29 14:26:46 +03:00
|
|
|
unsafe { RwLock::<CssRules>::addref(rules) };
|
2016-11-24 02:47:18 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_CssRules_Release(rules: ServoCssRulesBorrowed) -> () {
|
2016-11-29 14:26:46 +03:00
|
|
|
unsafe { RwLock::<CssRules>::release(rules) };
|
2016-11-24 02:47:18 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleRule_AddRef(rule: RawServoStyleRuleBorrowed) -> () {
|
|
|
|
unsafe { RwLock::<StyleRule>::addref(rule) };
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleRule_Release(rule: RawServoStyleRuleBorrowed) -> () {
|
|
|
|
unsafe { RwLock::<StyleRule>::release(rule) };
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleRule_Debug(rule: RawServoStyleRuleBorrowed, result: *mut nsACString) -> () {
|
|
|
|
let rule = RwLock::<StyleRule>::as_arc(&rule);
|
|
|
|
let result = unsafe { result.as_mut().unwrap() };
|
|
|
|
write!(result, "{:?}", *rule.read()).unwrap();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleRule_GetStyle(rule: RawServoStyleRuleBorrowed) -> RawServoDeclarationBlockStrong {
|
|
|
|
let rule = RwLock::<StyleRule>::as_arc(&rule);
|
|
|
|
rule.read().block.clone().into_strong()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleRule_SetStyle(rule: RawServoStyleRuleBorrowed,
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed) -> () {
|
|
|
|
let rule = RwLock::<StyleRule>::as_arc(&rule);
|
|
|
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
|
|
|
rule.write().block = declarations.clone();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleRule_GetCssText(rule: RawServoStyleRuleBorrowed, result: *mut nsAString) -> () {
|
|
|
|
let rule = RwLock::<StyleRule>::as_arc(&rule);
|
|
|
|
rule.read().to_css(unsafe { result.as_mut().unwrap() }).unwrap();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleRule_GetSelectorText(rule: RawServoStyleRuleBorrowed, result: *mut nsAString) -> () {
|
|
|
|
let rule = RwLock::<StyleRule>::as_arc(&rule);
|
|
|
|
rule.read().selectors.to_css(unsafe { result.as_mut().unwrap() }).unwrap();
|
|
|
|
}
|
|
|
|
|
2016-12-31 06:12:55 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_ImportRule_AddRef(rule: RawServoImportRuleBorrowed) -> () {
|
|
|
|
unsafe { RwLock::<ImportRule>::addref(rule) };
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_ImportRule_Release(rule: RawServoImportRuleBorrowed) -> () {
|
|
|
|
unsafe { RwLock::<ImportRule>::release(rule) };
|
|
|
|
}
|
|
|
|
|
2016-03-25 00:57:33 +03:00
|
|
|
#[no_mangle]
|
2016-09-03 06:42:21 +03:00
|
|
|
pub extern "C" fn Servo_ComputedValues_GetForAnonymousBox(parent_style_or_null: ServoComputedValuesBorrowedOrNull,
|
2016-04-30 00:27:16 +03:00
|
|
|
pseudo_tag: *mut nsIAtom,
|
2016-10-11 20:03:29 +03:00
|
|
|
raw_data: RawServoStyleSetBorrowed)
|
2016-08-17 15:35:43 +03:00
|
|
|
-> ServoComputedValuesStrong {
|
2016-12-26 05:13:30 +03:00
|
|
|
let data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
2016-08-16 20:50:29 +03:00
|
|
|
let atom = Atom::from(pseudo_tag);
|
|
|
|
let pseudo = PseudoElement::from_atom_unchecked(atom, /* anon_box = */ true);
|
2016-04-30 00:27:16 +03:00
|
|
|
|
|
|
|
|
2016-10-05 08:59:56 +03:00
|
|
|
let maybe_parent = ComputedValues::arc_from_borrowed(&parent_style_or_null);
|
2016-11-06 01:11:24 +03:00
|
|
|
let new_computed = data.stylist.precomputed_values_for_pseudo(&pseudo, maybe_parent, false)
|
2016-11-25 20:00:44 +03:00
|
|
|
.map(|styles| styles.values);
|
2016-09-03 06:42:21 +03:00
|
|
|
new_computed.map_or(Strong::null(), |c| c.into_strong())
|
2016-03-25 00:57:33 +03:00
|
|
|
}
|
|
|
|
|
2016-05-04 13:42:23 +03:00
|
|
|
#[no_mangle]
|
2016-12-26 05:13:30 +03:00
|
|
|
pub extern "C" fn Servo_ResolvePseudoStyle(element: RawGeckoElementBorrowed,
|
|
|
|
pseudo_tag: *mut nsIAtom, is_probe: bool,
|
|
|
|
raw_data: RawServoStyleSetBorrowed)
|
|
|
|
-> ServoComputedValuesStrong
|
|
|
|
{
|
|
|
|
let element = GeckoElement(element);
|
|
|
|
let data = unsafe { element.ensure_data() }.borrow_mut();
|
2016-05-04 13:42:23 +03:00
|
|
|
|
2016-12-26 05:13:30 +03:00
|
|
|
// FIXME(bholley): Assert against this.
|
|
|
|
if data.get_styles().is_none() {
|
|
|
|
error!("Calling Servo_ResolvePseudoStyle on unstyled element");
|
|
|
|
return if is_probe {
|
2016-09-03 06:42:21 +03:00
|
|
|
Strong::null()
|
2016-05-04 13:42:23 +03:00
|
|
|
} else {
|
2016-12-26 05:13:30 +03:00
|
|
|
Arc::new(ComputedValues::initial_values().clone()).into_strong()
|
|
|
|
};
|
|
|
|
}
|
2016-05-04 13:42:23 +03:00
|
|
|
|
2016-12-26 05:13:30 +03:00
|
|
|
let doc_data = PerDocumentStyleData::from_ffi(raw_data);
|
|
|
|
match get_pseudo_style(element, pseudo_tag, data.styles(), doc_data) {
|
|
|
|
Some(values) => values.into_strong(),
|
|
|
|
None if !is_probe => data.styles().primary.values.clone().into_strong(),
|
|
|
|
None => Strong::null(),
|
|
|
|
}
|
|
|
|
}
|
2016-05-04 13:42:23 +03:00
|
|
|
|
2016-12-26 05:13:30 +03:00
|
|
|
fn get_pseudo_style(element: GeckoElement, pseudo_tag: *mut nsIAtom,
|
|
|
|
styles: &ElementStyles, doc_data: &PerDocumentStyleData)
|
|
|
|
-> Option<Arc<ComputedValues>>
|
|
|
|
{
|
|
|
|
let pseudo = PseudoElement::from_atom_unchecked(Atom::from(pseudo_tag), false);
|
2016-11-22 19:44:03 +03:00
|
|
|
match SelectorImpl::pseudo_element_cascade_type(&pseudo) {
|
2016-12-26 05:13:30 +03:00
|
|
|
PseudoElementCascadeType::Eager => styles.pseudos.get(&pseudo).map(|s| s.values.clone()),
|
|
|
|
PseudoElementCascadeType::Precomputed => unreachable!("No anonymous boxes"),
|
2016-05-04 13:42:23 +03:00
|
|
|
PseudoElementCascadeType::Lazy => {
|
2016-12-26 05:13:30 +03:00
|
|
|
let d = doc_data.borrow_mut();
|
|
|
|
let base = &styles.primary.values;
|
|
|
|
d.stylist.lazily_compute_pseudo_element_style(&element, &pseudo, base)
|
|
|
|
.map(|s| s.values.clone())
|
|
|
|
},
|
2016-05-04 13:42:23 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-06 14:30:47 +03:00
|
|
|
#[no_mangle]
|
2016-09-03 06:42:21 +03:00
|
|
|
pub extern "C" fn Servo_ComputedValues_Inherit(parent_style: ServoComputedValuesBorrowedOrNull)
|
2016-08-17 15:35:43 +03:00
|
|
|
-> ServoComputedValuesStrong {
|
2016-10-05 08:59:56 +03:00
|
|
|
let maybe_arc = ComputedValues::arc_from_borrowed(&parent_style);
|
|
|
|
let style = if let Some(reference) = maybe_arc.as_ref() {
|
|
|
|
ComputedValues::inherit_from(reference)
|
2016-08-04 04:20:21 +03:00
|
|
|
} else {
|
2016-10-05 08:59:56 +03:00
|
|
|
Arc::new(ComputedValues::initial_values().clone())
|
2016-08-04 04:20:21 +03:00
|
|
|
};
|
2016-09-03 06:42:21 +03:00
|
|
|
style.into_strong()
|
2016-05-06 14:30:47 +03:00
|
|
|
}
|
|
|
|
|
2016-03-25 00:57:33 +03:00
|
|
|
#[no_mangle]
|
2016-08-24 16:16:05 +03:00
|
|
|
pub extern "C" fn Servo_ComputedValues_AddRef(ptr: ServoComputedValuesBorrowed) -> () {
|
2016-08-17 15:35:43 +03:00
|
|
|
unsafe { ComputedValues::addref(ptr) };
|
2016-03-25 00:57:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2016-08-24 16:16:05 +03:00
|
|
|
pub extern "C" fn Servo_ComputedValues_Release(ptr: ServoComputedValuesBorrowed) -> () {
|
2016-08-17 15:35:43 +03:00
|
|
|
unsafe { ComputedValues::release(ptr) };
|
2016-02-04 20:55:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2016-09-03 06:42:21 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_Init() -> RawServoStyleSetOwned {
|
2016-02-04 20:55:09 +03:00
|
|
|
let data = Box::new(PerDocumentStyleData::new());
|
2016-09-03 06:42:21 +03:00
|
|
|
data.into_ffi()
|
2016-02-04 20:55:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2016-09-03 06:42:21 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_Drop(data: RawServoStyleSetOwned) -> () {
|
|
|
|
let _ = data.into_box::<PerDocumentStyleData>();
|
2016-02-04 20:55:09 +03:00
|
|
|
}
|
2016-06-24 05:46:25 +03:00
|
|
|
|
2016-10-09 16:53:28 +03:00
|
|
|
|
|
|
|
#[no_mangle]
|
2016-10-25 12:09:19 +03:00
|
|
|
pub extern "C" fn Servo_ParseProperty(property: *const nsACString, value: *const nsACString,
|
|
|
|
base_url: *const nsACString, base: *mut ThreadSafeURIHolder,
|
2016-10-09 16:53:28 +03:00
|
|
|
referrer: *mut ThreadSafeURIHolder,
|
|
|
|
principal: *mut ThreadSafePrincipalHolder)
|
2016-10-18 08:51:14 +03:00
|
|
|
-> RawServoDeclarationBlockStrong {
|
2016-10-25 12:09:19 +03:00
|
|
|
let name = unsafe { property.as_ref().unwrap().as_str_unchecked() };
|
2016-12-10 12:16:26 +03:00
|
|
|
let id = if let Ok(id) = PropertyId::parse(name.into()) {
|
|
|
|
id
|
|
|
|
} else {
|
|
|
|
return RawServoDeclarationBlockStrong::null()
|
|
|
|
};
|
2016-10-25 12:09:19 +03:00
|
|
|
let value = unsafe { value.as_ref().unwrap().as_str_unchecked() };
|
|
|
|
let base_str = unsafe { base_url.as_ref().unwrap().as_str_unchecked() };
|
2016-11-18 00:34:47 +03:00
|
|
|
let base_url = ServoUrl::parse(base_str).unwrap();
|
2016-10-14 06:31:20 +03:00
|
|
|
let extra_data = unsafe { ParserContextExtraData {
|
2016-10-09 16:53:28 +03:00
|
|
|
base: Some(GeckoArcURI::new(base)),
|
|
|
|
referrer: Some(GeckoArcURI::new(referrer)),
|
|
|
|
principal: Some(GeckoArcPrincipal::new(principal)),
|
2016-10-14 06:31:20 +03:00
|
|
|
}};
|
2016-10-09 16:53:28 +03:00
|
|
|
|
|
|
|
let context = ParserContext::new_with_extra_data(Origin::Author, &base_url,
|
|
|
|
Box::new(StdoutErrorReporter),
|
|
|
|
extra_data);
|
|
|
|
|
|
|
|
let mut results = vec![];
|
2016-12-10 12:16:26 +03:00
|
|
|
match PropertyDeclaration::parse(id, &context, &mut Parser::new(value),
|
2016-10-09 16:53:28 +03:00
|
|
|
&mut results, false) {
|
|
|
|
PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => {},
|
2016-10-18 08:51:14 +03:00
|
|
|
_ => return RawServoDeclarationBlockStrong::null(),
|
2016-10-09 16:53:28 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
let results = results.into_iter().map(|r| (r, Importance::Normal)).collect();
|
|
|
|
|
2016-10-18 08:51:14 +03:00
|
|
|
Arc::new(RwLock::new(PropertyDeclarationBlock {
|
|
|
|
declarations: results,
|
|
|
|
important_count: 0,
|
|
|
|
})).into_strong()
|
2016-10-09 16:53:28 +03:00
|
|
|
}
|
2016-10-18 08:51:14 +03:00
|
|
|
|
2016-06-24 05:46:25 +03:00
|
|
|
#[no_mangle]
|
2016-10-25 12:09:19 +03:00
|
|
|
pub extern "C" fn Servo_ParseStyleAttribute(data: *const nsACString) -> RawServoDeclarationBlockStrong {
|
|
|
|
let value = unsafe { data.as_ref().unwrap().as_str_unchecked() };
|
2016-10-18 08:51:14 +03:00
|
|
|
Arc::new(RwLock::new(GeckoElement::parse_style_attribute(value))).into_strong()
|
2016-06-24 05:46:25 +03:00
|
|
|
}
|
|
|
|
|
2016-11-04 07:42:06 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_CreateEmpty() -> RawServoDeclarationBlockStrong {
|
|
|
|
Arc::new(RwLock::new(PropertyDeclarationBlock { declarations: vec![], important_count: 0 })).into_strong()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_Clone(declarations: RawServoDeclarationBlockBorrowed)
|
|
|
|
-> RawServoDeclarationBlockStrong {
|
|
|
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
|
|
|
Arc::new(RwLock::new(declarations.read().clone())).into_strong()
|
|
|
|
}
|
|
|
|
|
2016-06-24 05:46:25 +03:00
|
|
|
#[no_mangle]
|
2016-10-18 08:51:14 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_AddRef(declarations: RawServoDeclarationBlockBorrowed) {
|
|
|
|
unsafe { RwLock::<PropertyDeclarationBlock>::addref(declarations) };
|
2016-06-24 05:46:25 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2016-10-18 08:51:14 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_Release(declarations: RawServoDeclarationBlockBorrowed) {
|
|
|
|
unsafe { RwLock::<PropertyDeclarationBlock>::release(declarations) };
|
2016-08-23 05:12:23 +03:00
|
|
|
}
|
|
|
|
|
2016-10-09 16:53:28 +03:00
|
|
|
#[no_mangle]
|
2016-10-18 08:51:14 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_Equals(a: RawServoDeclarationBlockBorrowed,
|
|
|
|
b: RawServoDeclarationBlockBorrowed)
|
2016-10-09 16:53:28 +03:00
|
|
|
-> bool {
|
2016-10-18 08:51:14 +03:00
|
|
|
*RwLock::<PropertyDeclarationBlock>::as_arc(&a).read() == *RwLock::<PropertyDeclarationBlock>::as_arc(&b).read()
|
2016-06-24 05:46:25 +03:00
|
|
|
}
|
2016-07-19 07:25:31 +03:00
|
|
|
|
2016-11-04 07:42:06 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_GetCssText(declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
result: *mut nsAString) {
|
|
|
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
|
|
|
declarations.read().to_css(unsafe { result.as_mut().unwrap() }).unwrap();
|
|
|
|
}
|
|
|
|
|
2016-12-18 05:22:10 +03:00
|
|
|
macro_rules! get_property_id_from_nscsspropertyid {
|
|
|
|
($property_id: ident, $ret: expr) => {{
|
|
|
|
match PropertyId::from_nscsspropertyid($property_id) {
|
|
|
|
Ok(property_id) => property_id,
|
|
|
|
Err(()) => { return $ret; }
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
}
|
|
|
|
|
2016-10-09 16:53:28 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_SerializeOneValue(
|
2016-10-18 08:51:14 +03:00
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
2016-12-18 05:22:10 +03:00
|
|
|
property_id: nsCSSPropertyID, buffer: *mut nsAString)
|
2016-10-09 16:53:28 +03:00
|
|
|
{
|
2016-12-18 05:22:10 +03:00
|
|
|
let property_id = get_property_id_from_nscsspropertyid!(property_id, ());
|
2016-10-18 08:51:14 +03:00
|
|
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
2016-11-25 13:39:52 +03:00
|
|
|
let mut string = String::new();
|
2016-12-18 05:22:10 +03:00
|
|
|
let rv = declarations.read().single_value_to_css(&property_id, &mut string);
|
2016-11-25 13:39:52 +03:00
|
|
|
debug_assert!(rv.is_ok());
|
2016-10-18 08:51:14 +03:00
|
|
|
|
2016-12-01 07:12:28 +03:00
|
|
|
write!(unsafe { &mut *buffer }, "{}", string).expect("Failed to copy string");
|
2016-10-09 16:53:28 +03:00
|
|
|
}
|
|
|
|
|
2016-11-04 07:42:06 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_Count(declarations: RawServoDeclarationBlockBorrowed) -> u32 {
|
|
|
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
|
|
|
declarations.read().declarations.len() as u32
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_GetNthProperty(declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
index: u32, result: *mut nsAString) -> bool {
|
|
|
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
|
|
|
if let Some(&(ref decl, _)) = declarations.read().declarations.get(index as usize) {
|
|
|
|
let result = unsafe { result.as_mut().unwrap() };
|
2016-12-10 12:16:26 +03:00
|
|
|
decl.id().to_css(result).unwrap();
|
2016-11-04 07:42:06 +03:00
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-18 05:22:10 +03:00
|
|
|
macro_rules! get_property_id_from_property {
|
|
|
|
($property: ident, $ret: expr) => {{
|
|
|
|
let property = unsafe { $property.as_ref().unwrap().as_str_unchecked() };
|
|
|
|
match PropertyId::parse(Cow::Borrowed(property)) {
|
|
|
|
Ok(property_id) => property_id,
|
|
|
|
Err(()) => { return $ret; }
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_property_value(declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property_id: PropertyId, value: *mut nsAString) {
|
|
|
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
|
|
|
declarations.read().property_value_to_css(&property_id, unsafe { value.as_mut().unwrap() }).unwrap();
|
2016-11-04 07:42:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_GetPropertyValue(declarations: RawServoDeclarationBlockBorrowed,
|
2016-12-18 05:22:10 +03:00
|
|
|
property: *const nsACString, value: *mut nsAString) {
|
|
|
|
get_property_value(declarations, get_property_id_from_property!(property, ()), value)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_GetPropertyValueById(declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: nsCSSPropertyID, value: *mut nsAString) {
|
|
|
|
get_property_value(declarations, get_property_id_from_nscsspropertyid!(property, ()), value)
|
2016-11-04 07:42:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_GetPropertyIsImportant(declarations: RawServoDeclarationBlockBorrowed,
|
2016-12-18 05:22:10 +03:00
|
|
|
property: *const nsACString) -> bool {
|
|
|
|
let property_id = get_property_id_from_property!(property, false);
|
2016-11-04 07:42:06 +03:00
|
|
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
2016-12-18 05:22:10 +03:00
|
|
|
declarations.read().property_priority(&property_id).important()
|
2016-11-04 07:42:06 +03:00
|
|
|
}
|
|
|
|
|
2016-12-18 05:22:10 +03:00
|
|
|
fn set_property(declarations: RawServoDeclarationBlockBorrowed, property_id: PropertyId,
|
|
|
|
value: *mut nsACString, is_important: bool) -> bool {
|
2016-11-04 07:42:06 +03:00
|
|
|
let value = unsafe { value.as_ref().unwrap().as_str_unchecked() };
|
|
|
|
// FIXME Needs real URL and ParserContextExtraData.
|
|
|
|
let base_url = &*DUMMY_BASE_URL;
|
|
|
|
let extra_data = ParserContextExtraData::default();
|
2016-12-18 05:22:10 +03:00
|
|
|
if let Ok(decls) = parse_one_declaration(property_id, value, &base_url,
|
2016-11-04 07:42:06 +03:00
|
|
|
Box::new(StdoutErrorReporter), extra_data) {
|
|
|
|
let mut declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations).write();
|
|
|
|
let importance = if is_important { Importance::Important } else { Importance::Normal };
|
|
|
|
for decl in decls.into_iter() {
|
|
|
|
declarations.set_parsed_declaration(decl, importance);
|
|
|
|
}
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2016-12-18 05:22:10 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_SetProperty(declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: *const nsACString, value: *mut nsACString,
|
|
|
|
is_important: bool) -> bool {
|
|
|
|
set_property(declarations, get_property_id_from_property!(property, false), value, is_important)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_SetPropertyById(declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: nsCSSPropertyID, value: *mut nsACString,
|
|
|
|
is_important: bool) -> bool {
|
|
|
|
set_property(declarations, get_property_id_from_nscsspropertyid!(property, false), value, is_important)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn remove_property(declarations: RawServoDeclarationBlockBorrowed, property_id: PropertyId) {
|
2016-11-04 07:42:06 +03:00
|
|
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
2016-12-18 05:22:10 +03:00
|
|
|
declarations.write().remove_property(&property_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_RemoveProperty(declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: *const nsACString) {
|
|
|
|
remove_property(declarations, get_property_id_from_property!(property, ()))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_RemovePropertyById(declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: nsCSSPropertyID) {
|
|
|
|
remove_property(declarations, get_property_id_from_nscsspropertyid!(property, ()))
|
2016-11-04 07:42:06 +03:00
|
|
|
}
|
|
|
|
|
2016-07-19 07:25:31 +03:00
|
|
|
#[no_mangle]
|
2016-10-25 12:09:19 +03:00
|
|
|
pub extern "C" fn Servo_CSSSupports(property: *const nsACString, value: *const nsACString) -> bool {
|
|
|
|
let property = unsafe { property.as_ref().unwrap().as_str_unchecked() };
|
2016-12-10 12:16:26 +03:00
|
|
|
let id = if let Ok(id) = PropertyId::parse(property.into()) {
|
|
|
|
id
|
|
|
|
} else {
|
|
|
|
return false
|
|
|
|
};
|
2016-10-25 12:09:19 +03:00
|
|
|
let value = unsafe { value.as_ref().unwrap().as_str_unchecked() };
|
2016-07-19 07:25:31 +03:00
|
|
|
|
|
|
|
let base_url = &*DUMMY_BASE_URL;
|
|
|
|
let extra_data = ParserContextExtraData::default();
|
|
|
|
|
2016-12-10 12:16:26 +03:00
|
|
|
match parse_one_declaration(id, &value, &base_url, Box::new(StdoutErrorReporter), extra_data) {
|
2016-07-19 07:25:31 +03:00
|
|
|
Ok(decls) => !decls.is_empty(),
|
|
|
|
Err(()) => false,
|
|
|
|
}
|
|
|
|
}
|
2016-07-22 00:54:34 +03:00
|
|
|
|
2016-11-25 20:00:44 +03:00
|
|
|
/// Only safe to call on the main thread, with exclusive access to the element and
|
|
|
|
/// its ancestors.
|
|
|
|
unsafe fn maybe_restyle<'a>(data: &'a mut AtomicRefMut<ElementData>, element: GeckoElement)
|
|
|
|
-> Option<&'a mut RestyleData>
|
|
|
|
{
|
|
|
|
let r = data.restyle();
|
|
|
|
if r.is_some() {
|
|
|
|
// Propagate the bit up the chain.
|
|
|
|
let mut curr = element;
|
|
|
|
while let Some(parent) = curr.parent_element() {
|
|
|
|
curr = parent;
|
|
|
|
if curr.has_dirty_descendants() { break; }
|
|
|
|
curr.set_dirty_descendants();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r
|
|
|
|
}
|
|
|
|
|
2016-07-22 00:54:34 +03:00
|
|
|
#[no_mangle]
|
2016-11-25 20:00:44 +03:00
|
|
|
pub extern "C" fn Servo_Element_GetSnapshot(element: RawGeckoElementBorrowed) -> *mut structs::ServoElementSnapshot
|
|
|
|
{
|
2016-09-09 10:00:13 +03:00
|
|
|
let element = GeckoElement(element);
|
2016-11-25 20:00:44 +03:00
|
|
|
let mut data = unsafe { element.ensure_data().borrow_mut() };
|
|
|
|
let snapshot = if let Some(restyle_data) = unsafe { maybe_restyle(&mut data, element) } {
|
2016-12-10 04:01:05 +03:00
|
|
|
restyle_data.snapshot.ensure(|| element.create_snapshot()).borrow_mut_raw()
|
2016-11-25 20:00:44 +03:00
|
|
|
} else {
|
|
|
|
ptr::null_mut()
|
|
|
|
};
|
|
|
|
|
|
|
|
debug!("Servo_Element_GetSnapshot: {:?}: {:?}", element, snapshot);
|
|
|
|
snapshot
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_NoteExplicitHints(element: RawGeckoElementBorrowed,
|
|
|
|
restyle_hint: nsRestyleHint,
|
|
|
|
change_hint: nsChangeHint) {
|
|
|
|
let element = GeckoElement(element);
|
|
|
|
let damage = GeckoRestyleDamage::new(change_hint);
|
|
|
|
let mut data = unsafe { element.ensure_data().borrow_mut() };
|
|
|
|
debug!("Servo_NoteExplicitHints: {:?}, restyle_hint={:?}, change_hint={:?}",
|
|
|
|
element, restyle_hint, change_hint);
|
|
|
|
|
|
|
|
if let Some(restyle_data) = unsafe { maybe_restyle(&mut data, element) } {
|
|
|
|
let restyle_hint: RestyleHint = restyle_hint.into();
|
|
|
|
restyle_data.hint.insert(&restyle_hint.into());
|
|
|
|
restyle_data.damage |= damage;
|
|
|
|
} else {
|
|
|
|
debug!("(Element not styled, discarding hints)");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-31 06:12:55 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_ImportRule_GetSheet(import_rule:
|
|
|
|
RawServoImportRuleBorrowed)
|
|
|
|
-> RawServoStyleSheetStrong {
|
|
|
|
let import_rule = RwLock::<ImportRule>::as_arc(&import_rule);
|
|
|
|
unsafe { transmute(import_rule.read().stylesheet.clone()) }
|
|
|
|
}
|
|
|
|
|
2016-11-25 20:00:44 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_CheckChangeHint(element: RawGeckoElementBorrowed) -> nsChangeHint
|
|
|
|
{
|
|
|
|
let element = GeckoElement(element);
|
|
|
|
if element.get_data().is_none() {
|
|
|
|
error!("Trying to get change hint from unstyled element");
|
|
|
|
return nsChangeHint(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut data = element.get_data().unwrap().borrow_mut();
|
|
|
|
let damage = data.damage_sloppy();
|
|
|
|
|
|
|
|
// If there's no change hint, the caller won't consume the new style. Do that
|
|
|
|
// ourselves.
|
|
|
|
//
|
|
|
|
// FIXME(bholley): Once we start storing style data on frames, we'll want to
|
|
|
|
// drop the data here instead.
|
|
|
|
if damage.is_empty() {
|
|
|
|
data.persist();
|
|
|
|
}
|
|
|
|
|
|
|
|
debug!("Servo_GetChangeHint: {:?}, damage={:?}", element, damage);
|
|
|
|
damage.as_change_hint()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_ResolveStyle(element: RawGeckoElementBorrowed,
|
2016-12-28 06:55:01 +03:00
|
|
|
consume: structs::ConsumeStyleBehavior)
|
|
|
|
-> ServoComputedValuesStrong
|
2016-11-25 20:00:44 +03:00
|
|
|
{
|
|
|
|
let element = GeckoElement(element);
|
2016-12-28 06:55:01 +03:00
|
|
|
debug!("Servo_ResolveStyle: {:?}, consume={:?}", element, consume);
|
2016-11-25 20:00:44 +03:00
|
|
|
|
2016-12-10 04:01:05 +03:00
|
|
|
let mut data = unsafe { element.ensure_data() }.borrow_mut();
|
|
|
|
|
|
|
|
if !data.has_current_styles() {
|
|
|
|
error!("Resolving style on unstyled element with lazy computation forbidden.");
|
|
|
|
return Arc::new(ComputedValues::initial_values().clone()).into_strong();
|
|
|
|
}
|
|
|
|
|
|
|
|
let values = data.styles().primary.values.clone();
|
2016-07-22 00:54:34 +03:00
|
|
|
|
2016-12-05 14:52:16 +03:00
|
|
|
if consume == structs::ConsumeStyleBehavior::Consume {
|
2016-11-25 20:00:44 +03:00
|
|
|
// FIXME(bholley): Once we start storing style data on frames, we'll want to
|
|
|
|
// drop the data here instead.
|
2016-12-10 04:01:05 +03:00
|
|
|
data.persist();
|
2016-11-25 20:00:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
values.into_strong()
|
|
|
|
}
|
2016-07-22 00:54:34 +03:00
|
|
|
|
2016-12-28 06:55:01 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_ResolveStyleLazily(element: RawGeckoElementBorrowed,
|
|
|
|
pseudo_tag: *mut nsIAtom,
|
|
|
|
consume: structs::ConsumeStyleBehavior,
|
|
|
|
raw_data: RawServoStyleSetBorrowed)
|
|
|
|
-> ServoComputedValuesStrong
|
|
|
|
{
|
|
|
|
let element = GeckoElement(element);
|
|
|
|
let doc_data = PerDocumentStyleData::from_ffi(raw_data);
|
|
|
|
let finish = |styles: &ElementStyles| -> Arc<ComputedValues> {
|
|
|
|
let maybe_pseudo = if !pseudo_tag.is_null() {
|
|
|
|
get_pseudo_style(element, pseudo_tag, styles, doc_data)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
maybe_pseudo.unwrap_or_else(|| styles.primary.values.clone())
|
|
|
|
};
|
|
|
|
|
|
|
|
// In the common case we already have the style. Check that before setting
|
|
|
|
// up all the computation machinery.
|
|
|
|
let mut result = element.mutate_data()
|
|
|
|
.and_then(|d| d.get_styles().map(&finish));
|
|
|
|
if result.is_some() {
|
|
|
|
if consume == structs::ConsumeStyleBehavior::Consume {
|
|
|
|
let mut d = element.mutate_data().unwrap();
|
|
|
|
if !d.is_persistent() {
|
|
|
|
// XXXheycam is it right to persist an ElementData::Restyle?
|
|
|
|
// Couldn't we lose restyle hints that would cause us to
|
|
|
|
// restyle descendants?
|
|
|
|
d.persist();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result.unwrap().into_strong();
|
|
|
|
}
|
|
|
|
|
|
|
|
// We don't have the style ready. Go ahead and compute it as necessary.
|
|
|
|
let shared = create_shared_context(&mut doc_data.borrow_mut());
|
|
|
|
let mut tlc = ThreadLocalStyleContext::new(&shared);
|
|
|
|
let mut context = StyleContext {
|
|
|
|
shared: &shared,
|
|
|
|
thread_local: &mut tlc,
|
|
|
|
};
|
|
|
|
let ensure = |el: GeckoElement| { unsafe { el.ensure_data(); } };
|
|
|
|
let clear = |el: GeckoElement| el.clear_data();
|
|
|
|
resolve_style(&mut context, element, &ensure, &clear,
|
|
|
|
|styles| result = Some(finish(styles)));
|
|
|
|
|
|
|
|
// Consume the style if requested, though it may not exist anymore if the
|
|
|
|
// element is in a display:none subtree.
|
|
|
|
if consume == structs::ConsumeStyleBehavior::Consume {
|
|
|
|
element.mutate_data().map(|mut d| d.persist());
|
|
|
|
}
|
|
|
|
|
|
|
|
result.unwrap().into_strong()
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-11-25 20:00:44 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_AssertTreeIsClean(root: RawGeckoElementBorrowed) {
|
|
|
|
if !cfg!(debug_assertions) {
|
|
|
|
panic!("Calling Servo_AssertTreeIsClean in release build");
|
|
|
|
}
|
|
|
|
|
|
|
|
let root = GeckoElement(root);
|
|
|
|
fn assert_subtree_is_clean<'le>(el: GeckoElement<'le>) {
|
|
|
|
debug_assert!(!el.has_dirty_descendants());
|
|
|
|
for child in el.as_node().children() {
|
|
|
|
if let Some(child) = child.as_element() {
|
|
|
|
assert_subtree_is_clean(child);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-07-22 00:54:34 +03:00
|
|
|
|
2016-11-25 20:00:44 +03:00
|
|
|
assert_subtree_is_clean(root);
|
2016-07-22 00:54:34 +03:00
|
|
|
}
|