Repository: LadybirdBrowser/ladybird
File: Libraries/LibWeb/CSS/Fetch.cpp (C++)

Code before:
 */

#include <LibWeb/CSS/CSSStyleSheet.h>
#include <LibWeb/CSS/Fetch.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOMURL/DOMURL.h>
#include <LibWeb/Fetch/Fetching/Fetching.h>
#include <LibWeb/HTML/SharedResourceRequest.h>
#include <LibWeb/Painting/ViewportPaintable.h>

namespace Web::CSS {

// https://drafts.csswg.org/css-values-4/#style-resource-base-url

struct StyleSheetAndURL {
    GC::Ptr<CSSStyleSheet> sheet;
    ::URL::URL url;
};
static StyleSheetAndURL style_resource_base_url(RuleOrDeclaration css_rule_or_declaration)
{
    // 1. Let sheet be null.
    GC::Ptr<CSSStyleSheet> sheet;

    // 2. If cssRuleOrDeclaration is a CSS declaration block whose parent CSS rule is not null, set cssRuleOrDeclaration to cssRuleOrDeclaration’s parent CSS rule.
    if (css_rule_or_declaration.value.has<RuleOrDeclaration::StyleDeclaration>()) {
        auto& declaration = css_rule_or_declaration.value.get<RuleOrDeclaration::StyleDeclaration>();
        if (declaration.parent_rule)
            css_rule_or_declaration.value = RuleOrDeclaration::Rule { declaration.parent_rule->parent_style_sheet() };
    }

    // 3. If cssRuleOrDeclaration is a CSS rule, set sheet to cssRuleOrDeclaration’s parent style sheet.
    if (css_rule_or_declaration.value.has<RuleOrDeclaration::Rule>()) {
        auto& rule = css_rule_or_declaration.value.get<RuleOrDeclaration::Rule>();
        if (rule.parent_style_sheet) {
            sheet = rule.parent_style_sheet;
        }
    }

    // 4. If sheet is not null:
    if (sheet) {
        // 1. If sheet’s stylesheet base URL is not null, return sheet’s stylesheet base URL.
        if (auto base_url = sheet->base_url(); base_url.has_value())
            return { sheet, base_url.value() };

        // 2. If sheet’s location is not null, return sheet’s location.
        if (auto location = sheet->location(); location.has_value())
            return { sheet, location.value() };
    }

    // 5. Return cssRuleOrDeclaration’s relevant settings object’s API base URL.
    return { sheet, css_rule_or_declaration.environment_settings_object->api_base_url() };

Review comment (performance):
Using `get_pointer<RuleOrDeclaration::StyleDeclaration>()` would reduce the code a bit, and IIRC also avoids some expensive variant code running twice. You could also combine this and step 3 into a `visit()` but that's a bit harder to read.

Code after:
 */

#include <LibWeb/CSS/CSSStyleSheet.h>
#include <LibWeb/CSS/Fetch.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOMURL/DOMURL.h>
#include <LibWeb/Fetch/Fetching/Fetching.h>
#include <LibWeb/HTML/SharedResourceRequest.h>
#include <LibWeb/Painting/ViewportPaintable.h>

namespace Web::CSS {

// https://drafts.csswg.org/css-values-4/#style-resource-base-url

struct StyleSheetAndURL {
    GC::Ptr<CSSStyleSheet> sheet;
    ::URL::URL url;
};
static StyleSheetAndURL style_resource_base_url(RuleOrDeclaration css_rule_or_declaration)
{
    // 1. Let sheet be null.
    GC::Ptr<CSSStyleSheet> sheet;

    // 2. If cssRuleOrDeclaration is a CSS declaration block whose parent CSS rule is not null, set cssRuleOrDeclaration to cssRuleOrDeclaration’s parent CSS rule.
    if (auto* block = css_rule_or_declaration.value.get_pointer<RuleOrDeclaration::StyleDeclaration>()) {
        if (block->parent_rule)
            css_rule_or_declaration.value = RuleOrDeclaration::Rule { block->parent_rule->parent_style_sheet() };
    }

    // 3. If cssRuleOrDeclaration is a CSS rule, set sheet to cssRuleOrDeclaration’s parent style sheet.
    if (auto* rule = css_rule_or_declaration.value.get_pointer<RuleOrDeclaration::Rule>()) {
        if (rule->parent_style_sheet) {
            sheet = rule->parent_style_sheet;
        }
    }

    // 4. If sheet is not null:
    if (sheet) {
        // 1. If sheet’s stylesheet base URL is not null, return sheet’s stylesheet base URL.
        if (auto base_url = sheet->base_url(); base_url.has_value())
            return { sheet, base_url.value() };

        // 2. If sheet’s location is not null, return sheet’s location.
        if (auto location = sheet->location(); location.has_value())
            return { sheet, location.value() };
    }

    // 5. Return cssRuleOrDeclaration’s relevant settings object’s API base URL.
    return { sheet, css_rule_or_declaration.environment_settings_object->api_base_url() };
}