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 #ifndef QV4ERROROBJECT_H
40 #define QV4ERROROBJECT_H
41 
42 //
43 //  W A R N I N G
44 //  -------------
45 //
46 // This file is not part of the Qt API.  It exists purely as an
47 // implementation detail.  This header file may change from version to
48 // version without notice, or even be removed.
49 //
50 // We mean it.
51 //
52 
53 #include "qv4object_p.h"
54 #include "qv4functionobject_p.h"
55 #include "qv4string_p.h"
56 
57 QT_BEGIN_NAMESPACE
58 
59 namespace QV4 {
60 
61 struct SyntaxErrorObject;
62 
63 namespace Heap {
64 
65 
66 #define ErrorObjectMembers(class, Member) \
67     Member(class, Pointer, String *, stack)
68 
DECLARE_HEAP_OBJECT(ErrorObject,Object)69 DECLARE_HEAP_OBJECT(ErrorObject, Object) {
70     DECLARE_MARKOBJECTS(ErrorObject);
71     enum ErrorType {
72         Error,
73         EvalError,
74         RangeError,
75         ReferenceError,
76         SyntaxError,
77         TypeError,
78         URIError
79     };
80     StackTrace *stackTrace;
81     ErrorType errorType;
82 
83     void init();
84     void init(const Value &message, ErrorType t = Error);
85     void init(const Value &message, const QString &fileName, int line, int column, ErrorType t = Error);
86     void destroy() {
87         delete stackTrace;
88         Object::destroy();
89     }
90 };
91 
92 struct EvalErrorObject : ErrorObject {
93     void init(const Value &message);
94 };
95 
96 struct RangeErrorObject : ErrorObject {
97     void init(const Value &message);
98 };
99 
100 struct ReferenceErrorObject : ErrorObject {
101     void init(const Value &message);
102     void init(const Value &msg, const QString &fileName, int lineNumber, int columnNumber);
103 };
104 
105 struct SyntaxErrorObject : ErrorObject {
106     void init(const Value &message);
107     void init(const Value &msg, const QString &fileName, int lineNumber, int columnNumber);
108 };
109 
110 struct TypeErrorObject : ErrorObject {
111     void init(const Value &message);
112 };
113 
114 struct URIErrorObject : ErrorObject {
115     void init(const Value &message);
116 };
117 
118 struct ErrorCtor : FunctionObject {
119     void init(QV4::ExecutionContext *scope);
120     void init(QV4::ExecutionContext *scope, const QString &name);
121 };
122 
123 struct EvalErrorCtor : ErrorCtor {
124     void init(QV4::ExecutionContext *scope);
125 };
126 
127 struct RangeErrorCtor : ErrorCtor {
128     void init(QV4::ExecutionContext *scope);
129 };
130 
131 struct ReferenceErrorCtor : ErrorCtor {
132     void init(QV4::ExecutionContext *scope);
133 };
134 
135 struct SyntaxErrorCtor : ErrorCtor {
136     void init(QV4::ExecutionContext *scope);
137 };
138 
139 struct TypeErrorCtor : ErrorCtor {
140     void init(QV4::ExecutionContext *scope);
141 };
142 
143 struct URIErrorCtor : ErrorCtor {
144     void init(QV4::ExecutionContext *scope);
145 };
146 
147 }
148 
149 struct ErrorObject: Object {
150     enum {
151         IsErrorObject = true
152     };
153 
154     enum {
155         Index_Stack = 0, // Accessor Property
156         Index_StackSetter = 1, // Accessor Property
157         Index_FileName = 2,
158         Index_LineNumber = 3,
159         Index_Message = 4
160     };
161 
162     V4_OBJECT2(ErrorObject, Object)
163     Q_MANAGED_TYPE(ErrorObject)
164     V4_INTERNALCLASS(ErrorObject)
165     V4_PROTOTYPE(errorPrototype)
166     V4_NEEDS_DESTROY
167 
168     template <typename T>
169     static Heap::Object *create(ExecutionEngine *e, const Value &message, const Value *newTarget);
170     template <typename T>
171     static Heap::Object *create(ExecutionEngine *e, const QString &message);
172     template <typename T>
173     static Heap::Object *create(ExecutionEngine *e, const QString &message, const QString &filename, int line, int column);
174 
175     SyntaxErrorObject *asSyntaxError();
176 
177     static const char *className(Heap::ErrorObject::ErrorType t);
178 
179     static ReturnedValue method_get_stack(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
180 };
181 
182 template<>
as()183 inline const ErrorObject *Value::as() const {
184     return isManaged() && m()->internalClass->vtable->isErrorObject ? reinterpret_cast<const ErrorObject *>(this) : nullptr;
185 }
186 
187 struct EvalErrorObject: ErrorObject {
188     typedef Heap::EvalErrorObject Data;
V4_PROTOTYPEEvalErrorObject189     V4_PROTOTYPE(evalErrorPrototype)
190     const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
dEvalErrorObject191     Data *d() { return static_cast<Data *>(ErrorObject::d()); }
192 };
193 
194 struct RangeErrorObject: ErrorObject {
195     typedef Heap::RangeErrorObject Data;
V4_PROTOTYPERangeErrorObject196     V4_PROTOTYPE(rangeErrorPrototype)
197     const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
dRangeErrorObject198     Data *d() { return static_cast<Data *>(ErrorObject::d()); }
199 };
200 
201 struct ReferenceErrorObject: ErrorObject {
202     typedef Heap::ReferenceErrorObject Data;
V4_PROTOTYPEReferenceErrorObject203     V4_PROTOTYPE(referenceErrorPrototype)
204     const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
dReferenceErrorObject205     Data *d() { return static_cast<Data *>(ErrorObject::d()); }
206 };
207 
208 struct SyntaxErrorObject: ErrorObject {
209     typedef Heap::SyntaxErrorObject Data;
V4_PROTOTYPESyntaxErrorObject210     V4_PROTOTYPE(syntaxErrorPrototype)
211     const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
dSyntaxErrorObject212     Data *d() { return static_cast<Data *>(ErrorObject::d()); }
213 };
214 
215 struct TypeErrorObject: ErrorObject {
216     typedef Heap::TypeErrorObject Data;
V4_PROTOTYPETypeErrorObject217     V4_PROTOTYPE(typeErrorPrototype)
218     const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
dTypeErrorObject219     Data *d() { return static_cast<Data *>(ErrorObject::d()); }
220 };
221 
222 struct URIErrorObject: ErrorObject {
223     typedef Heap::URIErrorObject Data;
V4_PROTOTYPEURIErrorObject224     V4_PROTOTYPE(uRIErrorPrototype)
225     const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
dURIErrorObject226     Data *d() { return static_cast<Data *>(ErrorObject::d()); }
227 };
228 
229 struct ErrorCtor: FunctionObject
230 {
231     V4_OBJECT2(ErrorCtor, FunctionObject)
232 
233     static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
234     static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
235 };
236 
237 struct EvalErrorCtor: ErrorCtor
238 {
239     V4_OBJECT2(EvalErrorCtor, FunctionObject)
240     V4_PROTOTYPE(errorCtor)
241 
242     static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
243 };
244 
245 struct RangeErrorCtor: ErrorCtor
246 {
247     V4_OBJECT2(RangeErrorCtor, FunctionObject)
248     V4_PROTOTYPE(errorCtor)
249 
250     static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
251 };
252 
253 struct ReferenceErrorCtor: ErrorCtor
254 {
255     V4_OBJECT2(ReferenceErrorCtor, FunctionObject)
256     V4_PROTOTYPE(errorCtor)
257 
258     static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
259 };
260 
261 struct SyntaxErrorCtor: ErrorCtor
262 {
263     V4_OBJECT2(SyntaxErrorCtor, FunctionObject)
264     V4_PROTOTYPE(errorCtor)
265 
266     static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
267 };
268 
269 struct TypeErrorCtor: ErrorCtor
270 {
271     V4_OBJECT2(TypeErrorCtor, FunctionObject)
272     V4_PROTOTYPE(errorCtor)
273 
274     static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
275 };
276 
277 struct URIErrorCtor: ErrorCtor
278 {
279     V4_OBJECT2(URIErrorCtor, FunctionObject)
280     V4_PROTOTYPE(errorCtor)
281 
282     static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *);
283 };
284 
285 
286 struct ErrorPrototype : Object
287 {
288     enum {
289         Index_Constructor = 0,
290         Index_Message = 1,
291         Index_Name = 2
292     };
initErrorPrototype293     void init(ExecutionEngine *engine, Object *ctor) { init(engine, ctor, this, Heap::ErrorObject::Error); }
294 
295     static void init(ExecutionEngine *engine, Object *ctor, Object *obj, Heap::ErrorObject::ErrorType t);
296     static ReturnedValue method_toString(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
297 };
298 
299 struct EvalErrorPrototype : Object
300 {
initEvalErrorPrototype301     void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::EvalError); }
302 };
303 
304 struct RangeErrorPrototype : Object
305 {
initRangeErrorPrototype306     void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::RangeError); }
307 };
308 
309 struct ReferenceErrorPrototype : Object
310 {
initReferenceErrorPrototype311     void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::ReferenceError); }
312 };
313 
314 struct SyntaxErrorPrototype : Object
315 {
initSyntaxErrorPrototype316     void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::SyntaxError); }
317 };
318 
319 struct TypeErrorPrototype : Object
320 {
initTypeErrorPrototype321     void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::TypeError); }
322 };
323 
324 struct URIErrorPrototype : Object
325 {
initURIErrorPrototype326     void init(ExecutionEngine *engine, Object *ctor) { ErrorPrototype::init(engine, ctor, this, Heap::ErrorObject::URIError); }
327 };
328 
329 
asSyntaxError()330 inline SyntaxErrorObject *ErrorObject::asSyntaxError()
331 {
332     return d()->errorType == QV4::Heap::ErrorObject::SyntaxError ? static_cast<SyntaxErrorObject *>(this) : nullptr;
333 }
334 
335 
336 template <typename T>
create(ExecutionEngine * e,const Value & message,const Value * newTarget)337 Heap::Object *ErrorObject::create(ExecutionEngine *e, const Value &message, const Value *newTarget) {
338     EngineBase::InternalClassType klass = message.isUndefined() ? EngineBase::Class_ErrorObject : EngineBase::Class_ErrorObjectWithMessage;
339     Scope scope(e);
340     ScopedObject proto(scope, static_cast<const Object *>(newTarget)->get(scope.engine->id_prototype()));
341     Scoped<InternalClass> ic(scope, e->internalClasses(klass)->changePrototype(proto->d()));
342     return e->memoryManager->allocObject<T>(ic->d(), message);
343 }
344 template <typename T>
create(ExecutionEngine * e,const QString & message)345 Heap::Object *ErrorObject::create(ExecutionEngine *e, const QString &message) {
346     Scope scope(e);
347     ScopedValue v(scope, message.isEmpty() ? Encode::undefined() : e->newString(message)->asReturnedValue());
348     EngineBase::InternalClassType klass = v->isUndefined() ? EngineBase::Class_ErrorObject : EngineBase::Class_ErrorObjectWithMessage;
349     Scoped<InternalClass> ic(scope, e->internalClasses(klass)->changePrototype(T::defaultPrototype(e)->d()));
350     return e->memoryManager->allocObject<T>(ic->d(), v);
351 }
352 template <typename T>
create(ExecutionEngine * e,const QString & message,const QString & filename,int line,int column)353 Heap::Object *ErrorObject::create(ExecutionEngine *e, const QString &message, const QString &filename, int line, int column) {
354     Scope scope(e);
355     ScopedValue v(scope, message.isEmpty() ? Encode::undefined() : e->newString(message)->asReturnedValue());
356     EngineBase::InternalClassType klass = v->isUndefined() ? EngineBase::Class_ErrorObject : EngineBase::Class_ErrorObjectWithMessage;
357     Scoped<InternalClass> ic(scope, e->internalClasses(klass)->changePrototype(T::defaultPrototype(e)->d()));
358     return e->memoryManager->allocObject<T>(ic->d(), v, filename, line, column);
359 }
360 
361 
362 }
363 
364 QT_END_NAMESPACE
365 
366 #endif // QV4ECMAOBJECTS_P_H
367