Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/qtdeclarative/src/qtdeclarative/src/qml/jsruntime/qv4functionobject.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 "qv4object_p.h" | - | ||||||||||||
41 | #include "qv4objectproto_p.h" | - | ||||||||||||
42 | #include "qv4stringobject_p.h" | - | ||||||||||||
43 | #include "qv4function_p.h" | - | ||||||||||||
44 | #include "qv4symbol_p.h" | - | ||||||||||||
45 | #include <private/qv4mm_p.h> | - | ||||||||||||
46 | - | |||||||||||||
47 | #include "qv4arrayobject_p.h" | - | ||||||||||||
48 | #include "qv4scopedvalue_p.h" | - | ||||||||||||
49 | #include "qv4argumentsobject_p.h" | - | ||||||||||||
50 | - | |||||||||||||
51 | #include <private/qqmljsengine_p.h> | - | ||||||||||||
52 | #include <private/qqmljslexer_p.h> | - | ||||||||||||
53 | #include <private/qqmljsparser_p.h> | - | ||||||||||||
54 | #include <private/qqmljsast_p.h> | - | ||||||||||||
55 | #include <private/qqmljavascriptexpression_p.h> | - | ||||||||||||
56 | #include <private/qqmlengine_p.h> | - | ||||||||||||
57 | #include <qv4runtimecodegen_p.h> | - | ||||||||||||
58 | #include "private/qlocale_tools_p.h" | - | ||||||||||||
59 | #include "private/qqmlbuiltinfunctions_p.h" | - | ||||||||||||
60 | #include <private/qv4jscall_p.h> | - | ||||||||||||
61 | #include <private/qv4vme_moth_p.h> | - | ||||||||||||
62 | - | |||||||||||||
63 | #include <QtCore/QDebug> | - | ||||||||||||
64 | #include <algorithm> | - | ||||||||||||
65 | #include "qv4alloca_p.h" | - | ||||||||||||
66 | #include "qv4profiling_p.h" | - | ||||||||||||
67 | - | |||||||||||||
68 | using namespace QV4; | - | ||||||||||||
69 | - | |||||||||||||
70 | - | |||||||||||||
71 | DEFINE_OBJECT_VTABLE(FunctionObject); | - | ||||||||||||
72 | - | |||||||||||||
73 | void Heap::FunctionObject::init(QV4::ExecutionContext *scope, QV4::String *name, | - | ||||||||||||
74 | ReturnedValue (*code)(const QV4::FunctionObject *, const Value *thisObject, const Value *argv, int argc)) | - | ||||||||||||
75 | { | - | ||||||||||||
76 | jsCall = code; | - | ||||||||||||
77 | jsConstruct = QV4::FunctionObject::virtualCallAsConstructor; | - | ||||||||||||
78 | - | |||||||||||||
79 | Object::init(); | - | ||||||||||||
80 | this->scope.set(scope->engine(), scope->d()); | - | ||||||||||||
81 | Scope s(scope->engine()); | - | ||||||||||||
82 | ScopedFunctionObject f(s, this); | - | ||||||||||||
83 | if (name)
| 99063-34321871 | ||||||||||||
84 | f->setName(name); executed 34317055 times by 153 tests: f->setName(name); Executed by:
| 34317055 | ||||||||||||
85 | } executed 34351957 times by 153 tests: end of block Executed by:
| 34351957 | ||||||||||||
86 | - | |||||||||||||
87 | void Heap::FunctionObject::init(QV4::ExecutionContext *scope, QV4::String *name, bool createProto) | - | ||||||||||||
88 | { | - | ||||||||||||
89 | jsCall = vtable()->call; | - | ||||||||||||
90 | jsConstruct = vtable()->callAsConstructor; | - | ||||||||||||
91 | - | |||||||||||||
92 | Object::init(); | - | ||||||||||||
93 | this->scope.set(scope->engine(), scope->d()); | - | ||||||||||||
94 | Scope s(scope->engine()); | - | ||||||||||||
95 | ScopedFunctionObject f(s, this); | - | ||||||||||||
96 | if (name)
| 180222-3180157 | ||||||||||||
97 | f->setName(name); executed 3178928 times by 153 tests: f->setName(name); Executed by:
| 3178928 | ||||||||||||
98 | - | |||||||||||||
99 | if (createProto)
| 0-3359402 | ||||||||||||
100 | f->createDefaultPrototypeProperty(Heap::FunctionObject::Index_Prototype, Heap::FunctionObject::Index_ProtoConstructor); never executed: f->createDefaultPrototypeProperty(Heap::FunctionObject::Index_Prototype, Heap::FunctionObject::Index_ProtoConstructor); | 0 | ||||||||||||
101 | } executed 3358433 times by 153 tests: end of block Executed by:
| 3358433 | ||||||||||||
102 | - | |||||||||||||
103 | - | |||||||||||||
104 | - | |||||||||||||
105 | void Heap::FunctionObject::init(QV4::ExecutionContext *scope, Function *function, bool createProto) | - | ||||||||||||
106 | { | - | ||||||||||||
107 | jsCall = vtable()->call; | - | ||||||||||||
108 | jsConstruct = vtable()->callAsConstructor; | - | ||||||||||||
109 | - | |||||||||||||
110 | Object::init(); | - | ||||||||||||
111 | setFunction(function); | - | ||||||||||||
112 | this->scope.set(scope->engine(), scope->d()); | - | ||||||||||||
113 | Scope s(scope->engine()); | - | ||||||||||||
114 | ScopedString name(s, function->name()); | - | ||||||||||||
115 | ScopedFunctionObject f(s, this); | - | ||||||||||||
116 | if (name)
| 0-90 | ||||||||||||
117 | f->setName(name); executed 90 times by 8 tests: f->setName(name); Executed by:
| 90 | ||||||||||||
118 | - | |||||||||||||
119 | if (createProto)
| 0-90 | ||||||||||||
120 | f->createDefaultPrototypeProperty(Heap::FunctionObject::Index_Prototype, Heap::FunctionObject::Index_ProtoConstructor); never executed: f->createDefaultPrototypeProperty(Heap::FunctionObject::Index_Prototype, Heap::FunctionObject::Index_ProtoConstructor); | 0 | ||||||||||||
121 | } executed 90 times by 8 tests: end of block Executed by:
| 90 | ||||||||||||
122 | - | |||||||||||||
123 | void Heap::FunctionObject::init(QV4::ExecutionContext *scope, const QString &name, bool createProto) | - | ||||||||||||
124 | { | - | ||||||||||||
125 | Scope valueScope(scope); | - | ||||||||||||
126 | ScopedString s(valueScope, valueScope.engine->newString(name)); | - | ||||||||||||
127 | init(scope, s, createProto); | - | ||||||||||||
128 | } executed 3083351 times by 153 tests: end of block Executed by:
| 3083351 | ||||||||||||
129 | - | |||||||||||||
130 | void Heap::FunctionObject::init() | - | ||||||||||||
131 | { | - | ||||||||||||
132 | jsCall = vtable()->call; | - | ||||||||||||
133 | jsConstruct = vtable()->callAsConstructor; | - | ||||||||||||
134 | - | |||||||||||||
135 | Object::init(); | - | ||||||||||||
136 | this->scope.set(internalClass->engine, internalClass->engine->rootContext()->d()); | - | ||||||||||||
137 | Q_ASSERT(internalClass && internalClass->find(internalClass->engine->id_prototype()->propertyKey()) == Index_Prototype); | - | ||||||||||||
138 | setProperty(internalClass->engine, Index_Prototype, Primitive::undefinedValue()); | - | ||||||||||||
139 | } executed 1621011 times by 153 tests: end of block Executed by:
| 1621011 | ||||||||||||
140 | - | |||||||||||||
141 | void Heap::FunctionObject::setFunction(Function *f) | - | ||||||||||||
142 | { | - | ||||||||||||
143 | if (f) {
| 44-1522818 | ||||||||||||
144 | function = f; | - | ||||||||||||
145 | function->compilationUnit->addref(); | - | ||||||||||||
146 | } executed 1524066 times by 62 tests: end of block Executed by:
| 1524066 | ||||||||||||
147 | } executed 1524161 times by 62 tests: end of block Executed by:
| 1524161 | ||||||||||||
148 | void Heap::FunctionObject::destroy() | - | ||||||||||||
149 | { | - | ||||||||||||
150 | if (function)
| 1525791-37877975 | ||||||||||||
151 | function->compilationUnit->release(); executed 1525800 times by 62 tests: function->compilationUnit->release(); Executed by:
| 1525800 | ||||||||||||
152 | Object::destroy(); | - | ||||||||||||
153 | } executed 39395632 times by 153 tests: end of block Executed by:
| 39395632 | ||||||||||||
154 | - | |||||||||||||
155 | void FunctionObject::createDefaultPrototypeProperty(uint protoSlot, uint protoConstructorSlot) | - | ||||||||||||
156 | { | - | ||||||||||||
157 | Scope s(this); | - | ||||||||||||
158 | - | |||||||||||||
159 | Q_ASSERT(internalClass() && internalClass()->find(s.engine->id_prototype()->propertyKey()) == protoSlot); | - | ||||||||||||
160 | Q_ASSERT(s.engine->internalClasses(EngineBase::Class_ObjectProto)->find(s.engine->id_constructor()->propertyKey()) == protoConstructorSlot); | - | ||||||||||||
161 | - | |||||||||||||
162 | ScopedObject proto(s, s.engine->newObject(s.engine->internalClasses(EngineBase::Class_ObjectProto))); | - | ||||||||||||
163 | proto->setProperty(protoConstructorSlot, d()); | - | ||||||||||||
164 | setProperty(protoSlot, proto); | - | ||||||||||||
165 | } executed 1523507 times by 62 tests: end of block Executed by:
| 1523507 | ||||||||||||
166 | - | |||||||||||||
167 | ReturnedValue FunctionObject::name() const | - | ||||||||||||
168 | { | - | ||||||||||||
169 | return get(scope()->internalClass->engine->id_name()); executed 891471 times by 153 tests: return get(scope()->internalClass->engine->id_name()); Executed by:
| 891471 | ||||||||||||
170 | } | - | ||||||||||||
171 | - | |||||||||||||
172 | ReturnedValue FunctionObject::virtualCallAsConstructor(const FunctionObject *f, const Value *, int, const Value *) | - | ||||||||||||
173 | { | - | ||||||||||||
174 | return f->engine()->throwTypeError(); executed 302 times by 1 test: return f->engine()->throwTypeError(); Executed by:
| 302 | ||||||||||||
175 | } | - | ||||||||||||
176 | - | |||||||||||||
177 | ReturnedValue FunctionObject::virtualCall(const FunctionObject *, const Value *, const Value *, int) | - | ||||||||||||
178 | { | - | ||||||||||||
179 | return Encode::undefined(); executed 16 times by 1 test: return Encode::undefined(); Executed by:
| 16 | ||||||||||||
180 | } | - | ||||||||||||
181 | - | |||||||||||||
182 | Heap::FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *scope, Function *function) | - | ||||||||||||
183 | { | - | ||||||||||||
184 | return scope->engine()->memoryManager->allocate<ScriptFunction>(scope, function); executed 1508812 times by 62 tests: return scope->engine()->memoryManager->allocate<ScriptFunction>(scope, function); Executed by:
| 1508812 | ||||||||||||
185 | } | - | ||||||||||||
186 | - | |||||||||||||
187 | Heap::FunctionObject *FunctionObject::createConstructorFunction(ExecutionContext *scope, Function *function, bool isDerivedConstructor) | - | ||||||||||||
188 | { | - | ||||||||||||
189 | if (!function) {
| 660-8353 | ||||||||||||
190 | Heap::DefaultClassConstructorFunction *c = scope->engine()->memoryManager->allocate<DefaultClassConstructorFunction>(scope); | - | ||||||||||||
191 | c->isDerivedConstructor = isDerivedConstructor; | - | ||||||||||||
192 | return c; executed 8358 times by 1 test: return c; Executed by:
| 8358 | ||||||||||||
193 | } | - | ||||||||||||
194 | Heap::ConstructorFunction *c = scope->engine()->memoryManager->allocate<ConstructorFunction>(scope, function); | - | ||||||||||||
195 | c->isDerivedConstructor = isDerivedConstructor; | - | ||||||||||||
196 | return c; executed 660 times by 1 test: return c; Executed by:
| 660 | ||||||||||||
197 | } | - | ||||||||||||
198 | - | |||||||||||||
199 | Heap::FunctionObject *FunctionObject::createMemberFunction(ExecutionContext *scope, Function *function) | - | ||||||||||||
200 | { | - | ||||||||||||
201 | return scope->engine()->memoryManager->allocate<MemberFunction>(scope, function); executed 4735 times by 1 test: return scope->engine()->memoryManager->allocate<MemberFunction>(scope, function); Executed by:
| 4735 | ||||||||||||
202 | } | - | ||||||||||||
203 | - | |||||||||||||
204 | Heap::FunctionObject *FunctionObject::createBuiltinFunction(ExecutionEngine *engine, StringOrSymbol *nameOrSymbol, VTable::Call code, int argumentCount) | - | ||||||||||||
205 | { | - | ||||||||||||
206 | Scope scope(engine); | - | ||||||||||||
207 | ScopedString name(scope, nameOrSymbol); | - | ||||||||||||
208 | if (!name)
| 494366-33854654 | ||||||||||||
209 | name = engine->newString(QChar::fromLatin1('[') + nameOrSymbol->toQString().midRef(1) + QChar::fromLatin1(']')); executed 493746 times by 153 tests: name = engine->newString(QChar::fromLatin1('[') + nameOrSymbol->toQString().midRef(1) + QChar::fromLatin1(']')); Executed by:
| 493746 | ||||||||||||
210 | - | |||||||||||||
211 | ScopedFunctionObject function(scope, engine->memoryManager->allocate<FunctionObject>(engine->rootContext(), name, code)); | - | ||||||||||||
212 | function->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(argumentCount)); | - | ||||||||||||
213 | return function->d(); executed 34288646 times by 153 tests: return function->d(); Executed by:
| 34288646 | ||||||||||||
214 | } | - | ||||||||||||
215 | - | |||||||||||||
216 | bool FunctionObject::isBinding() const | - | ||||||||||||
217 | { | - | ||||||||||||
218 | return d()->vtable() == QQmlBindingFunction::staticVTable(); executed 742 times by 13 tests: return d()->vtable() == QQmlBindingFunction::staticVTable(); Executed by:
| 742 | ||||||||||||
219 | } | - | ||||||||||||
220 | - | |||||||||||||
221 | bool FunctionObject::isBoundFunction() const | - | ||||||||||||
222 | { | - | ||||||||||||
223 | return d()->vtable() == BoundFunction::staticVTable(); executed 4289625 times by 17 tests: return d()->vtable() == BoundFunction::staticVTable(); Executed by:
| 4289625 | ||||||||||||
224 | } | - | ||||||||||||
225 | - | |||||||||||||
226 | QQmlSourceLocation FunctionObject::sourceLocation() const | - | ||||||||||||
227 | { | - | ||||||||||||
228 | return d()->function->sourceLocation(); never executed: return d()->function->sourceLocation(); | 0 | ||||||||||||
229 | } | - | ||||||||||||
230 | - | |||||||||||||
231 | DEFINE_OBJECT_VTABLE(FunctionCtor); | - | ||||||||||||
232 | - | |||||||||||||
233 | void Heap::FunctionCtor::init(QV4::ExecutionContext *scope) | - | ||||||||||||
234 | { | - | ||||||||||||
235 | Heap::FunctionObject::init(scope, QStringLiteral("Function")); executed 98685 times by 153 tests: return qstring_literal_temp; Executed by:
| 98685 | ||||||||||||
236 | } executed 98961 times by 153 tests: end of block Executed by:
| 98961 | ||||||||||||
237 | - | |||||||||||||
238 | // 15.3.2 | - | ||||||||||||
239 | QQmlRefPointer<CompiledData::CompilationUnit> FunctionCtor::parse(ExecutionEngine *engine, const Value *argv, int argc, Type t) | - | ||||||||||||
240 | { | - | ||||||||||||
241 | QString arguments; | - | ||||||||||||
242 | QString body; | - | ||||||||||||
243 | if (argc > 0) {
| 180-818 | ||||||||||||
244 | for (int i = 0, ei = argc - 1; i < ei; ++i) {
| 548-820 | ||||||||||||
245 | if (i)
| 174-374 | ||||||||||||
246 | arguments += QLatin1String(", "); executed 176 times by 1 test: arguments += QLatin1String(", "); Executed by:
| 176 | ||||||||||||
247 | arguments += argv[i].toQString(); | - | ||||||||||||
248 | } executed 547 times by 2 tests: end of block Executed by:
| 547 | ||||||||||||
249 | body = argv[argc - 1].toQString(); | - | ||||||||||||
250 | } executed 825 times by 2 tests: end of block Executed by:
| 825 | ||||||||||||
251 | if (engine->hasException)
| 12-993 | ||||||||||||
252 | return nullptr; executed 12 times by 1 test: return nullptr; Executed by:
| 12 | ||||||||||||
253 | - | |||||||||||||
254 | QString function = (t == Type_Function ? QLatin1String("function anonymous(") : QLatin1String("function* anonymous(")) + arguments + QLatin1String("\n){") + body + QLatin1String("\n}");
| 120-867 | ||||||||||||
255 | - | |||||||||||||
256 | QQmlJS::Engine ee; | - | ||||||||||||
257 | QQmlJS::Lexer lexer(&ee); | - | ||||||||||||
258 | lexer.setCode(function, 1, false); | - | ||||||||||||
259 | QQmlJS::Parser parser(&ee); | - | ||||||||||||
260 | - | |||||||||||||
261 | const bool parsed = parser.parseExpression(); | - | ||||||||||||
262 | - | |||||||||||||
263 | if (!parsed) {
| 36-952 | ||||||||||||
264 | engine->throwSyntaxError(QLatin1String("Parse error")); | - | ||||||||||||
265 | return nullptr; executed 36 times by 1 test: return nullptr; Executed by:
| 36 | ||||||||||||
266 | } | - | ||||||||||||
267 | - | |||||||||||||
268 | QQmlJS::AST::FunctionExpression *fe = QQmlJS::AST::cast<QQmlJS::AST::FunctionExpression *>(parser.rootNode()); | - | ||||||||||||
269 | if (!fe) {
| 0-951 | ||||||||||||
270 | engine->throwSyntaxError(QLatin1String("Parse error")); | - | ||||||||||||
271 | return nullptr; never executed: return nullptr; | 0 | ||||||||||||
272 | } | - | ||||||||||||
273 | - | |||||||||||||
274 | Compiler::Module module(engine->debugger() != nullptr); | - | ||||||||||||
275 | - | |||||||||||||
276 | Compiler::JSUnitGenerator jsGenerator(&module); | - | ||||||||||||
277 | RuntimeCodegen cg(engine, &jsGenerator, false); | - | ||||||||||||
278 | cg.generateFromFunctionExpression(QString(), function, fe, &module); | - | ||||||||||||
279 | - | |||||||||||||
280 | if (engine->hasException)
| 16-935 | ||||||||||||
281 | return nullptr; executed 16 times by 1 test: return nullptr; Executed by:
| 16 | ||||||||||||
282 | - | |||||||||||||
283 | return cg.generateCompilationUnit(); executed 934 times by 2 tests: return cg.generateCompilationUnit(); Executed by:
| 934 | ||||||||||||
284 | } | - | ||||||||||||
285 | - | |||||||||||||
286 | ReturnedValue FunctionCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *) | - | ||||||||||||
287 | { | - | ||||||||||||
288 | ExecutionEngine *engine = f->engine(); | - | ||||||||||||
289 | - | |||||||||||||
290 | QQmlRefPointer<CompiledData::CompilationUnit> compilationUnit = parse(engine, argv, argc, Type_Function); | - | ||||||||||||
291 | if (engine->hasException)
| 56-823 | ||||||||||||
292 | return Encode::undefined(); executed 56 times by 1 test: return Encode::undefined(); Executed by:
| 56 | ||||||||||||
293 | - | |||||||||||||
294 | Function *vmf = compilationUnit->linkToEngine(engine); | - | ||||||||||||
295 | ExecutionContext *global = engine->scriptContext(); | - | ||||||||||||
296 | return Encode(FunctionObject::createScriptFunction(global, vmf)); executed 821 times by 2 tests: return Encode(FunctionObject::createScriptFunction(global, vmf)); Executed by:
| 821 | ||||||||||||
297 | } | - | ||||||||||||
298 | - | |||||||||||||
299 | // 15.3.1: This is equivalent to new Function(...) | - | ||||||||||||
300 | ReturnedValue FunctionCtor::virtualCall(const FunctionObject *f, const Value *, const Value *argv, int argc) | - | ||||||||||||
301 | { | - | ||||||||||||
302 | return virtualCallAsConstructor(f, argv, argc, f); executed 516 times by 1 test: return virtualCallAsConstructor(f, argv, argc, f); Executed by:
| 516 | ||||||||||||
303 | } | - | ||||||||||||
304 | - | |||||||||||||
305 | DEFINE_OBJECT_VTABLE(FunctionPrototype); | - | ||||||||||||
306 | - | |||||||||||||
307 | void Heap::FunctionPrototype::init() | - | ||||||||||||
308 | { | - | ||||||||||||
309 | Heap::FunctionObject::init(); | - | ||||||||||||
310 | } executed 98817 times by 153 tests: end of block Executed by:
| 98817 | ||||||||||||
311 | - | |||||||||||||
312 | void FunctionPrototype::init(ExecutionEngine *engine, Object *ctor) | - | ||||||||||||
313 | { | - | ||||||||||||
314 | Scope scope(engine); | - | ||||||||||||
315 | ScopedObject o(scope); | - | ||||||||||||
316 | - | |||||||||||||
317 | ctor->defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(1)); | - | ||||||||||||
318 | ctor->defineReadonlyProperty(engine->id_prototype(), (o = this)); | - | ||||||||||||
319 | - | |||||||||||||
320 | defineReadonlyConfigurableProperty(engine->id_name(), *engine->id_empty()); | - | ||||||||||||
321 | defineReadonlyConfigurableProperty(engine->id_length(), Primitive::fromInt32(0)); | - | ||||||||||||
322 | defineDefaultProperty(QStringLiteral("constructor"), (o = ctor)); executed 98860 times by 153 tests: return qstring_literal_temp; Executed by:
| 98860 | ||||||||||||
323 | defineDefaultProperty(engine->id_toString(), method_toString, 0); | - | ||||||||||||
324 | defineDefaultProperty(QStringLiteral("apply"), method_apply, 2); executed 99069 times by 153 tests: return qstring_literal_temp; Executed by:
| 99069 | ||||||||||||
325 | defineDefaultProperty(QStringLiteral("call"), method_call, 1); executed 99094 times by 153 tests: return qstring_literal_temp; Executed by:
| 99094 | ||||||||||||
326 | defineDefaultProperty(QStringLiteral("bind"), method_bind, 1); executed 99066 times by 153 tests: return qstring_literal_temp; Executed by:
| 99066 | ||||||||||||
327 | defineDefaultProperty(engine->symbol_hasInstance(), method_hasInstance, 1, Attr_ReadOnly); | - | ||||||||||||
328 | } executed 99035 times by 153 tests: end of block Executed by:
| 99035 | ||||||||||||
329 | - | |||||||||||||
330 | ReturnedValue FunctionPrototype::method_toString(const FunctionObject *b, const Value *thisObject, const Value *, int) | - | ||||||||||||
331 | { | - | ||||||||||||
332 | ExecutionEngine *v4 = b->engine(); | - | ||||||||||||
333 | const FunctionObject *fun = thisObject->as<FunctionObject>(); | - | ||||||||||||
334 | if (!fun)
| 22-1306 | ||||||||||||
335 | return v4->throwTypeError(); executed 22 times by 2 tests: return v4->throwTypeError(); Executed by:
| 22 | ||||||||||||
336 | - | |||||||||||||
337 | const Scope scope(fun->engine()); | - | ||||||||||||
338 | const ScopedString scopedFunctionName(scope, fun->name()); | - | ||||||||||||
339 | const QString functionName(scopedFunctionName ? scopedFunctionName->toQString() : QString()); | - | ||||||||||||
340 | QString functionAsString = QStringLiteral("function"); | - | ||||||||||||
341 | - | |||||||||||||
342 | // If fun->name() is empty, then there is no function name | - | ||||||||||||
343 | // to append because the function is anonymous. | - | ||||||||||||
344 | if (!functionName.isEmpty())
| 600-706 | ||||||||||||
345 | functionAsString.append(QLatin1Char(' ') + functionName); executed 600 times by 4 tests: functionAsString.append(QLatin1Char(' ') + functionName); Executed by:
| 600 | ||||||||||||
346 | - | |||||||||||||
347 | functionAsString.append(QStringLiteral("() { [code] }")); executed 1306 times by 4 tests: return qstring_literal_temp; Executed by:
| 1306 | ||||||||||||
348 | - | |||||||||||||
349 | return Encode(v4->newString(functionAsString)); executed 1306 times by 4 tests: return Encode(v4->newString(functionAsString)); Executed by:
| 1306 | ||||||||||||
350 | } | - | ||||||||||||
351 | - | |||||||||||||
352 | ReturnedValue FunctionPrototype::method_apply(const QV4::FunctionObject *b, const Value *thisObject, const Value *argv, int argc) | - | ||||||||||||
353 | { | - | ||||||||||||
354 | ExecutionEngine *v4 = b->engine(); | - | ||||||||||||
355 | const FunctionObject *f = thisObject->as<FunctionObject>(); | - | ||||||||||||
356 | if (!f)
| 19-259 | ||||||||||||
357 | return v4->throwTypeError(); executed 19 times by 1 test: return v4->throwTypeError(); Executed by:
| 19 | ||||||||||||
358 | thisObject = argc ? argv : nullptr;
| 28-231 | ||||||||||||
359 | if (argc < 2 || argv[1].isNullOrUndefined())
| 0-142 | ||||||||||||
360 | return f->call(thisObject, argv, 0); executed 141 times by 1 test: return f->call(thisObject, argv, 0); Executed by:
| 141 | ||||||||||||
361 | - | |||||||||||||
362 | Object *arr = argv[1].objectValue(); | - | ||||||||||||
363 | if (!arr)
| 8-108 | ||||||||||||
364 | return v4->throwTypeError(); executed 8 times by 1 test: return v4->throwTypeError(); Executed by:
| 8 | ||||||||||||
365 | - | |||||||||||||
366 | uint len = arr->getLength(); | - | ||||||||||||
367 | - | |||||||||||||
368 | Scope scope(v4); | - | ||||||||||||
369 | Value *arguments = scope.alloc(len); | - | ||||||||||||
370 | if (len) {
| 10-98 | ||||||||||||
371 | if (ArgumentsObject::isNonStrictArgumentsObject(arr) && !arr->cast<ArgumentsObject>()->fullyCreated()) {
| 0-84 | ||||||||||||
372 | QV4::ArgumentsObject *a = arr->cast<ArgumentsObject>(); | - | ||||||||||||
373 | int l = qMin(len, (uint)a->d()->context->argc()); | - | ||||||||||||
374 | memcpy(arguments, a->d()->context->args(), l*sizeof(Value)); | - | ||||||||||||
375 | for (quint32 i = l; i < len; ++i)
| 0-14 | ||||||||||||
376 | arguments[i] = Primitive::undefinedValue(); never executed: arguments[i] = Primitive::undefinedValue(); | 0 | ||||||||||||
377 | } else if (arr->arrayType() == Heap::ArrayData::Simple && !arr->protoHasArray()) { executed 14 times by 1 test: end of block Executed by:
| 0-84 | ||||||||||||
378 | auto sad = static_cast<Heap::SimpleArrayData *>(arr->arrayData()); | - | ||||||||||||
379 | uint alen = sad ? sad->values.size : 0;
| 6-78 | ||||||||||||
380 | if (alen > len)
| 0-84 | ||||||||||||
381 | alen = len; never executed: alen = len; | 0 | ||||||||||||
382 | for (uint i = 0; i < alen; ++i)
| 84-226 | ||||||||||||
383 | arguments[i] = sad->data(i); executed 226 times by 1 test: arguments[i] = sad->data(i); Executed by:
| 226 | ||||||||||||
384 | for (quint32 i = alen; i < len; ++i)
| 84-406 | ||||||||||||
385 | arguments[i] = Primitive::undefinedValue(); executed 406 times by 1 test: arguments[i] = Primitive::undefinedValue(); Executed by:
| 406 | ||||||||||||
386 | } else { executed 84 times by 1 test: end of block Executed by:
| 84 | ||||||||||||
387 | for (quint32 i = 0; i < len; ++i)
| 0 | ||||||||||||
388 | arguments[i] = arr->get(i); never executed: arguments[i] = arr->get(i); | 0 | ||||||||||||
389 | } never executed: end of block | 0 | ||||||||||||
390 | } | - | ||||||||||||
391 | - | |||||||||||||
392 | return f->call(thisObject, arguments, len); executed 108 times by 2 tests: return f->call(thisObject, arguments, len); Executed by:
| 108 | ||||||||||||
393 | } | - | ||||||||||||
394 | - | |||||||||||||
395 | ReturnedValue FunctionPrototype::method_call(const QV4::FunctionObject *b, const Value *thisObject, const Value *argv, int argc) | - | ||||||||||||
396 | { | - | ||||||||||||
397 | if (!thisObject->isFunctionObject())
| 44-28216 | ||||||||||||
398 | return b->engine()->throwTypeError(); executed 44 times by 1 test: return b->engine()->throwTypeError(); Executed by:
| 44 | ||||||||||||
399 | - | |||||||||||||
400 | const FunctionObject *f = static_cast<const FunctionObject *>(thisObject); | - | ||||||||||||
401 | - | |||||||||||||
402 | thisObject = argc ? argv : nullptr;
| 34-28183 | ||||||||||||
403 | if (argc) {
| 34-28207 | ||||||||||||
404 | ++argv; | - | ||||||||||||
405 | --argc; | - | ||||||||||||
406 | } executed 28196 times by 3 tests: end of block Executed by:
| 28196 | ||||||||||||
407 | return f->call(thisObject, argv, argc); executed 28237 times by 3 tests: return f->call(thisObject, argv, argc); Executed by:
| 28237 | ||||||||||||
408 | } | - | ||||||||||||
409 | - | |||||||||||||
410 | ReturnedValue FunctionPrototype::method_bind(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc) | - | ||||||||||||
411 | { | - | ||||||||||||
412 | QV4::Scope scope(b); | - | ||||||||||||
413 | ScopedFunctionObject target(scope, thisObject); | - | ||||||||||||
414 | if (!target || target->isBinding())
| 0-571 | ||||||||||||
415 | return scope.engine->throwTypeError(); executed 55 times by 1 test: return scope.engine->throwTypeError(); Executed by:
| 55 | ||||||||||||
416 | - | |||||||||||||
417 | ScopedValue boundThis(scope, argc ? argv[0] : Primitive::undefinedValue()); | - | ||||||||||||
418 | Scoped<MemberData> boundArgs(scope, (Heap::MemberData *)nullptr); | - | ||||||||||||
419 | - | |||||||||||||
420 | int nArgs = (argc - 1 >= 0) ? argc - 1 : 0;
| 114-451 | ||||||||||||
421 | if (target->isBoundFunction()) {
| 22-543 | ||||||||||||
422 | BoundFunction *bound = static_cast<BoundFunction *>(target.getPointer()); | - | ||||||||||||
423 | Scoped<MemberData> oldArgs(scope, bound->boundArgs()); | - | ||||||||||||
424 | boundThis = bound->boundThis(); | - | ||||||||||||
425 | int oldSize = !oldArgs ? 0 : oldArgs->size();
| 2-20 | ||||||||||||
426 | if (oldSize + nArgs) {
| 2-20 | ||||||||||||
427 | boundArgs = MemberData::allocate(scope.engine, oldSize + nArgs); | - | ||||||||||||
428 | boundArgs->d()->values.size = oldSize + nArgs; | - | ||||||||||||
429 | for (uint i = 0; i < static_cast<uint>(oldSize); ++i)
| 2 | ||||||||||||
430 | boundArgs->set(scope.engine, i, oldArgs->data()[i]); executed 2 times by 1 test: boundArgs->set(scope.engine, i, oldArgs->data()[i]); Executed by:
| 2 | ||||||||||||
431 | for (uint i = 0; i < static_cast<uint>(nArgs); ++i)
| 2 | ||||||||||||
432 | boundArgs->set(scope.engine, oldSize + i, argv[i + 1]); executed 2 times by 1 test: boundArgs->set(scope.engine, oldSize + i, argv[i + 1]); Executed by:
| 2 | ||||||||||||
433 | } executed 2 times by 1 test: end of block Executed by:
| 2 | ||||||||||||
434 | target = bound->target(); | - | ||||||||||||
435 | } else if (nArgs) { executed 22 times by 2 tests: end of block Executed by:
| 22-461 | ||||||||||||
436 | boundArgs = MemberData::allocate(scope.engine, nArgs); | - | ||||||||||||
437 | boundArgs->d()->values.size = nArgs; | - | ||||||||||||
438 | for (uint i = 0, ei = static_cast<uint>(nArgs); i < ei; ++i)
| 90-136 | ||||||||||||
439 | boundArgs->set(scope.engine, i, argv[i + 1]); executed 136 times by 3 tests: boundArgs->set(scope.engine, i, argv[i + 1]); Executed by:
| 136 | ||||||||||||
440 | } executed 90 times by 3 tests: end of block Executed by:
| 90 | ||||||||||||
441 | - | |||||||||||||
442 | ScopedContext ctx(scope, target->scope()); | - | ||||||||||||
443 | Heap::BoundFunction *bound = BoundFunction::create(ctx, target, boundThis, boundArgs); | - | ||||||||||||
444 | bound->setFunction(target->function()); | - | ||||||||||||
445 | return bound->asReturnedValue(); executed 574 times by 3 tests: return bound->asReturnedValue(); Executed by:
| 574 | ||||||||||||
446 | } | - | ||||||||||||
447 | - | |||||||||||||
448 | ReturnedValue FunctionPrototype::method_hasInstance(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc) | - | ||||||||||||
449 | { | - | ||||||||||||
450 | if (!argc)
| 8-4235391 | ||||||||||||
451 | return false; executed 8 times by 1 test: return false; Executed by:
| 8 | ||||||||||||
452 | const Object *o = thisObject->as<Object>(); | - | ||||||||||||
453 | if (!o)
| 0-4250958 | ||||||||||||
454 | return f->engine()->throwTypeError(); never executed: return f->engine()->throwTypeError(); | 0 | ||||||||||||
455 | - | |||||||||||||
456 | return Object::virtualInstanceOf(o, argv[0]); executed 4247077 times by 11 tests: return Object::virtualInstanceOf(o, argv[0]); Executed by:
| 4247077 | ||||||||||||
457 | } | - | ||||||||||||
458 | - | |||||||||||||
459 | DEFINE_OBJECT_VTABLE(ScriptFunction); | - | ||||||||||||
460 | - | |||||||||||||
461 | ReturnedValue ScriptFunction::virtualCallAsConstructor(const FunctionObject *fo, const Value *argv, int argc, const Value *newTarget) | - | ||||||||||||
462 | { | - | ||||||||||||
463 | ExecutionEngine *v4 = fo->engine(); | - | ||||||||||||
464 | const ScriptFunction *f = static_cast<const ScriptFunction *>(fo); | - | ||||||||||||
465 | Q_ASSERT(newTarget->isFunctionObject()); | - | ||||||||||||
466 | const FunctionObject *nt = static_cast<const FunctionObject *>(newTarget); | - | ||||||||||||
467 | - | |||||||||||||
468 | Scope scope(v4); | - | ||||||||||||
469 | Scoped<InternalClass> ic(scope); | - | ||||||||||||
470 | if (nt->d() == f->d()) {
| 208-14395 | ||||||||||||
471 | ic = f->classForConstructor(); | - | ||||||||||||
472 | } else { executed 14414 times by 3 tests: end of block Executed by:
| 14414 | ||||||||||||
473 | const Object *o = nt->d()->protoProperty(); | - | ||||||||||||
474 | ic = scope.engine->internalClasses(EngineBase::Class_Object); | - | ||||||||||||
475 | if (o)
| 0-208 | ||||||||||||
476 | ic = ic->changePrototype(o->d()); executed 208 times by 1 test: ic = ic->changePrototype(o->d()); Executed by:
| 208 | ||||||||||||
477 | } executed 208 times by 1 test: end of block Executed by:
| 208 | ||||||||||||
478 | ScopedValue thisObject(scope, v4->memoryManager->allocObject<Object>(ic)); | - | ||||||||||||
479 | - | |||||||||||||
480 | CppStackFrame frame; | - | ||||||||||||
481 | frame.init(v4, f->function(), argv, argc); | - | ||||||||||||
482 | frame.setupJSFrame(v4->jsStackTop, *f, f->scope(), | - | ||||||||||||
483 | thisObject, | - | ||||||||||||
484 | newTarget ? *newTarget : Primitive::undefinedValue()); | - | ||||||||||||
485 | - | |||||||||||||
486 | frame.push(); | - | ||||||||||||
487 | v4->jsStackTop += frame.requiredJSStackFrameSize(); | - | ||||||||||||
488 | - | |||||||||||||
489 | ReturnedValue result = Moth::VME::exec(&frame, v4); | - | ||||||||||||
490 | - | |||||||||||||
491 | frame.pop(); | - | ||||||||||||
492 | - | |||||||||||||
493 | if (Q_UNLIKELY(v4->hasException))
| 66-14561 | ||||||||||||
494 | return Encode::undefined(); executed 66 times by 2 tests: return Encode::undefined(); Executed by:
| 66 | ||||||||||||
495 | else if (!Value::fromReturnedValue(result).isObject())
| 184-14372 | ||||||||||||
496 | return thisObject->asReturnedValue(); executed 14376 times by 3 tests: return thisObject->asReturnedValue(); Executed by:
| 14376 | ||||||||||||
497 | return result; executed 184 times by 2 tests: return result; Executed by:
| 184 | ||||||||||||
498 | } | - | ||||||||||||
499 | - | |||||||||||||
500 | ReturnedValue ScriptFunction::virtualCall(const FunctionObject *fo, const Value *thisObject, const Value *argv, int argc) | - | ||||||||||||
501 | { | - | ||||||||||||
502 | ExecutionEngine *engine = fo->engine(); | - | ||||||||||||
503 | CppStackFrame frame; | - | ||||||||||||
504 | frame.init(engine, fo->function(), argv, argc); | - | ||||||||||||
505 | frame.setupJSFrame(engine->jsStackTop, *fo, fo->scope(), | - | ||||||||||||
506 | thisObject ? *thisObject : Primitive::undefinedValue(), | - | ||||||||||||
507 | Primitive::undefinedValue()); | - | ||||||||||||
508 | - | |||||||||||||
509 | frame.push(); | - | ||||||||||||
510 | engine->jsStackTop += frame.requiredJSStackFrameSize(); | - | ||||||||||||
511 | - | |||||||||||||
512 | ReturnedValue result = Moth::VME::exec(&frame, engine); | - | ||||||||||||
513 | - | |||||||||||||
514 | frame.pop(); | - | ||||||||||||
515 | - | |||||||||||||
516 | return result; executed 14908599 times by 59 tests: return result; Executed by:
| 14908599 | ||||||||||||
517 | } | - | ||||||||||||
518 | - | |||||||||||||
519 | void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function) | - | ||||||||||||
520 | { | - | ||||||||||||
521 | FunctionObject::init(); | - | ||||||||||||
522 | this->scope.set(scope->engine(), scope->d()); | - | ||||||||||||
523 | - | |||||||||||||
524 | setFunction(function); | - | ||||||||||||
525 | Q_ASSERT(function); | - | ||||||||||||
526 | - | |||||||||||||
527 | Scope s(scope); | - | ||||||||||||
528 | ScopedFunctionObject f(s, this); | - | ||||||||||||
529 | - | |||||||||||||
530 | ScopedString name(s, function->name()); | - | ||||||||||||
531 | if (name)
| 0-1522497 | ||||||||||||
532 | f->setName(name); executed 1522416 times by 62 tests: f->setName(name); Executed by:
| 1522416 | ||||||||||||
533 | f->createDefaultPrototypeProperty(Heap::FunctionObject::Index_Prototype, Heap::FunctionObject::Index_ProtoConstructor); | - | ||||||||||||
534 | - | |||||||||||||
535 | Q_ASSERT(internalClass && internalClass->find(s.engine->id_length()->propertyKey()) == Index_Length); | - | ||||||||||||
536 | setProperty(s.engine, Index_Length, Primitive::fromInt32(int(function->compiledFunction->length))); | - | ||||||||||||
537 | } executed 1523569 times by 62 tests: end of block Executed by:
| 1523569 | ||||||||||||
538 | - | |||||||||||||
539 | Heap::InternalClass *ScriptFunction::classForConstructor() const | - | ||||||||||||
540 | { | - | ||||||||||||
541 | const Object *o = d()->protoProperty(); | - | ||||||||||||
542 | if (d()->cachedClassForConstructor && d()->cachedClassForConstructor->prototype == o->d())
| 4-3208 | ||||||||||||
543 | return d()->cachedClassForConstructor; executed 3208 times by 2 tests: return d()->cachedClassForConstructor; Executed by:
| 3208 | ||||||||||||
544 | - | |||||||||||||
545 | Scope scope(engine()); | - | ||||||||||||
546 | Scoped<InternalClass> ic(scope, engine()->internalClasses(EngineBase::Class_Object)); | - | ||||||||||||
547 | if (o)
| 8-11200 | ||||||||||||
548 | ic = ic->changePrototype(o->d()); executed 11200 times by 3 tests: ic = ic->changePrototype(o->d()); Executed by:
| 11200 | ||||||||||||
549 | d()->cachedClassForConstructor.set(scope.engine, ic->d()); | - | ||||||||||||
550 | - | |||||||||||||
551 | return ic->d(); executed 11227 times by 3 tests: return ic->d(); Executed by:
| 11227 | ||||||||||||
552 | } | - | ||||||||||||
553 | - | |||||||||||||
554 | DEFINE_OBJECT_VTABLE(ConstructorFunction); | - | ||||||||||||
555 | - | |||||||||||||
556 | ReturnedValue ConstructorFunction::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget) | - | ||||||||||||
557 | { | - | ||||||||||||
558 | const ConstructorFunction *c = static_cast<const ConstructorFunction *>(f); | - | ||||||||||||
559 | if (!c->d()->isDerivedConstructor)
| 224-376 | ||||||||||||
560 | return ScriptFunction::virtualCallAsConstructor(f, argv, argc, newTarget); executed 224 times by 1 test: return ScriptFunction::virtualCallAsConstructor(f, argv, argc, newTarget); Executed by:
| 224 | ||||||||||||
561 | - | |||||||||||||
562 | ExecutionEngine *v4 = f->engine(); | - | ||||||||||||
563 | - | |||||||||||||
564 | CppStackFrame frame; | - | ||||||||||||
565 | frame.init(v4, f->function(), argv, argc); | - | ||||||||||||
566 | frame.setupJSFrame(v4->jsStackTop, *f, f->scope(), | - | ||||||||||||
567 | Primitive::undefinedValue(), | - | ||||||||||||
568 | newTarget ? *newTarget : Primitive::undefinedValue()); | - | ||||||||||||
569 | - | |||||||||||||
570 | frame.push(); | - | ||||||||||||
571 | v4->jsStackTop += frame.requiredJSStackFrameSize(); | - | ||||||||||||
572 | - | |||||||||||||
573 | ReturnedValue result = Moth::VME::exec(&frame, v4); | - | ||||||||||||
574 | - | |||||||||||||
575 | frame.pop(); | - | ||||||||||||
576 | - | |||||||||||||
577 | if (Q_UNLIKELY(v4->hasException))
| 88-287 | ||||||||||||
578 | return Encode::undefined(); executed 88 times by 1 test: return Encode::undefined(); Executed by:
| 88 | ||||||||||||
579 | else if (Value::fromReturnedValue(result).isObject())
| 12-275 | ||||||||||||
580 | return result; executed 12 times by 1 test: return result; Executed by:
| 12 | ||||||||||||
581 | else if (!Value::fromReturnedValue(result).isUndefined())
| 28-248 | ||||||||||||
582 | return v4->throwTypeError(); executed 28 times by 1 test: return v4->throwTypeError(); Executed by:
| 28 | ||||||||||||
583 | return frame.jsFrame->thisObject.asReturnedValue(); executed 248 times by 1 test: return frame.jsFrame->thisObject.asReturnedValue(); Executed by:
| 248 | ||||||||||||
584 | } | - | ||||||||||||
585 | - | |||||||||||||
586 | ReturnedValue ConstructorFunction::virtualCall(const FunctionObject *f, const Value *, const Value *, int) | - | ||||||||||||
587 | { | - | ||||||||||||
588 | return f->engine()->throwTypeError(QStringLiteral("Cannot call a class constructor without |new|")); executed 16 times by 1 test: return f->engine()->throwTypeError(([]() noexcept -> QString { enum { Size = sizeof(u"" "Cannot call a class constructor without |new|")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" "Cannot call a class constructor without |new|" }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); return qstring_literal_temp; }())); Executed by:
executed 16 times by 1 test: return qstring_literal_temp; Executed by:
| 16 | ||||||||||||
589 | } | - | ||||||||||||
590 | - | |||||||||||||
591 | DEFINE_OBJECT_VTABLE(MemberFunction); | - | ||||||||||||
592 | - | |||||||||||||
593 | ReturnedValue MemberFunction::virtualCallAsConstructor(const FunctionObject *f, const Value *, int, const Value *) | - | ||||||||||||
594 | { | - | ||||||||||||
595 | return f->engine()->throwTypeError(QStringLiteral("Function is not a constructor.")); never executed: return f->engine()->throwTypeError(([]() noexcept -> QString { enum { Size = sizeof(u"" "Function is not a constructor.")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" "Function is not a constructor." }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); return qstring_literal_temp; }())); never executed: return qstring_literal_temp; | 0 | ||||||||||||
596 | } | - | ||||||||||||
597 | - | |||||||||||||
598 | DEFINE_OBJECT_VTABLE(DefaultClassConstructorFunction); | - | ||||||||||||
599 | - | |||||||||||||
600 | ReturnedValue DefaultClassConstructorFunction::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget) | - | ||||||||||||
601 | { | - | ||||||||||||
602 | const DefaultClassConstructorFunction *c = static_cast<const DefaultClassConstructorFunction *>(f); | - | ||||||||||||
603 | ExecutionEngine *v4 = f->engine(); | - | ||||||||||||
604 | - | |||||||||||||
605 | Scope scope(v4); | - | ||||||||||||
606 | - | |||||||||||||
607 | if (!c->d()->isDerivedConstructor) {
| 359-2739 | ||||||||||||
608 | ScopedObject proto(scope, static_cast<const Object *>(newTarget) ->get(scope.engine->id_prototype())); | - | ||||||||||||
609 | ScopedObject c(scope, scope.engine->newObject()); | - | ||||||||||||
610 | c->setPrototypeUnchecked(proto); | - | ||||||||||||
611 | return c->asReturnedValue(); executed 2762 times by 1 test: return c->asReturnedValue(); Executed by:
| 2762 | ||||||||||||
612 | } | - | ||||||||||||
613 | - | |||||||||||||
614 | ScopedFunctionObject super(scope, f->getPrototypeOf()); | - | ||||||||||||
615 | Q_ASSERT(super->isFunctionObject()); | - | ||||||||||||
616 | - | |||||||||||||
617 | CppStackFrame frame; | - | ||||||||||||
618 | frame.init(v4, nullptr, argv, argc); | - | ||||||||||||
619 | frame.setupJSFrame(v4->jsStackTop, *f, f->scope(), | - | ||||||||||||
620 | Primitive::undefinedValue(), | - | ||||||||||||
621 | newTarget ? *newTarget : Primitive::undefinedValue(), argc, argc); | - | ||||||||||||
622 | - | |||||||||||||
623 | frame.push(); | - | ||||||||||||
624 | v4->jsStackTop += frame.requiredJSStackFrameSize(argc); | - | ||||||||||||
625 | - | |||||||||||||
626 | // Do a super call | - | ||||||||||||
627 | ReturnedValue result = super->callAsConstructor(argv, argc, newTarget); | - | ||||||||||||
628 | - | |||||||||||||
629 | frame.pop(); | - | ||||||||||||
630 | - | |||||||||||||
631 | if (Q_UNLIKELY(v4->hasException))
| 12-347 | ||||||||||||
632 | return Encode::undefined(); executed 12 times by 1 test: return Encode::undefined(); Executed by:
| 12 | ||||||||||||
633 | else if (Value::fromReturnedValue(result).isObject())
| 0-348 | ||||||||||||
634 | return result; executed 348 times by 1 test: return result; Executed by:
| 348 | ||||||||||||
635 | else if (!Value::fromReturnedValue(result).isUndefined())
| 0 | ||||||||||||
636 | return v4->throwTypeError(); never executed: return v4->throwTypeError(); | 0 | ||||||||||||
637 | return frame.jsFrame->thisObject.asReturnedValue(); never executed: return frame.jsFrame->thisObject.asReturnedValue(); | 0 | ||||||||||||
638 | } | - | ||||||||||||
639 | - | |||||||||||||
640 | ReturnedValue DefaultClassConstructorFunction::virtualCall(const FunctionObject *f, const Value *, const Value *, int) | - | ||||||||||||
641 | { | - | ||||||||||||
642 | return f->engine()->throwTypeError(QStringLiteral("Cannot call a class constructor without |new|")); executed 20 times by 1 test: return f->engine()->throwTypeError(([]() noexcept -> QString { enum { Size = sizeof(u"" "Cannot call a class constructor without |new|")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" "Cannot call a class constructor without |new|" }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); return qstring_literal_temp; }())); Executed by:
executed 20 times by 1 test: return qstring_literal_temp; Executed by:
| 20 | ||||||||||||
643 | } | - | ||||||||||||
644 | - | |||||||||||||
645 | DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction); | - | ||||||||||||
646 | - | |||||||||||||
647 | DEFINE_OBJECT_VTABLE(BoundFunction); | - | ||||||||||||
648 | - | |||||||||||||
649 | void Heap::BoundFunction::init(QV4::ExecutionContext *scope, QV4::FunctionObject *target, | - | ||||||||||||
650 | const Value &boundThis, QV4::MemberData *boundArgs) | - | ||||||||||||
651 | { | - | ||||||||||||
652 | Scope s(scope); | - | ||||||||||||
653 | Heap::FunctionObject::init(scope, QStringLiteral("__bound function__")); executed 567 times by 3 tests: return qstring_literal_temp; Executed by:
| 567 | ||||||||||||
654 | this->target.set(s.engine, target->d()); | - | ||||||||||||
655 | this->boundArgs.set(s.engine, boundArgs ? boundArgs->d() : nullptr); | - | ||||||||||||
656 | this->boundThis.set(scope->engine(), boundThis); | - | ||||||||||||
657 | - | |||||||||||||
658 | ScopedObject f(s, this); | - | ||||||||||||
659 | - | |||||||||||||
660 | ScopedValue l(s, target->get(s.engine->id_length())); | - | ||||||||||||
661 | int len = l->toUInt32(); | - | ||||||||||||
662 | if (boundArgs)
| 90-480 | ||||||||||||
663 | len -= boundArgs->size(); executed 90 times by 3 tests: len -= boundArgs->size(); Executed by:
| 90 | ||||||||||||
664 | if (len < 0)
| 32-538 | ||||||||||||
665 | len = 0; executed 32 times by 1 test: len = 0; Executed by:
| 32 | ||||||||||||
666 | f->defineReadonlyConfigurableProperty(s.engine->id_length(), Primitive::fromInt32(len)); | - | ||||||||||||
667 | - | |||||||||||||
668 | ScopedProperty pd(s); | - | ||||||||||||
669 | pd->value = s.engine->thrower(); | - | ||||||||||||
670 | pd->set = s.engine->thrower(); | - | ||||||||||||
671 | f->insertMember(s.engine->id_arguments(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); | - | ||||||||||||
672 | f->insertMember(s.engine->id_caller(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); | - | ||||||||||||
673 | } executed 576 times by 3 tests: end of block Executed by:
| 576 | ||||||||||||
674 | - | |||||||||||||
675 | ReturnedValue BoundFunction::virtualCall(const FunctionObject *fo, const Value *, const Value *argv, int argc) | - | ||||||||||||
676 | { | - | ||||||||||||
677 | const BoundFunction *f = static_cast<const BoundFunction *>(fo); | - | ||||||||||||
678 | Scope scope(f->engine()); | - | ||||||||||||
679 | - | |||||||||||||
680 | if (scope.hasException())
| 0-186 | ||||||||||||
681 | return Encode::undefined(); never executed: return Encode::undefined(); | 0 | ||||||||||||
682 | - | |||||||||||||
683 | Scoped<MemberData> boundArgs(scope, f->boundArgs()); | - | ||||||||||||
684 | ScopedFunctionObject target(scope, f->target()); | - | ||||||||||||
685 | JSCallData jsCallData(scope, (boundArgs ? boundArgs->size() : 0) + argc); | - | ||||||||||||
686 | *jsCallData->thisObject = f->boundThis(); | - | ||||||||||||
687 | Value *argp = jsCallData->args; | - | ||||||||||||
688 | if (boundArgs) {
| 42-143 | ||||||||||||
689 | memcpy(argp, boundArgs->data(), boundArgs->size()*sizeof(Value)); | - | ||||||||||||
690 | argp += boundArgs->size(); | - | ||||||||||||
691 | } executed 41 times by 2 tests: end of block Executed by:
| 41 | ||||||||||||
692 | memcpy(argp, argv, argc*sizeof(Value)); | - | ||||||||||||
693 | return target->call(jsCallData); executed 184 times by 2 tests: return target->call(jsCallData); Executed by:
| 184 | ||||||||||||
694 | } | - | ||||||||||||
695 | - | |||||||||||||
696 | ReturnedValue BoundFunction::virtualCallAsConstructor(const FunctionObject *fo, const Value *argv, int argc, const Value *) | - | ||||||||||||
697 | { | - | ||||||||||||
698 | const BoundFunction *f = static_cast<const BoundFunction *>(fo); | - | ||||||||||||
699 | Scope scope(f->engine()); | - | ||||||||||||
700 | - | |||||||||||||
701 | if (scope.hasException())
| 0-100 | ||||||||||||
702 | return Encode::undefined(); never executed: return Encode::undefined(); | 0 | ||||||||||||
703 | - | |||||||||||||
704 | Scoped<MemberData> boundArgs(scope, f->boundArgs()); | - | ||||||||||||
705 | ScopedFunctionObject target(scope, f->target()); | - | ||||||||||||
706 | JSCallData jsCallData(scope, (boundArgs ? boundArgs->size() : 0) + argc); | - | ||||||||||||
707 | Value *argp = jsCallData->args; | - | ||||||||||||
708 | if (boundArgs) {
| 36-64 | ||||||||||||
709 | memcpy(argp, boundArgs->data(), boundArgs->size()*sizeof(Value)); | - | ||||||||||||
710 | argp += boundArgs->size(); | - | ||||||||||||
711 | } executed 36 times by 1 test: end of block Executed by:
| 36 | ||||||||||||
712 | memcpy(argp, argv, argc*sizeof(Value)); | - | ||||||||||||
713 | return target->callAsConstructor(jsCallData); executed 100 times by 1 test: return target->callAsConstructor(jsCallData); Executed by:
| 100 | ||||||||||||
714 | } | - | ||||||||||||
Source code | Switch to Preprocessed file |