| Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/qtdeclarative/src/qtdeclarative/src/qml/jsruntime/qv4argumentsobject.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 | #include <qv4argumentsobject_p.h> | - | ||||||||||||
| 40 | #include <qv4arrayobject_p.h> | - | ||||||||||||
| 41 | #include <qv4alloca_p.h> | - | ||||||||||||
| 42 | #include <qv4scopedvalue_p.h> | - | ||||||||||||
| 43 | #include <qv4string_p.h> | - | ||||||||||||
| 44 | #include <qv4function_p.h> | - | ||||||||||||
| 45 | #include <qv4jscall_p.h> | - | ||||||||||||
| 46 | #include <qv4symbol_p.h> | - | ||||||||||||
| 47 | - | |||||||||||||
| 48 | using namespace QV4; | - | ||||||||||||
| 49 | - | |||||||||||||
| 50 | DEFINE_OBJECT_VTABLE(ArgumentsObject); | - | ||||||||||||
| 51 | DEFINE_OBJECT_VTABLE(StrictArgumentsObject); | - | ||||||||||||
| 52 | - | |||||||||||||
| 53 | void Heap::ArgumentsObject::init(QV4::CppStackFrame *frame) | - | ||||||||||||
| 54 | { | - | ||||||||||||
| 55 | ExecutionEngine *v4 = internalClass->engine; | - | ||||||||||||
| 56 | - | |||||||||||||
| 57 | int nFormals = frame->v4Function->nFormals; | - | ||||||||||||
| 58 | QV4::CallContext *context = static_cast<QV4::CallContext *>(frame->context()); | - | ||||||||||||
| 59 | - | |||||||||||||
| 60 | Object::init(); | - | ||||||||||||
| 61 | fullyCreated = false; | - | ||||||||||||
| 62 | this->nFormals = nFormals; | - | ||||||||||||
| 63 | this->context.set(v4, context->d()); | - | ||||||||||||
| 64 | Q_ASSERT(vtable() == QV4::ArgumentsObject::staticVTable()); | - | ||||||||||||
| 65 | - | |||||||||||||
| 66 | Q_ASSERT(CalleePropertyIndex == internalClass->find(v4->id_callee()->propertyKey())); | - | ||||||||||||
| 67 | setProperty(v4, CalleePropertyIndex, context->d()->function); | - | ||||||||||||
| 68 | Q_ASSERT(LengthPropertyIndex == internalClass->find(v4->id_length()->propertyKey())); | - | ||||||||||||
| 69 | setProperty(v4, LengthPropertyIndex, Primitive::fromInt32(context->argc())); | - | ||||||||||||
| 70 | Q_ASSERT(SymbolIteratorPropertyIndex == internalClass->find(v4->symbol_iterator()->propertyKey())); | - | ||||||||||||
| 71 | setProperty(v4, SymbolIteratorPropertyIndex, *v4->arrayProtoValues()); | - | ||||||||||||
| 72 | } executed 4487 times by 11 tests: end of blockExecuted by:
| 4487 | ||||||||||||
| 73 | - | |||||||||||||
| 74 | void Heap::StrictArgumentsObject::init(QV4::CppStackFrame *frame) | - | ||||||||||||
| 75 | { | - | ||||||||||||
| 76 | Q_ASSERT(vtable() == QV4::StrictArgumentsObject::staticVTable()); | - | ||||||||||||
| 77 | ExecutionEngine *v4 = internalClass->engine; | - | ||||||||||||
| 78 | - | |||||||||||||
| 79 | Object::init(); | - | ||||||||||||
| 80 | - | |||||||||||||
| 81 | Q_ASSERT(CalleePropertyIndex == internalClass->find(v4->id_callee()->propertyKey())); | - | ||||||||||||
| 82 | Q_ASSERT(SymbolIteratorPropertyIndex == internalClass->find(v4->symbol_iterator()->propertyKey())); | - | ||||||||||||
| 83 | setProperty(v4, SymbolIteratorPropertyIndex, *v4->arrayProtoValues()); | - | ||||||||||||
| 84 | setProperty(v4, CalleePropertyIndex + QV4::Object::GetterOffset, *v4->thrower()); | - | ||||||||||||
| 85 | setProperty(v4, CalleePropertyIndex + QV4::Object::SetterOffset, *v4->thrower()); | - | ||||||||||||
| 86 | - | |||||||||||||
| 87 | Scope scope(v4); | - | ||||||||||||
| 88 | Scoped<QV4::StrictArgumentsObject> args(scope, this); | - | ||||||||||||
| 89 | args->arrayReserve(frame->originalArgumentsCount); | - | ||||||||||||
| 90 | args->arrayPut(0, frame->originalArguments, frame->originalArgumentsCount); | - | ||||||||||||
| 91 | - | |||||||||||||
| 92 | Q_ASSERT(LengthPropertyIndex == args->internalClass()->find(v4->id_length()->propertyKey())); | - | ||||||||||||
| 93 | setProperty(v4, LengthPropertyIndex, Primitive::fromInt32(frame->originalArgumentsCount)); | - | ||||||||||||
| 94 | } executed 3836 times by 2 tests: end of blockExecuted by:
| 3836 | ||||||||||||
| 95 | - | |||||||||||||
| 96 | void ArgumentsObject::fullyCreate() | - | ||||||||||||
| 97 | { | - | ||||||||||||
| 98 | if (fullyCreated())
| 446-1101 | ||||||||||||
| 99 | return; executed 1101 times by 1 test: return;Executed by:
| 1101 | ||||||||||||
| 100 | - | |||||||||||||
| 101 | Scope scope(engine()); | - | ||||||||||||
| 102 | - | |||||||||||||
| 103 | int argCount = context()->argc(); | - | ||||||||||||
| 104 | uint numAccessors = qMin(d()->nFormals, argCount); | - | ||||||||||||
| 105 | ArrayData::realloc(this, Heap::ArrayData::Sparse, argCount, true); | - | ||||||||||||
| 106 | scope.engine->requireArgumentsAccessors(numAccessors); | - | ||||||||||||
| 107 | - | |||||||||||||
| 108 | Scoped<MemberData> md(scope, d()->mappedArguments); | - | ||||||||||||
| 109 | if (numAccessors) {
| 200-252 | ||||||||||||
| 110 | d()->mappedArguments.set(scope.engine, md->allocate(scope.engine, numAccessors)); | - | ||||||||||||
| 111 | for (uint i = 0; i < numAccessors; ++i) {
| 198-403 | ||||||||||||
| 112 | d()->mappedArguments->values.set(scope.engine, i, context()->args()[i]); | - | ||||||||||||
| 113 | arraySet(i, scope.engine->argumentsAccessors + i, Attr_Accessor); | - | ||||||||||||
| 114 | } executed 403 times by 1 test: end of blockExecuted by:
| 403 | ||||||||||||
| 115 | } executed 199 times by 1 test: end of blockExecuted by:
| 199 | ||||||||||||
| 116 | arrayPut(numAccessors, context()->args() + numAccessors, argCount - numAccessors); | - | ||||||||||||
| 117 | for (int i = int(numAccessors); i < argCount; ++i)
| 334-451 | ||||||||||||
| 118 | setArrayAttributes(i, Attr_Data); executed 334 times by 1 test: setArrayAttributes(i, Attr_Data);Executed by:
| 334 | ||||||||||||
| 119 | - | |||||||||||||
| 120 | d()->fullyCreated = true; | - | ||||||||||||
| 121 | } executed 450 times by 1 test: end of blockExecuted by:
| 450 | ||||||||||||
| 122 | - | |||||||||||||
| 123 | bool ArgumentsObject::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property *desc, PropertyAttributes attrs) | - | ||||||||||||
| 124 | { | - | ||||||||||||
| 125 | if (!id.isArrayIndex())
| 188-399 | ||||||||||||
| 126 | return Object::virtualDefineOwnProperty(m, id, desc, attrs); executed 188 times by 1 test: return Object::virtualDefineOwnProperty(m, id, desc, attrs);Executed by:
| 188 | ||||||||||||
| 127 | - | |||||||||||||
| 128 | ArgumentsObject *a = static_cast<ArgumentsObject *>(m); | - | ||||||||||||
| 129 | a->fullyCreate(); | - | ||||||||||||
| 130 | - | |||||||||||||
| 131 | uint index = id.asArrayIndex(); | - | ||||||||||||
| 132 | Scope scope(m); | - | ||||||||||||
| 133 | ScopedProperty map(scope); | - | ||||||||||||
| 134 | PropertyAttributes mapAttrs; | - | ||||||||||||
| 135 | uint numAccessors = qMin(a->d()->nFormals, a->context()->argc()); | - | ||||||||||||
| 136 | bool isMapped = false; | - | ||||||||||||
| 137 | if (a->arrayData() && index < numAccessors &&
| 0-401 | ||||||||||||
| 138 | a->arrayData()->attributes(index).isAccessor() &&
| 80-144 | ||||||||||||
| 139 | a->arrayData()->get(index) == scope.engine->argumentsAccessors[index].getter()->asReturnedValue())
| 20-124 | ||||||||||||
| 140 | isMapped = true; executed 124 times by 1 test: isMapped = true;Executed by:
| 124 | ||||||||||||
| 141 | - | |||||||||||||
| 142 | if (isMapped) {
| 124-276 | ||||||||||||
| 143 | Q_ASSERT(a->arrayData()); | - | ||||||||||||
| 144 | mapAttrs = a->arrayData()->attributes(index); | - | ||||||||||||
| 145 | a->arrayData()->getProperty(index, map, &mapAttrs); | - | ||||||||||||
| 146 | a->setArrayAttributes(index, Attr_Data); | - | ||||||||||||
| 147 | PropertyIndex arrayIndex{ a->arrayData(), a->arrayData()->values.values + a->arrayData()->mappedIndex(index) }; | - | ||||||||||||
| 148 | arrayIndex.set(scope.engine, a->d()->mappedArguments->values[index]); | - | ||||||||||||
| 149 | } executed 126 times by 1 test: end of blockExecuted by:
| 126 | ||||||||||||
| 150 | - | |||||||||||||
| 151 | bool result = Object::virtualDefineOwnProperty(m, id, desc, attrs); | - | ||||||||||||
| 152 | if (!result)
| 88-312 | ||||||||||||
| 153 | return false; executed 88 times by 1 test: return false;Executed by:
| 88 | ||||||||||||
| 154 | - | |||||||||||||
| 155 | if (isMapped && attrs.isData()) {
| 52-188 | ||||||||||||
| 156 | Q_ASSERT(a->arrayData()); | - | ||||||||||||
| 157 | ScopedFunctionObject setter(scope, map->setter()); | - | ||||||||||||
| 158 | JSCallData jsCallData(scope, 1); | - | ||||||||||||
| 159 | *jsCallData->thisObject = a->asReturnedValue(); | - | ||||||||||||
| 160 | jsCallData->args[0] = desc->value; | - | ||||||||||||
| 161 | setter->call(jsCallData); | - | ||||||||||||
| 162 | - | |||||||||||||
| 163 | if (attrs.isWritable()) {
| 2-49 | ||||||||||||
| 164 | a->setArrayAttributes(index, mapAttrs); | - | ||||||||||||
| 165 | a->arrayData()->setProperty(m->engine(), index, map); | - | ||||||||||||
| 166 | } executed 2 times by 1 test: end of blockExecuted by:
| 2 | ||||||||||||
| 167 | } executed 51 times by 1 test: end of blockExecuted by:
| 51 | ||||||||||||
| 168 | - | |||||||||||||
| 169 | return result; executed 313 times by 1 test: return result;Executed by:
| 313 | ||||||||||||
| 170 | } | - | ||||||||||||
| 171 | - | |||||||||||||
| 172 | ReturnedValue ArgumentsObject::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty) | - | ||||||||||||
| 173 | { | - | ||||||||||||
| 174 | const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m); | - | ||||||||||||
| 175 | if (id.isArrayIndex() && !args->fullyCreated()) {
| 525-1601 | ||||||||||||
| 176 | uint index = id.asArrayIndex(); | - | ||||||||||||
| 177 | if (index < static_cast<uint>(args->context()->argc())) {
| 28-1047 | ||||||||||||
| 178 | if (hasProperty)
| 222-825 | ||||||||||||
| 179 | *hasProperty = true; executed 222 times by 1 test: *hasProperty = true;Executed by:
| 222 | ||||||||||||
| 180 | return args->context()->args()[index].asReturnedValue(); executed 1046 times by 4 tests: return args->context()->args()[index].asReturnedValue();Executed by:
| 1046 | ||||||||||||
| 181 | } | - | ||||||||||||
| 182 | } executed 28 times by 2 tests: end of blockExecuted by:
| 28 | ||||||||||||
| 183 | return Object::virtualGet(m, id, receiver, hasProperty); executed 1844 times by 6 tests: return Object::virtualGet(m, id, receiver, hasProperty);Executed by:
| 1844 | ||||||||||||
| 184 | } | - | ||||||||||||
| 185 | - | |||||||||||||
| 186 | bool ArgumentsObject::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver) | - | ||||||||||||
| 187 | { | - | ||||||||||||
| 188 | ArgumentsObject *args = static_cast<ArgumentsObject *>(m); | - | ||||||||||||
| 189 | if (id.isArrayIndex()) {
| 237-327 | ||||||||||||
| 190 | uint index = id.asArrayIndex(); | - | ||||||||||||
| 191 | if (!args->fullyCreated() && index >= static_cast<uint>(args->context()->argc()))
| 16-191 | ||||||||||||
| 192 | args->fullyCreate(); executed 30 times by 1 test: args->fullyCreate();Executed by:
| 30 | ||||||||||||
| 193 | - | |||||||||||||
| 194 | if (!args->fullyCreated()) {
| 16-221 | ||||||||||||
| 195 | args->context()->setArg(index, value); | - | ||||||||||||
| 196 | return true; executed 16 times by 1 test: return true;Executed by:
| 16 | ||||||||||||
| 197 | } | - | ||||||||||||
| 198 | } executed 221 times by 1 test: end of blockExecuted by:
| 221 | ||||||||||||
| 199 | return Object::virtualPut(m, id, value, receiver); executed 549 times by 1 test: return Object::virtualPut(m, id, value, receiver);Executed by:
| 549 | ||||||||||||
| 200 | } | - | ||||||||||||
| 201 | - | |||||||||||||
| 202 | bool ArgumentsObject::virtualDeleteProperty(Managed *m, PropertyKey id) | - | ||||||||||||
| 203 | { | - | ||||||||||||
| 204 | ArgumentsObject *args = static_cast<ArgumentsObject *>(m); | - | ||||||||||||
| 205 | if (!args->fullyCreated())
| 54-287 | ||||||||||||
| 206 | args->fullyCreate(); executed 53 times by 1 test: args->fullyCreate();Executed by:
| 53 | ||||||||||||
| 207 | return Object::virtualDeleteProperty(m, id); executed 342 times by 1 test: return Object::virtualDeleteProperty(m, id);Executed by:
| 342 | ||||||||||||
| 208 | } | - | ||||||||||||
| 209 | - | |||||||||||||
| 210 | PropertyAttributes ArgumentsObject::virtualGetOwnProperty(Managed *m, PropertyKey id, Property *p) | - | ||||||||||||
| 211 | { | - | ||||||||||||
| 212 | const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m); | - | ||||||||||||
| 213 | if (!id.isArrayIndex() || args->fullyCreated())
| 2-978 | ||||||||||||
| 214 | return Object::virtualGetOwnProperty(m, id, p); executed 1778 times by 1 test: return Object::virtualGetOwnProperty(m, id, p);Executed by:
| 1778 | ||||||||||||
| 215 | - | |||||||||||||
| 216 | uint index = id.asArrayIndex(); | - | ||||||||||||
| 217 | uint argCount = args->context()->argc(); | - | ||||||||||||
| 218 | if (index >= argCount)
| 0-2 | ||||||||||||
| 219 | return PropertyAttributes(); executed 2 times by 1 test: return PropertyAttributes();Executed by:
| 2 | ||||||||||||
| 220 | if (p)
| 0 | ||||||||||||
| 221 | p->value = args->context()->args()[index]; never executed: p->value = args->context()->args()[index]; | 0 | ||||||||||||
| 222 | return Attr_Data; never executed: return Attr_Data; | 0 | ||||||||||||
| 223 | } | - | ||||||||||||
| 224 | - | |||||||||||||
| 225 | DEFINE_OBJECT_VTABLE(ArgumentsGetterFunction); | - | ||||||||||||
| 226 | - | |||||||||||||
| 227 | ReturnedValue ArgumentsGetterFunction::virtualCall(const FunctionObject *getter, const Value *thisObject, const Value *, int) | - | ||||||||||||
| 228 | { | - | ||||||||||||
| 229 | ExecutionEngine *v4 = getter->engine(); | - | ||||||||||||
| 230 | Scope scope(v4); | - | ||||||||||||
| 231 | const ArgumentsGetterFunction *g = static_cast<const ArgumentsGetterFunction *>(getter); | - | ||||||||||||
| 232 | Scoped<ArgumentsObject> o(scope, thisObject->as<ArgumentsObject>()); | - | ||||||||||||
| 233 | if (!o)
| 0-48 | ||||||||||||
| 234 | return v4->throwTypeError(); never executed: return v4->throwTypeError(); | 0 | ||||||||||||
| 235 | - | |||||||||||||
| 236 | Q_ASSERT(g->index() < static_cast<unsigned>(o->context()->argc())); | - | ||||||||||||
| 237 | return o->context()->args()[g->index()].asReturnedValue(); executed 48 times by 1 test: return o->context()->args()[g->index()].asReturnedValue();Executed by:
| 48 | ||||||||||||
| 238 | } | - | ||||||||||||
| 239 | - | |||||||||||||
| 240 | DEFINE_OBJECT_VTABLE(ArgumentsSetterFunction); | - | ||||||||||||
| 241 | - | |||||||||||||
| 242 | ReturnedValue ArgumentsSetterFunction::virtualCall(const FunctionObject *setter, const Value *thisObject, const Value *argv, int argc) | - | ||||||||||||
| 243 | { | - | ||||||||||||
| 244 | ExecutionEngine *v4 = setter->engine(); | - | ||||||||||||
| 245 | Scope scope(v4); | - | ||||||||||||
| 246 | const ArgumentsSetterFunction *s = static_cast<const ArgumentsSetterFunction *>(setter); | - | ||||||||||||
| 247 | Scoped<ArgumentsObject> o(scope, thisObject->as<ArgumentsObject>()); | - | ||||||||||||
| 248 | if (!o)
| 0-51 | ||||||||||||
| 249 | return v4->throwTypeError(); never executed: return v4->throwTypeError(); | 0 | ||||||||||||
| 250 | - | |||||||||||||
| 251 | Q_ASSERT(s->index() < static_cast<unsigned>(o->context()->argc())); | - | ||||||||||||
| 252 | o->context()->setArg(s->index(), argc ? argv[0] : Primitive::undefinedValue()); | - | ||||||||||||
| 253 | return Encode::undefined(); executed 51 times by 1 test: return Encode::undefined();Executed by:
| 51 | ||||||||||||
| 254 | } | - | ||||||||||||
| 255 | - | |||||||||||||
| 256 | qint64 ArgumentsObject::virtualGetLength(const Managed *m) | - | ||||||||||||
| 257 | { | - | ||||||||||||
| 258 | const ArgumentsObject *a = static_cast<const ArgumentsObject *>(m); | - | ||||||||||||
| 259 | return a->propertyData(Heap::ArgumentsObject::LengthPropertyIndex)->toLength(); executed 208 times by 1 test: return a->propertyData(Heap::ArgumentsObject::LengthPropertyIndex)->toLength();Executed by:
| 208 | ||||||||||||
| 260 | } | - | ||||||||||||
| Source code | Switch to Preprocessed file |