Jelajahi Sumber

LibJS: Parse the RegExp.prototype.hasIndices flag

Timothy Flynn 4 tahun lalu
induk
melakukan
d1e06b00e3

+ 1 - 0
Userland/Libraries/LibJS/Forward.h

@@ -109,6 +109,7 @@
     __JS_ENUMERATE(toStringTag, to_string_tag)
 
 #define JS_ENUMERATE_REGEXP_FLAGS              \
+    __JS_ENUMERATE(hasIndices, has_indices, d) \
     __JS_ENUMERATE(global, global, g)          \
     __JS_ENUMERATE(ignoreCase, ignore_case, i) \
     __JS_ENUMERATE(multiline, multiline, m)    \

+ 1 - 1
Userland/Libraries/LibJS/Parser.cpp

@@ -789,7 +789,7 @@ NonnullRefPtr<RegExpLiteral> Parser::parse_regexp_literal()
         HashTable<char> seen_flags;
         for (size_t i = 0; i < flags.length(); ++i) {
             auto flag = flags.substring_view(i, 1);
-            if (!flag.is_one_of("g", "i", "m", "s", "u", "y"))
+            if (!flag.is_one_of("d", "g", "i", "m", "s", "u", "y"))
                 syntax_error(String::formatted("Invalid RegExp flag '{}'", flag), Position { flags_start.line, flags_start.column + i });
             if (seen_flags.contains(*flag.characters_without_null_termination()))
                 syntax_error(String::formatted("Repeated RegExp flag '{}'", flag), Position { flags_start.line, flags_start.column + i });

+ 1 - 0
Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h

@@ -188,6 +188,7 @@ namespace JS {
     P(globalThis)                            \
     P(groups)                                \
     P(has)                                   \
+    P(hasIndices)                            \
     P(hasOwn)                                \
     P(hasOwnProperty)                        \
     P(hypot)                                 \

+ 6 - 1
Userland/Libraries/LibJS/Runtime/RegExpObject.cpp

@@ -16,7 +16,7 @@ namespace JS {
 static Flags options_from(GlobalObject& global_object, const String& flags)
 {
     auto& vm = global_object.vm();
-    bool g = false, i = false, m = false, s = false, u = false, y = false;
+    bool d = false, g = false, i = false, m = false, s = false, u = false, y = false;
     Flags options {
         // JS regexps are all 'global' by default as per our definition, but the "global" flag enables "stateful".
         // FIXME: Enable 'BrowserExtended' only if in a browser context.
@@ -26,6 +26,11 @@ static Flags options_from(GlobalObject& global_object, const String& flags)
 
     for (auto ch : flags) {
         switch (ch) {
+        case 'd':
+            if (d)
+                vm.throw_exception<SyntaxError>(global_object, ErrorType::RegExpObjectRepeatedFlag, ch);
+            d = true;
+            break;
         case 'g':
             if (g)
                 vm.throw_exception<SyntaxError>(global_object, ErrorType::RegExpObjectRepeatedFlag, ch);

+ 1 - 0
Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp

@@ -224,6 +224,7 @@ static Value regexp_exec(GlobalObject& global_object, Object& regexp_object, Str
     return regexp_builtin_exec(global_object, static_cast<RegExpObject&>(regexp_object), string);
 }
 
+// 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
 // 22.2.5.6 get RegExp.prototype.ignoreCase, https://tc39.es/ecma262/#sec-get-regexp.prototype.ignorecase

+ 2 - 1
Userland/Libraries/LibJS/Tests/builtins/RegExp/RegExp.prototype.flags.js

@@ -1,5 +1,6 @@
 test("basic functionality", () => {
     expect(/foo/.flags).toBe("");
+    expect(/foo/d.flags).toBe("d");
     expect(/foo/g.flags).toBe("g");
     expect(/foo/i.flags).toBe("i");
     expect(/foo/m.flags).toBe("m");
@@ -7,5 +8,5 @@ test("basic functionality", () => {
     expect(/foo/u.flags).toBe("u");
     expect(/foo/y.flags).toBe("y");
     // prettier-ignore
-    expect(/foo/sgimyu.flags).toBe("gimsuy");
+    expect(/foo/dsgimyu.flags).toBe("dgimsuy");
 });