mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
script: Tell SpiderMonkey whether scripts are inline (#38363)
to use the [SpiderMonkey Debugger API](https://firefox-source-docs.mozilla.org/js/Debugger/) as the single source of truth about scripts and their sources for devtools purposes (servo/servo#38334), the debugger script needs to be able to distinguish inline scripts from other scripts, because inline scripts are a special case where the source contents need to come from the Servo parser. the mechanism for this is [Debugger.Script.prototype.**introductionType**](https://firefox-source-docs.mozilla.org/js/Debugger/Debugger.Source.html#introductiontype), which is `inlineScript` for inline scripts or a variety of other values for other kinds of scripts, but only the embedder can provide this information. this patch bumps mozjs to servo/mozjs#603, which expands on CompileOptionsWrapper, making it a safe wrapper around CompileOptions. to construct one from safe code, use Runtime::new_compile_options(). then you can call `set_introduction_type(&'static CStr)` on the new instance. we also make Runtime::evaluate_script() take a CompileOptionsWrapper from the caller, instead of constructing one internally. in this patch, we set the introductionType to `c"inlineScript"` when calling run_a_classic_script() and compile_module_script() for inline scripts, and leave it unset all other cases. Testing: will undergo automated tests in #38334 Fixes: part of #36027, part of servo/servo#38378 --------- Signed-off-by: Delan Azabani <dazabani@igalia.com> Co-authored-by: atbrakhi <atbrakhi@igalia.com>
This commit is contained in:
parent
0bf8676345
commit
3eddfeaee2
8 changed files with 52 additions and 13 deletions
|
@ -65,6 +65,7 @@ pub(crate) fn handle_evaluate_js(
|
|||
ScriptFetchOptions::default_classic_script(global),
|
||||
global.api_base_url(),
|
||||
can_gc,
|
||||
None,
|
||||
);
|
||||
|
||||
if rval.is_undefined() {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
use std::cell::{Cell, OnceCell, Ref};
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::collections::{HashMap, HashSet, VecDeque};
|
||||
use std::ffi::CStr;
|
||||
use std::ops::Index;
|
||||
use std::rc::Rc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
@ -2768,6 +2769,7 @@ impl GlobalScope {
|
|||
fetch_options,
|
||||
script_base_url,
|
||||
can_gc,
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -2783,6 +2785,7 @@ impl GlobalScope {
|
|||
fetch_options: ScriptFetchOptions,
|
||||
script_base_url: ServoUrl,
|
||||
can_gc: CanGc,
|
||||
introduction_type: Option<&'static CStr>,
|
||||
) -> bool {
|
||||
let cx = GlobalScope::get_cx();
|
||||
|
||||
|
@ -2794,7 +2797,10 @@ impl GlobalScope {
|
|||
rooted!(in(*cx) let mut compiled_script = std::ptr::null_mut::<JSScript>());
|
||||
match code {
|
||||
SourceCode::Text(text_code) => {
|
||||
let options = CompileOptionsWrapper::new(*cx, filename, line_number);
|
||||
let mut options = CompileOptionsWrapper::new(*cx, filename, line_number);
|
||||
if let Some(introduction_type) = introduction_type {
|
||||
options.set_introduction_type(introduction_type);
|
||||
}
|
||||
|
||||
debug!("compiling dom string");
|
||||
compiled_script.set(Compile1(
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#![allow(unused_imports)]
|
||||
use core::ffi::c_void;
|
||||
use std::cell::Cell;
|
||||
use std::ffi::CStr;
|
||||
use std::fs::read_to_string;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
@ -80,7 +81,7 @@ use crate::script_module::{
|
|||
ImportMap, ModuleOwner, ScriptFetchOptions, fetch_external_module_script,
|
||||
fetch_inline_module_script, parse_an_import_map_string, register_import_map,
|
||||
};
|
||||
use crate::script_runtime::CanGc;
|
||||
use crate::script_runtime::{CanGc, IntroductionType};
|
||||
use crate::task_source::{SendableTaskSource, TaskSourceName};
|
||||
use crate::unminify::{ScriptSource, unminify_js};
|
||||
|
||||
|
@ -1145,6 +1146,7 @@ impl HTMLScriptElement {
|
|||
// Step 6.
|
||||
let document = self.owner_document();
|
||||
let old_script = document.GetCurrentScript();
|
||||
let introduction_type = (!script.external).then_some(IntroductionType::INLINE_SCRIPT);
|
||||
|
||||
match script.type_ {
|
||||
ScriptType::Classic => {
|
||||
|
@ -1153,7 +1155,7 @@ impl HTMLScriptElement {
|
|||
} else {
|
||||
document.set_current_script(Some(self))
|
||||
}
|
||||
self.run_a_classic_script(&script, can_gc);
|
||||
self.run_a_classic_script(&script, can_gc, introduction_type);
|
||||
document.set_current_script(old_script.as_deref());
|
||||
},
|
||||
ScriptType::Module => {
|
||||
|
@ -1179,7 +1181,12 @@ impl HTMLScriptElement {
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#run-a-classic-script
|
||||
pub(crate) fn run_a_classic_script(&self, script: &ScriptOrigin, can_gc: CanGc) {
|
||||
pub(crate) fn run_a_classic_script(
|
||||
&self,
|
||||
script: &ScriptOrigin,
|
||||
can_gc: CanGc,
|
||||
introduction_type: Option<&'static CStr>,
|
||||
) {
|
||||
// TODO use a settings object rather than this element's document/window
|
||||
// Step 2
|
||||
let document = self.owner_document();
|
||||
|
@ -1205,6 +1212,7 @@ impl HTMLScriptElement {
|
|||
script.fetch_options.clone(),
|
||||
script.url.clone(),
|
||||
can_gc,
|
||||
introduction_type,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ pub(crate) fn load_script(head: &HTMLHeadElement) {
|
|||
ScriptFetchOptions::default_classic_script(global_scope),
|
||||
global_scope.api_base_url(),
|
||||
CanGc::note(),
|
||||
None,
|
||||
);
|
||||
}
|
||||
}));
|
||||
|
|
|
@ -427,12 +427,17 @@ impl WorkerGlobalScopeMethods<crate::DomTypeHolder> for WorkerGlobalScope {
|
|||
Ok((metadata, bytes)) => (metadata.final_url, String::from_utf8(bytes).unwrap()),
|
||||
};
|
||||
|
||||
let options = self
|
||||
.runtime
|
||||
.borrow()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.new_compile_options(url.as_str(), 1);
|
||||
let result = self.runtime.borrow().as_ref().unwrap().evaluate_script(
|
||||
self.reflector().get_jsobject(),
|
||||
&source,
|
||||
url.as_str(),
|
||||
1,
|
||||
rval.handle_mut(),
|
||||
options,
|
||||
);
|
||||
|
||||
maybe_resume_unwind();
|
||||
|
@ -639,12 +644,17 @@ impl WorkerGlobalScope {
|
|||
let _aes = AutoEntryScript::new(self.upcast());
|
||||
let cx = self.runtime.borrow().as_ref().unwrap().cx();
|
||||
rooted!(in(cx) let mut rval = UndefinedValue());
|
||||
let options = self
|
||||
.runtime
|
||||
.borrow()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.new_compile_options(self.worker_url.borrow().as_str(), 1);
|
||||
match self.runtime.borrow().as_ref().unwrap().evaluate_script(
|
||||
self.reflector().get_jsobject(),
|
||||
&source,
|
||||
self.worker_url.borrow().as_str(),
|
||||
1,
|
||||
rval.handle_mut(),
|
||||
options,
|
||||
) {
|
||||
Ok(_) => (),
|
||||
Err(_) => {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
//! related to `type=module` for script thread or worker threads.
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::ffi::CStr;
|
||||
use std::rc::Rc;
|
||||
use std::str::FromStr;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
@ -77,7 +78,7 @@ use crate::dom::window::Window;
|
|||
use crate::dom::worker::TrustedWorkerAddress;
|
||||
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
|
||||
use crate::realms::{AlreadyInRealm, InRealm, enter_realm};
|
||||
use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
|
||||
use crate::script_runtime::{CanGc, IntroductionType, JSContext as SafeJSContext};
|
||||
use crate::task::TaskBox;
|
||||
|
||||
fn gen_type_error(global: &GlobalScope, string: String, can_gc: CanGc) -> RethrowError {
|
||||
|
@ -467,11 +468,15 @@ impl ModuleTree {
|
|||
mut module_script: RustMutableHandleObject,
|
||||
inline: bool,
|
||||
can_gc: CanGc,
|
||||
introduction_type: Option<&'static CStr>,
|
||||
) -> Result<(), RethrowError> {
|
||||
let cx = GlobalScope::get_cx();
|
||||
let _ac = JSAutoRealm::new(*cx, *global.reflector().get_jsobject());
|
||||
|
||||
let compile_options = unsafe { CompileOptionsWrapper::new(*cx, url.as_str(), 1) };
|
||||
let mut compile_options = unsafe { CompileOptionsWrapper::new(*cx, url.as_str(), 1) };
|
||||
if let Some(introduction_type) = introduction_type {
|
||||
compile_options.set_introduction_type(introduction_type);
|
||||
}
|
||||
let mut module_source = ModuleSource {
|
||||
source: module_script_text,
|
||||
unminified_dir: global.unminified_js_dir(),
|
||||
|
@ -1331,6 +1336,7 @@ impl FetchResponseListener for ModuleContext {
|
|||
compiled_module.handle_mut(),
|
||||
false,
|
||||
CanGc::note(),
|
||||
None,
|
||||
);
|
||||
|
||||
match compiled_module_result {
|
||||
|
@ -1895,6 +1901,7 @@ pub(crate) fn fetch_inline_module_script(
|
|||
compiled_module.handle_mut(),
|
||||
true,
|
||||
can_gc,
|
||||
Some(IntroductionType::INLINE_SCRIPT),
|
||||
);
|
||||
|
||||
match compiled_module_result {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
use core::ffi::c_char;
|
||||
use std::cell::Cell;
|
||||
use std::ffi::CString;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::io::{Write, stdout};
|
||||
use std::ops::Deref;
|
||||
use std::os::raw::c_void;
|
||||
|
@ -1194,3 +1194,9 @@ impl Runnable {
|
|||
}
|
||||
|
||||
pub(crate) use script_bindings::script_runtime::CanGc;
|
||||
|
||||
/// `introductionType` values in SpiderMonkey TransitiveCompileOptions.
|
||||
pub(crate) struct IntroductionType;
|
||||
impl IntroductionType {
|
||||
pub const INLINE_SCRIPT: &'static CStr = c"inlineScript";
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue