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

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