mirror of
https://github.com/lexmount/moli.git
synced 2026-09-28 16:01:39 +00:00
fix(stylesheets): preserve parser event ordering
This commit is contained in:
Vendored
+7
-6
@@ -3,17 +3,18 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
window.runtimeInsertedHrefMutationStart = Date.now();
|
||||
|
||||
const link = document.createElement("link");
|
||||
link.rel = "stylesheet";
|
||||
link.href = "/assets/blocking_stylesheet_slow.css?stale=1";
|
||||
link.href =
|
||||
"/assets/runtime_inserted_stylesheet_href_mutation_stale.css";
|
||||
document.head.appendChild(link);
|
||||
link.href = "/assets/chrome_stylesheetlist_1.css?fresh=1";
|
||||
link.href =
|
||||
"/assets/runtime_inserted_stylesheet_href_mutation_fresh.css";
|
||||
</script>
|
||||
<script
|
||||
src="/assets/runtime_inserted_stylesheet_href_mutation_probe.js"
|
||||
></script>
|
||||
<script>
|
||||
window.runtimeInsertedHrefMutationParserNotBlocked =
|
||||
Date.now() - window.runtimeInsertedHrefMutationStart < 50;
|
||||
window.runtimeInsertedHrefMutationSawLate =
|
||||
!!document.getElementById("late");
|
||||
</script>
|
||||
|
||||
@@ -830,6 +830,10 @@ async fn runtime_inserted_stylesheet_load_can_trigger_location_replace() -> Resu
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn runtime_inserted_stylesheet_href_mutation_uses_fresh_fetch_for_parser_blocking_progress()
|
||||
-> Result<()> {
|
||||
// The stale stylesheet response is gated until the following parser script
|
||||
// requests its probe. The probe reports whether it arrived before the
|
||||
// stale-response fallback fired, so this checks parser progress without a
|
||||
// wall-clock threshold in page script.
|
||||
let server = FixtureServer::spawn().await?;
|
||||
let browser = Browser::new(AppConfig::default())?;
|
||||
|
||||
@@ -845,6 +849,12 @@ async fn runtime_inserted_stylesheet_href_mutation_uses_fresh_fetch_for_parser_b
|
||||
diagnostic_global(&page, "runtimeInsertedHrefMutationSawLate"),
|
||||
Some(&JsValueSnapshot::Bool(false))
|
||||
);
|
||||
assert!(
|
||||
page.subresource_network_records().iter().any(|record| {
|
||||
record.url().path() == "/assets/runtime_inserted_stylesheet_href_mutation_fresh.css"
|
||||
}),
|
||||
"the retargeted stylesheet must start the fresh fetch"
|
||||
);
|
||||
|
||||
server.shutdown().await;
|
||||
Ok(())
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use super::*;
|
||||
use parking_lot::Mutex;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||
use std::sync::{Arc, OnceLock};
|
||||
|
||||
static NET_UPSTREAM_XHR_404_THEN_200_REQUESTS: AtomicUsize = AtomicUsize::new(0);
|
||||
@@ -21,6 +21,25 @@ static RUNTIME_OWNED_IN_ORDER_ERROR_AFTER_DCL_GATES: OnceLock<
|
||||
static RUNTIME_OWNED_IN_ORDER_LOAD_AFTER_DCL_GATES: OnceLock<
|
||||
Mutex<HashMap<String, Arc<tokio::sync::Notify>>>,
|
||||
> = OnceLock::new();
|
||||
static RUNTIME_INSERTED_STYLESHEET_HREF_MUTATION_GATES: OnceLock<
|
||||
Mutex<HashMap<String, Arc<RuntimeInsertedStylesheetHrefMutationGate>>>,
|
||||
> = OnceLock::new();
|
||||
|
||||
struct RuntimeInsertedStylesheetHrefMutationGate {
|
||||
release_stale_response: tokio::sync::Notify,
|
||||
stale_request_started: AtomicBool,
|
||||
stale_response_timed_out: AtomicBool,
|
||||
}
|
||||
|
||||
impl RuntimeInsertedStylesheetHrefMutationGate {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
release_stale_response: tokio::sync::Notify::new(),
|
||||
stale_request_started: AtomicBool::new(false),
|
||||
stale_response_timed_out: AtomicBool::new(false),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ConcurrentSharedStateRequestGuard;
|
||||
|
||||
@@ -169,6 +188,34 @@ pub(crate) fn notify_runtime_owned_in_order_load_after_dcl_gate(host_key: &str)
|
||||
runtime_owned_in_order_load_after_dcl_gate(host_key).notify_one();
|
||||
}
|
||||
|
||||
fn runtime_inserted_stylesheet_href_mutation_gate(
|
||||
host_key: &str,
|
||||
) -> Arc<RuntimeInsertedStylesheetHrefMutationGate> {
|
||||
let gates =
|
||||
RUNTIME_INSERTED_STYLESHEET_HREF_MUTATION_GATES.get_or_init(|| Mutex::new(HashMap::new()));
|
||||
let mut gates = gates.lock();
|
||||
gates
|
||||
.entry(host_key.to_owned())
|
||||
.or_insert_with(|| Arc::new(RuntimeInsertedStylesheetHrefMutationGate::new()))
|
||||
.clone()
|
||||
}
|
||||
|
||||
fn remove_runtime_inserted_stylesheet_href_mutation_gate(host_key: &str) {
|
||||
let Some(gates) = RUNTIME_INSERTED_STYLESHEET_HREF_MUTATION_GATES.get() else {
|
||||
return;
|
||||
};
|
||||
gates.lock().remove(host_key);
|
||||
}
|
||||
|
||||
pub(crate) fn clear_runtime_inserted_stylesheet_href_mutation_gate(host_key: &str) {
|
||||
let Some(gates) = RUNTIME_INSERTED_STYLESHEET_HREF_MUTATION_GATES.get() else {
|
||||
return;
|
||||
};
|
||||
if let Some(gate) = gates.lock().remove(host_key) {
|
||||
gate.release_stale_response.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) async fn static_page() -> Html<&'static str> {
|
||||
Html(STATIC_HTML)
|
||||
}
|
||||
@@ -5526,6 +5573,45 @@ pub(super) async fn asset_dynamic_blocking_stylesheet_gated_css(
|
||||
css_response(BLOCKING_STYLESHEET_SLOW_CSS)
|
||||
}
|
||||
|
||||
pub(super) async fn asset_runtime_inserted_stylesheet_href_mutation_stale_css(
|
||||
headers: HeaderMap,
|
||||
) -> Response {
|
||||
let host_key = request_host_key(&headers).unwrap_or_default();
|
||||
let gate = runtime_inserted_stylesheet_href_mutation_gate(&host_key);
|
||||
gate.stale_request_started.store(true, Ordering::SeqCst);
|
||||
let released_by_probe = tokio::time::timeout(
|
||||
Duration::from_secs(2),
|
||||
gate.release_stale_response.notified(),
|
||||
)
|
||||
.await
|
||||
.is_ok();
|
||||
if released_by_probe {
|
||||
remove_runtime_inserted_stylesheet_href_mutation_gate(&host_key);
|
||||
} else {
|
||||
gate.stale_response_timed_out.store(true, Ordering::SeqCst);
|
||||
}
|
||||
css_response(BLOCKING_STYLESHEET_SLOW_CSS)
|
||||
}
|
||||
|
||||
pub(super) async fn asset_runtime_inserted_stylesheet_href_mutation_fresh_css() -> Response {
|
||||
css_response(CHROME_STYLESHEETLIST_1_CSS)
|
||||
}
|
||||
|
||||
pub(super) async fn asset_runtime_inserted_stylesheet_href_mutation_probe_script(
|
||||
headers: HeaderMap,
|
||||
) -> Response {
|
||||
let host_key = request_host_key(&headers).unwrap_or_default();
|
||||
let gate = runtime_inserted_stylesheet_href_mutation_gate(&host_key);
|
||||
let parser_not_blocked = !gate.stale_response_timed_out.load(Ordering::SeqCst);
|
||||
gate.release_stale_response.notify_one();
|
||||
if gate.stale_request_started.load(Ordering::SeqCst) {
|
||||
remove_runtime_inserted_stylesheet_href_mutation_gate(&host_key);
|
||||
}
|
||||
javascript_string_response(format!(
|
||||
"window.runtimeInsertedHrefMutationParserNotBlocked = {parser_not_blocked};"
|
||||
))
|
||||
}
|
||||
|
||||
pub(super) async fn asset_runtime_connected_preload_very_slow_css() -> Response {
|
||||
sleep(Duration::from_millis(250)).await;
|
||||
css_response(BLOCKING_STYLESHEET_SLOW_CSS)
|
||||
|
||||
@@ -52,6 +52,9 @@ impl FixtureServer {
|
||||
}
|
||||
|
||||
pub async fn shutdown(mut self) {
|
||||
crate::routes_core::clear_runtime_inserted_stylesheet_href_mutation_gate(
|
||||
&self.addr.to_string(),
|
||||
);
|
||||
if let Some(shutdown_tx) = self.shutdown_tx.take() {
|
||||
let _ = shutdown_tx.send(());
|
||||
}
|
||||
@@ -64,6 +67,9 @@ impl FixtureServer {
|
||||
|
||||
impl Drop for FixtureServer {
|
||||
fn drop(&mut self) {
|
||||
crate::routes_core::clear_runtime_inserted_stylesheet_href_mutation_gate(
|
||||
&self.addr.to_string(),
|
||||
);
|
||||
if let Some(shutdown_tx) = self.shutdown_tx.take() {
|
||||
let _ = shutdown_tx.send(());
|
||||
}
|
||||
|
||||
@@ -2393,6 +2393,18 @@ pub(super) fn build_router() -> Router {
|
||||
"/assets/blocking_stylesheet_slow.css",
|
||||
get(asset_blocking_stylesheet_slow_css),
|
||||
)
|
||||
.route(
|
||||
"/assets/runtime_inserted_stylesheet_href_mutation_stale.css",
|
||||
get(asset_runtime_inserted_stylesheet_href_mutation_stale_css),
|
||||
)
|
||||
.route(
|
||||
"/assets/runtime_inserted_stylesheet_href_mutation_fresh.css",
|
||||
get(asset_runtime_inserted_stylesheet_href_mutation_fresh_css),
|
||||
)
|
||||
.route(
|
||||
"/assets/runtime_inserted_stylesheet_href_mutation_probe.js",
|
||||
get(asset_runtime_inserted_stylesheet_href_mutation_probe_script),
|
||||
)
|
||||
.route(
|
||||
"/assets/runtime_connected_modulepreload_slow.mjs",
|
||||
get(asset_runtime_connected_modulepreload_slow_module),
|
||||
|
||||
Reference in New Issue
Block a user