summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS
diff options
context:
space:
mode:
authorTimothy Flynn <trflynn89@pm.me>2021-12-20 14:18:28 -0500
committerLinus Groh <mail@linusgroh.de>2021-12-21 14:56:00 +0100
commit968f6e24329722681133e0fbde0e9bce7bbb64ed (patch)
tree87de7a594395d30aa27b93740aafab337da550de /Userland/Libraries/LibJS
parent7ea85ed10ba83c7007e6f610d586481a7bf1aace (diff)
downloadserenity-968f6e24329722681133e0fbde0e9bce7bbb64ed.zip
LibJS: Define RegExp.prototype methods in spec order
Diffstat (limited to 'Userland/Libraries/LibJS')
-rw-r--r--Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp192
-rw-r--r--Userland/Libraries/LibJS/Runtime/RegExpPrototype.h9
2 files changed, 100 insertions, 101 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp b/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp
index 6bc346d7e8..b452e48cc7 100644
--- a/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp
+++ b/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp
@@ -55,27 +55,6 @@ RegExpPrototype::~RegExpPrototype()
{
}
-// 22.2.5.2.3 AdvanceStringIndex ( S, index, unicode ), https://tc39.es/ecma262/#sec-advancestringindex
-size_t advance_string_index(Utf16View const& string, size_t index, bool unicode)
-{
- // 1. Assert: index ≤ 2^53 - 1.
-
- // 2. If unicode is false, return index + 1.
- if (!unicode)
- return index + 1;
-
- // 3. Let length be the number of code units in S.
- // 4. If index + 1 ≥ length, return index + 1.
- if (index + 1 >= string.length_in_code_units())
- return index + 1;
-
- // 5. Let cp be ! CodePointAt(S, index).
- auto code_point = code_point_at(string, index);
-
- // 6. Return index + cp.[[CodeUnitCount]].
- return index + code_point.code_unit_count;
-}
-
// 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)
{
@@ -426,6 +405,27 @@ ThrowCompletionOr<Value> regexp_exec(GlobalObject& global_object, Object& regexp
return regexp_builtin_exec(global_object, static_cast<RegExpObject&>(regexp_object), move(string));
}
+// 22.2.5.2.3 AdvanceStringIndex ( S, index, unicode ), https://tc39.es/ecma262/#sec-advancestringindex
+size_t advance_string_index(Utf16View const& string, size_t index, bool unicode)
+{
+ // 1. Assert: index ≤ 2^53 - 1.
+
+ // 2. If unicode is false, return index + 1.
+ if (!unicode)
+ return index + 1;
+
+ // 3. Let length be the number of code units in S.
+ // 4. If index + 1 ≥ length, return index + 1.
+ if (index + 1 >= string.length_in_code_units())
+ return index + 1;
+
+ // 5. Let cp be ! CodePointAt(S, index).
+ auto code_point = code_point_at(string, index);
+
+ // 6. Return index + cp.[[CodeUnitCount]].
+ return index + code_point.code_unit_count;
+}
+
// 1.1.4.3 get RegExp.prototype.hasIndices, https://tc39.es/proposal-regexp-match-indices/#sec-get-regexp.prototype.hasIndices
// 22.2.5.3 get RegExp.prototype.dotAll, https://tc39.es/ecma262/#sec-get-regexp.prototype.dotAll
// 22.2.5.5 get RegExp.prototype.global, https://tc39.es/ecma262/#sec-get-regexp.prototype.global
@@ -455,6 +455,20 @@ ThrowCompletionOr<Value> regexp_exec(GlobalObject& global_object, Object& regexp
JS_ENUMERATE_REGEXP_FLAGS
#undef __JS_ENUMERATE
+// 22.2.5.2 RegExp.prototype.exec ( string ), https://tc39.es/ecma262/#sec-regexp.prototype.exec
+JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::exec)
+{
+ // 1. Let R be the this value.
+ // 2. Perform ? RequireInternalSlot(R, [[RegExpMatcher]]).
+ auto* regexp_object = TRY(typed_this_object(global_object));
+
+ // 3. Let S be ? ToString(string).
+ auto string = TRY(vm.argument(0).to_utf16_string(global_object));
+
+ // 4. Return ? RegExpBuiltinExec(R, S).
+ return TRY(regexp_builtin_exec(global_object, *regexp_object, move(string)));
+}
+
// 22.2.5.4 get RegExp.prototype.flags, https://tc39.es/ecma262/#sec-get-regexp.prototype.flags
JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::flags)
{
@@ -489,81 +503,6 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::flags)
return js_string(vm, builder.to_string());
}
-// 22.2.5.12 get RegExp.prototype.source, https://tc39.es/ecma262/#sec-get-regexp.prototype.source
-JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::source)
-{
- // 1. Let R be the this value.
- // 2. If Type(R) is not Object, throw a TypeError exception.
- auto* regexp_object = TRY(this_object(global_object));
-
- // 3. If R does not have an [[OriginalSource]] internal slot, then
- if (!is<RegExpObject>(regexp_object)) {
- // a. If SameValue(R, %RegExp.prototype%) is true, return "(?:)".
- if (same_value(regexp_object, global_object.regexp_prototype()))
- return js_string(vm, "(?:)");
-
- // b. Otherwise, throw a TypeError exception.
- return vm.throw_completion<TypeError>(global_object, ErrorType::NotAnObjectOfType, "RegExp");
- }
-
- // 4. Assert: R has an [[OriginalFlags]] internal slot.
- // 5. Let src be R.[[OriginalSource]].
- // 6. Let flags be R.[[OriginalFlags]].
- // 7. Return EscapeRegExpPattern(src, flags).
- return js_string(vm, static_cast<RegExpObject&>(*regexp_object).escape_regexp_pattern());
-}
-
-// 22.2.5.2 RegExp.prototype.exec ( string ), https://tc39.es/ecma262/#sec-regexp.prototype.exec
-JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::exec)
-{
- // 1. Let R be the this value.
- // 2. Perform ? RequireInternalSlot(R, [[RegExpMatcher]]).
- auto* regexp_object = TRY(typed_this_object(global_object));
-
- // 3. Let S be ? ToString(string).
- auto string = TRY(vm.argument(0).to_utf16_string(global_object));
-
- // 4. Return ? RegExpBuiltinExec(R, S).
- return TRY(regexp_builtin_exec(global_object, *regexp_object, move(string)));
-}
-
-// 22.2.5.15 RegExp.prototype.test ( S ), https://tc39.es/ecma262/#sec-regexp.prototype.test
-JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::test)
-{
- // 1. Let R be the this value.
- // 2. If Type(R) is not Object, throw a TypeError exception.
- auto* regexp_object = TRY(this_object(global_object));
-
- // 3. Let string be ? ToString(S).
- auto string = TRY(vm.argument(0).to_utf16_string(global_object));
-
- // 4. Let match be ? RegExpExec(R, string).
- auto match = TRY(regexp_exec(global_object, *regexp_object, move(string)));
-
- // 5. If match is not null, return true; else return false.
- return Value(!match.is_null());
-}
-
-// 22.2.5.16 RegExp.prototype.toString ( ), https://tc39.es/ecma262/#sec-regexp.prototype.tostring
-JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::to_string)
-{
- // 1. Let R be the this value.
- // 2. If Type(R) is not Object, throw a TypeError exception.
- auto* regexp_object = TRY(this_object(global_object));
-
- // 3. Let pattern be ? ToString(? Get(R, "source")).
- auto source_attr = TRY(regexp_object->get(vm.names.source));
- auto pattern = TRY(source_attr.to_string(global_object));
-
- // 4. Let flags be ? ToString(? Get(R, "flags")).
- auto flags_attr = TRY(regexp_object->get(vm.names.flags));
- auto flags = TRY(flags_attr.to_string(global_object));
-
- // 5. Let result be the string-concatenation of "/", pattern, "/", and flags.
- // 6. Return result.
- return js_string(vm, String::formatted("/{}/{}", pattern, flags));
-}
-
// 22.2.5.7 RegExp.prototype [ @@match ] ( string ), https://tc39.es/ecma262/#sec-regexp.prototype-@@match
JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_match)
{
@@ -905,6 +844,30 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_search)
return TRY(result.get(global_object, vm.names.index));
}
+// 22.2.5.12 get RegExp.prototype.source, https://tc39.es/ecma262/#sec-get-regexp.prototype.source
+JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::source)
+{
+ // 1. Let R be the this value.
+ // 2. If Type(R) is not Object, throw a TypeError exception.
+ auto* regexp_object = TRY(this_object(global_object));
+
+ // 3. If R does not have an [[OriginalSource]] internal slot, then
+ if (!is<RegExpObject>(regexp_object)) {
+ // a. If SameValue(R, %RegExp.prototype%) is true, return "(?:)".
+ if (same_value(regexp_object, global_object.regexp_prototype()))
+ return js_string(vm, "(?:)");
+
+ // b. Otherwise, throw a TypeError exception.
+ return vm.throw_completion<TypeError>(global_object, ErrorType::NotAnObjectOfType, "RegExp");
+ }
+
+ // 4. Assert: R has an [[OriginalFlags]] internal slot.
+ // 5. Let src be R.[[OriginalSource]].
+ // 6. Let flags be R.[[OriginalFlags]].
+ // 7. Return EscapeRegExpPattern(src, flags).
+ return js_string(vm, static_cast<RegExpObject&>(*regexp_object).escape_regexp_pattern());
+}
+
// 22.2.5.13 RegExp.prototype [ @@split ] ( string, limit ), https://tc39.es/ecma262/#sec-regexp.prototype-@@split
JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_split)
{
@@ -1062,6 +1025,43 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_split)
return array;
}
+// 22.2.5.15 RegExp.prototype.test ( S ), https://tc39.es/ecma262/#sec-regexp.prototype.test
+JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::test)
+{
+ // 1. Let R be the this value.
+ // 2. If Type(R) is not Object, throw a TypeError exception.
+ auto* regexp_object = TRY(this_object(global_object));
+
+ // 3. Let string be ? ToString(S).
+ auto string = TRY(vm.argument(0).to_utf16_string(global_object));
+
+ // 4. Let match be ? RegExpExec(R, string).
+ auto match = TRY(regexp_exec(global_object, *regexp_object, move(string)));
+
+ // 5. If match is not null, return true; else return false.
+ return Value(!match.is_null());
+}
+
+// 22.2.5.16 RegExp.prototype.toString ( ), https://tc39.es/ecma262/#sec-regexp.prototype.tostring
+JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::to_string)
+{
+ // 1. Let R be the this value.
+ // 2. If Type(R) is not Object, throw a TypeError exception.
+ auto* regexp_object = TRY(this_object(global_object));
+
+ // 3. Let pattern be ? ToString(? Get(R, "source")).
+ auto source_attr = TRY(regexp_object->get(vm.names.source));
+ auto pattern = TRY(source_attr.to_string(global_object));
+
+ // 4. Let flags be ? ToString(? Get(R, "flags")).
+ auto flags_attr = TRY(regexp_object->get(vm.names.flags));
+ auto flags = TRY(flags_attr.to_string(global_object));
+
+ // 5. Let result be the string-concatenation of "/", pattern, "/", and flags.
+ // 6. Return result.
+ return js_string(vm, String::formatted("/{}/{}", pattern, flags));
+}
+
// B.2.4.1 RegExp.prototype.compile ( pattern, flags ), https://tc39.es/ecma262/#sec-regexp.prototype.compile
JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::compile)
{
diff --git a/Userland/Libraries/LibJS/Runtime/RegExpPrototype.h b/Userland/Libraries/LibJS/Runtime/RegExpPrototype.h
index 247bbe8af5..34fac8e30c 100644
--- a/Userland/Libraries/LibJS/Runtime/RegExpPrototype.h
+++ b/Userland/Libraries/LibJS/Runtime/RegExpPrototype.h
@@ -24,17 +24,16 @@ public:
virtual ~RegExpPrototype() override;
private:
- JS_DECLARE_NATIVE_FUNCTION(flags);
- JS_DECLARE_NATIVE_FUNCTION(source);
-
JS_DECLARE_NATIVE_FUNCTION(exec);
- JS_DECLARE_NATIVE_FUNCTION(test);
- JS_DECLARE_NATIVE_FUNCTION(to_string);
+ JS_DECLARE_NATIVE_FUNCTION(flags);
JS_DECLARE_NATIVE_FUNCTION(symbol_match);
JS_DECLARE_NATIVE_FUNCTION(symbol_match_all);
JS_DECLARE_NATIVE_FUNCTION(symbol_replace);
JS_DECLARE_NATIVE_FUNCTION(symbol_search);
+ JS_DECLARE_NATIVE_FUNCTION(source);
JS_DECLARE_NATIVE_FUNCTION(symbol_split);
+ JS_DECLARE_NATIVE_FUNCTION(test);
+ JS_DECLARE_NATIVE_FUNCTION(to_string);
JS_DECLARE_NATIVE_FUNCTION(compile);
#define __JS_ENUMERATE(_, flag_name, ...) \