summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS/Runtime
diff options
context:
space:
mode:
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);
+};
+
+}