script: Ensure JS->webdriver conversions have a non-empty settings stack (#38709)

JS scripts that are evaluated already run with an [entry
script](https://html.spec.whatwg.org/#entry) on the script settings
stack. The codepaths that do something with the return value (eg.
WebDriver and embedder JS evaluation) have the potential to run
additional JS, since they can trigger getters for arbitrary properties
of objects, so they also need an entry script present in case code like
e649b9b91d/components/script/dom/location.rs (L182)
is executed.

Testing: Added a regression unit test.
Fixes: #38692

Signed-off-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
Josh Matthews 2025-08-16 13:14:56 -04:00 committed by GitHub
parent f19b2f6e84
commit e80d36783a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 16 additions and 0 deletions

View file

@ -59,6 +59,7 @@ use crate::dom::bindings::error::{Error, report_pending_exception, throw_dom_exc
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::{DomGlobal, DomObject};
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::settings_stack::AutoEntryScript;
use crate::dom::bindings::str::DOMString;
use crate::dom::document::Document;
use crate::dom::domrect::DOMRect;
@ -345,6 +346,7 @@ pub(crate) fn jsval_to_webdriver(
realm: InRealm,
can_gc: CanGc,
) -> WebDriverJSResult {
let _aes = AutoEntryScript::new(global_scope);
let mut seen = HashSet::new();
let result = unsafe { jsval_to_webdriver_inner(*cx, global_scope, val, &mut seen) };
if result.is_err() {

View file

@ -134,6 +134,19 @@ fn test_evaluate_javascript_basic(servo_test: &ServoTest) -> Result<(), anyhow::
Ok(())
}
fn test_evaluate_javascript_panic(servo_test: &ServoTest) -> Result<(), anyhow::Error> {
let delegate = Rc::new(WebViewDelegateImpl::default());
let webview = WebViewBuilder::new(servo_test.servo())
.delegate(delegate.clone())
.build();
let input = "location";
let result = evaluate_javascript(servo_test, webview.clone(), input);
ensure!(matches!(result, Ok(JSValue::Object(..))));
Ok(())
}
fn test_create_webview_and_immediately_drop_webview_before_shutdown(
servo_test: &ServoTest,
) -> Result<(), anyhow::Error> {
@ -174,6 +187,7 @@ fn main() {
run_api_tests!(
test_create_webview,
test_evaluate_javascript_basic,
test_evaluate_javascript_panic,
test_theme_change,
// This test needs to be last, as it tests creating and dropping
// a WebView right before shutdown.