mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
style: Parse sheets on the thread pool.
Note that we also drop the dead optional aReusableSheets argument from the async parsing path, since it was always null. Bug: 1346988 Reviewed-by: bz,emilio MozReview-Commit-ID: KddpGFdaqEe
This commit is contained in:
parent
c06e3dcd58
commit
dfa019c884
5 changed files with 152 additions and 21 deletions
|
@ -312,3 +312,9 @@ impl_threadsafe_refcount!(
|
|||
Gecko_AddRefSharedFontListArbitraryThread,
|
||||
Gecko_ReleaseSharedFontListArbitraryThread
|
||||
);
|
||||
|
||||
impl_threadsafe_refcount!(
|
||||
::gecko_bindings::structs::SheetLoadDataHolder,
|
||||
Gecko_AddRefSheetLoadDataHolderArbitraryThread,
|
||||
Gecko_ReleaseSheetLoadDataHolderArbitraryThread
|
||||
);
|
||||
|
|
|
@ -171,10 +171,9 @@ pub struct ImportRule {
|
|||
/// The `<url>` this `@import` rule is loading.
|
||||
pub url: CssUrl,
|
||||
|
||||
/// The stylesheet is always present.
|
||||
///
|
||||
/// It contains an empty list of rules and namespace set that is updated
|
||||
/// when it loads.
|
||||
/// The stylesheet is always present. However, in the case of gecko async
|
||||
/// parsing, we don't actually have a Gecko sheet at first, and so the
|
||||
/// ImportSheet just has stub behavior until it appears.
|
||||
pub stylesheet: ImportSheet,
|
||||
|
||||
/// The line and column of the rule's source code.
|
||||
|
|
|
@ -6,6 +6,7 @@ use cssparser::{ParseErrorKind, Parser, ParserInput, SourceLocation};
|
|||
use cssparser::ToCss as ParserToCss;
|
||||
use env_logger::Builder;
|
||||
use malloc_size_of::MallocSizeOfOps;
|
||||
use nsstring::nsCString;
|
||||
use selectors::{NthIndexCache, SelectorList};
|
||||
use selectors::matching::{MatchingContext, MatchingMode, matches_selector};
|
||||
use servo_arc::{Arc, ArcBorrow, RawOffsetArc};
|
||||
|
@ -92,7 +93,8 @@ use style::gecko_bindings::structs;
|
|||
use style::gecko_bindings::structs::{CallerType, CSSPseudoElementType, CompositeOperation};
|
||||
use style::gecko_bindings::structs::{Loader, LoaderReusableStyleSheets};
|
||||
use style::gecko_bindings::structs::{RawServoStyleRule, ComputedStyleStrong, RustString};
|
||||
use style::gecko_bindings::structs::{ServoStyleSheet, SheetLoadData, SheetParsingMode, nsAtom, nsCSSPropertyID};
|
||||
use style::gecko_bindings::structs::{ServoStyleSheet, SheetLoadData, SheetLoadDataHolder};
|
||||
use style::gecko_bindings::structs::{SheetParsingMode, nsAtom, nsCSSPropertyID};
|
||||
use style::gecko_bindings::structs::{nsCSSFontDesc, nsCSSCounterDesc};
|
||||
use style::gecko_bindings::structs::{nsRestyleHint, nsChangeHint, PropertyValuePair};
|
||||
use style::gecko_bindings::structs::AtomArray;
|
||||
|
@ -145,6 +147,7 @@ use style::stylesheets::{DocumentRule, FontFaceRule, FontFeatureValuesRule, Impo
|
|||
use style::stylesheets::{KeyframesRule, MediaRule, NamespaceRule, Origin, OriginSet, PageRule};
|
||||
use style::stylesheets::{StyleRule, StylesheetContents, SupportsRule};
|
||||
use style::stylesheets::StylesheetLoader as StyleStylesheetLoader;
|
||||
use style::stylesheets::import_rule::ImportSheet;
|
||||
use style::stylesheets::keyframes_rule::{Keyframe, KeyframeSelector, KeyframesStepValue};
|
||||
use style::stylesheets::supports_rule::parse_condition_or_declaration;
|
||||
use style::stylist::{add_size_of_ua_cache, AuthorStylesEnabled, RuleInclusion, Stylist};
|
||||
|
@ -163,7 +166,7 @@ use style::values::specified::gecko::{IntersectionObserverRootMargin, PixelOrPer
|
|||
use style::values::specified::source_size_list::SourceSizeList;
|
||||
use style_traits::{CssWriter, ParsingMode, StyleParseErrorKind, ToCss};
|
||||
use super::error_reporter::ErrorReporter;
|
||||
use super::stylesheet_loader::StylesheetLoader;
|
||||
use super::stylesheet_loader::{AsyncStylesheetParser, StylesheetLoader};
|
||||
|
||||
/*
|
||||
* For Gecko->Servo function calls, we need to redeclare the same signature that was declared in
|
||||
|
@ -1122,6 +1125,15 @@ pub extern "C" fn Servo_StyleSheet_Empty(mode: SheetParsingMode) -> RawServoStyl
|
|||
).into_strong()
|
||||
}
|
||||
|
||||
fn mode_to_origin(mode: SheetParsingMode) -> Origin {
|
||||
match mode {
|
||||
SheetParsingMode::eAuthorSheetFeatures => Origin::Author,
|
||||
SheetParsingMode::eUserSheetFeatures => Origin::User,
|
||||
SheetParsingMode::eAgentSheetFeatures => Origin::UserAgent,
|
||||
SheetParsingMode::eSafeAgentSheetFeatures => Origin::UserAgent,
|
||||
}
|
||||
}
|
||||
|
||||
/// Note: The load_data corresponds to this sheet, and is passed as the parent
|
||||
/// load data for child sheet loads. It may be null for certain cases where we
|
||||
/// know we won't have child loads.
|
||||
|
@ -1140,13 +1152,6 @@ pub extern "C" fn Servo_StyleSheet_FromUTF8Bytes(
|
|||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||
let input: &str = unsafe { (*bytes).as_str_unchecked() };
|
||||
|
||||
let origin = match mode {
|
||||
SheetParsingMode::eAuthorSheetFeatures => Origin::Author,
|
||||
SheetParsingMode::eUserSheetFeatures => Origin::User,
|
||||
SheetParsingMode::eAgentSheetFeatures => Origin::UserAgent,
|
||||
SheetParsingMode::eSafeAgentSheetFeatures => Origin::UserAgent,
|
||||
};
|
||||
|
||||
let reporter = ErrorReporter::new(stylesheet, loader, extra_data);
|
||||
let url_data = unsafe { RefPtr::from_ptr_ref(&extra_data) };
|
||||
let loader = if loader.is_null() {
|
||||
|
@ -1163,12 +1168,44 @@ pub extern "C" fn Servo_StyleSheet_FromUTF8Bytes(
|
|||
|
||||
|
||||
Arc::new(StylesheetContents::from_str(
|
||||
input, url_data.clone(), origin,
|
||||
input, url_data.clone(), mode_to_origin(mode),
|
||||
&global_style_data.shared_lock, loader, &reporter,
|
||||
quirks_mode.into(), line_number_offset)
|
||||
).into_strong()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_StyleSheet_FromUTF8BytesAsync(
|
||||
load_data: *mut SheetLoadDataHolder,
|
||||
extra_data: *mut URLExtraData,
|
||||
bytes: *const nsACString,
|
||||
mode: SheetParsingMode,
|
||||
line_number_offset: u32,
|
||||
quirks_mode: nsCompatibility,
|
||||
) {
|
||||
let (load_data, extra_data, bytes) = unsafe {
|
||||
let mut b = nsCString::new();
|
||||
b.assign(&*bytes);
|
||||
(RefPtr::new(load_data), RefPtr::new(extra_data), b)
|
||||
};
|
||||
let async_parser = AsyncStylesheetParser::new(
|
||||
load_data,
|
||||
extra_data,
|
||||
bytes,
|
||||
mode_to_origin(mode),
|
||||
quirks_mode.into(),
|
||||
line_number_offset
|
||||
);
|
||||
|
||||
if let Some(thread_pool) = STYLE_THREAD_POOL.style_thread_pool.as_ref() {
|
||||
thread_pool.spawn(|| {
|
||||
async_parser.parse();
|
||||
});
|
||||
} else {
|
||||
async_parser.parse();
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_StyleSet_AppendStyleSheet(
|
||||
raw_data: RawServoStyleSetBorrowed,
|
||||
|
@ -2051,6 +2088,17 @@ pub extern "C" fn Servo_ImportRule_GetSheet(
|
|||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_ImportRule_SetSheet(
|
||||
rule: RawServoImportRuleBorrowed,
|
||||
sheet: *mut ServoStyleSheet,
|
||||
) {
|
||||
write_locked_arc(rule, |rule: &mut ImportRule| {
|
||||
let sheet = unsafe { GeckoStyleSheet::new(sheet) };
|
||||
rule.stylesheet = ImportSheet::new(sheet);
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_Keyframe_GetKeyText(
|
||||
keyframe: RawServoKeyframeBorrowed,
|
||||
|
|
|
@ -9,6 +9,7 @@ extern crate env_logger;
|
|||
extern crate libc;
|
||||
#[macro_use] extern crate log;
|
||||
extern crate malloc_size_of;
|
||||
extern crate nsstring;
|
||||
extern crate selectors;
|
||||
extern crate servo_arc;
|
||||
extern crate smallvec;
|
||||
|
|
|
@ -3,15 +3,24 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use cssparser::SourceLocation;
|
||||
use nsstring::nsCString;
|
||||
use servo_arc::Arc;
|
||||
use style::context::QuirksMode;
|
||||
use style::error_reporting::NullReporter;
|
||||
use style::gecko::data::GeckoStyleSheet;
|
||||
use style::gecko::global_style_data::GLOBAL_STYLE_DATA;
|
||||
use style::gecko_bindings::bindings;
|
||||
use style::gecko_bindings::bindings::Gecko_LoadStyleSheet;
|
||||
use style::gecko_bindings::structs::{Loader, ServoStyleSheet, SheetLoadData, LoaderReusableStyleSheets};
|
||||
use style::gecko_bindings::structs::{Loader, LoaderReusableStyleSheets};
|
||||
use style::gecko_bindings::structs::{ServoStyleSheet, SheetLoadData, SheetLoadDataHolder};
|
||||
use style::gecko_bindings::structs::URLExtraData;
|
||||
use style::gecko_bindings::sugar::ownership::FFIArcHelpers;
|
||||
use style::gecko_bindings::sugar::refptr::RefPtr;
|
||||
use style::media_queries::MediaList;
|
||||
use style::parser::ParserContext;
|
||||
use style::shared_lock::{Locked, SharedRwLock};
|
||||
use style::stylesheets::{ImportRule, StylesheetLoader as StyleStylesheetLoader};
|
||||
use style::stylesheets::{ImportRule, Origin, StylesheetLoader as StyleStylesheetLoader};
|
||||
use style::stylesheets::StylesheetContents;
|
||||
use style::stylesheets::import_rule::ImportSheet;
|
||||
use style::values::CssUrl;
|
||||
|
||||
|
@ -41,15 +50,11 @@ impl StyleStylesheetLoader for StylesheetLoader {
|
|||
// so this raw pointer will still be valid.
|
||||
|
||||
let child_sheet = unsafe {
|
||||
let (spec_bytes, spec_len) = url.as_slice_components();
|
||||
let base_url_data = url.extra_data.get();
|
||||
Gecko_LoadStyleSheet(self.0,
|
||||
self.1,
|
||||
self.2,
|
||||
self.3,
|
||||
base_url_data,
|
||||
spec_bytes,
|
||||
spec_len as u32,
|
||||
url.for_ffi(),
|
||||
media.into_strong())
|
||||
};
|
||||
|
||||
|
@ -60,3 +65,75 @@ impl StyleStylesheetLoader for StylesheetLoader {
|
|||
Arc::new(lock.wrap(ImportRule { url, source_location, stylesheet }))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AsyncStylesheetParser {
|
||||
load_data: RefPtr<SheetLoadDataHolder>,
|
||||
extra_data: RefPtr<URLExtraData>,
|
||||
bytes: nsCString,
|
||||
origin: Origin,
|
||||
quirks_mode: QuirksMode,
|
||||
line_number_offset: u32,
|
||||
}
|
||||
|
||||
impl AsyncStylesheetParser {
|
||||
pub fn new(
|
||||
load_data: RefPtr<SheetLoadDataHolder>,
|
||||
extra_data: RefPtr<URLExtraData>,
|
||||
bytes: nsCString,
|
||||
origin: Origin,
|
||||
quirks_mode: QuirksMode,
|
||||
line_number_offset: u32,
|
||||
) -> Self {
|
||||
AsyncStylesheetParser {
|
||||
load_data,
|
||||
extra_data,
|
||||
bytes,
|
||||
origin,
|
||||
quirks_mode,
|
||||
line_number_offset,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(self) {
|
||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||
let input: &str = unsafe { (*self.bytes).as_str_unchecked() };
|
||||
|
||||
// Note: Parallel CSS parsing doesn't report CSS errors. When errors
|
||||
// are being logged, Gecko prevents the parallel parsing path from
|
||||
// running.
|
||||
let sheet = Arc::new(StylesheetContents::from_str(
|
||||
input, self.extra_data.clone(), self.origin,
|
||||
&global_style_data.shared_lock, Some(&self), &NullReporter,
|
||||
self.quirks_mode.into(), self.line_number_offset)
|
||||
);
|
||||
|
||||
unsafe {
|
||||
bindings::Gecko_StyleSheet_FinishAsyncParse(self.load_data.get(), sheet.into_strong());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StyleStylesheetLoader for AsyncStylesheetParser {
|
||||
fn request_stylesheet(
|
||||
&self,
|
||||
url: CssUrl,
|
||||
source_location: SourceLocation,
|
||||
_context: &ParserContext,
|
||||
lock: &SharedRwLock,
|
||||
media: Arc<Locked<MediaList>>,
|
||||
) -> Arc<Locked<ImportRule>> {
|
||||
let stylesheet = ImportSheet::new_pending(self.origin, self.quirks_mode);
|
||||
let rule = Arc::new(lock.wrap(ImportRule { url: url.clone(), source_location, stylesheet }));
|
||||
|
||||
unsafe {
|
||||
bindings::Gecko_LoadStyleSheetAsync(
|
||||
self.load_data.get(),
|
||||
url.for_ffi(),
|
||||
media.into_strong(),
|
||||
rule.clone().into_strong()
|
||||
);
|
||||
}
|
||||
|
||||
rule
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue