mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-27 20:58:16 +00:00
IDLGenerators: Fix Exposed extended attribute codegen
This commit is contained in:
parent
6812aa00ca
commit
1a7932601a
Notes:
github-actions[bot]
2025-06-30 17:40:34 +00:00
Author: https://github.com/bplaat
Commit: 1a7932601a
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4535
Reviewed-by: https://github.com/ADKaster ✅
Reviewed-by: https://github.com/trflynn89
3 changed files with 89 additions and 10 deletions
|
@ -17,6 +17,7 @@
|
|||
#include <AK/NumericLimits.h>
|
||||
#include <AK/Queue.h>
|
||||
#include <AK/QuickSort.h>
|
||||
#include <LibIDL/ExposedTo.h>
|
||||
#include <LibIDL/Types.h>
|
||||
|
||||
namespace IDL {
|
||||
|
@ -3500,22 +3501,34 @@ void @class_name@::initialize(JS::Realm& realm)
|
|||
)~~~");
|
||||
}
|
||||
|
||||
// NOTE: Add more specified exposed global interface groups when needed.
|
||||
StringBuilder window_exposed_only_members_builder;
|
||||
SourceGenerator window_exposed_only_members_generator { window_exposed_only_members_builder, generator.clone_mapping() };
|
||||
auto generator_for_member = [&](auto const& name, auto& extended_attributes) -> SourceGenerator {
|
||||
if (auto maybe_exposed = extended_attributes.get("Exposed"); maybe_exposed.has_value()) {
|
||||
auto exposed_to = MUST(IDL::parse_exposure_set(name, *maybe_exposed));
|
||||
if (exposed_to == IDL::ExposedTo::Window) {
|
||||
return window_exposed_only_members_generator.fork();
|
||||
}
|
||||
}
|
||||
return generator.fork();
|
||||
};
|
||||
|
||||
// https://webidl.spec.whatwg.org/#es-attributes
|
||||
for (auto& attribute : interface.attributes) {
|
||||
bool has_unforgeable_attribute = attribute.extended_attributes.contains("LegacyUnforgeable"sv);
|
||||
if ((generate_unforgeables == GenerateUnforgeables::Yes && !has_unforgeable_attribute) || (generate_unforgeables == GenerateUnforgeables::No && has_unforgeable_attribute))
|
||||
continue;
|
||||
|
||||
auto attribute_generator = generator_for_member(attribute.name, attribute.extended_attributes);
|
||||
if (attribute.extended_attributes.contains("FIXME")) {
|
||||
auto fixme_attribute_generator = generator.fork();
|
||||
fixme_attribute_generator.set("attribute.name", attribute.name);
|
||||
fixme_attribute_generator.append(R"~~~(
|
||||
attribute_generator.set("attribute.name", attribute.name);
|
||||
attribute_generator.append(R"~~~(
|
||||
@define_direct_property@("@attribute.name@"_fly_string, JS::js_undefined(), default_attributes | JS::Attribute::Unimplemented);
|
||||
)~~~");
|
||||
continue;
|
||||
}
|
||||
|
||||
auto attribute_generator = generator.fork();
|
||||
attribute_generator.set("attribute.name", attribute.name);
|
||||
attribute_generator.set("attribute.getter_callback", attribute.getter_callback_name);
|
||||
|
||||
|
@ -3541,9 +3554,9 @@ void @class_name@::initialize(JS::Realm& realm)
|
|||
continue;
|
||||
|
||||
if (function.extended_attributes.contains("FIXME")) {
|
||||
auto fixme_function_generator = generator.fork();
|
||||
fixme_function_generator.set("function.name", function.name);
|
||||
fixme_function_generator.append(R"~~~(
|
||||
auto function_generator = generator_for_member(function.name, function.extended_attributes);
|
||||
function_generator.set("function.name", function.name);
|
||||
function_generator.append(R"~~~(
|
||||
@define_direct_property@("@function.name@"_fly_string, JS::js_undefined(), default_attributes | JS::Attribute::Unimplemented);
|
||||
)~~~");
|
||||
}
|
||||
|
@ -3572,7 +3585,8 @@ void @class_name@::initialize(JS::Realm& realm)
|
|||
if ((generate_unforgeables == GenerateUnforgeables::Yes && !has_unforgeable_attribute) || (generate_unforgeables == GenerateUnforgeables::No && has_unforgeable_attribute))
|
||||
continue;
|
||||
|
||||
auto function_generator = generator.fork();
|
||||
auto const& function = overload_set.value.first();
|
||||
auto function_generator = generator_for_member(function.name, function.extended_attributes);
|
||||
function_generator.set("function.name", overload_set.key);
|
||||
function_generator.set("function.name:snakecase", make_input_acceptable_cpp(overload_set.key.to_snakecase()));
|
||||
function_generator.set("function.length", ByteString::number(get_shortest_function_length(overload_set.value)));
|
||||
|
@ -3595,10 +3609,11 @@ void @class_name@::initialize(JS::Realm& realm)
|
|||
if ((generate_unforgeables == GenerateUnforgeables::Yes && !has_unforgeable_attribute) || (generate_unforgeables == GenerateUnforgeables::No && has_unforgeable_attribute))
|
||||
should_generate_stringifier = false;
|
||||
}
|
||||
|
||||
if (interface.has_stringifier && should_generate_stringifier) {
|
||||
// FIXME: Do stringifiers need to be added to the unscopable list?
|
||||
auto stringifier_generator = generator.fork();
|
||||
auto stringifier_generator = interface.stringifier_extended_attributes.has_value()
|
||||
? generator_for_member("stringifier"sv, *interface.stringifier_extended_attributes)
|
||||
: generator.fork();
|
||||
stringifier_generator.append(R"~~~(
|
||||
@define_native_function@(realm, "toString"_fly_string, to_string, 0, default_attributes);
|
||||
)~~~");
|
||||
|
@ -3691,6 +3706,16 @@ void @class_name@::initialize(JS::Realm& realm)
|
|||
)~~~");
|
||||
}
|
||||
|
||||
if (!window_exposed_only_members_generator.as_string_view().is_empty()) {
|
||||
auto window_only_property_declarations = generator.fork();
|
||||
window_only_property_declarations.set("defines", window_exposed_only_members_generator.as_string_view());
|
||||
window_only_property_declarations.append(R"~~~(
|
||||
if (is<HTML::Window>(realm.global_object())) {
|
||||
@defines@
|
||||
}
|
||||
)~~~");
|
||||
}
|
||||
|
||||
if (!define_on_existing_object) {
|
||||
generator.append(R"~~~(
|
||||
Base::initialize(realm);
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
1. {"a":1,"b":2,"c":3,"d":4,"e":5,"f":6,"m11":1,"m12":2,"m13":0,"m14":0,"m21":3,"m22":4,"m23":0,"m24":0,"m31":0,"m32":0,"m33":1,"m34":0,"m41":5,"m42":6,"m43":0,"m44":1,"is2D":true,"isIdentity":false}
|
||||
2. "matrix(1, 0, 0, 1, 0, 0)"
|
||||
3. "Google Inc."
|
||||
4. TypeError: undefined is not a function (evaluated from '<object>.setMatrixValue')
|
||||
5. [object DOMMatrix]
|
||||
6. undefined
|
|
@ -0,0 +1,48 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="../include.js"></script>
|
||||
<script>
|
||||
asyncTest(async done => {
|
||||
let testCounter = 1;
|
||||
function testPart(part) {
|
||||
println(`${testCounter++}. ${JSON.stringify(part())}`);
|
||||
}
|
||||
|
||||
// 1. In this Window environment, check if DOMMatrix setMatrixValue is available.
|
||||
testPart(() => new DOMMatrix().setMatrixValue("matrix(1, 2, 3, 4, 5, 6)"));
|
||||
|
||||
// 2. In this Window environment, check if DOMMatrix toString has custom behavior.
|
||||
testPart(() => new DOMMatrix().toString());
|
||||
|
||||
// 3. In this Window environment, check if navigator vendor toString is available.
|
||||
testPart(() => navigator.vendor);
|
||||
|
||||
const worker = new Worker(URL.createObjectURL(new Blob([`
|
||||
// 4. In this new Worker environment, check if DOMMatrix setMatrixValue doesn't exists.
|
||||
try {
|
||||
postMessage(new DOMMatrix().setMatrixValue("matrix(1, 2, 3, 4, 5, 6)"));
|
||||
} catch (error) {
|
||||
postMessage(error);
|
||||
}
|
||||
|
||||
// 5. In this Worker environment, check if DOMMatrix toString doesn't have custom behavior.
|
||||
try {
|
||||
postMessage(new DOMMatrix().toString());
|
||||
} catch (error) {
|
||||
postMessage(error);
|
||||
}
|
||||
|
||||
// 6. In this Worker environment, check if navigator vendor doesn't exists.
|
||||
try {
|
||||
postMessage(navigator.vendor);
|
||||
} catch (error) {
|
||||
postMessage(error);
|
||||
}
|
||||
`], { type: 'application/javascript' })));
|
||||
worker.onmessage = (result) => {
|
||||
println(`${testCounter++}. ${result.data}`);
|
||||
if (testCounter === 7) {
|
||||
done();
|
||||
}
|
||||
};
|
||||
});
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue