diff --git a/Userland/Libraries/LibWeb/Bindings/CSSNamespace.cpp b/Userland/Libraries/LibWeb/Bindings/CSSNamespace.cpp deleted file mode 100644 index 8db43b2672..0000000000 --- a/Userland/Libraries/LibWeb/Bindings/CSSNamespace.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2021-2023, Sam Atkins - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include - -namespace Web::Bindings { - -CSSNamespace::CSSNamespace(JS::Realm& realm) - : JS::Object(ConstructWithPrototypeTag::Tag, *realm.intrinsics().object_prototype()) -{ -} - -JS::ThrowCompletionOr CSSNamespace::initialize(JS::Realm& realm) -{ - MUST_OR_THROW_OOM(Object::initialize(realm)); - u8 attr = JS::Attribute::Enumerable; - define_native_function(realm, "escape", escape, 1, attr); - define_native_function(realm, "supports", supports, 2, attr); - - return {}; -} - -// https://www.w3.org/TR/cssom-1/#dom-css-escape -JS_DEFINE_NATIVE_FUNCTION(CSSNamespace::escape) -{ - if (!vm.argument_count()) - return vm.throw_completion(JS::ErrorType::BadArgCountAtLeastOne, "CSS.escape"); - - auto identifier = TRY(vm.argument(0).to_string(vm)); - return JS::PrimitiveString::create(vm, TRY_OR_THROW_OOM(vm, Web::CSS::serialize_an_identifier(identifier))); -} - -// https://www.w3.org/TR/css-conditional-3/#dom-css-supports -JS_DEFINE_NATIVE_FUNCTION(CSSNamespace::supports) -{ - auto& realm = *vm.current_realm(); - - if (!vm.argument_count()) - return vm.throw_completion(JS::ErrorType::BadArgCountAtLeastOne, "CSS.supports"); - - if (vm.argument_count() >= 2) { - // When the supports(property, value) method is invoked with two arguments property and value: - auto property_name = TRY(vm.argument(0).to_deprecated_string(vm)); - - // If property is an ASCII case-insensitive match for any defined CSS property that the UA supports, - // and value successfully parses according to that property’s grammar, return true. - auto property = CSS::property_id_from_string(property_name); - if (property != CSS::PropertyID::Invalid) { - auto value_string = TRY(vm.argument(1).to_deprecated_string(vm)); - if (parse_css_value(CSS::Parser::ParsingContext { realm }, value_string, property)) - return JS::Value(true); - } - // Otherwise, if property is a custom property name string, return true. - // FIXME: This check is not enough to make sure this is a valid custom property name, but it's close enough. - else if (property_name.starts_with("--"sv) && property_name.length() >= 3) { - return JS::Value(true); - } - - // Otherwise, return false. - return JS::Value(false); - } else { - // When the supports(conditionText) method is invoked with a single conditionText argument: - auto supports_text = TRY(vm.argument(0).to_deprecated_string(vm)); - - // If conditionText, parsed and evaluated as a , would return true, return true. - if (auto supports = parse_css_supports(CSS::Parser::ParsingContext { realm }, supports_text); supports && supports->matches()) - return JS::Value(true); - - // Otherwise, If conditionText, wrapped in parentheses and then parsed and evaluated as a , would return true, return true. - if (auto supports = parse_css_supports(CSS::Parser::ParsingContext { realm }, DeprecatedString::formatted("({})", supports_text)); supports && supports->matches()) - return JS::Value(true); - - // Otherwise, return false. - return JS::Value(false); - } -} - -} diff --git a/Userland/Libraries/LibWeb/Bindings/CSSNamespace.h b/Userland/Libraries/LibWeb/Bindings/CSSNamespace.h deleted file mode 100644 index 2466ed9c6b..0000000000 --- a/Userland/Libraries/LibWeb/Bindings/CSSNamespace.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2021, Sam Atkins - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include - -namespace Web::Bindings { - -// The `CSS` namespace object in IDL. https://www.w3.org/TR/cssom-1/#namespacedef-css -class CSSNamespace final : public JS::Object { - JS_OBJECT(CSSNamespace, JS::Object) - -public: - explicit CSSNamespace(JS::Realm&); - virtual JS::ThrowCompletionOr initialize(JS::Realm&) override; - virtual ~CSSNamespace() override = default; - -private: - JS_DECLARE_NATIVE_FUNCTION(escape); - JS_DECLARE_NATIVE_FUNCTION(supports); -}; - -} diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 216eebcc17..cdf5bcd2b8 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -5,7 +5,6 @@ set(SOURCES ARIA/ARIAMixin.idl ARIA/Roles.cpp Bindings/AudioConstructor.cpp - Bindings/CSSNamespace.cpp Bindings/HostDefined.cpp Bindings/ImageConstructor.cpp Bindings/Intrinsics.cpp @@ -18,6 +17,7 @@ set(SOURCES Crypto/SubtleCrypto.cpp CSS/Angle.cpp CSS/Clip.cpp + CSS/CSS.cpp CSS/CSSConditionRule.cpp CSS/CSSGroupingRule.cpp CSS/CSSImportRule.cpp diff --git a/Userland/Libraries/LibWeb/CSS/CSS.cpp b/Userland/Libraries/LibWeb/CSS/CSS.cpp new file mode 100644 index 0000000000..925e89a7c6 --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/CSS.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021-2023, Sam Atkins + * Copyright (c) 2023, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include + +namespace Web::CSS { + +// https://www.w3.org/TR/cssom-1/#dom-css-escape +WebIDL::ExceptionOr escape(JS::VM& vm, StringView identifier) +{ + // The escape(ident) operation must return the result of invoking serialize an identifier of ident. + return TRY_OR_THROW_OOM(vm, serialize_an_identifier(identifier)); +} + +// https://www.w3.org/TR/css-conditional-3/#dom-css-supports +bool supports(JS::VM& vm, StringView property, StringView value) +{ + auto& realm = *vm.current_realm(); + + // 1. If property is an ASCII case-insensitive match for any defined CSS property that the UA supports, + // and value successfully parses according to that property’s grammar, return true. + if (auto property_id = property_id_from_string(property); property_id != PropertyID::Invalid) { + if (parse_css_value(Parser::ParsingContext { realm }, value, property_id)) + return true; + } + + // 2. Otherwise, if property is a custom property name string, return true. + // FIXME: This check is not enough to make sure this is a valid custom property name, but it's close enough. + else if (property.starts_with("--"sv) && property.length() >= 3) { + return true; + } + + // 3. Otherwise, return false. + return false; +} + +// https://www.w3.org/TR/css-conditional-3/#dom-css-supports +WebIDL::ExceptionOr supports(JS::VM& vm, StringView condition_text) +{ + auto& realm = *vm.current_realm(); + + // 1. If conditionText, parsed and evaluated as a , would return true, return true. + if (auto supports = parse_css_supports(Parser::ParsingContext { realm }, condition_text); supports && supports->matches()) + return true; + + // 2. Otherwise, If conditionText, wrapped in parentheses and then parsed and evaluated as a , would return true, return true. + auto wrapped_condition_text = TRY_OR_THROW_OOM(vm, String::formatted("({})", condition_text)); + + if (auto supports = parse_css_supports(Parser::ParsingContext { realm }, wrapped_condition_text); supports && supports->matches()) + return true; + + // 3. Otherwise, return false. + return false; +} + +} diff --git a/Userland/Libraries/LibWeb/CSS/CSS.h b/Userland/Libraries/LibWeb/CSS/CSS.h new file mode 100644 index 0000000000..eb84f7b1de --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/CSS.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021, Sam Atkins + * Copyright (c) 2023, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include + +// https://www.w3.org/TR/cssom-1/#namespacedef-css +namespace Web::CSS { + +WebIDL::ExceptionOr escape(JS::VM&, StringView identifier); + +bool supports(JS::VM&, StringView property, StringView value); +WebIDL::ExceptionOr supports(JS::VM&, StringView condition_text); + +} diff --git a/Userland/Libraries/LibWeb/CSS/CSS.idl b/Userland/Libraries/LibWeb/CSS/CSS.idl new file mode 100644 index 0000000000..77e87a523f --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/CSS.idl @@ -0,0 +1,8 @@ +// https://www.w3.org/TR/cssom-1/#namespacedef-css +[Exposed=Window] +namespace CSS { + CSSOMString escape(CSSOMString ident); + + boolean supports(CSSOMString property, CSSOMString value); + boolean supports(CSSOMString conditionText); +}; diff --git a/Userland/Libraries/LibWeb/HTML/Window.cpp b/Userland/Libraries/LibWeb/HTML/Window.cpp index fa4276e807..88a78e22b0 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.cpp +++ b/Userland/Libraries/LibWeb/HTML/Window.cpp @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -753,7 +752,6 @@ WebIDL::ExceptionOr Window::initialize_web_interfaces(Badge(realm, realm))); create_method_property("WebAssembly", MUST_OR_THROW_OOM(heap().allocate(realm, realm))); return {}; diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index 39f39c242b..bbb10269a9 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -8,6 +8,7 @@ libweb_js_bindings(CSS/CSSFontFaceRule) libweb_js_bindings(CSS/CSSGroupingRule) libweb_js_bindings(CSS/CSSImportRule) libweb_js_bindings(CSS/CSSMediaRule) +libweb_js_bindings(CSS/CSS NAMESPACE) libweb_js_bindings(CSS/CSSRule) libweb_js_bindings(CSS/CSSRuleList) libweb_js_bindings(CSS/CSSStyleDeclaration)