diff --git a/src/Escargot.h b/src/Escargot.h index 10f16efd3..0850dcde3 100755 --- a/src/Escargot.h +++ b/src/Escargot.h @@ -285,7 +285,6 @@ extern "C" { #ifdef ENABLE_ICU #if defined(ENABLE_RUNTIME_ICU_BINDER) -typedef unsigned char LChar; #include "RuntimeICUBinder.h" #include "ICUPolyfill.h" #else @@ -574,6 +573,10 @@ typedef uint16_t LexicalBlockIndex; #endif #include +#include + +namespace Escargot { + template , class KeyEqual = std::equal_to, class Allocator = std::allocator, @@ -581,7 +584,6 @@ template , class GrowthPolicy = tsl::rh::power_of_two_growth_policy<2>> using HashSet = tsl::robin_set; -#include template , class KeyEqual = std::equal_to, class Allocator = std::allocator>, @@ -589,6 +591,8 @@ template , class GrowthPolicy = tsl::rh::power_of_two_growth_policy<2>> using HashMap = tsl::robin_map; +} // namespace Escargot + #include "EscargotInfo.h" #include "heap/Heap.h" diff --git a/src/api/EscargotPublic.h b/src/api/EscargotPublic.h index 07c59360f..ff00eb05a 100644 --- a/src/api/EscargotPublic.h +++ b/src/api/EscargotPublic.h @@ -1721,12 +1721,14 @@ class ESCARGOT_EXPORT RegExpObjectRef : public ObjectRef { public: enum RegExpObjectOption { None = 0 << 0, - Global = 1 << 0, - IgnoreCase = 1 << 1, - MultiLine = 1 << 2, - Sticky = 1 << 3, - Unicode = 1 << 4, - DotAll = 1 << 5, + HasIndices = 1 << 0, + Global = 1 << 1, + IgnoreCase = 1 << 2, + MultiLine = 1 << 3, + DotAll = 1 << 4, + Unicode = 1 << 5, + UnicodeSets = 1 << 6, + Sticky = 1 << 7, }; struct ESCARGOT_EXPORT RegexMatchResult { diff --git a/src/builtins/BuiltinRegExp.cpp b/src/builtins/BuiltinRegExp.cpp index bfcfc437c..c92cda719 100644 --- a/src/builtins/BuiltinRegExp.cpp +++ b/src/builtins/BuiltinRegExp.cpp @@ -200,6 +200,29 @@ static Value builtinRegExpCompile(ExecutionState& state, Value thisValue, size_t ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, ErrorObject::Messages::GlobalObject_ThisNotRegExpObject); } + Optional proto = thisValue.asObject()->getPrototypeObject(state); + Context* calleeContext = state.resolveCallee()->codeBlock()->context(); + + if (!proto || !proto->isRegExpPrototypeObject()) { + ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, ErrorObject::Messages::GlobalObject_ThisNotRegExpObject); + } + + bool match = false; + while (proto) { + Value c = proto->getOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor)).value(state, proto.value()); + if (c.isFunction()) { + if (c.asFunction()->codeBlock()->context() == calleeContext) { + match = true; + break; + } + } + proto = proto->getPrototypeObject(state); + } + + if (!match) { + ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "Cannot use compile function with another Realm"); + } + if (argv[0].isObject() && argv[0].asObject()->isRegExpObject()) { if (!argv[1].isUndefined()) { ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "Cannot supply flags when constructing one RegExp from another"); @@ -216,9 +239,9 @@ static Value builtinRegExpCompile(ExecutionState& state, Value thisValue, size_t } RegExpObject* retVal = thisValue.asPointerValue()->asObject()->asRegExpObject(); - String* pattern_str = argv[0].isUndefined() ? String::emptyString : argv[0].toString(state); - String* flags_str = argv[1].isUndefined() ? String::emptyString : argv[1].toString(state); - retVal->init(state, pattern_str, flags_str); + String* patternStr = argv[0].isUndefined() ? String::emptyString : argv[0].toString(state); + String* flagsStr = argv[1].isUndefined() ? String::emptyString : argv[1].toString(state); + retVal->init(state, patternStr, flagsStr); return retVal; } static Value builtinRegExpSearch(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional newTarget) @@ -620,6 +643,11 @@ static Value builtinRegExpMultiLineGetter(ExecutionState& state, Value thisValue return builtinRegExpOptionGetterHelper(state, thisValue, RegExpObject::Option::MultiLine); } +static Value builtinRegExpHasIndicesGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional newTarget) +{ + return builtinRegExpOptionGetterHelper(state, thisValue, RegExpObject::Option::HasIndices); +} + static Value builtinRegExpSourceGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional newTarget) { if (!thisValue.isObject()) { @@ -868,6 +896,13 @@ void GlobalObject::installRegExp(ExecutionState& state) m_regexpPrototype->directDefineOwnProperty(state, ObjectPropertyName(state, strings->multiline), desc); } + { + Value getter = new NativeFunctionObject(state, NativeFunctionInfo(strings->getHasIndices, builtinRegExpHasIndicesGetter, 0, NativeFunctionInfo::Strict)); + JSGetterSetter gs(getter, Value()); + ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent); + m_regexpPrototype->directDefineOwnProperty(state, ObjectPropertyName(state, strings->hasIndices), desc); + } + { Value getter = new NativeFunctionObject(state, NativeFunctionInfo(strings->getSource, builtinRegExpSourceGetter, 0, NativeFunctionInfo::Strict)); JSGetterSetter gs(getter, Value()); diff --git a/src/parser/Lexer.cpp b/src/parser/Lexer.cpp index 06896c670..47986bd11 100644 --- a/src/parser/Lexer.cpp +++ b/src/parser/Lexer.cpp @@ -1984,7 +1984,11 @@ void Scanner::scanRegExp(Scanner::ScannerResult* token) String* body = this->scanRegExpBody(); String* flags = this->scanRegExpFlags(); - // const value = this->testRegExp(body.value, flags.value); + + auto error = RegExpObject::checkRegExpSyntax(body, flags); + if (UNLIKELY(error)) { + ErrorHandler::throwError(this->index, this->lineNumber, this->index - this->lineStart + 1, error.value(), ErrorCode::SyntaxError); + } ScanRegExpResult result; result.body = body; diff --git a/src/parser/esprima_cpp/esprima.cpp b/src/parser/esprima_cpp/esprima.cpp index f9d84e581..35d77759e 100644 --- a/src/parser/esprima_cpp/esprima.cpp +++ b/src/parser/esprima_cpp/esprima.cpp @@ -208,14 +208,9 @@ class Parser { { ASSERT(escargotContext != nullptr); - this->stackLimit = ThreadLocal::stackLimit(); - // Use more stack for computing loc on stack-overflow situation -#ifdef STACK_GROWS_DOWN - this->stackLimit = this->stackLimit + STACK_FREESPACE_FROM_LIMIT / 2; -#else - this->stackLimit = this->stackLimit - STACK_FREESPACE_FROM_LIMIT / 2; -#endif + this->stackLimit = ThreadLocal::extendedStackLimit(); + this->escargotContext = escargotContext; this->stringArguments = escargotContext->staticStrings().arguments; this->currentBlockContext = nullptr; diff --git a/src/runtime/RegExpObject.cpp b/src/runtime/RegExpObject.cpp index d1c7b5227..d474a2935 100644 --- a/src/runtime/RegExpObject.cpp +++ b/src/runtime/RegExpObject.cpp @@ -28,6 +28,7 @@ #include "Yarr.h" #include "YarrPattern.h" #include "YarrInterpreter.h" +#include "YarrSyntaxChecker.h" namespace Escargot { @@ -182,6 +183,7 @@ bool RegExpObject::defineOwnProperty(ExecutionState& state, const ObjectProperty || name->equals(state.context()->staticStrings().sticky.string()) || name->equals(state.context()->staticStrings().dotAll.string()) || name->equals(state.context()->staticStrings().source.string()) + || name->equals(state.context()->staticStrings().hasIndices.string()) || name->equals(state.context()->staticStrings().flags.string())) { m_hasOwnPropertyWhichHasDefinedFromRegExpPrototype = true; } @@ -233,6 +235,16 @@ RegExpObject::Option RegExpObject::parseOption(ExecutionState& state, String* op ErrorObject::throwBuiltinError(state, ErrorCode::SyntaxError, "RegExp has multiple 's' flags"); tempOption = (Option)(tempOption | Option::DotAll); break; + case 'v': + if (tempOption & Option::UnicodeSets) + ErrorObject::throwBuiltinError(state, ErrorCode::SyntaxError, "RegExp has multiple 'v' flags"); + tempOption = (Option)(tempOption | Option::UnicodeSets); + break; + case 'd': + if (tempOption & Option::HasIndices) + ErrorObject::throwBuiltinError(state, ErrorCode::SyntaxError, "RegExp has multiple 'd' flags"); + tempOption = (Option)(tempOption | Option::HasIndices); + break; default: ErrorObject::throwBuiltinError(state, ErrorCode::SyntaxError, "RegExp has invalid flag"); } @@ -465,6 +477,40 @@ ArrayObject* RegExpObject::createRegExpMatchedArray(ExecutionState& state, const } } + if (option() & HasIndices) { + ArrayObject* indices = new ArrayObject(state, len); + arr->directDefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().indices), ObjectPropertyDescriptor(Value(indices), ObjectPropertyDescriptor::AllPresent)); + + size_t idx = 0; + for (unsigned i = 0; i < result.m_matchResults.size(); i++) { + for (unsigned j = 0; j < result.m_matchResults[i].size(); j++) { + if (result.m_matchResults[i][j].m_start == std::numeric_limits::max()) { + indices->defineOwnIndexedPropertyWithoutExpanding(state, idx++, Value()); + } else { + ArrayObject* pair = new ArrayObject(state, 2); + pair->defineOwnIndexedPropertyWithoutExpanding(state, 0, Value(result.m_matchResults[i][j].m_start)); + pair->defineOwnIndexedPropertyWithoutExpanding(state, 1, Value(result.m_matchResults[i][j].m_end)); + + indices->defineOwnIndexedPropertyWithoutExpanding(state, idx++, Value(pair)); + } + } + } + + if (m_yarrPattern->m_namedGroupToParenIndices.empty()) { + indices->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().groups), ObjectPropertyDescriptor(Value(), ObjectPropertyDescriptor::AllPresent)); + } else { + Object* groups = new Object(state, Object::PrototypeIsNull); + for (auto it = m_yarrPattern->m_captureGroupNames.begin(); it != m_yarrPattern->m_captureGroupNames.end(); ++it) { + auto foundMapElement = m_yarrPattern->m_namedGroupToParenIndices.find(*it); + if (foundMapElement != m_yarrPattern->m_namedGroupToParenIndices.end()) { + groups->directDefineOwnProperty(state, ObjectPropertyName(state, it->impl()), + ObjectPropertyDescriptor(indices->getOwnProperty(state, ObjectPropertyName(state, foundMapElement->second[0])).value(state, this), ObjectPropertyDescriptor::AllPresent)); + } + } + indices->directDefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().groups), ObjectPropertyDescriptor(Value(groups), ObjectPropertyDescriptor::AllPresent)); + } + } + if (m_yarrPattern->m_namedGroupToParenIndices.empty()) { arr->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().groups), ObjectPropertyDescriptor(Value(), ObjectPropertyDescriptor::AllPresent)); } else { @@ -533,6 +579,16 @@ Value RegExpObject::regexpFlagsValue(ExecutionState& state, Object* obj) } } +Optional RegExpObject::checkRegExpSyntax(String* pattern, String* flags) +{ + JSC::Yarr::ErrorCode errorCode = JSC::Yarr::checkSyntax(pattern, flags); + if (errorCode != JSC::Yarr::ErrorCode::NoError) { + auto str = JSC::Yarr::errorMessage(errorCode); + return String::fromASCII(str, strlen(str)); + } + return nullptr; +} + String* RegExpObject::computeRegExpOptionString(ExecutionState& state, Object* obj) { char flags[8] = { 0 }; diff --git a/src/runtime/RegExpObject.h b/src/runtime/RegExpObject.h index 13fc025ab..d05e31a69 100644 --- a/src/runtime/RegExpObject.h +++ b/src/runtime/RegExpObject.h @@ -173,6 +173,8 @@ class RegExpObject : public DerivedObject { static String* computeRegExpOptionString(ExecutionState& state, Object* obj); static String* regexpSourceValue(ExecutionState& state, Object* obj); static Value regexpFlagsValue(ExecutionState& state, Object* obj); + // returns error string if there is error + static Optional checkRegExpSyntax(String* pattern, String* flags); protected: explicit RegExpObject(ExecutionState& state, Object* proto, bool hasLastIndex = true); diff --git a/src/runtime/StaticStrings.cpp b/src/runtime/StaticStrings.cpp index 61d195bb6..e82666ec0 100644 --- a/src/runtime/StaticStrings.cpp +++ b/src/runtime/StaticStrings.cpp @@ -97,6 +97,7 @@ void StaticStrings::initStaticStrings() INIT_STATIC_STRING(getFlags, "get flags"); INIT_STATIC_STRING(getFormat, "get format"); INIT_STATIC_STRING(getGlobal, "get global"); + INIT_STATIC_STRING(getHasIndices, "get hasIndices"); INIT_STATIC_STRING(getHourCycle, "get hourCycle"); INIT_STATIC_STRING(getHourCycles, "get hourCycles"); INIT_STATIC_STRING(getIgnoreCase, "get ignoreCase"); diff --git a/src/runtime/StaticStrings.h b/src/runtime/StaticStrings.h index f3f75af33..d231e560a 100644 --- a/src/runtime/StaticStrings.h +++ b/src/runtime/StaticStrings.h @@ -288,6 +288,7 @@ namespace Escargot { F(implements) \ F(imul) \ F(includes) \ + F(indices) \ F(index) \ F(indexOf) \ F(input) \ @@ -1002,6 +1003,7 @@ class StaticStrings { AtomicString getFlags; AtomicString getFormat; AtomicString getGlobal; + AtomicString getHasIndices; AtomicString getHourCycle; AtomicString getHourCycles; AtomicString getIgnoreCase; diff --git a/src/runtime/ThreadLocal.h b/src/runtime/ThreadLocal.h index da5a82a40..d4d36fd9d 100644 --- a/src/runtime/ThreadLocal.h +++ b/src/runtime/ThreadLocal.h @@ -118,6 +118,16 @@ class ThreadLocal { return g_stackLimit; } + // Use this limit if you want to use more stack + static size_t extendedStackLimit() + { +#ifdef STACK_GROWS_DOWN + return stackLimit() + STACK_FREESPACE_FROM_LIMIT / 2; +#else + return stackLimit() - STACK_FREESPACE_FROM_LIMIT / 2; +#endif + } + static std::mt19937& randEngine() { ASSERT(inited && !!g_randEngine); diff --git a/test/vendortest b/test/vendortest index dab636534..4163d8e45 160000 --- a/test/vendortest +++ b/test/vendortest @@ -1 +1 @@ -Subproject commit dab6365343219e88a11f0aebb5c3b4f6bb8551bd +Subproject commit 4163d8e45071951f626005c0fe5927a9e0c4b6be diff --git a/third_party/yarr/HashMap.h b/third_party/yarr/HashMap.h new file mode 100644 index 000000000..3d2a09a13 --- /dev/null +++ b/third_party/yarr/HashMap.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2024-present Samsung Electronics Co., Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#pragma once + +#include +#include + +namespace WTF { + +template >> +class HashMap : public std::unordered_map, std::equal_to, Allocator> { +public: + struct AddResult { + bool isNewEntry; + typename std::unordered_map, std::equal_to, Allocator>::iterator iterator; + }; + AddResult add(const Key& k, const Value& v) + { + AddResult r; + auto result = std::unordered_map, std::equal_to, Allocator>::insert(std::make_pair(k, v)); + r.iterator = result.first; + r.isNewEntry = result.second; + return r; + } + + const Value& get(const Key& k) + { + return std::unordered_map, std::equal_to, Allocator>::find(k)->second; + } +}; + +} // namespace WTF + +using WTF::HashMap; diff --git a/third_party/yarr/HashSet.h b/third_party/yarr/HashSet.h new file mode 100644 index 000000000..95d304de0 --- /dev/null +++ b/third_party/yarr/HashSet.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2024-present Samsung Electronics Co., Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#pragma once + +#include +#include + +namespace WTF { + +template > +class HashSet : public std::unordered_set, std::equal_to, Allocator> { +public: + struct AddResult { + bool isNewEntry; + }; + AddResult add(const Key& k) + { + AddResult r; + r.isNewEntry = std::unordered_set, std::equal_to, Allocator>::insert(k).second; + return r; + } + + template + void formUnion(const Other& other) + { + for (const auto& value: other) { + add(value); + } + } + + bool contains(const Key& k) + { + return std::unordered_set, std::equal_to, Allocator>::find(k) != std::unordered_set, std::equal_to, Allocator>::end(); + } + + bool isEmpty() + { + return std::unordered_set, std::equal_to, Allocator>::empty(); + } +}; + +} // namespace WTF + +using WTF::HashSet; diff --git a/third_party/yarr/OptionSet.h b/third_party/yarr/OptionSet.h index 65d39083a..4c3325e73 100644 --- a/third_party/yarr/OptionSet.h +++ b/third_party/yarr/OptionSet.h @@ -94,6 +94,24 @@ template class OptionSet { constexpr iterator begin() const { return m_storage; } constexpr iterator end() const { return 0; } + void add(OptionSet optionSet) + { + m_storage |= optionSet.m_storage; + } + + void remove(OptionSet optionSet) + { + m_storage &= ~optionSet.m_storage; + } + + void set(OptionSet optionSet, bool value) + { + if (value) + add(optionSet); + else + remove(optionSet); + } + constexpr bool contains(OptionSet optionSet) const { return m_storage & optionSet.m_storage; diff --git a/third_party/yarr/StackCheck.h b/third_party/yarr/StackCheck.h new file mode 100644 index 000000000..76309877a --- /dev/null +++ b/third_party/yarr/StackCheck.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024-present Samsung Electronics Co., Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#pragma once + +namespace WTF { + +class StackCheck { +public: + StackCheck() + { + m_stackLimit = Escargot::ThreadLocal::extendedStackLimit(); + } + bool isSafeToRecurse() + { +#ifdef STACK_GROWS_DOWN + return m_stackLimit < (size_t)Escargot::currentStackPointer(); +#else + return m_stackLimit > (size_t)Escargot::currentStackPointer(); +#endif + } + +private: + size_t m_stackLimit; +}; + +} // namespace WTF + +using WTF::StackCheck; diff --git a/third_party/yarr/Vector.h b/third_party/yarr/Vector.h new file mode 100644 index 000000000..cd0230fde --- /dev/null +++ b/third_party/yarr/Vector.h @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2016-present Samsung Electronics Co., Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#pragma once + +#include +#include + +namespace WTF { + +template +class Vector { +public: + typedef typename std::vector::iterator iterator; + typedef typename std::vector::const_iterator const_iterator; + std::vector impl; + +public: + Vector() {} + Vector(const Vector& v) + { + append(v); + } + + Vector(const T* v, size_t len) + { + impl.reserve(len); + for (size_t i = 0; i < len; i ++) { + impl.push_back(v[i]); + } + } + + Vector(std::initializer_list list) + { + impl.reserve(list.size()); + for (auto& i : list) { + impl.push_back(i); + } + } + + size_t size() const + { + return impl.size(); + } + + T& operator[](size_t i) + { + return impl[i]; + } + + const T& operator[](size_t i) const + { + return impl[i]; + } + + T& at(size_t i) + { + return impl[i]; + } + + T* data() + { + return impl.data(); + } + + iterator begin() + { + return impl.begin(); + } + + iterator end() + { + return impl.end(); + } + + const_iterator begin() const + { + return impl.begin(); + } + + const_iterator end() const + { + return impl.end(); + } + + T& last() + { + return impl.back(); + } + + bool isEmpty() const + { + return impl.empty(); + } + + template + void append(const U& u) + { + impl.push_back(static_cast(u)); + } + + void append(T&& u) + { + impl.push_back(std::move(u)); + } + + template + void append(const Vector& v) + { + impl.insert(impl.end(), v.impl.begin(), v.impl.end()); + } + + void insert(size_t i, const T& t) + { + impl.insert(impl.begin() + i, t); + } + + void remove(size_t i) + { + impl.erase(impl.begin() + i); + } + + void removeLast() + { + impl.pop_back(); + } + + void clear() + { + std::vector().swap(impl); + } + + void grow(size_t s) + { + impl.resize(s); + } + + void shrink(size_t newLength) + { + ASSERT(newLength <= impl.size()); + while (impl.size() != newLength) { + impl.pop_back(); + } + } + + void shrinkToFit() + { + impl.shrink_to_fit(); + } + + size_t capacity() const + { + return impl.capacity(); + } + + void reserveInitialCapacity(size_t siz) + { + impl.reserve(siz); + } + + void swap(Vector& other) + { + impl.swap(other.impl); + } + + void deleteAllValues() + { + clear(); + } + + void reserve(size_t capacity) + { + impl.reserve(capacity); + } + + T takeLast() + { + T last(*impl.rbegin()); + impl.pop_back(); + return last; + } + + void fill(const T& val, size_t newSize) + { + if (size() > newSize) + shrink(newSize); + else if (newSize > capacity()) { + clear(); + grow(newSize); + } + std::fill(begin(), end(), val); + } + +}; + +} // namespace WTF + +using WTF::Vector; diff --git a/third_party/yarr/WTFBridge.h b/third_party/yarr/WTFBridge.h index 72db94cfe..07ec8ec26 100644 --- a/third_party/yarr/WTFBridge.h +++ b/third_party/yarr/WTFBridge.h @@ -41,6 +41,9 @@ #define yarr_wtfbridge_h #include "Escargot.h" + +#include +#include #include #define JS_EXPORT_PRIVATE @@ -166,457 +169,15 @@ bool findBitInWord(T word, size_t& startOrResultIndex, size_t endIndex, bool val #include "runtime/String.h" #include "CheckedArithmetic.h" -#include "StringHasher.h" -#include "SuperFastHash.h" -#include "StringHasherInlines.h" - -#include -#include - -typedef unsigned char LChar; - -enum TextCaseSensitivity { - TextCaseSensitive, - TextCaseInsensitive -}; - - -namespace JSC { -namespace Yarr { -template -class Vector { -public: - typedef typename std::vector::iterator iterator; - typedef typename std::vector::const_iterator const_iterator; - std::vector impl; - -public: - Vector() {} - Vector(const Vector& v) - { - append(v); - } - - Vector(const T* v, size_t len) - { - impl.reserve(len); - for (size_t i = 0; i < len; i ++) { - impl.push_back(v[i]); - } - } - - Vector(std::initializer_list list) - { - impl.reserve(list.size()); - for (auto& i : list) { - impl.push_back(i); - } - } - - size_t size() const - { - return impl.size(); - } - - T& operator[](size_t i) - { - return impl[i]; - } - - const T& operator[](size_t i) const - { - return impl[i]; - } - - T& at(size_t i) - { - return impl[i]; - } - - T* data() - { - return impl.data(); - } - - iterator begin() - { - return impl.begin(); - } - - iterator end() - { - return impl.end(); - } - - const_iterator begin() const - { - return impl.begin(); - } - - const_iterator end() const - { - return impl.end(); - } - - T& last() - { - return impl.back(); - } - - bool isEmpty() const - { - return impl.empty(); - } - - template - void append(const U& u) - { - impl.push_back(static_cast(u)); - } - - void append(T&& u) - { - impl.push_back(std::move(u)); - } - - template - void append(const Vector& v) - { - impl.insert(impl.end(), v.impl.begin(), v.impl.end()); - } - - void insert(size_t i, const T& t) - { - impl.insert(impl.begin() + i, t); - } - - void remove(size_t i) - { - impl.erase(impl.begin() + i); - } - - void removeLast() - { - impl.pop_back(); - } - - void clear() - { - std::vector().swap(impl); - } - - void grow(size_t s) - { - impl.resize(s); - } - - void shrink(size_t newLength) - { - ASSERT(newLength <= impl.size()); - while (impl.size() != newLength) { - impl.pop_back(); - } - } - - void shrinkToFit() - { - impl.shrink_to_fit(); - } - - size_t capacity() const - { - return impl.capacity(); - } - - void reserveInitialCapacity(size_t siz) - { - impl.reserve(siz); - } - - void swap(Vector& other) - { - impl.swap(other.impl); - } - - void deleteAllValues() - { - clear(); - } - - void reserve(size_t capacity) - { - impl.reserve(capacity); - } - - T takeLast() - { - T last(*impl.rbegin()); - impl.pop_back(); - return last; - } - - void fill(const T& val, size_t newSize) - { - if (size() > newSize) - shrink(newSize); - else if (newSize > capacity()) { - clear(); - grow(newSize); - } - std::fill(begin(), end(), val); - } - -}; - - -template -inline void -deleteAllValues(Vector& v) -{ - v.deleteAllValues(); -} - -static inline void -dataLog(const char* fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); -} - -template >> -class HashMap : public std::unordered_map, std::equal_to, Allocator> { -public: - struct AddResult { - bool isNewEntry; - typename std::unordered_map, std::equal_to, Allocator>::iterator iterator; - }; - AddResult add(const Key& k, const Value& v) - { - AddResult r; - auto result = std::unordered_map, std::equal_to, Allocator>::insert(std::make_pair(k, v)); - r.iterator = result.first; - r.isNewEntry = result.second; - return r; - } - - const Value& get(const Key& k) - { - return std::unordered_map, std::equal_to, Allocator>::find(k)->second; - } -}; -template > -class HashSet : public std::unordered_set, std::equal_to, Allocator> { -public: - struct AddResult { - bool isNewEntry; - }; - AddResult add(const Key& k) - { - AddResult r; - r.isNewEntry = std::unordered_set, std::equal_to, Allocator>::insert(k).second; - return r; - } - - template - void formUnion(const Other& other) - { - for (const auto& value: other) { - add(value); - } - } - - bool contains(const Key& k) - { - return std::unordered_set, std::equal_to, Allocator>::find(k) != std::unordered_set, std::equal_to, Allocator>::end(); - } - - bool isEmpty() - { - return std::unordered_set, std::equal_to, Allocator>::empty(); - } -}; +namespace WTF { template using Optional = Escargot::Optional; -class String { -public: - String() - : m_impl() - { - } - - String(::Escargot::String* impl) - : m_impl(impl) - { - } - - ALWAYS_INLINE char16_t operator[](const size_t idx) const - { - if (isNull()) { - return 0; - } - return m_impl->charAt(idx); - } - - ALWAYS_INLINE size_t length() const - { - if (isNull()) { - return 0; - } - return m_impl->length(); - } - - bool equals(const String& src) const - { - if (isNull() && src.isNull()) { - return true; - } - if (isNull() || src.isNull()) { - return false; - } - return m_impl.value()->equals(src.m_impl.value()); - } - - ALWAYS_INLINE size_t hash() const - { - if (isNull()) { - return 0; - } - if (m_impl->is8Bit()) { - return StringHasher::computeHashAndMaskTop8Bits(m_impl->characters8(), m_impl->length()); - } else { - return StringHasher::computeHashAndMaskTop8Bits(m_impl->characters16(), m_impl->length()); - } - } - - bool contains(char c) const - { - if (isNull()) { - return false; - } - char b[2] = { c, 0x0 }; - return m_impl->contains(b); - } - - bool isNull() const - { - return !m_impl; - } - - ALWAYS_INLINE bool is8Bit() const - { - if (isNull()) { - return true; - } - return m_impl->is8Bit(); - } - - template - const Any* characters() const - { - if (isNull()) { - return nullptr; - } - if (is8Bit()) { - return (Any*)m_impl->characters8(); - } else { - return (Any*)m_impl->characters16(); - } - } - - ALWAYS_INLINE const LChar* characters8() const - { - if (isNull()) { - return nullptr; - } - return m_impl->characters8(); - } - - ALWAYS_INLINE const char16_t* characters16() const - { - if (isNull()) { - return nullptr; - } - return m_impl->characters16(); - } - - ALWAYS_INLINE::Escargot::String* impl() - { - return m_impl.value(); - } - - template - ALWAYS_INLINE bool operator==(const char (&src)[srcLen]) const - { - if (isNull()) { - return !srcLen; - } - return m_impl->equals(src); - } - -private: - Optional<::Escargot::String*> m_impl; -}; - -using StringView = const String&; - -class StringBuilder { -public: - void append(int c) - { - char16_t buf[2]; - auto cnt = ::Escargot::utf32ToUtf16((char32_t)c, buf); - m_impl.appendChar(buf[0]); - if (cnt == 2) { - m_impl.appendChar(buf[1]); - } - } - - String toString() - { - return m_impl.finalize(); - } - - void clear() - { - m_impl.clear(); - } - -private: - ::Escargot::StringBuilder m_impl; -}; - typedef Checked CheckedUint32; -} /* namespace Yarr */ - -} /* namespace JSC */ - -namespace std { -template <> -struct hash<::JSC::Yarr::String> { - size_t operator()(::JSC::Yarr::String const& x) const - { - return x.hash(); - } -}; - -template <> -struct equal_to<::JSC::Yarr::String> { - bool operator()(::JSC::Yarr::String const& a, ::JSC::Yarr::String const& b) const - { - return a.equals(b); - } -}; -} - -namespace WTF { -const size_t notFound = static_cast(-1); -using String = ::JSC::Yarr::String; +constexpr size_t notFound = static_cast(-1); // Returns a count of the number of bits set in 'bits'. inline size_t bitCount(unsigned bits) @@ -643,13 +204,48 @@ inline ToType bitwise_cast(FromType from) return u.to; } -} +} /* namespace WTF */ + +using WTF::CheckedUint32; #include "ASCIICType.h" +#include "StringHasher.h" +#include "SuperFastHash.h" +#include "StringHasherInlines.h" +#include "WTFString.h" + +#include "Vector.h" +#include "HashMap.h" +#include "HashSet.h" + #include "BitSet.h" #include "BitVector.h" #include "OptionSet.h" +#include "StackCheck.h" + +namespace std { +template <> +struct hash<::WTF::String> { + size_t operator()(::WTF::String const& x) const + { + return x.hash(); + } +}; + +template <> +struct equal_to<::WTF::String> { + bool operator()(::WTF::String const& a, ::WTF::String const& b) const + { + return a.equals(b); + } +}; +} + + +using WTF::Optional; +using WTF::StringView; + #undef RELEASE_ASSERT #define RELEASE_ASSERT ASSERT diff --git a/third_party/yarr/WTFString.h b/third_party/yarr/WTFString.h new file mode 100644 index 000000000..1d53c2c1f --- /dev/null +++ b/third_party/yarr/WTFString.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2024-present Samsung Electronics Co., Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#pragma once + +#include "runtime/String.h" + +namespace WTF { + +typedef unsigned char LChar; + +enum TextCaseSensitivity { + TextCaseSensitive, + TextCaseInsensitive +}; + +class String { +public: + String() + : m_impl() + { + } + + String(::Escargot::String* impl) + : m_impl(impl) + { + } + + ALWAYS_INLINE char16_t operator[](const size_t idx) const + { + if (isNull()) { + return 0; + } + return m_impl->charAt(idx); + } + + ALWAYS_INLINE size_t length() const + { + if (isNull()) { + return 0; + } + return m_impl->length(); + } + + bool equals(const String& src) const + { + if (isNull() && src.isNull()) { + return true; + } + if (isNull() || src.isNull()) { + return false; + } + return m_impl.value()->equals(src.m_impl.value()); + } + + ALWAYS_INLINE size_t hash() const + { + if (isNull()) { + return 0; + } + if (m_impl->is8Bit()) { + return StringHasher::computeHashAndMaskTop8Bits(m_impl->characters8(), m_impl->length()); + } else { + return StringHasher::computeHashAndMaskTop8Bits(m_impl->characters16(), m_impl->length()); + } + } + + bool contains(char c) const + { + if (isNull()) { + return false; + } + char b[2] = { c, 0x0 }; + return m_impl->contains(b); + } + + bool isNull() const + { + return !m_impl; + } + + ALWAYS_INLINE bool is8Bit() const + { + if (isNull()) { + return true; + } + return m_impl->is8Bit(); + } + + template + const Any* characters() const + { + if (isNull()) { + return nullptr; + } + if (is8Bit()) { + return (Any*)m_impl->characters8(); + } else { + return (Any*)m_impl->characters16(); + } + } + + ALWAYS_INLINE const LChar* characters8() const + { + if (isNull()) { + return nullptr; + } + return m_impl->characters8(); + } + + ALWAYS_INLINE const char16_t* characters16() const + { + if (isNull()) { + return nullptr; + } + return m_impl->characters16(); + } + + ALWAYS_INLINE::Escargot::String* impl() + { + return m_impl.value(); + } + + template + ALWAYS_INLINE bool operator==(const char (&src)[srcLen]) const + { + if (isNull()) { + return !srcLen; + } + return m_impl->equals(src); + } + +private: + Optional<::Escargot::String*> m_impl; +}; + +using StringView = const String&; + +class StringBuilder { +public: + void append(int c) + { + char16_t buf[2]; + auto cnt = ::Escargot::utf32ToUtf16((char32_t)c, buf); + m_impl.appendChar(buf[0]); + if (cnt == 2) { + m_impl.appendChar(buf[1]); + } + } + + String toString() + { + return m_impl.finalize(); + } + + void clear() + { + m_impl.clear(); + } + +private: + ::Escargot::StringBuilder m_impl; +}; + +} // namespace WTF + +using WTF::LChar; +using WTF::String; +using WTF::StringView; +using WTF::StringBuilder; diff --git a/third_party/yarr/YarrFlags.cpp b/third_party/yarr/YarrFlags.cpp new file mode 100644 index 000000000..70214473d --- /dev/null +++ b/third_party/yarr/YarrFlags.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2019 Sony Interactive Entertainment Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "WTFBridge.h" +#include "YarrFlags.h" + +namespace JSC { namespace Yarr { + +Optional> parseFlags(StringView string) +{ + OptionSet flags; + + for (size_t i = 0; i < string.length(); i ++) { + char16_t character = string[i]; + switch (character) { +#define JSC_HANDLE_REGEXP_FLAG(key, name, lowerCaseName, _) \ + case key: \ + if (flags.contains(Flags::name)) \ + return nullptr; \ + flags.add(Flags::name); \ + break; + + JSC_REGEXP_FLAGS(JSC_HANDLE_REGEXP_FLAG) + +#undef JSC_HANDLE_REGEXP_FLAG + + default: + return nullptr; + } + } + + // Can only specify one of 'u' and 'v' flags. + if (flags.contains(Flags::Unicode) && flags.contains(Flags::UnicodeSets)) + return nullptr; + + return flags; +} + +} } // namespace JSC::Yarr diff --git a/third_party/yarr/YarrFlags.h b/third_party/yarr/YarrFlags.h index e16b8d032..7230ce2b9 100644 --- a/third_party/yarr/YarrFlags.h +++ b/third_party/yarr/YarrFlags.h @@ -50,4 +50,6 @@ enum class Flags : uint16_t { DeletedValue = 1 << numberOfFlags, }; +JS_EXPORT_PRIVATE Optional> parseFlags(StringView); + } } // namespace JSC::Yarr diff --git a/third_party/yarr/YarrInterpreter.cpp b/third_party/yarr/YarrInterpreter.cpp index 87c737356..2fef5a885 100644 --- a/third_party/yarr/YarrInterpreter.cpp +++ b/third_party/yarr/YarrInterpreter.cpp @@ -2111,15 +2111,13 @@ class Interpreter { inline bool isUnicodeSetsCompilation() const { return compileMode == CompileMode::UnicodeSets; } inline bool isEitherUnicodeCompilation() const { return isUnicodeCompilation() || isUnicodeSetsCompilation(); } - // inline bool isSafeToRecurse() { return m_stackCheck.isSafeToRecurse(); } - // TODO - inline bool isSafeToRecurse() { return true; } + inline bool isSafeToRecurse() { return m_stackCheck.isSafeToRecurse(); } BytecodePattern* pattern; CompileMode compileMode; unsigned* output; InputStream input; - // StackCheck m_stackCheck; + StackCheck m_stackCheck; WTF::BumpPointerPool* allocatorPool { nullptr }; unsigned startOffset; unsigned remainingMatchCount; @@ -2722,14 +2720,11 @@ class ByteCompiler { } private: - // TODO - // inline bool isSafeToRecurse() { return m_stackCheck.isSafeToRecurse(); } - inline bool isSafeToRecurse() { return true; } + inline bool isSafeToRecurse() { return m_stackCheck.isSafeToRecurse(); } YarrPattern& m_pattern; std::unique_ptr m_bodyDisjunction; - // TODO - // StackCheck m_stackCheck; + StackCheck m_stackCheck; unsigned m_currentAlternativeIndex { 0 }; Vector m_parenthesesStack; Vector> m_allParenthesesInfo; diff --git a/third_party/yarr/YarrPattern.cpp b/third_party/yarr/YarrPattern.cpp index d54abb4a6..0dc49f078 100644 --- a/third_party/yarr/YarrPattern.cpp +++ b/third_party/yarr/YarrPattern.cpp @@ -2044,8 +2044,7 @@ class YarrPatternConstructor { return m_parenthesisContext.matchDirection(); } - // inline bool isSafeToRecurse() { return m_stackCheck.isSafeToRecurse(); } - inline bool isSafeToRecurse() { return true; } + inline bool isSafeToRecurse() { return m_stackCheck.isSafeToRecurse(); } YarrPattern& m_pattern; PatternAlternative* m_alternative; @@ -2053,8 +2052,7 @@ class YarrPatternConstructor { CharacterClassConstructor* m_currentCharacterClassConstructor; Vector m_characterClassStack; Vector m_forwardReferencesInLookbehind; - // TODO - // StackCheck m_stackCheck; + StackCheck m_stackCheck; ErrorCode m_error { ErrorCode::NoError }; bool m_invertCharacterClass; ParenthesisContext m_parenthesisContext; diff --git a/third_party/yarr/YarrSyntaxChecker.cpp b/third_party/yarr/YarrSyntaxChecker.cpp new file mode 100644 index 000000000..72079e60e --- /dev/null +++ b/third_party/yarr/YarrSyntaxChecker.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2011, 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "WTFBridge.h" +#include "YarrSyntaxChecker.h" + +#include "YarrFlags.h" +#include "YarrParser.h" + +namespace JSC { namespace Yarr { + +class SyntaxChecker { +public: + void assertionBOL() { } + void assertionEOL() { } + void assertionWordBoundary(bool) { } + void atomPatternCharacter(char32_t) { } + void atomBuiltInCharacterClass(BuiltInCharacterClassID, bool) { } + void atomCharacterClassBegin(bool = false) { } + void atomCharacterClassAtom(UChar) { } + void atomCharacterClassRange(UChar, UChar) { } + void atomCharacterClassBuiltIn(BuiltInCharacterClassID, bool) { } + void atomClassStringDisjunction(Vector>&) { } + void atomCharacterClassSetOp(CharacterClassSetOp) { } + void atomCharacterClassPushNested() { } + void atomCharacterClassPopNested() { } + void atomCharacterClassEnd() { } + void atomParenthesesSubpatternBegin(bool = true, Optional = nullptr) { } + void atomParentheticalAssertionBegin(bool, MatchDirection) { } + void atomParenthesesEnd() { } + void atomBackReference(unsigned) { } + void atomNamedBackReference(const String&) { } + void atomNamedForwardReference(const String&) { } + void quantifyAtom(unsigned, unsigned, bool) { } + void disjunction(CreateDisjunctionPurpose) { } + void resetForReparsing() { } +}; + +ErrorCode checkSyntax(StringView pattern, StringView flags) +{ + SyntaxChecker syntaxChecker; + + auto parsedFlags = parseFlags(flags); + if (!parsedFlags) + return ErrorCode::InvalidRegularExpressionFlags; + + return parse(syntaxChecker, pattern, compileMode(parsedFlags)); +} + +}} // JSC::Yarr diff --git a/third_party/yarr/YarrSyntaxChecker.h b/third_party/yarr/YarrSyntaxChecker.h new file mode 100644 index 000000000..c287b3fb2 --- /dev/null +++ b/third_party/yarr/YarrSyntaxChecker.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "YarrErrorCode.h" + +namespace JSC { namespace Yarr { + +ErrorCode checkSyntax(StringView pattern, StringView flags); + +}} // JSC::Yarr diff --git a/tools/test/test262/excludelist.orig.xml b/tools/test/test262/excludelist.orig.xml index 164e23fa3..e68130990 100644 --- a/tools/test/test262/excludelist.orig.xml +++ b/tools/test/test262/excludelist.orig.xml @@ -31,8 +31,6 @@ ICU 67 returns wrong result with -0.0001 ICU 67 returns wrong result with -0.0001 - TODO - TODO TODO TODO TODO @@ -581,20 +579,6 @@ TODO TODO TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO TODO TODO TODO @@ -602,176 +586,6 @@ TODO TODO TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO TODO TODO TODO @@ -784,45 +598,7 @@ TODO TODO TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO TODO TODO TODO @@ -831,120 +607,9 @@ TODO TODO TODO - TODO + TODO TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO - TODO TODO TODO TODO diff --git a/tools/test/v8/v8.mjsunit.status b/tools/test/v8/v8.mjsunit.status index a1686939d..86032fc0b 100644 --- a/tools/test/v8/v8.mjsunit.status +++ b/tools/test/v8/v8.mjsunit.status @@ -804,7 +804,8 @@ 'json-parser-recursive': [SKIP], # Yarr support number in { } uint32 range 'regress/regress-126412': [SKIP], - + # Stackoverflow occured when paring RegExp + 'regress/regress-148378': [SKIP], }], # 'escargot == True' ]