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/. */
|
|
|
|
|
2017-06-10 00:31:48 +03:00
|
|
|
use cssparser::{Parser, ParserInput};
|
2016-11-24 02:47:18 +03:00
|
|
|
use cssparser::ToCss as ParserToCss;
|
2017-02-15 14:05:07 +03:00
|
|
|
use env_logger::LogBuilder;
|
servo: Merge #18452 - Overhaul MallocSizeOf and related things (from nnethercote:bug-1398737); r=jdm
This patch makes the MallocSizeOf stuff in Stylo work more like the HeapSizeOf
stuff already in Servo, except better. In particular, it adds deriving support
for MallocSizeOf, which will make it easier to improve coverage.
The patch does the following.
- Combines servo/components/style/stylesheets/memory.rs and the heapsize crate
into a new crate, malloc_size_of.
- Forks the heapsize_derive crate, calling it malloc_size_of, so that
MallocSizeOf can be derived.
- Both the new crates have MIT/Apache licenses, like heapsize, in case they are
incorporated into heapsize in the future.
- Renames the methods within MallocSizeOf and the related traits so they are
more concise.
- Removes MallocSizeOfWithGuard.
- Adds `derive(MallocSizeOf)` to a lot of types, in some cases replacing an
equivalent or almost-equivalent hand-written implementation.
- Adds stuff so that Rc/Arc can be handled properly.
<!-- Please describe your changes on the following line: -->
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [X] These changes do not require tests because tested on Gecko side.
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- 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: 7f4cb1861b172423781a369b2decca6c65d60546
--HG--
rename : servo/components/hashglobe/LICENSE-APACHE => servo/components/malloc_size_of/LICENSE-APACHE
rename : servo/components/hashglobe/LICENSE-MIT => servo/components/malloc_size_of/LICENSE-MIT
rename : servo/components/jstraceable_derive/Cargo.toml => servo/components/malloc_size_of_derive/Cargo.toml
rename : servo/components/hashglobe/LICENSE-APACHE => servo/components/malloc_size_of_derive/LICENSE-APACHE
rename : servo/components/hashglobe/LICENSE-MIT => servo/components/malloc_size_of_derive/LICENSE-MIT
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : a8254c4ae15901b764d918355e900a1e74d6eb03
2017-09-12 06:11:25 +03:00
|
|
|
use malloc_size_of::MallocSizeOfOps;
|
2017-10-13 18:48:57 +03:00
|
|
|
use selectors::Element;
|
2017-07-04 15:08:03 +03:00
|
|
|
use selectors::matching::{MatchingContext, MatchingMode, matches_selector};
|
2017-07-21 21:05:13 +03:00
|
|
|
use servo_arc::{Arc, ArcBorrow, RawOffsetArc};
|
2017-09-14 12:28:50 +03:00
|
|
|
use std::cell::RefCell;
|
2017-02-15 14:05:07 +03:00
|
|
|
use std::env;
|
2016-11-04 07:42:06 +03:00
|
|
|
use std::fmt::Write;
|
2017-08-11 08:40:18 +03:00
|
|
|
use std::iter;
|
2017-09-15 22:43:30 +03:00
|
|
|
use std::mem;
|
2016-11-25 20:00:44 +03:00
|
|
|
use std::ptr;
|
2017-09-07 00:40:33 +03:00
|
|
|
use style::applicable_declarations::ApplicableDeclarationBlock;
|
2017-06-30 19:11:41 +03:00
|
|
|
use style::context::{CascadeInputs, QuirksMode, SharedStyleContext, StyleContext};
|
2017-05-12 16:56:47 +03:00
|
|
|
use style::context::ThreadLocalStyleContext;
|
2017-09-20 10:05:57 +03:00
|
|
|
use style::data::{ElementStyles, self};
|
2017-10-26 15:51:21 +03:00
|
|
|
use style::dom::{ShowSubtreeData, TDocument, TElement, TNode};
|
2017-08-25 20:23:41 +03:00
|
|
|
use style::driver;
|
2017-10-20 10:56:47 +03:00
|
|
|
use style::element_state::{DocumentState, ElementState};
|
2017-07-11 04:13:44 +03:00
|
|
|
use style::error_reporting::{NullReporter, ParseErrorReporter};
|
2017-06-02 06:56:48 +03:00
|
|
|
use style::font_metrics::{FontMetricsProvider, get_metrics_provider_for_product};
|
2017-07-02 17:00:39 +03:00
|
|
|
use style::gecko::data::{GeckoStyleSheet, PerDocumentStyleData, PerDocumentStyleDataImpl};
|
2017-06-23 20:37:43 +03:00
|
|
|
use style::gecko::global_style_data::{GLOBAL_STYLE_DATA, GlobalStyleData, STYLE_THREAD_POOL};
|
2016-11-25 20:00:44 +03:00
|
|
|
use style::gecko::restyle_damage::GeckoRestyleDamage;
|
2017-04-27 15:39:42 +03:00
|
|
|
use style::gecko::selector_parser::PseudoElement;
|
2016-09-26 10:36:05 +03:00
|
|
|
use style::gecko::traversal::RecalcStyleOnly;
|
2017-10-23 16:14:35 +03:00
|
|
|
use style::gecko::wrapper::{GeckoElement, GeckoNode};
|
2017-08-23 06:04:34 +03:00
|
|
|
use style::gecko_bindings::bindings;
|
2017-10-23 16:14:35 +03:00
|
|
|
use style::gecko_bindings::bindings::{RawGeckoElementBorrowed, RawGeckoElementBorrowedOrNull, RawGeckoNodeBorrowed};
|
2017-02-24 15:09:33 +03:00
|
|
|
use style::gecko_bindings::bindings::{RawGeckoKeyframeListBorrowed, RawGeckoKeyframeListBorrowedMut};
|
2016-10-18 08:51:14 +03:00
|
|
|
use style::gecko_bindings::bindings::{RawServoDeclarationBlockBorrowed, RawServoDeclarationBlockStrong};
|
2017-05-11 14:27:42 +03:00
|
|
|
use style::gecko_bindings::bindings::{RawServoDocumentRule, RawServoDocumentRuleBorrowed};
|
2017-07-28 00:15:02 +03:00
|
|
|
use style::gecko_bindings::bindings::{RawServoFontFeatureValuesRule, RawServoFontFeatureValuesRuleBorrowed};
|
2017-05-30 02:51:45 +03:00
|
|
|
use style::gecko_bindings::bindings::{RawServoImportRule, RawServoImportRuleBorrowed};
|
2017-05-19 07:49:30 +03:00
|
|
|
use style::gecko_bindings::bindings::{RawServoKeyframe, RawServoKeyframeBorrowed, RawServoKeyframeStrong};
|
|
|
|
use style::gecko_bindings::bindings::{RawServoKeyframesRule, RawServoKeyframesRuleBorrowed};
|
2017-07-02 17:00:39 +03:00
|
|
|
use style::gecko_bindings::bindings::{RawServoMediaListBorrowed, RawServoMediaListStrong};
|
2017-03-15 13:58:06 +03:00
|
|
|
use style::gecko_bindings::bindings::{RawServoMediaRule, RawServoMediaRuleBorrowed};
|
|
|
|
use style::gecko_bindings::bindings::{RawServoNamespaceRule, RawServoNamespaceRuleBorrowed};
|
2017-04-10 05:47:59 +03:00
|
|
|
use style::gecko_bindings::bindings::{RawServoPageRule, RawServoPageRuleBorrowed};
|
2017-10-10 09:20:38 +03:00
|
|
|
use style::gecko_bindings::bindings::{RawServoSelectorListBorrowed, RawServoSelectorListOwned};
|
2017-11-13 06:01:34 +03:00
|
|
|
use style::gecko_bindings::bindings::{RawServoSourceSizeListBorrowedOrNull, RawServoSourceSizeListOwned};
|
2017-10-16 12:49:33 +03:00
|
|
|
use style::gecko_bindings::bindings::{RawServoStyleSetBorrowed, RawServoStyleSetBorrowedOrNull, RawServoStyleSetOwned};
|
2017-07-21 21:05:13 +03:00
|
|
|
use style::gecko_bindings::bindings::{RawServoStyleSheetContentsBorrowed, ServoComputedDataBorrowed};
|
2017-07-18 05:44:25 +03:00
|
|
|
use style::gecko_bindings::bindings::{RawServoStyleSheetContentsStrong, ServoStyleContextBorrowed};
|
2017-04-28 13:11:04 +03:00
|
|
|
use style::gecko_bindings::bindings::{RawServoSupportsRule, RawServoSupportsRuleBorrowed};
|
2016-11-24 02:47:18 +03:00
|
|
|
use style::gecko_bindings::bindings::{ServoCssRulesBorrowed, ServoCssRulesStrong};
|
2017-05-20 15:24:21 +03:00
|
|
|
use style::gecko_bindings::bindings::{nsACString, nsAString, nsCSSPropertyIDSetBorrowedMut};
|
|
|
|
use style::gecko_bindings::bindings::Gecko_AddPropertyToSet;
|
2017-07-20 08:48:47 +03:00
|
|
|
use style::gecko_bindings::bindings::Gecko_AppendPropertyValuePair;
|
2017-09-06 02:35:55 +03:00
|
|
|
use style::gecko_bindings::bindings::Gecko_ConstructFontFeatureValueSet;
|
2017-05-13 22:05:40 +03:00
|
|
|
use style::gecko_bindings::bindings::Gecko_GetOrCreateFinalKeyframe;
|
|
|
|
use style::gecko_bindings::bindings::Gecko_GetOrCreateInitialKeyframe;
|
|
|
|
use style::gecko_bindings::bindings::Gecko_GetOrCreateKeyframeAtStart;
|
servo: Merge #18452 - Overhaul MallocSizeOf and related things (from nnethercote:bug-1398737); r=jdm
This patch makes the MallocSizeOf stuff in Stylo work more like the HeapSizeOf
stuff already in Servo, except better. In particular, it adds deriving support
for MallocSizeOf, which will make it easier to improve coverage.
The patch does the following.
- Combines servo/components/style/stylesheets/memory.rs and the heapsize crate
into a new crate, malloc_size_of.
- Forks the heapsize_derive crate, calling it malloc_size_of, so that
MallocSizeOf can be derived.
- Both the new crates have MIT/Apache licenses, like heapsize, in case they are
incorporated into heapsize in the future.
- Renames the methods within MallocSizeOf and the related traits so they are
more concise.
- Removes MallocSizeOfWithGuard.
- Adds `derive(MallocSizeOf)` to a lot of types, in some cases replacing an
equivalent or almost-equivalent hand-written implementation.
- Adds stuff so that Rc/Arc can be handled properly.
<!-- Please describe your changes on the following line: -->
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [X] These changes do not require tests because tested on Gecko side.
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- 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: 7f4cb1861b172423781a369b2decca6c65d60546
--HG--
rename : servo/components/hashglobe/LICENSE-APACHE => servo/components/malloc_size_of/LICENSE-APACHE
rename : servo/components/hashglobe/LICENSE-MIT => servo/components/malloc_size_of/LICENSE-MIT
rename : servo/components/jstraceable_derive/Cargo.toml => servo/components/malloc_size_of_derive/Cargo.toml
rename : servo/components/hashglobe/LICENSE-APACHE => servo/components/malloc_size_of_derive/LICENSE-APACHE
rename : servo/components/hashglobe/LICENSE-MIT => servo/components/malloc_size_of_derive/LICENSE-MIT
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : a8254c4ae15901b764d918355e900a1e74d6eb03
2017-09-12 06:11:25 +03:00
|
|
|
use style::gecko_bindings::bindings::Gecko_HaveSeenPtr;
|
2017-05-20 15:24:21 +03:00
|
|
|
use style::gecko_bindings::bindings::Gecko_NewNoneTransform;
|
2017-04-06 06:53:30 +03:00
|
|
|
use style::gecko_bindings::bindings::RawGeckoAnimationPropertySegmentBorrowed;
|
2017-05-20 15:24:21 +03:00
|
|
|
use style::gecko_bindings::bindings::RawGeckoCSSPropertyIDListBorrowed;
|
2017-02-24 15:09:33 +03:00
|
|
|
use style::gecko_bindings::bindings::RawGeckoComputedKeyframeValuesListBorrowedMut;
|
2017-04-06 06:53:30 +03:00
|
|
|
use style::gecko_bindings::bindings::RawGeckoComputedTimingBorrowed;
|
2017-03-30 04:50:47 +03:00
|
|
|
use style::gecko_bindings::bindings::RawGeckoFontFaceRuleListBorrowedMut;
|
2017-06-09 02:23:56 +03:00
|
|
|
use style::gecko_bindings::bindings::RawGeckoServoAnimationValueListBorrowed;
|
|
|
|
use style::gecko_bindings::bindings::RawGeckoServoAnimationValueListBorrowedMut;
|
2017-04-10 12:04:54 +03:00
|
|
|
use style::gecko_bindings::bindings::RawGeckoServoStyleRuleListBorrowedMut;
|
2017-01-14 00:25:39 +03:00
|
|
|
use style::gecko_bindings::bindings::RawServoAnimationValueBorrowed;
|
2017-10-27 22:38:43 +03:00
|
|
|
use style::gecko_bindings::bindings::RawServoAnimationValueBorrowedOrNull;
|
2017-05-01 13:51:48 +03:00
|
|
|
use style::gecko_bindings::bindings::RawServoAnimationValueMapBorrowedMut;
|
2017-01-26 10:36:33 +03:00
|
|
|
use style::gecko_bindings::bindings::RawServoAnimationValueStrong;
|
2017-08-04 00:27:12 +03:00
|
|
|
use style::gecko_bindings::bindings::RawServoAnimationValueTableBorrowed;
|
2017-09-27 12:35:00 +03:00
|
|
|
use style::gecko_bindings::bindings::RawServoDeclarationBlockBorrowedOrNull;
|
2017-04-10 12:04:54 +03:00
|
|
|
use style::gecko_bindings::bindings::RawServoStyleRuleBorrowed;
|
2017-08-16 06:11:50 +03:00
|
|
|
use style::gecko_bindings::bindings::RawServoStyleSet;
|
2017-07-18 05:44:25 +03:00
|
|
|
use style::gecko_bindings::bindings::ServoStyleContextBorrowedOrNull;
|
2016-11-24 02:47:18 +03:00
|
|
|
use style::gecko_bindings::bindings::nsTArrayBorrowed_uintptr_t;
|
2017-03-21 11:36:49 +03:00
|
|
|
use style::gecko_bindings::bindings::nsTimingFunctionBorrowed;
|
|
|
|
use style::gecko_bindings::bindings::nsTimingFunctionBorrowedMut;
|
2016-11-25 20:00:44 +03:00
|
|
|
use style::gecko_bindings::structs;
|
2017-10-25 15:50:46 +03:00
|
|
|
use style::gecko_bindings::structs::{CallerType, CSSPseudoElementType, CompositeOperation};
|
2017-08-24 22:58:49 +03:00
|
|
|
use style::gecko_bindings::structs::{Loader, LoaderReusableStyleSheets};
|
2017-09-15 22:43:30 +03:00
|
|
|
use style::gecko_bindings::structs::{RawServoStyleRule, ServoStyleContextStrong, RustString};
|
2017-10-09 03:10:40 +03:00
|
|
|
use style::gecko_bindings::structs::{ServoStyleSheet, SheetParsingMode, nsAtom, nsCSSPropertyID};
|
2017-05-16 09:17:07 +03:00
|
|
|
use style::gecko_bindings::structs::{nsCSSFontFaceRule, nsCSSCounterStyleRule};
|
2017-05-31 20:03:50 +03:00
|
|
|
use style::gecko_bindings::structs::{nsRestyleHint, nsChangeHint, PropertyValuePair};
|
2017-10-20 12:18:53 +03:00
|
|
|
use style::gecko_bindings::structs::AtomArray;
|
2017-05-24 08:03:42 +03:00
|
|
|
use style::gecko_bindings::structs::IterationCompositeOperation;
|
2017-08-31 08:31:31 +03:00
|
|
|
use style::gecko_bindings::structs::MallocSizeOf as GeckoMallocSizeOf;
|
2017-08-13 14:39:40 +03:00
|
|
|
use style::gecko_bindings::structs::OriginFlags;
|
|
|
|
use style::gecko_bindings::structs::OriginFlags_Author;
|
|
|
|
use style::gecko_bindings::structs::OriginFlags_User;
|
|
|
|
use style::gecko_bindings::structs::OriginFlags_UserAgent;
|
2017-06-07 09:54:41 +03:00
|
|
|
use style::gecko_bindings::structs::RawGeckoGfxMatrix4x4;
|
2017-01-18 16:39:57 +03:00
|
|
|
use style::gecko_bindings::structs::RawGeckoPresContextOwned;
|
2017-10-10 09:20:38 +03:00
|
|
|
use style::gecko_bindings::structs::RawServoSelectorList;
|
2017-11-13 06:01:34 +03:00
|
|
|
use style::gecko_bindings::structs::RawServoSourceSizeList;
|
2017-08-03 03:39:15 +03:00
|
|
|
use style::gecko_bindings::structs::SeenPtrs;
|
2017-05-10 23:08:59 +03:00
|
|
|
use style::gecko_bindings::structs::ServoElementSnapshotTable;
|
2017-08-31 08:31:31 +03:00
|
|
|
use style::gecko_bindings::structs::ServoStyleSetSizes;
|
2017-07-28 02:29:29 +03:00
|
|
|
use style::gecko_bindings::structs::ServoTraversalFlags;
|
2017-05-25 13:50:52 +03:00
|
|
|
use style::gecko_bindings::structs::StyleRuleInclusion;
|
2017-04-03 07:30:56 +03:00
|
|
|
use style::gecko_bindings::structs::URLExtraData;
|
2017-08-25 23:45:03 +03:00
|
|
|
use style::gecko_bindings::structs::gfxFontFeatureValueSet;
|
2017-02-09 05:39:45 +03:00
|
|
|
use style::gecko_bindings::structs::nsCSSValueSharedList;
|
2017-05-14 04:50:10 +03:00
|
|
|
use style::gecko_bindings::structs::nsCompatibility;
|
2017-06-10 22:25:59 +03:00
|
|
|
use style::gecko_bindings::structs::nsIDocument;
|
2017-06-07 09:54:41 +03:00
|
|
|
use style::gecko_bindings::structs::nsStyleTransformMatrix::MatrixTransformOperator;
|
2017-07-24 07:54:12 +03:00
|
|
|
use style::gecko_bindings::structs::nsTArray;
|
2016-12-01 08:54:46 +03:00
|
|
|
use style::gecko_bindings::structs::nsresult;
|
2017-08-16 06:11:50 +03:00
|
|
|
use style::gecko_bindings::sugar::ownership::{FFIArcHelpers, HasFFI, HasArcFFI};
|
2016-09-26 10:36:05 +03:00
|
|
|
use style::gecko_bindings::sugar::ownership::{HasSimpleFFI, Strong};
|
2017-04-03 15:05:42 +03:00
|
|
|
use style::gecko_bindings::sugar::refptr::RefPtr;
|
2017-11-12 22:04:22 +03:00
|
|
|
use style::gecko_properties;
|
2017-08-03 00:27:58 +03:00
|
|
|
use style::invalidation::element::restyle_hints;
|
2017-09-04 23:19:06 +03:00
|
|
|
use style::media_queries::{Device, MediaList, parse_media_query_list};
|
2017-10-17 09:11:39 +03:00
|
|
|
use style::parser::{Parse, ParserContext, self};
|
2017-10-14 13:27:51 +03:00
|
|
|
use style::properties::{CascadeFlags, ComputedValues, DeclarationSource, Importance};
|
2017-10-31 02:25:45 +03:00
|
|
|
use style::properties::{LonghandId, LonghandIdSet, PropertyDeclaration, PropertyDeclarationBlock, PropertyId};
|
2017-09-29 18:01:52 +03:00
|
|
|
use style::properties::{PropertyDeclarationId, ShorthandId};
|
2017-10-31 02:25:45 +03:00
|
|
|
use style::properties::{SourcePropertyDeclaration, StyleBuilder};
|
2017-09-29 18:01:52 +03:00
|
|
|
use style::properties::animated_properties::AnimationValue;
|
2017-07-24 07:54:12 +03:00
|
|
|
use style::properties::animated_properties::compare_property_priority;
|
2017-05-20 02:37:14 +03:00
|
|
|
use style::properties::parse_one_declaration_into;
|
2017-09-14 12:28:50 +03:00
|
|
|
use style::rule_cache::RuleCacheConditions;
|
2017-10-19 09:24:38 +03:00
|
|
|
use style::rule_tree::{CascadeLevel, StrongRuleNode, StyleSource};
|
2017-10-03 16:05:07 +03:00
|
|
|
use style::selector_parser::{PseudoElementCascadeType, SelectorImpl};
|
2017-07-10 12:31:35 +03:00
|
|
|
use style::shared_lock::{SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard, Locked};
|
2017-10-20 12:18:53 +03:00
|
|
|
use style::string_cache::{Atom, WeakAtom};
|
2017-04-28 18:25:21 +03:00
|
|
|
use style::style_adjuster::StyleAdjuster;
|
servo: Merge #17044 - Introduce and start using the MallocSizeOf trait (from nnethercote:MallocSizeOf); r=emilio
MallocSizeOf is similar to the existing HeapSizeOf trait from the
heapsize crate. The only difference is that MallocSizeOf's
malloc_size_of_children() function takes an additional MallocSizeOfFn
argument, which is used to measure heap blocks. This extra argument
makes MallocSizeOf match how Gecko's memory measurements work, and is
required for Stylo to integrate with DMD.
The patch also introduces a second trait, MallocSizeOfWithGuard, which
is much the same as MallocSizeOf, but with a |guard| argument for the
global style lock.
Finally, the patch uses the new traits to measure a small amount of
Stylo's memory usage.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [X] These changes do not require tests because code is only for Gecko integration.
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- 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: aca09436b71e6defe007e1d17a9d79214d094a7b
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 1d5dc4e7ab75e8e0332922396b5b55ed67c4572e
2017-05-29 05:10:25 +03:00
|
|
|
use style::stylesheets::{CssRule, CssRules, CssRuleType, CssRulesHelpers, DocumentRule};
|
servo: Merge #18452 - Overhaul MallocSizeOf and related things (from nnethercote:bug-1398737); r=jdm
This patch makes the MallocSizeOf stuff in Stylo work more like the HeapSizeOf
stuff already in Servo, except better. In particular, it adds deriving support
for MallocSizeOf, which will make it easier to improve coverage.
The patch does the following.
- Combines servo/components/style/stylesheets/memory.rs and the heapsize crate
into a new crate, malloc_size_of.
- Forks the heapsize_derive crate, calling it malloc_size_of, so that
MallocSizeOf can be derived.
- Both the new crates have MIT/Apache licenses, like heapsize, in case they are
incorporated into heapsize in the future.
- Renames the methods within MallocSizeOf and the related traits so they are
more concise.
- Removes MallocSizeOfWithGuard.
- Adds `derive(MallocSizeOf)` to a lot of types, in some cases replacing an
equivalent or almost-equivalent hand-written implementation.
- Adds stuff so that Rc/Arc can be handled properly.
<!-- Please describe your changes on the following line: -->
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [X] These changes do not require tests because tested on Gecko side.
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- 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: 7f4cb1861b172423781a369b2decca6c65d60546
--HG--
rename : servo/components/hashglobe/LICENSE-APACHE => servo/components/malloc_size_of/LICENSE-APACHE
rename : servo/components/hashglobe/LICENSE-MIT => servo/components/malloc_size_of/LICENSE-MIT
rename : servo/components/jstraceable_derive/Cargo.toml => servo/components/malloc_size_of_derive/Cargo.toml
rename : servo/components/hashglobe/LICENSE-APACHE => servo/components/malloc_size_of_derive/LICENSE-APACHE
rename : servo/components/hashglobe/LICENSE-MIT => servo/components/malloc_size_of_derive/LICENSE-MIT
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : a8254c4ae15901b764d918355e900a1e74d6eb03
2017-09-12 06:11:25 +03:00
|
|
|
use style::stylesheets::{FontFeatureValuesRule, ImportRule, KeyframesRule, MediaRule};
|
|
|
|
use style::stylesheets::{NamespaceRule, Origin, OriginSet, PageRule, StyleRule};
|
2017-08-16 10:56:13 +03:00
|
|
|
use style::stylesheets::{StylesheetContents, SupportsRule};
|
2016-12-31 06:12:55 +03:00
|
|
|
use style::stylesheets::StylesheetLoader as StyleStylesheetLoader;
|
2017-06-05 00:26:30 +03:00
|
|
|
use style::stylesheets::keyframes_rule::{Keyframe, KeyframeSelector, KeyframesStepValue};
|
|
|
|
use style::stylesheets::supports_rule::parse_condition_or_declaration;
|
2017-09-20 02:46:49 +03:00
|
|
|
use style::stylist::{add_size_of_ua_cache, RuleInclusion, Stylist};
|
2016-11-21 17:16:36 +03:00
|
|
|
use style::thread_state;
|
2016-07-20 21:38:31 +03:00
|
|
|
use style::timer::Timer;
|
2017-08-25 20:23:41 +03:00
|
|
|
use style::traversal::DomTraversal;
|
2017-07-12 10:28:44 +03:00
|
|
|
use style::traversal::resolve_style;
|
2017-10-31 02:25:45 +03:00
|
|
|
use style::traversal_flags::{self, TraversalFlags};
|
2017-05-19 07:49:30 +03:00
|
|
|
use style::values::{CustomIdent, KeyframesName};
|
2017-08-22 15:22:10 +03:00
|
|
|
use style::values::animated::{Animate, Procedure, ToAnimatedZero};
|
2017-09-17 23:12:46 +03:00
|
|
|
use style::values::computed::{Context, ToComputedValue};
|
2017-08-14 00:23:58 +03:00
|
|
|
use style::values::distance::ComputeSquaredDistance;
|
2017-10-16 12:49:33 +03:00
|
|
|
use style::values::specified;
|
2017-10-17 09:11:39 +03:00
|
|
|
use style::values::specified::gecko::IntersectionObserverRootMargin;
|
2017-11-13 06:01:34 +03:00
|
|
|
use style::values::specified::source_size_list::SourceSizeList;
|
2017-10-31 02:25:45 +03:00
|
|
|
use style_traits::{ParsingMode, ToCss};
|
2017-07-11 04:13:44 +03:00
|
|
|
use super::error_reporter::ErrorReporter;
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
use super::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.
|
|
|
|
*/
|
|
|
|
|
2017-04-03 15:05:42 +03:00
|
|
|
// A dummy url data for where we don't pass url data in.
|
|
|
|
// We need to get rid of this sooner than later.
|
2017-04-07 03:33:35 +03:00
|
|
|
static mut DUMMY_URL_DATA: *mut URLExtraData = 0 as *mut URLExtraData;
|
2017-02-23 21:15:41 +03:00
|
|
|
|
2016-05-05 04:37:26 +03:00
|
|
|
#[no_mangle]
|
2017-04-07 03:33:35 +03:00
|
|
|
pub extern "C" fn Servo_Initialize(dummy_url_data: *mut URLExtraData) {
|
2017-08-14 14:42:44 +03:00
|
|
|
use style::gecko_bindings::sugar::origin_flags;
|
|
|
|
|
2017-02-15 14:05:07 +03:00
|
|
|
// Initialize logging.
|
|
|
|
let mut builder = LogBuilder::new();
|
|
|
|
let default_level = if cfg!(debug_assertions) { "warn" } else { "error" };
|
|
|
|
match env::var("RUST_LOG") {
|
|
|
|
Ok(v) => builder.parse(&v).init().unwrap(),
|
|
|
|
_ => builder.parse(default_level).init().unwrap(),
|
|
|
|
};
|
2016-08-04 04:20:21 +03:00
|
|
|
|
2016-11-21 17:16:36 +03:00
|
|
|
// Pretend that we're a Servo Layout thread, to make some assertions happy.
|
2017-10-31 02:25:45 +03:00
|
|
|
thread_state::initialize(thread_state::ThreadState::LAYOUT);
|
2017-02-14 06:44:12 +03:00
|
|
|
|
|
|
|
// Perform some debug-only runtime assertions.
|
|
|
|
restyle_hints::assert_restyle_hints_match();
|
2017-08-14 14:42:44 +03:00
|
|
|
origin_flags::assert_flags_match();
|
2017-07-28 02:29:29 +03:00
|
|
|
parser::assert_parsing_mode_match();
|
|
|
|
traversal_flags::assert_traversal_flags_match();
|
2017-11-16 05:00:48 +03:00
|
|
|
specified::font::assert_variant_east_asian_matches();
|
2017-11-18 00:03:14 +03:00
|
|
|
specified::font::assert_variant_ligatures_matches();
|
2017-02-20 08:12:57 +03:00
|
|
|
|
2017-04-03 15:05:42 +03:00
|
|
|
// Initialize the dummy url data
|
2017-04-07 03:33:35 +03:00
|
|
|
unsafe { DUMMY_URL_DATA = dummy_url_data; }
|
2016-08-04 04:20:21 +03:00
|
|
|
}
|
|
|
|
|
2017-09-20 08:59:35 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_InitializeCooperativeThread() {
|
|
|
|
// Pretend that we're a Servo Layout thread to make some assertions happy.
|
2017-10-31 02:25:45 +03:00
|
|
|
thread_state::initialize(thread_state::ThreadState::LAYOUT);
|
2017-09-20 08:59:35 +03:00
|
|
|
}
|
|
|
|
|
2016-08-04 04:20:21 +03:00
|
|
|
#[no_mangle]
|
2017-03-13 20:01:16 +03:00
|
|
|
pub extern "C" fn Servo_Shutdown() {
|
2017-04-07 03:33:35 +03:00
|
|
|
// The dummy url will be released after shutdown, so clear the
|
|
|
|
// reference to avoid use-after-free.
|
|
|
|
unsafe { DUMMY_URL_DATA = ptr::null_mut(); }
|
2017-09-15 22:43:18 +03:00
|
|
|
Stylist::shutdown();
|
2017-04-03 15:05:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
unsafe fn dummy_url_data() -> &'static RefPtr<URLExtraData> {
|
2017-04-07 03:33:35 +03:00
|
|
|
RefPtr::from_ptr_ref(&DUMMY_URL_DATA)
|
2016-11-25 20:00:44 +03:00
|
|
|
}
|
2016-04-04 17:41:29 +03:00
|
|
|
|
2017-04-12 10:27:02 +03:00
|
|
|
fn create_shared_context<'a>(global_style_data: &GlobalStyleData,
|
|
|
|
guard: &'a SharedRwLockReadGuard,
|
2017-05-12 16:56:47 +03:00
|
|
|
per_doc_data: &'a PerDocumentStyleDataImpl,
|
2017-05-10 23:08:59 +03:00
|
|
|
traversal_flags: TraversalFlags,
|
2017-07-07 00:57:36 +03:00
|
|
|
snapshot_map: &'a ServoElementSnapshotTable)
|
2017-05-10 23:08:59 +03:00
|
|
|
-> SharedStyleContext<'a> {
|
2016-11-25 20:00:44 +03:00
|
|
|
SharedStyleContext {
|
2017-05-12 16:56:47 +03:00
|
|
|
stylist: &per_doc_data.stylist,
|
2017-07-29 06:51:20 +03:00
|
|
|
visited_styles_enabled: per_doc_data.visited_styles_enabled(),
|
2017-04-12 10:27:02 +03:00
|
|
|
options: global_style_data.options.clone(),
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
guards: StylesheetGuards::same(guard),
|
2016-07-20 21:38:31 +03:00
|
|
|
timer: Timer::new(),
|
2017-04-09 09:04:57 +03:00
|
|
|
traversal_flags: traversal_flags,
|
2017-05-10 23:08:59 +03:00
|
|
|
snapshot_map: snapshot_map,
|
2016-11-25 20:00:44 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-27 15:39:42 +03:00
|
|
|
fn traverse_subtree(element: GeckoElement,
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
2017-05-10 23:08:59 +03:00
|
|
|
traversal_flags: TraversalFlags,
|
|
|
|
snapshots: &ServoElementSnapshotTable) {
|
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.
|
2017-06-09 13:57:36 +03:00
|
|
|
if let Some(parent) = element.traversal_parent() {
|
2017-06-23 03:46:55 +03:00
|
|
|
if parent.borrow_data().map_or(true, |d| d.styles.is_display_none()) {
|
2017-03-30 12:34:25 +03:00
|
|
|
debug!("{:?} has unstyled parent {:?} - ignoring call to traverse_subtree", element, parent);
|
2016-11-25 20:00:44 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-23 21:15:41 +03:00
|
|
|
let per_doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
2017-08-22 19:45:42 +03:00
|
|
|
debug_assert!(!per_doc_data.stylist.stylesheets_have_changed());
|
2016-12-10 04:01:05 +03:00
|
|
|
|
2017-05-10 23:08:59 +03:00
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
2017-09-26 14:58:04 +03:00
|
|
|
let shared_style_context = create_shared_context(
|
|
|
|
&global_style_data,
|
|
|
|
&guard,
|
|
|
|
&per_doc_data,
|
|
|
|
traversal_flags,
|
|
|
|
snapshots,
|
|
|
|
);
|
2017-05-10 23:08:59 +03:00
|
|
|
|
2017-09-26 14:58:04 +03:00
|
|
|
let token = RecalcStyleOnly::pre_traverse(
|
|
|
|
element,
|
|
|
|
&shared_style_context,
|
|
|
|
);
|
2017-05-10 23:08:59 +03:00
|
|
|
|
2016-12-10 04:01:05 +03:00
|
|
|
if !token.should_traverse() {
|
2016-10-26 14:36:06 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-08-27 02:13:40 +03:00
|
|
|
debug!("Traversing subtree from {:?}", element);
|
2016-12-13 06:13:03 +03:00
|
|
|
|
2017-08-25 20:23:41 +03:00
|
|
|
let thread_pool_holder = &*STYLE_THREAD_POOL;
|
2017-10-31 02:25:45 +03:00
|
|
|
let thread_pool = if traversal_flags.contains(TraversalFlags::ParallelTraversal) {
|
2017-08-25 20:23:41 +03:00
|
|
|
thread_pool_holder.style_thread_pool.as_ref()
|
2016-07-28 01:56:26 +03:00
|
|
|
} else {
|
2017-08-25 20:23:41 +03:00
|
|
|
None
|
2017-01-25 04:02:41 +03:00
|
|
|
};
|
|
|
|
|
2017-08-25 20:23:41 +03:00
|
|
|
let traversal = RecalcStyleOnly::new(shared_style_context);
|
2017-09-26 14:58:04 +03:00
|
|
|
driver::traverse_dom(&traversal, token, thread_pool);
|
2016-01-19 11:49:10 +03:00
|
|
|
}
|
|
|
|
|
2017-05-10 23:08:59 +03:00
|
|
|
/// Traverses the subtree rooted at `root` for restyling.
|
|
|
|
///
|
2017-09-26 14:58:04 +03:00
|
|
|
/// Returns whether the root was restyled. Whether anything else was restyled or
|
|
|
|
/// not can be inferred from the dirty bits in the rest of the tree.
|
2016-05-26 00:26:11 +03:00
|
|
|
#[no_mangle]
|
2017-08-27 02:13:40 +03:00
|
|
|
pub extern "C" fn Servo_TraverseSubtree(
|
|
|
|
root: RawGeckoElementBorrowed,
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
|
|
|
snapshots: *const ServoElementSnapshotTable,
|
|
|
|
raw_flags: ServoTraversalFlags
|
|
|
|
) -> bool {
|
2017-07-28 02:29:29 +03:00
|
|
|
let traversal_flags = TraversalFlags::from_bits_truncate(raw_flags);
|
2017-05-10 23:08:59 +03:00
|
|
|
debug_assert!(!snapshots.is_null());
|
2017-04-09 09:04:57 +03:00
|
|
|
|
2016-11-25 20:00:44 +03:00
|
|
|
let element = GeckoElement(root);
|
2017-03-27 07:13:44 +03:00
|
|
|
|
2017-08-09 21:03:00 +03:00
|
|
|
debug!("Servo_TraverseSubtree (flags={:?})", traversal_flags);
|
2017-08-27 02:13:40 +03:00
|
|
|
debug!("{:?}", ShowSubtreeData(element.as_node()));
|
2017-07-24 11:09:24 +03:00
|
|
|
|
2017-11-20 13:18:30 +03:00
|
|
|
let needs_animation_only_restyle =
|
|
|
|
element.has_animation_only_dirty_descendants() ||
|
|
|
|
element.has_animation_restyle_hints();
|
|
|
|
|
|
|
|
if needs_animation_only_restyle {
|
|
|
|
debug!("Servo_TraverseSubtree doing animation-only restyle (aodd={})",
|
|
|
|
element.has_animation_only_dirty_descendants());
|
|
|
|
traverse_subtree(element,
|
|
|
|
raw_data,
|
|
|
|
traversal_flags | TraversalFlags::AnimationOnly,
|
|
|
|
unsafe { &*snapshots });
|
2017-03-27 07:13:44 +03:00
|
|
|
}
|
|
|
|
|
2017-05-10 23:08:59 +03:00
|
|
|
traverse_subtree(element,
|
|
|
|
raw_data,
|
|
|
|
traversal_flags,
|
|
|
|
unsafe { &*snapshots });
|
2017-02-10 06:27:33 +03:00
|
|
|
|
2017-09-12 21:16:26 +03:00
|
|
|
debug!("Servo_TraverseSubtree complete (dd={}, aodd={}, lfcd={}, lfc={}, data={:?})",
|
2017-08-09 21:03:00 +03:00
|
|
|
element.has_dirty_descendants(),
|
|
|
|
element.has_animation_only_dirty_descendants(),
|
2017-08-23 06:04:34 +03:00
|
|
|
element.descendants_need_frames(),
|
|
|
|
element.needs_frame(),
|
2017-09-12 21:16:26 +03:00
|
|
|
element.borrow_data().unwrap());
|
2017-08-09 21:03:00 +03:00
|
|
|
|
2017-09-26 14:58:04 +03:00
|
|
|
let element_was_restyled =
|
|
|
|
element.borrow_data().unwrap().contains_restyle_data();
|
|
|
|
element_was_restyled
|
2016-05-26 00:26:11 +03:00
|
|
|
}
|
|
|
|
|
2017-06-17 00:13:38 +03:00
|
|
|
/// Checks whether the rule tree has crossed its threshold for unused nodes, and
|
|
|
|
/// if so, frees them.
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_MaybeGCRuleTree(raw_data: RawServoStyleSetBorrowed) {
|
|
|
|
let per_doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
|
|
|
unsafe {
|
|
|
|
per_doc_data.stylist.rule_tree().maybe_gc();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-26 10:36:33 +03:00
|
|
|
#[no_mangle]
|
2017-10-14 16:13:59 +03:00
|
|
|
pub extern "C" fn Servo_AnimationValues_Interpolate(
|
|
|
|
from: RawServoAnimationValueBorrowed,
|
|
|
|
to: RawServoAnimationValueBorrowed,
|
|
|
|
progress: f64,
|
|
|
|
) -> RawServoAnimationValueStrong {
|
2017-01-26 10:36:33 +03:00
|
|
|
let from_value = AnimationValue::as_arc(&from);
|
|
|
|
let to_value = AnimationValue::as_arc(&to);
|
2017-08-22 15:22:10 +03:00
|
|
|
if let Ok(value) = from_value.animate(to_value, Procedure::Interpolate { progress }) {
|
2017-01-26 10:36:33 +03:00
|
|
|
Arc::new(value).into_strong()
|
|
|
|
} else {
|
|
|
|
RawServoAnimationValueStrong::null()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-12 15:00:20 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_AnimationValues_IsInterpolable(from: RawServoAnimationValueBorrowed,
|
|
|
|
to: RawServoAnimationValueBorrowed)
|
|
|
|
-> bool {
|
|
|
|
let from_value = AnimationValue::as_arc(&from);
|
|
|
|
let to_value = AnimationValue::as_arc(&to);
|
2017-08-22 15:22:10 +03:00
|
|
|
from_value.animate(to_value, Procedure::Interpolate { progress: 0.5 }).is_ok()
|
2017-04-12 15:00:20 +03:00
|
|
|
}
|
|
|
|
|
2017-06-05 07:41:06 +03:00
|
|
|
#[no_mangle]
|
2017-10-14 16:13:59 +03:00
|
|
|
pub extern "C" fn Servo_AnimationValues_Add(
|
|
|
|
a: RawServoAnimationValueBorrowed,
|
|
|
|
b: RawServoAnimationValueBorrowed,
|
|
|
|
) -> RawServoAnimationValueStrong {
|
2017-06-05 07:41:06 +03:00
|
|
|
let a_value = AnimationValue::as_arc(&a);
|
|
|
|
let b_value = AnimationValue::as_arc(&b);
|
2017-08-22 15:22:10 +03:00
|
|
|
if let Ok(value) = a_value.animate(b_value, Procedure::Add) {
|
2017-06-05 07:41:06 +03:00
|
|
|
Arc::new(value).into_strong()
|
|
|
|
} else {
|
|
|
|
RawServoAnimationValueStrong::null()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-14 16:13:59 +03:00
|
|
|
pub extern "C" fn Servo_AnimationValues_Accumulate(
|
|
|
|
a: RawServoAnimationValueBorrowed,
|
|
|
|
b: RawServoAnimationValueBorrowed,
|
|
|
|
count: u64,
|
|
|
|
) -> RawServoAnimationValueStrong {
|
2017-06-05 07:41:06 +03:00
|
|
|
let a_value = AnimationValue::as_arc(&a);
|
|
|
|
let b_value = AnimationValue::as_arc(&b);
|
2017-08-22 15:22:10 +03:00
|
|
|
if let Ok(value) = a_value.animate(b_value, Procedure::Accumulate { count }) {
|
2017-06-05 07:41:06 +03:00
|
|
|
Arc::new(value).into_strong()
|
|
|
|
} else {
|
|
|
|
RawServoAnimationValueStrong::null()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_AnimationValues_GetZeroValue(
|
|
|
|
value_to_match: RawServoAnimationValueBorrowed)
|
|
|
|
-> RawServoAnimationValueStrong
|
|
|
|
{
|
|
|
|
let value_to_match = AnimationValue::as_arc(&value_to_match);
|
2017-07-19 11:56:05 +03:00
|
|
|
if let Ok(zero_value) = value_to_match.to_animated_zero() {
|
2017-06-05 07:41:06 +03:00
|
|
|
Arc::new(zero_value).into_strong()
|
|
|
|
} else {
|
|
|
|
RawServoAnimationValueStrong::null()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-21 08:52:13 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_AnimationValues_ComputeDistance(from: RawServoAnimationValueBorrowed,
|
|
|
|
to: RawServoAnimationValueBorrowed)
|
|
|
|
-> f64 {
|
|
|
|
let from_value = AnimationValue::as_arc(&from);
|
|
|
|
let to_value = AnimationValue::as_arc(&to);
|
2017-08-31 07:21:49 +03:00
|
|
|
// If compute_squared_distance() failed, this function will return negative value
|
|
|
|
// in order to check whether we support the specified paced animation values.
|
|
|
|
from_value.compute_squared_distance(to_value).map(|d| d.sqrt()).unwrap_or(-1.0)
|
2017-04-21 08:52:13 +03:00
|
|
|
}
|
|
|
|
|
2017-10-27 22:38:43 +03:00
|
|
|
/// Compute one of the endpoints for the interpolation interval, compositing it with the
|
|
|
|
/// underlying value if needed.
|
|
|
|
/// An None returned value means, "Just use endpoint_value as-is."
|
|
|
|
/// It is the responsibility of the caller to ensure that |underlying_value| is provided
|
|
|
|
/// when it will be used.
|
|
|
|
fn composite_endpoint(
|
|
|
|
endpoint_value: Option<&RawOffsetArc<AnimationValue>>,
|
|
|
|
composite: CompositeOperation,
|
|
|
|
underlying_value: Option<&AnimationValue>,
|
|
|
|
) -> Option<AnimationValue> {
|
|
|
|
match endpoint_value {
|
|
|
|
Some(endpoint_value) => {
|
|
|
|
match composite {
|
|
|
|
CompositeOperation::Add => {
|
|
|
|
underlying_value
|
|
|
|
.expect("We should have an underlying_value")
|
|
|
|
.animate(endpoint_value, Procedure::Add).ok()
|
|
|
|
},
|
|
|
|
CompositeOperation::Accumulate => {
|
|
|
|
underlying_value
|
|
|
|
.expect("We should have an underlying value")
|
|
|
|
.animate(endpoint_value, Procedure::Accumulate { count: 1 })
|
|
|
|
.ok()
|
|
|
|
},
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
None => underlying_value.map(|v| v.clone()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Accumulate one of the endpoints of the animation interval.
|
|
|
|
/// A returned value of None means, "Just use endpoint_value as-is."
|
|
|
|
fn accumulate_endpoint(
|
|
|
|
endpoint_value: Option<&RawOffsetArc<AnimationValue>>,
|
|
|
|
composited_value: Option<AnimationValue>,
|
|
|
|
last_value: &AnimationValue,
|
|
|
|
current_iteration: u64
|
|
|
|
) -> Option<AnimationValue> {
|
|
|
|
debug_assert!(endpoint_value.is_some() || composited_value.is_some(),
|
|
|
|
"Should have a suitable value to use");
|
|
|
|
|
|
|
|
let count = current_iteration;
|
|
|
|
match composited_value {
|
|
|
|
Some(endpoint) => {
|
|
|
|
last_value
|
|
|
|
.animate(&endpoint, Procedure::Accumulate { count })
|
|
|
|
.ok()
|
|
|
|
.or(Some(endpoint))
|
|
|
|
},
|
|
|
|
None => {
|
|
|
|
last_value
|
|
|
|
.animate(endpoint_value.unwrap(), Procedure::Accumulate { count })
|
|
|
|
.ok()
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Compose the animation segment. We composite it with the underlying_value and last_value if
|
|
|
|
/// needed.
|
|
|
|
/// The caller is responsible for providing an underlying value and last value
|
|
|
|
/// in all situations where there are needed.
|
|
|
|
fn compose_animation_segment(
|
|
|
|
segment: RawGeckoAnimationPropertySegmentBorrowed,
|
|
|
|
underlying_value: Option<&AnimationValue>,
|
|
|
|
last_value: Option<&AnimationValue>,
|
|
|
|
iteration_composite: IterationCompositeOperation,
|
|
|
|
current_iteration: u64,
|
|
|
|
total_progress: f64,
|
|
|
|
segment_progress: f64,
|
|
|
|
) -> AnimationValue {
|
|
|
|
// Extract keyframe values.
|
|
|
|
let raw_from_value;
|
|
|
|
let keyframe_from_value = if !segment.mFromValue.mServo.mRawPtr.is_null() {
|
|
|
|
raw_from_value = unsafe { &*segment.mFromValue.mServo.mRawPtr };
|
|
|
|
Some(AnimationValue::as_arc(&raw_from_value))
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
|
|
|
let raw_to_value;
|
|
|
|
let keyframe_to_value = if !segment.mToValue.mServo.mRawPtr.is_null() {
|
|
|
|
raw_to_value = unsafe { &*segment.mToValue.mServo.mRawPtr };
|
|
|
|
Some(AnimationValue::as_arc(&raw_to_value))
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut composited_from_value = composite_endpoint(keyframe_from_value,
|
|
|
|
segment.mFromComposite,
|
|
|
|
underlying_value);
|
|
|
|
let mut composited_to_value = composite_endpoint(keyframe_to_value,
|
|
|
|
segment.mToComposite,
|
|
|
|
underlying_value);
|
|
|
|
|
|
|
|
debug_assert!(keyframe_from_value.is_some() || composited_from_value.is_some(),
|
|
|
|
"Should have a suitable from value to use");
|
|
|
|
debug_assert!(keyframe_to_value.is_some() || composited_to_value.is_some(),
|
|
|
|
"Should have a suitable to value to use");
|
|
|
|
|
|
|
|
// Apply iteration composite behavior.
|
|
|
|
if iteration_composite == IterationCompositeOperation::Accumulate && current_iteration > 0 {
|
|
|
|
let last_value = last_value.unwrap_or_else(|| {
|
|
|
|
underlying_value.expect("Should have a valid underlying value")
|
|
|
|
});
|
|
|
|
|
|
|
|
composited_from_value = accumulate_endpoint(keyframe_from_value,
|
|
|
|
composited_from_value,
|
|
|
|
last_value,
|
|
|
|
current_iteration);
|
|
|
|
composited_to_value = accumulate_endpoint(keyframe_to_value,
|
|
|
|
composited_to_value,
|
|
|
|
last_value,
|
|
|
|
current_iteration);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Use the composited value if there is one, otherwise, use the original keyframe value.
|
|
|
|
let from = composited_from_value.as_ref().unwrap_or_else(|| keyframe_from_value.unwrap());
|
|
|
|
let to = composited_to_value.as_ref().unwrap_or_else(|| keyframe_to_value.unwrap());
|
|
|
|
|
|
|
|
if segment.mToKey == segment.mFromKey {
|
|
|
|
return if total_progress < 0. { from.clone() } else { to.clone() };
|
|
|
|
}
|
|
|
|
|
|
|
|
match from.animate(to, Procedure::Interpolate { progress: segment_progress }) {
|
|
|
|
Ok(value) => value,
|
|
|
|
_ => if segment_progress < 0.5 { from.clone() } else { to.clone() },
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_ComposeAnimationSegment(
|
|
|
|
segment: RawGeckoAnimationPropertySegmentBorrowed,
|
|
|
|
underlying_value: RawServoAnimationValueBorrowedOrNull,
|
|
|
|
last_value: RawServoAnimationValueBorrowedOrNull,
|
|
|
|
iteration_composite: IterationCompositeOperation,
|
|
|
|
progress: f64,
|
|
|
|
current_iteration: u64
|
|
|
|
) -> RawServoAnimationValueStrong {
|
|
|
|
let underlying_value = AnimationValue::arc_from_borrowed(&underlying_value).map(|v| &**v);
|
|
|
|
let last_value = AnimationValue::arc_from_borrowed(&last_value).map(|v| &**v);
|
|
|
|
let result = compose_animation_segment(segment,
|
|
|
|
underlying_value,
|
|
|
|
last_value,
|
|
|
|
iteration_composite,
|
|
|
|
current_iteration,
|
|
|
|
progress,
|
|
|
|
progress);
|
|
|
|
Arc::new(result).into_strong()
|
|
|
|
}
|
|
|
|
|
2017-04-06 06:53:30 +03:00
|
|
|
#[no_mangle]
|
2017-05-01 13:51:48 +03:00
|
|
|
pub extern "C" fn Servo_AnimationCompose(raw_value_map: RawServoAnimationValueMapBorrowedMut,
|
2017-08-04 00:27:12 +03:00
|
|
|
base_values: RawServoAnimationValueTableBorrowed,
|
2017-04-06 06:53:30 +03:00
|
|
|
css_property: nsCSSPropertyID,
|
|
|
|
segment: RawGeckoAnimationPropertySegmentBorrowed,
|
2017-05-24 08:03:42 +03:00
|
|
|
last_segment: RawGeckoAnimationPropertySegmentBorrowed,
|
|
|
|
computed_timing: RawGeckoComputedTimingBorrowed,
|
|
|
|
iteration_composite: IterationCompositeOperation)
|
2017-04-06 06:53:30 +03:00
|
|
|
{
|
|
|
|
use style::gecko_bindings::bindings::Gecko_AnimationGetBaseStyle;
|
|
|
|
use style::gecko_bindings::bindings::Gecko_GetPositionInSegment;
|
|
|
|
use style::gecko_bindings::bindings::Gecko_GetProgressFromComputedTiming;
|
|
|
|
use style::properties::animated_properties::AnimationValueMap;
|
|
|
|
|
2017-09-29 18:01:52 +03:00
|
|
|
let property = match LonghandId::from_nscsspropertyid(css_property) {
|
|
|
|
Ok(longhand) if longhand.is_animatable() => longhand,
|
|
|
|
_ => return,
|
2017-06-15 06:17:47 +03:00
|
|
|
};
|
2017-05-01 13:51:48 +03:00
|
|
|
let value_map = AnimationValueMap::from_ffi_mut(raw_value_map);
|
2017-04-06 06:53:30 +03:00
|
|
|
|
2017-05-24 08:03:42 +03:00
|
|
|
// We will need an underlying value if either of the endpoints is null...
|
2017-05-15 07:24:48 +03:00
|
|
|
let need_underlying_value = segment.mFromValue.mServo.mRawPtr.is_null() ||
|
|
|
|
segment.mToValue.mServo.mRawPtr.is_null() ||
|
2017-05-24 08:03:42 +03:00
|
|
|
// ... or if they have a non-replace composite mode ...
|
2017-05-15 07:24:48 +03:00
|
|
|
segment.mFromComposite != CompositeOperation::Replace ||
|
2017-05-24 08:03:42 +03:00
|
|
|
segment.mToComposite != CompositeOperation::Replace ||
|
|
|
|
// ... or if we accumulate onto the last value and it is null.
|
|
|
|
(iteration_composite == IterationCompositeOperation::Accumulate &&
|
|
|
|
computed_timing.mCurrentIteration > 0 &&
|
|
|
|
last_segment.mToValue.mServo.mRawPtr.is_null());
|
2017-05-15 07:24:48 +03:00
|
|
|
|
2017-04-06 06:53:30 +03:00
|
|
|
// If either of the segment endpoints are null, get the underlying value to
|
|
|
|
// use from the current value in the values map (set by a lower-priority
|
|
|
|
// effect), or, if there is no current value, look up the cached base value
|
|
|
|
// for this property.
|
2017-05-15 07:24:48 +03:00
|
|
|
let underlying_value = if need_underlying_value {
|
2017-05-01 13:51:48 +03:00
|
|
|
let previous_composed_value = value_map.get(&property).cloned();
|
2017-04-06 06:53:30 +03:00
|
|
|
previous_composed_value.or_else(|| {
|
|
|
|
let raw_base_style = unsafe { Gecko_AnimationGetBaseStyle(base_values, css_property) };
|
2017-07-18 05:44:25 +03:00
|
|
|
AnimationValue::arc_from_borrowed(&raw_base_style).map(|v| &**v).cloned()
|
2017-04-06 06:53:30 +03:00
|
|
|
})
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
2017-05-15 07:24:48 +03:00
|
|
|
if need_underlying_value && underlying_value.is_none() {
|
|
|
|
warn!("Underlying value should be valid when we expect to use it");
|
2017-04-06 06:53:30 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-10-27 22:38:43 +03:00
|
|
|
let raw_last_value;
|
|
|
|
let last_value = if !last_segment.mToValue.mServo.mRawPtr.is_null() {
|
|
|
|
raw_last_value = unsafe { &*last_segment.mToValue.mServo.mRawPtr };
|
|
|
|
Some(&**AnimationValue::as_arc(&raw_last_value))
|
2017-04-06 06:53:30 +03:00
|
|
|
} else {
|
2017-05-24 08:03:42 +03:00
|
|
|
None
|
2017-04-06 06:53:30 +03:00
|
|
|
};
|
|
|
|
|
2017-10-27 22:38:43 +03:00
|
|
|
let progress = unsafe { Gecko_GetProgressFromComputedTiming(computed_timing) };
|
|
|
|
let position = if segment.mToKey == segment.mFromKey {
|
|
|
|
// Note: compose_animation_segment doesn't use this value
|
|
|
|
// if segment.mFromKey == segment.mToKey, so assigning |progress| directly is fine.
|
|
|
|
progress
|
2017-04-06 06:53:30 +03:00
|
|
|
} else {
|
2017-10-27 22:38:43 +03:00
|
|
|
unsafe { Gecko_GetPositionInSegment(segment, progress, computed_timing.mBeforeFlag) }
|
2017-05-24 08:03:42 +03:00
|
|
|
};
|
|
|
|
|
2017-10-27 22:38:43 +03:00
|
|
|
let result = compose_animation_segment(segment,
|
|
|
|
underlying_value.as_ref(),
|
|
|
|
last_value,
|
|
|
|
iteration_composite,
|
|
|
|
computed_timing.mCurrentIteration,
|
|
|
|
progress,
|
|
|
|
position);
|
|
|
|
value_map.insert(property, result);
|
2017-04-06 06:53:30 +03:00
|
|
|
}
|
|
|
|
|
2017-02-10 12:34:07 +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; }
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
}
|
|
|
|
|
2017-02-09 05:39:45 +03:00
|
|
|
#[no_mangle]
|
2017-02-10 12:34:07 +03:00
|
|
|
pub extern "C" fn Servo_AnimationValue_Serialize(value: RawServoAnimationValueBorrowed,
|
|
|
|
property: nsCSSPropertyID,
|
|
|
|
buffer: *mut nsAString)
|
|
|
|
{
|
|
|
|
let uncomputed_value = AnimationValue::as_arc(&value).uncompute();
|
|
|
|
let mut string = String::new();
|
2017-03-08 14:07:04 +03:00
|
|
|
let rv = PropertyDeclarationBlock::with_one(uncomputed_value, Importance::Normal)
|
2017-08-21 07:05:57 +03:00
|
|
|
.single_value_to_css(&get_property_id_from_nscsspropertyid!(property, ()), &mut string,
|
2017-09-27 12:35:00 +03:00
|
|
|
None, None /* No extra custom properties */);
|
2017-02-10 12:34:07 +03:00
|
|
|
debug_assert!(rv.is_ok());
|
|
|
|
|
2017-06-09 02:23:56 +03:00
|
|
|
let buffer = unsafe { buffer.as_mut().unwrap() };
|
|
|
|
buffer.assign_utf8(&string);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_Shorthand_AnimationValues_Serialize(shorthand_property: nsCSSPropertyID,
|
|
|
|
values: RawGeckoServoAnimationValueListBorrowed,
|
|
|
|
buffer: *mut nsAString)
|
|
|
|
{
|
|
|
|
let property_id = get_property_id_from_nscsspropertyid!(shorthand_property, ());
|
|
|
|
let shorthand = match property_id.as_shorthand() {
|
|
|
|
Ok(shorthand) => shorthand,
|
|
|
|
_ => return,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Convert RawServoAnimationValue(s) into a vector of PropertyDeclaration
|
|
|
|
// so that we can use reference of the PropertyDeclaration without worrying
|
|
|
|
// about its lifetime. (longhands_to_css() expects &PropertyDeclaration
|
|
|
|
// iterator.)
|
|
|
|
let declarations: Vec<PropertyDeclaration> =
|
|
|
|
values.iter().map(|v| AnimationValue::as_arc(unsafe { &&*v.mRawPtr }).uncompute()).collect();
|
|
|
|
|
|
|
|
let mut string = String::new();
|
|
|
|
let rv = shorthand.longhands_to_css(declarations.iter(), &mut string);
|
|
|
|
if rv.is_ok() {
|
|
|
|
let buffer = unsafe { buffer.as_mut().unwrap() };
|
|
|
|
buffer.assign_utf8(&string);
|
|
|
|
}
|
2017-02-10 12:34:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-27 22:38:43 +03:00
|
|
|
pub extern "C" fn Servo_AnimationValue_GetOpacity(
|
|
|
|
value: RawServoAnimationValueBorrowed
|
|
|
|
) -> f32 {
|
2017-02-09 05:39:45 +03:00
|
|
|
let value = AnimationValue::as_arc(&value);
|
|
|
|
if let AnimationValue::Opacity(opacity) = **value {
|
|
|
|
opacity
|
|
|
|
} else {
|
|
|
|
panic!("The AnimationValue should be Opacity");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-27 22:38:43 +03:00
|
|
|
pub extern "C" fn Servo_AnimationValue_Opacity(
|
|
|
|
opacity: f32
|
|
|
|
) -> RawServoAnimationValueStrong {
|
|
|
|
Arc::new(AnimationValue::Opacity(opacity)).into_strong()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_AnimationValue_GetTransform(
|
|
|
|
value: RawServoAnimationValueBorrowed,
|
|
|
|
list: *mut structs::RefPtr<nsCSSValueSharedList>
|
|
|
|
) {
|
2017-02-09 05:39:45 +03:00
|
|
|
let value = AnimationValue::as_arc(&value);
|
|
|
|
if let AnimationValue::Transform(ref servo_list) = **value {
|
2017-05-20 15:24:21 +03:00
|
|
|
let list = unsafe { &mut *list };
|
2017-11-03 01:02:07 +03:00
|
|
|
if servo_list.0.is_empty() {
|
|
|
|
unsafe {
|
2017-05-20 15:24:21 +03:00
|
|
|
list.set_move(RefPtr::from_addrefed(Gecko_NewNoneTransform()));
|
|
|
|
}
|
2017-11-03 01:02:07 +03:00
|
|
|
} else {
|
2017-11-12 22:04:22 +03:00
|
|
|
gecko_properties::convert_transform(&servo_list.0, list);
|
2017-05-20 15:24:21 +03:00
|
|
|
}
|
2017-02-09 05:39:45 +03:00
|
|
|
} else {
|
|
|
|
panic!("The AnimationValue should be transform");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-27 22:38:43 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_AnimationValue_Transform(
|
|
|
|
list: *const nsCSSValueSharedList
|
|
|
|
) -> RawServoAnimationValueStrong {
|
|
|
|
let list = unsafe { (&*list).mHead.as_ref() };
|
2017-11-12 22:04:22 +03:00
|
|
|
let transform = gecko_properties::clone_transform_from_list(list);
|
2017-10-27 22:38:43 +03:00
|
|
|
Arc::new(AnimationValue::Transform(transform)).into_strong()
|
|
|
|
}
|
|
|
|
|
2017-02-24 10:16:14 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_AnimationValue_DeepEqual(this: RawServoAnimationValueBorrowed,
|
|
|
|
other: RawServoAnimationValueBorrowed)
|
|
|
|
-> bool
|
|
|
|
{
|
|
|
|
let this_value = AnimationValue::as_arc(&this);
|
|
|
|
let other_value = AnimationValue::as_arc(&other);
|
|
|
|
this_value == other_value
|
|
|
|
}
|
|
|
|
|
2017-04-12 15:00:20 +03:00
|
|
|
#[no_mangle]
|
2017-10-14 16:13:59 +03:00
|
|
|
pub extern "C" fn Servo_AnimationValue_Uncompute(
|
|
|
|
value: RawServoAnimationValueBorrowed,
|
|
|
|
) -> RawServoDeclarationBlockStrong {
|
2017-04-12 15:00:20 +03:00
|
|
|
let value = AnimationValue::as_arc(&value);
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
Arc::new(global_style_data.shared_lock.wrap(
|
|
|
|
PropertyDeclarationBlock::with_one(value.uncompute(), Importance::Normal))).into_strong()
|
|
|
|
}
|
|
|
|
|
2017-10-19 09:24:38 +03:00
|
|
|
// Return the ComputedValues by a base ComputedValues and the rules.
|
|
|
|
fn resolve_rules_for_element_with_context<'a>(
|
|
|
|
element: GeckoElement<'a>,
|
|
|
|
mut context: StyleContext<GeckoElement<'a>>,
|
|
|
|
rules: StrongRuleNode
|
|
|
|
) -> Arc<ComputedValues> {
|
2017-08-25 10:30:50 +03:00
|
|
|
use style::style_resolver::{PseudoElementResolution, StyleResolverForElement};
|
2017-07-12 10:28:44 +03:00
|
|
|
|
2017-10-19 09:24:38 +03:00
|
|
|
// This currently ignores visited styles, which seems acceptable, as
|
|
|
|
// existing browsers don't appear to animate visited styles.
|
|
|
|
let inputs =
|
|
|
|
CascadeInputs {
|
|
|
|
rules: Some(rules),
|
|
|
|
visited_rules: None,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Actually `PseudoElementResolution` doesn't matter.
|
|
|
|
StyleResolverForElement::new(element,
|
|
|
|
&mut context,
|
|
|
|
RuleInclusion::All,
|
|
|
|
PseudoElementResolution::IfApplicable)
|
|
|
|
.cascade_style_and_visited_with_default_parents(inputs).0
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleSet_GetBaseComputedValuesForElement(
|
|
|
|
raw_style_set: RawServoStyleSetBorrowed,
|
|
|
|
element: RawGeckoElementBorrowed,
|
|
|
|
computed_values: ServoStyleContextBorrowed,
|
|
|
|
snapshots: *const ServoElementSnapshotTable,
|
|
|
|
) -> ServoStyleContextStrong {
|
2017-05-10 23:08:59 +03:00
|
|
|
debug_assert!(!snapshots.is_null());
|
2017-07-21 21:05:13 +03:00
|
|
|
let computed_values = unsafe { ArcBorrow::from_ref(computed_values) };
|
2017-07-12 10:28:44 +03:00
|
|
|
|
|
|
|
let rules = match computed_values.rules {
|
2017-07-21 21:05:13 +03:00
|
|
|
None => return computed_values.clone_arc().into(),
|
2017-07-12 10:28:44 +03:00
|
|
|
Some(ref rules) => rules,
|
|
|
|
};
|
2017-04-06 06:53:30 +03:00
|
|
|
|
2017-10-19 09:24:38 +03:00
|
|
|
let doc_data = PerDocumentStyleData::from_ffi(raw_style_set).borrow();
|
|
|
|
let without_animations_rules = doc_data.stylist.rule_tree().remove_animation_rules(rules);
|
|
|
|
if without_animations_rules == *rules {
|
2017-07-21 21:05:13 +03:00
|
|
|
return computed_values.clone_arc().into();
|
2017-07-12 10:28:44 +03:00
|
|
|
}
|
|
|
|
|
2017-04-06 06:53:30 +03:00
|
|
|
let element = GeckoElement(element);
|
2017-07-12 10:28:44 +03:00
|
|
|
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
let shared = create_shared_context(&global_style_data,
|
|
|
|
&guard,
|
|
|
|
&doc_data,
|
|
|
|
TraversalFlags::empty(),
|
|
|
|
unsafe { &*snapshots });
|
|
|
|
let mut tlc = ThreadLocalStyleContext::new(&shared);
|
2017-10-19 09:24:38 +03:00
|
|
|
let context = StyleContext {
|
2017-07-12 10:28:44 +03:00
|
|
|
shared: &shared,
|
|
|
|
thread_local: &mut tlc,
|
2017-04-23 12:55:34 +03:00
|
|
|
};
|
2017-04-06 06:53:30 +03:00
|
|
|
|
2017-10-19 09:24:38 +03:00
|
|
|
resolve_rules_for_element_with_context(element, context, without_animations_rules).into()
|
|
|
|
}
|
2017-07-12 10:28:44 +03:00
|
|
|
|
2017-10-19 09:24:38 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleSet_GetComputedValuesByAddingAnimation(
|
|
|
|
raw_style_set: RawServoStyleSetBorrowed,
|
|
|
|
element: RawGeckoElementBorrowed,
|
|
|
|
computed_values: ServoStyleContextBorrowed,
|
|
|
|
snapshots: *const ServoElementSnapshotTable,
|
|
|
|
animation_value: RawServoAnimationValueBorrowed,
|
|
|
|
) -> ServoStyleContextStrong {
|
|
|
|
debug_assert!(!snapshots.is_null());
|
|
|
|
let computed_values = unsafe { ArcBorrow::from_ref(computed_values) };
|
|
|
|
let rules = match computed_values.rules {
|
|
|
|
None => return ServoStyleContextStrong::null(),
|
|
|
|
Some(ref rules) => rules,
|
|
|
|
};
|
|
|
|
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
let uncomputed_value = AnimationValue::as_arc(&animation_value).uncompute();
|
|
|
|
let doc_data = PerDocumentStyleData::from_ffi(raw_style_set).borrow();
|
|
|
|
|
|
|
|
let with_animations_rules = {
|
|
|
|
let guards = StylesheetGuards::same(&guard);
|
|
|
|
let declarations =
|
|
|
|
Arc::new(global_style_data.shared_lock.wrap(
|
|
|
|
PropertyDeclarationBlock::with_one(uncomputed_value, Importance::Normal)));
|
|
|
|
doc_data.stylist
|
|
|
|
.rule_tree()
|
|
|
|
.add_animation_rules_at_transition_level(rules, declarations, &guards)
|
|
|
|
};
|
|
|
|
|
|
|
|
let element = GeckoElement(element);
|
|
|
|
if element.borrow_data().is_none() {
|
|
|
|
return ServoStyleContextStrong::null();
|
|
|
|
}
|
|
|
|
|
|
|
|
let shared = create_shared_context(&global_style_data,
|
|
|
|
&guard,
|
|
|
|
&doc_data,
|
|
|
|
TraversalFlags::empty(),
|
|
|
|
unsafe { &*snapshots });
|
|
|
|
let mut tlc: ThreadLocalStyleContext<GeckoElement> = ThreadLocalStyleContext::new(&shared);
|
|
|
|
let context = StyleContext {
|
|
|
|
shared: &shared,
|
|
|
|
thread_local: &mut tlc,
|
|
|
|
};
|
|
|
|
|
|
|
|
resolve_rules_for_element_with_context(element, context, with_animations_rules).into()
|
2017-04-06 06:53:30 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-09-29 18:01:52 +03:00
|
|
|
pub extern "C" fn Servo_ComputedValues_ExtractAnimationValue(
|
|
|
|
computed_values: ServoStyleContextBorrowed,
|
|
|
|
property_id: nsCSSPropertyID,
|
|
|
|
) -> RawServoAnimationValueStrong {
|
|
|
|
let property = match LonghandId::from_nscsspropertyid(property_id) {
|
|
|
|
Ok(longhand) => longhand,
|
|
|
|
Err(()) => return Strong::null(),
|
2017-06-15 06:17:47 +03:00
|
|
|
};
|
|
|
|
|
2017-09-29 18:01:52 +03:00
|
|
|
match AnimationValue::from_computed_values(&property, &computed_values) {
|
|
|
|
Some(v) => Arc::new(v).into_strong(),
|
|
|
|
None => Strong::null(),
|
|
|
|
}
|
2017-04-06 06:53:30 +03:00
|
|
|
}
|
|
|
|
|
2017-04-12 15:00:20 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_Property_IsAnimatable(property: nsCSSPropertyID) -> bool {
|
|
|
|
use style::properties::animated_properties;
|
|
|
|
animated_properties::nscsspropertyid_is_animatable(property)
|
|
|
|
}
|
|
|
|
|
2017-06-15 06:17:47 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_Property_IsTransitionable(property: nsCSSPropertyID) -> bool {
|
|
|
|
use style::properties::animated_properties;
|
|
|
|
animated_properties::nscsspropertyid_is_transitionable(property)
|
|
|
|
}
|
|
|
|
|
2017-04-12 15:00:20 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_Property_IsDiscreteAnimatable(property: nsCSSPropertyID) -> bool {
|
2017-09-29 18:01:52 +03:00
|
|
|
match LonghandId::from_nscsspropertyid(property) {
|
|
|
|
Ok(longhand) => longhand.is_discrete_animatable(),
|
|
|
|
Err(()) => return false,
|
2017-06-15 06:17:47 +03:00
|
|
|
}
|
2017-04-12 15:00:20 +03:00
|
|
|
}
|
|
|
|
|
2016-07-06 04:55:36 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleWorkerThreadCount() -> u32 {
|
2017-06-23 20:37:43 +03:00
|
|
|
STYLE_THREAD_POOL.num_threads as u32
|
2016-07-06 04:55:36 +03:00
|
|
|
}
|
|
|
|
|
2016-01-19 11:49:10 +03:00
|
|
|
#[no_mangle]
|
2017-03-13 20:01:16 +03:00
|
|
|
pub extern "C" fn Servo_Element_ClearData(element: RawGeckoElementBorrowed) {
|
2017-07-15 17:44:08 +03:00
|
|
|
unsafe { GeckoElement(element).clear_data() };
|
2016-01-19 11:49:10 +03:00
|
|
|
}
|
2016-02-04 20:55:09 +03:00
|
|
|
|
2017-08-03 03:39:15 +03:00
|
|
|
#[no_mangle]
|
2017-08-31 08:31:31 +03:00
|
|
|
pub extern "C" fn Servo_Element_SizeOfExcludingThisAndCVs(malloc_size_of: GeckoMallocSizeOf,
|
2017-09-18 07:19:54 +03:00
|
|
|
malloc_enclosing_size_of:
|
|
|
|
GeckoMallocSizeOf,
|
2017-08-14 05:07:01 +03:00
|
|
|
seen_ptrs: *mut SeenPtrs,
|
|
|
|
element: RawGeckoElementBorrowed) -> usize {
|
2017-08-03 03:39:15 +03:00
|
|
|
let element = GeckoElement(element);
|
|
|
|
let borrow = element.borrow_data();
|
|
|
|
if let Some(data) = borrow {
|
servo: Merge #18452 - Overhaul MallocSizeOf and related things (from nnethercote:bug-1398737); r=jdm
This patch makes the MallocSizeOf stuff in Stylo work more like the HeapSizeOf
stuff already in Servo, except better. In particular, it adds deriving support
for MallocSizeOf, which will make it easier to improve coverage.
The patch does the following.
- Combines servo/components/style/stylesheets/memory.rs and the heapsize crate
into a new crate, malloc_size_of.
- Forks the heapsize_derive crate, calling it malloc_size_of, so that
MallocSizeOf can be derived.
- Both the new crates have MIT/Apache licenses, like heapsize, in case they are
incorporated into heapsize in the future.
- Renames the methods within MallocSizeOf and the related traits so they are
more concise.
- Removes MallocSizeOfWithGuard.
- Adds `derive(MallocSizeOf)` to a lot of types, in some cases replacing an
equivalent or almost-equivalent hand-written implementation.
- Adds stuff so that Rc/Arc can be handled properly.
<!-- Please describe your changes on the following line: -->
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [X] These changes do not require tests because tested on Gecko side.
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- 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: 7f4cb1861b172423781a369b2decca6c65d60546
--HG--
rename : servo/components/hashglobe/LICENSE-APACHE => servo/components/malloc_size_of/LICENSE-APACHE
rename : servo/components/hashglobe/LICENSE-MIT => servo/components/malloc_size_of/LICENSE-MIT
rename : servo/components/jstraceable_derive/Cargo.toml => servo/components/malloc_size_of_derive/Cargo.toml
rename : servo/components/hashglobe/LICENSE-APACHE => servo/components/malloc_size_of_derive/LICENSE-APACHE
rename : servo/components/hashglobe/LICENSE-MIT => servo/components/malloc_size_of_derive/LICENSE-MIT
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : a8254c4ae15901b764d918355e900a1e74d6eb03
2017-09-12 06:11:25 +03:00
|
|
|
let have_seen_ptr = move |ptr| { unsafe { Gecko_HaveSeenPtr(seen_ptrs, ptr) } };
|
2017-09-18 07:19:54 +03:00
|
|
|
let mut ops = MallocSizeOfOps::new(malloc_size_of.unwrap(),
|
servo: Merge #18938 - Replace all uses of the `heapsize` crate with `malloc_size_of` (from nnethercote:bug-1409255); r=SimonSapin
Servo currently uses `heapsize`, but Stylo/Gecko use `malloc_size_of`.
`malloc_size_of` is better -- it handles various cases that `heapsize` does not
-- so this patch changes Servo to use `malloc_size_of`.
This patch makes the following changes to the `malloc_size_of` crate.
- Adds `MallocSizeOf` trait implementations for numerous types, some built-in
(e.g. `VecDeque`), some external and Servo-only (e.g. `string_cache`).
- Makes `enclosing_size_of_op` optional, because vanilla jemalloc doesn't
support that operation.
- For `HashSet`/`HashMap`, falls back to a computed estimate when
`enclosing_size_of_op` isn't available.
- Adds an extern "C" `malloc_size_of` function that does the actual heap
measurement; this is based on the same functions from the `heapsize` crate.
This patch makes the following changes elsewhere.
- Converts all the uses of `heapsize` to instead use `malloc_size_of`.
- Disables the "heapsize"/"heap_size" feature for the external crates that
provide it.
- Removes the `HeapSizeOf` implementation from `hashglobe`.
- Adds `ignore` annotations to a few `Rc`/`Arc`, because `malloc_size_of`
doesn't derive those types, unlike `heapsize`.
<!-- Please describe your changes on the following line: -->
---
<!-- 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
- [ ] These changes fix https://bugzilla.mozilla.org/show_bug.cgi?id=1409255
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because testing is on the Gecko side.
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- 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: 4c538b642e4bdfbf42c522c5a59c258a6d14546e
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : f9a6feed1088d0b0be2b55d7f0c2ec9c594ac33b
2017-10-18 21:56:05 +03:00
|
|
|
Some(malloc_enclosing_size_of.unwrap()),
|
servo: Merge #18452 - Overhaul MallocSizeOf and related things (from nnethercote:bug-1398737); r=jdm
This patch makes the MallocSizeOf stuff in Stylo work more like the HeapSizeOf
stuff already in Servo, except better. In particular, it adds deriving support
for MallocSizeOf, which will make it easier to improve coverage.
The patch does the following.
- Combines servo/components/style/stylesheets/memory.rs and the heapsize crate
into a new crate, malloc_size_of.
- Forks the heapsize_derive crate, calling it malloc_size_of, so that
MallocSizeOf can be derived.
- Both the new crates have MIT/Apache licenses, like heapsize, in case they are
incorporated into heapsize in the future.
- Renames the methods within MallocSizeOf and the related traits so they are
more concise.
- Removes MallocSizeOfWithGuard.
- Adds `derive(MallocSizeOf)` to a lot of types, in some cases replacing an
equivalent or almost-equivalent hand-written implementation.
- Adds stuff so that Rc/Arc can be handled properly.
<!-- Please describe your changes on the following line: -->
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [X] These changes do not require tests because tested on Gecko side.
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- 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: 7f4cb1861b172423781a369b2decca6c65d60546
--HG--
rename : servo/components/hashglobe/LICENSE-APACHE => servo/components/malloc_size_of/LICENSE-APACHE
rename : servo/components/hashglobe/LICENSE-MIT => servo/components/malloc_size_of/LICENSE-MIT
rename : servo/components/jstraceable_derive/Cargo.toml => servo/components/malloc_size_of_derive/Cargo.toml
rename : servo/components/hashglobe/LICENSE-APACHE => servo/components/malloc_size_of_derive/LICENSE-APACHE
rename : servo/components/hashglobe/LICENSE-MIT => servo/components/malloc_size_of_derive/LICENSE-MIT
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : a8254c4ae15901b764d918355e900a1e74d6eb03
2017-09-12 06:11:25 +03:00
|
|
|
Some(Box::new(have_seen_ptr)));
|
|
|
|
(*data).size_of_excluding_cvs(&mut ops)
|
2017-08-03 03:39:15 +03:00
|
|
|
} else {
|
|
|
|
0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-14 05:07:01 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_Element_HasPrimaryComputedValues(element: RawGeckoElementBorrowed) -> bool
|
|
|
|
{
|
|
|
|
let element = GeckoElement(element);
|
|
|
|
let data = element.borrow_data().expect("Looking for CVs on unstyled element");
|
|
|
|
data.has_styles()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_Element_GetPrimaryComputedValues(element: RawGeckoElementBorrowed)
|
|
|
|
-> ServoStyleContextStrong
|
|
|
|
{
|
|
|
|
let element = GeckoElement(element);
|
|
|
|
let data = element.borrow_data().expect("Getting CVs on unstyled element");
|
|
|
|
data.styles.primary().clone().into()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_Element_HasPseudoComputedValues(element: RawGeckoElementBorrowed,
|
|
|
|
index: usize) -> bool
|
|
|
|
{
|
|
|
|
let element = GeckoElement(element);
|
|
|
|
let data = element.borrow_data().expect("Looking for CVs on unstyled element");
|
|
|
|
data.styles.pseudos.as_array()[index].is_some()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_Element_GetPseudoComputedValues(element: RawGeckoElementBorrowed,
|
|
|
|
index: usize) -> ServoStyleContextStrong
|
|
|
|
{
|
|
|
|
let element = GeckoElement(element);
|
|
|
|
let data = element.borrow_data().expect("Getting CVs that aren't present");
|
|
|
|
data.styles.pseudos.as_array()[index].as_ref().expect("Getting CVs that aren't present")
|
|
|
|
.clone().into()
|
|
|
|
}
|
|
|
|
|
2017-08-23 06:04:34 +03:00
|
|
|
#[no_mangle]
|
2017-09-20 10:05:57 +03:00
|
|
|
pub extern "C" fn Servo_Element_IsDisplayNone(element: RawGeckoElementBorrowed) -> bool {
|
2017-08-23 06:04:34 +03:00
|
|
|
let element = GeckoElement(element);
|
|
|
|
let data = element.borrow_data().expect("Invoking Servo_Element_IsDisplayNone on unstyled element");
|
|
|
|
data.styles.is_display_none()
|
|
|
|
}
|
|
|
|
|
2017-09-20 10:05:57 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_Element_IsPrimaryStyleReusedViaRuleNode(element: RawGeckoElementBorrowed) -> bool {
|
|
|
|
let element = GeckoElement(element);
|
|
|
|
let data = element.borrow_data()
|
|
|
|
.expect("Invoking Servo_Element_IsPrimaryStyleReusedViaRuleNode on unstyled element");
|
2017-10-31 02:25:45 +03:00
|
|
|
data.flags.contains(data::ElementDataFlags::PRIMARY_STYLE_REUSED_VIA_RULE_NODE)
|
2017-09-20 10:05:57 +03:00
|
|
|
}
|
|
|
|
|
2016-11-10 21:56:48 +03:00
|
|
|
#[no_mangle]
|
2017-07-02 17:00:39 +03:00
|
|
|
pub extern "C" fn Servo_StyleSheet_Empty(mode: SheetParsingMode) -> RawServoStyleSheetContentsStrong {
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
2016-11-10 21:56:48 +03:00
|
|
|
let origin = match mode {
|
|
|
|
SheetParsingMode::eAuthorSheetFeatures => Origin::Author,
|
|
|
|
SheetParsingMode::eUserSheetFeatures => Origin::User,
|
|
|
|
SheetParsingMode::eAgentSheetFeatures => Origin::UserAgent,
|
2017-05-02 07:52:36 +03:00
|
|
|
SheetParsingMode::eSafeAgentSheetFeatures => Origin::UserAgent,
|
2016-11-10 21:56:48 +03:00
|
|
|
};
|
2017-07-02 17:00:39 +03:00
|
|
|
let shared_lock = &global_style_data.shared_lock;
|
|
|
|
Arc::new(
|
|
|
|
StylesheetContents::from_str(
|
|
|
|
"",
|
|
|
|
unsafe { dummy_url_data() }.clone(),
|
|
|
|
origin,
|
|
|
|
shared_lock,
|
|
|
|
/* loader = */ None,
|
2017-07-11 04:13:44 +03:00
|
|
|
&NullReporter,
|
2017-07-02 17:00:39 +03:00
|
|
|
QuirksMode::NoQuirks,
|
|
|
|
0
|
|
|
|
)
|
2017-02-23 22:02:24 +03:00
|
|
|
).into_strong()
|
2016-11-10 21:56:48 +03:00
|
|
|
}
|
|
|
|
|
2016-02-04 20:55:09 +03:00
|
|
|
#[no_mangle]
|
2017-07-02 17:00:39 +03:00
|
|
|
pub extern "C" fn Servo_StyleSheet_FromUTF8Bytes(
|
2017-07-07 00:57:36 +03:00
|
|
|
loader: *mut Loader,
|
2017-07-02 17:00:39 +03:00
|
|
|
stylesheet: *mut ServoStyleSheet,
|
2017-09-01 20:25:54 +03:00
|
|
|
data: *const u8,
|
|
|
|
data_len: usize,
|
2017-07-02 17:00:39 +03:00
|
|
|
mode: SheetParsingMode,
|
|
|
|
extra_data: *mut URLExtraData,
|
|
|
|
line_number_offset: u32,
|
2017-08-24 22:58:49 +03:00
|
|
|
quirks_mode: nsCompatibility,
|
|
|
|
reusable_sheets: *mut LoaderReusableStyleSheets
|
2017-07-02 17:00:39 +03:00
|
|
|
) -> RawServoStyleSheetContentsStrong {
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
2017-09-01 20:25:54 +03:00
|
|
|
let input = unsafe { ::std::str::from_utf8_unchecked(::std::slice::from_raw_parts(data, data_len)) };
|
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,
|
2017-05-02 07:52:36 +03:00
|
|
|
SheetParsingMode::eSafeAgentSheetFeatures => Origin::UserAgent,
|
2016-04-30 00:27:16 +03:00
|
|
|
};
|
|
|
|
|
2017-07-11 04:13:44 +03:00
|
|
|
let reporter = ErrorReporter::new(stylesheet, loader, extra_data);
|
2017-04-03 15:05:42 +03:00
|
|
|
let url_data = unsafe { RefPtr::from_ptr_ref(&extra_data) };
|
2017-07-07 00:57:36 +03:00
|
|
|
let loader = if loader.is_null() {
|
2016-12-31 06:12:55 +03:00
|
|
|
None
|
|
|
|
} else {
|
2017-08-24 22:58:49 +03:00
|
|
|
Some(StylesheetLoader::new(loader, stylesheet, reusable_sheets))
|
2016-12-31 06:12:55 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
// FIXME(emilio): loader.as_ref() doesn't typecheck for some reason?
|
|
|
|
let loader: Option<&StyleStylesheetLoader> = match loader {
|
|
|
|
None => None,
|
|
|
|
Some(ref s) => Some(s),
|
|
|
|
};
|
|
|
|
|
2017-04-12 18:00:26 +03:00
|
|
|
|
2017-07-02 17:00:39 +03:00
|
|
|
Arc::new(StylesheetContents::from_str(
|
|
|
|
input, url_data.clone(), origin,
|
2017-07-11 04:13:44 +03:00
|
|
|
&global_style_data.shared_lock, loader, &reporter,
|
2017-08-29 06:57:13 +03:00
|
|
|
quirks_mode.into(), line_number_offset)
|
2017-02-23 22:02:24 +03:00
|
|
|
).into_strong()
|
2016-02-04 20:55:09 +03:00
|
|
|
}
|
|
|
|
|
2016-12-31 06:12:55 +03:00
|
|
|
#[no_mangle]
|
2017-07-02 17:00:39 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_AppendStyleSheet(
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
|
|
|
sheet: *const ServoStyleSheet,
|
|
|
|
) {
|
2017-05-29 22:19:16 +03:00
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
2016-10-11 20:03:29 +03:00
|
|
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
2017-08-17 19:05:32 +03:00
|
|
|
let data = &mut *data;
|
2017-05-29 22:19:16 +03:00
|
|
|
let guard = global_style_data.shared_lock.read();
|
2017-08-13 14:39:40 +03:00
|
|
|
let sheet = unsafe { GeckoStyleSheet::new(sheet) };
|
2017-08-22 19:45:42 +03:00
|
|
|
data.stylist.append_stylesheet(sheet, &guard);
|
2016-02-04 20:55:09 +03:00
|
|
|
}
|
|
|
|
|
2017-06-03 18:11:23 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleSet_MediumFeaturesChanged(
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
2017-08-03 17:36:21 +03:00
|
|
|
viewport_units_used: *mut bool,
|
2017-08-16 06:11:50 +03:00
|
|
|
) -> u8 {
|
2017-06-03 18:11:23 +03:00
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
|
|
|
|
// NOTE(emilio): We don't actually need to flush the stylist here and ensure
|
|
|
|
// it's up to date.
|
|
|
|
//
|
|
|
|
// In case it isn't we would trigger a rebuild + restyle as needed too.
|
|
|
|
//
|
|
|
|
// We need to ensure the default computed values are up to date though,
|
|
|
|
// because those can influence the result of media query evaluation.
|
|
|
|
//
|
|
|
|
// FIXME(emilio, bug 1369984): do the computation conditionally, to do it
|
|
|
|
// less often.
|
|
|
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
|
|
|
|
2017-08-03 17:36:21 +03:00
|
|
|
unsafe {
|
|
|
|
*viewport_units_used = data.stylist.device().used_viewport_size();
|
|
|
|
}
|
2017-06-03 18:11:23 +03:00
|
|
|
data.stylist.device_mut().reset_computed_values();
|
2017-09-14 23:55:21 +03:00
|
|
|
let guards = StylesheetGuards::same(&guard);
|
2017-08-14 14:42:44 +03:00
|
|
|
let origins_in_which_rules_changed =
|
2017-09-14 23:55:21 +03:00
|
|
|
data.stylist.media_features_change_changed_style(&guards);
|
2017-08-03 17:36:21 +03:00
|
|
|
|
2017-08-16 06:11:50 +03:00
|
|
|
// We'd like to return `OriginFlags` here, but bindgen bitfield enums don't
|
|
|
|
// work as return values with the Linux 32-bit ABI at the moment because
|
2017-09-04 23:19:06 +03:00
|
|
|
// they wrap the value in a struct, so for now just unwrap it.
|
|
|
|
OriginFlags::from(origins_in_which_rules_changed).0
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleSet_SetDevice(
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
|
|
|
pres_context: RawGeckoPresContextOwned
|
|
|
|
) -> u8 {
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
|
|
|
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
|
|
|
let device = Device::new(pres_context);
|
2017-09-14 23:55:21 +03:00
|
|
|
let guards = StylesheetGuards::same(&guard);
|
2017-09-04 23:19:06 +03:00
|
|
|
let origins_in_which_rules_changed =
|
2017-09-14 23:55:21 +03:00
|
|
|
data.stylist.set_device(device, &guards);
|
2017-09-04 23:19:06 +03:00
|
|
|
|
|
|
|
// We'd like to return `OriginFlags` here, but bindgen bitfield enums don't
|
|
|
|
// work as return values with the Linux 32-bit ABI at the moment because
|
2017-08-16 06:11:50 +03:00
|
|
|
// they wrap the value in a struct, so for now just unwrap it.
|
|
|
|
OriginFlags::from(origins_in_which_rules_changed).0
|
2017-06-03 18:11:23 +03:00
|
|
|
}
|
|
|
|
|
2016-02-04 20:55:09 +03:00
|
|
|
#[no_mangle]
|
2017-07-02 17:00:39 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_PrependStyleSheet(
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
|
|
|
sheet: *const ServoStyleSheet,
|
|
|
|
) {
|
2017-05-29 22:19:16 +03:00
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
2016-10-11 20:03:29 +03:00
|
|
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
2017-08-17 19:05:32 +03:00
|
|
|
let data = &mut *data;
|
2017-05-29 22:19:16 +03:00
|
|
|
let guard = global_style_data.shared_lock.read();
|
2017-08-13 14:39:40 +03:00
|
|
|
let sheet = unsafe { GeckoStyleSheet::new(sheet) };
|
2017-08-22 19:45:42 +03:00
|
|
|
data.stylist.prepend_stylesheet(sheet, &guard);
|
2016-02-04 20:55:09 +03:00
|
|
|
}
|
|
|
|
|
2016-04-29 08:37:40 +03:00
|
|
|
#[no_mangle]
|
2017-07-02 17:00:39 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_InsertStyleSheetBefore(
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
|
|
|
sheet: *const ServoStyleSheet,
|
|
|
|
before_sheet: *const ServoStyleSheet
|
|
|
|
) {
|
2017-05-29 22:19:16 +03:00
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
2016-10-11 20:03:29 +03:00
|
|
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
2017-08-17 19:05:32 +03:00
|
|
|
let data = &mut *data;
|
2017-05-29 22:19:16 +03:00
|
|
|
let guard = global_style_data.shared_lock.read();
|
2017-08-13 14:39:40 +03:00
|
|
|
let sheet = unsafe { GeckoStyleSheet::new(sheet) };
|
2017-08-22 19:45:42 +03:00
|
|
|
data.stylist.insert_stylesheet_before(
|
2017-08-13 14:39:40 +03:00
|
|
|
sheet,
|
2017-07-02 17:00:39 +03:00
|
|
|
unsafe { GeckoStyleSheet::new(before_sheet) },
|
2017-07-09 15:18:36 +03:00
|
|
|
&guard,
|
|
|
|
);
|
2016-04-29 08:37:40 +03:00
|
|
|
}
|
|
|
|
|
2017-06-21 14:36:52 +03:00
|
|
|
#[no_mangle]
|
2017-07-02 17:00:39 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_RemoveStyleSheet(
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
|
|
|
sheet: *const ServoStyleSheet
|
|
|
|
) {
|
2017-07-09 15:18:36 +03:00
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
2016-10-11 20:03:29 +03:00
|
|
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
2017-08-17 19:05:32 +03:00
|
|
|
let data = &mut *data;
|
2017-07-09 15:18:36 +03:00
|
|
|
let guard = global_style_data.shared_lock.read();
|
2017-08-13 14:39:40 +03:00
|
|
|
let sheet = unsafe { GeckoStyleSheet::new(sheet) };
|
2017-08-22 19:45:42 +03:00
|
|
|
data.stylist.remove_stylesheet(sheet, &guard);
|
2016-12-26 05:13:30 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-05-29 22:19:16 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_FlushStyleSheets(
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
2017-07-02 17:00:39 +03:00
|
|
|
doc_element: RawGeckoElementBorrowedOrNull,
|
|
|
|
) {
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
2016-12-26 05:13:30 +03:00
|
|
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
2017-05-29 22:19:16 +03:00
|
|
|
let doc_element = doc_element.map(GeckoElement);
|
2017-08-23 06:04:34 +03:00
|
|
|
let have_invalidations = data.flush_stylesheets(&guard, doc_element);
|
|
|
|
if have_invalidations && doc_element.is_some() {
|
|
|
|
// The invalidation machinery propagates the bits up, but we still
|
|
|
|
// need to tell the gecko restyle root machinery about it.
|
2017-08-31 22:14:15 +03:00
|
|
|
unsafe {
|
|
|
|
bindings::Gecko_NoteDirtySubtreeForInvalidation(doc_element.unwrap().0);
|
|
|
|
}
|
2017-08-23 06:04:34 +03:00
|
|
|
}
|
2016-02-04 20:55:09 +03:00
|
|
|
}
|
|
|
|
|
2016-12-19 08:49:28 +03:00
|
|
|
#[no_mangle]
|
2017-05-29 22:19:16 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_NoteStyleSheetsChanged(
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
2017-07-02 17:00:39 +03:00
|
|
|
author_style_disabled: bool,
|
2017-08-13 14:39:40 +03:00
|
|
|
changed_origins: OriginFlags,
|
2017-07-02 17:00:39 +03:00
|
|
|
) {
|
2016-12-19 08:49:28 +03:00
|
|
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
2017-08-22 19:45:42 +03:00
|
|
|
data.stylist.force_stylesheet_origins_dirty(OriginSet::from(changed_origins));
|
|
|
|
data.stylist.set_author_style_disabled(author_style_disabled);
|
2016-12-19 08:49:28 +03:00
|
|
|
}
|
|
|
|
|
2016-02-04 20:55:09 +03:00
|
|
|
#[no_mangle]
|
2017-07-02 17:00:39 +03:00
|
|
|
pub extern "C" fn Servo_StyleSheet_HasRules(
|
|
|
|
raw_contents: RawServoStyleSheetContentsBorrowed
|
|
|
|
) -> bool {
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
2017-07-02 17:00:39 +03:00
|
|
|
!StylesheetContents::as_arc(&raw_contents)
|
|
|
|
.rules.read_with(&guard).0.is_empty()
|
2016-02-04 20:55:09 +03:00
|
|
|
}
|
|
|
|
|
2016-11-24 02:47:18 +03:00
|
|
|
#[no_mangle]
|
2017-07-02 17:00:39 +03:00
|
|
|
pub extern "C" fn Servo_StyleSheet_GetRules(
|
|
|
|
sheet: RawServoStyleSheetContentsBorrowed
|
|
|
|
) -> ServoCssRulesStrong {
|
|
|
|
StylesheetContents::as_arc(&sheet).rules.clone().into_strong()
|
2016-11-24 02:47:18 +03:00
|
|
|
}
|
|
|
|
|
2017-05-25 07:26:23 +03:00
|
|
|
#[no_mangle]
|
2017-07-02 17:00:39 +03:00
|
|
|
pub extern "C" fn Servo_StyleSheet_Clone(
|
|
|
|
raw_sheet: RawServoStyleSheetContentsBorrowed,
|
|
|
|
reference_sheet: *const ServoStyleSheet,
|
|
|
|
) -> RawServoStyleSheetContentsStrong {
|
|
|
|
use style::shared_lock::{DeepCloneParams, DeepCloneWithLock};
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
let contents = StylesheetContents::as_arc(&raw_sheet);
|
|
|
|
let params = DeepCloneParams { reference_sheet };
|
|
|
|
|
|
|
|
Arc::new(contents.deep_clone_with_lock(
|
|
|
|
&global_style_data.shared_lock,
|
|
|
|
&guard,
|
|
|
|
¶ms,
|
|
|
|
)).into_strong()
|
2017-05-25 07:26:23 +03:00
|
|
|
}
|
|
|
|
|
servo: Merge #17044 - Introduce and start using the MallocSizeOf trait (from nnethercote:MallocSizeOf); r=emilio
MallocSizeOf is similar to the existing HeapSizeOf trait from the
heapsize crate. The only difference is that MallocSizeOf's
malloc_size_of_children() function takes an additional MallocSizeOfFn
argument, which is used to measure heap blocks. This extra argument
makes MallocSizeOf match how Gecko's memory measurements work, and is
required for Stylo to integrate with DMD.
The patch also introduces a second trait, MallocSizeOfWithGuard, which
is much the same as MallocSizeOf, but with a |guard| argument for the
global style lock.
Finally, the patch uses the new traits to measure a small amount of
Stylo's memory usage.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [X] These changes do not require tests because code is only for Gecko integration.
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- 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: aca09436b71e6defe007e1d17a9d79214d094a7b
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 1d5dc4e7ab75e8e0332922396b5b55ed67c4572e
2017-05-29 05:10:25 +03:00
|
|
|
#[no_mangle]
|
2017-07-02 17:00:39 +03:00
|
|
|
pub extern "C" fn Servo_StyleSheet_SizeOfIncludingThis(
|
2017-08-31 08:31:31 +03:00
|
|
|
malloc_size_of: GeckoMallocSizeOf,
|
2017-09-18 07:19:54 +03:00
|
|
|
malloc_enclosing_size_of: GeckoMallocSizeOf,
|
2017-07-02 17:00:39 +03:00
|
|
|
sheet: RawServoStyleSheetContentsBorrowed
|
|
|
|
) -> usize {
|
servo: Merge #17044 - Introduce and start using the MallocSizeOf trait (from nnethercote:MallocSizeOf); r=emilio
MallocSizeOf is similar to the existing HeapSizeOf trait from the
heapsize crate. The only difference is that MallocSizeOf's
malloc_size_of_children() function takes an additional MallocSizeOfFn
argument, which is used to measure heap blocks. This extra argument
makes MallocSizeOf match how Gecko's memory measurements work, and is
required for Stylo to integrate with DMD.
The patch also introduces a second trait, MallocSizeOfWithGuard, which
is much the same as MallocSizeOf, but with a |guard| argument for the
global style lock.
Finally, the patch uses the new traits to measure a small amount of
Stylo's memory usage.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [X] These changes do not require tests because code is only for Gecko integration.
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- 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: aca09436b71e6defe007e1d17a9d79214d094a7b
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 1d5dc4e7ab75e8e0332922396b5b55ed67c4572e
2017-05-29 05:10:25 +03:00
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
2017-09-18 07:19:54 +03:00
|
|
|
let mut ops = MallocSizeOfOps::new(malloc_size_of.unwrap(),
|
servo: Merge #18938 - Replace all uses of the `heapsize` crate with `malloc_size_of` (from nnethercote:bug-1409255); r=SimonSapin
Servo currently uses `heapsize`, but Stylo/Gecko use `malloc_size_of`.
`malloc_size_of` is better -- it handles various cases that `heapsize` does not
-- so this patch changes Servo to use `malloc_size_of`.
This patch makes the following changes to the `malloc_size_of` crate.
- Adds `MallocSizeOf` trait implementations for numerous types, some built-in
(e.g. `VecDeque`), some external and Servo-only (e.g. `string_cache`).
- Makes `enclosing_size_of_op` optional, because vanilla jemalloc doesn't
support that operation.
- For `HashSet`/`HashMap`, falls back to a computed estimate when
`enclosing_size_of_op` isn't available.
- Adds an extern "C" `malloc_size_of` function that does the actual heap
measurement; this is based on the same functions from the `heapsize` crate.
This patch makes the following changes elsewhere.
- Converts all the uses of `heapsize` to instead use `malloc_size_of`.
- Disables the "heapsize"/"heap_size" feature for the external crates that
provide it.
- Removes the `HeapSizeOf` implementation from `hashglobe`.
- Adds `ignore` annotations to a few `Rc`/`Arc`, because `malloc_size_of`
doesn't derive those types, unlike `heapsize`.
<!-- Please describe your changes on the following line: -->
---
<!-- 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
- [ ] These changes fix https://bugzilla.mozilla.org/show_bug.cgi?id=1409255
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because testing is on the Gecko side.
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- 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: 4c538b642e4bdfbf42c522c5a59c258a6d14546e
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : f9a6feed1088d0b0be2b55d7f0c2ec9c594ac33b
2017-10-18 21:56:05 +03:00
|
|
|
Some(malloc_enclosing_size_of.unwrap()),
|
2017-09-18 07:19:54 +03:00
|
|
|
None);
|
servo: Merge #18452 - Overhaul MallocSizeOf and related things (from nnethercote:bug-1398737); r=jdm
This patch makes the MallocSizeOf stuff in Stylo work more like the HeapSizeOf
stuff already in Servo, except better. In particular, it adds deriving support
for MallocSizeOf, which will make it easier to improve coverage.
The patch does the following.
- Combines servo/components/style/stylesheets/memory.rs and the heapsize crate
into a new crate, malloc_size_of.
- Forks the heapsize_derive crate, calling it malloc_size_of, so that
MallocSizeOf can be derived.
- Both the new crates have MIT/Apache licenses, like heapsize, in case they are
incorporated into heapsize in the future.
- Renames the methods within MallocSizeOf and the related traits so they are
more concise.
- Removes MallocSizeOfWithGuard.
- Adds `derive(MallocSizeOf)` to a lot of types, in some cases replacing an
equivalent or almost-equivalent hand-written implementation.
- Adds stuff so that Rc/Arc can be handled properly.
<!-- Please describe your changes on the following line: -->
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [X] These changes do not require tests because tested on Gecko side.
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- 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: 7f4cb1861b172423781a369b2decca6c65d60546
--HG--
rename : servo/components/hashglobe/LICENSE-APACHE => servo/components/malloc_size_of/LICENSE-APACHE
rename : servo/components/hashglobe/LICENSE-MIT => servo/components/malloc_size_of/LICENSE-MIT
rename : servo/components/jstraceable_derive/Cargo.toml => servo/components/malloc_size_of_derive/Cargo.toml
rename : servo/components/hashglobe/LICENSE-APACHE => servo/components/malloc_size_of_derive/LICENSE-APACHE
rename : servo/components/hashglobe/LICENSE-MIT => servo/components/malloc_size_of_derive/LICENSE-MIT
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : a8254c4ae15901b764d918355e900a1e74d6eb03
2017-09-12 06:11:25 +03:00
|
|
|
StylesheetContents::as_arc(&sheet).size_of(&guard, &mut ops)
|
servo: Merge #17044 - Introduce and start using the MallocSizeOf trait (from nnethercote:MallocSizeOf); r=emilio
MallocSizeOf is similar to the existing HeapSizeOf trait from the
heapsize crate. The only difference is that MallocSizeOf's
malloc_size_of_children() function takes an additional MallocSizeOfFn
argument, which is used to measure heap blocks. This extra argument
makes MallocSizeOf match how Gecko's memory measurements work, and is
required for Stylo to integrate with DMD.
The patch also introduces a second trait, MallocSizeOfWithGuard, which
is much the same as MallocSizeOf, but with a |guard| argument for the
global style lock.
Finally, the patch uses the new traits to measure a small amount of
Stylo's memory usage.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [X] These changes do not require tests because code is only for Gecko integration.
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- 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: aca09436b71e6defe007e1d17a9d79214d094a7b
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 1d5dc4e7ab75e8e0332922396b5b55ed67c4572e
2017-05-29 05:10:25 +03:00
|
|
|
}
|
|
|
|
|
2017-08-13 14:39:40 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleSheet_GetOrigin(
|
|
|
|
sheet: RawServoStyleSheetContentsBorrowed
|
2017-08-22 21:42:39 +03:00
|
|
|
) -> u8 {
|
|
|
|
let origin = match StylesheetContents::as_arc(&sheet).origin {
|
2017-08-13 14:39:40 +03:00
|
|
|
Origin::UserAgent => OriginFlags_UserAgent,
|
|
|
|
Origin::User => OriginFlags_User,
|
|
|
|
Origin::Author => OriginFlags_Author,
|
2017-08-22 21:42:39 +03:00
|
|
|
};
|
|
|
|
// We'd like to return `OriginFlags` here, but bindgen bitfield enums don't
|
|
|
|
// work as return values with the Linux 32-bit ABI at the moment because
|
|
|
|
// they wrap the value in a struct, so for now just unwrap it.
|
|
|
|
origin.0
|
2017-08-13 14:39:40 +03:00
|
|
|
}
|
|
|
|
|
2017-08-17 16:08:16 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleSheet_GetSourceMapURL(
|
|
|
|
sheet: RawServoStyleSheetContentsBorrowed,
|
|
|
|
result: *mut nsAString
|
|
|
|
) {
|
|
|
|
let contents = StylesheetContents::as_arc(&sheet);
|
|
|
|
let url_opt = contents.source_map_url.read();
|
|
|
|
if let Some(ref url) = *url_opt {
|
|
|
|
write!(unsafe { &mut *result }, "{}", url).unwrap();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-15 22:44:03 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleSheet_GetSourceURL(
|
|
|
|
sheet: RawServoStyleSheetContentsBorrowed,
|
|
|
|
result: *mut nsAString
|
|
|
|
) {
|
|
|
|
let contents = StylesheetContents::as_arc(&sheet);
|
|
|
|
let url_opt = contents.source_url.read();
|
|
|
|
if let Some(ref url) = *url_opt {
|
|
|
|
write!(unsafe { &mut *result }, "{}", url).unwrap();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-22 14:17:09 +03:00
|
|
|
fn read_locked_arc<T, R, F>(raw: &<Locked<T> as HasFFI>::FFIType, func: F) -> R
|
|
|
|
where Locked<T>: HasArcFFI, F: FnOnce(&T) -> R
|
|
|
|
{
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
func(Locked::<T>::as_arc(&raw).read_with(&guard))
|
|
|
|
}
|
|
|
|
|
2017-09-06 07:20:55 +03:00
|
|
|
#[cfg(debug_assertions)]
|
|
|
|
unsafe fn read_locked_arc_unchecked<T, R, F>(raw: &<Locked<T> as HasFFI>::FFIType, func: F) -> R
|
|
|
|
where Locked<T>: HasArcFFI, F: FnOnce(&T) -> R
|
|
|
|
{
|
|
|
|
read_locked_arc(raw, func)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(debug_assertions))]
|
|
|
|
unsafe fn read_locked_arc_unchecked<T, R, F>(raw: &<Locked<T> as HasFFI>::FFIType, func: F) -> R
|
|
|
|
where Locked<T>: HasArcFFI, F: FnOnce(&T) -> R
|
|
|
|
{
|
|
|
|
func(Locked::<T>::as_arc(&raw).read_unchecked())
|
|
|
|
}
|
|
|
|
|
2017-03-22 14:17:09 +03:00
|
|
|
fn write_locked_arc<T, R, F>(raw: &<Locked<T> as HasFFI>::FFIType, func: F) -> R
|
|
|
|
where Locked<T>: HasArcFFI, F: FnOnce(&mut T) -> R
|
|
|
|
{
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let mut guard = global_style_data.shared_lock.write();
|
|
|
|
func(Locked::<T>::as_arc(&raw).write_with(&mut guard))
|
|
|
|
}
|
|
|
|
|
2016-11-24 02:47:18 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_CssRules_ListTypes(rules: ServoCssRulesBorrowed,
|
2017-03-13 20:01:16 +03:00
|
|
|
result: nsTArrayBorrowed_uintptr_t) {
|
2017-03-22 14:17:09 +03:00
|
|
|
read_locked_arc(rules, |rules: &CssRules| {
|
|
|
|
let iter = rules.0.iter().map(|rule| rule.rule_type() as usize);
|
|
|
|
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);
|
|
|
|
})
|
2016-11-24 02:47:18 +03:00
|
|
|
}
|
|
|
|
|
2016-12-01 08:54:46 +03:00
|
|
|
#[no_mangle]
|
2017-07-02 17:00:39 +03:00
|
|
|
pub extern "C" fn Servo_CssRules_InsertRule(
|
|
|
|
rules: ServoCssRulesBorrowed,
|
|
|
|
contents: RawServoStyleSheetContentsBorrowed,
|
|
|
|
rule: *const nsACString,
|
|
|
|
index: u32,
|
|
|
|
nested: bool,
|
|
|
|
loader: *mut Loader,
|
|
|
|
gecko_stylesheet: *mut ServoStyleSheet,
|
|
|
|
rule_type: *mut u16,
|
|
|
|
) -> nsresult {
|
2017-04-03 15:05:42 +03:00
|
|
|
let loader = if loader.is_null() {
|
|
|
|
None
|
|
|
|
} else {
|
2017-06-05 11:44:53 +03:00
|
|
|
Some(StylesheetLoader::new(loader, gecko_stylesheet, ptr::null_mut()))
|
2017-04-03 15:05:42 +03:00
|
|
|
};
|
|
|
|
let loader = loader.as_ref().map(|loader| loader as &StyleStylesheetLoader);
|
2016-12-01 08:54:46 +03:00
|
|
|
let rule = unsafe { rule.as_ref().unwrap().as_str_unchecked() };
|
2017-04-12 18:00:26 +03:00
|
|
|
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
2017-07-02 17:00:39 +03:00
|
|
|
let contents = StylesheetContents::as_arc(&contents);
|
|
|
|
let result = Locked::<CssRules>::as_arc(&rules).insert_rule(
|
|
|
|
&global_style_data.shared_lock,
|
|
|
|
rule,
|
|
|
|
contents,
|
|
|
|
index as usize,
|
|
|
|
nested,
|
|
|
|
loader
|
|
|
|
);
|
|
|
|
|
|
|
|
match result {
|
2017-04-12 18:00:26 +03:00
|
|
|
Ok(new_rule) => {
|
|
|
|
*unsafe { rule_type.as_mut().unwrap() } = new_rule.rule_type() as u16;
|
|
|
|
nsresult::NS_OK
|
2016-12-01 08:54:46 +03:00
|
|
|
}
|
2017-04-12 18:00:26 +03:00
|
|
|
Err(err) => err.into(),
|
|
|
|
}
|
2016-12-01 08:54:46 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-07-02 17:00:39 +03:00
|
|
|
pub extern "C" fn Servo_CssRules_DeleteRule(
|
|
|
|
rules: ServoCssRulesBorrowed,
|
|
|
|
index: u32
|
|
|
|
) -> nsresult {
|
2017-03-22 14:17:09 +03:00
|
|
|
write_locked_arc(rules, |rules: &mut CssRules| {
|
|
|
|
match rules.remove_rule(index as usize) {
|
|
|
|
Ok(_) => nsresult::NS_OK,
|
|
|
|
Err(err) => err.into()
|
|
|
|
}
|
|
|
|
})
|
2016-12-01 08:54:46 +03:00
|
|
|
}
|
|
|
|
|
2017-05-19 07:49:30 +03:00
|
|
|
macro_rules! impl_basic_rule_funcs_without_getter {
|
|
|
|
{ ($rule_type:ty, $raw_type:ty),
|
|
|
|
debug: $debug:ident,
|
|
|
|
to_css: $to_css:ident,
|
|
|
|
} => {
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn $debug(rule: &$raw_type, result: *mut nsACString) {
|
|
|
|
read_locked_arc(rule, |rule: &$rule_type| {
|
|
|
|
write!(unsafe { result.as_mut().unwrap() }, "{:?}", *rule).unwrap();
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn $to_css(rule: &$raw_type, result: *mut nsAString) {
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
let rule = Locked::<$rule_type>::as_arc(&rule);
|
|
|
|
rule.read_with(&guard).to_css(&guard, unsafe { result.as_mut().unwrap() }).unwrap();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-15 13:58:06 +03:00
|
|
|
macro_rules! impl_basic_rule_funcs {
|
|
|
|
{ ($name:ident, $rule_type:ty, $raw_type:ty),
|
|
|
|
getter: $getter:ident,
|
|
|
|
debug: $debug:ident,
|
|
|
|
to_css: $to_css:ident,
|
|
|
|
} => {
|
|
|
|
#[no_mangle]
|
2017-05-15 13:28:50 +03:00
|
|
|
pub extern "C" fn $getter(rules: ServoCssRulesBorrowed, index: u32,
|
|
|
|
line: *mut u32, column: *mut u32)
|
|
|
|
-> Strong<$raw_type> {
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
let rules = Locked::<CssRules>::as_arc(&rules).read_with(&guard);
|
2017-07-02 17:00:39 +03:00
|
|
|
let index = index as usize;
|
|
|
|
|
|
|
|
if index >= rules.0.len() {
|
|
|
|
return Strong::null();
|
|
|
|
}
|
|
|
|
|
|
|
|
match rules.0[index] {
|
2017-05-15 13:28:50 +03:00
|
|
|
CssRule::$name(ref rule) => {
|
|
|
|
let location = rule.read_with(&guard).source_location;
|
|
|
|
*unsafe { line.as_mut().unwrap() } = location.line as u32;
|
|
|
|
*unsafe { column.as_mut().unwrap() } = location.column as u32;
|
|
|
|
rule.clone().into_strong()
|
|
|
|
},
|
|
|
|
_ => {
|
2017-07-02 17:00:39 +03:00
|
|
|
Strong::null()
|
2017-03-15 13:58:06 +03:00
|
|
|
}
|
2017-05-15 13:28:50 +03:00
|
|
|
}
|
2017-03-15 13:58:06 +03:00
|
|
|
}
|
|
|
|
|
2017-05-19 07:49:30 +03:00
|
|
|
impl_basic_rule_funcs_without_getter! { ($rule_type, $raw_type),
|
|
|
|
debug: $debug,
|
|
|
|
to_css: $to_css,
|
2017-03-15 13:58:06 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-28 13:11:04 +03:00
|
|
|
macro_rules! impl_group_rule_funcs {
|
|
|
|
{ ($name:ident, $rule_type:ty, $raw_type:ty),
|
|
|
|
get_rules: $get_rules:ident,
|
|
|
|
$($basic:tt)+
|
|
|
|
} => {
|
|
|
|
impl_basic_rule_funcs! { ($name, $rule_type, $raw_type), $($basic)+ }
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn $get_rules(rule: &$raw_type) -> ServoCssRulesStrong {
|
|
|
|
read_locked_arc(rule, |rule: &$rule_type| {
|
|
|
|
rule.rules.clone().into_strong()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-15 13:58:06 +03:00
|
|
|
impl_basic_rule_funcs! { (Style, StyleRule, RawServoStyleRule),
|
|
|
|
getter: Servo_CssRules_GetStyleRuleAt,
|
|
|
|
debug: Servo_StyleRule_Debug,
|
|
|
|
to_css: Servo_StyleRule_GetCssText,
|
|
|
|
}
|
|
|
|
|
2017-05-30 02:51:45 +03:00
|
|
|
impl_basic_rule_funcs! { (Import, ImportRule, RawServoImportRule),
|
|
|
|
getter: Servo_CssRules_GetImportRuleAt,
|
|
|
|
debug: Servo_ImportRule_Debug,
|
|
|
|
to_css: Servo_ImportRule_GetCssText,
|
|
|
|
}
|
|
|
|
|
2017-05-19 07:49:30 +03:00
|
|
|
impl_basic_rule_funcs_without_getter! { (Keyframe, RawServoKeyframe),
|
|
|
|
debug: Servo_Keyframe_Debug,
|
|
|
|
to_css: Servo_Keyframe_GetCssText,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl_basic_rule_funcs! { (Keyframes, KeyframesRule, RawServoKeyframesRule),
|
|
|
|
getter: Servo_CssRules_GetKeyframesRuleAt,
|
|
|
|
debug: Servo_KeyframesRule_Debug,
|
|
|
|
to_css: Servo_KeyframesRule_GetCssText,
|
|
|
|
}
|
|
|
|
|
2017-04-28 13:11:04 +03:00
|
|
|
impl_group_rule_funcs! { (Media, MediaRule, RawServoMediaRule),
|
|
|
|
get_rules: Servo_MediaRule_GetRules,
|
2017-03-15 13:58:06 +03:00
|
|
|
getter: Servo_CssRules_GetMediaRuleAt,
|
|
|
|
debug: Servo_MediaRule_Debug,
|
|
|
|
to_css: Servo_MediaRule_GetCssText,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl_basic_rule_funcs! { (Namespace, NamespaceRule, RawServoNamespaceRule),
|
|
|
|
getter: Servo_CssRules_GetNamespaceRuleAt,
|
|
|
|
debug: Servo_NamespaceRule_Debug,
|
|
|
|
to_css: Servo_NamespaceRule_GetCssText,
|
2016-11-24 02:47:18 +03:00
|
|
|
}
|
|
|
|
|
2017-04-10 05:47:59 +03:00
|
|
|
impl_basic_rule_funcs! { (Page, PageRule, RawServoPageRule),
|
|
|
|
getter: Servo_CssRules_GetPageRuleAt,
|
|
|
|
debug: Servo_PageRule_Debug,
|
|
|
|
to_css: Servo_PageRule_GetCssText,
|
|
|
|
}
|
|
|
|
|
2017-04-28 13:11:04 +03:00
|
|
|
impl_group_rule_funcs! { (Supports, SupportsRule, RawServoSupportsRule),
|
|
|
|
get_rules: Servo_SupportsRule_GetRules,
|
|
|
|
getter: Servo_CssRules_GetSupportsRuleAt,
|
|
|
|
debug: Servo_SupportsRule_Debug,
|
|
|
|
to_css: Servo_SupportsRule_GetCssText,
|
|
|
|
}
|
|
|
|
|
2017-05-11 14:27:42 +03:00
|
|
|
impl_group_rule_funcs! { (Document, DocumentRule, RawServoDocumentRule),
|
|
|
|
get_rules: Servo_DocumentRule_GetRules,
|
|
|
|
getter: Servo_CssRules_GetDocumentRuleAt,
|
|
|
|
debug: Servo_DocumentRule_Debug,
|
|
|
|
to_css: Servo_DocumentRule_GetCssText,
|
|
|
|
}
|
|
|
|
|
2017-07-28 00:15:02 +03:00
|
|
|
impl_basic_rule_funcs! { (FontFeatureValues, FontFeatureValuesRule, RawServoFontFeatureValuesRule),
|
|
|
|
getter: Servo_CssRules_GetFontFeatureValuesRuleAt,
|
|
|
|
debug: Servo_FontFeatureValuesRule_Debug,
|
|
|
|
to_css: Servo_FontFeatureValuesRule_GetCssText,
|
|
|
|
}
|
|
|
|
|
2017-05-16 09:17:07 +03:00
|
|
|
macro_rules! impl_getter_for_embedded_rule {
|
|
|
|
($getter:ident: $name:ident -> $ty:ty) => {
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn $getter(rules: ServoCssRulesBorrowed, index: u32) -> *mut $ty
|
|
|
|
{
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
let rules = Locked::<CssRules>::as_arc(&rules).read_with(&guard);
|
|
|
|
match rules.0[index as usize] {
|
|
|
|
CssRule::$name(ref rule) => rule.read_with(&guard).get(),
|
|
|
|
_ => unreachable!(concat!(stringify!($getter), " should only be called on a ",
|
|
|
|
stringify!($name), " rule")),
|
|
|
|
}
|
|
|
|
}
|
2017-03-30 04:50:47 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-16 09:17:07 +03:00
|
|
|
impl_getter_for_embedded_rule!(Servo_CssRules_GetFontFaceRuleAt:
|
|
|
|
FontFace -> nsCSSFontFaceRule);
|
|
|
|
impl_getter_for_embedded_rule!(Servo_CssRules_GetCounterStyleRuleAt:
|
|
|
|
CounterStyle -> nsCSSCounterStyleRule);
|
|
|
|
|
2016-11-24 02:47:18 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleRule_GetStyle(rule: RawServoStyleRuleBorrowed) -> RawServoDeclarationBlockStrong {
|
2017-03-22 14:17:09 +03:00
|
|
|
read_locked_arc(rule, |rule: &StyleRule| {
|
|
|
|
rule.block.clone().into_strong()
|
|
|
|
})
|
2016-11-24 02:47:18 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleRule_SetStyle(rule: RawServoStyleRuleBorrowed,
|
2017-03-13 20:01:16 +03:00
|
|
|
declarations: RawServoDeclarationBlockBorrowed) {
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
let declarations = Locked::<PropertyDeclarationBlock>::as_arc(&declarations);
|
2017-03-22 14:17:09 +03:00
|
|
|
write_locked_arc(rule, |rule: &mut StyleRule| {
|
2017-07-18 05:44:25 +03:00
|
|
|
rule.block = declarations.clone_arc();
|
2017-03-22 14:17:09 +03:00
|
|
|
})
|
2016-11-24 02:47:18 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-03-13 20:01:16 +03:00
|
|
|
pub extern "C" fn Servo_StyleRule_GetSelectorText(rule: RawServoStyleRuleBorrowed, result: *mut nsAString) {
|
2017-03-22 14:17:09 +03:00
|
|
|
read_locked_arc(rule, |rule: &StyleRule| {
|
|
|
|
rule.selectors.to_css(unsafe { result.as_mut().unwrap() }).unwrap();
|
|
|
|
})
|
2016-11-24 02:47:18 +03:00
|
|
|
}
|
|
|
|
|
2017-06-07 19:54:47 +03:00
|
|
|
#[no_mangle]
|
2017-06-12 15:46:11 +03:00
|
|
|
pub extern "C" fn Servo_StyleRule_GetSelectorTextAtIndex(rule: RawServoStyleRuleBorrowed,
|
|
|
|
index: u32,
|
|
|
|
result: *mut nsAString) {
|
2017-06-07 19:54:47 +03:00
|
|
|
read_locked_arc(rule, |rule: &StyleRule| {
|
2017-06-12 15:46:11 +03:00
|
|
|
let index = index as usize;
|
|
|
|
if index >= rule.selectors.0.len() {
|
|
|
|
return;
|
|
|
|
}
|
2017-07-13 14:15:15 +03:00
|
|
|
rule.selectors.0[index].to_css(unsafe { result.as_mut().unwrap() }).unwrap();
|
2017-06-07 19:54:47 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleRule_GetSelectorCount(rule: RawServoStyleRuleBorrowed, count: *mut u32) {
|
|
|
|
read_locked_arc(rule, |rule: &StyleRule| {
|
|
|
|
*unsafe { count.as_mut().unwrap() } = rule.selectors.0.len() as u32;
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-06-12 15:46:11 +03:00
|
|
|
#[no_mangle]
|
2017-07-02 17:00:39 +03:00
|
|
|
pub extern "C" fn Servo_StyleRule_GetSpecificityAtIndex(
|
|
|
|
rule: RawServoStyleRuleBorrowed,
|
|
|
|
index: u32,
|
|
|
|
specificity: *mut u64
|
|
|
|
) {
|
2017-06-12 15:46:11 +03:00
|
|
|
read_locked_arc(rule, |rule: &StyleRule| {
|
2017-08-17 19:05:32 +03:00
|
|
|
let specificity = unsafe { specificity.as_mut().unwrap() };
|
2017-06-12 15:46:11 +03:00
|
|
|
let index = index as usize;
|
|
|
|
if index >= rule.selectors.0.len() {
|
|
|
|
*specificity = 0;
|
|
|
|
return;
|
|
|
|
}
|
2017-07-13 14:15:15 +03:00
|
|
|
*specificity = rule.selectors.0[index].specificity() as u64;
|
2017-06-12 15:46:11 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-07-04 15:08:03 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleRule_SelectorMatchesElement(rule: RawServoStyleRuleBorrowed,
|
|
|
|
element: RawGeckoElementBorrowed,
|
|
|
|
index: u32,
|
|
|
|
pseudo_type: CSSPseudoElementType) -> bool {
|
|
|
|
read_locked_arc(rule, |rule: &StyleRule| {
|
|
|
|
let index = index as usize;
|
|
|
|
if index >= rule.selectors.0.len() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-07-13 14:15:15 +03:00
|
|
|
let selector = &rule.selectors.0[index];
|
2017-07-04 15:08:03 +03:00
|
|
|
let mut matching_mode = MatchingMode::Normal;
|
|
|
|
|
|
|
|
match PseudoElement::from_pseudo_type(pseudo_type) {
|
|
|
|
Some(pseudo) => {
|
|
|
|
// We need to make sure that the requested pseudo element type
|
|
|
|
// matches the selector pseudo element type before proceeding.
|
2017-07-13 14:15:15 +03:00
|
|
|
match selector.pseudo_element() {
|
2017-07-04 15:08:03 +03:00
|
|
|
Some(selector_pseudo) if *selector_pseudo == pseudo => {
|
|
|
|
matching_mode = MatchingMode::ForStatelessPseudoElement
|
|
|
|
},
|
|
|
|
_ => return false,
|
|
|
|
};
|
|
|
|
},
|
|
|
|
None => {
|
|
|
|
// Do not attempt to match if a pseudo element is requested and
|
|
|
|
// this is not a pseudo element selector, or vice versa.
|
2017-07-13 14:15:15 +03:00
|
|
|
if selector.has_pseudo_element() {
|
2017-07-04 15:08:03 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
let element = GeckoElement(element);
|
2017-10-26 15:51:21 +03:00
|
|
|
let quirks_mode = element.as_node().owner_doc().quirks_mode();
|
|
|
|
let mut ctx =
|
|
|
|
MatchingContext::new(matching_mode, None, None, quirks_mode);
|
2017-07-13 14:15:15 +03:00
|
|
|
matches_selector(selector, 0, None, &element, &mut ctx, &mut |_, _| {})
|
2017-07-04 15:08:03 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-10-13 15:22:43 +03:00
|
|
|
#[no_mangle]
|
2017-10-14 16:13:59 +03:00
|
|
|
pub unsafe extern "C" fn Servo_SelectorList_Closest(
|
|
|
|
element: RawGeckoElementBorrowed,
|
2017-10-13 15:22:43 +03:00
|
|
|
selectors: RawServoSelectorListBorrowed,
|
2017-10-14 16:13:59 +03:00
|
|
|
) -> *const structs::RawGeckoElement {
|
2017-10-13 15:22:43 +03:00
|
|
|
use std::borrow::Borrow;
|
2017-10-13 18:48:57 +03:00
|
|
|
use style::dom_apis;
|
2017-10-13 15:22:43 +03:00
|
|
|
|
|
|
|
let element = GeckoElement(element);
|
2017-10-26 15:51:21 +03:00
|
|
|
let quirks_mode = element.as_node().owner_doc().quirks_mode();
|
2017-10-13 15:22:43 +03:00
|
|
|
let selectors = ::selectors::SelectorList::from_ffi(selectors).borrow();
|
|
|
|
|
2017-10-26 15:51:21 +03:00
|
|
|
dom_apis::element_closest(element, &selectors, quirks_mode)
|
2017-10-14 16:13:59 +03:00
|
|
|
.map_or(ptr::null(), |e| e.0)
|
2017-10-13 15:22:43 +03:00
|
|
|
}
|
|
|
|
|
2017-10-03 16:05:07 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub unsafe extern "C" fn Servo_SelectorList_Matches(
|
|
|
|
element: RawGeckoElementBorrowed,
|
2017-10-10 09:20:38 +03:00
|
|
|
selectors: RawServoSelectorListBorrowed,
|
2017-10-03 16:05:07 +03:00
|
|
|
) -> bool {
|
2017-10-10 09:20:38 +03:00
|
|
|
use std::borrow::Borrow;
|
2017-10-13 18:48:57 +03:00
|
|
|
use style::dom_apis;
|
2017-10-10 09:20:38 +03:00
|
|
|
|
2017-10-03 16:05:07 +03:00
|
|
|
let element = GeckoElement(element);
|
2017-10-26 15:51:21 +03:00
|
|
|
let quirks_mode = element.as_node().owner_doc().quirks_mode();
|
2017-10-10 09:20:38 +03:00
|
|
|
let selectors = ::selectors::SelectorList::from_ffi(selectors).borrow();
|
2017-10-13 18:48:57 +03:00
|
|
|
dom_apis::element_matches(
|
|
|
|
&element,
|
|
|
|
&selectors,
|
2017-10-26 15:51:21 +03:00
|
|
|
quirks_mode,
|
2017-10-13 18:48:57 +03:00
|
|
|
)
|
2017-10-03 16:05:07 +03:00
|
|
|
}
|
|
|
|
|
2017-10-23 16:14:35 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub unsafe extern "C" fn Servo_SelectorList_QueryFirst(
|
|
|
|
node: RawGeckoNodeBorrowed,
|
|
|
|
selectors: RawServoSelectorListBorrowed,
|
2017-11-04 13:36:17 +03:00
|
|
|
may_use_invalidation: bool,
|
2017-10-23 16:14:35 +03:00
|
|
|
) -> *const structs::RawGeckoElement {
|
|
|
|
use std::borrow::Borrow;
|
2017-11-04 13:36:17 +03:00
|
|
|
use style::dom_apis::{self, MayUseInvalidation, QueryFirst};
|
2017-10-23 16:14:35 +03:00
|
|
|
|
|
|
|
let node = GeckoNode(node);
|
|
|
|
let selectors = ::selectors::SelectorList::from_ffi(selectors).borrow();
|
|
|
|
let mut result = None;
|
2017-11-04 13:36:17 +03:00
|
|
|
|
|
|
|
let may_use_invalidation =
|
|
|
|
if may_use_invalidation {
|
|
|
|
MayUseInvalidation::Yes
|
|
|
|
} else {
|
|
|
|
MayUseInvalidation::No
|
|
|
|
};
|
|
|
|
|
2017-10-23 16:14:35 +03:00
|
|
|
dom_apis::query_selector::<GeckoElement, QueryFirst>(
|
|
|
|
node,
|
|
|
|
&selectors,
|
|
|
|
&mut result,
|
2017-11-04 13:36:17 +03:00
|
|
|
may_use_invalidation,
|
2017-10-23 16:14:35 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
result.map_or(ptr::null(), |e| e.0)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub unsafe extern "C" fn Servo_SelectorList_QueryAll(
|
|
|
|
node: RawGeckoNodeBorrowed,
|
|
|
|
selectors: RawServoSelectorListBorrowed,
|
|
|
|
content_list: *mut structs::nsSimpleContentList,
|
2017-11-04 13:36:17 +03:00
|
|
|
may_use_invalidation: bool,
|
2017-10-23 16:14:35 +03:00
|
|
|
) {
|
|
|
|
use smallvec::SmallVec;
|
|
|
|
use std::borrow::Borrow;
|
2017-11-04 13:36:17 +03:00
|
|
|
use style::dom_apis::{self, MayUseInvalidation, QueryAll};
|
2017-10-23 16:14:35 +03:00
|
|
|
|
|
|
|
let node = GeckoNode(node);
|
|
|
|
let selectors = ::selectors::SelectorList::from_ffi(selectors).borrow();
|
|
|
|
let mut result = SmallVec::new();
|
|
|
|
|
2017-11-04 13:36:17 +03:00
|
|
|
let may_use_invalidation =
|
|
|
|
if may_use_invalidation {
|
|
|
|
MayUseInvalidation::Yes
|
|
|
|
} else {
|
|
|
|
MayUseInvalidation::No
|
|
|
|
};
|
|
|
|
|
2017-10-23 16:14:35 +03:00
|
|
|
dom_apis::query_selector::<GeckoElement, QueryAll>(
|
|
|
|
node,
|
|
|
|
&selectors,
|
|
|
|
&mut result,
|
2017-11-04 13:36:17 +03:00
|
|
|
may_use_invalidation,
|
2017-10-23 16:14:35 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
if !result.is_empty() {
|
|
|
|
// NOTE(emilio): This relies on a slice of GeckoElement having the same
|
|
|
|
// memory representation than a slice of element pointers.
|
|
|
|
bindings::Gecko_ContentList_AppendAll(
|
|
|
|
content_list,
|
|
|
|
result.as_ptr() as *mut *const _,
|
|
|
|
result.len(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-30 02:51:45 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_ImportRule_GetHref(rule: RawServoImportRuleBorrowed, result: *mut nsAString) {
|
|
|
|
read_locked_arc(rule, |rule: &ImportRule| {
|
|
|
|
write!(unsafe { &mut *result }, "{}", rule.url.as_str()).unwrap();
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-07-02 17:00:39 +03:00
|
|
|
pub extern "C" fn Servo_ImportRule_GetSheet(
|
|
|
|
rule: RawServoImportRuleBorrowed
|
|
|
|
) -> *const ServoStyleSheet {
|
2017-05-30 02:51:45 +03:00
|
|
|
read_locked_arc(rule, |rule: &ImportRule| {
|
2017-07-02 17:00:39 +03:00
|
|
|
rule.stylesheet.0.raw() as *const ServoStyleSheet
|
2017-05-30 02:51:45 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-05-19 07:49:30 +03:00
|
|
|
#[no_mangle]
|
2017-07-02 17:00:39 +03:00
|
|
|
pub extern "C" fn Servo_Keyframe_GetKeyText(
|
|
|
|
keyframe: RawServoKeyframeBorrowed,
|
|
|
|
result: *mut nsAString
|
|
|
|
) {
|
2017-05-19 07:49:30 +03:00
|
|
|
read_locked_arc(keyframe, |keyframe: &Keyframe| {
|
|
|
|
keyframe.selector.to_css(unsafe { result.as_mut().unwrap() }).unwrap()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_Keyframe_SetKeyText(keyframe: RawServoKeyframeBorrowed, text: *const nsACString) -> bool {
|
|
|
|
let text = unsafe { text.as_ref().unwrap().as_str_unchecked() };
|
2017-06-10 00:31:48 +03:00
|
|
|
let mut input = ParserInput::new(&text);
|
|
|
|
if let Ok(selector) = Parser::new(&mut input).parse_entirely(KeyframeSelector::parse) {
|
2017-05-19 07:49:30 +03:00
|
|
|
write_locked_arc(keyframe, |keyframe: &mut Keyframe| {
|
|
|
|
keyframe.selector = selector;
|
|
|
|
});
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_Keyframe_GetStyle(keyframe: RawServoKeyframeBorrowed) -> RawServoDeclarationBlockStrong {
|
|
|
|
read_locked_arc(keyframe, |keyframe: &Keyframe| keyframe.block.clone().into_strong())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_Keyframe_SetStyle(keyframe: RawServoKeyframeBorrowed,
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed) {
|
|
|
|
let declarations = Locked::<PropertyDeclarationBlock>::as_arc(&declarations);
|
|
|
|
write_locked_arc(keyframe, |keyframe: &mut Keyframe| {
|
2017-07-18 05:44:25 +03:00
|
|
|
keyframe.block = declarations.clone_arc();
|
2017-05-19 07:49:30 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-09 03:10:40 +03:00
|
|
|
pub extern "C" fn Servo_KeyframesRule_GetName(rule: RawServoKeyframesRuleBorrowed) -> *mut nsAtom {
|
2017-05-19 07:49:30 +03:00
|
|
|
read_locked_arc(rule, |rule: &KeyframesRule| rule.name.as_atom().as_ptr())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-09 03:10:40 +03:00
|
|
|
pub extern "C" fn Servo_KeyframesRule_SetName(rule: RawServoKeyframesRuleBorrowed, name: *mut nsAtom) {
|
2017-05-19 07:49:30 +03:00
|
|
|
write_locked_arc(rule, |rule: &mut KeyframesRule| {
|
2017-05-21 23:40:41 +03:00
|
|
|
rule.name = KeyframesName::Ident(CustomIdent(unsafe { Atom::from_addrefed(name) }));
|
2017-05-19 07:49:30 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_KeyframesRule_GetCount(rule: RawServoKeyframesRuleBorrowed) -> u32 {
|
|
|
|
read_locked_arc(rule, |rule: &KeyframesRule| rule.keyframes.len() as u32)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-09-05 19:22:20 +03:00
|
|
|
pub extern "C" fn Servo_KeyframesRule_GetKeyframeAt(rule: RawServoKeyframesRuleBorrowed, index: u32,
|
|
|
|
line: *mut u32, column: *mut u32) -> RawServoKeyframeStrong {
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
let key = Locked::<KeyframesRule>::as_arc(&rule).read_with(&guard)
|
|
|
|
.keyframes[index as usize].clone();
|
|
|
|
let location = key.read_with(&guard).source_location;
|
|
|
|
*unsafe { line.as_mut().unwrap() } = location.line as u32;
|
|
|
|
*unsafe { column.as_mut().unwrap() } = location.column as u32;
|
|
|
|
key.into_strong()
|
2017-05-19 07:49:30 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_KeyframesRule_FindRule(rule: RawServoKeyframesRuleBorrowed,
|
|
|
|
key: *const nsACString) -> u32 {
|
|
|
|
let key = unsafe { key.as_ref().unwrap().as_str_unchecked() };
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
Locked::<KeyframesRule>::as_arc(&rule).read_with(&guard)
|
|
|
|
.find_rule(&guard, key).map(|index| index as u32)
|
|
|
|
.unwrap_or(u32::max_value())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-07-02 17:00:39 +03:00
|
|
|
pub extern "C" fn Servo_KeyframesRule_AppendRule(
|
|
|
|
rule: RawServoKeyframesRuleBorrowed,
|
|
|
|
contents: RawServoStyleSheetContentsBorrowed,
|
|
|
|
css: *const nsACString
|
|
|
|
) -> bool {
|
2017-05-19 07:49:30 +03:00
|
|
|
let css = unsafe { css.as_ref().unwrap().as_str_unchecked() };
|
2017-07-02 17:00:39 +03:00
|
|
|
let contents = StylesheetContents::as_arc(&contents);
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
2017-08-18 20:58:46 +03:00
|
|
|
|
2017-07-02 17:00:39 +03:00
|
|
|
match Keyframe::parse(css, &contents, &global_style_data.shared_lock) {
|
|
|
|
Ok(keyframe) => {
|
|
|
|
write_locked_arc(rule, |rule: &mut KeyframesRule| {
|
|
|
|
rule.keyframes.push(keyframe);
|
|
|
|
});
|
|
|
|
true
|
|
|
|
}
|
|
|
|
Err(..) => false,
|
2017-05-19 07:49:30 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_KeyframesRule_DeleteRule(rule: RawServoKeyframesRuleBorrowed, index: u32) {
|
|
|
|
write_locked_arc(rule, |rule: &mut KeyframesRule| {
|
|
|
|
rule.keyframes.remove(index as usize);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-03-13 09:55:46 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_MediaRule_GetMedia(rule: RawServoMediaRuleBorrowed) -> RawServoMediaListStrong {
|
2017-03-22 14:17:09 +03:00
|
|
|
read_locked_arc(rule, |rule: &MediaRule| {
|
|
|
|
rule.media_queries.clone().into_strong()
|
|
|
|
})
|
2017-03-13 09:55:46 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-09 03:10:40 +03:00
|
|
|
pub extern "C" fn Servo_NamespaceRule_GetPrefix(rule: RawServoNamespaceRuleBorrowed) -> *mut nsAtom {
|
2017-03-22 14:17:09 +03:00
|
|
|
read_locked_arc(rule, |rule: &NamespaceRule| {
|
|
|
|
rule.prefix.as_ref().unwrap_or(&atom!("")).as_ptr()
|
|
|
|
})
|
2017-03-15 13:58:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-09 03:10:40 +03:00
|
|
|
pub extern "C" fn Servo_NamespaceRule_GetURI(rule: RawServoNamespaceRuleBorrowed) -> *mut nsAtom {
|
2017-03-22 14:17:09 +03:00
|
|
|
read_locked_arc(rule, |rule: &NamespaceRule| rule.url.0.as_ptr())
|
2017-03-13 09:55:46 +03:00
|
|
|
}
|
|
|
|
|
2017-04-10 05:47:59 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_PageRule_GetStyle(rule: RawServoPageRuleBorrowed) -> RawServoDeclarationBlockStrong {
|
|
|
|
read_locked_arc(rule, |rule: &PageRule| {
|
2017-05-15 13:28:50 +03:00
|
|
|
rule.block.clone().into_strong()
|
2017-04-10 05:47:59 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_PageRule_SetStyle(rule: RawServoPageRuleBorrowed,
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed) {
|
|
|
|
let declarations = Locked::<PropertyDeclarationBlock>::as_arc(&declarations);
|
|
|
|
write_locked_arc(rule, |rule: &mut PageRule| {
|
2017-07-18 05:44:25 +03:00
|
|
|
rule.block = declarations.clone_arc();
|
2017-04-10 05:47:59 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-04-28 13:11:04 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_SupportsRule_GetConditionText(rule: RawServoSupportsRuleBorrowed,
|
|
|
|
result: *mut nsAString) {
|
|
|
|
read_locked_arc(rule, |rule: &SupportsRule| {
|
|
|
|
rule.condition.to_css(unsafe { result.as_mut().unwrap() }).unwrap();
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-05-11 14:27:42 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DocumentRule_GetConditionText(rule: RawServoDocumentRuleBorrowed,
|
|
|
|
result: *mut nsAString) {
|
|
|
|
read_locked_arc(rule, |rule: &DocumentRule| {
|
|
|
|
rule.condition.to_css(unsafe { result.as_mut().unwrap() }).unwrap();
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-07-28 00:15:02 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_FontFeatureValuesRule_GetFontFamily(rule: RawServoFontFeatureValuesRuleBorrowed,
|
|
|
|
result: *mut nsAString) {
|
|
|
|
read_locked_arc(rule, |rule: &FontFeatureValuesRule| {
|
|
|
|
rule.font_family_to_css(unsafe { result.as_mut().unwrap() }).unwrap();
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_FontFeatureValuesRule_GetValueText(rule: RawServoFontFeatureValuesRuleBorrowed,
|
|
|
|
result: *mut nsAString) {
|
|
|
|
read_locked_arc(rule, |rule: &FontFeatureValuesRule| {
|
|
|
|
rule.value_to_css(unsafe { result.as_mut().unwrap() }).unwrap();
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-03-25 00:57:33 +03:00
|
|
|
#[no_mangle]
|
2017-07-18 05:44:25 +03:00
|
|
|
pub extern "C" fn Servo_ComputedValues_GetForAnonymousBox(parent_style_or_null: ServoStyleContextBorrowedOrNull,
|
2017-10-09 03:10:40 +03:00
|
|
|
pseudo_tag: *mut nsAtom,
|
2017-03-13 20:47:05 +03:00
|
|
|
raw_data: RawServoStyleSetBorrowed)
|
2017-07-18 05:44:25 +03:00
|
|
|
-> ServoStyleContextStrong {
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
let guards = StylesheetGuards::same(&guard);
|
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);
|
2017-05-16 04:46:42 +03:00
|
|
|
let pseudo = PseudoElement::from_anon_box_atom(&atom)
|
|
|
|
.expect("Not an anon box pseudo?");
|
2016-04-30 00:27:16 +03:00
|
|
|
|
2017-10-31 02:25:45 +03:00
|
|
|
let mut cascade_flags = CascadeFlags::SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP;
|
2017-07-18 07:16:26 +03:00
|
|
|
if pseudo.is_fieldset_content() {
|
2017-10-31 02:25:45 +03:00
|
|
|
cascade_flags.insert(CascadeFlags::IS_FIELDSET_CONTENT);
|
2017-07-18 07:16:26 +03:00
|
|
|
}
|
2017-04-09 14:15:51 +03:00
|
|
|
let metrics = get_metrics_provider_for_product();
|
2017-09-07 00:40:33 +03:00
|
|
|
|
|
|
|
// If the pseudo element is PageContent, we should append the precomputed
|
|
|
|
// pseudo element declerations with specified page rules.
|
|
|
|
let page_decls = match pseudo {
|
|
|
|
PseudoElement::PageContent => {
|
|
|
|
let mut declarations = vec![];
|
2017-09-14 01:44:21 +03:00
|
|
|
let iter = data.stylist.iter_extra_data_origins_rev();
|
2017-09-07 00:40:33 +03:00
|
|
|
for (data, origin) in iter {
|
|
|
|
let level = match origin {
|
|
|
|
Origin::UserAgent => CascadeLevel::UANormal,
|
|
|
|
Origin::User => CascadeLevel::UserNormal,
|
|
|
|
Origin::Author => CascadeLevel::AuthorNormal,
|
|
|
|
};
|
|
|
|
for rule in data.pages.iter() {
|
|
|
|
declarations.push(ApplicableDeclarationBlock::from_declarations(
|
|
|
|
rule.read_with(level.guard(&guards)).block.clone(),
|
|
|
|
level
|
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Some(declarations)
|
|
|
|
},
|
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
|
|
|
|
let rule_node = data.stylist.rule_node_for_precomputed_pseudo(
|
|
|
|
&guards,
|
|
|
|
&pseudo,
|
|
|
|
page_decls,
|
|
|
|
);
|
|
|
|
|
|
|
|
data.stylist.precomputed_values_for_pseudo_with_rule_node(
|
2017-07-18 19:23:03 +03:00
|
|
|
&guards,
|
|
|
|
&pseudo,
|
|
|
|
parent_style_or_null.map(|x| &*x),
|
2017-09-07 00:40:33 +03:00
|
|
|
cascade_flags,
|
|
|
|
&metrics,
|
|
|
|
&rule_node
|
2017-07-21 21:05:13 +03:00
|
|
|
).into()
|
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,
|
2017-05-16 04:46:42 +03:00
|
|
|
pseudo_type: CSSPseudoElementType,
|
|
|
|
is_probe: bool,
|
2017-07-18 19:23:03 +03:00
|
|
|
inherited_style: ServoStyleContextBorrowedOrNull,
|
2016-12-26 05:13:30 +03:00
|
|
|
raw_data: RawServoStyleSetBorrowed)
|
2017-07-18 05:44:25 +03:00
|
|
|
-> ServoStyleContextStrong
|
2016-12-26 05:13:30 +03:00
|
|
|
{
|
|
|
|
let element = GeckoElement(element);
|
2017-06-24 09:58:16 +03:00
|
|
|
let doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
2016-05-04 13:42:23 +03:00
|
|
|
|
2017-06-24 09:58:16 +03:00
|
|
|
debug!("Servo_ResolvePseudoStyle: {:?} {:?}, is_probe: {}",
|
|
|
|
element, PseudoElement::from_pseudo_type(pseudo_type), is_probe);
|
2017-06-23 03:46:55 +03:00
|
|
|
|
2017-09-28 23:17:21 +03:00
|
|
|
let data = element.borrow_data();
|
|
|
|
|
|
|
|
let data = match data.as_ref() {
|
|
|
|
Some(data) if data.has_styles() => data,
|
|
|
|
_ => {
|
|
|
|
// FIXME(bholley, emilio): Assert against this.
|
|
|
|
//
|
|
|
|
// Known offender is nsMathMLmoFrame::MarkIntrinsicISizesDirty,
|
|
|
|
// which goes and does a bunch of work involving style resolution.
|
|
|
|
//
|
|
|
|
// Bug 1403865 tracks fixing it, and potentially adding an assert
|
|
|
|
// here instead.
|
|
|
|
warn!("Calling Servo_ResolvePseudoStyle on unstyled element");
|
|
|
|
return if is_probe {
|
|
|
|
Strong::null()
|
|
|
|
} else {
|
|
|
|
doc_data.default_computed_values().clone().into()
|
|
|
|
};
|
|
|
|
}
|
|
|
|
};
|
2016-05-04 13:42:23 +03:00
|
|
|
|
2017-05-16 04:46:42 +03:00
|
|
|
let pseudo = PseudoElement::from_pseudo_type(pseudo_type)
|
|
|
|
.expect("ResolvePseudoStyle with a non-pseudo?");
|
|
|
|
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
2017-06-24 09:58:16 +03:00
|
|
|
let style = get_pseudo_style(
|
|
|
|
&guard,
|
|
|
|
element,
|
|
|
|
&pseudo,
|
|
|
|
RuleInclusion::All,
|
|
|
|
&data.styles,
|
2017-07-18 05:44:25 +03:00
|
|
|
inherited_style,
|
2017-06-24 09:58:16 +03:00
|
|
|
&*doc_data,
|
2017-07-18 05:44:25 +03:00
|
|
|
is_probe,
|
2017-10-20 12:18:53 +03:00
|
|
|
/* matching_func = */ None,
|
2017-06-24 09:58:16 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
match style {
|
2017-07-21 21:05:13 +03:00
|
|
|
Some(s) => s.into(),
|
2017-06-24 09:58:16 +03:00
|
|
|
None => {
|
|
|
|
debug_assert!(is_probe);
|
|
|
|
Strong::null()
|
|
|
|
}
|
2016-12-26 05:13:30 +03:00
|
|
|
}
|
|
|
|
}
|
2016-05-04 13:42:23 +03:00
|
|
|
|
2017-10-20 12:18:53 +03:00
|
|
|
fn debug_atom_array(atoms: &AtomArray) -> String {
|
|
|
|
let mut result = String::from("[");
|
|
|
|
for atom in atoms.iter() {
|
|
|
|
if atom.mRawPtr.is_null() {
|
|
|
|
result += "(null), ";
|
|
|
|
} else {
|
|
|
|
let atom = unsafe { WeakAtom::new(atom.mRawPtr) };
|
|
|
|
write!(result, "{}, ", atom).unwrap();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
result.push(']');
|
|
|
|
result
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_ComputedValues_ResolveXULTreePseudoStyle(
|
|
|
|
element: RawGeckoElementBorrowed,
|
|
|
|
pseudo_tag: *mut nsAtom,
|
|
|
|
inherited_style: ServoStyleContextBorrowed,
|
|
|
|
input_word: *const AtomArray,
|
|
|
|
raw_data: RawServoStyleSetBorrowed
|
|
|
|
) -> ServoStyleContextStrong {
|
|
|
|
let element = GeckoElement(element);
|
|
|
|
let data = element.borrow_data()
|
|
|
|
.expect("Calling ResolveXULTreePseudoStyle on unstyled element?");
|
|
|
|
|
|
|
|
let pseudo = unsafe {
|
|
|
|
Atom::with(pseudo_tag, |atom| {
|
|
|
|
PseudoElement::from_tree_pseudo_atom(atom, Box::new([]))
|
|
|
|
}).expect("ResolveXULTreePseudoStyle with a non-tree pseudo?")
|
|
|
|
};
|
|
|
|
let input_word = unsafe { input_word.as_ref().unwrap() };
|
|
|
|
|
|
|
|
let doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
|
|
|
|
|
|
|
debug!("ResolveXULTreePseudoStyle: {:?} {:?} {}",
|
|
|
|
element, pseudo, debug_atom_array(input_word));
|
|
|
|
|
|
|
|
let matching_fn = |pseudo: &PseudoElement| {
|
|
|
|
let args = pseudo.tree_pseudo_args().expect("Not a tree pseudo-element?");
|
|
|
|
args.iter().all(|atom| {
|
|
|
|
input_word.iter().any(|item| atom.as_ptr() == item.mRawPtr)
|
|
|
|
})
|
|
|
|
};
|
|
|
|
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
get_pseudo_style(
|
|
|
|
&guard,
|
|
|
|
element,
|
|
|
|
&pseudo,
|
|
|
|
RuleInclusion::All,
|
|
|
|
&data.styles,
|
|
|
|
Some(inherited_style),
|
|
|
|
&*doc_data,
|
|
|
|
/* is_probe = */ false,
|
|
|
|
Some(&matching_fn),
|
|
|
|
).unwrap().into()
|
|
|
|
}
|
|
|
|
|
2017-06-27 20:27:49 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_SetExplicitStyle(element: RawGeckoElementBorrowed,
|
2017-07-18 05:44:25 +03:00
|
|
|
style: ServoStyleContextBorrowed)
|
2017-06-27 20:27:49 +03:00
|
|
|
{
|
|
|
|
let element = GeckoElement(element);
|
|
|
|
debug!("Servo_SetExplicitStyle: {:?}", element);
|
|
|
|
// We only support this API for initial styling. There's no reason it couldn't
|
|
|
|
// work for other things, we just haven't had a reason to do so.
|
|
|
|
debug_assert!(element.get_data().is_none());
|
2017-07-15 17:44:08 +03:00
|
|
|
let mut data = unsafe { element.ensure_data() };
|
2017-07-21 21:05:13 +03:00
|
|
|
data.styles.primary = Some(unsafe { ArcBorrow::from_ref(style) }.clone_arc());
|
2017-06-27 20:27:49 +03:00
|
|
|
}
|
|
|
|
|
2017-05-09 21:21:29 +03:00
|
|
|
#[no_mangle]
|
2017-10-11 02:31:18 +03:00
|
|
|
pub extern "C" fn Servo_HasAuthorSpecifiedRules(style: ServoStyleContextBorrowed,
|
|
|
|
element: RawGeckoElementBorrowed,
|
|
|
|
pseudo_type: CSSPseudoElementType,
|
2017-05-09 21:21:29 +03:00
|
|
|
rule_type_mask: u32,
|
|
|
|
author_colors_allowed: bool)
|
|
|
|
-> bool
|
|
|
|
{
|
|
|
|
let element = GeckoElement(element);
|
2017-10-11 02:31:18 +03:00
|
|
|
let pseudo = PseudoElement::from_pseudo_type(pseudo_type);
|
2017-05-16 04:46:42 +03:00
|
|
|
|
2017-05-09 21:21:29 +03:00
|
|
|
let guard = (*GLOBAL_STYLE_DATA).shared_lock.read();
|
|
|
|
let guards = StylesheetGuards::same(&guard);
|
|
|
|
|
2017-10-11 02:31:18 +03:00
|
|
|
style.rules().has_author_specified_rules(element,
|
|
|
|
pseudo,
|
|
|
|
&guards,
|
|
|
|
rule_type_mask,
|
|
|
|
author_colors_allowed)
|
2017-05-09 21:21:29 +03:00
|
|
|
}
|
|
|
|
|
2017-06-24 09:58:16 +03:00
|
|
|
fn get_pseudo_style(
|
|
|
|
guard: &SharedRwLockReadGuard,
|
|
|
|
element: GeckoElement,
|
|
|
|
pseudo: &PseudoElement,
|
|
|
|
rule_inclusion: RuleInclusion,
|
|
|
|
styles: &ElementStyles,
|
2017-07-18 19:23:03 +03:00
|
|
|
inherited_styles: Option<&ComputedValues>,
|
2017-06-24 09:58:16 +03:00
|
|
|
doc_data: &PerDocumentStyleDataImpl,
|
|
|
|
is_probe: bool,
|
2017-10-20 12:18:53 +03:00
|
|
|
matching_func: Option<&Fn(&PseudoElement) -> bool>,
|
2017-06-24 09:58:16 +03:00
|
|
|
) -> Option<Arc<ComputedValues>> {
|
|
|
|
let style = match pseudo.cascade_type() {
|
2017-06-27 09:46:13 +03:00
|
|
|
PseudoElementCascadeType::Eager => {
|
|
|
|
match *pseudo {
|
|
|
|
PseudoElement::FirstLetter => {
|
2017-07-08 02:11:50 +03:00
|
|
|
styles.pseudos.get(&pseudo).and_then(|pseudo_styles| {
|
|
|
|
// inherited_styles can be None when doing lazy resolution
|
|
|
|
// (e.g. for computed style) or when probing. In that case
|
|
|
|
// we just inherit from our element, which is what Gecko
|
|
|
|
// does in that situation. What should actually happen in
|
|
|
|
// the computed style case is a bit unclear.
|
|
|
|
let inherited_styles =
|
|
|
|
inherited_styles.unwrap_or(styles.primary());
|
|
|
|
let guards = StylesheetGuards::same(guard);
|
|
|
|
let metrics = get_metrics_provider_for_product();
|
|
|
|
let inputs = CascadeInputs::new_from_style(pseudo_styles);
|
|
|
|
doc_data.stylist
|
|
|
|
.compute_pseudo_element_style_with_inputs(
|
|
|
|
&inputs,
|
2017-07-18 19:23:03 +03:00
|
|
|
pseudo,
|
2017-07-08 02:11:50 +03:00
|
|
|
&guards,
|
|
|
|
inherited_styles,
|
2017-07-18 19:23:03 +03:00
|
|
|
&metrics
|
|
|
|
)
|
2017-07-08 02:11:50 +03:00
|
|
|
})
|
2017-06-27 09:46:13 +03:00
|
|
|
},
|
|
|
|
_ => {
|
2017-07-29 06:51:20 +03:00
|
|
|
// Unfortunately, we can't assert that inherited_styles, if
|
|
|
|
// present, is pointer-equal to styles.primary(), or even
|
|
|
|
// equal in any meaningful way. The way it can fail is as
|
|
|
|
// follows. Say we append an element with a ::before,
|
|
|
|
// ::after, or ::first-line to a parent with a ::first-line,
|
|
|
|
// such that the element ends up on the first line of the
|
|
|
|
// parent (e.g. it's an inline-block in the case it has a
|
|
|
|
// ::first-line, or any container in the ::before/::after
|
|
|
|
// cases). Then gecko will update its frame's style to
|
|
|
|
// inherit from the parent's ::first-line. The next time we
|
|
|
|
// try to get the ::before/::after/::first-line style for
|
|
|
|
// the kid, we'll likely pass in the frame's style as
|
|
|
|
// inherited_styles, but that's not pointer-identical to
|
|
|
|
// styles.primary(), because it got reparented.
|
|
|
|
//
|
|
|
|
// Now in practice this turns out to be OK, because all the
|
|
|
|
// cases in which there's a mismatch go ahead and reparent
|
|
|
|
// styles again as needed to make sure the ::first-line
|
|
|
|
// affects all the things it should affect. But it makes it
|
|
|
|
// impossible to assert anything about the two styles
|
|
|
|
// matching here, unfortunately.
|
2017-06-27 09:46:13 +03:00
|
|
|
styles.pseudos.get(&pseudo).cloned()
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2016-12-26 05:13:30 +03:00
|
|
|
PseudoElementCascadeType::Precomputed => unreachable!("No anonymous boxes"),
|
2016-05-04 13:42:23 +03:00
|
|
|
PseudoElementCascadeType::Lazy => {
|
2017-06-27 09:46:13 +03:00
|
|
|
debug_assert!(inherited_styles.is_none() ||
|
2017-07-18 19:23:03 +03:00
|
|
|
ptr::eq(inherited_styles.unwrap(),
|
|
|
|
&**styles.primary()));
|
2017-05-23 10:25:07 +03:00
|
|
|
let base = if pseudo.inherits_from_default_values() {
|
2017-06-14 12:00:07 +03:00
|
|
|
doc_data.default_computed_values()
|
2017-05-23 10:25:07 +03:00
|
|
|
} else {
|
2017-06-23 03:46:55 +03:00
|
|
|
styles.primary()
|
2017-05-23 10:25:07 +03:00
|
|
|
};
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
let guards = StylesheetGuards::same(guard);
|
2017-04-09 14:15:51 +03:00
|
|
|
let metrics = get_metrics_provider_for_product();
|
2017-06-14 12:00:07 +03:00
|
|
|
doc_data.stylist
|
|
|
|
.lazily_compute_pseudo_element_style(
|
|
|
|
&guards,
|
|
|
|
&element,
|
|
|
|
&pseudo,
|
|
|
|
rule_inclusion,
|
|
|
|
base,
|
2017-06-30 19:11:41 +03:00
|
|
|
is_probe,
|
2017-07-18 05:44:25 +03:00
|
|
|
&metrics,
|
2017-10-20 12:18:53 +03:00
|
|
|
matching_func,
|
2017-07-18 19:23:03 +03:00
|
|
|
)
|
2016-12-26 05:13:30 +03:00
|
|
|
},
|
2017-06-24 09:58:16 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
if is_probe {
|
|
|
|
return style;
|
2016-05-04 13:42:23 +03:00
|
|
|
}
|
2017-06-24 09:58:16 +03:00
|
|
|
|
|
|
|
Some(style.unwrap_or_else(|| {
|
2017-07-18 05:44:25 +03:00
|
|
|
StyleBuilder::for_inheritance(
|
2017-07-18 19:23:03 +03:00
|
|
|
doc_data.stylist.device(),
|
2017-06-24 09:58:16 +03:00
|
|
|
styles.primary(),
|
2017-07-18 19:23:03 +03:00
|
|
|
Some(pseudo),
|
|
|
|
).build()
|
2017-06-24 09:58:16 +03:00
|
|
|
}))
|
2016-05-04 13:42:23 +03:00
|
|
|
}
|
|
|
|
|
2016-05-06 14:30:47 +03:00
|
|
|
#[no_mangle]
|
2017-01-05 08:01:38 +03:00
|
|
|
pub extern "C" fn Servo_ComputedValues_Inherit(
|
2017-07-02 17:00:39 +03:00
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
2017-10-09 03:10:40 +03:00
|
|
|
pseudo_tag: *mut nsAtom,
|
2017-07-18 05:44:25 +03:00
|
|
|
parent_style_context: ServoStyleContextBorrowedOrNull,
|
2017-07-02 17:00:39 +03:00
|
|
|
target: structs::InheritTarget
|
2017-07-18 05:44:25 +03:00
|
|
|
) -> ServoStyleContextStrong {
|
2017-01-05 08:01:38 +03:00
|
|
|
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
2017-04-28 18:25:21 +03:00
|
|
|
|
|
|
|
let for_text = target == structs::InheritTarget::Text;
|
2017-07-18 19:23:03 +03:00
|
|
|
let atom = Atom::from(pseudo_tag);
|
|
|
|
let pseudo = PseudoElement::from_anon_box_atom(&atom)
|
|
|
|
.expect("Not an anon-box? Gah!");
|
2017-07-18 05:44:25 +03:00
|
|
|
let style = if let Some(reference) = parent_style_context {
|
2017-07-18 19:23:03 +03:00
|
|
|
let mut style = StyleBuilder::for_inheritance(
|
|
|
|
data.stylist.device(),
|
|
|
|
reference,
|
|
|
|
Some(&pseudo)
|
|
|
|
);
|
|
|
|
|
2017-04-28 18:25:21 +03:00
|
|
|
if for_text {
|
2017-06-22 14:17:04 +03:00
|
|
|
StyleAdjuster::new(&mut style)
|
2017-08-15 09:08:56 +03:00
|
|
|
.adjust_for_text();
|
2017-04-28 18:25:21 +03:00
|
|
|
}
|
|
|
|
|
2017-07-18 05:44:25 +03:00
|
|
|
style.build()
|
2016-08-04 04:20:21 +03:00
|
|
|
} else {
|
2017-04-28 18:25:21 +03:00
|
|
|
debug_assert!(!for_text);
|
2017-07-18 19:23:03 +03:00
|
|
|
StyleBuilder::for_derived_style(
|
|
|
|
data.stylist.device(),
|
|
|
|
data.default_computed_values(),
|
2017-07-20 12:36:15 +03:00
|
|
|
/* parent_style = */ None,
|
2017-07-18 19:23:03 +03:00
|
|
|
Some(&pseudo),
|
|
|
|
).build()
|
2017-07-18 05:44:25 +03:00
|
|
|
};
|
|
|
|
|
2017-07-21 21:05:13 +03:00
|
|
|
style.into()
|
2017-05-25 03:53:48 +03:00
|
|
|
}
|
|
|
|
|
2017-07-14 06:02:36 +03:00
|
|
|
#[no_mangle]
|
2017-07-21 21:05:13 +03:00
|
|
|
pub extern "C" fn Servo_ComputedValues_GetStyleBits(values: ServoStyleContextBorrowed) -> u64 {
|
2017-10-31 02:25:45 +03:00
|
|
|
use style::properties::computed_value_flags::ComputedValueFlags;
|
2017-08-03 13:50:18 +03:00
|
|
|
// FIXME(emilio): We could do this more efficiently I'm quite sure.
|
2017-07-18 05:44:25 +03:00
|
|
|
let flags = values.flags;
|
2017-07-14 06:02:36 +03:00
|
|
|
let mut result = 0;
|
2017-10-31 02:25:45 +03:00
|
|
|
if flags.contains(ComputedValueFlags::IS_RELEVANT_LINK_VISITED) {
|
2017-07-23 23:46:43 +03:00
|
|
|
result |= structs::NS_STYLE_RELEVANT_LINK_VISITED as u64;
|
2017-07-23 14:15:39 +03:00
|
|
|
}
|
2017-10-31 02:25:45 +03:00
|
|
|
if flags.contains(ComputedValueFlags::HAS_TEXT_DECORATION_LINES) {
|
2017-07-14 06:02:36 +03:00
|
|
|
result |= structs::NS_STYLE_HAS_TEXT_DECORATION_LINES as u64;
|
|
|
|
}
|
2017-10-31 02:25:45 +03:00
|
|
|
if flags.contains(ComputedValueFlags::SHOULD_SUPPRESS_LINEBREAK) {
|
2017-07-14 06:02:36 +03:00
|
|
|
result |= structs::NS_STYLE_SUPPRESS_LINEBREAK as u64;
|
|
|
|
}
|
2017-10-31 02:25:45 +03:00
|
|
|
if flags.contains(ComputedValueFlags::IS_TEXT_COMBINED) {
|
2017-07-22 03:30:05 +03:00
|
|
|
result |= structs::NS_STYLE_IS_TEXT_COMBINED as u64;
|
|
|
|
}
|
2017-10-31 02:25:45 +03:00
|
|
|
if flags.contains(ComputedValueFlags::IS_IN_PSEUDO_ELEMENT_SUBTREE) {
|
2017-08-03 13:50:18 +03:00
|
|
|
result |= structs::NS_STYLE_HAS_PSEUDO_ELEMENT_DATA as u64;
|
|
|
|
}
|
2017-10-31 02:25:45 +03:00
|
|
|
if flags.contains(ComputedValueFlags::IS_IN_DISPLAY_NONE_SUBTREE) {
|
2017-08-03 13:50:18 +03:00
|
|
|
result |= structs::NS_STYLE_IN_DISPLAY_NONE_SUBTREE as u64;
|
|
|
|
}
|
2017-07-14 06:02:36 +03:00
|
|
|
result
|
|
|
|
}
|
|
|
|
|
2017-06-27 20:27:49 +03:00
|
|
|
#[no_mangle]
|
2017-07-21 21:05:13 +03:00
|
|
|
pub extern "C" fn Servo_ComputedValues_SpecifiesAnimationsOrTransitions(values: ServoStyleContextBorrowed)
|
2017-06-27 20:27:49 +03:00
|
|
|
-> bool {
|
|
|
|
let b = values.get_box();
|
|
|
|
b.specifies_animations() || b.specifies_transitions()
|
|
|
|
}
|
|
|
|
|
2017-07-14 09:21:30 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_ComputedValues_EqualCustomProperties(
|
2017-07-21 21:05:13 +03:00
|
|
|
first: ServoComputedDataBorrowed,
|
|
|
|
second: ServoComputedDataBorrowed
|
2017-07-14 09:21:30 +03:00
|
|
|
) -> bool {
|
2017-10-01 21:30:18 +03:00
|
|
|
first.custom_properties == second.custom_properties
|
2017-07-14 09:21:30 +03:00
|
|
|
}
|
|
|
|
|
2017-07-10 06:07:41 +03:00
|
|
|
#[no_mangle]
|
2017-07-21 21:05:13 +03:00
|
|
|
pub extern "C" fn Servo_ComputedValues_GetStyleRuleList(values: ServoStyleContextBorrowed,
|
2017-07-10 06:07:41 +03:00
|
|
|
rules: RawGeckoServoStyleRuleListBorrowedMut) {
|
2017-09-29 18:01:52 +03:00
|
|
|
use smallvec::SmallVec;
|
|
|
|
|
2017-08-08 11:21:54 +03:00
|
|
|
let rule_node = match values.rules {
|
|
|
|
Some(ref r) => r,
|
|
|
|
None => return,
|
|
|
|
};
|
|
|
|
|
2017-09-29 18:01:52 +03:00
|
|
|
let mut result = SmallVec::<[_; 10]>::new();
|
2017-08-08 11:21:54 +03:00
|
|
|
for node in rule_node.self_and_ancestors() {
|
|
|
|
let style_rule = match *node.style_source() {
|
|
|
|
StyleSource::Style(ref rule) => rule,
|
|
|
|
_ => continue,
|
|
|
|
};
|
|
|
|
|
2017-09-01 12:15:21 +03:00
|
|
|
// For the rules with any important declaration, we insert them into
|
|
|
|
// rule tree twice, one for normal level and another for important
|
|
|
|
// level. So, we skip the important one to keep the specificity order of
|
|
|
|
// rules.
|
2017-08-08 11:21:54 +03:00
|
|
|
if node.importance().important() {
|
2017-09-01 12:15:21 +03:00
|
|
|
continue;
|
2017-07-10 06:07:41 +03:00
|
|
|
}
|
2017-08-08 11:21:54 +03:00
|
|
|
|
|
|
|
result.push(style_rule);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe { rules.set_len(result.len() as u32) };
|
|
|
|
for (ref src, ref mut dest) in result.into_iter().zip(rules.iter_mut()) {
|
|
|
|
src.with_raw_offset_arc(|arc| {
|
|
|
|
**dest = *Locked::<StyleRule>::arc_as_borrowed(arc);
|
|
|
|
})
|
2017-07-10 06:07:41 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-18 16:39:57 +03:00
|
|
|
/// See the comment in `Device` to see why it's ok to pass an owned reference to
|
|
|
|
/// the pres context (hint: the context outlives the StyleSet, that holds the
|
|
|
|
/// device alive).
|
2016-02-04 20:55:09 +03:00
|
|
|
#[no_mangle]
|
2017-01-18 16:39:57 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_Init(pres_context: RawGeckoPresContextOwned)
|
2017-08-16 06:11:50 +03:00
|
|
|
-> *mut RawServoStyleSet {
|
2017-01-05 08:01:38 +03:00
|
|
|
let data = Box::new(PerDocumentStyleData::new(pres_context));
|
2017-08-16 06:11:50 +03:00
|
|
|
Box::into_raw(data) as *mut RawServoStyleSet
|
2016-02-04 20:55:09 +03:00
|
|
|
}
|
|
|
|
|
2017-01-05 08:01:38 +03:00
|
|
|
#[no_mangle]
|
2017-08-03 17:36:21 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_RebuildCachedData(raw_data: RawServoStyleSetBorrowed) {
|
2017-01-05 08:01:38 +03:00
|
|
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
2017-08-03 17:36:21 +03:00
|
|
|
data.stylist.device_mut().rebuild_cached_data();
|
2017-01-05 08:01:38 +03:00
|
|
|
}
|
|
|
|
|
2016-02-04 20:55:09 +03:00
|
|
|
#[no_mangle]
|
2017-03-13 20:01:16 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_Drop(data: RawServoStyleSetOwned) {
|
2016-09-03 06:42:21 +03:00
|
|
|
let _ = data.into_box::<PerDocumentStyleData>();
|
2016-02-04 20:55:09 +03:00
|
|
|
}
|
2016-06-24 05:46:25 +03:00
|
|
|
|
2017-06-10 22:25:59 +03:00
|
|
|
|
|
|
|
/// Updating the stylesheets and redoing selector matching is always happens
|
|
|
|
/// before the document element is inserted. Therefore we don't need to call
|
|
|
|
/// `force_dirty` here.
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleSet_CompatModeChanged(raw_data: RawServoStyleSetBorrowed) {
|
|
|
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
|
|
|
let quirks_mode = unsafe {
|
2017-06-22 14:17:04 +03:00
|
|
|
(*data.stylist.device().pres_context().mDocument.raw::<nsIDocument>())
|
|
|
|
.mCompatMode
|
2017-06-10 22:25:59 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
data.stylist.set_quirks_mode(quirks_mode.into());
|
|
|
|
}
|
|
|
|
|
2017-10-13 22:11:02 +03:00
|
|
|
fn parse_property_into<R>(
|
|
|
|
declarations: &mut SourcePropertyDeclaration,
|
|
|
|
property_id: PropertyId,
|
|
|
|
value: *const nsACString,
|
|
|
|
data: *mut URLExtraData,
|
|
|
|
parsing_mode: structs::ParsingMode,
|
|
|
|
quirks_mode: QuirksMode,
|
|
|
|
reporter: &R
|
|
|
|
) -> Result<(), ()>
|
|
|
|
where
|
|
|
|
R: ParseErrorReporter
|
2017-08-24 21:19:25 +03:00
|
|
|
{
|
2017-06-14 05:25:09 +03:00
|
|
|
use style_traits::ParsingMode;
|
2017-05-11 05:25:47 +03:00
|
|
|
let value = unsafe { value.as_ref().unwrap().as_str_unchecked() };
|
|
|
|
let url_data = unsafe { RefPtr::from_ptr_ref(&data) };
|
2017-05-14 02:53:07 +03:00
|
|
|
let parsing_mode = ParsingMode::from_bits_truncate(parsing_mode);
|
2017-05-11 05:25:47 +03:00
|
|
|
|
2017-05-20 02:37:14 +03:00
|
|
|
parse_one_declaration_into(
|
|
|
|
declarations,
|
|
|
|
property_id,
|
|
|
|
value,
|
|
|
|
url_data,
|
2017-07-11 04:13:44 +03:00
|
|
|
reporter,
|
2017-05-20 02:37:14 +03:00
|
|
|
parsing_mode,
|
2017-11-21 16:47:52 +03:00
|
|
|
quirks_mode,
|
|
|
|
)
|
2017-05-11 05:25:47 +03:00
|
|
|
}
|
|
|
|
|
2016-10-09 16:53:28 +03:00
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_ParseProperty(
|
|
|
|
property: nsCSSPropertyID, value: *const nsACString,
|
|
|
|
data: *mut URLExtraData,
|
|
|
|
parsing_mode: structs::ParsingMode,
|
|
|
|
quirks_mode: nsCompatibility,
|
|
|
|
loader: *mut Loader,
|
|
|
|
) -> RawServoDeclarationBlockStrong {
|
2017-04-15 14:20:52 +03:00
|
|
|
let id = get_property_id_from_nscsspropertyid!(property,
|
|
|
|
RawServoDeclarationBlockStrong::null());
|
2017-05-20 02:37:14 +03:00
|
|
|
let mut declarations = SourcePropertyDeclaration::new();
|
2017-07-11 04:13:44 +03:00
|
|
|
let reporter = ErrorReporter::new(ptr::null_mut(), loader, data);
|
2017-05-20 02:37:14 +03:00
|
|
|
match parse_property_into(&mut declarations, id, value, data,
|
2017-07-11 04:13:44 +03:00
|
|
|
parsing_mode, quirks_mode.into(), &reporter) {
|
2017-05-20 02:37:14 +03:00
|
|
|
Ok(()) => {
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
2017-03-08 14:07:04 +03:00
|
|
|
let mut block = PropertyDeclarationBlock::new();
|
2017-10-14 13:27:51 +03:00
|
|
|
block.extend(
|
|
|
|
declarations.drain(),
|
|
|
|
Importance::Normal,
|
|
|
|
DeclarationSource::CssOm,
|
|
|
|
);
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
Arc::new(global_style_data.shared_lock.wrap(block)).into_strong()
|
2017-03-08 14:07:04 +03:00
|
|
|
}
|
|
|
|
Err(_) => RawServoDeclarationBlockStrong::null()
|
2016-10-09 16:53:28 +03:00
|
|
|
}
|
|
|
|
}
|
2016-10-18 08:51:14 +03:00
|
|
|
|
2017-03-21 11:36:49 +03:00
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_ParseEasing(
|
|
|
|
easing: *const nsAString,
|
|
|
|
data: *mut URLExtraData,
|
|
|
|
output: nsTimingFunctionBorrowedMut
|
|
|
|
) -> bool {
|
2017-03-21 11:36:49 +03:00
|
|
|
use style::properties::longhands::transition_timing_function;
|
|
|
|
|
2017-10-17 09:11:39 +03:00
|
|
|
// FIXME Dummy URL data would work fine here.
|
2017-04-03 15:05:42 +03:00
|
|
|
let url_data = unsafe { RefPtr::from_ptr_ref(&data) };
|
2017-04-28 18:25:21 +03:00
|
|
|
let context = ParserContext::new(Origin::Author,
|
|
|
|
url_data,
|
|
|
|
Some(CssRuleType::Style),
|
2017-10-31 02:25:45 +03:00
|
|
|
ParsingMode::DEFAULT,
|
2017-04-28 06:32:24 +03:00
|
|
|
QuirksMode::NoQuirks);
|
2017-03-21 11:36:49 +03:00
|
|
|
let easing = unsafe { (*easing).to_string() };
|
2017-06-10 00:31:48 +03:00
|
|
|
let mut input = ParserInput::new(&easing);
|
2017-06-16 16:09:52 +03:00
|
|
|
let mut parser = Parser::new(&mut input);
|
2017-08-11 03:48:34 +03:00
|
|
|
let result =
|
|
|
|
parser.parse_entirely(|p| transition_timing_function::single_value::parse(&context, p));
|
2017-06-16 16:09:52 +03:00
|
|
|
match result {
|
2017-03-21 11:36:49 +03:00
|
|
|
Ok(parsed_easing) => {
|
|
|
|
*output = parsed_easing.into();
|
|
|
|
true
|
|
|
|
},
|
|
|
|
Err(_) => false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-20 15:24:21 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_GetProperties_Overriding_Animation(element: RawGeckoElementBorrowed,
|
|
|
|
list: RawGeckoCSSPropertyIDListBorrowed,
|
|
|
|
set: nsCSSPropertyIDSetBorrowedMut) {
|
|
|
|
let element = GeckoElement(element);
|
|
|
|
let element_data = match element.borrow_data() {
|
|
|
|
Some(data) => data,
|
|
|
|
None => return
|
|
|
|
};
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
let guards = StylesheetGuards::same(&guard);
|
|
|
|
let (overridden, custom) =
|
2017-06-23 03:46:55 +03:00
|
|
|
element_data.styles.primary().rules().get_properties_overriding_animations(&guards);
|
2017-05-20 15:24:21 +03:00
|
|
|
for p in list.iter() {
|
|
|
|
match PropertyId::from_nscsspropertyid(*p) {
|
|
|
|
Ok(property) => {
|
|
|
|
if let PropertyId::Longhand(id) = property {
|
|
|
|
if overridden.contains(id) {
|
|
|
|
unsafe { Gecko_AddPropertyToSet(set, *p) };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
Err(_) => {
|
|
|
|
if *p == nsCSSPropertyID::eCSSPropertyExtra_variable && custom {
|
|
|
|
unsafe { Gecko_AddPropertyToSet(set, *p) };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-07 09:54:41 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_MatrixTransform_Operate(matrix_operator: MatrixTransformOperator,
|
|
|
|
from: *const RawGeckoGfxMatrix4x4,
|
|
|
|
to: *const RawGeckoGfxMatrix4x4,
|
|
|
|
progress: f64,
|
|
|
|
output: *mut RawGeckoGfxMatrix4x4) {
|
|
|
|
use self::MatrixTransformOperator::{Accumulate, Interpolate};
|
2017-11-03 01:02:07 +03:00
|
|
|
use style::values::computed::transform::Matrix3D;
|
2017-06-07 09:54:41 +03:00
|
|
|
|
2017-11-03 01:02:07 +03:00
|
|
|
let from = Matrix3D::from(unsafe { from.as_ref() }.expect("not a valid 'from' matrix"));
|
|
|
|
let to = Matrix3D::from(unsafe { to.as_ref() }.expect("not a valid 'to' matrix"));
|
2017-06-07 09:54:41 +03:00
|
|
|
let result = match matrix_operator {
|
2017-08-22 15:22:10 +03:00
|
|
|
Interpolate => from.animate(&to, Procedure::Interpolate { progress }),
|
|
|
|
Accumulate => from.animate(&to, Procedure::Accumulate { count: progress as u64 }),
|
2017-06-07 09:54:41 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
let output = unsafe { output.as_mut() }.expect("not a valid 'output' matrix");
|
servo: Merge #18591 - stylo: do not handle the fallback discrete animation inside the Animate trait (from chenpighead:stylo-singular-matrix-animation); r=BorisChiou
At present, we do the fallback discrete animation for non-invertible matrices in
ComputedMatrix.animate(). However, according to the spec, we should fallback to
discrete animation for cases like:
1. animation between transform with single non-invertible matrix
2. animation between transform with matched transform functions that have at least
one non-invertible matrix
2. animation between transform with mismatched transform functions that have at
least one non-invertible matrix.
The current implementation only handles the first case.
Moreover, we already have fallback discrete animation procedures in CSS Animation
and Web Animation, so we should be able to not doing any fallback inside the
Animate trait.
In this patch, we let the animation between non-invertible matrices to return Err().
So, we can propagate the Err() to the callers, and let the fallback discrete
animation procedure stay at the Servo_MatrixTransform_Operate, which is ouside
the Animate trait.
Gecko bug: [Bug 1394284](https://bugzilla.mozilla.org/show_bug.cgi?id=1394284)
---
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] These changes fix [Bug 1394284](https://bugzilla.mozilla.org/show_bug.cgi?id=1394284)
- [X] There are wpt tests for these changes, and thet will be landed in [Bug 1394284](https://bugzilla.mozilla.org/show_bug.cgi?id=1394284)
Source-Repo: https://github.com/servo/servo
Source-Revision: ce7cee75e4c0c8357b489be42589d96348870627
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 830ee041c599c8dee799d36732e16f7e8b2fcd34
2017-09-21 11:16:58 +03:00
|
|
|
if let Ok(result) = result {
|
2017-06-07 09:54:41 +03:00
|
|
|
*output = result.into();
|
servo: Merge #18591 - stylo: do not handle the fallback discrete animation inside the Animate trait (from chenpighead:stylo-singular-matrix-animation); r=BorisChiou
At present, we do the fallback discrete animation for non-invertible matrices in
ComputedMatrix.animate(). However, according to the spec, we should fallback to
discrete animation for cases like:
1. animation between transform with single non-invertible matrix
2. animation between transform with matched transform functions that have at least
one non-invertible matrix
2. animation between transform with mismatched transform functions that have at
least one non-invertible matrix.
The current implementation only handles the first case.
Moreover, we already have fallback discrete animation procedures in CSS Animation
and Web Animation, so we should be able to not doing any fallback inside the
Animate trait.
In this patch, we let the animation between non-invertible matrices to return Err().
So, we can propagate the Err() to the callers, and let the fallback discrete
animation procedure stay at the Servo_MatrixTransform_Operate, which is ouside
the Animate trait.
Gecko bug: [Bug 1394284](https://bugzilla.mozilla.org/show_bug.cgi?id=1394284)
---
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] These changes fix [Bug 1394284](https://bugzilla.mozilla.org/show_bug.cgi?id=1394284)
- [X] There are wpt tests for these changes, and thet will be landed in [Bug 1394284](https://bugzilla.mozilla.org/show_bug.cgi?id=1394284)
Source-Repo: https://github.com/servo/servo
Source-Revision: ce7cee75e4c0c8357b489be42589d96348870627
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 830ee041c599c8dee799d36732e16f7e8b2fcd34
2017-09-21 11:16:58 +03:00
|
|
|
} else if progress < 0.5 {
|
|
|
|
*output = from.clone().into();
|
|
|
|
} else {
|
|
|
|
*output = to.clone().into();
|
|
|
|
}
|
2017-06-07 09:54:41 +03:00
|
|
|
}
|
|
|
|
|
2016-06-24 05:46:25 +03:00
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_ParseStyleAttribute(
|
|
|
|
data: *const nsACString,
|
|
|
|
raw_extra_data: *mut URLExtraData,
|
|
|
|
quirks_mode: nsCompatibility,
|
|
|
|
loader: *mut Loader,
|
|
|
|
) -> RawServoDeclarationBlockStrong {
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
2016-10-25 12:09:19 +03:00
|
|
|
let value = unsafe { data.as_ref().unwrap().as_str_unchecked() };
|
2017-07-11 04:13:44 +03:00
|
|
|
let reporter = ErrorReporter::new(ptr::null_mut(), loader, raw_extra_data);
|
2017-04-03 15:05:42 +03:00
|
|
|
let url_data = unsafe { RefPtr::from_ptr_ref(&raw_extra_data) };
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
Arc::new(global_style_data.shared_lock.wrap(
|
2017-07-11 04:13:44 +03:00
|
|
|
GeckoElement::parse_style_attribute(value, url_data, quirks_mode.into(), &reporter)))
|
|
|
|
.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 {
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
Arc::new(global_style_data.shared_lock.wrap(PropertyDeclarationBlock::new())).into_strong()
|
2016-11-04 07:42:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_Clone(declarations: RawServoDeclarationBlockBorrowed)
|
|
|
|
-> RawServoDeclarationBlockStrong {
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
let declarations = Locked::<PropertyDeclarationBlock>::as_arc(&declarations);
|
|
|
|
Arc::new(global_style_data.shared_lock.wrap(
|
|
|
|
declarations.read_with(&guard).clone()
|
|
|
|
)).into_strong()
|
2016-11-04 07:42:06 +03:00
|
|
|
}
|
|
|
|
|
2016-10-09 16:53:28 +03:00
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_Equals(
|
|
|
|
a: RawServoDeclarationBlockBorrowed,
|
|
|
|
b: RawServoDeclarationBlockBorrowed,
|
|
|
|
) -> bool {
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
*Locked::<PropertyDeclarationBlock>::as_arc(&a).read_with(&guard).declarations() ==
|
|
|
|
*Locked::<PropertyDeclarationBlock>::as_arc(&b).read_with(&guard).declarations()
|
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) {
|
2017-03-22 14:17:09 +03:00
|
|
|
read_locked_arc(declarations, |decls: &PropertyDeclarationBlock| {
|
|
|
|
decls.to_css(unsafe { result.as_mut().unwrap() }).unwrap();
|
|
|
|
})
|
2016-11-04 07:42:06 +03:00
|
|
|
}
|
|
|
|
|
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,
|
2017-08-21 07:05:57 +03:00
|
|
|
property_id: nsCSSPropertyID, buffer: *mut nsAString,
|
2017-09-27 12:35:00 +03:00
|
|
|
computed_values: ServoStyleContextBorrowedOrNull,
|
2017-10-13 22:11:02 +03:00
|
|
|
custom_properties: RawServoDeclarationBlockBorrowedOrNull,
|
|
|
|
) {
|
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
|
|
|
|
2017-09-27 12:35:00 +03:00
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
let decls = Locked::<PropertyDeclarationBlock>::as_arc(&declarations).read_with(&guard);
|
|
|
|
|
|
|
|
let mut string = String::new();
|
|
|
|
|
|
|
|
let custom_properties = Locked::<PropertyDeclarationBlock>::arc_from_borrowed(&custom_properties);
|
|
|
|
let custom_properties = custom_properties.map(|block| block.read_with(&guard));
|
|
|
|
let rv = decls.single_value_to_css(
|
|
|
|
&property_id, &mut string, computed_values, custom_properties);
|
|
|
|
debug_assert!(rv.is_ok());
|
|
|
|
|
|
|
|
let buffer = unsafe { buffer.as_mut().unwrap() };
|
|
|
|
buffer.assign_utf8(&string);
|
2016-10-09 16:53:28 +03:00
|
|
|
}
|
|
|
|
|
2017-05-22 07:22:35 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_SerializeFontValueForCanvas(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
2017-10-13 22:11:02 +03:00
|
|
|
buffer: *mut nsAString,
|
|
|
|
) {
|
2017-05-22 07:22:35 +03:00
|
|
|
use style::properties::shorthands::font;
|
|
|
|
|
|
|
|
read_locked_arc(declarations, |decls: &PropertyDeclarationBlock| {
|
2017-09-11 16:57:07 +03:00
|
|
|
let longhands = match font::LonghandsToSerialize::from_iter(decls.declarations().iter()) {
|
2017-05-22 07:22:35 +03:00
|
|
|
Ok(l) => l,
|
|
|
|
Err(()) => {
|
|
|
|
warn!("Unexpected property!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut string = String::new();
|
|
|
|
let rv = longhands.to_css_for_canvas(&mut string);
|
|
|
|
debug_assert!(rv.is_ok());
|
|
|
|
|
2017-06-09 02:23:56 +03:00
|
|
|
let buffer = unsafe { buffer.as_mut().unwrap() };
|
|
|
|
buffer.assign_utf8(&string);
|
2017-05-22 07:22:35 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-11-04 07:42:06 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_Count(declarations: RawServoDeclarationBlockBorrowed) -> u32 {
|
2017-03-22 14:17:09 +03:00
|
|
|
read_locked_arc(declarations, |decls: &PropertyDeclarationBlock| {
|
|
|
|
decls.declarations().len() as u32
|
|
|
|
})
|
2016-11-04 07:42:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_GetNthProperty(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
index: u32,
|
|
|
|
result: *mut nsAString,
|
|
|
|
) -> bool {
|
2017-03-22 14:17:09 +03:00
|
|
|
read_locked_arc(declarations, |decls: &PropertyDeclarationBlock| {
|
2017-09-11 16:57:07 +03:00
|
|
|
if let Some(decl) = decls.declarations().get(index as usize) {
|
2017-03-22 14:17:09 +03:00
|
|
|
let result = unsafe { result.as_mut().unwrap() };
|
2017-05-02 12:19:59 +03:00
|
|
|
result.assign_utf8(&decl.id().name());
|
2017-03-22 14:17:09 +03:00
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
})
|
2016-11-04 07:42:06 +03:00
|
|
|
}
|
|
|
|
|
2016-12-18 05:22:10 +03:00
|
|
|
macro_rules! get_property_id_from_property {
|
|
|
|
($property: ident, $ret: expr) => {{
|
2017-09-07 14:55:02 +03:00
|
|
|
let property = $property.as_ref().unwrap().as_str_unchecked();
|
2017-11-21 16:47:52 +03:00
|
|
|
match PropertyId::parse(property.into()) {
|
2016-12-18 05:22:10 +03:00
|
|
|
Ok(property_id) => property_id,
|
2017-06-10 00:31:48 +03:00
|
|
|
Err(_) => { return $ret; }
|
2016-12-18 05:22:10 +03:00
|
|
|
}
|
|
|
|
}}
|
|
|
|
}
|
|
|
|
|
2017-09-07 14:55:02 +03:00
|
|
|
unsafe fn get_property_value(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property_id: PropertyId,
|
|
|
|
value: *mut nsAString,
|
|
|
|
) {
|
2017-09-06 07:20:55 +03:00
|
|
|
// This callsite is hot enough that the lock acquisition shows up in profiles.
|
|
|
|
// Using an unchecked read here improves our performance by ~10% on the
|
|
|
|
// microbenchmark in bug 1355599.
|
2017-09-07 14:55:02 +03:00
|
|
|
read_locked_arc_unchecked(declarations, |decls: &PropertyDeclarationBlock| {
|
|
|
|
decls.property_value_to_css(&property_id, value.as_mut().unwrap()).unwrap();
|
|
|
|
})
|
2016-11-04 07:42:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-09-07 14:55:02 +03:00
|
|
|
pub unsafe extern "C" fn Servo_DeclarationBlock_GetPropertyValue(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: *const nsACString,
|
|
|
|
value: *mut nsAString,
|
|
|
|
) {
|
|
|
|
get_property_value(
|
|
|
|
declarations,
|
|
|
|
get_property_id_from_property!(property, ()),
|
|
|
|
value,
|
|
|
|
)
|
2016-12-18 05:22:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-09-07 14:55:02 +03:00
|
|
|
pub unsafe extern "C" fn Servo_DeclarationBlock_GetPropertyValueById(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: nsCSSPropertyID,
|
|
|
|
value: *mut nsAString,
|
|
|
|
) {
|
2016-12-18 05:22:10 +03:00
|
|
|
get_property_value(declarations, get_property_id_from_nscsspropertyid!(property, ()), value)
|
2016-11-04 07:42:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-09-07 14:55:02 +03:00
|
|
|
pub unsafe extern "C" fn Servo_DeclarationBlock_GetPropertyIsImportant(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: *const nsACString,
|
|
|
|
) -> bool {
|
2016-12-18 05:22:10 +03:00
|
|
|
let property_id = get_property_id_from_property!(property, false);
|
2017-03-22 14:17:09 +03:00
|
|
|
read_locked_arc(declarations, |decls: &PropertyDeclarationBlock| {
|
|
|
|
decls.property_priority(&property_id).important()
|
|
|
|
})
|
2016-11-04 07:42:06 +03:00
|
|
|
}
|
|
|
|
|
2017-10-13 22:11:02 +03:00
|
|
|
fn set_property(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property_id: PropertyId,
|
|
|
|
value: *const nsACString,
|
|
|
|
is_important: bool,
|
|
|
|
data: *mut URLExtraData,
|
|
|
|
parsing_mode: structs::ParsingMode,
|
|
|
|
quirks_mode: QuirksMode,
|
|
|
|
loader: *mut Loader
|
|
|
|
) -> bool {
|
2017-05-20 02:37:14 +03:00
|
|
|
let mut source_declarations = SourcePropertyDeclaration::new();
|
2017-07-11 04:13:44 +03:00
|
|
|
let reporter = ErrorReporter::new(ptr::null_mut(), loader, data);
|
2017-05-20 02:37:14 +03:00
|
|
|
match parse_property_into(&mut source_declarations, property_id, value, data,
|
2017-07-11 04:13:44 +03:00
|
|
|
parsing_mode, quirks_mode, &reporter) {
|
2017-05-20 02:37:14 +03:00
|
|
|
Ok(()) => {
|
2017-05-11 05:25:47 +03:00
|
|
|
let importance = if is_important { Importance::Important } else { Importance::Normal };
|
|
|
|
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
|
2017-10-14 13:27:51 +03:00
|
|
|
decls.extend(
|
|
|
|
source_declarations.drain(),
|
|
|
|
importance,
|
|
|
|
DeclarationSource::CssOm
|
|
|
|
)
|
2017-05-11 05:25:47 +03:00
|
|
|
})
|
|
|
|
},
|
|
|
|
Err(_) => false,
|
2016-11-04 07:42:06 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-09-07 14:55:02 +03:00
|
|
|
pub unsafe extern "C" fn Servo_DeclarationBlock_SetProperty(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: *const nsACString,
|
|
|
|
value: *const nsACString,
|
|
|
|
is_important: bool,
|
|
|
|
data: *mut URLExtraData,
|
|
|
|
parsing_mode: structs::ParsingMode,
|
|
|
|
quirks_mode: nsCompatibility,
|
|
|
|
loader: *mut Loader,
|
|
|
|
) -> bool {
|
|
|
|
set_property(
|
|
|
|
declarations,
|
|
|
|
get_property_id_from_property!(property, false),
|
|
|
|
value,
|
|
|
|
is_important,
|
|
|
|
data,
|
|
|
|
parsing_mode,
|
|
|
|
quirks_mode.into(),
|
|
|
|
loader,
|
|
|
|
)
|
2016-12-18 05:22:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-09-07 14:55:02 +03:00
|
|
|
pub unsafe extern "C" fn Servo_DeclarationBlock_SetPropertyById(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: nsCSSPropertyID,
|
|
|
|
value: *const nsACString,
|
|
|
|
is_important: bool,
|
|
|
|
data: *mut URLExtraData,
|
|
|
|
parsing_mode: structs::ParsingMode,
|
|
|
|
quirks_mode: nsCompatibility,
|
|
|
|
loader: *mut Loader,
|
|
|
|
) -> bool {
|
|
|
|
set_property(
|
|
|
|
declarations,
|
|
|
|
get_property_id_from_nscsspropertyid!(property, false),
|
|
|
|
value,
|
|
|
|
is_important,
|
|
|
|
data,
|
|
|
|
parsing_mode,
|
|
|
|
quirks_mode.into(),
|
|
|
|
loader,
|
|
|
|
)
|
2016-12-18 05:22:10 +03:00
|
|
|
}
|
|
|
|
|
2017-10-20 13:26:18 +03:00
|
|
|
fn remove_property(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property_id: PropertyId
|
|
|
|
) -> bool {
|
2017-03-22 14:17:09 +03:00
|
|
|
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
|
2017-10-20 13:26:18 +03:00
|
|
|
decls.remove_property(&property_id)
|
|
|
|
})
|
2016-12-18 05:22:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-09-07 14:55:02 +03:00
|
|
|
pub unsafe extern "C" fn Servo_DeclarationBlock_RemoveProperty(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: *const nsACString,
|
|
|
|
) {
|
2017-10-20 13:26:18 +03:00
|
|
|
remove_property(declarations, get_property_id_from_property!(property, ()));
|
2016-12-18 05:22:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-20 13:26:18 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_RemovePropertyById(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: nsCSSPropertyID
|
|
|
|
) -> bool {
|
|
|
|
remove_property(declarations, get_property_id_from_nscsspropertyid!(property, false))
|
2016-11-04 07:42:06 +03:00
|
|
|
}
|
|
|
|
|
2017-04-12 18:00:26 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_MediaList_Create() -> RawServoMediaListStrong {
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
Arc::new(global_style_data.shared_lock.wrap(MediaList::empty())).into_strong()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_MediaList_DeepClone(list: RawServoMediaListBorrowed) -> RawServoMediaListStrong {
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
read_locked_arc(list, |list: &MediaList| {
|
|
|
|
Arc::new(global_style_data.shared_lock.wrap(list.clone()))
|
|
|
|
.into_strong()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_MediaList_Matches(
|
|
|
|
list: RawServoMediaListBorrowed,
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
|
|
|
) -> bool {
|
2017-04-12 18:00:26 +03:00
|
|
|
let per_doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
|
|
|
read_locked_arc(list, |list: &MediaList| {
|
2017-05-23 04:12:46 +03:00
|
|
|
list.evaluate(per_doc_data.stylist.device(), per_doc_data.stylist.quirks_mode())
|
2017-04-12 18:00:26 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-04-15 14:20:52 +03:00
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_HasCSSWideKeyword(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: nsCSSPropertyID,
|
|
|
|
) -> bool {
|
2017-04-15 14:20:52 +03:00
|
|
|
let property_id = get_property_id_from_nscsspropertyid!(property, false);
|
|
|
|
read_locked_arc(declarations, |decls: &PropertyDeclarationBlock| {
|
|
|
|
decls.has_css_wide_keyword(&property_id)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-03-13 09:55:46 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_MediaList_GetText(list: RawServoMediaListBorrowed, result: *mut nsAString) {
|
2017-03-22 14:17:09 +03:00
|
|
|
read_locked_arc(list, |list: &MediaList| {
|
|
|
|
list.to_css(unsafe { result.as_mut().unwrap() }).unwrap();
|
|
|
|
})
|
2017-03-13 09:55:46 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-25 15:50:46 +03:00
|
|
|
pub unsafe extern "C" fn Servo_MediaList_SetText(
|
|
|
|
list: RawServoMediaListBorrowed,
|
|
|
|
text: *const nsACString,
|
|
|
|
caller_type: CallerType,
|
|
|
|
) {
|
|
|
|
let text = (*text).as_str_unchecked();
|
|
|
|
|
2017-06-10 00:31:48 +03:00
|
|
|
let mut input = ParserInput::new(&text);
|
|
|
|
let mut parser = Parser::new(&mut input);
|
2017-10-25 15:50:46 +03:00
|
|
|
let url_data = dummy_url_data();
|
|
|
|
|
|
|
|
// TODO(emilio): If the need for `CallerType` appears in more places,
|
|
|
|
// consider adding an explicit member in `ParserContext` instead of doing
|
|
|
|
// this (or adding a dummy "chrome://" url data).
|
|
|
|
//
|
|
|
|
// For media query parsing it's effectively the same, so for now...
|
|
|
|
let origin = match caller_type {
|
|
|
|
CallerType::System => Origin::UserAgent,
|
|
|
|
CallerType::NonSystem => Origin::Author,
|
|
|
|
};
|
|
|
|
|
|
|
|
let context = ParserContext::new(
|
|
|
|
origin,
|
|
|
|
url_data,
|
|
|
|
Some(CssRuleType::Media),
|
2017-10-31 02:25:45 +03:00
|
|
|
ParsingMode::DEFAULT,
|
2017-10-25 15:50:46 +03:00
|
|
|
QuirksMode::NoQuirks,
|
|
|
|
);
|
|
|
|
|
|
|
|
write_locked_arc(list, |list: &mut MediaList| {
|
|
|
|
*list = parse_media_query_list(
|
|
|
|
&context,
|
|
|
|
&mut parser,
|
|
|
|
&NullReporter,
|
|
|
|
);
|
2017-03-22 14:17:09 +03:00
|
|
|
})
|
2017-03-13 09:55:46 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_MediaList_GetLength(list: RawServoMediaListBorrowed) -> u32 {
|
2017-03-22 14:17:09 +03:00
|
|
|
read_locked_arc(list, |list: &MediaList| list.media_queries.len() as u32)
|
2017-03-13 09:55:46 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_MediaList_GetMediumAt(
|
|
|
|
list: RawServoMediaListBorrowed,
|
|
|
|
index: u32,
|
|
|
|
result: *mut nsAString,
|
|
|
|
) -> bool {
|
2017-03-22 14:17:09 +03:00
|
|
|
read_locked_arc(list, |list: &MediaList| {
|
|
|
|
if let Some(media_query) = list.media_queries.get(index as usize) {
|
|
|
|
media_query.to_css(unsafe { result.as_mut().unwrap() }).unwrap();
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
})
|
2017-03-13 09:55:46 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_MediaList_AppendMedium(
|
|
|
|
list: RawServoMediaListBorrowed,
|
|
|
|
new_medium: *const nsACString,
|
|
|
|
) {
|
2017-03-13 09:55:46 +03:00
|
|
|
let new_medium = unsafe { new_medium.as_ref().unwrap().as_str_unchecked() };
|
2017-04-12 13:38:50 +03:00
|
|
|
let url_data = unsafe { dummy_url_data() };
|
2017-08-24 21:19:25 +03:00
|
|
|
let context = ParserContext::new_for_cssom(url_data, Some(CssRuleType::Media),
|
2017-10-31 02:25:45 +03:00
|
|
|
ParsingMode::DEFAULT,
|
2017-04-28 06:32:24 +03:00
|
|
|
QuirksMode::NoQuirks);
|
2017-03-22 14:17:09 +03:00
|
|
|
write_locked_arc(list, |list: &mut MediaList| {
|
2017-04-12 13:38:50 +03:00
|
|
|
list.append_medium(&context, new_medium);
|
2017-03-22 14:17:09 +03:00
|
|
|
})
|
2017-03-13 09:55:46 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_MediaList_DeleteMedium(
|
|
|
|
list: RawServoMediaListBorrowed,
|
|
|
|
old_medium: *const nsACString,
|
|
|
|
) -> bool {
|
2017-03-13 09:55:46 +03:00
|
|
|
let old_medium = unsafe { old_medium.as_ref().unwrap().as_str_unchecked() };
|
2017-04-12 13:38:50 +03:00
|
|
|
let url_data = unsafe { dummy_url_data() };
|
2017-08-24 21:19:25 +03:00
|
|
|
let context = ParserContext::new_for_cssom(url_data, Some(CssRuleType::Media),
|
2017-10-31 02:25:45 +03:00
|
|
|
ParsingMode::DEFAULT,
|
2017-04-28 06:32:24 +03:00
|
|
|
QuirksMode::NoQuirks);
|
2017-04-12 13:38:50 +03:00
|
|
|
write_locked_arc(list, |list: &mut MediaList| list.delete_medium(&context, old_medium))
|
2017-03-13 09:55:46 +03:00
|
|
|
}
|
|
|
|
|
2017-02-19 07:43:33 +03:00
|
|
|
macro_rules! get_longhand_from_id {
|
2017-05-11 03:05:21 +03:00
|
|
|
($id:expr) => {
|
2017-02-19 07:43:33 +03:00
|
|
|
match PropertyId::from_nscsspropertyid($id) {
|
|
|
|
Ok(PropertyId::Longhand(long)) => long,
|
|
|
|
_ => {
|
2017-05-11 03:05:21 +03:00
|
|
|
panic!("stylo: unknown presentation property with id {:?}", $id);
|
2017-02-19 07:43:33 +03:00
|
|
|
}
|
2017-02-04 04:36:04 +03:00
|
|
|
}
|
|
|
|
};
|
2017-02-19 07:43:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! match_wrap_declared {
|
|
|
|
($longhand:ident, $($property:ident => $inner:expr,)*) => (
|
|
|
|
match $longhand {
|
|
|
|
$(
|
2017-03-17 00:48:53 +03:00
|
|
|
LonghandId::$property => PropertyDeclaration::$property($inner),
|
2017-02-19 07:43:33 +03:00
|
|
|
)*
|
|
|
|
_ => {
|
2017-05-11 03:05:21 +03:00
|
|
|
panic!("stylo: Don't know how to handle presentation property {:?}", $longhand);
|
2017-02-04 04:36:04 +03:00
|
|
|
}
|
|
|
|
}
|
2017-02-19 07:43:33 +03:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_PropertyIsSet(declarations:
|
|
|
|
RawServoDeclarationBlockBorrowed,
|
|
|
|
property: nsCSSPropertyID)
|
|
|
|
-> bool {
|
2017-03-22 14:17:09 +03:00
|
|
|
read_locked_arc(declarations, |decls: &PropertyDeclarationBlock| {
|
2017-09-12 02:50:19 +03:00
|
|
|
decls.contains(get_longhand_from_id!(property))
|
2017-03-22 14:17:09 +03:00
|
|
|
})
|
2017-02-19 07:43:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_SetIdentStringValue(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: nsCSSPropertyID,
|
|
|
|
value: *mut nsAtom,
|
|
|
|
) {
|
2017-03-17 00:48:53 +03:00
|
|
|
use style::properties::{PropertyDeclaration, LonghandId};
|
2017-02-19 07:43:33 +03:00
|
|
|
use style::properties::longhands::_x_lang::computed_value::T as Lang;
|
|
|
|
|
|
|
|
let long = get_longhand_from_id!(property);
|
|
|
|
let prop = match_wrap_declared! { long,
|
|
|
|
XLang => Lang(Atom::from(value)),
|
|
|
|
};
|
2017-03-22 14:17:09 +03:00
|
|
|
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
|
2017-10-14 13:27:51 +03:00
|
|
|
decls.push(prop, Importance::Normal, DeclarationSource::CssOm);
|
2017-03-22 14:17:09 +03:00
|
|
|
})
|
2017-02-19 07:43:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
#[allow(unreachable_code)]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_SetKeywordValue(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: nsCSSPropertyID,
|
|
|
|
value: i32
|
|
|
|
) {
|
2017-03-17 00:48:53 +03:00
|
|
|
use style::properties::{PropertyDeclaration, LonghandId};
|
2017-02-19 07:43:33 +03:00
|
|
|
use style::properties::longhands;
|
2017-03-20 10:28:46 +03:00
|
|
|
use style::values::specified::BorderStyle;
|
2017-02-19 07:43:33 +03:00
|
|
|
|
|
|
|
let long = get_longhand_from_id!(property);
|
|
|
|
let value = value as u32;
|
|
|
|
|
|
|
|
let prop = match_wrap_declared! { long,
|
|
|
|
MozUserModify => longhands::_moz_user_modify::SpecifiedValue::from_gecko_keyword(value),
|
|
|
|
// TextEmphasisPosition => FIXME implement text-emphasis-position
|
2017-04-12 17:16:55 +03:00
|
|
|
Direction => longhands::direction::SpecifiedValue::from_gecko_keyword(value),
|
2017-02-19 07:43:33 +03:00
|
|
|
Display => longhands::display::SpecifiedValue::from_gecko_keyword(value),
|
|
|
|
Float => longhands::float::SpecifiedValue::from_gecko_keyword(value),
|
|
|
|
VerticalAlign => longhands::vertical_align::SpecifiedValue::from_gecko_keyword(value),
|
|
|
|
TextAlign => longhands::text_align::SpecifiedValue::from_gecko_keyword(value),
|
2017-03-31 14:01:06 +03:00
|
|
|
TextEmphasisPosition => longhands::text_emphasis_position::SpecifiedValue::from_gecko_keyword(value),
|
2017-02-19 07:43:33 +03:00
|
|
|
Clear => longhands::clear::SpecifiedValue::from_gecko_keyword(value),
|
|
|
|
FontSize => {
|
|
|
|
// We rely on Gecko passing in font-size values (0...7) here.
|
2017-03-20 10:28:46 +03:00
|
|
|
longhands::font_size::SpecifiedValue::from_html_size(value as u8)
|
2017-02-19 07:43:33 +03:00
|
|
|
},
|
2017-09-17 23:12:46 +03:00
|
|
|
FontStyle => {
|
|
|
|
ToComputedValue::from_computed_value(&longhands::font_style::computed_value::T::from_gecko_keyword(value))
|
|
|
|
},
|
2017-04-12 17:16:55 +03:00
|
|
|
FontWeight => longhands::font_weight::SpecifiedValue::from_gecko_keyword(value),
|
2017-05-27 15:09:30 +03:00
|
|
|
ListStyleType => Box::new(longhands::list_style_type::SpecifiedValue::from_gecko_keyword(value)),
|
2017-04-12 17:16:55 +03:00
|
|
|
MozMathVariant => longhands::_moz_math_variant::SpecifiedValue::from_gecko_keyword(value),
|
2017-02-19 07:43:33 +03:00
|
|
|
WhiteSpace => longhands::white_space::SpecifiedValue::from_gecko_keyword(value),
|
|
|
|
CaptionSide => longhands::caption_side::SpecifiedValue::from_gecko_keyword(value),
|
|
|
|
BorderTopStyle => BorderStyle::from_gecko_keyword(value),
|
|
|
|
BorderRightStyle => BorderStyle::from_gecko_keyword(value),
|
|
|
|
BorderBottomStyle => BorderStyle::from_gecko_keyword(value),
|
|
|
|
BorderLeftStyle => BorderStyle::from_gecko_keyword(value),
|
|
|
|
};
|
2017-03-22 14:17:09 +03:00
|
|
|
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
|
2017-10-14 13:27:51 +03:00
|
|
|
decls.push(prop, Importance::Normal, DeclarationSource::CssOm);
|
2017-03-22 14:17:09 +03:00
|
|
|
})
|
2017-02-19 07:43:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_SetIntValue(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: nsCSSPropertyID,
|
|
|
|
value: i32
|
|
|
|
) {
|
2017-03-17 00:48:53 +03:00
|
|
|
use style::properties::{PropertyDeclaration, LonghandId};
|
2017-04-12 17:16:55 +03:00
|
|
|
use style::properties::longhands::_moz_script_level::SpecifiedValue as MozScriptLevel;
|
2017-02-19 07:43:33 +03:00
|
|
|
use style::properties::longhands::_x_span::computed_value::T as Span;
|
|
|
|
|
|
|
|
let long = get_longhand_from_id!(property);
|
|
|
|
let prop = match_wrap_declared! { long,
|
|
|
|
XSpan => Span(value),
|
2017-04-12 17:16:55 +03:00
|
|
|
// Gecko uses Integer values to signal that it is relative
|
|
|
|
MozScriptLevel => MozScriptLevel::Relative(value),
|
2017-02-19 07:43:33 +03:00
|
|
|
};
|
2017-03-22 14:17:09 +03:00
|
|
|
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
|
2017-10-14 13:27:51 +03:00
|
|
|
decls.push(prop, Importance::Normal, DeclarationSource::CssOm);
|
2017-03-22 14:17:09 +03:00
|
|
|
})
|
2017-02-19 07:43:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_SetPixelValue(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: nsCSSPropertyID,
|
|
|
|
value: f32
|
|
|
|
) {
|
2017-03-17 00:48:53 +03:00
|
|
|
use style::properties::{PropertyDeclaration, LonghandId};
|
2017-02-19 07:43:33 +03:00
|
|
|
use style::properties::longhands::border_spacing::SpecifiedValue as BorderSpacing;
|
2017-05-22 09:46:01 +03:00
|
|
|
use style::properties::longhands::height::SpecifiedValue as Height;
|
|
|
|
use style::properties::longhands::width::SpecifiedValue as Width;
|
2017-09-17 23:12:46 +03:00
|
|
|
use style::values::specified::{BorderSideWidth, MozLength, BorderCornerRadius};
|
|
|
|
use style::values::specified::length::{NoCalcLength, NonNegativeLength, LengthOrPercentage};
|
2017-02-19 07:43:33 +03:00
|
|
|
|
|
|
|
let long = get_longhand_from_id!(property);
|
|
|
|
let nocalc = NoCalcLength::from_px(value);
|
|
|
|
|
|
|
|
let prop = match_wrap_declared! { long,
|
2017-05-22 09:46:01 +03:00
|
|
|
Height => Height(MozLength::LengthOrPercentageOrAuto(nocalc.into())),
|
|
|
|
Width => Width(MozLength::LengthOrPercentageOrAuto(nocalc.into())),
|
2017-06-02 11:53:55 +03:00
|
|
|
BorderTopWidth => BorderSideWidth::Length(nocalc.into()),
|
|
|
|
BorderRightWidth => BorderSideWidth::Length(nocalc.into()),
|
|
|
|
BorderBottomWidth => BorderSideWidth::Length(nocalc.into()),
|
|
|
|
BorderLeftWidth => BorderSideWidth::Length(nocalc.into()),
|
2017-02-19 07:43:33 +03:00
|
|
|
MarginTop => nocalc.into(),
|
|
|
|
MarginRight => nocalc.into(),
|
|
|
|
MarginBottom => nocalc.into(),
|
|
|
|
MarginLeft => nocalc.into(),
|
|
|
|
PaddingTop => nocalc.into(),
|
|
|
|
PaddingRight => nocalc.into(),
|
|
|
|
PaddingBottom => nocalc.into(),
|
|
|
|
PaddingLeft => nocalc.into(),
|
2017-09-17 23:12:46 +03:00
|
|
|
BorderSpacing => {
|
|
|
|
let v = NonNegativeLength::from(nocalc);
|
|
|
|
Box::new(BorderSpacing::new(v.clone(), v))
|
|
|
|
},
|
|
|
|
BorderTopLeftRadius => {
|
|
|
|
let length = LengthOrPercentage::from(nocalc);
|
|
|
|
Box::new(BorderCornerRadius::new(length.clone(), length))
|
|
|
|
},
|
|
|
|
BorderTopRightRadius => {
|
|
|
|
let length = LengthOrPercentage::from(nocalc);
|
|
|
|
Box::new(BorderCornerRadius::new(length.clone(), length))
|
|
|
|
},
|
|
|
|
BorderBottomLeftRadius => {
|
|
|
|
let length = LengthOrPercentage::from(nocalc);
|
|
|
|
Box::new(BorderCornerRadius::new(length.clone(), length))
|
|
|
|
},
|
|
|
|
BorderBottomRightRadius => {
|
|
|
|
let length = LengthOrPercentage::from(nocalc);
|
|
|
|
Box::new(BorderCornerRadius::new(length.clone(), length))
|
|
|
|
},
|
2017-02-19 07:43:33 +03:00
|
|
|
};
|
2017-03-22 14:17:09 +03:00
|
|
|
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
|
2017-10-14 13:27:51 +03:00
|
|
|
decls.push(prop, Importance::Normal, DeclarationSource::CssOm);
|
2017-03-22 14:17:09 +03:00
|
|
|
})
|
2017-02-19 07:43:33 +03:00
|
|
|
}
|
|
|
|
|
2017-04-12 17:16:55 +03:00
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_SetLengthValue(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: nsCSSPropertyID,
|
|
|
|
value: f32,
|
|
|
|
unit: structs::nsCSSUnit,
|
|
|
|
) {
|
2017-04-12 17:16:55 +03:00
|
|
|
use style::properties::{PropertyDeclaration, LonghandId};
|
2017-04-25 21:06:23 +03:00
|
|
|
use style::properties::longhands::_moz_script_min_size::SpecifiedValue as MozScriptMinSize;
|
2017-05-22 09:46:01 +03:00
|
|
|
use style::properties::longhands::width::SpecifiedValue as Width;
|
|
|
|
use style::values::specified::MozLength;
|
2017-11-14 16:27:28 +03:00
|
|
|
use style::values::specified::length::{AbsoluteLength, FontRelativeLength};
|
2017-04-12 17:16:55 +03:00
|
|
|
use style::values::specified::length::{LengthOrPercentage, NoCalcLength};
|
|
|
|
|
|
|
|
let long = get_longhand_from_id!(property);
|
|
|
|
let nocalc = match unit {
|
|
|
|
structs::nsCSSUnit::eCSSUnit_EM => NoCalcLength::FontRelative(FontRelativeLength::Em(value)),
|
|
|
|
structs::nsCSSUnit::eCSSUnit_XHeight => NoCalcLength::FontRelative(FontRelativeLength::Ex(value)),
|
|
|
|
structs::nsCSSUnit::eCSSUnit_Pixel => NoCalcLength::Absolute(AbsoluteLength::Px(value)),
|
|
|
|
structs::nsCSSUnit::eCSSUnit_Inch => NoCalcLength::Absolute(AbsoluteLength::In(value)),
|
|
|
|
structs::nsCSSUnit::eCSSUnit_Centimeter => NoCalcLength::Absolute(AbsoluteLength::Cm(value)),
|
|
|
|
structs::nsCSSUnit::eCSSUnit_Millimeter => NoCalcLength::Absolute(AbsoluteLength::Mm(value)),
|
|
|
|
structs::nsCSSUnit::eCSSUnit_Point => NoCalcLength::Absolute(AbsoluteLength::Pt(value)),
|
|
|
|
structs::nsCSSUnit::eCSSUnit_Pica => NoCalcLength::Absolute(AbsoluteLength::Pc(value)),
|
|
|
|
structs::nsCSSUnit::eCSSUnit_Quarter => NoCalcLength::Absolute(AbsoluteLength::Q(value)),
|
|
|
|
_ => unreachable!("Unknown unit {:?} passed to SetLengthValue", unit)
|
|
|
|
};
|
|
|
|
|
|
|
|
let prop = match_wrap_declared! { long,
|
2017-05-22 09:46:01 +03:00
|
|
|
Width => Width(MozLength::LengthOrPercentageOrAuto(nocalc.into())),
|
2017-04-12 17:16:55 +03:00
|
|
|
FontSize => LengthOrPercentage::from(nocalc).into(),
|
2017-04-25 21:06:23 +03:00
|
|
|
MozScriptMinSize => MozScriptMinSize(nocalc),
|
2017-04-12 17:16:55 +03:00
|
|
|
};
|
|
|
|
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
|
2017-10-14 13:27:51 +03:00
|
|
|
decls.push(prop, Importance::Normal, DeclarationSource::CssOm);
|
2017-04-12 17:16:55 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_SetNumberValue(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: nsCSSPropertyID,
|
|
|
|
value: f32,
|
|
|
|
) {
|
2017-04-12 17:16:55 +03:00
|
|
|
use style::properties::{PropertyDeclaration, LonghandId};
|
|
|
|
use style::properties::longhands::_moz_script_level::SpecifiedValue as MozScriptLevel;
|
2017-11-23 13:28:18 +03:00
|
|
|
use style::properties::longhands::_moz_script_size_multiplier::SpecifiedValue as MozScriptSizeMultiplier;
|
2017-04-12 17:16:55 +03:00
|
|
|
|
|
|
|
let long = get_longhand_from_id!(property);
|
|
|
|
|
|
|
|
let prop = match_wrap_declared! { long,
|
2017-11-23 13:28:18 +03:00
|
|
|
MozScriptSizeMultiplier => MozScriptSizeMultiplier(value),
|
2017-04-12 17:16:55 +03:00
|
|
|
// Gecko uses Number values to signal that it is absolute
|
2017-11-12 18:41:04 +03:00
|
|
|
MozScriptLevel => MozScriptLevel::MozAbsolute(value as i32),
|
2017-04-12 17:16:55 +03:00
|
|
|
};
|
|
|
|
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
|
2017-10-14 13:27:51 +03:00
|
|
|
decls.push(prop, Importance::Normal, DeclarationSource::CssOm);
|
2017-04-12 17:16:55 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-02-19 07:43:33 +03:00
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_SetPercentValue(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: nsCSSPropertyID,
|
|
|
|
value: f32,
|
|
|
|
) {
|
2017-03-17 00:48:53 +03:00
|
|
|
use style::properties::{PropertyDeclaration, LonghandId};
|
2017-05-22 09:46:01 +03:00
|
|
|
use style::properties::longhands::height::SpecifiedValue as Height;
|
|
|
|
use style::properties::longhands::width::SpecifiedValue as Width;
|
2017-07-17 11:29:11 +03:00
|
|
|
use style::values::computed::Percentage;
|
2017-05-22 09:46:01 +03:00
|
|
|
use style::values::specified::MozLength;
|
2017-07-17 11:29:11 +03:00
|
|
|
use style::values::specified::length::LengthOrPercentage;
|
2017-02-19 07:43:33 +03:00
|
|
|
|
|
|
|
let long = get_longhand_from_id!(property);
|
|
|
|
let pc = Percentage(value);
|
|
|
|
|
|
|
|
let prop = match_wrap_declared! { long,
|
2017-05-22 09:46:01 +03:00
|
|
|
Height => Height(MozLength::LengthOrPercentageOrAuto(pc.into())),
|
|
|
|
Width => Width(MozLength::LengthOrPercentageOrAuto(pc.into())),
|
2017-02-19 07:43:33 +03:00
|
|
|
MarginTop => pc.into(),
|
|
|
|
MarginRight => pc.into(),
|
|
|
|
MarginBottom => pc.into(),
|
|
|
|
MarginLeft => pc.into(),
|
2017-04-12 17:16:55 +03:00
|
|
|
FontSize => LengthOrPercentage::from(pc).into(),
|
2017-02-19 07:43:33 +03:00
|
|
|
};
|
2017-03-22 14:17:09 +03:00
|
|
|
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
|
2017-10-14 13:27:51 +03:00
|
|
|
decls.push(prop, Importance::Normal, DeclarationSource::CssOm);
|
2017-03-22 14:17:09 +03:00
|
|
|
})
|
2017-02-19 07:43:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_SetAutoValue(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: nsCSSPropertyID,
|
|
|
|
) {
|
2017-03-17 00:48:53 +03:00
|
|
|
use style::properties::{PropertyDeclaration, LonghandId};
|
2017-05-22 09:46:01 +03:00
|
|
|
use style::properties::longhands::height::SpecifiedValue as Height;
|
|
|
|
use style::properties::longhands::width::SpecifiedValue as Width;
|
2017-02-19 07:43:33 +03:00
|
|
|
use style::values::specified::LengthOrPercentageOrAuto;
|
|
|
|
|
|
|
|
let long = get_longhand_from_id!(property);
|
|
|
|
let auto = LengthOrPercentageOrAuto::Auto;
|
|
|
|
|
|
|
|
let prop = match_wrap_declared! { long,
|
2017-05-22 09:46:01 +03:00
|
|
|
Height => Height::auto(),
|
|
|
|
Width => Width::auto(),
|
2017-02-19 07:43:33 +03:00
|
|
|
MarginTop => auto,
|
|
|
|
MarginRight => auto,
|
|
|
|
MarginBottom => auto,
|
|
|
|
MarginLeft => auto,
|
2017-02-04 04:36:04 +03:00
|
|
|
};
|
2017-03-22 14:17:09 +03:00
|
|
|
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
|
2017-10-14 13:27:51 +03:00
|
|
|
decls.push(prop, Importance::Normal, DeclarationSource::CssOm);
|
2017-03-22 14:17:09 +03:00
|
|
|
})
|
2017-02-19 07:43:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_SetCurrentColor(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: nsCSSPropertyID,
|
|
|
|
) {
|
2017-03-17 00:48:53 +03:00
|
|
|
use style::properties::{PropertyDeclaration, LonghandId};
|
2017-06-08 07:03:52 +03:00
|
|
|
use style::values::specified::Color;
|
2017-02-04 04:36:04 +03:00
|
|
|
|
2017-02-19 07:43:33 +03:00
|
|
|
let long = get_longhand_from_id!(property);
|
2017-06-08 07:03:52 +03:00
|
|
|
let cc = Color::currentcolor();
|
2017-02-19 07:43:33 +03:00
|
|
|
|
|
|
|
let prop = match_wrap_declared! { long,
|
|
|
|
BorderTopColor => cc,
|
|
|
|
BorderRightColor => cc,
|
|
|
|
BorderBottomColor => cc,
|
|
|
|
BorderLeftColor => cc,
|
|
|
|
};
|
2017-03-22 14:17:09 +03:00
|
|
|
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
|
2017-10-14 13:27:51 +03:00
|
|
|
decls.push(prop, Importance::Normal, DeclarationSource::CssOm);
|
2017-03-22 14:17:09 +03:00
|
|
|
})
|
2017-02-19 07:43:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_SetColorValue(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: nsCSSPropertyID,
|
|
|
|
value: structs::nscolor,
|
|
|
|
) {
|
2017-02-19 07:43:33 +03:00
|
|
|
use style::gecko::values::convert_nscolor_to_rgba;
|
2017-03-17 00:48:53 +03:00
|
|
|
use style::properties::{PropertyDeclaration, LonghandId};
|
2017-02-28 10:08:33 +03:00
|
|
|
use style::properties::longhands;
|
2017-06-08 07:03:52 +03:00
|
|
|
use style::values::specified::Color;
|
2017-02-19 07:43:33 +03:00
|
|
|
|
|
|
|
let long = get_longhand_from_id!(property);
|
|
|
|
let rgba = convert_nscolor_to_rgba(value);
|
2017-06-08 07:03:52 +03:00
|
|
|
let color = Color::rgba(rgba);
|
2017-02-19 07:43:33 +03:00
|
|
|
|
|
|
|
let prop = match_wrap_declared! { long,
|
|
|
|
BorderTopColor => color,
|
|
|
|
BorderRightColor => color,
|
|
|
|
BorderBottomColor => color,
|
|
|
|
BorderLeftColor => color,
|
2017-02-28 10:08:33 +03:00
|
|
|
Color => longhands::color::SpecifiedValue(color),
|
2017-02-19 07:43:33 +03:00
|
|
|
BackgroundColor => color,
|
|
|
|
};
|
2017-03-22 14:17:09 +03:00
|
|
|
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
|
2017-10-14 13:27:51 +03:00
|
|
|
decls.push(prop, Importance::Normal, DeclarationSource::CssOm);
|
2017-03-22 14:17:09 +03:00
|
|
|
})
|
2017-02-19 07:43:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_SetFontFamily(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
value: *const nsAString,
|
|
|
|
) {
|
2017-06-10 00:31:48 +03:00
|
|
|
use cssparser::{Parser, ParserInput};
|
2017-03-17 00:48:53 +03:00
|
|
|
use style::properties::PropertyDeclaration;
|
2017-02-19 07:43:33 +03:00
|
|
|
use style::properties::longhands::font_family::SpecifiedValue as FontFamily;
|
|
|
|
|
|
|
|
let string = unsafe { (*value).to_string() };
|
2017-06-10 00:31:48 +03:00
|
|
|
let mut input = ParserInput::new(&string);
|
|
|
|
let mut parser = Parser::new(&mut input);
|
2017-06-16 16:09:52 +03:00
|
|
|
let result = FontFamily::parse(&mut parser);
|
|
|
|
if let Ok(family) = result {
|
2017-02-19 07:43:33 +03:00
|
|
|
if parser.is_exhausted() {
|
2017-10-04 13:01:45 +03:00
|
|
|
let decl = PropertyDeclaration::FontFamily(family);
|
2017-03-22 14:17:09 +03:00
|
|
|
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
|
2017-10-14 13:27:51 +03:00
|
|
|
decls.push(decl, Importance::Normal, DeclarationSource::CssOm);
|
2017-03-22 14:17:09 +03:00
|
|
|
})
|
2017-02-19 07:43:33 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-12 17:16:55 +03:00
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_SetBackgroundImage(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
value: *const nsAString,
|
|
|
|
raw_extra_data: *mut URLExtraData,
|
|
|
|
) {
|
2017-04-12 17:16:55 +03:00
|
|
|
use style::properties::PropertyDeclaration;
|
|
|
|
use style::properties::longhands::background_image::SpecifiedValue as BackgroundImage;
|
2017-05-15 17:13:38 +03:00
|
|
|
use style::values::Either;
|
|
|
|
use style::values::generics::image::Image;
|
2017-04-12 17:16:55 +03:00
|
|
|
use style::values::specified::url::SpecifiedUrl;
|
|
|
|
|
|
|
|
let url_data = unsafe { RefPtr::from_ptr_ref(&raw_extra_data) };
|
|
|
|
let string = unsafe { (*value).to_string() };
|
2017-08-24 21:19:25 +03:00
|
|
|
let context = ParserContext::new(Origin::Author, url_data,
|
2017-10-31 02:25:45 +03:00
|
|
|
Some(CssRuleType::Style), ParsingMode::DEFAULT,
|
2017-04-28 06:32:24 +03:00
|
|
|
QuirksMode::NoQuirks);
|
2017-05-16 02:04:59 +03:00
|
|
|
if let Ok(mut url) = SpecifiedUrl::parse_from_string(string.into(), &context) {
|
|
|
|
url.build_image_value();
|
2017-04-12 17:16:55 +03:00
|
|
|
let decl = PropertyDeclaration::BackgroundImage(BackgroundImage(
|
2017-05-15 17:13:38 +03:00
|
|
|
vec![Either::Second(Image::Url(url))]
|
2017-04-12 17:16:55 +03:00
|
|
|
));
|
|
|
|
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
|
2017-10-14 13:27:51 +03:00
|
|
|
decls.push(decl, Importance::Normal, DeclarationSource::CssOm);
|
2017-04-12 17:16:55 +03:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-19 07:43:33 +03:00
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_SetTextDecorationColorOverride(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
) {
|
2017-03-17 00:48:53 +03:00
|
|
|
use style::properties::PropertyDeclaration;
|
2017-11-15 00:34:10 +03:00
|
|
|
use style::values::specified::text::TextDecorationLine;
|
2017-02-19 07:43:33 +03:00
|
|
|
|
2017-11-15 00:34:10 +03:00
|
|
|
let mut decoration = TextDecorationLine::none();
|
|
|
|
decoration |= TextDecorationLine::COLOR_OVERRIDE;
|
2017-03-17 00:48:53 +03:00
|
|
|
let decl = PropertyDeclaration::TextDecorationLine(decoration);
|
2017-03-22 14:17:09 +03:00
|
|
|
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
|
2017-10-14 13:27:51 +03:00
|
|
|
decls.push(decl, Importance::Normal, DeclarationSource::CssOm);
|
2017-03-22 14:17:09 +03:00
|
|
|
})
|
2017-02-04 04:36:04 +03:00
|
|
|
}
|
|
|
|
|
2016-07-19 07:25:31 +03:00
|
|
|
#[no_mangle]
|
2017-09-07 14:55:02 +03:00
|
|
|
pub unsafe extern "C" fn Servo_CSSSupports2(
|
|
|
|
property: *const nsACString,
|
|
|
|
value: *const nsACString,
|
|
|
|
) -> bool {
|
2017-05-11 05:25:47 +03:00
|
|
|
let id = get_property_id_from_property!(property, false);
|
2016-07-19 07:25:31 +03:00
|
|
|
|
2017-05-20 02:37:14 +03:00
|
|
|
let mut declarations = SourcePropertyDeclaration::new();
|
|
|
|
parse_property_into(
|
|
|
|
&mut declarations,
|
|
|
|
id,
|
|
|
|
value,
|
2017-09-07 14:55:02 +03:00
|
|
|
DUMMY_URL_DATA,
|
2017-05-20 02:37:14 +03:00
|
|
|
structs::ParsingMode_Default,
|
2017-07-11 04:13:44 +03:00
|
|
|
QuirksMode::NoQuirks,
|
|
|
|
&NullReporter,
|
2017-05-20 02:37:14 +03:00
|
|
|
).is_ok()
|
2016-07-19 07:25:31 +03:00
|
|
|
}
|
2016-07-22 00:54:34 +03:00
|
|
|
|
2017-01-17 00:56:51 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_CSSSupports(cond: *const nsACString) -> bool {
|
|
|
|
let condition = unsafe { cond.as_ref().unwrap().as_str_unchecked() };
|
2017-06-10 00:31:48 +03:00
|
|
|
let mut input = ParserInput::new(&condition);
|
|
|
|
let mut input = Parser::new(&mut input);
|
2017-06-06 09:19:31 +03:00
|
|
|
let cond = input.parse_entirely(|i| parse_condition_or_declaration(i));
|
2017-01-17 00:56:51 +03:00
|
|
|
if let Ok(cond) = cond {
|
2017-04-03 15:05:42 +03:00
|
|
|
let url_data = unsafe { dummy_url_data() };
|
2017-08-18 20:58:46 +03:00
|
|
|
// NOTE(emilio): The supports API is not associated to any stylesheet,
|
|
|
|
// so the fact that there are no namespace map here is fine.
|
|
|
|
let context =
|
|
|
|
ParserContext::new_for_cssom(
|
|
|
|
url_data,
|
|
|
|
Some(CssRuleType::Style),
|
2017-10-31 02:25:45 +03:00
|
|
|
ParsingMode::DEFAULT,
|
2017-08-18 20:58:46 +03:00
|
|
|
QuirksMode::NoQuirks,
|
|
|
|
);
|
2017-01-17 00:56:51 +03:00
|
|
|
cond.eval(&context)
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-25 20:00:44 +03:00
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_NoteExplicitHints(
|
|
|
|
element: RawGeckoElementBorrowed,
|
|
|
|
restyle_hint: nsRestyleHint,
|
|
|
|
change_hint: nsChangeHint,
|
|
|
|
) {
|
2017-08-03 00:27:58 +03:00
|
|
|
GeckoElement(element).note_explicit_hints(restyle_hint, change_hint);
|
2016-11-25 20:00:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_TakeChangeHint(
|
|
|
|
element: RawGeckoElementBorrowed,
|
|
|
|
was_restyled: *mut bool
|
|
|
|
) -> u32 {
|
2017-08-17 19:05:32 +03:00
|
|
|
let was_restyled = unsafe { was_restyled.as_mut().unwrap() };
|
2016-11-25 20:00:44 +03:00
|
|
|
let element = GeckoElement(element);
|
2017-07-15 07:07:38 +03:00
|
|
|
|
2017-06-16 06:28:56 +03:00
|
|
|
let damage = match element.mutate_data() {
|
|
|
|
Some(mut data) => {
|
2017-09-12 21:16:26 +03:00
|
|
|
*was_restyled = data.is_restyle();
|
2017-07-15 07:07:38 +03:00
|
|
|
|
2017-09-12 21:16:26 +03:00
|
|
|
let damage = data.damage;
|
2017-08-12 05:15:12 +03:00
|
|
|
data.clear_restyle_state();
|
2017-06-16 06:28:56 +03:00
|
|
|
damage
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
warn!("Trying to get change hint from unstyled element");
|
2017-07-15 07:07:38 +03:00
|
|
|
*was_restyled = false;
|
2017-06-16 06:28:56 +03:00
|
|
|
GeckoRestyleDamage::empty()
|
|
|
|
}
|
2017-01-10 04:26:50 +03:00
|
|
|
};
|
2016-11-25 20:00:44 +03:00
|
|
|
|
2017-01-10 04:26:50 +03:00
|
|
|
debug!("Servo_TakeChangeHint: {:?}, damage={:?}", element, damage);
|
2017-08-16 06:11:50 +03:00
|
|
|
// We'd like to return `nsChangeHint` here, but bindgen bitfield enums don't
|
|
|
|
// work as return values with the Linux 32-bit ABI at the moment because
|
|
|
|
// they wrap the value in a struct, so for now just unwrap it.
|
|
|
|
damage.as_change_hint().0
|
2016-11-25 20:00:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_ResolveStyle(
|
|
|
|
element: RawGeckoElementBorrowed,
|
|
|
|
_raw_data: RawServoStyleSetBorrowed,
|
|
|
|
) -> ServoStyleContextStrong {
|
2016-11-25 20:00:44 +03:00
|
|
|
let element = GeckoElement(element);
|
2017-01-10 04:26:50 +03:00
|
|
|
debug!("Servo_ResolveStyle: {:?}", element);
|
2017-07-15 15:49:54 +03:00
|
|
|
let data =
|
|
|
|
element.borrow_data().expect("Resolving style on unstyled element");
|
2016-12-10 04:01:05 +03:00
|
|
|
|
2017-08-12 05:15:12 +03:00
|
|
|
debug_assert!(element.has_current_styles(&*data),
|
2017-07-24 11:09:24 +03:00
|
|
|
"Resolving style on {:?} without current styles: {:?}", element, data);
|
2017-07-21 21:05:13 +03:00
|
|
|
data.styles.primary().clone().into()
|
2016-11-25 20:00:44 +03:00
|
|
|
}
|
2016-07-22 00:54:34 +03:00
|
|
|
|
2017-07-28 02:29:29 +03:00
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_ResolveStyleLazily(
|
|
|
|
element: RawGeckoElementBorrowed,
|
|
|
|
pseudo_type: CSSPseudoElementType,
|
|
|
|
rule_inclusion: StyleRuleInclusion,
|
|
|
|
snapshots: *const ServoElementSnapshotTable,
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
|
|
|
ignore_existing_styles: bool
|
|
|
|
) -> ServoStyleContextStrong {
|
2017-05-10 23:08:59 +03:00
|
|
|
debug_assert!(!snapshots.is_null());
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
2016-12-28 06:55:01 +03:00
|
|
|
let element = GeckoElement(element);
|
|
|
|
let doc_data = PerDocumentStyleData::from_ffi(raw_data);
|
2017-06-14 12:00:07 +03:00
|
|
|
let data = doc_data.borrow();
|
2017-05-25 13:50:52 +03:00
|
|
|
let rule_inclusion = RuleInclusion::from(rule_inclusion);
|
2017-08-25 10:30:50 +03:00
|
|
|
let pseudo = PseudoElement::from_pseudo_type(pseudo_type);
|
|
|
|
let finish = |styles: &ElementStyles, is_probe: bool| -> Option<Arc<ComputedValues>> {
|
|
|
|
match pseudo {
|
2017-06-24 09:58:16 +03:00
|
|
|
Some(ref pseudo) => {
|
|
|
|
get_pseudo_style(
|
|
|
|
&guard,
|
|
|
|
element,
|
|
|
|
pseudo,
|
|
|
|
rule_inclusion,
|
|
|
|
styles,
|
2017-06-27 09:46:13 +03:00
|
|
|
/* inherited_styles = */ None,
|
2017-06-24 09:58:16 +03:00
|
|
|
&*data,
|
2017-08-25 10:30:50 +03:00
|
|
|
is_probe,
|
2017-10-20 12:18:53 +03:00
|
|
|
/* matching_func = */ None,
|
2017-08-25 10:30:50 +03:00
|
|
|
)
|
2017-06-24 09:58:16 +03:00
|
|
|
}
|
2017-08-25 10:30:50 +03:00
|
|
|
None => Some(styles.primary().clone()),
|
2017-06-24 09:58:16 +03:00
|
|
|
}
|
2016-12-28 06:55:01 +03:00
|
|
|
};
|
|
|
|
|
2017-08-25 10:30:50 +03:00
|
|
|
let is_before_or_after = pseudo.as_ref().map_or(false, |p| p.is_before_or_after());
|
|
|
|
|
2016-12-28 06:55:01 +03:00
|
|
|
// In the common case we already have the style. Check that before setting
|
2017-05-25 13:50:52 +03:00
|
|
|
// up all the computation machinery. (Don't use it when we're getting
|
2017-08-05 05:33:59 +03:00
|
|
|
// default styles or in a bfcached document (as indicated by
|
|
|
|
// ignore_existing_styles), though.)
|
2017-08-25 10:30:50 +03:00
|
|
|
//
|
|
|
|
// Also, only probe in the ::before or ::after case, since their styles may
|
|
|
|
// not be in the `ElementData`, given they may exist but not be applicable
|
|
|
|
// to generate an actual pseudo-element (like, having a `content: none`).
|
2017-08-05 05:33:59 +03:00
|
|
|
if rule_inclusion == RuleInclusion::All && !ignore_existing_styles {
|
2017-06-23 03:46:55 +03:00
|
|
|
let styles = element.mutate_data().and_then(|d| {
|
|
|
|
if d.has_styles() {
|
2017-08-25 10:30:50 +03:00
|
|
|
finish(&d.styles, is_before_or_after)
|
2017-06-23 03:46:55 +03:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if let Some(result) = styles {
|
2017-07-21 21:05:13 +03:00
|
|
|
return result.into();
|
2017-05-25 13:50:52 +03:00
|
|
|
}
|
2016-12-28 06:55:01 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// We don't have the style ready. Go ahead and compute it as necessary.
|
2017-04-12 10:27:02 +03:00
|
|
|
let shared = create_shared_context(&global_style_data,
|
|
|
|
&guard,
|
2017-05-12 16:56:47 +03:00
|
|
|
&data,
|
2017-07-12 10:28:44 +03:00
|
|
|
TraversalFlags::empty(),
|
2017-07-07 00:57:36 +03:00
|
|
|
unsafe { &*snapshots });
|
2016-12-28 06:55:01 +03:00
|
|
|
let mut tlc = ThreadLocalStyleContext::new(&shared);
|
|
|
|
let mut context = StyleContext {
|
|
|
|
shared: &shared,
|
|
|
|
thread_local: &mut tlc,
|
|
|
|
};
|
|
|
|
|
2017-08-25 10:30:50 +03:00
|
|
|
let styles = resolve_style(
|
|
|
|
&mut context,
|
|
|
|
element,
|
|
|
|
rule_inclusion,
|
|
|
|
ignore_existing_styles,
|
|
|
|
pseudo.as_ref()
|
|
|
|
);
|
|
|
|
|
|
|
|
finish(&styles, /* is_probe = */ false)
|
|
|
|
.expect("We're not probing, so we should always get a style back")
|
|
|
|
.into()
|
2016-12-28 06:55:01 +03:00
|
|
|
}
|
|
|
|
|
2017-07-29 06:51:20 +03:00
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_ReparentStyle(
|
|
|
|
style_to_reparent: ServoStyleContextBorrowed,
|
|
|
|
parent_style: ServoStyleContextBorrowed,
|
|
|
|
parent_style_ignoring_first_line: ServoStyleContextBorrowed,
|
|
|
|
layout_parent_style: ServoStyleContextBorrowed,
|
|
|
|
element: RawGeckoElementBorrowedOrNull,
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
|
|
|
) -> ServoStyleContextStrong {
|
2017-07-29 06:51:20 +03:00
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
let doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
|
|
|
let inputs = CascadeInputs::new_from_style(style_to_reparent);
|
|
|
|
let metrics = get_metrics_provider_for_product();
|
|
|
|
let pseudo = style_to_reparent.pseudo();
|
|
|
|
let element = element.map(GeckoElement);
|
|
|
|
|
|
|
|
let mut cascade_flags = CascadeFlags::empty();
|
|
|
|
if style_to_reparent.is_anon_box() {
|
2017-10-31 02:25:45 +03:00
|
|
|
cascade_flags.insert(CascadeFlags::SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP);
|
2017-07-29 06:51:20 +03:00
|
|
|
}
|
|
|
|
if let Some(element) = element {
|
|
|
|
if element.is_link() {
|
2017-10-31 02:25:45 +03:00
|
|
|
cascade_flags.insert(CascadeFlags::IS_LINK);
|
2017-07-29 06:51:20 +03:00
|
|
|
if element.is_visited_link() &&
|
|
|
|
doc_data.visited_styles_enabled() {
|
2017-10-31 02:25:45 +03:00
|
|
|
cascade_flags.insert(CascadeFlags::IS_VISITED_LINK);
|
2017-07-29 06:51:20 +03:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
if element.is_native_anonymous() {
|
2017-10-31 02:25:45 +03:00
|
|
|
cascade_flags.insert(CascadeFlags::PROHIBIT_DISPLAY_CONTENTS);
|
2017-07-29 06:51:20 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if let Some(pseudo) = pseudo.as_ref() {
|
2017-10-31 02:25:45 +03:00
|
|
|
cascade_flags.insert(CascadeFlags::PROHIBIT_DISPLAY_CONTENTS);
|
2017-07-29 06:51:20 +03:00
|
|
|
if pseudo.is_fieldset_content() {
|
2017-10-31 02:25:45 +03:00
|
|
|
cascade_flags.insert(CascadeFlags::IS_FIELDSET_CONTENT);
|
2017-07-29 06:51:20 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
doc_data.stylist
|
|
|
|
.compute_style_with_inputs(&inputs,
|
|
|
|
pseudo.as_ref(),
|
|
|
|
&StylesheetGuards::same(&guard),
|
|
|
|
parent_style,
|
|
|
|
parent_style_ignoring_first_line,
|
|
|
|
layout_parent_style,
|
|
|
|
&metrics,
|
|
|
|
cascade_flags)
|
|
|
|
.into()
|
|
|
|
}
|
|
|
|
|
2017-05-31 20:03:50 +03:00
|
|
|
#[cfg(feature = "gecko_debug")]
|
|
|
|
fn simulate_compute_values_failure(property: &PropertyValuePair) -> bool {
|
|
|
|
let p = property.mProperty;
|
|
|
|
let id = get_property_id_from_nscsspropertyid!(p, false);
|
|
|
|
id.as_shorthand().is_ok() && property.mSimulateComputeValuesFailure
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(feature = "gecko_debug"))]
|
|
|
|
fn simulate_compute_values_failure(_: &PropertyValuePair) -> bool {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
|
2017-07-20 12:36:15 +03:00
|
|
|
fn create_context<'a>(
|
|
|
|
per_doc_data: &'a PerDocumentStyleDataImpl,
|
|
|
|
font_metrics_provider: &'a FontMetricsProvider,
|
|
|
|
style: &'a ComputedValues,
|
|
|
|
parent_style: Option<&'a ComputedValues>,
|
|
|
|
pseudo: Option<&'a PseudoElement>,
|
2017-07-25 05:13:08 +03:00
|
|
|
for_smil_animation: bool,
|
2017-09-14 12:28:50 +03:00
|
|
|
rule_cache_conditions: &'a mut RuleCacheConditions,
|
2017-07-20 12:36:15 +03:00
|
|
|
) -> Context<'a> {
|
2017-06-02 06:56:48 +03:00
|
|
|
Context {
|
|
|
|
is_root_element: false,
|
2017-07-20 12:36:15 +03:00
|
|
|
builder: StyleBuilder::for_derived_style(
|
|
|
|
per_doc_data.stylist.device(),
|
|
|
|
style,
|
|
|
|
parent_style,
|
|
|
|
pseudo,
|
|
|
|
),
|
2017-06-02 06:56:48 +03:00
|
|
|
font_metrics_provider: font_metrics_provider,
|
|
|
|
cached_system_font: None,
|
|
|
|
in_media_query: false,
|
|
|
|
quirks_mode: per_doc_data.stylist.quirks_mode(),
|
2017-07-25 05:13:08 +03:00
|
|
|
for_smil_animation,
|
2017-09-14 12:28:50 +03:00
|
|
|
for_non_inherited_property: None,
|
|
|
|
rule_cache_conditions: RefCell::new(rule_cache_conditions),
|
2017-06-02 06:56:48 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-24 07:54:12 +03:00
|
|
|
struct PropertyAndIndex {
|
|
|
|
property: PropertyId,
|
|
|
|
index: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
struct PrioritizedPropertyIter<'a> {
|
|
|
|
properties: &'a nsTArray<PropertyValuePair>,
|
|
|
|
sorted_property_indices: Vec<PropertyAndIndex>,
|
|
|
|
curr: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> PrioritizedPropertyIter<'a> {
|
|
|
|
pub fn new(properties: &'a nsTArray<PropertyValuePair>) -> PrioritizedPropertyIter {
|
|
|
|
// If we fail to convert a nsCSSPropertyID into a PropertyId we shouldn't fail outright
|
|
|
|
// but instead by treating that property as the 'all' property we make it sort last.
|
|
|
|
let all = PropertyId::Shorthand(ShorthandId::All);
|
|
|
|
|
|
|
|
let mut sorted_property_indices: Vec<PropertyAndIndex> =
|
|
|
|
properties.iter().enumerate().map(|(index, pair)| {
|
|
|
|
PropertyAndIndex {
|
|
|
|
property: PropertyId::from_nscsspropertyid(pair.mProperty)
|
|
|
|
.unwrap_or(all.clone()),
|
|
|
|
index,
|
|
|
|
}
|
|
|
|
}).collect();
|
|
|
|
sorted_property_indices.sort_by(|a, b| compare_property_priority(&a.property, &b.property));
|
|
|
|
|
|
|
|
PrioritizedPropertyIter {
|
|
|
|
properties,
|
|
|
|
sorted_property_indices,
|
|
|
|
curr: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Iterator for PrioritizedPropertyIter<'a> {
|
|
|
|
type Item = &'a PropertyValuePair;
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<&'a PropertyValuePair> {
|
|
|
|
if self.curr >= self.sorted_property_indices.len() {
|
|
|
|
return None
|
|
|
|
}
|
|
|
|
self.curr += 1;
|
|
|
|
Some(&self.properties[self.sorted_property_indices[self.curr - 1].index])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-24 15:09:33 +03:00
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_GetComputedKeyframeValues(
|
|
|
|
keyframes: RawGeckoKeyframeListBorrowed,
|
|
|
|
element: RawGeckoElementBorrowed,
|
|
|
|
style: ServoStyleContextBorrowed,
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
|
|
|
computed_keyframes: RawGeckoComputedKeyframeValuesListBorrowedMut
|
|
|
|
) {
|
2017-03-31 13:20:26 +03:00
|
|
|
use std::mem;
|
2017-02-27 01:09:44 +03:00
|
|
|
use style::properties::LonghandIdSet;
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
|
2017-03-11 15:40:31 +03:00
|
|
|
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
2017-06-02 06:56:48 +03:00
|
|
|
let metrics = get_metrics_provider_for_product();
|
2017-03-11 15:40:31 +03:00
|
|
|
|
2017-06-02 06:56:48 +03:00
|
|
|
let element = GeckoElement(element);
|
|
|
|
let parent_element = element.inheritance_parent();
|
|
|
|
let parent_data = parent_element.as_ref().and_then(|e| e.borrow_data());
|
2017-07-18 19:23:03 +03:00
|
|
|
let parent_style = parent_data.as_ref().map(|d| d.styles.primary()).map(|x| &**x);
|
2017-02-24 15:09:33 +03:00
|
|
|
|
2017-07-18 19:23:03 +03:00
|
|
|
let pseudo = style.pseudo();
|
2017-09-14 12:28:50 +03:00
|
|
|
let mut conditions = Default::default();
|
2017-07-25 05:13:08 +03:00
|
|
|
let mut context = create_context(
|
|
|
|
&data,
|
|
|
|
&metrics,
|
|
|
|
&style,
|
|
|
|
parent_style,
|
|
|
|
pseudo.as_ref(),
|
|
|
|
/* for_smil_animation = */ false,
|
2017-09-14 12:28:50 +03:00
|
|
|
&mut conditions,
|
2017-07-25 05:13:08 +03:00
|
|
|
);
|
2017-06-02 06:56:48 +03:00
|
|
|
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
let default_values = data.default_computed_values();
|
2017-02-24 15:09:33 +03:00
|
|
|
|
2017-09-27 12:35:00 +03:00
|
|
|
let mut raw_custom_properties_block; // To make the raw block alive in the scope.
|
2017-02-24 15:09:33 +03:00
|
|
|
for (index, keyframe) in keyframes.iter().enumerate() {
|
2017-09-27 12:35:00 +03:00
|
|
|
let mut custom_properties = None;
|
|
|
|
for property in keyframe.mPropertyValues.iter() {
|
|
|
|
// Find the block for custom properties first.
|
|
|
|
if property.mProperty == nsCSSPropertyID::eCSSPropertyExtra_variable {
|
|
|
|
raw_custom_properties_block = unsafe {
|
|
|
|
&*property.mServoDeclarationBlock.mRawPtr.clone()
|
|
|
|
};
|
|
|
|
let guard = Locked::<PropertyDeclarationBlock>::as_arc(
|
|
|
|
&raw_custom_properties_block).read_with(&guard);
|
|
|
|
custom_properties = guard.cascade_custom_properties_with_context(&context);
|
|
|
|
// There should be one PropertyDeclarationBlock for custom properties.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-24 15:09:33 +03:00
|
|
|
let ref mut animation_values = computed_keyframes[index];
|
|
|
|
|
2017-02-27 01:09:44 +03:00
|
|
|
let mut seen = LonghandIdSet::new();
|
2017-02-24 15:09:33 +03:00
|
|
|
|
2017-05-02 14:03:40 +03:00
|
|
|
let mut property_index = 0;
|
2017-07-24 07:54:12 +03:00
|
|
|
for property in PrioritizedPropertyIter::new(&keyframe.mPropertyValues) {
|
2017-05-31 20:03:50 +03:00
|
|
|
if simulate_compute_values_failure(property) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-09-29 18:01:52 +03:00
|
|
|
let mut maybe_append_animation_value = |property: LonghandId, value: Option<AnimationValue>| {
|
|
|
|
if seen.contains(property) {
|
2017-07-10 12:31:35 +03:00
|
|
|
return;
|
|
|
|
}
|
2017-09-29 18:01:52 +03:00
|
|
|
seen.insert(property);
|
2017-07-10 12:31:35 +03:00
|
|
|
|
|
|
|
// This is safe since we immediately write to the uninitialized values.
|
|
|
|
unsafe { animation_values.set_len((property_index + 1) as u32) };
|
2017-09-29 18:01:52 +03:00
|
|
|
animation_values[property_index].mProperty = property.to_nscsspropertyid();
|
2017-07-10 12:31:35 +03:00
|
|
|
// We only make sure we have enough space for this variable,
|
|
|
|
// but didn't construct a default value for StyleAnimationValue,
|
|
|
|
// so we should zero it to avoid getting undefined behaviors.
|
|
|
|
animation_values[property_index].mValue.mGecko = unsafe { mem::zeroed() };
|
|
|
|
match value {
|
|
|
|
Some(v) => {
|
|
|
|
animation_values[property_index].mValue.mServo.set_arc_leaky(Arc::new(v));
|
|
|
|
},
|
|
|
|
None => {
|
|
|
|
animation_values[property_index].mValue.mServo.mRawPtr = ptr::null_mut();
|
|
|
|
},
|
|
|
|
}
|
|
|
|
property_index += 1;
|
|
|
|
};
|
|
|
|
|
|
|
|
if property.mServoDeclarationBlock.mRawPtr.is_null() {
|
2017-09-29 18:01:52 +03:00
|
|
|
let property =
|
|
|
|
LonghandId::from_nscsspropertyid(property.mProperty);
|
|
|
|
if let Ok(prop) = property {
|
|
|
|
maybe_append_animation_value(prop, None);
|
2017-07-10 12:31:35 +03:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-02-24 15:09:33 +03:00
|
|
|
let declarations = unsafe { &*property.mServoDeclarationBlock.mRawPtr.clone() };
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
let declarations = Locked::<PropertyDeclarationBlock>::as_arc(&declarations);
|
|
|
|
let guard = declarations.read_with(&guard);
|
2017-09-27 12:35:00 +03:00
|
|
|
let iter = guard.to_animation_value_iter(
|
|
|
|
&mut context,
|
|
|
|
&default_values,
|
2017-10-01 21:30:18 +03:00
|
|
|
custom_properties.as_ref(),
|
2017-09-27 12:35:00 +03:00
|
|
|
);
|
2017-02-24 15:09:33 +03:00
|
|
|
|
2017-09-29 18:01:52 +03:00
|
|
|
for value in iter {
|
|
|
|
let id = value.id();
|
|
|
|
maybe_append_animation_value(id, Some(value));
|
2017-02-24 15:09:33 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-09 02:23:56 +03:00
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_GetAnimationValues(
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
element: RawGeckoElementBorrowed,
|
|
|
|
style: ServoStyleContextBorrowed,
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
|
|
|
animation_values: RawGeckoServoAnimationValueListBorrowedMut,
|
|
|
|
) {
|
2017-06-09 02:23:56 +03:00
|
|
|
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
|
|
|
let metrics = get_metrics_provider_for_product();
|
|
|
|
|
|
|
|
let element = GeckoElement(element);
|
|
|
|
let parent_element = element.inheritance_parent();
|
|
|
|
let parent_data = parent_element.as_ref().and_then(|e| e.borrow_data());
|
2017-07-18 19:23:03 +03:00
|
|
|
let parent_style = parent_data.as_ref().map(|d| d.styles.primary()).map(|x| &**x);
|
2017-06-09 02:23:56 +03:00
|
|
|
|
2017-07-18 19:23:03 +03:00
|
|
|
let pseudo = style.pseudo();
|
2017-09-14 12:28:50 +03:00
|
|
|
let mut conditions = Default::default();
|
2017-07-25 05:13:08 +03:00
|
|
|
let mut context = create_context(
|
|
|
|
&data,
|
|
|
|
&metrics,
|
|
|
|
&style,
|
|
|
|
parent_style,
|
|
|
|
pseudo.as_ref(),
|
2017-09-14 12:28:50 +03:00
|
|
|
/* for_smil_animation = */ true,
|
|
|
|
&mut conditions,
|
2017-07-25 05:13:08 +03:00
|
|
|
);
|
2017-06-09 02:23:56 +03:00
|
|
|
|
|
|
|
let default_values = data.default_computed_values();
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
|
|
|
|
let declarations = Locked::<PropertyDeclarationBlock>::as_arc(&declarations);
|
|
|
|
let guard = declarations.read_with(&guard);
|
2017-09-27 12:35:00 +03:00
|
|
|
let iter = guard.to_animation_value_iter(
|
|
|
|
&mut context,
|
|
|
|
&default_values,
|
2017-10-01 21:30:18 +03:00
|
|
|
None, // SMIL has no extra custom properties.
|
2017-09-27 12:35:00 +03:00
|
|
|
);
|
|
|
|
for (index, anim) in iter.enumerate() {
|
2017-06-09 02:23:56 +03:00
|
|
|
unsafe { animation_values.set_len((index + 1) as u32) };
|
2017-09-29 18:01:52 +03:00
|
|
|
animation_values[index].set_arc_leaky(Arc::new(anim));
|
2017-06-09 02:23:56 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-03 07:46:15 +03:00
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_AnimationValue_Compute(
|
|
|
|
element: RawGeckoElementBorrowed,
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
style: ServoStyleContextBorrowed,
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
|
|
|
) -> RawServoAnimationValueStrong {
|
2017-05-03 07:46:15 +03:00
|
|
|
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
|
|
|
let metrics = get_metrics_provider_for_product();
|
|
|
|
|
2017-06-02 06:56:48 +03:00
|
|
|
let element = GeckoElement(element);
|
|
|
|
let parent_element = element.inheritance_parent();
|
|
|
|
let parent_data = parent_element.as_ref().and_then(|e| e.borrow_data());
|
2017-07-18 19:23:03 +03:00
|
|
|
let parent_style = parent_data.as_ref().map(|d| d.styles.primary()).map(|x| &**x);
|
2017-06-02 06:56:48 +03:00
|
|
|
|
2017-07-18 19:23:03 +03:00
|
|
|
let pseudo = style.pseudo();
|
2017-09-14 12:28:50 +03:00
|
|
|
let mut conditions = Default::default();
|
2017-07-25 05:13:08 +03:00
|
|
|
let mut context = create_context(
|
|
|
|
&data,
|
|
|
|
&metrics,
|
|
|
|
style,
|
|
|
|
parent_style,
|
|
|
|
pseudo.as_ref(),
|
2017-09-14 12:28:50 +03:00
|
|
|
/* for_smil_animation = */ false,
|
|
|
|
&mut conditions,
|
2017-07-25 05:13:08 +03:00
|
|
|
);
|
2017-06-02 06:56:48 +03:00
|
|
|
|
|
|
|
let default_values = data.default_computed_values();
|
2017-05-03 07:46:15 +03:00
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
let declarations = Locked::<PropertyDeclarationBlock>::as_arc(&declarations);
|
|
|
|
// We only compute the first element in declarations.
|
2017-09-11 16:57:07 +03:00
|
|
|
match declarations.read_with(&guard).declaration_importance_iter().next() {
|
|
|
|
Some((decl, imp)) if imp == Importance::Normal => {
|
2017-09-27 12:35:00 +03:00
|
|
|
let animation = AnimationValue::from_declaration(
|
|
|
|
decl,
|
|
|
|
&mut context,
|
2017-10-01 21:30:18 +03:00
|
|
|
None, // No extra custom properties for devtools.
|
2017-09-27 12:35:00 +03:00
|
|
|
default_values,
|
|
|
|
);
|
2017-05-03 07:46:15 +03:00
|
|
|
animation.map_or(RawServoAnimationValueStrong::null(), |value| {
|
|
|
|
Arc::new(value).into_strong()
|
|
|
|
})
|
|
|
|
},
|
|
|
|
_ => RawServoAnimationValueStrong::null()
|
|
|
|
}
|
|
|
|
}
|
2016-12-28 06:55:01 +03:00
|
|
|
|
2016-11-25 20:00:44 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_AssertTreeIsClean(root: RawGeckoElementBorrowed) {
|
2017-04-23 02:40:47 +03:00
|
|
|
if !cfg!(feature = "gecko_debug") {
|
2016-11-25 20:00:44 +03:00
|
|
|
panic!("Calling Servo_AssertTreeIsClean in release build");
|
|
|
|
}
|
|
|
|
|
|
|
|
let root = GeckoElement(root);
|
2017-08-27 02:13:40 +03:00
|
|
|
debug!("Servo_AssertTreeIsClean: ");
|
|
|
|
debug!("{:?}", ShowSubtreeData(root.as_node()));
|
|
|
|
|
2016-11-25 20:00:44 +03:00
|
|
|
fn assert_subtree_is_clean<'le>(el: GeckoElement<'le>) {
|
2017-06-20 06:19:16 +03:00
|
|
|
debug_assert!(!el.has_dirty_descendants() && !el.has_animation_only_dirty_descendants(),
|
|
|
|
"{:?} has still dirty bit {:?} or animation-only dirty bit {:?}",
|
|
|
|
el, el.has_dirty_descendants(), el.has_animation_only_dirty_descendants());
|
2017-10-17 13:18:29 +03:00
|
|
|
for child in el.traversal_children() {
|
2016-11-25 20:00:44 +03:00
|
|
|
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
|
|
|
}
|
2017-01-29 08:24:04 +03:00
|
|
|
|
2017-09-19 07:58:53 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_IsWorkerThread() -> bool {
|
|
|
|
thread_state::get().is_worker()
|
|
|
|
}
|
|
|
|
|
2017-05-24 12:26:19 +03:00
|
|
|
enum Offset {
|
|
|
|
Zero,
|
|
|
|
One
|
|
|
|
}
|
|
|
|
|
2017-09-29 18:01:52 +03:00
|
|
|
fn fill_in_missing_keyframe_values(
|
|
|
|
all_properties: &LonghandIdSet,
|
|
|
|
timing_function: nsTimingFunctionBorrowed,
|
|
|
|
longhands_at_offset: &LonghandIdSet,
|
|
|
|
offset: Offset,
|
|
|
|
keyframes: RawGeckoKeyframeListBorrowedMut,
|
|
|
|
) {
|
|
|
|
// Return early if all animated properties are already set.
|
|
|
|
if longhands_at_offset.contains_all(all_properties) {
|
2017-05-13 22:05:40 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let keyframe = match offset {
|
2017-05-24 12:26:19 +03:00
|
|
|
Offset::Zero => unsafe {
|
2017-05-13 22:05:40 +03:00
|
|
|
Gecko_GetOrCreateInitialKeyframe(keyframes, timing_function)
|
|
|
|
},
|
2017-05-24 12:26:19 +03:00
|
|
|
Offset::One => unsafe {
|
2017-05-13 22:05:40 +03:00
|
|
|
Gecko_GetOrCreateFinalKeyframe(keyframes, timing_function)
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
// Append properties that have not been set at this offset.
|
2017-09-29 18:01:52 +03:00
|
|
|
for property in all_properties.iter() {
|
|
|
|
if !longhands_at_offset.contains(property) {
|
|
|
|
unsafe {
|
|
|
|
Gecko_AppendPropertyValuePair(
|
|
|
|
&mut (*keyframe).mPropertyValues,
|
|
|
|
property.to_nscsspropertyid()
|
|
|
|
);
|
|
|
|
}
|
2017-05-13 22:05:40 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_GetKeyframesForName(
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
|
|
|
name: *mut nsAtom,
|
|
|
|
inherited_timing_function: nsTimingFunctionBorrowed,
|
|
|
|
keyframes: RawGeckoKeyframeListBorrowedMut,
|
|
|
|
) -> bool {
|
2017-05-13 22:05:40 +03:00
|
|
|
debug_assert!(keyframes.len() == 0,
|
|
|
|
"keyframes should be initially empty");
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
|
2017-03-10 07:23:21 +03:00
|
|
|
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
2017-10-10 12:34:47 +03:00
|
|
|
let name = Atom::from(name);
|
2017-05-13 22:05:40 +03:00
|
|
|
|
2017-08-10 03:28:07 +03:00
|
|
|
let animation = match data.stylist.get_animation(&name) {
|
2017-05-13 22:05:40 +03:00
|
|
|
Some(animation) => animation,
|
|
|
|
None => return false,
|
|
|
|
};
|
|
|
|
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
2017-01-29 08:24:04 +03:00
|
|
|
|
2017-05-13 22:05:40 +03:00
|
|
|
let mut properties_set_at_current_offset = LonghandIdSet::new();
|
|
|
|
let mut properties_set_at_start = LonghandIdSet::new();
|
|
|
|
let mut properties_set_at_end = LonghandIdSet::new();
|
|
|
|
let mut has_complete_initial_keyframe = false;
|
|
|
|
let mut has_complete_final_keyframe = false;
|
|
|
|
let mut current_offset = -1.;
|
|
|
|
|
|
|
|
// Iterate over the keyframe rules backwards so we can drop overridden
|
|
|
|
// properties (since declarations in later rules override those in earlier
|
|
|
|
// ones).
|
|
|
|
for step in animation.steps.iter().rev() {
|
|
|
|
if step.start_percentage.0 != current_offset {
|
|
|
|
properties_set_at_current_offset.clear();
|
|
|
|
current_offset = step.start_percentage.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Override timing_function if the keyframe has an animation-timing-function.
|
|
|
|
let timing_function = match step.get_animation_timing_function(&guard) {
|
|
|
|
Some(val) => val.into(),
|
|
|
|
None => *inherited_timing_function,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Look for an existing keyframe with the same offset and timing
|
|
|
|
// function or else add a new keyframe at the beginning of the keyframe
|
|
|
|
// array.
|
|
|
|
let keyframe = unsafe {
|
|
|
|
Gecko_GetOrCreateKeyframeAtStart(keyframes,
|
|
|
|
step.start_percentage.0 as f32,
|
|
|
|
&timing_function)
|
|
|
|
};
|
|
|
|
|
|
|
|
match step.value {
|
|
|
|
KeyframesStepValue::ComputedValues => {
|
|
|
|
// In KeyframesAnimation::from_keyframes if there is no 0% or
|
|
|
|
// 100% keyframe at all, we will create a 'ComputedValues' step
|
|
|
|
// to represent that all properties animated by the keyframes
|
|
|
|
// animation should be set to the underlying computed value for
|
|
|
|
// that keyframe.
|
|
|
|
for property in animation.properties_changed.iter() {
|
2017-07-20 08:48:47 +03:00
|
|
|
unsafe {
|
2017-09-29 18:01:52 +03:00
|
|
|
Gecko_AppendPropertyValuePair(
|
|
|
|
&mut (*keyframe).mPropertyValues,
|
|
|
|
property.to_nscsspropertyid(),
|
|
|
|
);
|
2017-07-20 08:48:47 +03:00
|
|
|
}
|
2017-04-19 11:06:31 +03:00
|
|
|
}
|
2017-05-13 22:05:40 +03:00
|
|
|
if current_offset == 0.0 {
|
|
|
|
has_complete_initial_keyframe = true;
|
|
|
|
} else if current_offset == 1.0 {
|
|
|
|
has_complete_final_keyframe = true;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
KeyframesStepValue::Declarations { ref block } => {
|
|
|
|
let guard = block.read_with(&guard);
|
2017-09-29 18:01:52 +03:00
|
|
|
|
|
|
|
let mut custom_properties = PropertyDeclarationBlock::new();
|
|
|
|
|
|
|
|
// Filter out non-animatable properties and properties with
|
|
|
|
// !important.
|
|
|
|
for declaration in guard.normal_declaration_iter() {
|
|
|
|
let id = declaration.id();
|
|
|
|
|
|
|
|
let id = match id {
|
|
|
|
PropertyDeclarationId::Longhand(id) => {
|
|
|
|
// Skip the 'display' property because although it
|
|
|
|
// is animatable from SMIL, it should not be
|
|
|
|
// animatable from CSS Animations.
|
|
|
|
if id == LonghandId::Display {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if !id.is_animatable() {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
id
|
|
|
|
}
|
|
|
|
PropertyDeclarationId::Custom(..) => {
|
2017-10-14 13:27:51 +03:00
|
|
|
custom_properties.push(
|
|
|
|
declaration.clone(),
|
|
|
|
Importance::Normal,
|
|
|
|
DeclarationSource::CssOm,
|
|
|
|
);
|
2017-09-29 18:01:52 +03:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
if properties_set_at_current_offset.contains(id) {
|
|
|
|
continue;
|
2017-09-27 12:35:00 +03:00
|
|
|
}
|
2017-09-29 18:01:52 +03:00
|
|
|
|
|
|
|
let pair = unsafe {
|
|
|
|
Gecko_AppendPropertyValuePair(
|
|
|
|
&mut (*keyframe).mPropertyValues,
|
|
|
|
id.to_nscsspropertyid(),
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
2017-09-27 12:35:00 +03:00
|
|
|
unsafe {
|
|
|
|
(*pair).mServoDeclarationBlock.set_arc_leaky(
|
2017-09-29 18:01:52 +03:00
|
|
|
Arc::new(global_style_data.shared_lock.wrap(
|
|
|
|
PropertyDeclarationBlock::with_one(
|
|
|
|
declaration.clone(),
|
|
|
|
Importance::Normal,
|
|
|
|
)
|
|
|
|
))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if current_offset == 0.0 {
|
|
|
|
properties_set_at_start.insert(id);
|
|
|
|
} else if current_offset == 1.0 {
|
|
|
|
properties_set_at_end.insert(id);
|
2017-09-27 12:35:00 +03:00
|
|
|
}
|
2017-09-29 18:01:52 +03:00
|
|
|
properties_set_at_current_offset.insert(id);
|
2017-09-27 12:35:00 +03:00
|
|
|
}
|
|
|
|
|
2017-09-29 18:01:52 +03:00
|
|
|
if custom_properties.any_normal() {
|
|
|
|
let pair = unsafe {
|
|
|
|
Gecko_AppendPropertyValuePair(
|
|
|
|
&mut (*keyframe).mPropertyValues,
|
|
|
|
nsCSSPropertyID::eCSSPropertyExtra_variable,
|
|
|
|
)
|
|
|
|
};
|
2017-04-19 11:06:31 +03:00
|
|
|
|
2017-09-29 18:01:52 +03:00
|
|
|
unsafe {
|
|
|
|
(*pair).mServoDeclarationBlock.set_arc_leaky(Arc::new(
|
|
|
|
global_style_data.shared_lock.wrap(custom_properties)
|
|
|
|
));
|
2017-04-19 11:06:31 +03:00
|
|
|
}
|
2017-09-29 18:01:52 +03:00
|
|
|
|
2017-05-13 22:05:40 +03:00
|
|
|
}
|
|
|
|
},
|
2017-04-19 11:06:31 +03:00
|
|
|
}
|
2017-01-29 08:24:04 +03:00
|
|
|
}
|
2017-05-13 22:05:40 +03:00
|
|
|
|
|
|
|
// Append property values that are missing in the initial or the final keyframes.
|
|
|
|
if !has_complete_initial_keyframe {
|
2017-09-29 18:01:52 +03:00
|
|
|
fill_in_missing_keyframe_values(
|
|
|
|
&animation.properties_changed,
|
|
|
|
inherited_timing_function,
|
|
|
|
&properties_set_at_start,
|
|
|
|
Offset::Zero,
|
|
|
|
keyframes,
|
|
|
|
);
|
2017-05-13 22:05:40 +03:00
|
|
|
}
|
|
|
|
if !has_complete_final_keyframe {
|
2017-09-29 18:01:52 +03:00
|
|
|
fill_in_missing_keyframe_values(
|
|
|
|
&animation.properties_changed,
|
|
|
|
inherited_timing_function,
|
|
|
|
&properties_set_at_end,
|
|
|
|
Offset::One,
|
|
|
|
keyframes,
|
|
|
|
);
|
2017-05-13 22:05:40 +03:00
|
|
|
}
|
|
|
|
true
|
2017-01-29 08:24:04 +03:00
|
|
|
}
|
|
|
|
|
2017-03-30 04:50:47 +03:00
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_GetFontFaceRules(
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
|
|
|
rules: RawGeckoFontFaceRuleListBorrowedMut,
|
|
|
|
) {
|
2017-03-30 04:50:47 +03:00
|
|
|
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
|
|
|
debug_assert!(rules.len() == 0);
|
|
|
|
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
|
2017-09-14 01:44:21 +03:00
|
|
|
let len: u32 = data
|
|
|
|
.stylist
|
|
|
|
.iter_extra_data_origins()
|
2017-08-11 08:40:18 +03:00
|
|
|
.map(|(d, _)| d.font_faces.len() as u32)
|
|
|
|
.sum();
|
|
|
|
|
2017-08-14 12:19:34 +03:00
|
|
|
// Reversed iterator because Gecko expects rules to appear sorted
|
|
|
|
// UserAgent first, Author last.
|
2017-09-14 01:44:21 +03:00
|
|
|
let font_face_iter = data
|
|
|
|
.stylist
|
|
|
|
.iter_extra_data_origins_rev()
|
2017-08-11 08:40:18 +03:00
|
|
|
.flat_map(|(d, o)| d.font_faces.iter().zip(iter::repeat(o)));
|
|
|
|
|
|
|
|
unsafe { rules.set_len(len) };
|
|
|
|
for (src, dest) in font_face_iter.zip(rules.iter_mut()) {
|
2017-03-30 04:50:47 +03:00
|
|
|
dest.mRule = src.0.read_with(&guard).clone().forget();
|
|
|
|
dest.mSheetType = src.1.into();
|
|
|
|
}
|
|
|
|
}
|
2017-04-15 14:20:52 +03:00
|
|
|
|
2017-05-16 09:17:07 +03:00
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_GetCounterStyleRule(
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
|
|
|
name: *mut nsAtom,
|
|
|
|
) -> *mut nsCSSCounterStyleRule {
|
2017-05-16 09:17:07 +03:00
|
|
|
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
2017-08-11 08:40:18 +03:00
|
|
|
|
2017-05-16 09:17:07 +03:00
|
|
|
unsafe {
|
2017-08-11 08:40:18 +03:00
|
|
|
Atom::with(name, |name| {
|
2017-09-14 01:44:21 +03:00
|
|
|
data.stylist
|
|
|
|
.iter_extra_data_origins()
|
2017-08-11 08:40:18 +03:00
|
|
|
.filter_map(|(d, _)| d.counter_styles.get(name))
|
|
|
|
.next()
|
|
|
|
})
|
2017-05-16 09:17:07 +03:00
|
|
|
}.map(|rule| {
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
rule.read_with(&guard).get()
|
|
|
|
}).unwrap_or(ptr::null_mut())
|
|
|
|
}
|
|
|
|
|
2017-08-25 23:45:03 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleSet_BuildFontFeatureValueSet(
|
2017-10-13 22:11:02 +03:00
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
|
|
|
) -> *mut gfxFontFeatureValueSet {
|
2017-08-25 23:45:03 +03:00
|
|
|
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
|
|
|
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
|
2017-09-14 01:44:21 +03:00
|
|
|
let has_rule =
|
|
|
|
data.stylist
|
|
|
|
.iter_extra_data_origins()
|
|
|
|
.any(|(d, _)| !d.font_feature_values.is_empty());
|
2017-09-06 02:35:55 +03:00
|
|
|
|
|
|
|
if !has_rule {
|
|
|
|
return ptr::null_mut();
|
|
|
|
}
|
|
|
|
|
2017-09-14 01:44:21 +03:00
|
|
|
let font_feature_values_iter =
|
|
|
|
data.stylist
|
|
|
|
.iter_extra_data_origins_rev()
|
|
|
|
.flat_map(|(d, _)| d.font_feature_values.iter());
|
2017-08-25 23:45:03 +03:00
|
|
|
|
2017-09-06 02:35:55 +03:00
|
|
|
let set = unsafe { Gecko_ConstructFontFeatureValueSet() };
|
2017-08-25 23:45:03 +03:00
|
|
|
for src in font_feature_values_iter {
|
|
|
|
let rule = src.read_with(&guard);
|
|
|
|
rule.set_at_rules(set);
|
|
|
|
}
|
2017-09-06 02:35:55 +03:00
|
|
|
set
|
2017-08-25 23:45:03 +03:00
|
|
|
}
|
|
|
|
|
2017-04-15 14:20:52 +03:00
|
|
|
#[no_mangle]
|
2017-07-02 17:00:39 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_ResolveForDeclarations(
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
2017-07-18 05:44:25 +03:00
|
|
|
parent_style_context: ServoStyleContextBorrowedOrNull,
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
) -> ServoStyleContextStrong {
|
2017-04-15 14:20:52 +03:00
|
|
|
let doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
let guards = StylesheetGuards::same(&guard);
|
|
|
|
|
2017-07-18 05:44:25 +03:00
|
|
|
let parent_style = match parent_style_context {
|
2017-07-18 19:23:03 +03:00
|
|
|
Some(parent) => &*parent,
|
2017-04-15 14:20:52 +03:00
|
|
|
None => doc_data.default_computed_values(),
|
|
|
|
};
|
|
|
|
|
|
|
|
let declarations = Locked::<PropertyDeclarationBlock>::as_arc(&declarations);
|
|
|
|
|
2017-07-18 19:23:03 +03:00
|
|
|
doc_data.stylist.compute_for_declarations(
|
|
|
|
&guards,
|
|
|
|
parent_style,
|
|
|
|
declarations.clone_arc(),
|
2017-07-21 21:05:13 +03:00
|
|
|
).into()
|
2017-04-15 14:20:52 +03:00
|
|
|
}
|
2017-05-12 13:41:35 +03:00
|
|
|
|
2017-08-31 08:31:31 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleSet_AddSizeOfExcludingThis(
|
|
|
|
malloc_size_of: GeckoMallocSizeOf,
|
2017-09-05 20:51:17 +03:00
|
|
|
malloc_enclosing_size_of: GeckoMallocSizeOf,
|
2017-08-31 08:31:31 +03:00
|
|
|
sizes: *mut ServoStyleSetSizes,
|
|
|
|
raw_data: RawServoStyleSetBorrowed
|
|
|
|
) {
|
|
|
|
let data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
servo: Merge #18452 - Overhaul MallocSizeOf and related things (from nnethercote:bug-1398737); r=jdm
This patch makes the MallocSizeOf stuff in Stylo work more like the HeapSizeOf
stuff already in Servo, except better. In particular, it adds deriving support
for MallocSizeOf, which will make it easier to improve coverage.
The patch does the following.
- Combines servo/components/style/stylesheets/memory.rs and the heapsize crate
into a new crate, malloc_size_of.
- Forks the heapsize_derive crate, calling it malloc_size_of, so that
MallocSizeOf can be derived.
- Both the new crates have MIT/Apache licenses, like heapsize, in case they are
incorporated into heapsize in the future.
- Renames the methods within MallocSizeOf and the related traits so they are
more concise.
- Removes MallocSizeOfWithGuard.
- Adds `derive(MallocSizeOf)` to a lot of types, in some cases replacing an
equivalent or almost-equivalent hand-written implementation.
- Adds stuff so that Rc/Arc can be handled properly.
<!-- Please describe your changes on the following line: -->
---
<!-- 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
- [ ] These changes fix #__ (github issue number if applicable).
<!-- Either: -->
- [ ] There are tests for these changes OR
- [X] These changes do not require tests because tested on Gecko side.
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- 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: 7f4cb1861b172423781a369b2decca6c65d60546
--HG--
rename : servo/components/hashglobe/LICENSE-APACHE => servo/components/malloc_size_of/LICENSE-APACHE
rename : servo/components/hashglobe/LICENSE-MIT => servo/components/malloc_size_of/LICENSE-MIT
rename : servo/components/jstraceable_derive/Cargo.toml => servo/components/malloc_size_of_derive/Cargo.toml
rename : servo/components/hashglobe/LICENSE-APACHE => servo/components/malloc_size_of_derive/LICENSE-APACHE
rename : servo/components/hashglobe/LICENSE-MIT => servo/components/malloc_size_of_derive/LICENSE-MIT
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : a8254c4ae15901b764d918355e900a1e74d6eb03
2017-09-12 06:11:25 +03:00
|
|
|
let mut ops = MallocSizeOfOps::new(malloc_size_of.unwrap(),
|
servo: Merge #18938 - Replace all uses of the `heapsize` crate with `malloc_size_of` (from nnethercote:bug-1409255); r=SimonSapin
Servo currently uses `heapsize`, but Stylo/Gecko use `malloc_size_of`.
`malloc_size_of` is better -- it handles various cases that `heapsize` does not
-- so this patch changes Servo to use `malloc_size_of`.
This patch makes the following changes to the `malloc_size_of` crate.
- Adds `MallocSizeOf` trait implementations for numerous types, some built-in
(e.g. `VecDeque`), some external and Servo-only (e.g. `string_cache`).
- Makes `enclosing_size_of_op` optional, because vanilla jemalloc doesn't
support that operation.
- For `HashSet`/`HashMap`, falls back to a computed estimate when
`enclosing_size_of_op` isn't available.
- Adds an extern "C" `malloc_size_of` function that does the actual heap
measurement; this is based on the same functions from the `heapsize` crate.
This patch makes the following changes elsewhere.
- Converts all the uses of `heapsize` to instead use `malloc_size_of`.
- Disables the "heapsize"/"heap_size" feature for the external crates that
provide it.
- Removes the `HeapSizeOf` implementation from `hashglobe`.
- Adds `ignore` annotations to a few `Rc`/`Arc`, because `malloc_size_of`
doesn't derive those types, unlike `heapsize`.
<!-- Please describe your changes on the following line: -->
---
<!-- 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
- [ ] These changes fix https://bugzilla.mozilla.org/show_bug.cgi?id=1409255
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because testing is on the Gecko side.
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- 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: 4c538b642e4bdfbf42c522c5a59c258a6d14546e
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : f9a6feed1088d0b0be2b55d7f0c2ec9c594ac33b
2017-10-18 21:56:05 +03:00
|
|
|
Some(malloc_enclosing_size_of.unwrap()),
|
2017-09-18 07:19:54 +03:00
|
|
|
None);
|
2017-08-31 08:31:31 +03:00
|
|
|
let sizes = unsafe { sizes.as_mut() }.unwrap();
|
2017-09-26 13:52:34 +03:00
|
|
|
data.add_size_of(&mut ops, sizes);
|
2017-08-31 08:31:31 +03:00
|
|
|
}
|
|
|
|
|
2017-09-20 02:46:49 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_UACache_AddSizeOf(
|
|
|
|
malloc_size_of: GeckoMallocSizeOf,
|
|
|
|
malloc_enclosing_size_of: GeckoMallocSizeOf,
|
|
|
|
sizes: *mut ServoStyleSetSizes
|
|
|
|
) {
|
|
|
|
let mut ops = MallocSizeOfOps::new(malloc_size_of.unwrap(),
|
servo: Merge #18938 - Replace all uses of the `heapsize` crate with `malloc_size_of` (from nnethercote:bug-1409255); r=SimonSapin
Servo currently uses `heapsize`, but Stylo/Gecko use `malloc_size_of`.
`malloc_size_of` is better -- it handles various cases that `heapsize` does not
-- so this patch changes Servo to use `malloc_size_of`.
This patch makes the following changes to the `malloc_size_of` crate.
- Adds `MallocSizeOf` trait implementations for numerous types, some built-in
(e.g. `VecDeque`), some external and Servo-only (e.g. `string_cache`).
- Makes `enclosing_size_of_op` optional, because vanilla jemalloc doesn't
support that operation.
- For `HashSet`/`HashMap`, falls back to a computed estimate when
`enclosing_size_of_op` isn't available.
- Adds an extern "C" `malloc_size_of` function that does the actual heap
measurement; this is based on the same functions from the `heapsize` crate.
This patch makes the following changes elsewhere.
- Converts all the uses of `heapsize` to instead use `malloc_size_of`.
- Disables the "heapsize"/"heap_size" feature for the external crates that
provide it.
- Removes the `HeapSizeOf` implementation from `hashglobe`.
- Adds `ignore` annotations to a few `Rc`/`Arc`, because `malloc_size_of`
doesn't derive those types, unlike `heapsize`.
<!-- Please describe your changes on the following line: -->
---
<!-- 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
- [ ] These changes fix https://bugzilla.mozilla.org/show_bug.cgi?id=1409255
<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because testing is on the Gecko side.
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- 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: 4c538b642e4bdfbf42c522c5a59c258a6d14546e
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : f9a6feed1088d0b0be2b55d7f0c2ec9c594ac33b
2017-10-18 21:56:05 +03:00
|
|
|
Some(malloc_enclosing_size_of.unwrap()),
|
2017-09-20 02:46:49 +03:00
|
|
|
None);
|
|
|
|
let sizes = unsafe { sizes.as_mut() }.unwrap();
|
|
|
|
add_size_of_ua_cache(&mut ops, sizes);
|
|
|
|
}
|
|
|
|
|
2017-05-12 13:41:35 +03:00
|
|
|
#[no_mangle]
|
2017-06-29 03:02:17 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_MightHaveAttributeDependency(
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
|
|
|
element: RawGeckoElementBorrowed,
|
2017-10-09 03:10:40 +03:00
|
|
|
local_name: *mut nsAtom,
|
2017-06-29 03:02:17 +03:00
|
|
|
) -> bool {
|
2017-05-12 13:41:35 +03:00
|
|
|
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
2017-06-29 03:02:17 +03:00
|
|
|
let element = GeckoElement(element);
|
|
|
|
let mut has_dep = false;
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
Atom::with(local_name, |atom| {
|
|
|
|
has_dep = data.stylist.might_have_attribute_dependency(atom);
|
|
|
|
|
|
|
|
if !has_dep {
|
|
|
|
// TODO(emilio): Consider optimizing this storing attribute
|
|
|
|
// dependencies from UA sheets separately, so we could optimize
|
|
|
|
// the above lookup if cut_off_inheritance is true.
|
|
|
|
element.each_xbl_stylist(|stylist| {
|
|
|
|
has_dep =
|
|
|
|
has_dep || stylist.might_have_attribute_dependency(atom);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
has_dep
|
2017-05-12 13:41:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-06-29 03:02:17 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_HasStateDependency(
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
|
|
|
element: RawGeckoElementBorrowed,
|
|
|
|
state: u64,
|
|
|
|
) -> bool {
|
|
|
|
let element = GeckoElement(element);
|
|
|
|
|
|
|
|
let state = ElementState::from_bits_truncate(state);
|
2017-05-12 13:41:35 +03:00
|
|
|
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
2017-06-29 03:02:17 +03:00
|
|
|
|
2017-10-20 10:56:47 +03:00
|
|
|
let mut has_dep = data.stylist.has_state_dependency(state);
|
2017-06-29 03:02:17 +03:00
|
|
|
if !has_dep {
|
|
|
|
// TODO(emilio): Consider optimizing this storing attribute
|
|
|
|
// dependencies from UA sheets separately, so we could optimize
|
|
|
|
// the above lookup if cut_off_inheritance is true.
|
|
|
|
element.each_xbl_stylist(|stylist| {
|
2017-10-20 10:56:47 +03:00
|
|
|
has_dep = has_dep || stylist.has_state_dependency(state);
|
2017-06-29 03:02:17 +03:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
has_dep
|
2017-05-12 13:41:35 +03:00
|
|
|
}
|
2017-06-23 04:49:38 +03:00
|
|
|
|
2017-10-20 10:56:47 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleSet_HasDocumentStateDependency(
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
|
|
|
state: u64,
|
|
|
|
) -> bool {
|
|
|
|
let state = DocumentState::from_bits_truncate(state);
|
|
|
|
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
|
|
|
|
|
|
|
data.stylist.has_document_state_dependency(state)
|
|
|
|
}
|
|
|
|
|
2017-06-23 04:49:38 +03:00
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_GetCustomPropertyValue(
|
|
|
|
computed_values: ServoStyleContextBorrowed,
|
|
|
|
name: *const nsAString,
|
|
|
|
value: *mut nsAString,
|
|
|
|
) -> bool {
|
2017-07-18 05:44:25 +03:00
|
|
|
let custom_properties = match computed_values.custom_properties() {
|
2017-06-23 04:49:38 +03:00
|
|
|
Some(p) => p,
|
|
|
|
None => return false,
|
|
|
|
};
|
|
|
|
|
|
|
|
let name = unsafe { Atom::from((&*name)) };
|
2017-08-08 16:29:14 +03:00
|
|
|
let computed_value = match custom_properties.get(&name) {
|
2017-06-23 04:49:38 +03:00
|
|
|
Some(v) => v,
|
|
|
|
None => return false,
|
|
|
|
};
|
|
|
|
|
|
|
|
computed_value.to_css(unsafe { value.as_mut().unwrap() }).unwrap();
|
|
|
|
true
|
|
|
|
}
|
2017-06-29 04:04:58 +03:00
|
|
|
|
|
|
|
#[no_mangle]
|
2017-07-21 21:05:13 +03:00
|
|
|
pub extern "C" fn Servo_GetCustomPropertiesCount(computed_values: ServoStyleContextBorrowed) -> u32 {
|
2017-07-18 05:44:25 +03:00
|
|
|
match computed_values.custom_properties() {
|
2017-06-29 04:04:58 +03:00
|
|
|
Some(p) => p.len() as u32,
|
|
|
|
None => 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_GetCustomPropertyNameAt(
|
|
|
|
computed_values: ServoStyleContextBorrowed,
|
|
|
|
index: u32,
|
|
|
|
name: *mut nsAString,
|
|
|
|
) -> bool {
|
2017-07-18 05:44:25 +03:00
|
|
|
let custom_properties = match computed_values.custom_properties() {
|
2017-06-29 04:04:58 +03:00
|
|
|
Some(p) => p,
|
|
|
|
None => return false,
|
|
|
|
};
|
|
|
|
|
2017-08-08 16:29:14 +03:00
|
|
|
let property_name = match custom_properties.get_key_at(index) {
|
2017-06-29 04:04:58 +03:00
|
|
|
Some(n) => n,
|
|
|
|
None => return false,
|
|
|
|
};
|
|
|
|
|
|
|
|
let name = unsafe { name.as_mut().unwrap() };
|
|
|
|
name.assign(&*property_name.as_slice());
|
|
|
|
|
|
|
|
true
|
|
|
|
}
|
2017-08-25 11:36:34 +03:00
|
|
|
|
2017-09-15 22:43:30 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub unsafe extern "C" fn Servo_ReleaseArcStringData(string: *const RawOffsetArc<RustString>) {
|
|
|
|
let string = string as *const RawOffsetArc<String>;
|
|
|
|
// Cause RawOffsetArc::drop to run, releasing the strong reference to the string data.
|
|
|
|
let _ = ptr::read(string);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub unsafe extern "C" fn Servo_CloneArcStringData(
|
|
|
|
string: *const RawOffsetArc<RustString>,
|
|
|
|
) -> RawOffsetArc<RustString> {
|
2017-09-15 22:43:30 +03:00
|
|
|
let string = string as *const RawOffsetArc<String>;
|
|
|
|
let cloned = (*string).clone();
|
|
|
|
mem::transmute::<_, RawOffsetArc<RustString>>(cloned)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub unsafe extern "C" fn Servo_GetArcStringData(
|
|
|
|
string: *const RustString,
|
|
|
|
utf8_chars: *mut *const u8,
|
|
|
|
utf8_len: *mut u32,
|
|
|
|
) {
|
2017-09-15 22:43:30 +03:00
|
|
|
let string = &*(string as *const String);
|
|
|
|
*utf8_len = string.len() as u32;
|
|
|
|
*utf8_chars = string.as_ptr();
|
|
|
|
}
|
|
|
|
|
2017-08-25 11:36:34 +03:00
|
|
|
#[no_mangle]
|
2017-10-13 22:11:02 +03:00
|
|
|
pub extern "C" fn Servo_ProcessInvalidations(
|
|
|
|
set: RawServoStyleSetBorrowed,
|
|
|
|
element: RawGeckoElementBorrowed,
|
|
|
|
snapshots: *const ServoElementSnapshotTable,
|
|
|
|
) {
|
2017-08-25 11:36:34 +03:00
|
|
|
debug_assert!(!snapshots.is_null());
|
|
|
|
|
|
|
|
let element = GeckoElement(element);
|
|
|
|
debug_assert!(element.has_snapshot());
|
|
|
|
debug_assert!(!element.handled_snapshot());
|
|
|
|
|
|
|
|
let mut data = element.mutate_data();
|
|
|
|
debug_assert!(data.is_some());
|
|
|
|
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
let guard = global_style_data.shared_lock.read();
|
|
|
|
let per_doc_data = PerDocumentStyleData::from_ffi(set).borrow();
|
|
|
|
let shared_style_context = create_shared_context(&global_style_data,
|
|
|
|
&guard,
|
|
|
|
&per_doc_data,
|
|
|
|
TraversalFlags::empty(),
|
|
|
|
unsafe { &*snapshots });
|
|
|
|
let mut data = data.as_mut().map(|d| &mut **d);
|
|
|
|
|
|
|
|
if let Some(ref mut data) = data {
|
2017-10-03 08:40:03 +03:00
|
|
|
// FIXME(emilio): an nth-index cache could be worth here, even
|
|
|
|
// if temporary?
|
|
|
|
//
|
|
|
|
// Also, ideally we could share them across all the elements?
|
|
|
|
let result = data.invalidate_style_if_needed(
|
|
|
|
element,
|
|
|
|
&shared_style_context,
|
|
|
|
None,
|
|
|
|
None,
|
|
|
|
);
|
|
|
|
|
2017-09-05 22:18:52 +03:00
|
|
|
if result.has_invalidated_siblings() {
|
|
|
|
let parent = element.traversal_parent().expect("How could we invalidate siblings without a common parent?");
|
|
|
|
unsafe {
|
|
|
|
parent.set_dirty_descendants();
|
|
|
|
bindings::Gecko_NoteDirtySubtreeForInvalidation(parent.0);
|
|
|
|
}
|
|
|
|
} else if result.has_invalidated_descendants() {
|
|
|
|
unsafe { bindings::Gecko_NoteDirtySubtreeForInvalidation(element.0) };
|
|
|
|
} else if result.has_invalidated_self() {
|
|
|
|
unsafe { bindings::Gecko_NoteDirtyElement(element.0) };
|
|
|
|
}
|
2017-08-25 11:36:34 +03:00
|
|
|
}
|
|
|
|
}
|
2017-09-06 18:47:32 +03:00
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_HasPendingRestyleAncestor(element: RawGeckoElementBorrowed) -> bool {
|
|
|
|
let mut element = Some(GeckoElement(element));
|
|
|
|
while let Some(e) = element {
|
2017-10-25 18:28:18 +03:00
|
|
|
if e.has_animations() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the element needs a frame, it means that we haven't styled it yet
|
|
|
|
// after it got inserted in the document, and thus we may need to do
|
|
|
|
// that for transitions and animations to trigger.
|
|
|
|
if e.needs_frame() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-09-06 18:47:32 +03:00
|
|
|
if let Some(data) = e.borrow_data() {
|
2017-09-12 21:16:26 +03:00
|
|
|
if !data.hint.is_empty() {
|
2017-09-06 18:47:32 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2017-10-25 18:28:18 +03:00
|
|
|
|
2017-09-06 18:47:32 +03:00
|
|
|
element = e.traversal_parent();
|
|
|
|
}
|
|
|
|
false
|
|
|
|
}
|
2017-09-29 03:10:46 +03:00
|
|
|
|
2017-10-03 16:05:07 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub unsafe extern "C" fn Servo_SelectorList_Parse(
|
|
|
|
selector_list: *const nsACString,
|
2017-10-10 09:20:38 +03:00
|
|
|
) -> *mut RawServoSelectorList {
|
2017-10-03 16:05:07 +03:00
|
|
|
use style::selector_parser::SelectorParser;
|
|
|
|
|
|
|
|
debug_assert!(!selector_list.is_null());
|
|
|
|
|
2017-11-13 06:01:34 +03:00
|
|
|
let input = (*selector_list).as_str_unchecked();
|
2017-10-03 16:05:07 +03:00
|
|
|
let selector_list = match SelectorParser::parse_author_origin_no_namespace(&input) {
|
|
|
|
Ok(selector_list) => selector_list,
|
|
|
|
Err(..) => return ptr::null_mut(),
|
|
|
|
};
|
|
|
|
|
2017-10-10 09:20:38 +03:00
|
|
|
Box::into_raw(Box::new(selector_list)) as *mut RawServoSelectorList
|
2017-10-03 16:05:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-10-10 09:20:38 +03:00
|
|
|
pub unsafe extern "C" fn Servo_SelectorList_Drop(list: RawServoSelectorListOwned) {
|
|
|
|
let _ = list.into_box::<::selectors::SelectorList<SelectorImpl>>();
|
2017-10-03 16:05:07 +03:00
|
|
|
}
|
2017-10-16 12:49:33 +03:00
|
|
|
|
|
|
|
fn parse_color(value: &str) -> Result<specified::Color, ()> {
|
|
|
|
let mut input = ParserInput::new(value);
|
|
|
|
let mut parser = Parser::new(&mut input);
|
|
|
|
parser.parse_entirely(specified::Color::parse_color).map_err(|_| ())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_IsValidCSSColor(
|
|
|
|
value: *const nsAString,
|
|
|
|
) -> bool {
|
|
|
|
let value = unsafe { (*value).to_string() };
|
|
|
|
parse_color(&value).is_ok()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_ComputeColor(
|
|
|
|
raw_data: RawServoStyleSetBorrowedOrNull,
|
|
|
|
current_color: structs::nscolor,
|
|
|
|
value: *const nsAString,
|
|
|
|
result_color: *mut structs::nscolor,
|
|
|
|
) -> bool {
|
|
|
|
use style::gecko;
|
|
|
|
|
|
|
|
let current_color = gecko::values::convert_nscolor_to_rgba(current_color);
|
|
|
|
let value = unsafe { (*value).to_string() };
|
|
|
|
let result_color = unsafe { result_color.as_mut().unwrap() };
|
|
|
|
|
|
|
|
match parse_color(&value) {
|
|
|
|
Ok(specified_color) => {
|
|
|
|
let computed_color = match raw_data {
|
|
|
|
Some(raw_data) => {
|
|
|
|
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
|
|
|
let metrics = get_metrics_provider_for_product();
|
|
|
|
let mut conditions = Default::default();
|
|
|
|
let context = create_context(
|
|
|
|
&data,
|
|
|
|
&metrics,
|
|
|
|
data.stylist.device().default_computed_values(),
|
|
|
|
/* parent_style = */ None,
|
|
|
|
/* pseudo = */ None,
|
|
|
|
/* for_smil_animation = */ false,
|
|
|
|
&mut conditions,
|
|
|
|
);
|
|
|
|
specified_color.to_computed_color(Some(&context))
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
specified_color.to_computed_color(None)
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
match computed_color {
|
|
|
|
Some(computed_color) => {
|
|
|
|
let rgba = computed_color.to_rgba(current_color);
|
|
|
|
*result_color = gecko::values::convert_rgba_to_nscolor(&rgba);
|
|
|
|
true
|
|
|
|
}
|
|
|
|
None => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(_) => false,
|
|
|
|
}
|
|
|
|
}
|
2017-10-17 09:11:39 +03:00
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_ParseIntersectionObserverRootMargin(
|
|
|
|
value: *const nsAString,
|
|
|
|
result: *mut structs::nsCSSRect,
|
|
|
|
) -> bool {
|
|
|
|
let value = unsafe { value.as_ref().unwrap().to_string() };
|
|
|
|
let result = unsafe { result.as_mut().unwrap() };
|
|
|
|
|
|
|
|
let mut input = ParserInput::new(&value);
|
|
|
|
let mut parser = Parser::new(&mut input);
|
|
|
|
|
|
|
|
let url_data = unsafe { dummy_url_data() };
|
|
|
|
let context = ParserContext::new(
|
|
|
|
Origin::Author,
|
|
|
|
url_data,
|
|
|
|
Some(CssRuleType::Style),
|
2017-10-31 02:25:45 +03:00
|
|
|
ParsingMode::DEFAULT,
|
2017-10-17 09:11:39 +03:00
|
|
|
QuirksMode::NoQuirks,
|
|
|
|
);
|
|
|
|
|
|
|
|
let margin = parser.parse_entirely(|p| {
|
|
|
|
IntersectionObserverRootMargin::parse(&context, p)
|
|
|
|
});
|
|
|
|
match margin {
|
|
|
|
Ok(margin) => {
|
|
|
|
let rect = margin.0;
|
|
|
|
result.mTop.set_from(rect.0);
|
|
|
|
result.mRight.set_from(rect.1);
|
|
|
|
result.mBottom.set_from(rect.2);
|
|
|
|
result.mLeft.set_from(rect.3);
|
|
|
|
true
|
|
|
|
}
|
|
|
|
Err(..) => false,
|
|
|
|
}
|
|
|
|
}
|
2017-11-13 06:01:34 +03:00
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub unsafe extern "C" fn Servo_SourceSizeList_Parse(
|
|
|
|
value: *const nsACString,
|
|
|
|
) -> *mut RawServoSourceSizeList {
|
|
|
|
let value = (*value).as_str_unchecked();
|
|
|
|
let mut input = ParserInput::new(value);
|
|
|
|
let mut parser = Parser::new(&mut input);
|
|
|
|
|
|
|
|
let context = ParserContext::new(
|
|
|
|
Origin::Author,
|
|
|
|
dummy_url_data(),
|
|
|
|
Some(CssRuleType::Style),
|
|
|
|
ParsingMode::DEFAULT,
|
|
|
|
QuirksMode::NoQuirks,
|
|
|
|
);
|
|
|
|
|
|
|
|
// NB: Intentionally not calling parse_entirely.
|
|
|
|
let list = SourceSizeList::parse(&context, &mut parser);
|
|
|
|
Box::into_raw(Box::new(list)) as *mut _
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub unsafe extern "C" fn Servo_SourceSizeList_Evaluate(
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
|
|
|
list: RawServoSourceSizeListBorrowedOrNull,
|
|
|
|
) -> i32 {
|
|
|
|
let doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
|
|
|
let device = doc_data.stylist.device();
|
|
|
|
let quirks_mode = doc_data.stylist.quirks_mode();
|
|
|
|
|
|
|
|
let result = match list {
|
|
|
|
Some(list) => {
|
|
|
|
SourceSizeList::from_ffi(list).evaluate(device, quirks_mode)
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
SourceSizeList::empty().evaluate(device, quirks_mode)
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
result.0
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub unsafe extern "C" fn Servo_SourceSizeList_Drop(list: RawServoSourceSizeListOwned) {
|
|
|
|
let _ = list.into_box::<SourceSizeList>();
|
|
|
|
}
|