Repository: LadybirdBrowser/ladybird
File: Libraries/LibWeb/HTML/HTMLScriptElement.cpp (C++)

Code before:
            fetch_inline_module_script_graph(realm(), m_document->url().to_byte_string(), source_text.to_byte_string(), base_url, document().relevant_settings_object(), steps);
        }
        // -> "importmap"
        else if (m_script_type == ScriptType::ImportMap) {
            // 1. Let result be the result of creating an import map parse result given source text and base URL.
            auto result = ImportMapParseResult::create(realm(), source_text.to_byte_string(), base_url);

            // 2. Mark as ready el given result.
            mark_as_ready(Result(move(result)));
        }
        // FIXME: -> "speculationrules"
    }

    // 36. If el's type is "classic" and el has a src attribute, or el's type is "module":
    if ((m_script_type == ScriptType::Classic && has_attribute(HTML::AttributeNames::src)) || m_script_type == ScriptType::Module) {
        // 1. Assert: el's result is "uninitialized".
        // FIXME: I believe this step to be a spec bug, and it should be removed: https://github.com/whatwg/html/issues/8534

        // 2. If el has an async attribute or el's force async is true:
        if (has_attribute(HTML::AttributeNames::async) || m_force_async) {
            // 1. Let scripts be el's preparation-time document's set of scripts that will execute as soon as possible.
            // 2. Append el to scripts.
            m_preparation_time_document->scripts_to_execute_as_soon_as_possible().append(*this);

            // 3. Set el's steps to run when the result is ready to the following:
            set_steps_to_run_when_the_result_is_ready([this] {
                // 1. Execute the script element el.
                execute_script();

                // 2. Remove el from scripts.
                m_preparation_time_document->scripts_to_execute_as_soon_as_possible().remove_first_matching([this](auto& entry) {
                    return entry.ptr() == this;
                });
            });
        }

        // 3. Otherwise, if el is not parser-inserted:
        else if (!is_parser_inserted()) {
            // 1. Let scripts be el's preparation-time document's list of scripts that will execute in order as soon as possible.
            // 2. Append el to scripts.
            m_preparation_time_document->scripts_to_execute_in_order_as_soon_as_possible().append(*this);

            // 3. Set el's steps to run when the result is ready to the following:
            set_steps_to_run_when_the_result_is_ready([this] {
                auto& scripts = m_preparation_time_document->scripts_to_execute_in_order_as_soon_as_possible();
                // 1. If scripts[0] is not el, then abort these steps.
                if (scripts[0] != this)
                    return;

                // 2. While scripts is not empty, and scripts[0]'s result is not "uninitialized":
                while (!scripts.is_empty() && !scripts[0]->m_result.has<ResultState::Uninitialized>()) {

Review comment (bug):
Thanks! The change in fetch also fixes the WPT tests from crashing of:
* https://wpt.live/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-fetch-error.sub.html
* https://wpt.live/html/semantics/scripting-1/the-script-element/json-module/load-error-events.html

However, the change to HTMLScriptElement here seems dubious - I don't quite understand the issue here. I believe we are matching the specification text as written currently. The crash also seems to be resolved without this change also.

What situation does the change to HTMLScriptElement fix?


Code after:
            auto steps = create_on_fetch_script_complete(heap(), [this](auto result) {
                // 1. Queue an element task on the networking task source given el to perform the following steps:
                queue_an_element_task(Task::Source::Networking, [this, result = move(result)] {
                    // 1. Mark as ready el given result.
                    if (!result)
                        mark_as_ready(ResultState::Null {});
                    else
                        mark_as_ready(Result(*result));
                });
            });

            // 2. Fetch an inline module script graph, given source text, base URL, settings object, options, and with the following steps given result:
            // FIXME: Pass options
            fetch_inline_module_script_graph(realm(), m_document->url().to_byte_string(), source_text.to_byte_string(), base_url, document().relevant_settings_object(), steps);
        }
        // -> "importmap"
        else if (m_script_type == ScriptType::ImportMap) {
            // 1. Let result be the result of creating an import map parse result given source text and base URL.
            auto result = ImportMapParseResult::create(realm(), source_text.to_byte_string(), base_url);

            // 2. Mark as ready el given result.
            mark_as_ready(Result(move(result)));
        }
        // FIXME: -> "speculationrules"
    }

    // 36. If el's type is "classic" and el has a src attribute, or el's type is "module":
    if ((m_script_type == ScriptType::Classic && has_attribute(HTML::AttributeNames::src)) || m_script_type == ScriptType::Module) {
        // 1. Assert: el's result is "uninitialized".
        // FIXME: I believe this step to be a spec bug, and it should be removed: https://github.com/whatwg/html/issues/8534

        // 2. If el has an async attribute or el's force async is true:
        if (has_attribute(HTML::AttributeNames::async) || m_force_async) {
            // 1. Let scripts be el's preparation-time document's set of scripts that will execute as soon as possible.
            // 2. Append el to scripts.
            m_preparation_time_document->scripts_to_execute_as_soon_as_possible().append(*this);

            // 3. Set el's steps to run when the result is ready to the following:
            m_steps_to_run_when_the_result_is_ready = [this] {
                // 1. Execute the script element el.
                execute_script();

                // 2. Remove el from scripts.
                m_preparation_time_document->scripts_to_execute_as_soon_as_possible().remove_first_matching([this](auto& entry) {
                    return entry.ptr() == this;
                });
            };
        }

        // 3. Otherwise, if el is not parser-inserted:
        else if (!is_parser_inserted()) {