diff options
author | Timothy Flynn <trflynn89@pm.me> | 2021-12-17 15:22:22 -0500 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-12-21 14:56:00 +0100 |
commit | 179ca9d0582de720d525c0e8bcdc1fc624e8d644 (patch) | |
tree | 15f68e92897043aab92fed48b2ac98aaa874f717 /Userland/Libraries | |
parent | 4a915fc9fa27f1ea55310bf686a3c5705660db35 (diff) | |
download | serenity-179ca9d0582de720d525c0e8bcdc1fc624e8d644.zip |
LibJS: Add spec comments to RegExp.prototype.[flags, source, exec, test]
Diffstat (limited to 'Userland/Libraries')
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp | 54 |
1 files changed, 53 insertions, 1 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp b/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp index 5e2c97009b..2b907c971d 100644 --- a/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp @@ -283,14 +283,20 @@ ThrowCompletionOr<Value> regexp_exec(GlobalObject& global_object, Object& regexp #define __JS_ENUMERATE(flagName, flag_name, flag_char) \ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::flag_name) \ { \ + /* 1. If Type(R) is not Object, throw a TypeError exception. */ \ auto* regexp_object = TRY(this_object(global_object)); \ + /* 2. If R does not have an [[OriginalFlags]] internal slot, then */ \ if (!is<RegExpObject>(regexp_object)) { \ + /* a. If SameValue(R, %RegExp.prototype%) is true, return undefined. */ \ if (same_value(regexp_object, global_object.regexp_prototype())) \ return js_undefined(); \ + /* b. Otherwise, throw a TypeError exception. */ \ return vm.throw_completion<TypeError>(global_object, ErrorType::NotAnObjectOfType, "RegExp"); \ } \ - \ + /* 3. Let flags be R.[[OriginalFlags]]. */ \ auto const& flags = static_cast<RegExpObject*>(regexp_object)->flags(); \ + /* 4. If flags contains codeUnit, return true. */ \ + /* 5. Return false. */ \ return Value(flags.contains(#flag_char##sv)); \ } JS_ENUMERATE_REGEXP_FLAGS @@ -299,9 +305,26 @@ JS_ENUMERATE_REGEXP_FLAGS // 22.2.5.4 get RegExp.prototype.flags, https://tc39.es/ecma262/#sec-get-regexp.prototype.flags JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::flags) { + + // 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 result be the empty String. StringBuilder builder(8); + // 4. Let global be ! ToBoolean(? Get(R, "global")). + // 5. If global is true, append the code unit 0x0067 (LATIN SMALL LETTER G) as the last code unit of result. + // 6. Let ignoreCase be ! ToBoolean(? Get(R, "ignoreCase")). + // 7. If ignoreCase is true, append the code unit 0x0069 (LATIN SMALL LETTER I) as the last code unit of result. + // 8. Let multiline be ! ToBoolean(? Get(R, "multiline")). + // 9. If multiline is true, append the code unit 0x006D (LATIN SMALL LETTER M) as the last code unit of result. + // 10. Let dotAll be ! ToBoolean(? Get(R, "dotAll")). + // 11. If dotAll is true, append the code unit 0x0073 (LATIN SMALL LETTER S) as the last code unit of result. + // 12. Let unicode be ! ToBoolean(? Get(R, "unicode")). + // 13. If unicode is true, append the code unit 0x0075 (LATIN SMALL LETTER U) as the last code unit of result. + // 14. Let sticky be ! ToBoolean(? Get(R, "sticky")). + // 15. If sticky is true, append the code unit 0x0079 (LATIN SMALL LETTER Y) as the last code unit of result. #define __JS_ENUMERATE(flagName, flag_name, flag_char) \ auto flag_##flag_name = TRY(regexp_object->get(vm.names.flagName)); \ if (flag_##flag_name.to_boolean()) \ @@ -309,53 +332,82 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::flags) JS_ENUMERATE_REGEXP_FLAGS #undef __JS_ENUMERATE + // 16. Return result. 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)); } |