mirror of
https://github.com/servo/servo.git
synced 2025-07-18 21:03:45 +01:00
These changes introduce a new kind of task that uses a variation of the `task!` syntax. Existing `task!` usages create task structs that have a `Send` bound, which requires the use of `Trusted<T>` to reference a DOM object T inside of the task closure. The new syntax replaces the `Send` bound with a `JSTraceable` bound, which requires explicit capture clauses with types. This looks like: ```rust task!(ScriptPrepare: {script: DomRoot<HTMLScriptElement>} |script| { script.prepare(CanGc::note()); }), ``` The capture clauses must list every value that will be referenced from the closure's environment—these values are moved into fields in the generated task structure, which allows them to be traced by the GC as part of a generated JSTraceable implementation. Since the closure itself is not a `move` closure, any attempts to reference values not explicitly captured will generate a borrow checker error since the closure requires the `'static` lifetime. Testing: Existing WPT tests exercise these code paths. I also attempted to write incorrect tasks that capture references or use values not explicitly captured, and the compiler correctly errors out. Fixes: part of #35517 Signed-off-by: Josh Matthews <josh@joshmatthews.net>
45 lines
1.6 KiB
Rust
45 lines
1.6 KiB
Rust
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
|
|
use std::rc::Rc;
|
|
|
|
use js::jsval::UndefinedValue;
|
|
use script_bindings::root::DomRoot;
|
|
|
|
use crate::dom::bindings::str::DOMString;
|
|
use crate::dom::htmlheadelement::HTMLHeadElement;
|
|
use crate::dom::htmlscriptelement::SourceCode;
|
|
use crate::dom::node::NodeTraits;
|
|
use crate::dom::window::Window;
|
|
use crate::script_module::ScriptFetchOptions;
|
|
use crate::script_runtime::CanGc;
|
|
|
|
pub(crate) fn load_script(head: &HTMLHeadElement) {
|
|
let doc = head.owner_document();
|
|
let userscripts = doc.window().userscripts().to_owned();
|
|
if userscripts.is_empty() {
|
|
return;
|
|
}
|
|
let win = DomRoot::from_ref(doc.window());
|
|
doc.add_delayed_task(task!(UserScriptExecute: |win: DomRoot<Window>| {
|
|
let cx = win.get_cx();
|
|
rooted!(in(*cx) let mut rval = UndefinedValue());
|
|
|
|
for user_script in userscripts {
|
|
let script_text = SourceCode::Text(
|
|
Rc::new(DOMString::from_string(user_script.script))
|
|
);
|
|
let global_scope = win.as_global_scope();
|
|
global_scope.evaluate_script_on_global_with_result(
|
|
&script_text,
|
|
&user_script.source_file.map(|path| path.to_string_lossy().to_string()).unwrap_or_default(),
|
|
rval.handle_mut(),
|
|
1,
|
|
ScriptFetchOptions::default_classic_script(global_scope),
|
|
global_scope.api_base_url(),
|
|
CanGc::note(),
|
|
);
|
|
}
|
|
}));
|
|
}
|