1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-23 19:37:34 +00:00

LibJS: Parse the RegExp.prototype.hasIndices flag

This commit is contained in:
Timothy Flynn 2021-07-09 16:10:17 -04:00 committed by Linus Groh
parent e801cc7afd
commit d1e06b00e3
6 changed files with 12 additions and 3 deletions

View file

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

View file

@ -789,7 +789,7 @@ NonnullRefPtr<RegExpLiteral> Parser::parse_regexp_literal()
HashTable<char> seen_flags; HashTable<char> seen_flags;
for (size_t i = 0; i < flags.length(); ++i) { for (size_t i = 0; i < flags.length(); ++i) {
auto flag = flags.substring_view(i, 1); 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 }); 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())) 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 }); syntax_error(String::formatted("Repeated RegExp flag '{}'", flag), Position { flags_start.line, flags_start.column + i });

View file

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

View file

@ -16,7 +16,7 @@ namespace JS {
static Flags options_from(GlobalObject& global_object, const String& flags) static Flags options_from(GlobalObject& global_object, const String& flags)
{ {
auto& vm = global_object.vm(); 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 { Flags options {
// JS regexps are all 'global' by default as per our definition, but the "global" flag enables "stateful". // 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. // 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) { for (auto ch : flags) {
switch (ch) { switch (ch) {
case 'd':
if (d)
vm.throw_exception<SyntaxError>(global_object, ErrorType::RegExpObjectRepeatedFlag, ch);
d = true;
break;
case 'g': case 'g':
if (g) if (g)
vm.throw_exception<SyntaxError>(global_object, ErrorType::RegExpObjectRepeatedFlag, ch); vm.throw_exception<SyntaxError>(global_object, ErrorType::RegExpObjectRepeatedFlag, ch);

View file

@ -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); 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.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.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 // 22.2.5.6 get RegExp.prototype.ignoreCase, https://tc39.es/ecma262/#sec-get-regexp.prototype.ignorecase

View file

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