mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-30 08:41:15 +00:00
LibJS: Replace GlobalObject with VM in RegExp AOs [Part 9/19]
This commit is contained in:
parent
d74f8039eb
commit
f0b793db74
Notes:
sideshowbarker
2024-07-17 08:00:23 +09:00
Author: https://github.com/linusg Commit: https://github.com/SerenityOS/serenity/commit/f0b793db74 Pull-request: https://github.com/SerenityOS/serenity/pull/14973 Reviewed-by: https://github.com/davidot ✅
|
@ -243,10 +243,12 @@ ThrowCompletionOr<void> NewObject::execute_impl(Bytecode::Interpreter& interpret
|
|||
|
||||
ThrowCompletionOr<void> NewRegExp::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||
{
|
||||
auto& vm = interpreter.vm();
|
||||
|
||||
auto source = interpreter.current_executable().get_string(m_source_index);
|
||||
auto flags = interpreter.current_executable().get_string(m_flags_index);
|
||||
|
||||
interpreter.accumulator() = TRY(regexp_create(interpreter.global_object(), js_string(interpreter.vm(), source), js_string(interpreter.vm(), flags)));
|
||||
interpreter.accumulator() = TRY(regexp_create(vm, js_string(vm, source), js_string(vm, flags)));
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,6 @@ ThrowCompletionOr<Value> RegExpConstructor::call()
|
|||
ThrowCompletionOr<Object*> RegExpConstructor::construct(FunctionObject&)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
auto pattern = vm.argument(0);
|
||||
auto flags = vm.argument(1);
|
||||
|
@ -83,7 +82,7 @@ ThrowCompletionOr<Object*> RegExpConstructor::construct(FunctionObject&)
|
|||
flags_value = flags;
|
||||
}
|
||||
|
||||
return TRY(regexp_create(global_object, pattern_value, flags_value));
|
||||
return TRY(regexp_create(vm, pattern_value, flags_value));
|
||||
}
|
||||
|
||||
// 22.2.4.2 get RegExp [ @@species ], https://tc39.es/ecma262/#sec-get-regexp-@@species
|
||||
|
|
|
@ -154,10 +154,8 @@ void RegExpObject::initialize(Realm& realm)
|
|||
}
|
||||
|
||||
// 22.2.3.2.2 RegExpInitialize ( obj, pattern, flags ), https://tc39.es/ecma262/#sec-regexpinitialize
|
||||
ThrowCompletionOr<RegExpObject*> RegExpObject::regexp_initialize(GlobalObject& global_object, Value pattern, Value flags)
|
||||
ThrowCompletionOr<RegExpObject*> RegExpObject::regexp_initialize(VM& vm, Value pattern, Value flags)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
|
||||
String f;
|
||||
if (flags.is_undefined()) {
|
||||
f = String::empty();
|
||||
|
@ -205,11 +203,11 @@ String RegExpObject::escape_regexp_pattern() const
|
|||
}
|
||||
|
||||
// 22.2.3.2.4 RegExpCreate ( P, F ), https://tc39.es/ecma262/#sec-regexpcreate
|
||||
ThrowCompletionOr<RegExpObject*> regexp_create(GlobalObject& global_object, Value pattern, Value flags)
|
||||
ThrowCompletionOr<RegExpObject*> regexp_create(VM& vm, Value pattern, Value flags)
|
||||
{
|
||||
auto& realm = *global_object.associated_realm();
|
||||
auto& realm = *vm.current_realm();
|
||||
auto* regexp_object = RegExpObject::create(realm);
|
||||
return TRY(regexp_object->regexp_initialize(global_object, pattern, flags));
|
||||
return TRY(regexp_object->regexp_initialize(vm, pattern, flags));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
namespace JS {
|
||||
|
||||
ThrowCompletionOr<RegExpObject*> regexp_create(GlobalObject&, Value pattern, Value flags);
|
||||
ThrowCompletionOr<RegExpObject*> regexp_create(VM&, Value pattern, Value flags);
|
||||
|
||||
Result<regex::RegexOptions<ECMAScriptFlags>, String> regex_flags_from_string(StringView flags);
|
||||
struct ParseRegexPatternError {
|
||||
|
@ -42,7 +42,7 @@ public:
|
|||
RegExpObject(Object& prototype);
|
||||
RegExpObject(Regex<ECMA262> regex, String pattern, String flags, Object& prototype);
|
||||
|
||||
ThrowCompletionOr<RegExpObject*> regexp_initialize(GlobalObject&, Value pattern, Value flags);
|
||||
ThrowCompletionOr<RegExpObject*> regexp_initialize(VM&, Value pattern, Value flags);
|
||||
String escape_regexp_pattern() const;
|
||||
|
||||
virtual void initialize(Realm&) override;
|
||||
|
|
|
@ -52,10 +52,8 @@ void RegExpPrototype::initialize(Realm& realm)
|
|||
}
|
||||
|
||||
// Non-standard abstraction around steps used by multiple prototypes.
|
||||
static ThrowCompletionOr<void> increment_last_index(GlobalObject& global_object, Object& regexp_object, Utf16View const& string, bool unicode)
|
||||
static ThrowCompletionOr<void> increment_last_index(VM& vm, Object& regexp_object, Utf16View const& string, bool unicode)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
|
||||
// Let thisIndex be ℝ(? ToLength(? Get(rx, "lastIndex"))).
|
||||
auto last_index_value = TRY(regexp_object.get(vm.names.lastIndex));
|
||||
auto last_index = TRY(last_index_value.to_length(vm));
|
||||
|
@ -80,9 +78,9 @@ struct Match {
|
|||
};
|
||||
|
||||
// 22.2.5.2.7 GetMatchIndexPair ( S, match ), https://tc39.es/ecma262/#sec-getmatchindexpair
|
||||
static Value get_match_index_par(GlobalObject& global_object, Utf16View const& string, Match const& match)
|
||||
static Value get_match_index_par(VM& vm, Utf16View const& string, Match const& match)
|
||||
{
|
||||
auto& realm = *global_object.associated_realm();
|
||||
auto& realm = *vm.current_realm();
|
||||
|
||||
// 1. Assert: match.[[StartIndex]] is an integer value ≥ 0 and ≤ the length of S.
|
||||
VERIFY(match.start_index <= string.length_in_code_units());
|
||||
|
@ -96,7 +94,7 @@ static Value get_match_index_par(GlobalObject& global_object, Utf16View const& s
|
|||
}
|
||||
|
||||
// 22.2.5.2.8 MakeMatchIndicesIndexPairArray ( S, indices, groupNames, hasGroups ), https://tc39.es/ecma262/#sec-makematchindicesindexpairarray
|
||||
static Value make_match_indices_index_pair_array(GlobalObject& global_object, Utf16View const& string, Vector<Optional<Match>> const& indices, HashMap<FlyString, Match> const& group_names, bool has_groups)
|
||||
static Value make_match_indices_index_pair_array(VM& vm, Utf16View const& string, Vector<Optional<Match>> const& indices, HashMap<FlyString, Match> const& group_names, bool has_groups)
|
||||
{
|
||||
// Note: This implementation differs from the spec, but has the same behavior.
|
||||
//
|
||||
|
@ -112,8 +110,7 @@ static Value make_match_indices_index_pair_array(GlobalObject& global_object, Ut
|
|||
// Therefore, this implementation tracks the group names without the assertion that the group
|
||||
// names align with the indices. The end result is the same.
|
||||
|
||||
auto& vm = global_object.vm();
|
||||
auto& realm = *global_object.associated_realm();
|
||||
auto& realm = *vm.current_realm();
|
||||
|
||||
// 1. Let n be the number of elements in indices.
|
||||
// 2. Assert: n < 2^32-1.
|
||||
|
@ -142,14 +139,14 @@ static Value make_match_indices_index_pair_array(GlobalObject& global_object, Ut
|
|||
// i. Let matchIndicesArray be undefined.
|
||||
auto match_indices_array = js_undefined();
|
||||
if (match_indices.has_value())
|
||||
match_indices_array = get_match_index_par(global_object, string, *match_indices);
|
||||
match_indices_array = get_match_index_par(vm, string, *match_indices);
|
||||
|
||||
// d. Perform ! CreateDataPropertyOrThrow(A, ! ToString(i), matchIndicesArray).
|
||||
MUST(array->create_data_property_or_throw(i, match_indices_array));
|
||||
}
|
||||
|
||||
for (auto const& entry : group_names) {
|
||||
auto match_indices_array = get_match_index_par(global_object, string, entry.value);
|
||||
auto match_indices_array = get_match_index_par(vm, string, entry.value);
|
||||
|
||||
// e. If i > 0 and groupNames[i - 1] is not undefined, then
|
||||
// i. Assert: groups is not undefined.
|
||||
|
@ -166,10 +163,9 @@ static Value make_match_indices_index_pair_array(GlobalObject& global_object, Ut
|
|||
}
|
||||
|
||||
// 22.2.5.2.2 RegExpBuiltinExec ( R, S ), https://tc39.es/ecma262/#sec-regexpbuiltinexec
|
||||
static ThrowCompletionOr<Value> regexp_builtin_exec(GlobalObject& global_object, RegExpObject& regexp_object, Utf16String string)
|
||||
static ThrowCompletionOr<Value> regexp_builtin_exec(VM& vm, RegExpObject& regexp_object, Utf16String string)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
auto& realm = *global_object.associated_realm();
|
||||
auto& realm = *vm.current_realm();
|
||||
|
||||
// 1. Let length be the length of S.
|
||||
// 2. Let lastIndex be ℝ(? ToLength(? Get(R, "lastIndex"))).
|
||||
|
@ -344,7 +340,7 @@ static ThrowCompletionOr<Value> regexp_builtin_exec(GlobalObject& global_object,
|
|||
// 33. If hasIndices is true, then
|
||||
if (has_indices) {
|
||||
// a. Let indicesArray be MakeMatchIndicesIndexPairArray(S, indices, groupNames, hasGroups).
|
||||
auto indices_array = make_match_indices_index_pair_array(global_object, string.view(), indices, group_names, has_groups);
|
||||
auto indices_array = make_match_indices_index_pair_array(vm, string.view(), indices, group_names, has_groups);
|
||||
// b. Perform ! CreateDataProperty(A, "indices", indicesArray).
|
||||
MUST(array->create_data_property(vm.names.indices, indices_array));
|
||||
}
|
||||
|
@ -358,9 +354,10 @@ static ThrowCompletionOr<Value> regexp_builtin_exec(GlobalObject& global_object,
|
|||
}
|
||||
|
||||
// 22.2.5.2.1 RegExpExec ( R, S ), https://tc39.es/ecma262/#sec-regexpexec
|
||||
ThrowCompletionOr<Value> regexp_exec(GlobalObject& global_object, Object& regexp_object, Utf16String string)
|
||||
ThrowCompletionOr<Value> regexp_exec(VM& vm, Object& regexp_object, Utf16String string)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
auto& realm = *vm.current_realm();
|
||||
auto& global_object = realm.global_object();
|
||||
|
||||
// 1. Let exec be ? Get(R, "exec").
|
||||
auto exec = TRY(regexp_object.get(vm.names.exec));
|
||||
|
@ -383,7 +380,7 @@ ThrowCompletionOr<Value> regexp_exec(GlobalObject& global_object, Object& regexp
|
|||
return vm.throw_completion<TypeError>(ErrorType::NotAnObjectOfType, "RegExp");
|
||||
|
||||
// 4. Return ? RegExpBuiltinExec(R, S).
|
||||
return regexp_builtin_exec(global_object, static_cast<RegExpObject&>(regexp_object), move(string));
|
||||
return regexp_builtin_exec(vm, static_cast<RegExpObject&>(regexp_object), move(string));
|
||||
}
|
||||
|
||||
// 22.2.5.2.3 AdvanceStringIndex ( S, index, unicode ), https://tc39.es/ecma262/#sec-advancestringindex
|
||||
|
@ -448,7 +445,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::exec)
|
|||
auto string = TRY(vm.argument(0).to_utf16_string(vm));
|
||||
|
||||
// 4. Return ? RegExpBuiltinExec(R, S).
|
||||
return TRY(regexp_builtin_exec(global_object, *regexp_object, move(string)));
|
||||
return TRY(regexp_builtin_exec(vm, *regexp_object, move(string)));
|
||||
}
|
||||
|
||||
// 22.2.5.4 get RegExp.prototype.flags, https://tc39.es/ecma262/#sec-get-regexp.prototype.flags
|
||||
|
@ -508,7 +505,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_match)
|
|||
// 5. If global is false, then
|
||||
if (!global) {
|
||||
// a. Return ? RegExpExec(rx, S).
|
||||
return TRY(regexp_exec(global_object, *regexp_object, move(string)));
|
||||
return TRY(regexp_exec(vm, *regexp_object, move(string)));
|
||||
}
|
||||
|
||||
// 6. Else,
|
||||
|
@ -533,7 +530,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_match)
|
|||
// g. Repeat,
|
||||
while (true) {
|
||||
// i. Let result be ? RegExpExec(rx, S).
|
||||
auto result_value = TRY(regexp_exec(global_object, *regexp_object, string));
|
||||
auto result_value = TRY(regexp_exec(vm, *regexp_object, string));
|
||||
|
||||
// ii. If result is null, then
|
||||
if (result_value.is_null()) {
|
||||
|
@ -560,7 +557,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_match)
|
|||
// 3. If matchStr is the empty String, then
|
||||
if (match_str.is_empty()) {
|
||||
// Steps 3a-3c are implemented by increment_last_index.
|
||||
TRY(increment_last_index(global_object, *regexp_object, string.view(), full_unicode));
|
||||
TRY(increment_last_index(vm, *regexp_object, string.view(), full_unicode));
|
||||
}
|
||||
|
||||
// 4. Set n to n + 1.
|
||||
|
@ -660,7 +657,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_replace)
|
|||
// 11. Repeat, while done is false,
|
||||
while (true) {
|
||||
// a. Let result be ? RegExpExec(rx, S).
|
||||
auto result = TRY(regexp_exec(global_object, *regexp_object, string));
|
||||
auto result = TRY(regexp_exec(vm, *regexp_object, string));
|
||||
|
||||
// b. If result is null, set done to true.
|
||||
if (result.is_null())
|
||||
|
@ -684,7 +681,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_replace)
|
|||
// 2. If matchStr is the empty String, then
|
||||
if (match_str.is_empty()) {
|
||||
// Steps 2a-2c are implemented by increment_last_index.
|
||||
TRY(increment_last_index(global_object, *regexp_object, string.view(), full_unicode));
|
||||
TRY(increment_last_index(vm, *regexp_object, string.view(), full_unicode));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -826,7 +823,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_search)
|
|||
}
|
||||
|
||||
// 6. Let result be ? RegExpExec(rx, S).
|
||||
auto result = TRY(regexp_exec(global_object, *regexp_object, move(string)));
|
||||
auto result = TRY(regexp_exec(vm, *regexp_object, move(string)));
|
||||
|
||||
// 7. Let currentLastIndex be ? Get(rx, "lastIndex").
|
||||
auto current_last_index = TRY(regexp_object->get(vm.names.lastIndex));
|
||||
|
@ -918,7 +915,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_split)
|
|||
// 16. If size is 0, then
|
||||
if (string.is_empty()) {
|
||||
// a. Let z be ? RegExpExec(splitter, S).
|
||||
auto result = TRY(regexp_exec(global_object, *splitter, string));
|
||||
auto result = TRY(regexp_exec(vm, *splitter, string));
|
||||
|
||||
// b. If z is not null, return A.
|
||||
if (!result.is_null())
|
||||
|
@ -943,7 +940,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_split)
|
|||
TRY(splitter->set(vm.names.lastIndex, Value(next_search_from), Object::ShouldThrowExceptions::Yes));
|
||||
|
||||
// b. Let z be ? RegExpExec(splitter, S).
|
||||
auto result = TRY(regexp_exec(global_object, *splitter, string));
|
||||
auto result = TRY(regexp_exec(vm, *splitter, string));
|
||||
|
||||
// c. If z is null, set q to AdvanceStringIndex(S, q, unicodeMatching).
|
||||
if (result.is_null()) {
|
||||
|
@ -1036,7 +1033,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::test)
|
|||
auto string = TRY(vm.argument(0).to_utf16_string(vm));
|
||||
|
||||
// 4. Let match be ? RegExpExec(R, string).
|
||||
auto match = TRY(regexp_exec(global_object, *regexp_object, move(string)));
|
||||
auto match = TRY(regexp_exec(vm, *regexp_object, move(string)));
|
||||
|
||||
// 5. If match is not null, return true; else return false.
|
||||
return Value(!match.is_null());
|
||||
|
@ -1091,7 +1088,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::compile)
|
|||
// b. Let F be flags.
|
||||
|
||||
// 5. Return ? RegExpInitialize(O, P, F).
|
||||
return TRY(regexp_object->regexp_initialize(global_object, pattern, flags));
|
||||
return TRY(regexp_object->regexp_initialize(vm, pattern, flags));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
namespace JS {
|
||||
|
||||
ThrowCompletionOr<Value> regexp_exec(GlobalObject& global_object, Object& regexp_object, Utf16String string);
|
||||
ThrowCompletionOr<Value> regexp_exec(VM&, Object& regexp_object, Utf16String string);
|
||||
size_t advance_string_index(Utf16View const& string, size_t index, bool unicode);
|
||||
|
||||
class RegExpPrototype final : public PrototypeObject<RegExpPrototype, RegExpObject> {
|
||||
|
|
|
@ -37,7 +37,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpStringIteratorPrototype::next)
|
|||
if (iterator->done())
|
||||
return create_iterator_result_object(vm, js_undefined(), true);
|
||||
|
||||
auto match = TRY(regexp_exec(global_object, iterator->regexp_object(), iterator->string()));
|
||||
auto match = TRY(regexp_exec(vm, iterator->regexp_object(), iterator->string()));
|
||||
|
||||
if (match.is_null()) {
|
||||
iterator->set_done();
|
||||
|
|
|
@ -796,7 +796,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::match)
|
|||
|
||||
auto string = TRY(this_object.to_utf16_string(vm));
|
||||
|
||||
auto* rx = TRY(regexp_create(global_object, regexp, js_undefined()));
|
||||
auto* rx = TRY(regexp_create(vm, regexp, js_undefined()));
|
||||
return TRY(Value(rx).invoke(vm, *vm.well_known_symbol_match(), js_string(vm, move(string))));
|
||||
}
|
||||
|
||||
|
@ -820,7 +820,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::match_all)
|
|||
|
||||
auto string = TRY(this_object.to_utf16_string(vm));
|
||||
|
||||
auto* rx = TRY(regexp_create(global_object, regexp, js_string(vm, "g")));
|
||||
auto* rx = TRY(regexp_create(vm, regexp, js_string(vm, "g")));
|
||||
return TRY(Value(rx).invoke(vm, *vm.well_known_symbol_match_all(), js_string(vm, move(string))));
|
||||
}
|
||||
|
||||
|
@ -972,7 +972,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::search)
|
|||
|
||||
auto string = TRY(this_object.to_utf16_string(vm));
|
||||
|
||||
auto* rx = TRY(regexp_create(global_object, regexp, js_undefined()));
|
||||
auto* rx = TRY(regexp_create(vm, regexp, js_undefined()));
|
||||
return TRY(Value(rx).invoke(vm, *vm.well_known_symbol_search(), js_string(vm, move(string))));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue