mirror of
https://github.com/lexmount/moli.git
synced 2026-10-06 16:01:00 +00:00
fix(script): share the service-worker loader for child classics
This commit is contained in:
@@ -335,6 +335,11 @@ fn fixture_response(
|
||||
);
|
||||
("200 OK", javascript.to_owned(), body)
|
||||
}
|
||||
"/child-classic.html" => (
|
||||
"200 OK",
|
||||
"Content-Type: text/html\r\n".to_owned(),
|
||||
"<!doctype html><body><script>globalThis.sriExecutions=0</script><script src='/sw-default.js?parser'></script>".to_owned(),
|
||||
),
|
||||
"/page.html" | "/parser.html" | "/cookie-page.html" | "/csp-page.html" => {
|
||||
let mut html = "<!doctype html><body><script>globalThis.sriEvents = {}; globalThis.sriExecutions = 0;</script>".to_owned();
|
||||
if path == "/csp-page.html" {
|
||||
@@ -792,6 +797,53 @@ async fn manifest_roundtrip_checks_intermediate_and_final_cors_responses() -> Re
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn child_classic_scripts_use_the_controlling_service_worker() -> Result<()> {
|
||||
let servers = IntegrityServers::spawn().await?;
|
||||
let browser = Browser::new(AppConfig::default())?;
|
||||
let mut page = browser
|
||||
.fetch(&format!("{}/page.html", servers.origin))
|
||||
.await?;
|
||||
let result = tokio::time::timeout(
|
||||
Duration::from_secs(15),
|
||||
page.evaluate_runtime_expression_with_await_async(
|
||||
r#"(async () => {
|
||||
const controlled = navigator.serviceWorker.controller ? Promise.resolve() :
|
||||
new Promise(resolve => navigator.serviceWorker.addEventListener('controllerchange', resolve, {once:true}));
|
||||
await navigator.serviceWorker.register('/worker.js', {scope:'/'});
|
||||
await navigator.serviceWorker.ready;
|
||||
await controlled;
|
||||
const child = document.createElement('iframe');
|
||||
child.src='/child-classic.html';
|
||||
await new Promise(resolve => {child.onload=resolve;document.body.append(child);});
|
||||
const other = child.contentWindow;
|
||||
if (other.sriExecutions !== 1) throw new Error('parser script did not execute');
|
||||
const script = other.document.createElement('script');
|
||||
script.src='/sw-default.js?dynamic';
|
||||
await new Promise((resolve,reject) => {
|
||||
script.onload=resolve;
|
||||
script.onerror=() => reject(new Error('dynamic script failed'));
|
||||
other.document.body.append(script);
|
||||
});
|
||||
const executions = other.sriExecutions;
|
||||
child.remove();
|
||||
return executions;
|
||||
})()"#,
|
||||
true,
|
||||
),
|
||||
).await??;
|
||||
assert_eq!(result["value"], 2, "{result}");
|
||||
assert!(
|
||||
!servers
|
||||
.requests
|
||||
.lock()
|
||||
.iter()
|
||||
.any(|request| request.path.starts_with("/sw-default.js")),
|
||||
"both child script paths must be served by the controlling service worker"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn service_worker_script_integrity_preserves_response_filter() -> Result<()> {
|
||||
let servers = IntegrityServers::spawn().await?;
|
||||
|
||||
@@ -295,14 +295,23 @@ impl JsContextHost {
|
||||
.unwrap_or_else(|| self.document_character_set().to_owned());
|
||||
let completion_tx = self.resource_completion_tx.clone();
|
||||
let task_loader = loader.clone();
|
||||
let browser_context_runtime = self.browser_context_runtime();
|
||||
let client_id = self.service_worker_client_id_for_subresource_owner(
|
||||
crate::native_bridge::context_host::OwnerDispatchScope::Child(handle),
|
||||
);
|
||||
let document_url = network_attribution.document_url.clone();
|
||||
loader.spawn_resource_task(async move {
|
||||
let outcome =
|
||||
crate::planning::load_prepared_script_source_outcome_with_document_character_set(
|
||||
crate::planning::load_service_worker_aware_external_script_source_outcome(
|
||||
&script_for_load,
|
||||
&task_loader.fetch_context().request_origin(),
|
||||
task_loader.request_client(),
|
||||
task_loader.task_runner(),
|
||||
Some(&document_character_set),
|
||||
None,
|
||||
browser_context_runtime,
|
||||
client_id,
|
||||
document_url,
|
||||
)
|
||||
.await;
|
||||
let _ = completion_tx.send_child_classic_script(ChildClassicScriptLoadCompletion {
|
||||
@@ -708,14 +717,23 @@ impl JsContextHost {
|
||||
return;
|
||||
}
|
||||
let task_loader = loader.clone();
|
||||
let browser_context_runtime = self.browser_context_runtime();
|
||||
let client_id = self.service_worker_client_id_for_subresource_owner(
|
||||
crate::native_bridge::context_host::OwnerDispatchScope::Child(child_handle),
|
||||
);
|
||||
let document_url = network_attribution.document_url.clone();
|
||||
loader.spawn_resource_task(async move {
|
||||
let outcome =
|
||||
crate::planning::load_prepared_script_source_outcome_with_document_character_set(
|
||||
crate::planning::load_service_worker_aware_external_script_source_outcome(
|
||||
&script_for_load,
|
||||
&task_loader.fetch_context().request_origin(),
|
||||
task_loader.request_client(),
|
||||
task_loader.task_runner(),
|
||||
Some(&document_character_set),
|
||||
None,
|
||||
browser_context_runtime,
|
||||
client_id,
|
||||
document_url,
|
||||
)
|
||||
.await;
|
||||
let _ = completion_tx.send_child_classic_script(ChildClassicScriptLoadCompletion {
|
||||
|
||||
Reference in New Issue
Block a user