| Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/qtdeclarative/src/qtdeclarative/src/qml/jsruntime/qv4regexpobject.cpp |
| Source code | Switch to Preprocessed file |
| Line | Source | Count | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | /**************************************************************************** | - | ||||||||||||
| 2 | ** | - | ||||||||||||
| 3 | ** Copyright (C) 2016 The Qt Company Ltd. | - | ||||||||||||
| 4 | ** Contact: https://www.qt.io/licensing/ | - | ||||||||||||
| 5 | ** | - | ||||||||||||
| 6 | ** This file is part of the QtQml module of the Qt Toolkit. | - | ||||||||||||
| 7 | ** | - | ||||||||||||
| 8 | ** $QT_BEGIN_LICENSE:LGPL$ | - | ||||||||||||
| 9 | ** Commercial License Usage | - | ||||||||||||
| 10 | ** Licensees holding valid commercial Qt licenses may use this file in | - | ||||||||||||
| 11 | ** accordance with the commercial license agreement provided with the | - | ||||||||||||
| 12 | ** Software or, alternatively, in accordance with the terms contained in | - | ||||||||||||
| 13 | ** a written agreement between you and The Qt Company. For licensing terms | - | ||||||||||||
| 14 | ** and conditions see https://www.qt.io/terms-conditions. For further | - | ||||||||||||
| 15 | ** information use the contact form at https://www.qt.io/contact-us. | - | ||||||||||||
| 16 | ** | - | ||||||||||||
| 17 | ** GNU Lesser General Public License Usage | - | ||||||||||||
| 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | - | ||||||||||||
| 19 | ** General Public License version 3 as published by the Free Software | - | ||||||||||||
| 20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | - | ||||||||||||
| 21 | ** packaging of this file. Please review the following information to | - | ||||||||||||
| 22 | ** ensure the GNU Lesser General Public License version 3 requirements | - | ||||||||||||
| 23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | - | ||||||||||||
| 24 | ** | - | ||||||||||||
| 25 | ** GNU General Public License Usage | - | ||||||||||||
| 26 | ** Alternatively, this file may be used under the terms of the GNU | - | ||||||||||||
| 27 | ** General Public License version 2.0 or (at your option) the GNU General | - | ||||||||||||
| 28 | ** Public license version 3 or any later version approved by the KDE Free | - | ||||||||||||
| 29 | ** Qt Foundation. The licenses are as published by the Free Software | - | ||||||||||||
| 30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | - | ||||||||||||
| 31 | ** included in the packaging of this file. Please review the following | - | ||||||||||||
| 32 | ** information to ensure the GNU General Public License requirements will | - | ||||||||||||
| 33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | - | ||||||||||||
| 34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | - | ||||||||||||
| 35 | ** | - | ||||||||||||
| 36 | ** $QT_END_LICENSE$ | - | ||||||||||||
| 37 | ** | - | ||||||||||||
| 38 | ****************************************************************************/ | - | ||||||||||||
| 39 | - | |||||||||||||
| 40 | #include "qv4regexpobject_p.h" | - | ||||||||||||
| 41 | #include "qv4objectproto_p.h" | - | ||||||||||||
| 42 | #include "qv4regexp_p.h" | - | ||||||||||||
| 43 | #include "qv4stringobject_p.h" | - | ||||||||||||
| 44 | #include <private/qv4mm_p.h> | - | ||||||||||||
| 45 | #include "qv4scopedvalue_p.h" | - | ||||||||||||
| 46 | #include "qv4jscall_p.h" | - | ||||||||||||
| 47 | - | |||||||||||||
| 48 | #include "private/qlocale_tools_p.h" | - | ||||||||||||
| 49 | - | |||||||||||||
| 50 | #include <QtCore/QDebug> | - | ||||||||||||
| 51 | #include <QtCore/qregexp.h> | - | ||||||||||||
| 52 | #include <cassert> | - | ||||||||||||
| 53 | #include <typeinfo> | - | ||||||||||||
| 54 | #include <iostream> | - | ||||||||||||
| 55 | #include "qv4alloca_p.h" | - | ||||||||||||
| 56 | - | |||||||||||||
| 57 | QT_BEGIN_NAMESPACE | - | ||||||||||||
| 58 | - | |||||||||||||
| 59 | Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax); | - | ||||||||||||
| 60 | - | |||||||||||||
| 61 | using namespace QV4; | - | ||||||||||||
| 62 | - | |||||||||||||
| 63 | DEFINE_OBJECT_VTABLE(RegExpObject); | - | ||||||||||||
| 64 | - | |||||||||||||
| 65 | void Heap::RegExpObject::init() | - | ||||||||||||
| 66 | { | - | ||||||||||||
| 67 | Object::init(); | - | ||||||||||||
| 68 | Scope scope(internalClass->engine); | - | ||||||||||||
| 69 | Scoped<QV4::RegExpObject> o(scope, this); | - | ||||||||||||
| 70 | value.set(scope.engine, QV4::RegExp::create(scope.engine, QString(), false, false)); | - | ||||||||||||
| 71 | o->initProperties(); | - | ||||||||||||
| 72 | } executed 99134 times by 153 tests: end of blockExecuted by:
| 99134 | ||||||||||||
| 73 | - | |||||||||||||
| 74 | void Heap::RegExpObject::init(QV4::RegExp *value) | - | ||||||||||||
| 75 | { | - | ||||||||||||
| 76 | Object::init(); | - | ||||||||||||
| 77 | Scope scope(internalClass->engine); | - | ||||||||||||
| 78 | this->value.set(scope.engine, value->d()); | - | ||||||||||||
| 79 | Scoped<QV4::RegExpObject> o(scope, this); | - | ||||||||||||
| 80 | o->initProperties(); | - | ||||||||||||
| 81 | } executed 1055167 times by 9 tests: end of blockExecuted by:
| 1055167 | ||||||||||||
| 82 | - | |||||||||||||
| 83 | // Converts a QRegExp to a JS RegExp. | - | ||||||||||||
| 84 | // The conversion is not 100% exact since ECMA regexp and QRegExp | - | ||||||||||||
| 85 | // have different semantics/flags, but we try to do our best. | - | ||||||||||||
| 86 | void Heap::RegExpObject::init(const QRegExp &re) | - | ||||||||||||
| 87 | { | - | ||||||||||||
| 88 | Object::init(); | - | ||||||||||||
| 89 | - | |||||||||||||
| 90 | // Convert the pattern to a ECMAScript pattern. | - | ||||||||||||
| 91 | QString pattern = QT_PREPEND_NAMESPACE(qt_regexp_toCanonical)(re.pattern(), re.patternSyntax()); | - | ||||||||||||
| 92 | if (re.isMinimal()) {
| 16-46 | ||||||||||||
| 93 | QString ecmaPattern; | - | ||||||||||||
| 94 | int len = pattern.length(); | - | ||||||||||||
| 95 | ecmaPattern.reserve(len); | - | ||||||||||||
| 96 | int i = 0; | - | ||||||||||||
| 97 | const QChar *wc = pattern.unicode(); | - | ||||||||||||
| 98 | bool inBracket = false; | - | ||||||||||||
| 99 | while (i < len) {
| 16-80 | ||||||||||||
| 100 | QChar c = wc[i++]; | - | ||||||||||||
| 101 | ecmaPattern += c; | - | ||||||||||||
| 102 | switch (c.unicode()) { | - | ||||||||||||
| 103 | case '?': executed 4 times by 1 test: case '?':Executed by:
| 4 | ||||||||||||
| 104 | case '+': executed 4 times by 1 test: case '+':Executed by:
| 4 | ||||||||||||
| 105 | case '*': executed 6 times by 1 test: case '*':Executed by:
| 6 | ||||||||||||
| 106 | case '}': executed 2 times by 1 test: case '}':Executed by:
| 2 | ||||||||||||
| 107 | if (!inBracket)
| 6-10 | ||||||||||||
| 108 | ecmaPattern += QLatin1Char('?'); executed 10 times by 1 test: ecmaPattern += QLatin1Char('?');Executed by:
| 10 | ||||||||||||
| 109 | break; executed 16 times by 1 test: break;Executed by:
| 16 | ||||||||||||
| 110 | case '\\': executed 2 times by 1 test: case '\\':Executed by:
| 2 | ||||||||||||
| 111 | if (i < len)
| 0-2 | ||||||||||||
| 112 | ecmaPattern += wc[i++]; executed 2 times by 1 test: ecmaPattern += wc[i++];Executed by:
| 2 | ||||||||||||
| 113 | break; executed 2 times by 1 test: break;Executed by:
| 2 | ||||||||||||
| 114 | case '[': executed 6 times by 1 test: case '[':Executed by:
| 6 | ||||||||||||
| 115 | inBracket = true; | - | ||||||||||||
| 116 | break; executed 6 times by 1 test: break;Executed by:
| 6 | ||||||||||||
| 117 | case ']': executed 6 times by 1 test: case ']':Executed by:
| 6 | ||||||||||||
| 118 | inBracket = false; | - | ||||||||||||
| 119 | break; executed 6 times by 1 test: break;Executed by:
| 6 | ||||||||||||
| 120 | default: executed 50 times by 1 test: default:Executed by:
| 50 | ||||||||||||
| 121 | break; executed 50 times by 1 test: break;Executed by:
| 50 | ||||||||||||
| 122 | } | - | ||||||||||||
| 123 | } | - | ||||||||||||
| 124 | pattern = ecmaPattern; | - | ||||||||||||
| 125 | } executed 16 times by 1 test: end of blockExecuted by:
| 16 | ||||||||||||
| 126 | - | |||||||||||||
| 127 | Scope scope(internalClass->engine); | - | ||||||||||||
| 128 | Scoped<QV4::RegExpObject> o(scope, this); | - | ||||||||||||
| 129 | - | |||||||||||||
| 130 | o->d()->value.set(scope.engine, | - | ||||||||||||
| 131 | QV4::RegExp::create(scope.engine, pattern, re.caseSensitivity() == Qt::CaseInsensitive, false)); | - | ||||||||||||
| 132 | - | |||||||||||||
| 133 | o->initProperties(); | - | ||||||||||||
| 134 | } executed 62 times by 4 tests: end of blockExecuted by:
| 62 | ||||||||||||
| 135 | - | |||||||||||||
| 136 | void RegExpObject::initProperties() | - | ||||||||||||
| 137 | { | - | ||||||||||||
| 138 | setProperty(Index_LastIndex, Primitive::fromInt32(0)); | - | ||||||||||||
| 139 | - | |||||||||||||
| 140 | Q_ASSERT(value()); | - | ||||||||||||
| 141 | - | |||||||||||||
| 142 | QString p = *value()->pattern; | - | ||||||||||||
| 143 | if (p.isEmpty()) {
| 99545-1054645 | ||||||||||||
| 144 | p = QStringLiteral("(?:)"); | - | ||||||||||||
| 145 | } else { executed 99550 times by 153 tests: end of blockExecuted by:
| 99550 | ||||||||||||
| 146 | // escape certain parts, see ch. 15.10.4 | - | ||||||||||||
| 147 | p.replace('/', QLatin1String("\\/")); | - | ||||||||||||
| 148 | } executed 1054487 times by 9 tests: end of blockExecuted by:
| 1054487 | ||||||||||||
| 149 | - | |||||||||||||
| 150 | setProperty(Index_Source, engine()->newString(p)); | - | ||||||||||||
| 151 | setProperty(Index_Global, Primitive::fromBoolean(global())); | - | ||||||||||||
| 152 | setProperty(Index_IgnoreCase, Primitive::fromBoolean(value()->ignoreCase)); | - | ||||||||||||
| 153 | setProperty(Index_Multiline, Primitive::fromBoolean(value()->multiLine)); | - | ||||||||||||
| 154 | } executed 1154204 times by 153 tests: end of blockExecuted by:
| 1154204 | ||||||||||||
| 155 | - | |||||||||||||
| 156 | // Converts a JS RegExp to a QRegExp. | - | ||||||||||||
| 157 | // The conversion is not 100% exact since ECMA regexp and QRegExp | - | ||||||||||||
| 158 | // have different semantics/flags, but we try to do our best. | - | ||||||||||||
| 159 | QRegExp RegExpObject::toQRegExp() const | - | ||||||||||||
| 160 | { | - | ||||||||||||
| 161 | Qt::CaseSensitivity caseSensitivity = value()->ignoreCase ? Qt::CaseInsensitive : Qt::CaseSensitive;
| 12-38 | ||||||||||||
| 162 | return QRegExp(*value()->pattern, caseSensitivity, QRegExp::RegExp2); executed 50 times by 7 tests: return QRegExp(*value()->pattern, caseSensitivity, QRegExp::RegExp2);Executed by:
| 50 | ||||||||||||
| 163 | } | - | ||||||||||||
| 164 | - | |||||||||||||
| 165 | QString RegExpObject::toString() const | - | ||||||||||||
| 166 | { | - | ||||||||||||
| 167 | QString result = QLatin1Char('/') + source() + QLatin1Char('/'); | - | ||||||||||||
| 168 | if (global())
| 12-50 | ||||||||||||
| 169 | result += QLatin1Char('g'); executed 12 times by 2 tests: result += QLatin1Char('g');Executed by:
| 12 | ||||||||||||
| 170 | if (value()->ignoreCase)
| 6-56 | ||||||||||||
| 171 | result += QLatin1Char('i'); executed 6 times by 1 test: result += QLatin1Char('i');Executed by:
| 6 | ||||||||||||
| 172 | if (value()->multiLine)
| 6-56 | ||||||||||||
| 173 | result += QLatin1Char('m'); executed 6 times by 1 test: result += QLatin1Char('m');Executed by:
| 6 | ||||||||||||
| 174 | return result; executed 62 times by 2 tests: return result;Executed by:
| 62 | ||||||||||||
| 175 | } | - | ||||||||||||
| 176 | - | |||||||||||||
| 177 | QString RegExpObject::source() const | - | ||||||||||||
| 178 | { | - | ||||||||||||
| 179 | Scope scope(engine()); | - | ||||||||||||
| 180 | ScopedString source(scope, scope.engine->newIdentifier(QStringLiteral("source"))); executed 66 times by 3 tests: return qstring_literal_temp;Executed by:
| 66 | ||||||||||||
| 181 | ScopedValue s(scope, const_cast<RegExpObject *>(this)->get(source)); | - | ||||||||||||
| 182 | return s->toQString(); executed 66 times by 3 tests: return s->toQString();Executed by:
| 66 | ||||||||||||
| 183 | } | - | ||||||||||||
| 184 | - | |||||||||||||
| 185 | uint RegExpObject::flags() const | - | ||||||||||||
| 186 | { | - | ||||||||||||
| 187 | uint f = 0; | - | ||||||||||||
| 188 | if (global())
| 0-4 | ||||||||||||
| 189 | f |= QV4::RegExpObject::RegExp_Global; never executed: f |= QV4::RegExpObject::RegExp_Global; | 0 | ||||||||||||
| 190 | if (value()->ignoreCase)
| 0-4 | ||||||||||||
| 191 | f |= QV4::RegExpObject::RegExp_IgnoreCase; executed 4 times by 1 test: f |= QV4::RegExpObject::RegExp_IgnoreCase;Executed by:
| 4 | ||||||||||||
| 192 | if (value()->multiLine)
| 0-4 | ||||||||||||
| 193 | f |= QV4::RegExpObject::RegExp_Multiline; never executed: f |= QV4::RegExpObject::RegExp_Multiline; | 0 | ||||||||||||
| 194 | return f; executed 4 times by 1 test: return f;Executed by:
| 4 | ||||||||||||
| 195 | } | - | ||||||||||||
| 196 | - | |||||||||||||
| 197 | DEFINE_OBJECT_VTABLE(RegExpCtor); | - | ||||||||||||
| 198 | - | |||||||||||||
| 199 | void Heap::RegExpCtor::init(QV4::ExecutionContext *scope) | - | ||||||||||||
| 200 | { | - | ||||||||||||
| 201 | Heap::FunctionObject::init(scope, QStringLiteral("RegExp")); executed 98517 times by 153 tests: return qstring_literal_temp;Executed by:
| 98517 | ||||||||||||
| 202 | clearLastMatch(); | - | ||||||||||||
| 203 | } executed 98920 times by 153 tests: end of blockExecuted by:
| 98920 | ||||||||||||
| 204 | - | |||||||||||||
| 205 | void Heap::RegExpCtor::clearLastMatch() | - | ||||||||||||
| 206 | { | - | ||||||||||||
| 207 | lastMatch.set(internalClass->engine, Primitive::nullValue()); | - | ||||||||||||
| 208 | lastInput.set(internalClass->engine, internalClass->engine->id_empty()->d()); | - | ||||||||||||
| 209 | lastMatchStart = 0; | - | ||||||||||||
| 210 | lastMatchEnd = 0; | - | ||||||||||||
| 211 | } executed 106845 times by 153 tests: end of blockExecuted by:
| 106845 | ||||||||||||
| 212 | - | |||||||||||||
| 213 | ReturnedValue RegExpCtor::virtualCallAsConstructor(const FunctionObject *fo, const Value *argv, int argc, const Value *) | - | ||||||||||||
| 214 | { | - | ||||||||||||
| 215 | Scope scope(fo->engine()); | - | ||||||||||||
| 216 | ScopedValue r(scope, argc ? argv[0] : Primitive::undefinedValue()); | - | ||||||||||||
| 217 | ScopedValue f(scope, argc > 1 ? argv[1] : Primitive::undefinedValue()); | - | ||||||||||||
| 218 | Scoped<RegExpObject> re(scope, r); | - | ||||||||||||
| 219 | if (re) {
| 46-4088 | ||||||||||||
| 220 | if (!f->isUndefined())
| 22-25 | ||||||||||||
| 221 | return scope.engine->throwTypeError(); executed 22 times by 2 tests: return scope.engine->throwTypeError();Executed by:
| 22 | ||||||||||||
| 222 | - | |||||||||||||
| 223 | Scoped<RegExp> regexp(scope, re->value()); | - | ||||||||||||
| 224 | return Encode(scope.engine->newRegExpObject(regexp)); executed 26 times by 2 tests: return Encode(scope.engine->newRegExpObject(regexp));Executed by:
| 26 | ||||||||||||
| 225 | } | - | ||||||||||||
| 226 | - | |||||||||||||
| 227 | QString pattern; | - | ||||||||||||
| 228 | if (!r->isUndefined())
| 474-3615 | ||||||||||||
| 229 | pattern = r->toQString(); executed 3613 times by 3 tests: pattern = r->toQString();Executed by:
| 3613 | ||||||||||||
| 230 | if (scope.hasException())
| 27-4067 | ||||||||||||
| 231 | return Encode::undefined(); executed 27 times by 1 test: return Encode::undefined();Executed by:
| 27 | ||||||||||||
| 232 | - | |||||||||||||
| 233 | bool global = false; | - | ||||||||||||
| 234 | bool ignoreCase = false; | - | ||||||||||||
| 235 | bool multiLine = false; | - | ||||||||||||
| 236 | if (!f->isUndefined()) {
| 1977-2092 | ||||||||||||
| 237 | ScopedString s(scope, f->toString(scope.engine)); | - | ||||||||||||
| 238 | if (scope.hasException())
| 8-2083 | ||||||||||||
| 239 | return Encode::undefined(); executed 8 times by 1 test: return Encode::undefined();Executed by:
| 8 | ||||||||||||
| 240 | QString str = s->toQString(); | - | ||||||||||||
| 241 | for (int i = 0; i < str.length(); ++i) {
| 198-2144 | ||||||||||||
| 242 | if (str.at(i) == QLatin1Char('g') && !global) {
| 0-1966 | ||||||||||||
| 243 | global = true; | - | ||||||||||||
| 244 | } else if (str.at(i) == QLatin1Char('i') && !ignoreCase) { executed 178 times by 2 tests: end of blockExecuted by:
| 4-1918 | ||||||||||||
| 245 | ignoreCase = true; | - | ||||||||||||
| 246 | } else if (str.at(i) == QLatin1Char('m') && !multiLine) { executed 44 times by 2 tests: end of blockExecuted by:
| 0-1886 | ||||||||||||
| 247 | multiLine = true; | - | ||||||||||||
| 248 | } else { executed 36 times by 2 tests: end of blockExecuted by:
| 36 | ||||||||||||
| 249 | return scope.engine->throwSyntaxError(QStringLiteral("Invalid flags supplied to RegExp constructor")); executed 1886 times by 2 tests: return scope.engine->throwSyntaxError(([]() noexcept -> QString { enum { Size = sizeof(u"" "Invalid flags supplied to RegExp constructor")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" "Invalid flags supplied to RegExp constructor" }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); return qstring_literal_temp; }()));Executed by:
executed 1883 times by 2 tests: return qstring_literal_temp;Executed by:
| 1883-1886 | ||||||||||||
| 250 | } | - | ||||||||||||
| 251 | } | - | ||||||||||||
| 252 | } executed 198 times by 2 tests: end of blockExecuted by:
| 198 | ||||||||||||
| 253 | - | |||||||||||||
| 254 | Scoped<RegExp> regexp(scope, RegExp::create(scope.engine, pattern, ignoreCase, multiLine, global)); | - | ||||||||||||
| 255 | if (!regexp->isValid()) {
| 251-1923 | ||||||||||||
| 256 | return scope.engine->throwSyntaxError(QStringLiteral("Invalid regular expression")); executed 249 times by 1 test: return scope.engine->throwSyntaxError(([]() noexcept -> QString { enum { Size = sizeof(u"" "Invalid regular expression")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" "Invalid regular expression" }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); return qstring_literal_temp; }()));Executed by:
executed 251 times by 1 test: return qstring_literal_temp;Executed by:
| 249-251 | ||||||||||||
| 257 | } | - | ||||||||||||
| 258 | - | |||||||||||||
| 259 | return Encode(scope.engine->newRegExpObject(regexp)); executed 1925 times by 3 tests: return Encode(scope.engine->newRegExpObject(regexp));Executed by:
| 1925 | ||||||||||||
| 260 | } | - | ||||||||||||
| 261 | - | |||||||||||||
| 262 | ReturnedValue RegExpCtor::virtualCall(const FunctionObject *f, const Value *, const Value *argv, int argc) | - | ||||||||||||
| 263 | { | - | ||||||||||||
| 264 | if (argc > 0 && argv[0].as<RegExpObject>()) {
| 8-1958 | ||||||||||||
| 265 | if (argc == 1 || argv[1].isUndefined())
| 10-26 | ||||||||||||
| 266 | return Encode(argv[0]); executed 30 times by 2 tests: return Encode(argv[0]);Executed by:
| 30 | ||||||||||||
| 267 | } executed 10 times by 2 tests: end of blockExecuted by:
| 10 | ||||||||||||
| 268 | - | |||||||||||||
| 269 | return virtualCallAsConstructor(f, argv, argc, f); executed 1936 times by 3 tests: return virtualCallAsConstructor(f, argv, argc, f);Executed by:
| 1936 | ||||||||||||
| 270 | } | - | ||||||||||||
| 271 | - | |||||||||||||
| 272 | void RegExpPrototype::init(ExecutionEngine *engine, Object *constructor) | - | ||||||||||||
| 273 | { | - | ||||||||||||
| 274 | Scope scope(engine); | - | ||||||||||||
| 275 | ScopedObject o(scope); | - | ||||||||||||
| 276 | ScopedObject ctor(scope, constructor); | - | ||||||||||||
| 277 | - | |||||||||||||
| 278 | ctor->defineReadonlyProperty(engine->id_prototype(), (o = this)); | - | ||||||||||||
| 279 | ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(2)); | - | ||||||||||||
| 280 | ctor->addSymbolSpecies(); | - | ||||||||||||
| 281 | - | |||||||||||||
| 282 | // Properties deprecated in the spec but required by "the web" :( | - | ||||||||||||
| 283 | ctor->defineAccessorProperty(QStringLiteral("lastMatch"), method_get_lastMatch_n<0>, nullptr); executed 98240 times by 153 tests: return qstring_literal_temp;Executed by:
| 98240 | ||||||||||||
| 284 | ctor->defineAccessorProperty(QStringLiteral("$&"), method_get_lastMatch_n<0>, nullptr); executed 98598 times by 153 tests: return qstring_literal_temp;Executed by:
| 98598 | ||||||||||||
| 285 | ctor->defineAccessorProperty(QStringLiteral("$1"), method_get_lastMatch_n<1>, nullptr); executed 98506 times by 153 tests: return qstring_literal_temp;Executed by:
| 98506 | ||||||||||||
| 286 | ctor->defineAccessorProperty(QStringLiteral("$2"), method_get_lastMatch_n<2>, nullptr); executed 98913 times by 153 tests: return qstring_literal_temp;Executed by:
| 98913 | ||||||||||||
| 287 | ctor->defineAccessorProperty(QStringLiteral("$3"), method_get_lastMatch_n<3>, nullptr); executed 99099 times by 153 tests: return qstring_literal_temp;Executed by:
| 99099 | ||||||||||||
| 288 | ctor->defineAccessorProperty(QStringLiteral("$4"), method_get_lastMatch_n<4>, nullptr); executed 99049 times by 153 tests: return qstring_literal_temp;Executed by:
| 99049 | ||||||||||||
| 289 | ctor->defineAccessorProperty(QStringLiteral("$5"), method_get_lastMatch_n<5>, nullptr); executed 99077 times by 153 tests: return qstring_literal_temp;Executed by:
| 99077 | ||||||||||||
| 290 | ctor->defineAccessorProperty(QStringLiteral("$6"), method_get_lastMatch_n<6>, nullptr); executed 99030 times by 153 tests: return qstring_literal_temp;Executed by:
| 99030 | ||||||||||||
| 291 | ctor->defineAccessorProperty(QStringLiteral("$7"), method_get_lastMatch_n<7>, nullptr); executed 99045 times by 153 tests: return qstring_literal_temp;Executed by:
| 99045 | ||||||||||||
| 292 | ctor->defineAccessorProperty(QStringLiteral("$8"), method_get_lastMatch_n<8>, nullptr); executed 98900 times by 153 tests: return qstring_literal_temp;Executed by:
| 98900 | ||||||||||||
| 293 | ctor->defineAccessorProperty(QStringLiteral("$9"), method_get_lastMatch_n<9>, nullptr); executed 98561 times by 153 tests: return qstring_literal_temp;Executed by:
| 98561 | ||||||||||||
| 294 | ctor->defineAccessorProperty(QStringLiteral("lastParen"), method_get_lastParen, nullptr); executed 99030 times by 153 tests: return qstring_literal_temp;Executed by:
| 99030 | ||||||||||||
| 295 | ctor->defineAccessorProperty(QStringLiteral("$+"), method_get_lastParen, nullptr); executed 98953 times by 153 tests: return qstring_literal_temp;Executed by:
| 98953 | ||||||||||||
| 296 | ctor->defineAccessorProperty(QStringLiteral("input"), method_get_input, nullptr); executed 98778 times by 153 tests: return qstring_literal_temp;Executed by:
| 98778 | ||||||||||||
| 297 | ctor->defineAccessorProperty(QStringLiteral("$_"), method_get_input, nullptr); executed 99108 times by 153 tests: return qstring_literal_temp;Executed by:
| 99108 | ||||||||||||
| 298 | ctor->defineAccessorProperty(QStringLiteral("leftContext"), method_get_leftContext, nullptr); executed 98988 times by 153 tests: return qstring_literal_temp;Executed by:
| 98988 | ||||||||||||
| 299 | ctor->defineAccessorProperty(QStringLiteral("$`"), method_get_leftContext, nullptr); executed 98930 times by 153 tests: return qstring_literal_temp;Executed by:
| 98930 | ||||||||||||
| 300 | ctor->defineAccessorProperty(QStringLiteral("rightContext"), method_get_rightContext, nullptr); executed 98848 times by 153 tests: return qstring_literal_temp;Executed by:
| 98848 | ||||||||||||
| 301 | ctor->defineAccessorProperty(QStringLiteral("$'"), method_get_rightContext, nullptr); executed 98409 times by 153 tests: return qstring_literal_temp;Executed by:
| 98409 | ||||||||||||
| 302 | - | |||||||||||||
| 303 | defineDefaultProperty(QStringLiteral("constructor"), (o = ctor)); executed 98728 times by 153 tests: return qstring_literal_temp;Executed by:
| 98728 | ||||||||||||
| 304 | defineDefaultProperty(QStringLiteral("exec"), method_exec, 1); executed 98892 times by 153 tests: return qstring_literal_temp;Executed by:
| 98892 | ||||||||||||
| 305 | defineDefaultProperty(QStringLiteral("test"), method_test, 1); executed 98868 times by 153 tests: return qstring_literal_temp;Executed by:
| 98868 | ||||||||||||
| 306 | defineDefaultProperty(engine->id_toString(), method_toString, 0); | - | ||||||||||||
| 307 | defineDefaultProperty(QStringLiteral("compile"), method_compile, 2); executed 98665 times by 153 tests: return qstring_literal_temp;Executed by:
| 98665 | ||||||||||||
| 308 | } executed 98937 times by 153 tests: end of blockExecuted by:
| 98937 | ||||||||||||
| 309 | - | |||||||||||||
| 310 | /* used by String.match */ | - | ||||||||||||
| 311 | ReturnedValue RegExpPrototype::execFirstMatch(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc) | - | ||||||||||||
| 312 | { | - | ||||||||||||
| 313 | Scope scope(b); | - | ||||||||||||
| 314 | Scoped<RegExpObject> r(scope, thisObject->as<RegExpObject>()); | - | ||||||||||||
| 315 | Q_ASSERT(r && r->global()); | - | ||||||||||||
| 316 | - | |||||||||||||
| 317 | ScopedString str(scope, argc ? argv[0] : Primitive::undefinedValue()); | - | ||||||||||||
| 318 | Q_ASSERT(str); | - | ||||||||||||
| 319 | QString s = str->toQString(); | - | ||||||||||||
| 320 | - | |||||||||||||
| 321 | int offset = r->lastIndex(); | - | ||||||||||||
| 322 | if (offset < 0 || offset > s.length()) {
| 0-820 | ||||||||||||
| 323 | r->setLastIndex(0); | - | ||||||||||||
| 324 | RETURN_RESULT(Encode::null()); never executed: return QV4::Encode(Encode::null()); | 0 | ||||||||||||
| 325 | } | - | ||||||||||||
| 326 | - | |||||||||||||
| 327 | Q_ALLOCA_VAR(uint, matchOffsets, r->value()->captureCount() * 2 * sizeof(uint)); | - | ||||||||||||
| 328 | const int result = Scoped<RegExp>(scope, r->value())->match(s, offset, matchOffsets); | - | ||||||||||||
| 329 | - | |||||||||||||
| 330 | RegExpCtor *regExpCtor = static_cast<RegExpCtor *>(scope.engine->regExpCtor()); | - | ||||||||||||
| 331 | regExpCtor->d()->clearLastMatch(); | - | ||||||||||||
| 332 | - | |||||||||||||
| 333 | if (result == -1) {
| 144-679 | ||||||||||||
| 334 | r->setLastIndex(0); | - | ||||||||||||
| 335 | RETURN_RESULT(Encode::null()); executed 144 times by 1 test: return QV4::Encode(Encode::null());Executed by:
| 144 | ||||||||||||
| 336 | } | - | ||||||||||||
| 337 | - | |||||||||||||
| 338 | ReturnedValue retVal = Encode::undefined(); | - | ||||||||||||
| 339 | // return first match | - | ||||||||||||
| 340 | if (r->value()->captureCount()) {
| 0-678 | ||||||||||||
| 341 | int start = matchOffsets[0]; | - | ||||||||||||
| 342 | int end = matchOffsets[1]; | - | ||||||||||||
| 343 | retVal = (start != -1) ? scope.engine->memoryManager->alloc<ComplexString>(str->d(), start, end - start)->asReturnedValue() : Encode::undefined();
| 0-677 | ||||||||||||
| 344 | } executed 678 times by 1 test: end of blockExecuted by:
| 678 | ||||||||||||
| 345 | - | |||||||||||||
| 346 | RegExpCtor::Data *dd = regExpCtor->d(); | - | ||||||||||||
| 347 | dd->lastInput.set(scope.engine, str->d()); | - | ||||||||||||
| 348 | dd->lastMatchStart = matchOffsets[0]; | - | ||||||||||||
| 349 | dd->lastMatchEnd = matchOffsets[1]; | - | ||||||||||||
| 350 | - | |||||||||||||
| 351 | r->setLastIndex(matchOffsets[1]); | - | ||||||||||||
| 352 | - | |||||||||||||
| 353 | return retVal; executed 677 times by 1 test: return retVal;Executed by:
| 677 | ||||||||||||
| 354 | } | - | ||||||||||||
| 355 | - | |||||||||||||
| 356 | ReturnedValue RegExpPrototype::method_exec(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc) | - | ||||||||||||
| 357 | { | - | ||||||||||||
| 358 | Scope scope(b); | - | ||||||||||||
| 359 | Scoped<RegExpObject> r(scope, thisObject->as<RegExpObject>()); | - | ||||||||||||
| 360 | if (!r)
| 80-7397 | ||||||||||||
| 361 | return scope.engine->throwTypeError(); executed 80 times by 1 test: return scope.engine->throwTypeError();Executed by:
| 80 | ||||||||||||
| 362 | - | |||||||||||||
| 363 | ScopedValue arg(scope, argc ? argv[0]: Primitive::undefinedValue()); | - | ||||||||||||
| 364 | ScopedString str(scope, arg->toString(scope.engine)); | - | ||||||||||||
| 365 | if (scope.hasException())
| 16-7389 | ||||||||||||
| 366 | RETURN_UNDEFINED(); executed 15 times by 1 test: return QV4::Encode::undefined();Executed by:
| 15 | ||||||||||||
| 367 | QString s = str->toQString(); | - | ||||||||||||
| 368 | - | |||||||||||||
| 369 | int offset = r->global() ? r->lastIndex() : 0;
| 1728-5661 | ||||||||||||
| 370 | if (offset < 0 || offset > s.length()) {
| 12-7375 | ||||||||||||
| 371 | r->setLastIndex(0); | - | ||||||||||||
| 372 | RETURN_RESULT(Encode::null()); executed 24 times by 1 test: return QV4::Encode(Encode::null());Executed by:
| 24 | ||||||||||||
| 373 | } | - | ||||||||||||
| 374 | - | |||||||||||||
| 375 | Q_ALLOCA_VAR(uint, matchOffsets, r->value()->captureCount() * 2 * sizeof(uint)); | - | ||||||||||||
| 376 | const int result = Scoped<RegExp>(scope, r->value())->match(s, offset, matchOffsets); | - | ||||||||||||
| 377 | - | |||||||||||||
| 378 | RegExpCtor *regExpCtor = static_cast<RegExpCtor *>(scope.engine->regExpCtor()); | - | ||||||||||||
| 379 | regExpCtor->d()->clearLastMatch(); | - | ||||||||||||
| 380 | - | |||||||||||||
| 381 | if (result == -1) {
| 1848-5523 | ||||||||||||
| 382 | r->setLastIndex(0); | - | ||||||||||||
| 383 | RETURN_RESULT(Encode::null()); executed 1847 times by 1 test: return QV4::Encode(Encode::null());Executed by:
| 1847 | ||||||||||||
| 384 | } | - | ||||||||||||
| 385 | - | |||||||||||||
| 386 | // fill in result data | - | ||||||||||||
| 387 | ScopedArrayObject array(scope, scope.engine->newArrayObject(scope.engine->internalClasses(EngineBase::Class_RegExpExecArray))); | - | ||||||||||||
| 388 | int len = r->value()->captureCount(); | - | ||||||||||||
| 389 | array->arrayReserve(len); | - | ||||||||||||
| 390 | ScopedValue v(scope); | - | ||||||||||||
| 391 | for (int i = 0; i < len; ++i) {
| 5522-8040 | ||||||||||||
| 392 | int start = matchOffsets[i * 2]; | - | ||||||||||||
| 393 | int end = matchOffsets[i * 2 + 1]; | - | ||||||||||||
| 394 | v = (start != -1) ? scope.engine->memoryManager->alloc<ComplexString>(str->d(), start, end - start)->asReturnedValue() : Encode::undefined();
| 732-7303 | ||||||||||||
| 395 | array->arrayPut(i, v); | - | ||||||||||||
| 396 | } executed 8041 times by 2 tests: end of blockExecuted by:
| 8041 | ||||||||||||
| 397 | array->setArrayLengthUnchecked(len); | - | ||||||||||||
| 398 | array->setProperty(Index_ArrayIndex, Primitive::fromInt32(result)); | - | ||||||||||||
| 399 | array->setProperty(Index_ArrayInput, str); | - | ||||||||||||
| 400 | - | |||||||||||||
| 401 | RegExpCtor::Data *dd = regExpCtor->d(); | - | ||||||||||||
| 402 | dd->lastMatch.set(scope.engine, array); | - | ||||||||||||
| 403 | dd->lastInput.set(scope.engine, str->d()); | - | ||||||||||||
| 404 | dd->lastMatchStart = matchOffsets[0]; | - | ||||||||||||
| 405 | dd->lastMatchEnd = matchOffsets[1]; | - | ||||||||||||
| 406 | - | |||||||||||||
| 407 | if (r->global())
| 1655-3860 | ||||||||||||
| 408 | r->setLastIndex(matchOffsets[1]); executed 1655 times by 2 tests: r->setLastIndex(matchOffsets[1]);Executed by:
| 1655 | ||||||||||||
| 409 | - | |||||||||||||
| 410 | return array.asReturnedValue(); executed 5515 times by 2 tests: return array.asReturnedValue();Executed by:
| 5515 | ||||||||||||
| 411 | } | - | ||||||||||||
| 412 | - | |||||||||||||
| 413 | ReturnedValue RegExpPrototype::method_test(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc) | - | ||||||||||||
| 414 | { | - | ||||||||||||
| 415 | Value res = Value::fromReturnedValue(method_exec(b, thisObject, argv, argc)); | - | ||||||||||||
| 416 | return Encode(!res.isNull()); executed 694 times by 1 test: return Encode(!res.isNull());Executed by:
| 694 | ||||||||||||
| 417 | } | - | ||||||||||||
| 418 | - | |||||||||||||
| 419 | ReturnedValue RegExpPrototype::method_toString(const FunctionObject *b, const Value *thisObject, const Value *, int) | - | ||||||||||||
| 420 | { | - | ||||||||||||
| 421 | ExecutionEngine *v4 = b->engine(); | - | ||||||||||||
| 422 | const RegExpObject *r = thisObject->as<RegExpObject>(); | - | ||||||||||||
| 423 | if (!r)
| 0-62 | ||||||||||||
| 424 | return v4->throwTypeError(); never executed: return v4->throwTypeError(); | 0 | ||||||||||||
| 425 | - | |||||||||||||
| 426 | return Encode(v4->newString(r->toString())); executed 62 times by 2 tests: return Encode(v4->newString(r->toString()));Executed by:
| 62 | ||||||||||||
| 427 | } | - | ||||||||||||
| 428 | - | |||||||||||||
| 429 | ReturnedValue RegExpPrototype::method_compile(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc) | - | ||||||||||||
| 430 | { | - | ||||||||||||
| 431 | Scope scope(b); | - | ||||||||||||
| 432 | Scoped<RegExpObject> r(scope, thisObject->as<RegExpObject>()); | - | ||||||||||||
| 433 | if (!r)
| 0 | ||||||||||||
| 434 | return scope.engine->throwTypeError(); never executed: return scope.engine->throwTypeError(); | 0 | ||||||||||||
| 435 | - | |||||||||||||
| 436 | Scoped<RegExpObject> re(scope, scope.engine->regExpCtor()->callAsConstructor(argv, argc)); | - | ||||||||||||
| 437 | - | |||||||||||||
| 438 | r->d()->value.set(scope.engine, re->value()); | - | ||||||||||||
| 439 | return Encode::undefined(); never executed: return Encode::undefined(); | 0 | ||||||||||||
| 440 | } | - | ||||||||||||
| 441 | - | |||||||||||||
| 442 | template <uint index> | - | ||||||||||||
| 443 | ReturnedValue RegExpPrototype::method_get_lastMatch_n(const FunctionObject *b, const Value *, const Value *, int) | - | ||||||||||||
| 444 | { | - | ||||||||||||
| 445 | Scope scope(b); | - | ||||||||||||
| 446 | ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(scope.engine->regExpCtor())->lastMatch()); | - | ||||||||||||
| 447 | ScopedValue res(scope, lastMatch ? lastMatch->get(index) : Encode::undefined()); | - | ||||||||||||
| 448 | if (res->isUndefined())
| 8-30 | ||||||||||||
| 449 | res = scope.engine->newString(); executed 30 times by 1 test: res = scope.engine->newString();Executed by:
| 30 | ||||||||||||
| 450 | return res->asReturnedValue(); executed 38 times by 1 test: return res->asReturnedValue();Executed by:
| 38 | ||||||||||||
| 451 | } | - | ||||||||||||
| 452 | - | |||||||||||||
| 453 | ReturnedValue RegExpPrototype::method_get_lastParen(const FunctionObject *b, const Value *, const Value *, int) | - | ||||||||||||
| 454 | { | - | ||||||||||||
| 455 | Scope scope(b); | - | ||||||||||||
| 456 | ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(scope.engine->regExpCtor())->lastMatch()); | - | ||||||||||||
| 457 | ScopedValue res(scope, lastMatch ? lastMatch->get(lastMatch->getLength() - 1) : Encode::undefined()); | - | ||||||||||||
| 458 | if (res->isUndefined())
| 0-2 | ||||||||||||
| 459 | res = scope.engine->newString(); never executed: res = scope.engine->newString(); | 0 | ||||||||||||
| 460 | return res->asReturnedValue(); executed 2 times by 1 test: return res->asReturnedValue();Executed by:
| 2 | ||||||||||||
| 461 | } | - | ||||||||||||
| 462 | - | |||||||||||||
| 463 | ReturnedValue RegExpPrototype::method_get_input(const FunctionObject *b, const Value *, const Value *, int) | - | ||||||||||||
| 464 | { | - | ||||||||||||
| 465 | return static_cast<RegExpCtor*>(b->engine()->regExpCtor())->lastInput()->asReturnedValue(); executed 4 times by 1 test: return static_cast<RegExpCtor*>(b->engine()->regExpCtor())->lastInput()->asReturnedValue();Executed by:
| 4 | ||||||||||||
| 466 | } | - | ||||||||||||
| 467 | - | |||||||||||||
| 468 | ReturnedValue RegExpPrototype::method_get_leftContext(const FunctionObject *b, const Value *, const Value *, int) | - | ||||||||||||
| 469 | { | - | ||||||||||||
| 470 | Scope scope(b); | - | ||||||||||||
| 471 | Scoped<RegExpCtor> regExpCtor(scope, scope.engine->regExpCtor()); | - | ||||||||||||
| 472 | QString lastInput = regExpCtor->lastInput()->toQString(); | - | ||||||||||||
| 473 | return Encode(scope.engine->newString(lastInput.left(regExpCtor->lastMatchStart()))); executed 2 times by 1 test: return Encode(scope.engine->newString(lastInput.left(regExpCtor->lastMatchStart())));Executed by:
| 2 | ||||||||||||
| 474 | } | - | ||||||||||||
| 475 | - | |||||||||||||
| 476 | ReturnedValue RegExpPrototype::method_get_rightContext(const FunctionObject *b, const Value *, const Value *, int) | - | ||||||||||||
| 477 | { | - | ||||||||||||
| 478 | Scope scope(b); | - | ||||||||||||
| 479 | Scoped<RegExpCtor> regExpCtor(scope, scope.engine->regExpCtor()); | - | ||||||||||||
| 480 | QString lastInput = regExpCtor->lastInput()->toQString(); | - | ||||||||||||
| 481 | return Encode(scope.engine->newString(lastInput.mid(regExpCtor->lastMatchEnd()))); executed 2 times by 1 test: return Encode(scope.engine->newString(lastInput.mid(regExpCtor->lastMatchEnd())));Executed by:
| 2 | ||||||||||||
| 482 | } | - | ||||||||||||
| 483 | - | |||||||||||||
| 484 | QT_END_NAMESPACE | - | ||||||||||||
| Source code | Switch to Preprocessed file |