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 block Executed 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 block Executed 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 block Executed 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 block Executed 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 block Executed by:
| 99550 | ||||||||||||
146 | // escape certain parts, see ch. 15.10.4 | - | ||||||||||||
147 | p.replace('/', QLatin1String("\\/")); | - | ||||||||||||
148 | } executed 1054487 times by 9 tests: end of block Executed 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 block Executed 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 block Executed 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 block Executed 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 block Executed by:
| 4-1918 | ||||||||||||
245 | ignoreCase = true; | - | ||||||||||||
246 | } else if (str.at(i) == QLatin1Char('m') && !multiLine) { executed 44 times by 2 tests: end of block Executed by:
| 0-1886 | ||||||||||||
247 | multiLine = true; | - | ||||||||||||
248 | } else { executed 36 times by 2 tests: end of block Executed 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 block Executed 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 block Executed 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 block Executed 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 block Executed 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 block Executed 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 |