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
qv4reflect.cpp
Go to the documentation of this file.
1// Copyright (C) 2018 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
5#include "qv4reflect_p.h"
10
11using namespace QV4;
12
14
15void Heap::Reflect::init()
16{
17 Object::init();
18 Scope scope(internalClass->engine);
19 ScopedObject r(scope, this);
20
21 r->defineDefaultProperty(QStringLiteral("apply"), QV4::Reflect::method_apply, 3);
22 r->defineDefaultProperty(QStringLiteral("construct"), QV4::Reflect::method_construct, 2);
23 r->defineDefaultProperty(QStringLiteral("defineProperty"), QV4::Reflect::method_defineProperty, 3);
24 r->defineDefaultProperty(QStringLiteral("deleteProperty"), QV4::Reflect::method_deleteProperty, 2);
25 r->defineDefaultProperty(QStringLiteral("get"), QV4::Reflect::method_get, 2);
26 r->defineDefaultProperty(QStringLiteral("getOwnPropertyDescriptor"), QV4::Reflect::method_getOwnPropertyDescriptor, 2);
27 r->defineDefaultProperty(QStringLiteral("getPrototypeOf"), QV4::Reflect::method_getPrototypeOf, 1);
28 r->defineDefaultProperty(QStringLiteral("has"), QV4::Reflect::method_has, 2);
29 r->defineDefaultProperty(QStringLiteral("isExtensible"), QV4::Reflect::method_isExtensible, 1);
30 r->defineDefaultProperty(QStringLiteral("ownKeys"), QV4::Reflect::method_ownKeys, 1);
31 r->defineDefaultProperty(QStringLiteral("preventExtensions"), QV4::Reflect::method_preventExtensions, 1);
32 r->defineDefaultProperty(QStringLiteral("set"), QV4::Reflect::method_set, 3);
33 r->defineDefaultProperty(QStringLiteral("setPrototypeOf"), QV4::Reflect::method_setPrototypeOf, 2);
34}
35
36struct CallArgs {
38 int argc;
39};
40
41static CallArgs createListFromArrayLike(Scope &scope, const Object *o)
42{
43 int len = scope.engine->safeForAllocLength(o->getLength());
44 if (scope.engine->hasException)
45 return {nullptr, 0};
46
47 Value *arguments = scope.constructUndefined(len);
48
49 for (int i = 0; i < len; ++i) {
50 arguments[i] = o->get(i);
51 if (scope.hasException())
52 return { nullptr, 0 };
53 }
54 return { arguments, len };
55}
56
57ReturnedValue Reflect::method_apply(const FunctionObject *f, const Value *, const Value *argv, int argc)
58{
59 Scope scope(f);
60 if (argc < 3 || !argv[0].isFunctionObject() || !argv[2].isObject())
61 return scope.engine->throwTypeError();
62
63 const Object *o = static_cast<const Object *>(argv + 2);
64 CallArgs arguments = createListFromArrayLike(scope, o);
65 if (scope.hasException())
66 return Encode::undefined();
67
68 return checkedResult(scope.engine, static_cast<const FunctionObject &>(argv[0]).call(
69 &argv[1], arguments.argv, arguments.argc));
70}
71
72ReturnedValue Reflect::method_construct(const FunctionObject *f, const Value *, const Value *argv, int argc)
73{
74 Scope scope(f);
75 if (argc < 2 || !argv[1].isObject())
76 return scope.engine->throwTypeError();
77 const FunctionObject *target = argv[0].as<FunctionObject>();
78 const FunctionObject *newTarget = argc == 3 ? argv[2].as<FunctionObject>() : target;
79 if (!target || !target->isConstructor() || !newTarget || !newTarget->isConstructor())
80 return scope.engine->throwTypeError();
81
82 const Object *o = static_cast<const Object *>(argv + 1);
83 CallArgs arguments = createListFromArrayLike(scope, o);
84 if (scope.hasException())
85 return Encode::undefined();
86
87 return target->callAsConstructor(arguments.argv, arguments.argc, newTarget);
88}
89
90ReturnedValue Reflect::method_defineProperty(const FunctionObject *f, const Value *, const Value *argv, int argc)
91{
92 Scope scope(f);
93 if (!argc || !argv[0].isObject())
94 return scope.engine->throwTypeError();
95
96 ScopedObject O(scope, argv[0]);
97 ScopedPropertyKey name(scope, (argc > 1 ? argv[1] : Value::undefinedValue()).toPropertyKey(scope.engine));
98 if (scope.hasException())
99 return QV4::Encode::undefined();
100
101 ScopedValue attributes(scope, argc > 2 ? argv[2] : Value::undefinedValue());
102 ScopedProperty pd(scope);
103 PropertyAttributes attrs;
104 ObjectPrototype::toPropertyDescriptor(scope.engine, attributes, pd, &attrs);
105 if (scope.hasException())
106 return QV4::Encode::undefined();
107
108 bool result = O->defineOwnProperty(name, pd, attrs);
109
110 return Encode(result);
111}
112
113ReturnedValue Reflect::method_deleteProperty(const FunctionObject *f, const Value *, const Value *argv, int argc)
114{
115 ExecutionEngine *e = f->engine();
116 if (!argc || !argv[0].isObject())
117 return e->throwTypeError();
118
119 bool result = Runtime::DeleteProperty_NoThrow::call(e, argv[0], argc > 1 ? argv[1] : Value::undefinedValue());
120 return Encode(result);
121}
122
123ReturnedValue Reflect::method_get(const FunctionObject *f, const Value *, const Value *argv, int argc)
124{
125 Scope scope(f);
126 if (!argc || !argv[0].isObject())
127 return scope.engine->throwTypeError();
128
129 ScopedObject o(scope, static_cast<const Object *>(argv));
130 Value undef = Value::undefinedValue();
131 const Value *index = argc > 1 ? &argv[1] : &undef;
132 ScopedPropertyKey name(scope, index->toPropertyKey(scope.engine));
133 if (scope.hasException())
134 return Encode::undefined();
135 ScopedValue receiver(scope, argc > 2 ? argv[2] : *o);
136
137 return Encode(o->get(name, receiver));
138}
139
140ReturnedValue Reflect::method_getOwnPropertyDescriptor(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
141{
142 if (!argc || !argv[0].isObject())
143 return f->engine()->throwTypeError();
144
145 return ObjectPrototype::method_getOwnPropertyDescriptor(f, thisObject, argv, argc);
146}
147
148ReturnedValue Reflect::method_getPrototypeOf(const FunctionObject *f, const Value *, const Value *argv, int argc)
149{
150 if (!argc || !argv[0].isObject())
151 return f->engine()->throwTypeError();
152
153 const Object *o = static_cast<const Object *>(argv);
154 Heap::Object *p = o->getPrototypeOf();
155 return (p ? p->asReturnedValue() : Encode::null());
156}
157
158ReturnedValue Reflect::method_has(const FunctionObject *f, const Value *, const Value *argv, int argc)
159{
160 Scope scope(f);
161 if (!argc || !argv[0].isObject())
162 return scope.engine->throwTypeError();
163
164 ScopedObject o(scope, static_cast<const Object *>(argv));
165 Value undef = Value::undefinedValue();
166 const Value *index = argc > 1 ? &argv[1] : &undef;
167
168 ScopedPropertyKey name(scope, index->toPropertyKey(scope.engine));
169 if (scope.hasException())
170 return false;
171
172 return Encode(o->hasProperty(name));
173}
174
175ReturnedValue Reflect::method_isExtensible(const FunctionObject *f, const Value *, const Value *argv, int argc)
176{
177 if (!argc || !argv[0].isObject())
178 return f->engine()->throwTypeError();
179
180 const Object *o = static_cast<const Object *>(argv);
181 return Encode(o->isExtensible());
182}
183
184
185ReturnedValue Reflect::method_ownKeys(const FunctionObject *f, const Value *, const Value *argv, int argc)
186{
187 if (!argc || !argv[0].isObject())
188 return f->engine()->throwTypeError();
189
190 Scope scope(f);
191 if (!argc)
192 return scope.engine->throwTypeError();
193
194 ScopedObject O(scope, argv[0].toObject(scope.engine));
195 if (!O)
196 return Encode::undefined();
197
198 ScopedArrayObject keys(scope, scope.engine->newArrayObject());
199
200 ObjectIterator it(scope, O, ObjectIterator::WithSymbols);
201 ScopedPropertyKey key(scope);
202 ScopedValue v(scope);
203 while (1) {
204 key = it.next();
205 if (!key->isValid())
206 break;
207 v = key->toStringOrSymbol(scope.engine);
208 keys->push_back(v);
209 }
210
211 return keys->asReturnedValue();
212
213}
214
215ReturnedValue Reflect::method_preventExtensions(const FunctionObject *f, const Value *, const Value *argv, int argc)
216{
217 Scope scope(f);
218 if (!argc || !argv[0].isObject())
219 return scope.engine->throwTypeError();
220
221 ScopedObject o(scope, static_cast<const Object *>(argv));
222 return Encode(o->preventExtensions());
223}
224
225ReturnedValue Reflect::method_set(const FunctionObject *f, const Value *, const Value *argv, int argc)
226{
227 Scope scope(f);
228 if (!argc || !argv[0].isObject())
229 return scope.engine->throwTypeError();
230
231 ScopedObject o(scope, static_cast<const Object *>(argv));
232 Value undef = Value::undefinedValue();
233 const Value *index = argc > 1 ? &argv[1] : &undef;
234 const Value &val = argc > 2 ? argv[2] : undef;
235 ScopedValue receiver(scope, argc >3 ? argv[3] : argv[0]);
236
237 ScopedPropertyKey propertyKey(scope, index->toPropertyKey(scope.engine));
238 if (scope.hasException())
239 return false;
240 bool result = o->put(propertyKey, val, receiver);
241 return Encode(result);
242}
243
244ReturnedValue Reflect::method_setPrototypeOf(const FunctionObject *f, const Value *, const Value *argv, int argc)
245{
246 if (argc < 2 || !argv[0].isObject() || (!argv[1].isNull() && !argv[1].isObject()))
247 return f->engine()->throwTypeError();
248
249 Scope scope(f);
250 ScopedObject o(scope, static_cast<const Object *>(argv));
251 const Object *proto = argv[1].isNull() ? nullptr : static_cast<const Object *>(argv + 1);
252 return Encode(o->setPrototypeOf(proto));
253}
static CallArgs createListFromArrayLike(Scope &scope, const Object *o)
DEFINE_OBJECT_VTABLE(Reflect)
Value * argv