mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-05 01:10:24 +00:00
committed by
Ali Mohammad Pur
parent
8c9c2ee289
commit
57ef949b61
Notes:
github-actions[bot]
2025-11-01 16:50:59 +00:00
Author: https://github.com/alimpfard Commit: https://github.com/LadybirdBrowser/ladybird/commit/57ef949b61e Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6662
@@ -430,9 +430,18 @@ static bool has_overlap(Vector<CompareTypeAndValuePair> const& lhs, Vector<Compa
|
|||||||
temporary_inverse = false;
|
temporary_inverse = false;
|
||||||
reset_temporary_inverse = false;
|
reset_temporary_inverse = false;
|
||||||
inverse = false;
|
inverse = false;
|
||||||
auto in_or = false; // We're in an OR block, so we should wait for the EndAndOr to decide if we would match.
|
struct DisjunctionState {
|
||||||
auto matched_in_or = false;
|
bool in_or = false; // We're in an OR block, so we should wait for the EndAndOr to decide if we would match.
|
||||||
auto inverse_matched_in_or = false;
|
bool matched_in_or = false;
|
||||||
|
bool inverse_matched_in_or = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
Vector<DisjunctionState, 2> disjunction_stack;
|
||||||
|
disjunction_stack.empend();
|
||||||
|
|
||||||
|
auto in_or = [&] -> bool& { return disjunction_stack.last().in_or; };
|
||||||
|
auto matched_in_or = [&] -> bool& { return disjunction_stack.last().matched_in_or; };
|
||||||
|
auto inverse_matched_in_or = [&] -> bool& { return disjunction_stack.last().inverse_matched_in_or; };
|
||||||
|
|
||||||
for (auto const& pair : rhs) {
|
for (auto const& pair : rhs) {
|
||||||
if (reset_temporary_inverse) {
|
if (reset_temporary_inverse) {
|
||||||
@@ -452,7 +461,7 @@ static bool has_overlap(Vector<CompareTypeAndValuePair> const& lhs, Vector<Compa
|
|||||||
dbgln(" {}", character_class_name(char_class));
|
dbgln(" {}", character_class_name(char_class));
|
||||||
for (auto& char_class : lhs_negated_char_classes)
|
for (auto& char_class : lhs_negated_char_classes)
|
||||||
dbgln(" ^{}", character_class_name(char_class));
|
dbgln(" ^{}", character_class_name(char_class));
|
||||||
dbgln("}}, in or: {}, matched in or: {}, inverse matched in or: {}", in_or, matched_in_or, inverse_matched_in_or);
|
dbgln("}}, in or: {}, matched in or: {}, inverse matched in or: {}", in_or(), matched_in_or(), inverse_matched_in_or());
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (pair.type) {
|
switch (pair.type) {
|
||||||
@@ -465,20 +474,20 @@ static bool has_overlap(Vector<CompareTypeAndValuePair> const& lhs, Vector<Compa
|
|||||||
break;
|
break;
|
||||||
case CharacterCompareType::AnyChar:
|
case CharacterCompareType::AnyChar:
|
||||||
// Special case: if not inverted, AnyChar is always in the range.
|
// Special case: if not inverted, AnyChar is always in the range.
|
||||||
if (!in_or && !current_lhs_inversion_state())
|
if (!in_or() && !current_lhs_inversion_state())
|
||||||
return true;
|
return true;
|
||||||
if (in_or) {
|
if (in_or()) {
|
||||||
matched_in_or = true;
|
matched_in_or() = true;
|
||||||
inverse_matched_in_or = false;
|
inverse_matched_in_or() = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CharacterCompareType::Char: {
|
case CharacterCompareType::Char: {
|
||||||
auto matched = range_contains(pair.value);
|
auto matched = range_contains(pair.value);
|
||||||
if (!in_or && (current_lhs_inversion_state() ^ matched))
|
if (!in_or() && (current_lhs_inversion_state() ^ matched))
|
||||||
return true;
|
return true;
|
||||||
if (in_or) {
|
if (in_or()) {
|
||||||
matched_in_or |= matched;
|
matched_in_or() |= matched;
|
||||||
inverse_matched_in_or |= !matched;
|
inverse_matched_in_or() |= !matched;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -488,23 +497,23 @@ static bool has_overlap(Vector<CompareTypeAndValuePair> const& lhs, Vector<Compa
|
|||||||
return true;
|
return true;
|
||||||
case CharacterCompareType::CharClass: {
|
case CharacterCompareType::CharClass: {
|
||||||
auto contains = char_class_contains(static_cast<CharClass>(pair.value));
|
auto contains = char_class_contains(static_cast<CharClass>(pair.value));
|
||||||
if (!in_or && (current_lhs_inversion_state() ^ contains))
|
if (!in_or() && (current_lhs_inversion_state() ^ contains))
|
||||||
return true;
|
return true;
|
||||||
if (in_or) {
|
if (in_or()) {
|
||||||
matched_in_or |= contains;
|
matched_in_or() |= contains;
|
||||||
inverse_matched_in_or |= !contains;
|
inverse_matched_in_or() |= !contains;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CharacterCompareType::CharRange: {
|
case CharacterCompareType::CharRange: {
|
||||||
auto range = CharRange(pair.value);
|
auto range = CharRange(pair.value);
|
||||||
auto contains = range_contains(range);
|
auto contains = range_contains(range);
|
||||||
if (!in_or && (contains ^ current_lhs_inversion_state()))
|
if (!in_or() && (contains ^ current_lhs_inversion_state()))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (in_or) {
|
if (in_or()) {
|
||||||
matched_in_or |= contains;
|
matched_in_or() |= contains;
|
||||||
inverse_matched_in_or |= !contains;
|
inverse_matched_in_or() |= !contains;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -525,16 +534,16 @@ static bool has_overlap(Vector<CompareTypeAndValuePair> const& lhs, Vector<Compa
|
|||||||
return true;
|
return true;
|
||||||
if (has_any_unicode_property && !lhs_unicode_properties.is_empty() && !lhs_negated_unicode_properties.is_empty()) {
|
if (has_any_unicode_property && !lhs_unicode_properties.is_empty() && !lhs_negated_unicode_properties.is_empty()) {
|
||||||
auto contains = lhs_unicode_properties.contains(static_cast<Unicode::Property>(pair.value));
|
auto contains = lhs_unicode_properties.contains(static_cast<Unicode::Property>(pair.value));
|
||||||
if (!in_or && (current_lhs_inversion_state() ^ contains))
|
if (!in_or() && (current_lhs_inversion_state() ^ contains))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
auto inverse_contains = lhs_negated_unicode_properties.contains(static_cast<Unicode::Property>(pair.value));
|
auto inverse_contains = lhs_negated_unicode_properties.contains(static_cast<Unicode::Property>(pair.value));
|
||||||
if (!in_or && !(current_lhs_inversion_state() ^ inverse_contains))
|
if (!in_or() && !(current_lhs_inversion_state() ^ inverse_contains))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (in_or) {
|
if (in_or()) {
|
||||||
matched_in_or |= contains;
|
matched_in_or() |= contains;
|
||||||
inverse_matched_in_or |= inverse_contains;
|
inverse_matched_in_or() |= inverse_contains;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -543,14 +552,14 @@ static bool has_overlap(Vector<CompareTypeAndValuePair> const& lhs, Vector<Compa
|
|||||||
return true;
|
return true;
|
||||||
if (has_any_unicode_property && !lhs_unicode_general_categories.is_empty() && !lhs_negated_unicode_general_categories.is_empty()) {
|
if (has_any_unicode_property && !lhs_unicode_general_categories.is_empty() && !lhs_negated_unicode_general_categories.is_empty()) {
|
||||||
auto contains = lhs_unicode_general_categories.contains(static_cast<Unicode::GeneralCategory>(pair.value));
|
auto contains = lhs_unicode_general_categories.contains(static_cast<Unicode::GeneralCategory>(pair.value));
|
||||||
if (!in_or && (current_lhs_inversion_state() ^ contains))
|
if (!in_or() && (current_lhs_inversion_state() ^ contains))
|
||||||
return true;
|
return true;
|
||||||
auto inverse_contains = lhs_negated_unicode_general_categories.contains(static_cast<Unicode::GeneralCategory>(pair.value));
|
auto inverse_contains = lhs_negated_unicode_general_categories.contains(static_cast<Unicode::GeneralCategory>(pair.value));
|
||||||
if (!in_or && !(current_lhs_inversion_state() ^ inverse_contains))
|
if (!in_or() && !(current_lhs_inversion_state() ^ inverse_contains))
|
||||||
return true;
|
return true;
|
||||||
if (in_or) {
|
if (in_or()) {
|
||||||
matched_in_or |= contains;
|
matched_in_or() |= contains;
|
||||||
inverse_matched_in_or |= inverse_contains;
|
inverse_matched_in_or() |= inverse_contains;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -559,14 +568,14 @@ static bool has_overlap(Vector<CompareTypeAndValuePair> const& lhs, Vector<Compa
|
|||||||
return true;
|
return true;
|
||||||
if (has_any_unicode_property && !lhs_unicode_scripts.is_empty() && !lhs_negated_unicode_scripts.is_empty()) {
|
if (has_any_unicode_property && !lhs_unicode_scripts.is_empty() && !lhs_negated_unicode_scripts.is_empty()) {
|
||||||
auto contains = lhs_unicode_scripts.contains(static_cast<Unicode::Script>(pair.value));
|
auto contains = lhs_unicode_scripts.contains(static_cast<Unicode::Script>(pair.value));
|
||||||
if (!in_or && (current_lhs_inversion_state() ^ contains))
|
if (!in_or() && (current_lhs_inversion_state() ^ contains))
|
||||||
return true;
|
return true;
|
||||||
auto inverse_contains = lhs_negated_unicode_scripts.contains(static_cast<Unicode::Script>(pair.value));
|
auto inverse_contains = lhs_negated_unicode_scripts.contains(static_cast<Unicode::Script>(pair.value));
|
||||||
if (!in_or && !(current_lhs_inversion_state() ^ inverse_contains))
|
if (!in_or() && !(current_lhs_inversion_state() ^ inverse_contains))
|
||||||
return true;
|
return true;
|
||||||
if (in_or) {
|
if (in_or()) {
|
||||||
matched_in_or |= contains;
|
matched_in_or() |= contains;
|
||||||
inverse_matched_in_or |= inverse_contains;
|
inverse_matched_in_or() |= inverse_contains;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -575,33 +584,34 @@ static bool has_overlap(Vector<CompareTypeAndValuePair> const& lhs, Vector<Compa
|
|||||||
return true;
|
return true;
|
||||||
if (has_any_unicode_property && !lhs_unicode_script_extensions.is_empty() && !lhs_negated_unicode_script_extensions.is_empty()) {
|
if (has_any_unicode_property && !lhs_unicode_script_extensions.is_empty() && !lhs_negated_unicode_script_extensions.is_empty()) {
|
||||||
auto contains = lhs_unicode_script_extensions.contains(static_cast<Unicode::Script>(pair.value));
|
auto contains = lhs_unicode_script_extensions.contains(static_cast<Unicode::Script>(pair.value));
|
||||||
if (!in_or && (current_lhs_inversion_state() ^ contains))
|
if (!in_or() && (current_lhs_inversion_state() ^ contains))
|
||||||
return true;
|
return true;
|
||||||
auto inverse_contains = lhs_negated_unicode_script_extensions.contains(static_cast<Unicode::Script>(pair.value));
|
auto inverse_contains = lhs_negated_unicode_script_extensions.contains(static_cast<Unicode::Script>(pair.value));
|
||||||
if (!in_or && !(current_lhs_inversion_state() ^ inverse_contains))
|
if (!in_or() && !(current_lhs_inversion_state() ^ inverse_contains))
|
||||||
return true;
|
return true;
|
||||||
if (in_or) {
|
if (in_or()) {
|
||||||
matched_in_or |= contains;
|
matched_in_or() |= contains;
|
||||||
inverse_matched_in_or |= inverse_contains;
|
inverse_matched_in_or() |= inverse_contains;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CharacterCompareType::Or:
|
case CharacterCompareType::Or:
|
||||||
in_or = true;
|
disjunction_stack.empend(true);
|
||||||
break;
|
break;
|
||||||
case CharacterCompareType::EndAndOr:
|
case CharacterCompareType::EndAndOr: {
|
||||||
// FIXME: Handle And when we support it below.
|
// FIXME: Handle And when we support it below.
|
||||||
VERIFY(in_or);
|
VERIFY(in_or());
|
||||||
in_or = false;
|
auto state = disjunction_stack.take_last();
|
||||||
if (current_lhs_inversion_state()) {
|
if (current_lhs_inversion_state()) {
|
||||||
if (!inverse_matched_in_or)
|
if (!state.inverse_matched_in_or)
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
if (matched_in_or)
|
if (state.matched_in_or)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case CharacterCompareType::And:
|
case CharacterCompareType::And:
|
||||||
// FIXME: These are too difficult to handle, so bail out.
|
// FIXME: These are too difficult to handle, so bail out.
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -738,6 +738,9 @@ TEST_CASE(ECMA262_match)
|
|||||||
{ "((?<x>a)|(?<x>b))"sv, "aa"sv, false },
|
{ "((?<x>a)|(?<x>b))"sv, "aa"sv, false },
|
||||||
// Insensitive charclasses should accept upper/lowercase in pattern (lookup table should still be ordered if insensitive lookup is used), ladybird#5399.
|
// Insensitive charclasses should accept upper/lowercase in pattern (lookup table should still be ordered if insensitive lookup is used), ladybird#5399.
|
||||||
{ "[aBc]"sv, "b"sv, true, ECMAScriptFlags::Insensitive },
|
{ "[aBc]"sv, "b"sv, true, ECMAScriptFlags::Insensitive },
|
||||||
|
// Optimizer bug: nested 'or' compare ops caused a crash, ladybird#6647.
|
||||||
|
{ "([[[]]])*0"sv, ""sv, false, ECMAScriptFlags::UnicodeSets },
|
||||||
|
{ "(([[[]]]{2,})\\s)*"sv, ""sv, true, (ECMAScriptFlags::UnicodeSets | ECMAScriptFlags::Global).value() },
|
||||||
};
|
};
|
||||||
|
|
||||||
for (auto& test : tests) {
|
for (auto& test : tests) {
|
||||||
|
|||||||
Reference in New Issue
Block a user