fix(wasm): preserve binary fetch responses (#48)
* fix wasm response handling * fix URL inputs in fetch polyfill * test(wasm): cover binary fetch responses
This commit is contained in:
1 parent
fdec52c70f
commit
53a04fa905
6 files changed
+217
-30
No files matched your search
@@ -6,6 +6,7 @@ use std::sync::{Arc, OnceLock};
|
||||
use deno_core::op2;
|
||||
use deno_core::OpState;
|
||||
use deno_core::Extension;
|
||||
use base64::{engine::general_purpose::STANDARD as BASE64, Engine as _};
|
||||
use obscura_dom::{DomTree, NodeData, NodeId};
|
||||
use obscura_net::{CookieJar, ObscuraHttpClient};
|
||||
use tokio::sync::Mutex;
|
||||
@@ -517,16 +518,19 @@ async fn op_fetch_url(
|
||||
}
|
||||
}
|
||||
|
||||
let resp_body = response
|
||||
.text()
|
||||
let resp_bytes = response
|
||||
.bytes()
|
||||
.await
|
||||
.map_err(|e| deno_error::JsErrorBox::generic(e.to_string()))?;
|
||||
let resp_body = String::from_utf8_lossy(&resp_bytes).to_string();
|
||||
let resp_body_base64 = BASE64.encode(&resp_bytes);
|
||||
|
||||
tracing::debug!("op_fetch_url completed: {} {} ({} bytes)", method, url, resp_body.len());
|
||||
|
||||
Ok(serde_json::json!({
|
||||
"status": status,
|
||||
"body": resp_body,
|
||||
"bodyBase64": resp_body_base64,
|
||||
"url": url,
|
||||
"headers": resp_headers,
|
||||
})
|
||||
|
||||
@@ -1282,6 +1282,92 @@ mod tests {
|
||||
assert_eq!(result.as_str().unwrap(), "http://localhost:8080/dir/api.json");
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn test_fetch_url_input_decodes_binary_body_base64() {
|
||||
let mut rt = setup_runtime("<html><body></body></html>");
|
||||
let result = rt.call_function_on_for_cdp(
|
||||
r#"async () => {
|
||||
const originalFetchOp = Deno.core.ops.op_fetch_url;
|
||||
try {
|
||||
Deno.core.ops.op_fetch_url = (url) => {
|
||||
globalThis.__capturedFetchUrl = url;
|
||||
return JSON.stringify({
|
||||
status: 200,
|
||||
headers: { "content-type": "application/wasm" },
|
||||
bodyBase64: "AGFzbQEAAAA=",
|
||||
url,
|
||||
});
|
||||
};
|
||||
const response = await fetch(new URL("/pkg/app_bg.wasm", document.URL));
|
||||
const bytes = Array.from(new Uint8Array(await response.arrayBuffer()));
|
||||
return { url: globalThis.__capturedFetchUrl, bytes };
|
||||
} finally {
|
||||
Deno.core.ops.op_fetch_url = originalFetchOp;
|
||||
}
|
||||
}"#,
|
||||
None,
|
||||
&[],
|
||||
true,
|
||||
true,
|
||||
).await.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
result.value.unwrap(),
|
||||
serde_json::json!({
|
||||
"url": "http://example.com/pkg/app_bg.wasm",
|
||||
"bytes": [0, 97, 115, 109, 1, 0, 0, 0],
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn test_response_array_buffer_preserves_typed_array_view() {
|
||||
let mut rt = setup_runtime("<html><body></body></html>");
|
||||
let result = rt.call_function_on_for_cdp(
|
||||
r#"async () => {
|
||||
const bytes = new Uint8Array([9, 0, 97, 115, 109, 1, 8]);
|
||||
const response = new Response(bytes.subarray(1, 6));
|
||||
return Array.from(new Uint8Array(await response.arrayBuffer()));
|
||||
}"#,
|
||||
None,
|
||||
&[],
|
||||
true,
|
||||
true,
|
||||
).await.unwrap();
|
||||
|
||||
assert_eq!(result.value.unwrap(), serde_json::json!([0, 97, 115, 109, 1]));
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn test_wasm_instantiate_streaming_uses_response_array_buffer() {
|
||||
let mut rt = setup_runtime("<html><body></body></html>");
|
||||
let result = rt.call_function_on_for_cdp(
|
||||
r#"async () => {
|
||||
const bytes = new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0]);
|
||||
const result = await WebAssembly.instantiateStreaming(
|
||||
Promise.resolve(new Response(bytes)),
|
||||
{},
|
||||
);
|
||||
return result.instance instanceof WebAssembly.Instance;
|
||||
}"#,
|
||||
None,
|
||||
&[],
|
||||
true,
|
||||
true,
|
||||
).await.unwrap();
|
||||
|
||||
assert_eq!(result.value.unwrap(), serde_json::json!(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_text_decoder_respects_typed_array_view() {
|
||||
let mut rt = setup_runtime("<html><body></body></html>");
|
||||
let result = rt.evaluate(
|
||||
"new TextDecoder().decode(new Uint8Array([65, 66, 67]).subarray(1, 2))"
|
||||
).unwrap();
|
||||
assert_eq!(result.as_str().unwrap(), "B");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_document_doctype() {
|
||||
let mut rt = setup_runtime("<!DOCTYPE html><html><body></body></html>");
|
||||
|
||||
Reference in new issue
Block a user