Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qv4argumentsobject.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant
4
6
7#include <private/qv4alloca_p.h>
8#include <private/qv4arrayobject_p.h>
9#include <private/qv4function_p.h>
10#include <private/qv4jscall_p.h>
11#include <private/qv4scopedvalue_p.h>
12#include <private/qv4stackframe_p.h>
13#include <private/qv4string_p.h>
14#include <private/qv4symbol_p.h>
15
16using namespace QV4;
17
20
21void Heap::StrictArgumentsObject::init(QV4::JSTypesStackFrame *frame)
22
23{
24 Q_ASSERT(vtable() == QV4::StrictArgumentsObject::staticVTable());
25 ExecutionEngine *v4 = internalClass->engine;
26
27 Object::init();
28
29 Q_ASSERT(internalClass->verifyIndex(v4->id_callee()->propertyKey(), CalleePropertyIndex));
30 Q_ASSERT(internalClass->findValueOrSetter(v4->id_callee()->propertyKey()).index == CalleeSetterPropertyIndex);
31 Q_ASSERT(internalClass->verifyIndex(v4->symbol_iterator()->propertyKey(), SymbolIteratorPropertyIndex));
32 setProperty(v4, SymbolIteratorPropertyIndex, *v4->arrayProtoValues());
33 setProperty(v4, CalleePropertyIndex, *v4->thrower());
34 setProperty(v4, CalleeSetterPropertyIndex, *v4->thrower());
35
36 Scope scope(v4);
37 Scoped<QV4::StrictArgumentsObject> args(scope, this);
38 args->arrayReserve(frame->argc());
39 args->arrayPut(0, frame->argv(), frame->argc());
40
41 Q_ASSERT(args->internalClass()->verifyIndex(v4->id_length()->propertyKey(), LengthPropertyIndex));
42 setProperty(v4, LengthPropertyIndex, Value::fromInt32(frame->argc()));
43}
44
45void Heap::ArgumentsObject::init(QV4::CppStackFrame *frame)
46{
47 ExecutionEngine *v4 = internalClass->engine;
48
49 QV4::CallContext *context = static_cast<QV4::CallContext *>(frame->context());
50
51 Object::init();
52 this->context.set(v4, context->d());
53 Q_ASSERT(vtable() == QV4::ArgumentsObject::staticVTable());
54
55 Q_ASSERT(internalClass->verifyIndex(v4->id_callee()->propertyKey(), CalleePropertyIndex));
56 setProperty(v4, CalleePropertyIndex, context->d()->function);
57 Q_ASSERT(internalClass->verifyIndex(v4->id_length()->propertyKey(), LengthPropertyIndex));
58 setProperty(v4, LengthPropertyIndex, Value::fromInt32(context->argc()));
59 Q_ASSERT(internalClass->verifyIndex(v4->symbol_iterator()->propertyKey(), SymbolIteratorPropertyIndex));
60 setProperty(v4, SymbolIteratorPropertyIndex, *v4->arrayProtoValues());
61
62 fullyCreated = false;
63 argCount = frame->argc();
64 uint nFormals = frame->v4Function->nFormals;
65 mapped = nFormals > 63 ? std::numeric_limits<quint64>::max() : (1ull << nFormals) - 1;
66}
67
68void ArgumentsObject::fullyCreate()
69{
70 if (d()->fullyCreated)
71 return;
72
73 Scope scope(engine());
74
75 arrayReserve(d()->argCount);
76 arrayPut(0, context()->args(), d()->argCount);
77 // Use a sparse array, so that method_getElement() doesn't shortcut
78 initSparseArray();
79
80 d()->fullyCreated = true;
81}
82
83bool ArgumentsObject::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property *desc, PropertyAttributes attrs)
84{
85 ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
86 args->fullyCreate();
87 if (!id.isArrayIndex())
88 return Object::virtualDefineOwnProperty(m, id, desc, attrs);
89
90 uint index = id.asArrayIndex();
91
92 if (!args->isMapped(index))
93 return Object::virtualDefineOwnProperty(m, id, desc, attrs);
94
95 Scope scope(args);
96 PropertyAttributes cAttrs = attrs;
97 ScopedProperty cDesc(scope);
98 cDesc->copy(desc, attrs);
99
100 if (attrs.isData() && desc->value.isEmpty() && attrs.hasWritable() && !attrs.isWritable()) {
101 cDesc->value = args->context()->args()[index];
102 cAttrs.setType(PropertyAttributes::Data);
103 }
104
105 bool allowed = Object::virtualDefineOwnProperty(m, id, cDesc, cAttrs);
106 if (!allowed)
107 return false;
108
109 if (attrs.isAccessor()) {
110 args->removeMapping(index);
111 } else {
112 if (!desc->value.isEmpty())
113 args->context()->setArg(index, desc->value);
114 if (attrs.hasWritable() && !attrs.isWritable())
115 args->removeMapping(index);
116 }
117 return true;
118}
119
120ReturnedValue ArgumentsObject::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
121{
122 if (id.isArrayIndex()) {
123 const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m);
124 uint index = id.asArrayIndex();
125 if (index < args->d()->argCount && !args->d()->fullyCreated) {
126 if (hasProperty)
127 *hasProperty = true;
128 return args->context()->args()[index].asReturnedValue();
129 }
130
131 if (args->isMapped(index)) {
132 Q_ASSERT(index < static_cast<uint>(args->context()->function->formalParameterCount()));
133 if (hasProperty)
134 *hasProperty = true;
135 return args->context()->args()[index].asReturnedValue();
136 }
137 }
138
139 return Object::virtualGet(m, id, receiver, hasProperty);
140}
141
142bool ArgumentsObject::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
143{
144 if (id.isArrayIndex()) {
145 ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
146 uint index = id.asArrayIndex();
147
148 if (args == receiver && index < args->d()->argCount && !args->d()->fullyCreated) {
149 args->context()->setArg(index, value);
150 return true;
151 }
152
153 bool isMapped = (args == receiver && args->isMapped(index));
154 if (isMapped)
155 args->context()->setArg(index, value);
156 }
157
158 return Object::virtualPut(m, id, value, receiver);
159}
160
161bool ArgumentsObject::virtualDeleteProperty(Managed *m, PropertyKey id)
162{
163 ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
164 args->fullyCreate();
165 bool result = Object::virtualDeleteProperty(m, id);
166 if (result && id.isArrayIndex())
167 args->removeMapping(id.asArrayIndex());
168 return result;
169}
170
171PropertyAttributes ArgumentsObject::virtualGetOwnProperty(const Managed *m, PropertyKey id, Property *p)
172{
173 if (!id.isArrayIndex())
174 return Object::virtualGetOwnProperty(m, id, p);
175
176 const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m);
177 uint index = id.asArrayIndex();
178 if (index < args->d()->argCount && !args->d()->fullyCreated) {
179 p->value = args->context()->args()[index];
180 return Attr_Data;
181 }
182
183 PropertyAttributes attrs = Object::virtualGetOwnProperty(m, id, p);
184 if (attrs.isEmpty() || !args->isMapped(index))
185 return attrs;
186
187 Q_ASSERT(index < static_cast<uint>(args->context()->function->formalParameterCount()));
188 if (p)
189 p->value = args->context()->args()[index];
190 return attrs;
191}
192
193qint64 ArgumentsObject::virtualGetLength(const Managed *m)
194{
195 const ArgumentsObject *a = static_cast<const ArgumentsObject *>(m);
196 return a->propertyData(Heap::ArgumentsObject::LengthPropertyIndex)->toLength();
197}
198
199OwnPropertyKeyIterator *ArgumentsObject::virtualOwnPropertyKeys(const Object *m, Value *target)
200{
201 static_cast<ArgumentsObject *>(const_cast<Object *>(m))->fullyCreate();
202 return Object::virtualOwnPropertyKeys(m, target);
203}
DEFINE_OBJECT_VTABLE(StrictArgumentsObject)
DEFINE_OBJECT_VTABLE(ArgumentsObject)