fix(api/js): Browser cookie jar + base href + Node.baseURI + XHR EventTarget + Page::settle (closes #241,#242,#244,#245,#247) (#243)
* fix(api): Browser::cookies() now shares context's CookieJar Previously Browser::build() created its own empty CookieJar, while BrowserContext internally creates a separate jar that actually receives Set-Cookie headers from HTTP responses. This caused browser.cookies().get_all() to always return empty after navigation — the populated jar was unreachable. Fix: use context.cookie_jar instead of creating a separate one. Also removes redundant cookie-loading logic in Browser::build() since BrowserContext::_new_inner already handles loading from storage_dir. Closes #241 * fix(browser): add <base href> support for script URL resolution (closes #242) Previously resolve_base_url() returned the document URL directly, causing relative <script src> URLs to resolve against the page URL rather than the <base href> target. On SPAs served from sub-paths (Angular/Vite/Next.js), this caused all bundle scripts to 404. Add resolve_base_url() that queries DOM for <base href> and uses it as the base for relative URL resolution per HTML spec. Applied to both regular scripts and ES modules in execute_scripts(). * fix(js): implement Node.baseURI getter per WHATWG DOM spec (closes #244) Node.baseURI was missing from the bootstrap.js Node class, causing document.baseURI to return undefined. This broke Angular's PlatformLocation.getBaseHref which calls new URL(href, document.baseURI) -- with baseURI empty, the URL constructor throws Invalid URL. Per https://dom.spec.whatwg.org/#dom-node-baseuri, Node.baseURI must return the href of the first <base href> resolved against the document URL, falling back to the document URL when no <base> is present. * fix(js): add XMLHttpRequestEventTarget + XHR dispatchEvent (closes #245) XHR shim lacked dispatchEvent and XMLHttpRequestEventTarget, causing zone.js (Angular/zone.js) to crash with 'Cannot read properties of undefined (reading call)' when Angular's HttpClient makes XHR calls. Add spec-compliant XMLHttpRequestEventTarget base class with addEventListener/removeEventListener/dispatchEvent. Make XHR extend it so zone.js can walk the proto chain correctly. * fix(js): fix XHR super() call order in ES6 class extends * fix(js): use base href for dynamic script/module URL resolution Angular lazy-loaded chunks were resolving against document.location.href instead of the <base href>. This caused all dynamic import() chunks on the Deutsche Boerse SPA to 404 (/bond/7591.xxx.js instead of /7591.xxx.js). Fix: resolve dynamic script src against <base href> when present, falling back to location.href per HTML spec. * Revert "fix(js): use base href for dynamic script/module URL resolution" This reverts commit 88af239be38f2aa11c3c978a4db2a7482f2ed6c0. * feat(api): expose Page::settle() to pump JS event loop (closes #247) obscura_browser::Page already had settle(max_ms) but it was unreachable from the public API. Exposing it allows callers to resolve Promises, fetch callbacks, and microtasks before reading results with evaluate(). --------- Co-authored-by: zhangyang-crazy-one <[email protected]>
This commit is contained in:
1 parent
6dea35bd0c
commit
98b62e53e8
4 files changed
+112
-16
No files matched your search
@@ -22,15 +22,6 @@ impl Browser {
|
||||
}
|
||||
|
||||
pub fn build(config: BrowserConfig) -> Result<Self, Error> {
|
||||
let cookie_jar = Arc::new(CookieJar::new());
|
||||
|
||||
if let Some(ref dir) = config.storage_dir {
|
||||
let cookie_path = dir.join("cookies.json");
|
||||
if cookie_path.exists() {
|
||||
let _ = cookie_jar.load_from_file(&cookie_path);
|
||||
}
|
||||
}
|
||||
|
||||
let context = if let Some(ref dir) = config.storage_dir {
|
||||
BrowserContext::with_storage_full(
|
||||
"api".to_string(),
|
||||
@@ -48,10 +39,10 @@ impl Browser {
|
||||
)
|
||||
};
|
||||
|
||||
Ok(Browser {
|
||||
context: Arc::new(context),
|
||||
cookie_jar,
|
||||
})
|
||||
let context = Arc::new(context);
|
||||
let cookie_jar = context.cookie_jar.clone();
|
||||
|
||||
Ok(Browser { context, cookie_jar })
|
||||
}
|
||||
|
||||
pub fn builder() -> BrowserBuilder {
|
||||
|
||||
@@ -84,6 +84,15 @@ impl Page {
|
||||
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||
}
|
||||
}
|
||||
|
||||
/// Drive the page's JS event loop for up to `max_ms` milliseconds.
|
||||
///
|
||||
/// Call this after `evaluate()` kicks off async work (Promises, fetch,
|
||||
/// setTimeout, RxJS subscribers) to let the V8 event loop pump and
|
||||
/// resolve scheduled microtasks/macrotasks before the next `evaluate()`.
|
||||
pub async fn settle(&mut self, max_ms: u64) {
|
||||
self.inner.settle(max_ms).await
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle to a DOM element.
|
||||
|
||||
Reference in new issue
Block a user