devtools: Expose introductionType to devtools clients (#38541)

in the devtools protocol, [source
forms](https://firefox-source-docs.mozilla.org/devtools/backend/protocol.html#loading-script-sources)
announced in `resources-available-array` messages can include the
`introductionType`, which more or less mirrors the field of the same
name in SpiderMonkey’s CompileOptions.

this patch exposes `introductionType` accordingly, allowing us to check
for the correct values in automated tests.

Testing: new coverage in devtools tests
Fixes: part of #36027

---------

Signed-off-by: Delan Azabani <dazabani@igalia.com>
Co-authored-by: atbrakhi <atbrakhi@igalia.com>
This commit is contained in:
shuppy 2025-08-08 20:20:30 +08:00 committed by GitHub
parent 23c0947072
commit c9541f2906
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 232 additions and 42 deletions

View file

@ -59,7 +59,9 @@ use crate::fetch::{CspViolationsProcessor, load_whole_resource};
use crate::messaging::{CommonScriptMsg, ScriptEventLoopReceiver, ScriptEventLoopSender};
use crate::realms::{AlreadyInRealm, InRealm, enter_realm};
use crate::script_runtime::ScriptThreadEventCategory::WorkerEvent;
use crate::script_runtime::{CanGc, JSContext as SafeJSContext, Runtime, ThreadSafeJSContext};
use crate::script_runtime::{
CanGc, IntroductionType, JSContext as SafeJSContext, Runtime, ThreadSafeJSContext,
};
use crate::task_queue::{QueuedTask, QueuedTaskConversion, TaskQueue};
use crate::task_source::{SendableTaskSource, TaskSourceName};
@ -517,6 +519,10 @@ impl DedicatedWorkerGlobalScope {
let pipeline_id = global_scope.pipeline_id();
let source_info = SourceInfo {
url: metadata.final_url,
introduction_type: IntroductionType::WORKER
.to_str()
.expect("Guaranteed by definition")
.to_owned(),
external: true, // Worker scripts are always external.
worker_id: Some(global.upcast::<WorkerGlobalScope>().get_worker_id()),
content: Some(source.to_string()),

View file

@ -1095,14 +1095,23 @@ impl HTMLScriptElement {
if let Some(chan) = self.global().devtools_chan() {
let pipeline_id = self.global().pipeline_id();
let (url, content, content_type, is_external) = if script.external {
let (url, content, content_type, introduction_type, is_external) = if script.external {
let content = match &script.code {
SourceCode::Text(text) => text.to_string(),
SourceCode::Compiled(compiled) => compiled.original_text.to_string(),
};
// content_type: https://html.spec.whatwg.org/multipage/#scriptingLanguages
(script.url.clone(), Some(content), "text/javascript", true)
(
script.url.clone(),
Some(content),
"text/javascript",
IntroductionType::SRC_SCRIPT
.to_str()
.expect("Guaranteed by definition")
.to_owned(),
true,
)
} else {
// TODO: if needed, fetch the page again, in the same way as in the original request.
// Fetch it from cache, even if the original request was non-idempotent (e.g. POST).
@ -1110,11 +1119,21 @@ impl HTMLScriptElement {
// fetch, the server could return a different response.
// TODO: handle cases where Content-Type is not text/html.
(doc.url(), None, "text/html", false)
(
doc.url(),
None,
"text/html",
IntroductionType::INLINE_SCRIPT
.to_str()
.expect("Guaranteed by definition")
.to_owned(),
false,
)
};
let source_info = SourceInfo {
url,
introduction_type: introduction_type.to_owned(),
external: is_external,
worker_id: None,
content,

View file

@ -72,7 +72,7 @@ use crate::dom::workernavigator::WorkerNavigator;
use crate::fetch::{CspViolationsProcessor, Fetch, load_whole_resource};
use crate::messaging::{CommonScriptMsg, ScriptEventLoopReceiver, ScriptEventLoopSender};
use crate::realms::{InRealm, enter_realm};
use crate::script_runtime::{CanGc, JSContext, JSContextHelper, Runtime};
use crate::script_runtime::{CanGc, IntroductionType, JSContext, JSContextHelper, Runtime};
use crate::task::TaskCanceller;
use crate::timers::{IsInterval, TimerCallback};
@ -644,12 +644,13 @@ 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
let mut options = self
.runtime
.borrow()
.as_ref()
.unwrap()
.new_compile_options(self.worker_url.borrow().as_str(), 1);
options.set_introduction_type(IntroductionType::WORKER);
match self.runtime.borrow().as_ref().unwrap().evaluate_script(
self.reflector().get_jsobject(),
&source,

View file

@ -1249,7 +1249,21 @@ impl Runnable {
pub(crate) use script_bindings::script_runtime::CanGc;
/// `introductionType` values in SpiderMonkey TransitiveCompileOptions.
///
/// Value definitions are based on the SpiderMonkey Debugger API docs:
/// <https://firefox-source-docs.mozilla.org/js/Debugger/Debugger.Source.html#introductiontype>
// TODO: squish `scriptElement` <https://searchfox.org/mozilla-central/rev/202069c4c5113a1a9052d84fa4679d4c1b22113e/devtools/server/actors/source.js#199-201>
pub(crate) struct IntroductionType;
impl IntroductionType {
pub const INLINE_SCRIPT: &'static CStr = c"inlineScript";
/// `introductionType` for code belonging to `<script src="file.js">` elements.
/// This includes `<script type="module" src="...">`.
pub const SRC_SCRIPT: &CStr = c"srcScript";
/// `introductionType` for code belonging to `<script>code;</script>` elements.
/// This includes `<script type="module" src="...">`.
pub const INLINE_SCRIPT: &CStr = c"inlineScript";
/// `introductionType` for web workers.
/// <https://searchfox.org/mozilla-central/rev/202069c4c5113a1a9052d84fa4679d4c1b22113e/devtools/docs/user/debugger-api/debugger.source/index.rst#96>
pub const WORKER: &CStr = c"Worker";
}