2020-06-03 20:05:49 -03:00
|
|
|
/*
|
2021-04-22 20:53:07 -03:00
|
|
|
* Copyright (c) 2020, Matthew Olsson <mattco@serenityos.org>
|
2024-10-25 12:29:03 -03:00
|
|
|
* Copyright (c) 2024, Andreas Kling <andreas@ladybird.org>
|
2020-06-03 20:05:49 -03:00
|
|
|
*
|
2021-04-22 05:24:48 -03:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-06-03 20:05:49 -03:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
2024-10-25 12:29:03 -03:00
|
|
|
#include <AK/EnumBits.h>
|
2021-08-20 10:14:27 -03:00
|
|
|
#include <AK/Optional.h>
|
2021-07-29 11:34:37 -03:00
|
|
|
#include <AK/Result.h>
|
Libraries: Clean up UTF-16 source text paths
Store parser errors, source range filenames, source code filenames,
module source, and Rust parser errors as UTF-16 where they flow back
into JavaScript-visible strings. Keep byte-oriented source buffers
byte-backed.
Remove temporary PrimitiveString, ByteString, and UTF-8 detours from
JSON, RegExp, module debug logging, print formatting, and tests.
2026-06-21 14:03:19 -03:00
|
|
|
#include <AK/String.h>
|
2025-07-19 17:49:30 -03:00
|
|
|
#include <LibJS/Export.h>
|
2020-06-03 20:05:49 -03:00
|
|
|
#include <LibJS/Runtime/Object.h>
|
LibJS+LibRegex: Switch RegExp over to the Rust engine
Switch LibJS `RegExp` over to the Rust-backed `ECMAScriptRegex` APIs.
Route `new RegExp()`, regex literals, and the RegExp builtins through
the new compile and exec APIs, and stop re-validating patterns with the
deleted C++ parser on the way in. Preserve the observable error
behavior by carrying structured compile errors and backtracking-limit
failures across the FFI boundary. Cache compiled regex state and named
capture metadata on `RegExpObject` in the new representation.
Use the new API surface to simplify and speed up the builtin paths too:
share `exec_internal`, cache compiled regex pointers, keep the legacy
RegExp statics lazy, run global replace through batch `find_all`, and
optimize replace, test, split, and String helper paths. Add regression
tests for those JavaScript-visible paths.
2026-03-25 06:52:40 -03:00
|
|
|
#include <LibRegex/ECMAScriptRegex.h>
|
2020-11-18 19:20:00 -03:00
|
|
|
|
2020-06-03 20:05:49 -03:00
|
|
|
namespace JS {
|
|
|
|
|
|
2025-07-19 17:49:30 -03:00
|
|
|
JS_API ThrowCompletionOr<GC::Ref<RegExpObject>> regexp_create(VM&, Value pattern, Value flags);
|
2025-07-19 14:41:08 -03:00
|
|
|
ThrowCompletionOr<GC::Ref<RegExpObject>> regexp_alloc(VM&, FunctionObject& new_target);
|
2021-03-14 07:03:11 -03:00
|
|
|
|
2022-07-16 02:44:03 -03:00
|
|
|
struct ParseRegexPatternError {
|
2026-06-21 14:03:10 -03:00
|
|
|
Utf16String error;
|
2022-07-16 02:44:03 -03:00
|
|
|
};
|
2026-06-22 08:07:20 -03:00
|
|
|
ErrorOr<Utf16String, ParseRegexPatternError> parse_regex_pattern(Utf16View const& pattern, bool unicode, bool unicode_sets);
|
|
|
|
|
ThrowCompletionOr<Utf16String> parse_regex_pattern(VM& vm, Utf16View const& pattern, bool unicode, bool unicode_sets);
|
2021-07-29 11:34:37 -03:00
|
|
|
|
2025-08-03 18:05:09 -03:00
|
|
|
class JS_API RegExpObject : public Object {
|
2020-06-21 10:14:02 -03:00
|
|
|
JS_OBJECT(RegExpObject, Object);
|
2024-11-14 12:01:23 -03:00
|
|
|
GC_DECLARE_ALLOCATOR(RegExpObject);
|
2020-06-21 10:14:02 -03:00
|
|
|
|
2020-06-03 20:05:49 -03:00
|
|
|
public:
|
2024-10-25 12:29:03 -03:00
|
|
|
enum class Flags {
|
|
|
|
|
HasIndices = 1 << 0,
|
|
|
|
|
Global = 1 << 1,
|
|
|
|
|
IgnoreCase = 1 << 2,
|
|
|
|
|
Multiline = 1 << 3,
|
|
|
|
|
DotAll = 1 << 4,
|
|
|
|
|
UnicodeSets = 1 << 5,
|
|
|
|
|
Unicode = 1 << 6,
|
|
|
|
|
Sticky = 1 << 7,
|
|
|
|
|
};
|
|
|
|
|
|
2024-11-14 12:01:23 -03:00
|
|
|
static GC::Ref<RegExpObject> create(Realm&);
|
LibJS+LibRegex: Switch RegExp over to the Rust engine
Switch LibJS `RegExp` over to the Rust-backed `ECMAScriptRegex` APIs.
Route `new RegExp()`, regex literals, and the RegExp builtins through
the new compile and exec APIs, and stop re-validating patterns with the
deleted C++ parser on the way in. Preserve the observable error
behavior by carrying structured compile errors and backtracking-limit
failures across the FFI boundary. Cache compiled regex state and named
capture metadata on `RegExpObject` in the new representation.
Use the new API surface to simplify and speed up the builtin paths too:
share `exec_internal`, cache compiled regex pointers, keep the legacy
RegExp statics lazy, run global replace through batch `find_all`, and
optimize replace, test, split, and String helper paths. Add regression
tests for those JavaScript-visible paths.
2026-03-25 06:52:40 -03:00
|
|
|
static GC::Ref<RegExpObject> create(Realm&, Utf16String pattern, Utf16String flags);
|
2020-06-03 20:05:49 -03:00
|
|
|
|
2024-11-14 12:01:23 -03:00
|
|
|
ThrowCompletionOr<GC::Ref<RegExpObject>> regexp_initialize(VM&, Value pattern, Value flags);
|
2026-06-22 08:07:20 -03:00
|
|
|
Utf16String escape_regexp_pattern() const;
|
2021-08-20 10:14:27 -03:00
|
|
|
|
2023-08-07 03:41:28 -03:00
|
|
|
virtual void initialize(Realm&) override;
|
2022-03-14 13:25:06 -03:00
|
|
|
virtual ~RegExpObject() override = default;
|
2020-06-03 20:05:49 -03:00
|
|
|
|
2025-08-06 12:28:18 -03:00
|
|
|
Utf16String const& pattern() const { return m_pattern; }
|
|
|
|
|
Utf16String const& flags() const { return m_flags; }
|
2024-10-25 12:29:03 -03:00
|
|
|
Flags flag_bits() const { return m_flag_bits; }
|
2022-10-16 21:59:27 -03:00
|
|
|
Realm& realm() { return *m_realm; }
|
|
|
|
|
Realm const& realm() const { return *m_realm; }
|
|
|
|
|
bool legacy_features_enabled() const { return m_legacy_features_enabled; }
|
|
|
|
|
void set_legacy_features_enabled(bool legacy_features_enabled) { m_legacy_features_enabled = legacy_features_enabled; }
|
|
|
|
|
void set_realm(Realm& realm) { m_realm = &realm; }
|
2020-06-03 20:05:49 -03:00
|
|
|
|
LibJS+LibRegex: Switch RegExp over to the Rust engine
Switch LibJS `RegExp` over to the Rust-backed `ECMAScriptRegex` APIs.
Route `new RegExp()`, regex literals, and the RegExp builtins through
the new compile and exec APIs, and stop re-validating patterns with the
deleted C++ parser on the way in. Preserve the observable error
behavior by carrying structured compile errors and backtracking-limit
failures across the FFI boundary. Cache compiled regex state and named
capture metadata on `RegExpObject` in the new representation.
Use the new API surface to simplify and speed up the builtin paths too:
share `exec_internal`, cache compiled regex pointers, keep the legacy
RegExp statics lazy, run global replace through batch `find_all`, and
optimize replace, test, split, and String helper paths. Add regression
tests for those JavaScript-visible paths.
2026-03-25 06:52:40 -03:00
|
|
|
regex::ECMAScriptRegex const* cached_regex() const { return m_cached_regex; }
|
|
|
|
|
void set_cached_regex(regex::ECMAScriptRegex const* ptr) const { m_cached_regex = ptr; }
|
|
|
|
|
|
2020-06-03 20:05:49 -03:00
|
|
|
private:
|
2022-08-28 18:51:28 -03:00
|
|
|
RegExpObject(Object& prototype);
|
LibJS+LibRegex: Switch RegExp over to the Rust engine
Switch LibJS `RegExp` over to the Rust-backed `ECMAScriptRegex` APIs.
Route `new RegExp()`, regex literals, and the RegExp builtins through
the new compile and exec APIs, and stop re-validating patterns with the
deleted C++ parser on the way in. Preserve the observable error
behavior by carrying structured compile errors and backtracking-limit
failures across the FFI boundary. Cache compiled regex state and named
capture metadata on `RegExpObject` in the new representation.
Use the new API surface to simplify and speed up the builtin paths too:
share `exec_internal`, cache compiled regex pointers, keep the legacy
RegExp statics lazy, run global replace through batch `find_all`, and
optimize replace, test, split, and String helper paths. Add regression
tests for those JavaScript-visible paths.
2026-03-25 06:52:40 -03:00
|
|
|
RegExpObject(Utf16String pattern, Utf16String flags, Object& prototype);
|
2022-08-28 18:51:28 -03:00
|
|
|
|
2025-03-25 05:34:06 -03:00
|
|
|
virtual bool is_regexp_object() const final { return true; }
|
2024-04-05 14:41:25 -03:00
|
|
|
virtual void visit_edges(Visitor&) override;
|
|
|
|
|
|
2025-08-06 12:28:18 -03:00
|
|
|
Utf16String m_pattern;
|
|
|
|
|
Utf16String m_flags;
|
2024-10-25 12:29:03 -03:00
|
|
|
Flags m_flag_bits { 0 };
|
2022-10-16 21:59:27 -03:00
|
|
|
bool m_legacy_features_enabled { false }; // [[LegacyFeaturesEnabled]]
|
LibJS+LibRegex: Switch RegExp over to the Rust engine
Switch LibJS `RegExp` over to the Rust-backed `ECMAScriptRegex` APIs.
Route `new RegExp()`, regex literals, and the RegExp builtins through
the new compile and exec APIs, and stop re-validating patterns with the
deleted C++ parser on the way in. Preserve the observable error
behavior by carrying structured compile errors and backtracking-limit
failures across the FFI boundary. Cache compiled regex state and named
capture metadata on `RegExpObject` in the new representation.
Use the new API surface to simplify and speed up the builtin paths too:
share `exec_internal`, cache compiled regex pointers, keep the legacy
RegExp statics lazy, run global replace through batch `find_all`, and
optimize replace, test, split, and String helper paths. Add regression
tests for those JavaScript-visible paths.
2026-03-25 06:52:40 -03:00
|
|
|
mutable regex::ECMAScriptRegex const* m_cached_regex { nullptr };
|
2022-10-16 21:59:27 -03:00
|
|
|
// Note: This is initialized in RegExpAlloc, but will be non-null afterwards
|
2024-11-14 12:01:23 -03:00
|
|
|
GC::Ptr<Realm> m_realm; // [[Realm]]
|
2020-06-03 20:05:49 -03:00
|
|
|
};
|
|
|
|
|
|
2025-03-25 05:34:06 -03:00
|
|
|
template<>
|
|
|
|
|
inline bool Object::fast_is<RegExpObject>() const { return is_regexp_object(); }
|
|
|
|
|
|
2024-10-25 12:29:03 -03:00
|
|
|
AK_ENUM_BITWISE_OPERATORS(RegExpObject::Flags);
|
|
|
|
|
|
2020-06-03 20:05:49 -03:00
|
|
|
}
|