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
41#include "qv4errorobject_p.h"
42#include <QtCore/qnumeric.h>
43#include <QtCore/qmath.h>
44#include <QtCore/QDateTime>
45#include <QtCore/QStringList>
46#include <QtCore/QDebug>
47
48#include "qv4string_p.h"
49#include <private/qv4mm_p.h>
50#include <private/qv4codegen_p.h>
51
52#ifndef Q_OS_WIN
53# include <time.h>
54# ifndef Q_OS_VXWORKS
55# include <sys/time.h>
56# else
57# include "qplatformdefs.h"
58# endif
59#else
60# include <windows.h>
61#endif
62
63using namespace QV4;
64
65void Heap::ErrorObject::init()
66{
67 Object::init();
68 stackTrace = nullptr;
69
70 Scope scope(internalClass->engine);
71 Scoped<QV4::ErrorObject> e(scope, this);
72
73 if (internalClass == scope.engine->internalClasses(icType: EngineBase::Class_ErrorProto))
74 return;
75
76 setProperty(e: scope.engine, index: QV4::ErrorObject::Index_Stack, b: scope.engine->getStackFunction()->d());
77 setProperty(e: scope.engine, index: QV4::ErrorObject::Index_StackSetter, v: Value::undefinedValue());
78 setProperty(e: scope.engine, index: QV4::ErrorObject::Index_FileName, v: Value::undefinedValue());
79 setProperty(e: scope.engine, index: QV4::ErrorObject::Index_LineNumber, v: Value::undefinedValue());
80}
81
82void Heap::ErrorObject::init(const Value &message, ErrorType t)
83{
84 Object::init();
85 errorType = t;
86
87 Scope scope(internalClass->engine);
88 Scoped<QV4::ErrorObject> e(scope, this);
89
90 setProperty(e: scope.engine, index: QV4::ErrorObject::Index_Stack, b: scope.engine->getStackFunction()->d());
91 setProperty(e: scope.engine, index: QV4::ErrorObject::Index_StackSetter, v: Value::undefinedValue());
92
93 e->d()->stackTrace = new StackTrace(scope.engine->stackTrace());
94 if (!e->d()->stackTrace->isEmpty()) {
95 setProperty(e: scope.engine, index: QV4::ErrorObject::Index_FileName, b: scope.engine->newString(s: e->d()->stackTrace->at(i: 0).source));
96 setProperty(e: scope.engine, index: QV4::ErrorObject::Index_LineNumber, v: Value::fromInt32(i: e->d()->stackTrace->at(i: 0).line));
97 }
98
99 if (!message.isUndefined())
100 setProperty(e: scope.engine, index: QV4::ErrorObject::Index_Message, v: message);
101}
102
103void Heap::ErrorObject::init(const Value &message, const QString &fileName, int line, int column, ErrorObject::ErrorType t)
104{
105 Q_UNUSED(fileName); // ####
106 Object::init();
107 errorType = t;
108
109 Scope scope(internalClass->engine);
110 Scoped<QV4::ErrorObject> e(scope, this);
111
112 setProperty(e: scope.engine, index: QV4::ErrorObject::Index_Stack, b: scope.engine->getStackFunction()->d());
113 setProperty(e: scope.engine, index: QV4::ErrorObject::Index_StackSetter, v: Value::undefinedValue());
114
115 e->d()->stackTrace = new StackTrace(scope.engine->stackTrace());
116 StackFrame frame;
117 frame.source = fileName;
118 frame.line = line;
119 frame.column = column;
120 e->d()->stackTrace->prepend(t: frame);
121
122 Q_ASSERT(!e->d()->stackTrace->isEmpty());
123 setProperty(e: scope.engine, index: QV4::ErrorObject::Index_FileName, b: scope.engine->newString(s: e->d()->stackTrace->at(i: 0).source));
124 setProperty(e: scope.engine, index: QV4::ErrorObject::Index_LineNumber, v: Value::fromInt32(i: e->d()->stackTrace->at(i: 0).line));
125
126 if (!message.isUndefined())
127 setProperty(e: scope.engine, index: QV4::ErrorObject::Index_Message, v: message);
128}
129
130const char *ErrorObject::className(Heap::ErrorObject::ErrorType t)
131{
132 switch (t) {
133 case Heap::ErrorObject::Error:
134 return "Error";
135 case Heap::ErrorObject::EvalError:
136 return "EvalError";
137 case Heap::ErrorObject::RangeError:
138 return "RangeError";
139 case Heap::ErrorObject::ReferenceError:
140 return "ReferenceError";
141 case Heap::ErrorObject::SyntaxError:
142 return "SyntaxError";
143 case Heap::ErrorObject::TypeError:
144 return "TypeError";
145 case Heap::ErrorObject::URIError:
146 return "URIError";
147 }
148 Q_UNREACHABLE();
149}
150
151ReturnedValue ErrorObject::method_get_stack(const FunctionObject *b, const Value *thisObject, const Value *, int)
152{
153 ExecutionEngine *v4 = b->engine();
154 const ErrorObject *This = thisObject->as<ErrorObject>();
155 if (!This)
156 return v4->throwTypeError();
157 if (!This->d()->stack) {
158 QString trace;
159 for (int i = 0; i < This->d()->stackTrace->count(); ++i) {
160 if (i > 0)
161 trace += QLatin1Char('\n');
162 const StackFrame &frame = This->d()->stackTrace->at(i);
163 trace += frame.function + QLatin1Char('@') + frame.source;
164 if (frame.line >= 0)
165 trace += QLatin1Char(':') + QString::number(frame.line);
166 }
167 This->d()->stack.set(e: v4, newVal: v4->newString(s: trace));
168 }
169 return This->d()->stack->asReturnedValue();
170}
171
172DEFINE_OBJECT_VTABLE(ErrorObject);
173
174void Heap::SyntaxErrorObject::init(const Value &msg)
175{
176 Heap::ErrorObject::init(message: msg, t: SyntaxError);
177}
178
179void Heap::SyntaxErrorObject::init(const Value &msg, const QString &fileName, int lineNumber, int columnNumber)
180{
181 Heap::ErrorObject::init(message: msg, fileName, line: lineNumber, column: columnNumber, t: SyntaxError);
182}
183
184void Heap::EvalErrorObject::init(const Value &message)
185{
186 Heap::ErrorObject::init(message, t: EvalError);
187}
188
189void Heap::RangeErrorObject::init(const Value &message)
190{
191 Heap::ErrorObject::init(message, t: RangeError);
192}
193
194void Heap::ReferenceErrorObject::init(const Value &message)
195{
196 Heap::ErrorObject::init(message, t: ReferenceError);
197}
198
199void Heap::ReferenceErrorObject::init(const Value &msg, const QString &fileName, int lineNumber, int columnNumber)
200{
201 Heap::ErrorObject::init(message: msg, fileName, line: lineNumber, column: columnNumber, t: ReferenceError);
202}
203
204void Heap::TypeErrorObject::init(const Value &message)
205{
206 Heap::ErrorObject::init(message, t: TypeError);
207}
208
209void Heap::URIErrorObject::init(const Value &message)
210{
211 Heap::ErrorObject::init(message, t: URIError);
212}
213
214DEFINE_OBJECT_VTABLE(ErrorCtor);
215DEFINE_OBJECT_VTABLE(EvalErrorCtor);
216DEFINE_OBJECT_VTABLE(RangeErrorCtor);
217DEFINE_OBJECT_VTABLE(ReferenceErrorCtor);
218DEFINE_OBJECT_VTABLE(SyntaxErrorCtor);
219DEFINE_OBJECT_VTABLE(TypeErrorCtor);
220DEFINE_OBJECT_VTABLE(URIErrorCtor);
221
222void Heap::ErrorCtor::init(QV4::ExecutionContext *scope)
223{
224 Heap::FunctionObject::init(scope, QStringLiteral("Error"));
225}
226
227void Heap::ErrorCtor::init(QV4::ExecutionContext *scope, const QString &name)
228{
229 Heap::FunctionObject::init(scope, name);
230}
231
232ReturnedValue ErrorCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
233{
234 Value v = argc ? *argv : Value::undefinedValue();
235 return ErrorObject::create<ErrorObject>(e: f->engine(), message: v, newTarget)->asReturnedValue();
236}
237
238ReturnedValue ErrorCtor::virtualCall(const FunctionObject *f, const Value *, const Value *argv, int argc)
239{
240 return f->callAsConstructor(argv, argc);
241}
242
243void Heap::EvalErrorCtor::init(QV4::ExecutionContext *scope)
244{
245 Heap::FunctionObject::init(scope, QStringLiteral("EvalError"));
246}
247
248ReturnedValue EvalErrorCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
249{
250 Value v = argc ? *argv : Value::undefinedValue();
251 return ErrorObject::create<EvalErrorObject>(e: f->engine(), message: v, newTarget)->asReturnedValue();
252}
253
254void Heap::RangeErrorCtor::init(QV4::ExecutionContext *scope)
255{
256 Heap::FunctionObject::init(scope, QStringLiteral("RangeError"));
257}
258
259ReturnedValue RangeErrorCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
260{
261 Value v = argc ? *argv : Value::undefinedValue();
262 return ErrorObject::create<RangeErrorObject>(e: f->engine(), message: v, newTarget)->asReturnedValue();
263}
264
265void Heap::ReferenceErrorCtor::init(QV4::ExecutionContext *scope)
266{
267 Heap::FunctionObject::init(scope, QStringLiteral("ReferenceError"));
268}
269
270ReturnedValue ReferenceErrorCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
271{
272 Value v = argc ? *argv : Value::undefinedValue();
273 return ErrorObject::create<ReferenceErrorObject>(e: f->engine(), message: v, newTarget)->asReturnedValue();
274}
275
276void Heap::SyntaxErrorCtor::init(QV4::ExecutionContext *scope)
277{
278 Heap::FunctionObject::init(scope, QStringLiteral("SyntaxError"));
279}
280
281ReturnedValue SyntaxErrorCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
282{
283 Value v = argc ? *argv : Value::undefinedValue();
284 return ErrorObject::create<SyntaxErrorObject>(e: f->engine(), message: v, newTarget)->asReturnedValue();
285}
286
287void Heap::TypeErrorCtor::init(QV4::ExecutionContext *scope)
288{
289 Heap::FunctionObject::init(scope, QStringLiteral("TypeError"));
290}
291
292ReturnedValue TypeErrorCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
293{
294 Value v = argc ? *argv : Value::undefinedValue();
295 return ErrorObject::create<TypeErrorObject>(e: f->engine(), message: v, newTarget)->asReturnedValue();
296}
297
298void Heap::URIErrorCtor::init(QV4::ExecutionContext *scope)
299{
300 Heap::FunctionObject::init(scope, QStringLiteral("URIError"));
301}
302
303ReturnedValue URIErrorCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
304{
305 Value v = argc ? *argv : Value::undefinedValue();
306 return ErrorObject::create<URIErrorObject>(e: f->engine(), message: v, newTarget)->asReturnedValue();
307}
308
309void ErrorPrototype::init(ExecutionEngine *engine, Object *ctor, Object *obj, Heap::ErrorObject::ErrorType t)
310{
311 Scope scope(engine);
312 ScopedString s(scope);
313 ScopedObject o(scope);
314 ctor->defineReadonlyProperty(name: engine->id_prototype(), value: (o = obj));
315 ctor->defineReadonlyConfigurableProperty(name: engine->id_length(), value: Value::fromInt32(i: 1));
316 obj->setProperty(index: Index_Constructor, b: ctor->d());
317 obj->setProperty(index: Index_Message, b: engine->id_empty()->d());
318 obj->setProperty(index: Index_Name, b: engine->newString(s: QString::fromLatin1(str: ErrorObject::className(t))));
319 obj->defineDefaultProperty(name: engine->id_toString(), code: method_toString, argumentCount: 0);
320}
321
322ReturnedValue ErrorPrototype::method_toString(const FunctionObject *b, const Value *thisObject, const Value *, int)
323{
324 ExecutionEngine *v4 = b->engine();
325 const Object *o = thisObject->as<Object>();
326 if (!o)
327 return v4->throwTypeError();
328
329 Scope scope(v4);
330 ScopedValue name(scope, o->get(name: scope.engine->id_name()));
331 QString qname;
332 if (name->isUndefined())
333 qname = QStringLiteral("Error");
334 else
335 qname = name->toQString();
336
337 ScopedString s(scope, scope.engine->newString(QStringLiteral("message")));
338 ScopedValue message(scope, o->get(name: s));
339 QString qmessage;
340 if (!message->isUndefined())
341 qmessage = message->toQString();
342
343 QString str;
344 if (qname.isEmpty()) {
345 str = qmessage;
346 } else if (qmessage.isEmpty()) {
347 str = qname;
348 } else {
349 str = qname + QLatin1String(": ") + qmessage;
350 }
351
352 return scope.engine->newString(s: str)->asReturnedValue();
353}
354

source code of qtdeclarative/src/qml/jsruntime/qv4errorobject.cpp