/* 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/. */

//! The script module mod contains common traits and structs
//! 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};
use std::{mem, ptr};

use encoding_rs::UTF_8;
use headers::{HeaderMapExt, ReferrerPolicy as ReferrerPolicyHeader};
use html5ever::local_name;
use hyper_serde::Serde;
use indexmap::{IndexMap, IndexSet};
use js::conversions::jsstr_to_string;
use js::jsapi::{
    CompileModule1, ExceptionStackBehavior, FinishDynamicModuleImport, GetModuleRequestSpecifier,
    GetModuleResolveHook, GetRequestedModuleSpecifier, GetRequestedModulesCount,
    Handle as RawHandle, HandleObject, HandleValue as RawHandleValue, Heap,
    JS_ClearPendingException, JS_DefineProperty4, JS_IsExceptionPending, JS_NewStringCopyN,
    JSAutoRealm, JSContext, JSObject, JSPROP_ENUMERATE, JSRuntime, ModuleErrorBehaviour,
    ModuleEvaluate, ModuleLink, MutableHandleValue, SetModuleDynamicImportHook,
    SetModuleMetadataHook, SetModulePrivate, SetModuleResolveHook, SetScriptPrivateReferenceHooks,
    ThrowOnModuleEvaluationFailure, Value,
};
use js::jsval::{JSVal, PrivateValue, UndefinedValue};
use js::rust::wrappers::{JS_GetModulePrivate, JS_GetPendingException, JS_SetPendingException};
use js::rust::{
    CompileOptionsWrapper, Handle, HandleObject as RustHandleObject, HandleValue, IntoHandle,
    MutableHandleObject as RustMutableHandleObject, transform_str_to_source_text,
};
use mime::Mime;
use net_traits::http_status::HttpStatus;
use net_traits::request::{
    CredentialsMode, Destination, ParserMetadata, Referrer, RequestBuilder, RequestId, RequestMode,
};
use net_traits::{
    FetchMetadata, FetchResponseListener, Metadata, NetworkError, ReferrerPolicy,
    ResourceFetchTiming, ResourceTimingType,
};
use script_bindings::error::Fallible;
use serde_json::{Map as JsonMap, Value as JsonValue};
use servo_url::ServoUrl;
use uuid::Uuid;

use crate::document_loader::LoadType;
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::WindowBinding::Window_Binding::WindowMethods;
use crate::dom::bindings::error::{
    Error, ErrorToJsval, report_pending_exception, throw_dom_exception,
};
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::{DomGlobal, DomObject};
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::settings_stack::AutoIncumbentScript;
use crate::dom::bindings::str::DOMString;
use crate::dom::bindings::trace::RootedTraceableBox;
use crate::dom::csp::{GlobalCspReporting, Violation};
use crate::dom::document::Document;
use crate::dom::dynamicmoduleowner::{DynamicModuleId, DynamicModuleOwner};
use crate::dom::element::Element;
use crate::dom::globalscope::GlobalScope;
use crate::dom::html::htmlscriptelement::{
    HTMLScriptElement, SCRIPT_JS_MIMES, ScriptId, ScriptOrigin, ScriptType,
};
use crate::dom::node::NodeTraits;
use crate::dom::performanceresourcetiming::InitiatorType;
use crate::dom::promise::Promise;
use crate::dom::promisenativehandler::{Callback, PromiseNativeHandler};
use crate::dom::types::Console;
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, IntroductionType, JSContext as SafeJSContext};
use crate::task::TaskBox;

fn gen_type_error(global: &GlobalScope, string: String, can_gc: CanGc) -> RethrowError {
    rooted!(in(*GlobalScope::get_cx()) let mut thrown = UndefinedValue());
    Error::Type(string).to_jsval(GlobalScope::get_cx(), global, thrown.handle_mut(), can_gc);

    RethrowError(RootedTraceableBox::from_box(Heap::boxed(thrown.get())))
}

#[derive(JSTraceable)]
pub(crate) struct ModuleObject(RootedTraceableBox<Heap<*mut JSObject>>);

impl ModuleObject {
    fn new(obj: RustHandleObject) -> ModuleObject {
        ModuleObject(RootedTraceableBox::from_box(Heap::boxed(obj.get())))
    }

    pub(crate) fn handle(&self) -> HandleObject {
        self.0.handle().into()
    }
}

#[derive(JSTraceable)]
pub(crate) struct RethrowError(RootedTraceableBox<Heap<JSVal>>);

impl RethrowError {
    fn handle(&self) -> Handle<'_, JSVal> {
        self.0.handle()
    }
}

impl Clone for RethrowError {
    fn clone(&self) -> Self {
        Self(RootedTraceableBox::from_box(Heap::boxed(self.0.get())))
    }
}

pub(crate) struct ModuleScript {
    base_url: ServoUrl,
    options: ScriptFetchOptions,
    owner: Option<ModuleOwner>,
}

impl ModuleScript {
    pub(crate) fn new(
        base_url: ServoUrl,
        options: ScriptFetchOptions,
        owner: Option<ModuleOwner>,
    ) -> Self {
        ModuleScript {
            base_url,
            options,
            owner,
        }
    }
}

/// Identity for a module which will be
/// used to retrieve the module when we'd
/// like to get it from module map.
///
/// For example, we will save module parents with
/// module identity so that we can get module tree
/// from a descendant no matter the parent is an
/// inline script or a external script
#[derive(Clone, Debug, Eq, Hash, JSTraceable, PartialEq)]
pub(crate) enum ModuleIdentity {
    ScriptId(ScriptId),
    ModuleUrl(#[no_trace] ServoUrl),
}

impl ModuleIdentity {
    pub(crate) fn get_module_tree(&self, global: &GlobalScope) -> Rc<ModuleTree> {
        match self {
            ModuleIdentity::ModuleUrl(url) => {
                let module_map = global.get_module_map().borrow();
                module_map.get(&url.clone()).unwrap().clone()
            },
            ModuleIdentity::ScriptId(script_id) => {
                let inline_module_map = global.get_inline_module_map().borrow();
                inline_module_map.get(script_id).unwrap().clone()
            },
        }
    }
}

#[derive(JSTraceable)]
pub(crate) struct ModuleTree {
    #[no_trace]
    url: ServoUrl,
    text: DomRefCell<Rc<DOMString>>,
    record: DomRefCell<Option<ModuleObject>>,
    status: DomRefCell<ModuleStatus>,
    // The spec maintains load order for descendants, so we use an indexset for descendants and
    // parents. This isn't actually necessary for parents however the IndexSet APIs don't
    // interop with HashSet, and IndexSet isn't very expensive
    // (https://github.com/bluss/indexmap/issues/110)
    //
    // By default all maps in web specs are ordered maps
    // (https://infra.spec.whatwg.org/#ordered-map), however we can usually get away with using
    // stdlib maps and sets because we rarely iterate over them.
    #[custom_trace]
    parent_identities: DomRefCell<IndexSet<ModuleIdentity>>,
    #[no_trace]
    descendant_urls: DomRefCell<IndexSet<ServoUrl>>,
    // A set to memoize which descendants are under fetching
    #[no_trace]
    incomplete_fetch_urls: DomRefCell<IndexSet<ServoUrl>>,
    #[no_trace]
    visited_urls: DomRefCell<HashSet<ServoUrl>>,
    rethrow_error: DomRefCell<Option<RethrowError>>,
    #[no_trace]
    network_error: DomRefCell<Option<NetworkError>>,
    // A promise for owners to execute when the module tree
    // is finished
    promise: DomRefCell<Option<Rc<Promise>>>,
    external: bool,
}

impl ModuleTree {
    pub(crate) fn new(url: ServoUrl, external: bool, visited_urls: HashSet<ServoUrl>) -> Self {
        ModuleTree {
            url,
            text: DomRefCell::new(Rc::new(DOMString::new())),
            record: DomRefCell::new(None),
            status: DomRefCell::new(ModuleStatus::Initial),
            parent_identities: DomRefCell::new(IndexSet::new()),
            descendant_urls: DomRefCell::new(IndexSet::new()),
            incomplete_fetch_urls: DomRefCell::new(IndexSet::new()),
            visited_urls: DomRefCell::new(visited_urls),
            rethrow_error: DomRefCell::new(None),
            network_error: DomRefCell::new(None),
            promise: DomRefCell::new(None),
            external,
        }
    }

    pub(crate) fn get_status(&self) -> ModuleStatus {
        *self.status.borrow()
    }

    pub(crate) fn set_status(&self, status: ModuleStatus) {
        *self.status.borrow_mut() = status;
    }

    pub(crate) fn get_record(&self) -> &DomRefCell<Option<ModuleObject>> {
        &self.record
    }

    pub(crate) fn set_record(&self, record: ModuleObject) {
        *self.record.borrow_mut() = Some(record);
    }

    pub(crate) fn get_rethrow_error(&self) -> &DomRefCell<Option<RethrowError>> {
        &self.rethrow_error
    }

    pub(crate) fn set_rethrow_error(&self, rethrow_error: RethrowError) {
        *self.rethrow_error.borrow_mut() = Some(rethrow_error);
    }

    pub(crate) fn get_network_error(&self) -> &DomRefCell<Option<NetworkError>> {
        &self.network_error
    }

    pub(crate) fn set_network_error(&self, network_error: NetworkError) {
        *self.network_error.borrow_mut() = Some(network_error);
    }

    pub(crate) fn get_text(&self) -> &DomRefCell<Rc<DOMString>> {
        &self.text
    }

    pub(crate) fn set_text(&self, module_text: Rc<DOMString>) {
        *self.text.borrow_mut() = module_text;
    }

    pub(crate) fn get_incomplete_fetch_urls(&self) -> &DomRefCell<IndexSet<ServoUrl>> {
        &self.incomplete_fetch_urls
    }

    pub(crate) fn get_descendant_urls(&self) -> &DomRefCell<IndexSet<ServoUrl>> {
        &self.descendant_urls
    }

    pub(crate) fn get_parent_urls(&self) -> IndexSet<ServoUrl> {
        let parent_identities = self.parent_identities.borrow();

        parent_identities
            .iter()
            .filter_map(|parent_identity| match parent_identity {
                ModuleIdentity::ScriptId(_) => None,
                ModuleIdentity::ModuleUrl(url) => Some(url.clone()),
            })
            .collect()
    }

    pub(crate) fn insert_parent_identity(&self, parent_identity: ModuleIdentity) {
        self.parent_identities.borrow_mut().insert(parent_identity);
    }

    pub(crate) fn insert_incomplete_fetch_url(&self, dependency: &ServoUrl) {
        self.incomplete_fetch_urls
            .borrow_mut()
            .insert(dependency.clone());
    }

    pub(crate) fn remove_incomplete_fetch_url(&self, dependency: &ServoUrl) {
        self.incomplete_fetch_urls
            .borrow_mut()
            .shift_remove(dependency);
    }

    /// recursively checks if all of the transitive descendants are
    /// in the FetchingDescendants or later status
    fn recursive_check_descendants(
        module_tree: &ModuleTree,
        module_map: &HashMap<ServoUrl, Rc<ModuleTree>>,
        discovered_urls: &mut HashSet<ServoUrl>,
    ) -> bool {
        discovered_urls.insert(module_tree.url.clone());

        let descendant_urls = module_tree.descendant_urls.borrow();

        for descendant_url in descendant_urls.iter() {
            match module_map.get(&descendant_url.clone()) {
                None => return false,
                Some(descendant_module) => {
                    if discovered_urls.contains(&descendant_module.url) {
                        continue;
                    }

                    let descendant_status = descendant_module.get_status();
                    if descendant_status < ModuleStatus::FetchingDescendants {
                        return false;
                    }

                    let all_ready_descendants = ModuleTree::recursive_check_descendants(
                        descendant_module,
                        module_map,
                        discovered_urls,
                    );

                    if !all_ready_descendants {
                        return false;
                    }
                },
            }
        }

        true
    }

    fn has_all_ready_descendants(&self, global: &GlobalScope) -> bool {
        let module_map = global.get_module_map().borrow();
        let mut discovered_urls = HashSet::new();

        ModuleTree::recursive_check_descendants(self, &module_map.0, &mut discovered_urls)
    }

    // We just leverage the power of Promise to run the task for `finish` the owner.
    // Thus, we will always `resolve` it and no need to register a callback for `reject`
    fn append_handler(
        &self,
        owner: ModuleOwner,
        module_identity: ModuleIdentity,
        fetch_options: ScriptFetchOptions,
        can_gc: CanGc,
    ) {
        let this = owner.clone();
        let identity = module_identity.clone();
        let options = fetch_options.clone();

        let handler = PromiseNativeHandler::new(
            &owner.global(),
            Some(ModuleHandler::new_boxed(Box::new(
                task!(fetched_resolve: move || {
                    this.notify_owner_to_finish(identity, options, CanGc::note());
                }),
            ))),
            None,
            can_gc,
        );

        let realm = enter_realm(&*owner.global());
        let comp = InRealm::Entered(&realm);
        let _ais = AutoIncumbentScript::new(&owner.global());

        if let Some(promise) = self.promise.borrow().as_ref() {
            promise.append_native_handler(&handler, comp, can_gc);
            return;
        }

        let new_promise = Promise::new_in_current_realm(comp, can_gc);
        new_promise.append_native_handler(&handler, comp, can_gc);
        *self.promise.borrow_mut() = Some(new_promise);
    }

    fn append_dynamic_module_handler(
        &self,
        owner: ModuleOwner,
        module_identity: ModuleIdentity,
        dynamic_module: RootedTraceableBox<DynamicModule>,
        can_gc: CanGc,
    ) {
        let this = owner.clone();
        let identity = module_identity.clone();

        let module_id = owner.global().dynamic_module_list().push(dynamic_module);

        let handler = PromiseNativeHandler::new(
            &owner.global(),
            Some(ModuleHandler::new_boxed(Box::new(
                task!(fetched_resolve: move || {
                    this.finish_dynamic_module(identity, module_id, CanGc::note());
                }),
            ))),
            None,
            can_gc,
        );

        let realm = enter_realm(&*owner.global());
        let comp = InRealm::Entered(&realm);
        let _ais = AutoIncumbentScript::new(&owner.global());

        if let Some(promise) = self.promise.borrow().as_ref() {
            promise.append_native_handler(&handler, comp, can_gc);
            return;
        }

        let new_promise = Promise::new_in_current_realm(comp, can_gc);
        new_promise.append_native_handler(&handler, comp, can_gc);
        *self.promise.borrow_mut() = Some(new_promise);
    }
}

#[derive(Clone, Copy, Debug, JSTraceable, PartialEq, PartialOrd)]
pub(crate) enum ModuleStatus {
    Initial,
    Fetching,
    FetchingDescendants,
    Finished,
}

struct ModuleSource {
    source: Rc<DOMString>,
    unminified_dir: Option<String>,
    external: bool,
    url: ServoUrl,
}

impl crate::unminify::ScriptSource for ModuleSource {
    fn unminified_dir(&self) -> Option<String> {
        self.unminified_dir.clone()
    }

    fn extract_bytes(&self) -> &[u8] {
        self.source.as_bytes()
    }

    fn rewrite_source(&mut self, source: Rc<DOMString>) {
        self.source = source;
    }

    fn url(&self) -> ServoUrl {
        self.url.clone()
    }

    fn is_external(&self) -> bool {
        self.external
    }
}

impl ModuleTree {
    #[allow(unsafe_code, clippy::too_many_arguments)]
    /// <https://html.spec.whatwg.org/multipage/#creating-a-module-script>
    /// Step 7-11.
    /// Although the CanGc argument appears unused, it represents the GC operations that
    /// can occur as part of compiling a script.
    fn compile_module_script(
        &self,
        global: &GlobalScope,
        owner: ModuleOwner,
        module_script_text: Rc<DOMString>,
        url: &ServoUrl,
        options: ScriptFetchOptions,
        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 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(),
            external: !inline,
            url: url.clone(),
        };
        crate::unminify::unminify_js(&mut module_source);

        unsafe {
            module_script.set(CompileModule1(
                *cx,
                compile_options.ptr,
                &mut transform_str_to_source_text(&module_source.source),
            ));

            if module_script.is_null() {
                warn!("fail to compile module script of {}", url);

                rooted!(in(*cx) let mut exception = UndefinedValue());
                assert!(JS_GetPendingException(*cx, exception.handle_mut()));
                JS_ClearPendingException(*cx);

                return Err(RethrowError(RootedTraceableBox::from_box(Heap::boxed(
                    exception.get(),
                ))));
            }

            let module_script_data = Rc::new(ModuleScript::new(url.clone(), options, Some(owner)));

            SetModulePrivate(
                module_script.get(),
                &PrivateValue(Rc::into_raw(module_script_data) as *const _),
            );

            debug!("module script of {} compile done", url);

            self.resolve_requested_module_specifiers(
                global,
                module_script.handle().into_handle(),
                can_gc,
            )
            .map(|_| ())
        }
    }

    #[allow(unsafe_code)]
    /// <https://html.spec.whatwg.org/multipage/#fetch-the-descendants-of-and-link-a-module-script>
    /// Step 5-2.
    pub(crate) fn instantiate_module_tree(
        &self,
        global: &GlobalScope,
        module_record: HandleObject,
    ) -> Result<(), RethrowError> {
        let cx = GlobalScope::get_cx();
        let _ac = JSAutoRealm::new(*cx, *global.reflector().get_jsobject());

        unsafe {
            if !ModuleLink(*cx, module_record) {
                warn!("fail to link & instantiate module");

                rooted!(in(*cx) let mut exception = UndefinedValue());
                assert!(JS_GetPendingException(*cx, exception.handle_mut()));
                JS_ClearPendingException(*cx);

                Err(RethrowError(RootedTraceableBox::from_box(Heap::boxed(
                    exception.get(),
                ))))
            } else {
                debug!("module instantiated successfully");

                Ok(())
            }
        }
    }

    /// Execute the provided module, storing the evaluation return value in the provided
    /// mutable handle. Although the CanGc appears unused, it represents the GC operations
    /// possible when evluating arbitrary JS.
    #[allow(unsafe_code)]
    pub(crate) fn execute_module(
        &self,
        global: &GlobalScope,
        module_record: HandleObject,
        eval_result: MutableHandleValue,
        _can_gc: CanGc,
    ) -> Result<(), RethrowError> {
        let cx = GlobalScope::get_cx();
        let _ac = JSAutoRealm::new(*cx, *global.reflector().get_jsobject());

        unsafe {
            let ok = ModuleEvaluate(*cx, module_record, eval_result);
            assert!(ok, "module evaluation failed");

            rooted!(in(*cx) let mut evaluation_promise = ptr::null_mut::<JSObject>());
            if eval_result.is_object() {
                evaluation_promise.set(eval_result.to_object());
            }

            let throw_result = ThrowOnModuleEvaluationFailure(
                *cx,
                evaluation_promise.handle().into(),
                ModuleErrorBehaviour::ThrowModuleErrorsSync,
            );
            if !throw_result {
                warn!("fail to evaluate module");

                rooted!(in(*cx) let mut exception = UndefinedValue());
                assert!(JS_GetPendingException(*cx, exception.handle_mut()));
                JS_ClearPendingException(*cx);

                Err(RethrowError(RootedTraceableBox::from_box(Heap::boxed(
                    exception.get(),
                ))))
            } else {
                debug!("module evaluated successfully");
                Ok(())
            }
        }
    }

    #[allow(unsafe_code)]
    pub(crate) fn report_error(&self, global: &GlobalScope, can_gc: CanGc) {
        let module_error = self.rethrow_error.borrow();

        if let Some(exception) = &*module_error {
            let ar = enter_realm(global);
            unsafe {
                JS_SetPendingException(
                    *GlobalScope::get_cx(),
                    exception.handle(),
                    ExceptionStackBehavior::Capture,
                );
            }
            report_pending_exception(GlobalScope::get_cx(), true, InRealm::Entered(&ar), can_gc);
        }
    }

    #[allow(unsafe_code)]
    fn resolve_requested_module_specifiers(
        &self,
        global: &GlobalScope,
        module_object: HandleObject,
        can_gc: CanGc,
    ) -> Result<IndexSet<ServoUrl>, RethrowError> {
        let cx = GlobalScope::get_cx();
        let _ac = JSAutoRealm::new(*cx, *global.reflector().get_jsobject());

        let mut specifier_urls = IndexSet::new();

        unsafe {
            let length = GetRequestedModulesCount(*cx, module_object);

            for index in 0..length {
                let jsstr =
                    std::ptr::NonNull::new(GetRequestedModuleSpecifier(*cx, module_object, index))
                        .unwrap();
                let specifier = DOMString::from_string(jsstr_to_string(*cx, jsstr));

                rooted!(in(*cx) let mut private = UndefinedValue());
                JS_GetModulePrivate(module_object.get(), private.handle_mut());
                let private = private.handle().into_handle();
                let script = module_script_from_reference_private(&private);
                let url = ModuleTree::resolve_module_specifier(global, script, specifier, can_gc);

                if url.is_err() {
                    let specifier_error =
                        gen_type_error(global, "Wrong module specifier".to_owned(), can_gc);

                    return Err(specifier_error);
                }

                specifier_urls.insert(url.unwrap());
            }
        }

        Ok(specifier_urls)
    }

    /// <https://html.spec.whatwg.org/multipage/#resolve-a-module-specifier>
    #[allow(unsafe_code)]
    fn resolve_module_specifier(
        global: &GlobalScope,
        script: Option<&ModuleScript>,
        specifier: DOMString,
        can_gc: CanGc,
    ) -> Fallible<ServoUrl> {
        // Step 1~3 to get settingsObject and baseURL
        let script_global = script.and_then(|s| s.owner.as_ref().map(|o| o.global()));
        // Step 1. Let settingsObject and baseURL be null.
        let (global, base_url): (&GlobalScope, &ServoUrl) = match script {
            // Step 2. If referringScript is not null, then:
            // Set settingsObject to referringScript's settings object.
            // Set baseURL to referringScript's base URL.
            Some(s) => (script_global.as_ref().map_or(global, |g| g), &s.base_url),
            // Step 3. Otherwise:
            // Set settingsObject to the current settings object.
            // Set baseURL to settingsObject's API base URL.
            // FIXME(#37553): Is this the correct current settings object?
            None => (global, &global.api_base_url()),
        };

        // Step 4. Let importMap be an empty import map.
        // Step 5. If settingsObject's global object implements Window, then set importMap to settingsObject's
        // global object's import map.
        let import_map = if global.is::<Window>() {
            Some(global.import_map())
        } else {
            None
        };

        // Step 6. Let serializedBaseURL be baseURL, serialized.
        let serialized_base_url = base_url.as_str();
        // Step 7. Let asURL be the result of resolving a URL-like module specifier given specifier and baseURL.
        let as_url = Self::resolve_url_like_module_specifier(&specifier, base_url);
        // Step 8. Let normalizedSpecifier be the serialization of asURL, if asURL is non-null;
        // otherwise, specifier.
        let normalized_specifier = match &as_url {
            Some(url) => url.as_str(),
            None => &specifier,
        };

        // Step 9. Let result be a URL-or-null, initially null.
        let mut result = None;
        if let Some(map) = import_map {
            // Step 10. For each scopePrefix → scopeImports of importMap's scopes:
            for (prefix, imports) in &map.scopes {
                // Step 10.1 If scopePrefix is serializedBaseURL, or if scopePrefix ends with U+002F (/)
                // and scopePrefix is a code unit prefix of serializedBaseURL, then:
                let prefix = prefix.as_str();
                if prefix == serialized_base_url ||
                    (serialized_base_url.starts_with(prefix) && prefix.ends_with('\u{002f}'))
                {
                    // Step 10.1.1 Let scopeImportsMatch be the result of resolving an imports match
                    // given normalizedSpecifier, asURL, and scopeImports.
                    // Step 10.1.2 If scopeImportsMatch is not null, then set result to scopeImportsMatch,
                    // and break.
                    result = resolve_imports_match(
                        normalized_specifier,
                        as_url.as_ref(),
                        imports,
                        can_gc,
                    )?;
                    break;
                }
            }

            // Step 11. If result is null, set result to the result of resolving an imports match given
            // normalizedSpecifier, asURL, and importMap's imports.
            if result.is_none() {
                result = resolve_imports_match(
                    normalized_specifier,
                    as_url.as_ref(),
                    &map.imports,
                    can_gc,
                )?;
            }
        }

        // Step 12. If result is null, set it to asURL.
        if result.is_none() {
            result = as_url.clone();
        }

        // Step 13. If result is not null, then:
        match result {
            Some(result) => {
                // Step 13.1 Add module to resolved module set given settingsObject, serializedBaseURL,
                // normalizedSpecifier, and asURL.
                global.add_module_to_resolved_module_set(
                    serialized_base_url,
                    normalized_specifier,
                    as_url.clone(),
                );
                // Step 13.2 Return result.
                Ok(result)
            },
            // Step 14. Throw a TypeError indicating that specifier was a bare specifier,
            // but was not remapped to anything by importMap.
            None => Err(Error::Type(
                "Specifier was a bare specifier, but was not remapped to anything by importMap."
                    .to_owned(),
            )),
        }
    }

    /// <https://html.spec.whatwg.org/multipage/#resolving-a-url-like-module-specifier>
    fn resolve_url_like_module_specifier(
        specifier: &DOMString,
        base_url: &ServoUrl,
    ) -> Option<ServoUrl> {
        // Step 1. If specifier starts with "/", "./", or "../", then:
        if specifier.starts_with('/') || specifier.starts_with("./") || specifier.starts_with("../")
        {
            // Step 1.1. Let url be the result of URL parsing specifier with baseURL.
            return ServoUrl::parse_with_base(Some(base_url), specifier).ok();
        }
        // Step 2. Let url be the result of URL parsing specifier (with no base URL).
        ServoUrl::parse(specifier).ok()
    }

    /// <https://html.spec.whatwg.org/multipage/#finding-the-first-parse-error>
    fn find_first_parse_error(
        &self,
        global: &GlobalScope,
        discovered_urls: &mut HashSet<ServoUrl>,
    ) -> (Option<NetworkError>, Option<RethrowError>) {
        // 3.
        discovered_urls.insert(self.url.clone());

        // 4.
        let record = self.get_record().borrow();
        if record.is_none() {
            return (
                self.network_error.borrow().clone(),
                self.rethrow_error.borrow().clone(),
            );
        }

        let module_map = global.get_module_map().borrow();
        let mut parse_error: Option<RethrowError> = None;

        // 5-6.
        let descendant_urls = self.descendant_urls.borrow();
        for descendant_module in descendant_urls
            .iter()
            // 7.
            .filter_map(|url| module_map.get(&url.clone()))
        {
            // 8-2.
            if discovered_urls.contains(&descendant_module.url) {
                continue;
            }

            // 8-3.
            let (child_network_error, child_parse_error) =
                descendant_module.find_first_parse_error(global, discovered_urls);

            // Due to network error's priority higher than parse error,
            // we will return directly when we meet a network error.
            if child_network_error.is_some() {
                return (child_network_error, None);
            }

            // 8-4.
            //
            // In case of having any network error in other descendants,
            // we will store the "first" parse error and keep running this
            // loop to ensure we don't have any network error.
            if child_parse_error.is_some() && parse_error.is_none() {
                parse_error = child_parse_error;
            }
        }

        // Step 9.
        (None, parse_error)
    }

    #[allow(unsafe_code)]
    // FIXME: spec links in this function are all broken, so it’s unclear what this algorithm does
    /// <https://html.spec.whatwg.org/multipage/#fetch-the-descendants-of-a-module-script>
    fn fetch_module_descendants(
        &self,
        owner: &ModuleOwner,
        destination: Destination,
        options: &ScriptFetchOptions,
        parent_identity: ModuleIdentity,
        can_gc: CanGc,
    ) {
        debug!("Start to load dependencies of {}", self.url);

        let global = owner.global();

        self.set_status(ModuleStatus::FetchingDescendants);

        let specifier_urls = {
            let raw_record = self.record.borrow();
            match raw_record.as_ref() {
                // Step 1.
                None => {
                    self.set_status(ModuleStatus::Finished);
                    debug!(
                        "Module {} doesn't have module record but tried to load descendants.",
                        self.url
                    );
                    return;
                },
                // Step 5.
                Some(raw_record) => {
                    self.resolve_requested_module_specifiers(&global, raw_record.handle(), can_gc)
                },
            }
        };

        match specifier_urls {
            // Step 3.
            Ok(valid_specifier_urls) if valid_specifier_urls.is_empty() => {
                debug!("Module {} doesn't have any dependencies.", self.url);
                self.advance_finished_and_link(&global, can_gc);
            },
            Ok(valid_specifier_urls) => {
                self.descendant_urls
                    .borrow_mut()
                    .extend(valid_specifier_urls.clone());

                let urls_to_fetch = {
                    let mut urls = IndexSet::new();
                    let mut visited_urls = self.visited_urls.borrow_mut();

                    for parsed_url in &valid_specifier_urls {
                        // Step 5-3.
                        if !visited_urls.contains(parsed_url) {
                            // Step 5-3-1.
                            urls.insert(parsed_url.clone());
                            // Step 5-3-2.
                            visited_urls.insert(parsed_url.clone());

                            self.insert_incomplete_fetch_url(parsed_url);
                        }
                    }
                    urls
                };

                // Step 3.
                if urls_to_fetch.is_empty() {
                    debug!(
                        "After checking with visited urls, module {} doesn't have dependencies to load.",
                        &self.url
                    );
                    self.advance_finished_and_link(&global, can_gc);
                    return;
                }

                // Step 8.

                let visited_urls = self.visited_urls.borrow().clone();
                let options = options.descendant_fetch_options();

                for url in urls_to_fetch {
                    // https://html.spec.whatwg.org/multipage/#internal-module-script-graph-fetching-procedure
                    // Step 1.
                    assert!(self.visited_urls.borrow().contains(&url));

                    // Step 2.
                    fetch_single_module_script(
                        owner.clone(),
                        url,
                        visited_urls.clone(),
                        destination,
                        options.clone(),
                        Some(parent_identity.clone()),
                        false,
                        None,
                        // TODO: is this correct?
                        Some(IntroductionType::IMPORTED_MODULE),
                        can_gc,
                    );
                }
            },
            Err(error) => {
                self.set_rethrow_error(error);
                self.advance_finished_and_link(&global, can_gc);
            },
        }
    }

    /// <https://html.spec.whatwg.org/multipage/#fetch-the-descendants-of-and-link-a-module-script>
    /// step 4-7.
    fn advance_finished_and_link(&self, global: &GlobalScope, can_gc: CanGc) {
        {
            if !self.has_all_ready_descendants(global) {
                return;
            }
        }

        self.set_status(ModuleStatus::Finished);

        debug!("Going to advance and finish for: {}", self.url);

        {
            // Notify parents of this module to finish
            //
            // Before notifying, if the parent module has already had zero incomplete
            // fetches, then it means we don't need to notify it.
            let parent_identities = self.parent_identities.borrow();
            for parent_identity in parent_identities.iter() {
                let parent_tree = parent_identity.get_module_tree(global);

                let incomplete_count_before_remove = {
                    let incomplete_urls = parent_tree.get_incomplete_fetch_urls().borrow();
                    incomplete_urls.len()
                };

                if incomplete_count_before_remove > 0 {
                    parent_tree.remove_incomplete_fetch_url(&self.url);
                    parent_tree.advance_finished_and_link(global, can_gc);
                }
            }
        }

        let mut discovered_urls: HashSet<ServoUrl> = HashSet::new();
        let (network_error, rethrow_error) =
            self.find_first_parse_error(global, &mut discovered_urls);

        match (network_error, rethrow_error) {
            (Some(network_error), _) => {
                self.set_network_error(network_error);
            },
            (None, None) => {
                let module_record = self.get_record().borrow();
                if let Some(record) = &*module_record {
                    let instantiated = self.instantiate_module_tree(global, record.handle());

                    if let Err(exception) = instantiated {
                        self.set_rethrow_error(exception);
                    }
                }
            },
            (None, Some(error)) => {
                self.set_rethrow_error(error);
            },
        }

        let promise = self.promise.borrow();
        if let Some(promise) = promise.as_ref() {
            promise.resolve_native(&(), can_gc);
        }
    }
}

#[derive(JSTraceable, MallocSizeOf)]
struct ModuleHandler {
    #[ignore_malloc_size_of = "Measuring trait objects is hard"]
    task: DomRefCell<Option<Box<dyn TaskBox>>>,
}

impl ModuleHandler {
    pub(crate) fn new_boxed(task: Box<dyn TaskBox>) -> Box<dyn Callback> {
        Box::new(Self {
            task: DomRefCell::new(Some(task)),
        })
    }
}

impl Callback for ModuleHandler {
    fn callback(&self, _cx: SafeJSContext, _v: HandleValue, _realm: InRealm, _can_gc: CanGc) {
        let task = self.task.borrow_mut().take().unwrap();
        task.run_box();
    }
}

/// The owner of the module
/// It can be `worker` or `script` element
#[derive(Clone)]
pub(crate) enum ModuleOwner {
    #[allow(dead_code)]
    Worker(TrustedWorkerAddress),
    Window(Trusted<HTMLScriptElement>),
    DynamicModule(Trusted<DynamicModuleOwner>),
}

impl ModuleOwner {
    pub(crate) fn global(&self) -> DomRoot<GlobalScope> {
        match &self {
            ModuleOwner::Worker(worker) => (*worker.root().clone()).global(),
            ModuleOwner::Window(script) => (*script.root()).global(),
            ModuleOwner::DynamicModule(dynamic_module) => (*dynamic_module.root()).global(),
        }
    }

    pub(crate) fn notify_owner_to_finish(
        &self,
        module_identity: ModuleIdentity,
        fetch_options: ScriptFetchOptions,
        can_gc: CanGc,
    ) {
        match &self {
            ModuleOwner::Worker(_) => unimplemented!(),
            ModuleOwner::DynamicModule(_) => unimplemented!(),
            ModuleOwner::Window(script) => {
                let global = self.global();

                let document = script.root().owner_document();
                let load = {
                    let module_tree = module_identity.get_module_tree(&global);

                    let network_error = module_tree.get_network_error().borrow();
                    match network_error.as_ref() {
                        Some(network_error) => Err(network_error.clone().into()),
                        None => match module_identity {
                            ModuleIdentity::ModuleUrl(script_src) => Ok(ScriptOrigin::external(
                                Rc::clone(&module_tree.get_text().borrow()),
                                script_src.clone(),
                                fetch_options,
                                ScriptType::Module,
                                global.unminified_js_dir(),
                            )),
                            ModuleIdentity::ScriptId(_) => Ok(ScriptOrigin::internal(
                                Rc::clone(&module_tree.get_text().borrow()),
                                document.base_url().clone(),
                                fetch_options,
                                ScriptType::Module,
                                global.unminified_js_dir(),
                                Err(Error::NotFound),
                            )),
                        },
                    }
                };

                let asynch = script
                    .root()
                    .upcast::<Element>()
                    .has_attribute(&local_name!("async"));

                if !asynch && (*script.root()).get_parser_inserted() {
                    document.deferred_script_loaded(&script.root(), load, can_gc);
                } else if !asynch && !(*script.root()).get_non_blocking() {
                    document.asap_in_order_script_loaded(&script.root(), load, can_gc);
                } else {
                    document.asap_script_loaded(&script.root(), load, can_gc);
                };
            },
        }
    }

    #[allow(unsafe_code)]
    /// <https://html.spec.whatwg.org/multipage/#hostimportmoduledynamically(referencingscriptormodule,-specifier,-promisecapability):fetch-an-import()-module-script-graph>
    /// Step 6-9
    fn finish_dynamic_module(
        &self,
        module_identity: ModuleIdentity,
        dynamic_module_id: DynamicModuleId,
        can_gc: CanGc,
    ) {
        let global = self.global();

        let module = global.dynamic_module_list().remove(dynamic_module_id);

        let cx = GlobalScope::get_cx();
        let module_tree = module_identity.get_module_tree(&global);

        // In the timing of executing this `finish_dynamic_module` function,
        // we've run `find_first_parse_error` which means we've had the highest
        // priority error in the tree. So, we can just get both `network_error` and
        // `rethrow_error` directly here.
        let network_error = module_tree.get_network_error().borrow().as_ref().cloned();
        let existing_rethrow_error = module_tree.get_rethrow_error().borrow().as_ref().cloned();

        rooted!(in(*cx) let mut rval = UndefinedValue());
        if network_error.is_none() && existing_rethrow_error.is_none() {
            let record = module_tree
                .get_record()
                .borrow()
                .as_ref()
                .map(|record| record.handle());

            if let Some(record) = record {
                let evaluated = module_tree
                    .execute_module(&global, record, rval.handle_mut().into(), can_gc)
                    .err();

                if let Some(exception) = evaluated.clone() {
                    module_tree.set_rethrow_error(exception);
                }
            }
        }

        // Ensure any failures related to importing this dynamic module are immediately reported.
        match (network_error, existing_rethrow_error) {
            (Some(_), _) => unsafe {
                let err = gen_type_error(&global, "Dynamic import failed".to_owned(), can_gc);
                JS_SetPendingException(*cx, err.handle(), ExceptionStackBehavior::Capture);
            },
            (None, Some(rethrow_error)) => unsafe {
                JS_SetPendingException(
                    *cx,
                    rethrow_error.handle(),
                    ExceptionStackBehavior::Capture,
                );
            },
            // do nothing if there's no errors
            (None, None) => {},
        };

        debug!("Finishing dynamic import for {:?}", module_identity);

        rooted!(in(*cx) let mut evaluation_promise = ptr::null_mut::<JSObject>());
        if rval.is_object() {
            evaluation_promise.set(rval.to_object());
        }

        unsafe {
            let ok = FinishDynamicModuleImport(
                *cx,
                evaluation_promise.handle().into(),
                module.referencing_private.handle(),
                module.specifier.handle(),
                module.promise.reflector().get_jsobject().into_handle(),
            );
            if ok {
                assert!(!JS_IsExceptionPending(*cx));
            } else {
                warn!("failed to finish dynamic module import");
            }
        }
    }
}

/// The context required for asynchronously loading an external module script source.
struct ModuleContext {
    /// The owner of the module that initiated the request.
    owner: ModuleOwner,
    /// The response body received to date.
    data: Vec<u8>,
    /// The response metadata received to date.
    metadata: Option<Metadata>,
    /// The initial URL requested.
    url: ServoUrl,
    /// Destination of current module context
    destination: Destination,
    /// Options for the current script fetch
    options: ScriptFetchOptions,
    /// Indicates whether the request failed, and why
    status: Result<(), NetworkError>,
    /// Timing object for this resource
    resource_timing: ResourceFetchTiming,
    /// `introductionType` value to set in the `CompileOptionsWrapper`.
    introduction_type: Option<&'static CStr>,
}

impl FetchResponseListener for ModuleContext {
    // TODO(cybai): Perhaps add custom steps to perform fetch here?
    fn process_request_body(&mut self, _: RequestId) {}

    // TODO(cybai): Perhaps add custom steps to perform fetch here?
    fn process_request_eof(&mut self, _: RequestId) {}

    fn process_response(&mut self, _: RequestId, metadata: Result<FetchMetadata, NetworkError>) {
        self.metadata = metadata.ok().map(|meta| match meta {
            FetchMetadata::Unfiltered(m) => m,
            FetchMetadata::Filtered { unsafe_, .. } => unsafe_,
        });

        let status = self
            .metadata
            .as_ref()
            .map(|m| m.status.clone())
            .unwrap_or_else(HttpStatus::new_error);

        self.status = {
            if status.is_error() {
                Err(NetworkError::Internal(
                    "No http status code received".to_owned(),
                ))
            } else if status.is_success() {
                Ok(())
            } else {
                Err(NetworkError::Internal(format!(
                    "HTTP error code {}",
                    status.code()
                )))
            }
        };
    }

    fn process_response_chunk(&mut self, _: RequestId, mut chunk: Vec<u8>) {
        if self.status.is_ok() {
            self.data.append(&mut chunk);
        }
    }

    /// <https://html.spec.whatwg.org/multipage/#fetch-a-single-module-script>
    /// Step 9-12
    #[allow(unsafe_code)]
    fn process_response_eof(
        &mut self,
        _: RequestId,
        response: Result<ResourceFetchTiming, NetworkError>,
    ) {
        let global = self.owner.global();

        if let Some(window) = global.downcast::<Window>() {
            window
                .Document()
                .finish_load(LoadType::Script(self.url.clone()), CanGc::note());
        }

        // Step 9-1 & 9-2.
        let load = response.and(self.status.clone()).and_then(|_| {
            // Step 9-3.
            let meta = self.metadata.take().unwrap();

            if let Some(content_type) = meta.content_type.map(Serde::into_inner) {
                if let Ok(content_type) = Mime::from_str(&content_type.to_string()) {
                    let essence_mime = content_type.essence_str();

                    if !SCRIPT_JS_MIMES.contains(&essence_mime) {
                        return Err(NetworkError::Internal(format!(
                            "Invalid MIME type: {}",
                            essence_mime
                        )));
                    }
                } else {
                    return Err(NetworkError::Internal(format!(
                        "Failed to parse MIME type: {}",
                        content_type
                    )));
                }
            } else {
                return Err(NetworkError::Internal("No MIME type".into()));
            }

            // Step 13.4: Let referrerPolicy be the result of parsing the `Referrer-Policy` header
            // given response.
            let referrer_policy = meta
                .headers
                .and_then(|headers| headers.typed_get::<ReferrerPolicyHeader>())
                .into();

            // Step 13.5: If referrerPolicy is not the empty string, set options's referrer policy
            // to referrerPolicy.
            if referrer_policy != ReferrerPolicy::EmptyString {
                self.options.referrer_policy = referrer_policy;
            }

            // Step 10.
            let (source_text, _, _) = UTF_8.decode(&self.data);
            Ok(ScriptOrigin::external(
                Rc::new(DOMString::from(source_text)),
                meta.final_url,
                self.options.clone(),
                ScriptType::Module,
                global.unminified_js_dir(),
            ))
        });

        let module_tree = {
            let module_map = global.get_module_map().borrow();
            module_map.get(&self.url).unwrap().clone()
        };

        module_tree.remove_incomplete_fetch_url(&self.url);

        // Step 12.
        match load {
            Err(err) => {
                error!("Failed to fetch {} with error {:?}", &self.url, err);
                module_tree.set_network_error(err);
                module_tree.advance_finished_and_link(&global, CanGc::note());
            },
            Ok(ref resp_mod_script) => {
                module_tree.set_text(resp_mod_script.text());

                let cx = GlobalScope::get_cx();
                rooted!(in(*cx) let mut compiled_module: *mut JSObject = ptr::null_mut());
                let compiled_module_result = module_tree.compile_module_script(
                    &global,
                    self.owner.clone(),
                    resp_mod_script.text(),
                    &self.url,
                    self.options.clone(),
                    compiled_module.handle_mut(),
                    false,
                    CanGc::note(),
                    self.introduction_type,
                );

                match compiled_module_result {
                    Err(exception) => {
                        module_tree.set_rethrow_error(exception);
                        module_tree.advance_finished_and_link(&global, CanGc::note());
                    },
                    Ok(_) => {
                        module_tree.set_record(ModuleObject::new(compiled_module.handle()));

                        module_tree.fetch_module_descendants(
                            &self.owner,
                            self.destination,
                            &self.options,
                            ModuleIdentity::ModuleUrl(self.url.clone()),
                            CanGc::note(),
                        );
                    },
                }
            },
        }
    }

    fn resource_timing_mut(&mut self) -> &mut ResourceFetchTiming {
        &mut self.resource_timing
    }

    fn resource_timing(&self) -> &ResourceFetchTiming {
        &self.resource_timing
    }

    fn submit_resource_timing(&mut self) {
        network_listener::submit_timing(self, CanGc::note())
    }

    fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<Violation>) {
        let global = &self.resource_timing_global();
        global.report_csp_violations(violations, None, None);
    }
}

impl ResourceTimingListener for ModuleContext {
    fn resource_timing_information(&self) -> (InitiatorType, ServoUrl) {
        let initiator_type = InitiatorType::LocalName("module".to_string());
        (initiator_type, self.url.clone())
    }

    fn resource_timing_global(&self) -> DomRoot<GlobalScope> {
        self.owner.global()
    }
}

impl PreInvoke for ModuleContext {}

#[allow(unsafe_code, non_snake_case)]
/// A function to register module hooks (e.g. listening on resolving modules,
/// getting module metadata, getting script private reference and resolving dynamic import)
pub(crate) unsafe fn EnsureModuleHooksInitialized(rt: *mut JSRuntime) {
    if GetModuleResolveHook(rt).is_some() {
        return;
    }

    SetModuleResolveHook(rt, Some(HostResolveImportedModule));
    SetModuleMetadataHook(rt, Some(HostPopulateImportMeta));
    SetScriptPrivateReferenceHooks(
        rt,
        Some(host_add_ref_top_level_script),
        Some(host_release_top_level_script),
    );
    SetModuleDynamicImportHook(rt, Some(host_import_module_dynamically));
}

#[allow(unsafe_code)]
unsafe extern "C" fn host_add_ref_top_level_script(value: *const Value) {
    let val = Rc::from_raw((*value).to_private() as *const ModuleScript);
    mem::forget(val.clone());
    mem::forget(val);
}

#[allow(unsafe_code)]
unsafe extern "C" fn host_release_top_level_script(value: *const Value) {
    let _val = Rc::from_raw((*value).to_private() as *const ModuleScript);
}

#[allow(unsafe_code)]
/// <https://tc39.es/ecma262/#sec-hostimportmoduledynamically>
/// <https://html.spec.whatwg.org/multipage/#hostimportmoduledynamically(referencingscriptormodule,-specifier,-promisecapability)>
pub(crate) unsafe extern "C" fn host_import_module_dynamically(
    cx: *mut JSContext,
    reference_private: RawHandleValue,
    specifier: RawHandle<*mut JSObject>,
    promise: RawHandle<*mut JSObject>,
) -> bool {
    // Step 1.
    let cx = SafeJSContext::from_ptr(cx);
    let in_realm_proof = AlreadyInRealm::assert_for_cx(cx);
    let global_scope = GlobalScope::from_context(*cx, InRealm::Already(&in_realm_proof));
    let promise = Promise::new_with_js_promise(Handle::from_raw(promise), cx);

    // Step 5 & 6.
    if let Err(e) = fetch_an_import_module_script_graph(
        &global_scope,
        specifier,
        reference_private,
        promise,
        CanGc::note(),
    ) {
        JS_SetPendingException(*cx, e.handle(), ExceptionStackBehavior::Capture);
        return false;
    }

    true
}

#[derive(Clone, Debug, JSTraceable, MallocSizeOf)]
/// <https://html.spec.whatwg.org/multipage/#script-fetch-options>
pub(crate) struct ScriptFetchOptions {
    #[no_trace]
    pub(crate) referrer: Referrer,
    pub(crate) integrity_metadata: String,
    #[no_trace]
    pub(crate) credentials_mode: CredentialsMode,
    pub(crate) cryptographic_nonce: String,
    #[no_trace]
    pub(crate) parser_metadata: ParserMetadata,
    #[no_trace]
    pub(crate) referrer_policy: ReferrerPolicy,
}

impl ScriptFetchOptions {
    /// <https://html.spec.whatwg.org/multipage/#default-classic-script-fetch-options>
    pub(crate) fn default_classic_script(global: &GlobalScope) -> ScriptFetchOptions {
        Self {
            cryptographic_nonce: String::new(),
            integrity_metadata: String::new(),
            referrer: global.get_referrer(),
            parser_metadata: ParserMetadata::NotParserInserted,
            credentials_mode: CredentialsMode::CredentialsSameOrigin,
            referrer_policy: ReferrerPolicy::EmptyString,
        }
    }

    /// <https://html.spec.whatwg.org/multipage/#descendant-script-fetch-options>
    fn descendant_fetch_options(&self) -> ScriptFetchOptions {
        Self {
            referrer: self.referrer.clone(),
            integrity_metadata: String::new(),
            cryptographic_nonce: self.cryptographic_nonce.clone(),
            credentials_mode: self.credentials_mode,
            parser_metadata: self.parser_metadata,
            referrer_policy: self.referrer_policy,
        }
    }
}

#[allow(unsafe_code)]
unsafe fn module_script_from_reference_private(
    reference_private: &RawHandle<JSVal>,
) -> Option<&ModuleScript> {
    if reference_private.get().is_undefined() {
        return None;
    }
    (reference_private.get().to_private() as *const ModuleScript).as_ref()
}

/// <https://html.spec.whatwg.org/multipage/#fetch-an-import()-module-script-graph>
#[allow(unsafe_code)]
fn fetch_an_import_module_script_graph(
    global: &GlobalScope,
    module_request: RawHandle<*mut JSObject>,
    reference_private: RawHandleValue,
    promise: Rc<Promise>,
    can_gc: CanGc,
) -> Result<(), RethrowError> {
    // Step 1.
    let cx = GlobalScope::get_cx();
    let specifier = unsafe {
        let jsstr = std::ptr::NonNull::new(GetModuleRequestSpecifier(*cx, module_request)).unwrap();
        DOMString::from_string(jsstr_to_string(*cx, jsstr))
    };
    let mut options = ScriptFetchOptions::default_classic_script(global);
    let module_data = unsafe { module_script_from_reference_private(&reference_private) };
    if let Some(data) = module_data {
        options = data.options.descendant_fetch_options();
    }
    let url = ModuleTree::resolve_module_specifier(global, module_data, specifier, can_gc);

    // Step 2.
    if url.is_err() {
        let specifier_error = gen_type_error(global, "Wrong module specifier".to_owned(), can_gc);
        return Err(specifier_error);
    }

    let dynamic_module_id = DynamicModuleId(Uuid::new_v4());

    // Step 3.
    let owner = match unsafe { module_script_from_reference_private(&reference_private) } {
        Some(module_data) if module_data.owner.is_some() => module_data.owner.clone().unwrap(),
        _ => ModuleOwner::DynamicModule(Trusted::new(&DynamicModuleOwner::new(
            global,
            promise.clone(),
            dynamic_module_id,
            can_gc,
        ))),
    };

    let dynamic_module = RootedTraceableBox::new(DynamicModule {
        promise,
        specifier: Heap::default(),
        referencing_private: Heap::default(),
        id: dynamic_module_id,
    });
    dynamic_module.specifier.set(module_request.get());
    dynamic_module
        .referencing_private
        .set(reference_private.get());

    let url = url.unwrap();

    let mut visited_urls = HashSet::new();
    visited_urls.insert(url.clone());

    fetch_single_module_script(
        owner,
        url,
        visited_urls,
        Destination::Script,
        options,
        None,
        true,
        Some(dynamic_module),
        Some(IntroductionType::IMPORTED_MODULE),
        can_gc,
    );
    Ok(())
}

#[allow(unsafe_code, non_snake_case)]
/// <https://tc39.es/ecma262/#sec-HostLoadImportedModule>
/// <https://html.spec.whatwg.org/multipage/#hostloadimportedmodule>
unsafe extern "C" fn HostResolveImportedModule(
    cx: *mut JSContext,
    reference_private: RawHandleValue,
    specifier: RawHandle<*mut JSObject>,
) -> *mut JSObject {
    let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
    let global_scope = GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof));

    // Step 5.
    let module_data = module_script_from_reference_private(&reference_private);
    let jsstr = std::ptr::NonNull::new(GetModuleRequestSpecifier(cx, specifier)).unwrap();
    let specifier = DOMString::from_string(jsstr_to_string(cx, jsstr));
    let url =
        ModuleTree::resolve_module_specifier(&global_scope, module_data, specifier, CanGc::note());

    // Step 6.
    assert!(url.is_ok());

    let parsed_url = url.unwrap();

    // Step 4 & 7.
    let module_map = global_scope.get_module_map().borrow();

    let module_tree = module_map.get(&parsed_url);

    // Step 9.
    assert!(module_tree.is_some());

    let fetched_module_object = module_tree.unwrap().get_record().borrow();

    // Step 8.
    assert!(fetched_module_object.is_some());

    // Step 10.
    if let Some(record) = &*fetched_module_object {
        return record.handle().get();
    }

    unreachable!()
}

#[allow(unsafe_code, non_snake_case)]
/// <https://tc39.es/ecma262/#sec-hostgetimportmetaproperties>
/// <https://html.spec.whatwg.org/multipage/#hostgetimportmetaproperties>
unsafe extern "C" fn HostPopulateImportMeta(
    cx: *mut JSContext,
    reference_private: RawHandleValue,
    meta_object: RawHandle<*mut JSObject>,
) -> bool {
    let in_realm_proof = AlreadyInRealm::assert_for_cx(SafeJSContext::from_ptr(cx));
    let global_scope = GlobalScope::from_context(cx, InRealm::Already(&in_realm_proof));

    // Step 2.
    let base_url = match module_script_from_reference_private(&reference_private) {
        Some(module_data) => module_data.base_url.clone(),
        None => global_scope.api_base_url(),
    };

    rooted!(in(cx) let url_string = JS_NewStringCopyN(
        cx,
        base_url.as_str().as_ptr() as *const _,
        base_url.as_str().len()
    ));

    // Step 3.
    JS_DefineProperty4(
        cx,
        meta_object,
        c"url".as_ptr(),
        url_string.handle().into_handle(),
        JSPROP_ENUMERATE.into(),
    )
}

/// <https://html.spec.whatwg.org/multipage/#fetch-a-module-script-tree>
pub(crate) fn fetch_external_module_script(
    owner: ModuleOwner,
    url: ServoUrl,
    destination: Destination,
    options: ScriptFetchOptions,
    can_gc: CanGc,
) {
    let mut visited_urls = HashSet::new();
    visited_urls.insert(url.clone());

    // Step 1.
    fetch_single_module_script(
        owner,
        url,
        visited_urls,
        destination,
        options,
        None,
        true,
        None,
        Some(IntroductionType::SRC_SCRIPT),
        can_gc,
    )
}

#[derive(JSTraceable, MallocSizeOf)]
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
pub(crate) struct DynamicModuleList {
    requests: Vec<RootedTraceableBox<DynamicModule>>,

    #[ignore_malloc_size_of = "Define in uuid"]
    next_id: DynamicModuleId,
}

impl DynamicModuleList {
    pub(crate) fn new() -> Self {
        Self {
            requests: vec![],
            next_id: DynamicModuleId(Uuid::new_v4()),
        }
    }

    fn push(&mut self, mut module: RootedTraceableBox<DynamicModule>) -> DynamicModuleId {
        let id = self.next_id;
        self.next_id = DynamicModuleId(Uuid::new_v4());
        module.id = id;
        self.requests.push(module);
        id
    }

    fn remove(&mut self, id: DynamicModuleId) -> RootedTraceableBox<DynamicModule> {
        let index = self
            .requests
            .iter()
            .position(|module| module.id == id)
            .expect("missing dynamic module");
        self.requests.remove(index)
    }
}

#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
#[derive(JSTraceable, MallocSizeOf)]
struct DynamicModule {
    #[ignore_malloc_size_of = "Rc is hard"]
    promise: Rc<Promise>,
    #[ignore_malloc_size_of = "GC types are hard"]
    specifier: Heap<*mut JSObject>,
    #[ignore_malloc_size_of = "GC types are hard"]
    referencing_private: Heap<JSVal>,
    #[ignore_malloc_size_of = "Defined in uuid"]
    id: DynamicModuleId,
}

/// <https://html.spec.whatwg.org/multipage/#fetch-a-single-module-script>
#[allow(clippy::too_many_arguments)]
fn fetch_single_module_script(
    owner: ModuleOwner,
    url: ServoUrl,
    visited_urls: HashSet<ServoUrl>,
    destination: Destination,
    options: ScriptFetchOptions,
    parent_identity: Option<ModuleIdentity>,
    top_level_module_fetch: bool,
    dynamic_module: Option<RootedTraceableBox<DynamicModule>>,
    introduction_type: Option<&'static CStr>,
    can_gc: CanGc,
) {
    {
        // Step 1.
        let global = owner.global();
        let module_map = global.get_module_map().borrow();

        debug!("Start to fetch {}", url);

        if let Some(module_tree) = module_map.get(&url.clone()) {
            let status = module_tree.get_status();

            debug!("Meet a fetched url {} and its status is {:?}", url, status);

            match dynamic_module {
                Some(module) => module_tree.append_dynamic_module_handler(
                    owner.clone(),
                    ModuleIdentity::ModuleUrl(url.clone()),
                    module,
                    can_gc,
                ),
                None if top_level_module_fetch => module_tree.append_handler(
                    owner.clone(),
                    ModuleIdentity::ModuleUrl(url.clone()),
                    options,
                    can_gc,
                ),
                // do nothing if it's neither a dynamic module nor a top level module
                None => {},
            }

            if let Some(parent_identity) = parent_identity {
                module_tree.insert_parent_identity(parent_identity);
            }

            match status {
                ModuleStatus::Initial => unreachable!(
                    "We have the module in module map so its status should not be `initial`"
                ),
                // Step 2.
                ModuleStatus::Fetching => {},
                // Step 3.
                ModuleStatus::FetchingDescendants | ModuleStatus::Finished => {
                    module_tree.advance_finished_and_link(&global, can_gc);
                },
            }

            return;
        }
    }

    let global = owner.global();
    let is_external = true;
    let module_tree = ModuleTree::new(url.clone(), is_external, visited_urls);
    module_tree.set_status(ModuleStatus::Fetching);

    match dynamic_module {
        Some(module) => module_tree.append_dynamic_module_handler(
            owner.clone(),
            ModuleIdentity::ModuleUrl(url.clone()),
            module,
            can_gc,
        ),
        None if top_level_module_fetch => module_tree.append_handler(
            owner.clone(),
            ModuleIdentity::ModuleUrl(url.clone()),
            options.clone(),
            can_gc,
        ),
        // do nothing if it's neither a dynamic module nor a top level module
        None => {},
    }

    if let Some(parent_identity) = parent_identity {
        module_tree.insert_parent_identity(parent_identity);
    }

    module_tree.insert_incomplete_fetch_url(&url);

    // Step 4.
    global.set_module_map(url.clone(), module_tree);

    // Step 5-6.
    let mode = match destination {
        Destination::Worker | Destination::SharedWorker if top_level_module_fetch => {
            RequestMode::SameOrigin
        },
        _ => RequestMode::CorsMode,
    };

    let document: Option<DomRoot<Document>> = match &owner {
        ModuleOwner::Worker(_) | ModuleOwner::DynamicModule(_) => None,
        ModuleOwner::Window(script) => Some(script.root().owner_document()),
    };
    let webview_id = document.as_ref().map(|document| document.webview_id());

    // Step 7-8.
    let request = RequestBuilder::new(webview_id, url.clone(), global.get_referrer())
        .destination(destination)
        .origin(global.origin().immutable().clone())
        .parser_metadata(options.parser_metadata)
        .integrity_metadata(options.integrity_metadata.clone())
        .credentials_mode(options.credentials_mode)
        .referrer_policy(options.referrer_policy)
        .mode(mode)
        .insecure_requests_policy(global.insecure_requests_policy())
        .has_trustworthy_ancestor_origin(global.has_trustworthy_ancestor_origin())
        .policy_container(global.policy_container().to_owned())
        .cryptographic_nonce_metadata(options.cryptographic_nonce.clone());

    let context = Arc::new(Mutex::new(ModuleContext {
        owner,
        data: vec![],
        metadata: None,
        url: url.clone(),
        destination,
        options,
        status: Ok(()),
        resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource),
        introduction_type,
    }));

    let network_listener = NetworkListener {
        context,
        task_source: global.task_manager().networking_task_source().to_sendable(),
    };
    match document {
        Some(document) => {
            let request = document.prepare_request(request);
            document.loader_mut().fetch_async_with_callback(
                LoadType::Script(url),
                request,
                network_listener.into_callback(),
            );
        },
        None => global.fetch_with_network_listener(request, network_listener),
    }
}

#[allow(unsafe_code)]
/// <https://html.spec.whatwg.org/multipage/#fetch-an-inline-module-script-graph>
pub(crate) fn fetch_inline_module_script(
    owner: ModuleOwner,
    module_script_text: Rc<DOMString>,
    url: ServoUrl,
    script_id: ScriptId,
    options: ScriptFetchOptions,
    can_gc: CanGc,
) {
    let global = owner.global();
    let is_external = false;
    let module_tree = ModuleTree::new(url.clone(), is_external, HashSet::new());

    let cx = GlobalScope::get_cx();
    rooted!(in(*cx) let mut compiled_module: *mut JSObject = ptr::null_mut());
    let compiled_module_result = module_tree.compile_module_script(
        &global,
        owner.clone(),
        module_script_text,
        &url,
        options.clone(),
        compiled_module.handle_mut(),
        true,
        can_gc,
        Some(IntroductionType::INLINE_SCRIPT),
    );

    match compiled_module_result {
        Ok(_) => {
            module_tree.append_handler(
                owner.clone(),
                ModuleIdentity::ScriptId(script_id),
                options.clone(),
                can_gc,
            );
            module_tree.set_record(ModuleObject::new(compiled_module.handle()));

            // We need to set `module_tree` into inline module map in case
            // of that the module descendants finished right after the
            // fetch module descendants step.
            global.set_inline_module_map(script_id, module_tree);

            // Due to needed to set `module_tree` to inline module_map first,
            // we will need to retrieve it again so that we can do the fetch
            // module descendants step.
            let inline_module_map = global.get_inline_module_map().borrow();
            let module_tree = inline_module_map.get(&script_id).unwrap().clone();

            module_tree.fetch_module_descendants(
                &owner,
                Destination::Script,
                &options,
                ModuleIdentity::ScriptId(script_id),
                can_gc,
            );
        },
        Err(exception) => {
            module_tree.set_rethrow_error(exception);
            module_tree.set_status(ModuleStatus::Finished);
            global.set_inline_module_map(script_id, module_tree);
            owner.notify_owner_to_finish(ModuleIdentity::ScriptId(script_id), options, can_gc);
        },
    }
}

pub(crate) type ModuleSpecifierMap = IndexMap<String, Option<ServoUrl>>;
pub(crate) type ModuleIntegrityMap = IndexMap<ServoUrl, String>;

/// <https://html.spec.whatwg.org/multipage/#specifier-resolution-record>
#[derive(Default, Eq, Hash, JSTraceable, MallocSizeOf, PartialEq)]
pub(crate) struct ResolvedModule {
    /// <https://html.spec.whatwg.org/multipage/#specifier-resolution-record-serialized-base-url>
    base_url: String,
    /// <https://html.spec.whatwg.org/multipage/#specifier-resolution-record-specifier>
    specifier: String,
    /// <https://html.spec.whatwg.org/multipage/#specifier-resolution-record-as-url>
    #[no_trace]
    specifier_url: Option<ServoUrl>,
}

impl ResolvedModule {
    pub(crate) fn new(
        base_url: String,
        specifier: String,
        specifier_url: Option<ServoUrl>,
    ) -> Self {
        Self {
            base_url,
            specifier,
            specifier_url,
        }
    }
}

/// <https://html.spec.whatwg.org/multipage/#import-map-processing-model>
#[derive(Default, JSTraceable, MallocSizeOf)]
pub(crate) struct ImportMap {
    #[no_trace]
    imports: ModuleSpecifierMap,
    #[no_trace]
    scopes: IndexMap<ServoUrl, ModuleSpecifierMap>,
    #[no_trace]
    integrity: ModuleIntegrityMap,
}

/// <https://html.spec.whatwg.org/multipage/#register-an-import-map>
pub(crate) fn register_import_map(
    global: &GlobalScope,
    result: Fallible<ImportMap>,
    can_gc: CanGc,
) {
    match result {
        Ok(new_import_map) => {
            // Step 2. Merge existing and new import maps, given global and result's import map.
            merge_existing_and_new_import_maps(global, new_import_map, can_gc);
        },
        Err(exception) => {
            // Step 1. If result's error to rethrow is not null, then report
            // an exception given by result's error to rethrow for global and return.
            throw_dom_exception(GlobalScope::get_cx(), global, exception.clone(), can_gc);
        },
    }
}

/// <https://html.spec.whatwg.org/multipage/#merge-existing-and-new-import-maps>
fn merge_existing_and_new_import_maps(
    global: &GlobalScope,
    new_import_map: ImportMap,
    can_gc: CanGc,
) {
    // Step 1. Let newImportMapScopes be a deep copy of newImportMap's scopes.
    let new_import_map_scopes = new_import_map.scopes;

    // Step 2. Let oldImportMap be global's import map.
    let mut old_import_map = global.import_map_mut();

    // Step 3. Let newImportMapImports be a deep copy of newImportMap's imports.
    let mut new_import_map_imports = new_import_map.imports;

    let resolved_module_set = global.resolved_module_set();
    // Step 4. For each scopePrefix → scopeImports of newImportMapScopes:
    for (scope_prefix, mut scope_imports) in new_import_map_scopes {
        // Step 4.1. For each record of global's resolved module set:
        for record in resolved_module_set.iter() {
            // If scopePrefix is record's serialized base URL, or if scopePrefix ends with
            // U+002F (/) and scopePrefix is a code unit prefix of record's serialized base URL, then:
            let prefix = scope_prefix.as_str();
            if prefix == record.base_url ||
                (record.base_url.starts_with(prefix) && prefix.ends_with('\u{002f}'))
            {
                // For each specifierKey → resolutionResult of scopeImports:
                scope_imports.retain(|key, val| {
                    // If specifierKey is record's specifier, or if all of the following conditions are true:
                    // specifierKey ends with U+002F (/);
                    // specifierKey is a code unit prefix of record's specifier;
                    // either record's specifier as a URL is null or is special,
                    if *key == record.specifier ||
                        (key.ends_with('\u{002f}') &&
                            record.specifier.starts_with(key) &&
                            (record.specifier_url.is_none() ||
                                record
                                    .specifier_url
                                    .as_ref()
                                    .map(|u| u.is_special_scheme())
                                    .unwrap_or_default()))
                    {
                        // The user agent may report a warning to the console indicating the ignored rule.
                        // They may choose to avoid reporting if the rule is identical to an existing one.
                        Console::internal_warn(
                            global,
                            DOMString::from(format!("Ignored rule: {key} -> {val:?}.")),
                        );
                        // Remove scopeImports[specifierKey].
                        false
                    } else {
                        true
                    }
                })
            }
        }

        // Step 4.2 If scopePrefix exists in oldImportMap's scopes
        if old_import_map.scopes.contains_key(&scope_prefix) {
            // set oldImportMap's scopes[scopePrefix] to the result of
            // merging module specifier maps, given scopeImports and oldImportMap's scopes[scopePrefix].
            let merged_module_specifier_map = merge_module_specifier_maps(
                global,
                scope_imports,
                &old_import_map.scopes[&scope_prefix],
                can_gc,
            );
            old_import_map
                .scopes
                .insert(scope_prefix, merged_module_specifier_map);
        } else {
            // Step 4.3 Otherwise, set oldImportMap's scopes[scopePrefix] to scopeImports.
            old_import_map.scopes.insert(scope_prefix, scope_imports);
        }
    }

    // Step 5. For each url → integrity of newImportMap's integrity:
    for (url, integrity) in &new_import_map.integrity {
        // Step 5.1 If url exists in oldImportMap's integrity, then:
        if old_import_map.integrity.contains_key(url) {
            // Step 5.1.1 The user agent may report a warning to the console indicating the ignored rule.
            // They may choose to avoid reporting if the rule is identical to an existing one.
            Console::internal_warn(
                global,
                DOMString::from(format!("Ignored rule: {url} -> {integrity}.")),
            );
            // Step 5.1.2 Continue.
            continue;
        }

        // Step 5.2 Set oldImportMap's integrity[url] to integrity.
        old_import_map
            .integrity
            .insert(url.clone(), integrity.clone());
    }

    // Step 6. For each record of global's resolved module set:
    for record in resolved_module_set.iter() {
        // For each specifier → url of newImportMapImports:
        new_import_map_imports.retain(|specifier, val| {
            // If specifier starts with record's specifier, then:
            if specifier.starts_with(&record.specifier) {
                // The user agent may report a warning to the console indicating the ignored rule.
                // They may choose to avoid reporting if the rule is identical to an existing one.
                Console::internal_warn(
                    global,
                    DOMString::from(format!("Ignored rule: {specifier} -> {val:?}.")),
                );
                // Remove newImportMapImports[specifier].
                false
            } else {
                true
            }
        });
    }

    // Step 7. Set oldImportMap's imports to the result of merge module specifier maps,
    // given newImportMapImports and oldImportMap's imports.
    let merged_module_specifier_map = merge_module_specifier_maps(
        global,
        new_import_map_imports,
        &old_import_map.imports,
        can_gc,
    );
    old_import_map.imports = merged_module_specifier_map;
}

/// <https://html.spec.whatwg.org/multipage/#merge-module-specifier-maps>
fn merge_module_specifier_maps(
    global: &GlobalScope,
    new_map: ModuleSpecifierMap,
    old_map: &ModuleSpecifierMap,
    _can_gc: CanGc,
) -> ModuleSpecifierMap {
    // Step 1. Let mergedMap be a deep copy of oldMap.
    let mut merged_map = old_map.clone();

    // Step 2. For each specifier → url of newMap:
    for (specifier, url) in new_map {
        // Step 2.1 If specifier exists in oldMap, then:
        if old_map.contains_key(&specifier) {
            // Step 2.1.1 The user agent may report a warning to the console indicating the ignored rule.
            // They may choose to avoid reporting if the rule is identical to an existing one.
            Console::internal_warn(
                global,
                DOMString::from(format!("Ignored rule: {specifier} -> {url:?}.")),
            );

            // Step 2.1.2 Continue.
            continue;
        }

        // Step 2.2 Set mergedMap[specifier] to url.
        merged_map.insert(specifier, url);
    }

    merged_map
}

/// <https://html.spec.whatwg.org/multipage/#parse-an-import-map-string>
pub(crate) fn parse_an_import_map_string(
    module_owner: ModuleOwner,
    input: Rc<DOMString>,
    base_url: ServoUrl,
    can_gc: CanGc,
) -> Fallible<ImportMap> {
    // Step 1. Let parsed be the result of parsing a JSON string to an Infra value given input.
    let parsed: JsonValue = serde_json::from_str(input.str())
        .map_err(|_| Error::Type("The value needs to be a JSON object.".to_owned()))?;
    // Step 2. If parsed is not an ordered map, then throw a TypeError indicating that the
    // top-level value needs to be a JSON object.
    let JsonValue::Object(mut parsed) = parsed else {
        return Err(Error::Type(
            "The top-level value needs to be a JSON object.".to_owned(),
        ));
    };

    // Step 3. Let sortedAndNormalizedImports be an empty ordered map.
    let mut sorted_and_normalized_imports = ModuleSpecifierMap::new();
    // Step 4. If parsed["imports"] exists, then:
    if let Some(imports) = parsed.get("imports") {
        // Step 4.1 If parsed["imports"] is not an ordered map, then throw a TypeError
        // indicating that the value for the "imports" top-level key needs to be a JSON object.
        let JsonValue::Object(imports) = imports else {
            return Err(Error::Type(
                "The \"imports\" top-level value needs to be a JSON object.".to_owned(),
            ));
        };
        // Step 4.2 Set sortedAndNormalizedImports to the result of sorting and
        // normalizing a module specifier map given parsed["imports"] and baseURL.
        sorted_and_normalized_imports = sort_and_normalize_module_specifier_map(
            &module_owner.global(),
            imports,
            &base_url,
            can_gc,
        );
    }

    // Step 5. Let sortedAndNormalizedScopes be an empty ordered map.
    let mut sorted_and_normalized_scopes: IndexMap<ServoUrl, ModuleSpecifierMap> = IndexMap::new();
    // Step 6. If parsed["scopes"] exists, then:
    if let Some(scopes) = parsed.get("scopes") {
        // Step 6.1 If parsed["scopes"] is not an ordered map, then throw a TypeError
        // indicating that the value for the "scopes" top-level key needs to be a JSON object.
        let JsonValue::Object(scopes) = scopes else {
            return Err(Error::Type(
                "The \"scopes\" top-level value needs to be a JSON object.".to_owned(),
            ));
        };
        // Step 6.2 Set sortedAndNormalizedScopes to the result of sorting and
        // normalizing scopes given parsed["scopes"] and baseURL.
        sorted_and_normalized_scopes =
            sort_and_normalize_scopes(&module_owner.global(), scopes, &base_url, can_gc)?;
    }

    // Step 7. Let normalizedIntegrity be an empty ordered map.
    let mut normalized_integrity = ModuleIntegrityMap::new();
    // Step 8. If parsed["integrity"] exists, then:
    if let Some(integrity) = parsed.get("integrity") {
        // Step 8.1 If parsed["integrity"] is not an ordered map, then throw a TypeError
        // indicating that the value for the "integrity" top-level key needs to be a JSON object.
        let JsonValue::Object(integrity) = integrity else {
            return Err(Error::Type(
                "The \"integrity\" top-level value needs to be a JSON object.".to_owned(),
            ));
        };
        // Step 8.2 Set normalizedIntegrity to the result of normalizing
        // a module integrity map given parsed["integrity"] and baseURL.
        normalized_integrity =
            normalize_module_integrity_map(&module_owner.global(), integrity, &base_url, can_gc);
    }

    // Step 9. If parsed's keys contains any items besides "imports", "scopes", or "integrity",
    // then the user agent should report a warning to the console indicating that an invalid
    // top-level key was present in the import map.
    parsed.retain(|k, _| !matches!(k.as_str(), "imports" | "scopes" | "integrity"));
    if !parsed.is_empty() {
        Console::internal_warn(
            &module_owner.global(),
            DOMString::from(
                "Invalid top-level key was present in the import map.
                Only \"imports\", \"scopes\", and \"integrity\" are allowed.",
            ),
        );
    }

    // Step 10. Return an import map
    Ok(ImportMap {
        imports: sorted_and_normalized_imports,
        scopes: sorted_and_normalized_scopes,
        integrity: normalized_integrity,
    })
}

/// <https://html.spec.whatwg.org/multipage/#sorting-and-normalizing-a-module-specifier-map>
#[allow(unsafe_code)]
fn sort_and_normalize_module_specifier_map(
    global: &GlobalScope,
    original_map: &JsonMap<String, JsonValue>,
    base_url: &ServoUrl,
    can_gc: CanGc,
) -> ModuleSpecifierMap {
    // Step 1. Let normalized be an empty ordered map.
    let mut normalized = ModuleSpecifierMap::new();

    // Step 2. For each specifier_key -> value in originalMap
    for (specifier_key, value) in original_map {
        // Step 2.1 Let normalized_specifier_key be the result of
        // normalizing a specifier key given specifier_key and base_url.
        let Some(normalized_specifier_key) =
            normalize_specifier_key(global, specifier_key, base_url, can_gc)
        else {
            // Step 2.2 If normalized_specifier_key is null, then continue.
            continue;
        };

        // Step 2.3 If value is not a string, then:
        let JsonValue::String(value) = value else {
            // Step 2.3.1 The user agent may report a warning to the console
            // indicating that addresses need to be strings.
            Console::internal_warn(global, DOMString::from("Addresses need to be strings."));

            // Step 2.3.2 Set normalized[normalized_specifier_key] to null.
            normalized.insert(normalized_specifier_key, None);
            // Step 2.3.3 Continue.
            continue;
        };

        // Step 2.4. Let address_url be the result of resolving a URL-like module specifier given value and baseURL.
        let value = DOMString::from(value.as_str());
        let Some(address_url) = ModuleTree::resolve_url_like_module_specifier(&value, base_url)
        else {
            // Step 2.5 If address_url is null, then:
            // Step 2.5.1. The user agent may report a warning to the console
            // indicating that the address was invalid.
            Console::internal_warn(
                global,
                DOMString::from(format!(
                    "Value failed to resolve to module specifier: {value}"
                )),
            );

            // Step 2.5.2 Set normalized[normalized_specifier_key] to null.
            normalized.insert(normalized_specifier_key, None);
            // Step 2.5.3 Continue.
            continue;
        };

        // Step 2.6 If specifier_key ends with U+002F (/), and the serialization of
        // address_url does not end with U+002F (/), then:
        if specifier_key.ends_with('\u{002f}') && !address_url.as_str().ends_with('\u{002f}') {
            // step 2.6.1. The user agent may report a warning to the console
            // indicating that an invalid address was given for the specifier key specifierKey;
            // since specifierKey ends with a slash, the address needs to as well.
            Console::internal_warn(
                global,
                DOMString::from(format!(
                    "Invalid address for specifier key '{specifier_key}': {address_url}.
                    Since specifierKey ends with a slash, the address needs to as well."
                )),
            );

            // Step 2.6.2 Set normalized[normalized_specifier_key] to null.
            normalized.insert(normalized_specifier_key, None);
            // Step 2.6.3 Continue.
            continue;
        }

        // Step 2.7 Set normalized[normalized_specifier_key] to address_url.
        normalized.insert(normalized_specifier_key, Some(address_url));
    }

    // Step 3. Return the result of sorting in descending order normalized
    // with an entry a being less than an entry b if a's key is code unit less than b's key.
    normalized.sort_by(|a_key, _, b_key, _| b_key.cmp(a_key));
    normalized
}

/// <https://html.spec.whatwg.org/multipage/#sorting-and-normalizing-scopes>
fn sort_and_normalize_scopes(
    global: &GlobalScope,
    original_map: &JsonMap<String, JsonValue>,
    base_url: &ServoUrl,
    can_gc: CanGc,
) -> Fallible<IndexMap<ServoUrl, ModuleSpecifierMap>> {
    // Step 1. Let normalized be an empty ordered map.
    let mut normalized: IndexMap<ServoUrl, ModuleSpecifierMap> = IndexMap::new();

    // Step 2. For each scopePrefix → potentialSpecifierMap of originalMap:
    for (scope_prefix, potential_specifier_map) in original_map {
        // Step 2.1 If potentialSpecifierMap is not an ordered map, then throw a TypeError indicating
        // that the value of the scope with prefix scopePrefix needs to be a JSON object.
        let JsonValue::Object(potential_specifier_map) = potential_specifier_map else {
            return Err(Error::Type(
                "The value of the scope with prefix scopePrefix needs to be a JSON object."
                    .to_owned(),
            ));
        };

        // Step 2.2 Let scopePrefixURL be the result of URL parsing scopePrefix with baseURL.
        let Ok(scope_prefix_url) = ServoUrl::parse_with_base(Some(base_url), scope_prefix) else {
            // Step 2.3 If scopePrefixURL is failure, then:
            // Step 2.3.1 The user agent may report a warning
            // to the console that the scope prefix URL was not parseable.
            Console::internal_warn(
                global,
                DOMString::from(format!(
                    "Scope prefix URL was not parseable: {scope_prefix}"
                )),
            );
            // Step 2.3.2 Continue.
            continue;
        };

        // Step 2.4 Let normalizedScopePrefix be the serialization of scopePrefixURL.
        let normalized_scope_prefix = scope_prefix_url;

        // Step 2.5 Set normalized[normalizedScopePrefix] to the result of sorting and
        // normalizing a module specifier map given potentialSpecifierMap and baseURL.
        let normalized_specifier_map = sort_and_normalize_module_specifier_map(
            global,
            potential_specifier_map,
            base_url,
            can_gc,
        );
        normalized.insert(normalized_scope_prefix, normalized_specifier_map);
    }

    // Step 3. Return the result of sorting in descending order normalized,
    // with an entry a being less than an entry b if a's key is code unit less than b's key.
    normalized.sort_by(|a_key, _, b_key, _| b_key.cmp(a_key));
    Ok(normalized)
}

/// <https://html.spec.whatwg.org/multipage/#normalizing-a-module-integrity-map>
fn normalize_module_integrity_map(
    global: &GlobalScope,
    original_map: &JsonMap<String, JsonValue>,
    base_url: &ServoUrl,
    _can_gc: CanGc,
) -> ModuleIntegrityMap {
    // Step 1. Let normalized be an empty ordered map.
    let mut normalized = ModuleIntegrityMap::new();

    // Step 2. For each key → value of originalMap:
    for (key, value) in original_map {
        // Step 2.1 Let resolvedURL be the result of
        // resolving a URL-like module specifier given key and baseURL.
        let Some(resolved_url) =
            ModuleTree::resolve_url_like_module_specifier(&DOMString::from(key.as_str()), base_url)
        else {
            // Step 2.2 If resolvedURL is null, then:
            // Step 2.2.1 The user agent may report a warning
            // to the console indicating that the key failed to resolve.
            Console::internal_warn(
                global,
                DOMString::from(format!("Key failed to resolve to module specifier: {key}")),
            );
            // Step 2.2.2 Continue.
            continue;
        };

        // Step 2.3 If value is not a string, then:
        let JsonValue::String(value) = value else {
            // Step 2.3.1 The user agent may report a warning
            // to the console indicating that integrity metadata values need to be strings.
            Console::internal_warn(
                global,
                DOMString::from("Integrity metadata values need to be strings."),
            );
            // Step 2.3.2 Continue.
            continue;
        };

        // Step 2.4 Set normalized[resolvedURL] to value.
        normalized.insert(resolved_url, value.clone());
    }

    // Step 3. Return normalized.
    normalized
}

/// <https://html.spec.whatwg.org/multipage/#normalizing-a-specifier-key>
fn normalize_specifier_key(
    global: &GlobalScope,
    specifier_key: &str,
    base_url: &ServoUrl,
    _can_gc: CanGc,
) -> Option<String> {
    // step 1. If specifierKey is the empty string, then:
    if specifier_key.is_empty() {
        // step 1.1 The user agent may report a warning to the console
        // indicating that specifier keys may not be the empty string.
        Console::internal_warn(
            global,
            DOMString::from("Specifier keys may not be the empty string."),
        );
        // step 1.2 Return null.
        return None;
    }
    // step 2. Let url be the result of resolving a URL-like module specifier, given specifierKey and baseURL.
    let url =
        ModuleTree::resolve_url_like_module_specifier(&DOMString::from(specifier_key), base_url);

    // step 3. If url is not null, then return the serialization of url.
    if let Some(url) = url {
        return Some(url.into_string());
    }

    // step 4. Return specifierKey.
    Some(specifier_key.to_string())
}

/// <https://html.spec.whatwg.org/multipage/#resolving-an-imports-match>
///
/// When the error is thrown, it will terminate the entire resolve a module specifier algorithm
/// without any further fallbacks.
pub(crate) fn resolve_imports_match(
    normalized_specifier: &str,
    as_url: Option<&ServoUrl>,
    specifier_map: &ModuleSpecifierMap,
    _can_gc: CanGc,
) -> Fallible<Option<ServoUrl>> {
    // Step 1. For each specifierKey → resolutionResult of specifierMap:
    for (specifier_key, resolution_result) in specifier_map {
        // Step 1.1 If specifierKey is normalizedSpecifier, then:
        if specifier_key == normalized_specifier {
            if let Some(resolution_result) = resolution_result {
                // Step 1.1.2 Assert: resolutionResult is a URL.
                // This is checked by Url type already.
                // Step 1.1.3 Return resolutionResult.
                return Ok(Some(resolution_result.clone()));
            } else {
                // Step 1.1.1 If resolutionResult is null, then throw a TypeError.
                return Err(Error::Type(
                    "Resolution of specifierKey was blocked by a null entry.".to_owned(),
                ));
            }
        }

        // Step 1.2 If all of the following are true:
        // - specifierKey ends with U+002F (/)
        // - specifierKey is a code unit prefix of normalizedSpecifier
        // - either asURL is null, or asURL is special, then:
        if specifier_key.ends_with('\u{002f}') &&
            normalized_specifier.starts_with(specifier_key) &&
            (as_url.is_none() || as_url.map(|u| u.is_special_scheme()).unwrap_or_default())
        {
            // Step 1.2.1 If resolutionResult is null, then throw a TypeError.
            // Step 1.2.2 Assert: resolutionResult is a URL.
            let Some(resolution_result) = resolution_result else {
                return Err(Error::Type(
                    "Resolution of specifierKey was blocked by a null entry.".to_owned(),
                ));
            };

            // Step 1.2.3 Let afterPrefix be the portion of normalizedSpecifier after the initial specifierKey prefix.
            let after_prefix = normalized_specifier
                .strip_prefix(specifier_key)
                .expect("specifier_key should be the prefix of normalized_specifier");

            // Step 1.2.4 Assert: resolutionResult, serialized, ends with U+002F (/), as enforced during parsing.
            debug_assert!(resolution_result.as_str().ends_with('\u{002f}'));

            // Step 1.2.5 Let url be the result of URL parsing afterPrefix with resolutionResult.
            let url = ServoUrl::parse_with_base(Some(resolution_result), after_prefix);

            // Step 1.2.6 If url is failure, then throw a TypeError
            // Step 1.2.7 Assert: url is a URL.
            let Ok(url) = url else {
                return Err(Error::Type(
                    "Resolution of normalizedSpecifier was blocked since
                    the afterPrefix portion could not be URL-parsed relative to
                    the resolutionResult mapped to by the specifierKey prefix."
                        .to_owned(),
                ));
            };

            // Step 1.2.8 If the serialization of resolutionResult is not
            // a code unit prefix of the serialization of url, then throw a TypeError
            if !url.as_str().starts_with(resolution_result.as_str()) {
                return Err(Error::Type(
                    "Resolution of normalizedSpecifier was blocked due to
                    it backtracking above its prefix specifierKey."
                        .to_owned(),
                ));
            }

            // Step 1.2.9 Return url.
            return Ok(Some(url));
        }
    }

    // Step 2. Return null.
    Ok(None)
}
