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

Code before:
    auto parsed = TRY(Infra::parse_json_string_to_javascript_value(realm, input));

    // 2. If parsed is not an ordered map, then throw a TypeError indicating that the top-level value needs to be a JSON object.
    if (!parsed.is_object() || is<JS::Array>(parsed.as_object()))
        return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "The top-level value of an importmap needs to be a JSON object."_string };
    auto& parsed_object = parsed.as_object();

    // 3. Let sortedAndNormalizedImports be an empty ordered map.
    ModuleSpecifierMap sorted_and_normalized_imports;

    // 4. If parsed["imports"] exists, then:
    if (TRY(parsed_object.has_property("imports"_utf16_fly_string))) {
        auto imports = TRY(parsed_object.get("imports"_utf16_fly_string));

        // 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.
        if (!imports.is_object() || is<JS::Array>(imports.as_object()))
            return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "The 'imports' top-level value of an importmap needs to be a JSON object."_string };

        // Set sortedAndNormalizedImports to the result of sorting and normalizing a module specifier map given parsed["imports"] and baseURL.
        sorted_and_normalized_imports = TRY(sort_and_normalise_module_specifier_map(realm, imports.as_object(), base_url));
    }

    // 5. Let sortedAndNormalizedScopes be an empty ordered map.
    HashMap<URL::URL, ModuleSpecifierMap> sorted_and_normalized_scopes;

    // 6. If parsed["scopes"] exists, then:
    if (TRY(parsed_object.has_property("scopes"_utf16_fly_string))) {
        auto scopes = TRY(parsed_object.get("scopes"_utf16_fly_string));

        // 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.
        if (!scopes.is_object() || is<JS::Array>(scopes.as_object()))
            return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "The 'scopes' top-level value of an importmap needs to be a JSON object."_string };

        // Set sortedAndNormalizedScopes to the result of sorting and normalizing scopes given parsed["scopes"] and baseURL.
        sorted_and_normalized_scopes = TRY(sort_and_normalise_scopes(realm, scopes.as_object(), base_url));
    }

    // 7. Let normalizedIntegrity be an empty ordered map.
    ModuleIntegrityMap normalized_integrity;

    // 8. If parsed["integrity"] exists, then:
    if (TRY(parsed_object.has_property("integrity"_utf16_fly_string))) {
        auto integrity = TRY(parsed_object.get("integrity"_utf16_fly_string));

        // 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.
        if (!integrity.is_object() || is<JS::Array>(integrity.as_object()))
            return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "The 'integrity' top-level value of an importmap needs to be a JSON object."_string };

        // 2. Set normalizedIntegrity to the result of normalizing a module integrity map given parsed["integrity"] and baseURL.
        normalized_integrity = TRY(normalize_module_integrity_map(realm, integrity.as_object(), base_url));
    }

Review comment (suggestion):
not sure, but `null` is also an object… is this valid or we could add it here as an error too?

(i feel that it is the shape that ultimately should be checked, not type… 🤔)

Code after:

// https://html.spec.whatwg.org/multipage/webappapis.html#parse-an-import-map-string
WebIDL::ExceptionOr<ImportMap> parse_import_map_string(JS::Realm& realm, ByteString const& input, URL::URL base_url)
{
    HTML::TemporaryExecutionContext execution_context { realm };

    // 1. Let parsed be the result of parsing a JSON string to an Infra value given input.
    auto parsed = TRY(Infra::parse_json_string_to_javascript_value(realm, input));

    // 2. If parsed is not an ordered map, then throw a TypeError indicating that the top-level value needs to be a JSON object.
    if (!value_is_ordered_map(parsed))
        return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "The top-level value of an importmap needs to be a JSON object."_string };
    auto& parsed_object = parsed.as_object();

    // 3. Let sortedAndNormalizedImports be an empty ordered map.
    ModuleSpecifierMap sorted_and_normalized_imports;

    // 4. If parsed["imports"] exists, then:
    if (TRY(parsed_object.has_property("imports"_utf16_fly_string))) {
        auto imports = TRY(parsed_object.get("imports"_utf16_fly_string));

        // 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.
        if (!value_is_ordered_map(imports))
            return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "The 'imports' top-level value of an importmap needs to be a JSON object."_string };

        // Set sortedAndNormalizedImports to the result of sorting and normalizing a module specifier map given parsed["imports"] and baseURL.
        sorted_and_normalized_imports = TRY(sort_and_normalise_module_specifier_map(realm, imports.as_object(), base_url));
    }

    // 5. Let sortedAndNormalizedScopes be an empty ordered map.
    HashMap<URL::URL, ModuleSpecifierMap> sorted_and_normalized_scopes;

    // 6. If parsed["scopes"] exists, then:
    if (TRY(parsed_object.has_property("scopes"_utf16_fly_string))) {
        auto scopes = TRY(parsed_object.get("scopes"_utf16_fly_string));

        // 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.
        if (!value_is_ordered_map(scopes))
            return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "The 'scopes' top-level value of an importmap needs to be a JSON object."_string };

        // Set sortedAndNormalizedScopes to the result of sorting and normalizing scopes given parsed["scopes"] and baseURL.
        sorted_and_normalized_scopes = TRY(sort_and_normalise_scopes(realm, scopes.as_object(), base_url));
    }

    // 7. Let normalizedIntegrity be an empty ordered map.
    ModuleIntegrityMap normalized_integrity;

    // 8. If parsed["integrity"] exists, then:
    if (TRY(parsed_object.has_property("integrity"_utf16_fly_string))) {
        auto integrity = TRY(parsed_object.get("integrity"_utf16_fly_string));