summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS/Runtime
diff options
context:
space:
mode:
authorTimothy Flynn <trflynn89@pm.me>2021-07-15 08:58:27 -0400
committerLinus Groh <mail@linusgroh.de>2021-07-16 13:53:11 +0100
commitcfddcad7cfebcb61ff2b8dd52d94cd5950d5347a (patch)
tree7cf47e5b4ab09e3fc07eef8fafd7c1a2b83da172 /Userland/Libraries/LibJS/Runtime
parent6cf64d0f095df68b14c72c93a58781f249eb2c96 (diff)
downloadserenity-cfddcad7cfebcb61ff2b8dd52d94cd5950d5347a.zip
LibJS: Implement the RegExpStringIterator object
This implementation closely follows the StringIterator object in that the abstract closure meant to be created in CreateRegExpStringIterator is instead unrolled into RegExpStringIterator.prototype.next.
Diffstat (limited to 'Userland/Libraries/LibJS/Runtime')
-rw-r--r--Userland/Libraries/LibJS/Runtime/GlobalObject.cpp1
-rw-r--r--Userland/Libraries/LibJS/Runtime/RegExpStringIterator.cpp27
-rw-r--r--Userland/Libraries/LibJS/Runtime/RegExpStringIterator.h38
-rw-r--r--Userland/Libraries/LibJS/Runtime/RegExpStringIteratorPrototype.cpp89
-rw-r--r--Userland/Libraries/LibJS/Runtime/RegExpStringIteratorPrototype.h26
5 files changed, 181 insertions, 0 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp b/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp
index 57011398d6..3a1fad31d9 100644
--- a/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp
+++ b/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp
@@ -59,6 +59,7 @@
#include <LibJS/Runtime/ReflectObject.h>
#include <LibJS/Runtime/RegExpConstructor.h>
#include <LibJS/Runtime/RegExpPrototype.h>
+#include <LibJS/Runtime/RegExpStringIteratorPrototype.h>
#include <LibJS/Runtime/SetConstructor.h>
#include <LibJS/Runtime/SetIteratorPrototype.h>
#include <LibJS/Runtime/SetPrototype.h>
diff --git a/Userland/Libraries/LibJS/Runtime/RegExpStringIterator.cpp b/Userland/Libraries/LibJS/Runtime/RegExpStringIterator.cpp
new file mode 100644
index 0000000000..573e7bb32e
--- /dev/null
+++ b/Userland/Libraries/LibJS/Runtime/RegExpStringIterator.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021, Tim Flynn <trflynn89@pm.me>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibJS/Runtime/GlobalObject.h>
+#include <LibJS/Runtime/RegExpStringIterator.h>
+
+namespace JS {
+
+// 22.2.7.1 CreateRegExpStringIterator ( R, S, global, fullUnicode ), https://tc39.es/ecma262/#sec-createregexpstringiterator
+RegExpStringIterator* RegExpStringIterator::create(GlobalObject& global_object, Object& regexp_object, String string, bool global, bool unicode)
+{
+ return global_object.heap().allocate<RegExpStringIterator>(global_object, *global_object.regexp_string_iterator_prototype(), regexp_object, move(string), global, unicode);
+}
+
+RegExpStringIterator::RegExpStringIterator(Object& prototype, Object& regexp_object, String string, bool global, bool unicode)
+ : Object(prototype)
+ , m_regexp_object(regexp_object)
+ , m_string(move(string))
+ , m_global(global)
+ , m_unicode(unicode)
+{
+}
+
+}
diff --git a/Userland/Libraries/LibJS/Runtime/RegExpStringIterator.h b/Userland/Libraries/LibJS/Runtime/RegExpStringIterator.h
new file mode 100644
index 0000000000..876dd796a9
--- /dev/null
+++ b/Userland/Libraries/LibJS/Runtime/RegExpStringIterator.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021, Tim Flynn <trflynn89@pm.me>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <LibJS/Runtime/Object.h>
+
+namespace JS {
+
+class RegExpStringIterator final : public Object {
+ JS_OBJECT(RegExpStringIterator, Object);
+
+public:
+ static RegExpStringIterator* create(GlobalObject&, Object& regexp_object, String string, bool global, bool unicode);
+
+ explicit RegExpStringIterator(Object& prototype, Object& regexp_object, String string, bool global, bool unicode);
+ virtual ~RegExpStringIterator() override = default;
+
+ Object& regexp_object() { return m_regexp_object; }
+ String const& string() const { return m_string; }
+ bool global() const { return m_global; }
+ bool unicode() const { return m_unicode; }
+
+ bool done() const { return m_done; }
+ void set_done() { m_done = true; }
+
+private:
+ Object& m_regexp_object;
+ String m_string;
+ bool m_global { false };
+ bool m_unicode { false };
+ bool m_done { false };
+};
+
+}
diff --git a/Userland/Libraries/LibJS/Runtime/RegExpStringIteratorPrototype.cpp b/Userland/Libraries/LibJS/Runtime/RegExpStringIteratorPrototype.cpp
new file mode 100644
index 0000000000..9b61656d20
--- /dev/null
+++ b/Userland/Libraries/LibJS/Runtime/RegExpStringIteratorPrototype.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2021, Tim Flynn <trflynn89@pm.me>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibJS/Runtime/GlobalObject.h>
+#include <LibJS/Runtime/IteratorOperations.h>
+#include <LibJS/Runtime/RegExpPrototype.h>
+#include <LibJS/Runtime/RegExpStringIterator.h>
+#include <LibJS/Runtime/RegExpStringIteratorPrototype.h>
+
+namespace JS {
+
+RegExpStringIteratorPrototype::RegExpStringIteratorPrototype(GlobalObject& global_object)
+ : Object(*global_object.iterator_prototype())
+{
+}
+
+void RegExpStringIteratorPrototype::initialize(GlobalObject& global_object)
+{
+ Object::initialize(global_object);
+ auto& vm = this->vm();
+
+ u8 attr = Attribute::Writable | Attribute::Configurable;
+ define_native_function(vm.names.next, next, 0, attr);
+
+ // 22.2.7.2.2 %RegExpStringIteratorPrototype% [ @@toStringTag ], https://tc39.es/ecma262/#sec-%regexpstringiteratorprototype%-@@tostringtag
+ define_direct_property(*vm.well_known_symbol_to_string_tag(), js_string(global_object.heap(), "RegExp String Iterator"), Attribute::Configurable);
+}
+
+// 22.2.7.2.1 %RegExpStringIteratorPrototype%.next ( ), https://tc39.es/ecma262/#sec-%regexpstringiteratorprototype%.next
+JS_DEFINE_NATIVE_FUNCTION(RegExpStringIteratorPrototype::next)
+{
+ // For details, see the 'closure' of: https://tc39.es/ecma262/#sec-createregexpstringiterator
+ auto this_value = vm.this_value(global_object);
+ if (!this_value.is_object() || !is<RegExpStringIterator>(this_value.as_object())) {
+ vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "RegExp String Iterator");
+ return {};
+ }
+
+ auto& iterator = static_cast<RegExpStringIterator&>(this_value.as_object());
+ if (iterator.done())
+ return create_iterator_result_object(global_object, js_undefined(), true);
+
+ auto match = regexp_exec(global_object, iterator.regexp_object(), iterator.string());
+ if (vm.exception())
+ return {};
+
+ if (match.is_null()) {
+ iterator.set_done();
+ return create_iterator_result_object(global_object, js_undefined(), true);
+ }
+
+ if (!iterator.global()) {
+ iterator.set_done();
+ return create_iterator_result_object(global_object, match, false);
+ }
+
+ auto* match_object = match.to_object(global_object);
+ if (!match_object)
+ return {};
+ auto match_string_value = match_object->get(0);
+ if (vm.exception())
+ return {};
+ auto match_string = match_string_value.to_string(global_object);
+ if (vm.exception())
+ return {};
+
+ if (match_string.is_empty()) {
+ auto last_index_value = iterator.regexp_object().get(vm.names.lastIndex);
+ if (vm.exception())
+ return {};
+ auto last_index = last_index_value.to_length(global_object);
+ if (vm.exception())
+ return {};
+
+ // FIXME: Implement AdvanceStringIndex to take Unicode code points into account - https://tc39.es/ecma262/#sec-advancestringindex
+ ++last_index;
+
+ iterator.regexp_object().set(vm.names.lastIndex, Value(last_index), true);
+ if (vm.exception())
+ return {};
+ }
+
+ return create_iterator_result_object(global_object, match, false);
+}
+
+}
diff --git a/Userland/Libraries/LibJS/Runtime/RegExpStringIteratorPrototype.h b/Userland/Libraries/LibJS/Runtime/RegExpStringIteratorPrototype.h
new file mode 100644
index 0000000000..075cffec74
--- /dev/null
+++ b/Userland/Libraries/LibJS/Runtime/RegExpStringIteratorPrototype.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021, Tim Flynn <trflynn89@pm.me>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <LibJS/Runtime/Object.h>
+
+namespace JS {
+
+class RegExpStringIteratorPrototype final : public Object {
+ JS_OBJECT(RegExpStringIteratorPrototype, Object)
+
+public:
+ explicit RegExpStringIteratorPrototype(GlobalObject&);
+ virtual ~RegExpStringIteratorPrototype() override = default;
+
+ virtual void initialize(GlobalObject&) override;
+
+private:
+ JS_DECLARE_NATIVE_FUNCTION(next);
+};
+
+}