]>
Commit | Line | Data |
---|---|---|
f9bf01c6 A |
1 | /* |
2 | Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) | |
3 | ||
4 | This library is free software; you can redistribute it and/or | |
5 | modify it under the terms of the GNU Library General Public | |
6 | License as published by the Free Software Foundation; either | |
7 | version 2 of the License, or (at your option) any later version. | |
8 | ||
9 | This library is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | Library General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU Library General Public License | |
15 | along with this library; see the file COPYING.LIB. If not, write to | |
16 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
17 | Boston, MA 02110-1301, USA. | |
18 | */ | |
19 | ||
20 | #ifndef qscriptengine_p_h | |
21 | #define qscriptengine_p_h | |
22 | ||
23 | #include "qscriptconverter_p.h" | |
24 | #include "qscriptengine.h" | |
14957cd0 | 25 | #include "qscriptoriginalglobalobject_p.h" |
4e4e5a6f A |
26 | #include "qscriptstring_p.h" |
27 | #include "qscriptsyntaxcheckresult_p.h" | |
f9bf01c6 A |
28 | #include "qscriptvalue.h" |
29 | #include <JavaScriptCore/JavaScript.h> | |
14957cd0 | 30 | #include <JavaScriptCore/JSRetainPtr.h> |
4e4e5a6f | 31 | #include <JSBasePrivate.h> |
f9bf01c6 A |
32 | #include <QtCore/qshareddata.h> |
33 | #include <QtCore/qstring.h> | |
14957cd0 | 34 | #include <QtCore/qstringlist.h> |
f9bf01c6 A |
35 | |
36 | class QScriptEngine; | |
4e4e5a6f | 37 | class QScriptSyntaxCheckResultPrivate; |
f9bf01c6 A |
38 | |
39 | class QScriptEnginePrivate : public QSharedData { | |
40 | public: | |
4e4e5a6f | 41 | static QScriptEnginePrivate* get(const QScriptEngine* q) { Q_ASSERT(q); return q->d_ptr.data(); } |
f9bf01c6 A |
42 | static QScriptEngine* get(const QScriptEnginePrivate* d) { Q_ASSERT(d); return d->q_ptr; } |
43 | ||
44 | QScriptEnginePrivate(const QScriptEngine*); | |
45 | ~QScriptEnginePrivate(); | |
46 | ||
14957cd0 A |
47 | enum SetExceptionFlag { |
48 | IgnoreNullException = 0x01, | |
49 | NotNullException = 0x02, | |
50 | }; | |
51 | ||
4e4e5a6f | 52 | QScriptSyntaxCheckResultPrivate* checkSyntax(const QString& program); |
f9bf01c6 | 53 | QScriptValuePrivate* evaluate(const QString& program, const QString& fileName, int lineNumber); |
4e4e5a6f A |
54 | QScriptValuePrivate* evaluate(const QScriptProgramPrivate* program); |
55 | inline JSValueRef evaluate(JSStringRef program, JSStringRef fileName, int lineNumber); | |
56 | ||
14957cd0 A |
57 | inline bool hasUncaughtException() const; |
58 | QScriptValuePrivate* uncaughtException() const; | |
59 | inline void clearExceptions(); | |
60 | inline void setException(JSValueRef exception, const /* SetExceptionFlags */ unsigned flags = IgnoreNullException); | |
61 | inline int uncaughtExceptionLineNumber() const; | |
62 | inline QStringList uncaughtExceptionBacktrace() const; | |
63 | ||
f9bf01c6 | 64 | inline void collectGarbage(); |
4e4e5a6f | 65 | inline void reportAdditionalMemoryCost(int cost); |
f9bf01c6 A |
66 | |
67 | inline JSValueRef makeJSValue(double number) const; | |
68 | inline JSValueRef makeJSValue(int number) const; | |
69 | inline JSValueRef makeJSValue(uint number) const; | |
70 | inline JSValueRef makeJSValue(const QString& string) const; | |
71 | inline JSValueRef makeJSValue(bool number) const; | |
72 | inline JSValueRef makeJSValue(QScriptValue::SpecialValue value) const; | |
73 | ||
14957cd0 A |
74 | QScriptValuePrivate* newFunction(QScriptEngine::FunctionSignature fun, QScriptValuePrivate* prototype, int length); |
75 | QScriptValuePrivate* newFunction(QScriptEngine::FunctionWithArgSignature fun, void* arg); | |
76 | QScriptValuePrivate* newFunction(JSObjectRef funObject, QScriptValuePrivate* prototype); | |
77 | ||
78 | QScriptValuePrivate* newObject() const; | |
79 | QScriptValuePrivate* newArray(uint length); | |
80 | QScriptValuePrivate* newDate(qsreal value); | |
4e4e5a6f A |
81 | QScriptValuePrivate* globalObject() const; |
82 | ||
83 | inline QScriptStringPrivate* toStringHandle(const QString& str) const; | |
84 | ||
14957cd0 A |
85 | inline operator JSGlobalContextRef() const; |
86 | ||
87 | inline bool isDate(JSValueRef value) const; | |
88 | inline bool isArray(JSValueRef value) const; | |
89 | inline bool isError(JSValueRef value) const; | |
90 | inline bool objectHasOwnProperty(JSObjectRef object, JSStringRef property) const; | |
91 | inline QVector<JSStringRef> objectGetOwnPropertyNames(JSObjectRef object) const; | |
92 | ||
f9bf01c6 A |
93 | private: |
94 | QScriptEngine* q_ptr; | |
95 | JSGlobalContextRef m_context; | |
14957cd0 A |
96 | JSValueRef m_exception; |
97 | ||
98 | QScriptOriginalGlobalObject m_originalGlobalObject; | |
99 | ||
100 | JSClassRef m_nativeFunctionClass; | |
101 | JSClassRef m_nativeFunctionWithArgClass; | |
f9bf01c6 A |
102 | }; |
103 | ||
4e4e5a6f A |
104 | |
105 | /*! | |
106 | Evaluates given JavaScript program and returns result of the evaluation. | |
107 | \attention this function doesn't take ownership of the parameters. | |
108 | \internal | |
109 | */ | |
110 | JSValueRef QScriptEnginePrivate::evaluate(JSStringRef program, JSStringRef fileName, int lineNumber) | |
111 | { | |
112 | JSValueRef exception; | |
113 | JSValueRef result = JSEvaluateScript(m_context, program, /* Global Object */ 0, fileName, lineNumber, &exception); | |
14957cd0 A |
114 | if (!result) { |
115 | setException(exception, NotNullException); | |
4e4e5a6f | 116 | return exception; // returns an exception |
14957cd0 A |
117 | } |
118 | clearExceptions(); | |
4e4e5a6f A |
119 | return result; |
120 | } | |
121 | ||
14957cd0 A |
122 | bool QScriptEnginePrivate::hasUncaughtException() const |
123 | { | |
124 | return m_exception; | |
125 | } | |
126 | ||
127 | void QScriptEnginePrivate::clearExceptions() | |
128 | { | |
129 | if (m_exception) | |
130 | JSValueUnprotect(m_context, m_exception); | |
131 | m_exception = 0; | |
132 | } | |
133 | ||
134 | void QScriptEnginePrivate::setException(JSValueRef exception, const /* SetExceptionFlags */ unsigned flags) | |
135 | { | |
136 | if (!((flags & NotNullException) || exception)) | |
137 | return; | |
138 | Q_ASSERT(exception); | |
139 | ||
140 | if (m_exception) | |
141 | JSValueUnprotect(m_context, m_exception); | |
142 | JSValueProtect(m_context, exception); | |
143 | m_exception = exception; | |
144 | } | |
145 | ||
146 | int QScriptEnginePrivate::uncaughtExceptionLineNumber() const | |
147 | { | |
148 | if (!hasUncaughtException() || !JSValueIsObject(m_context, m_exception)) | |
149 | return -1; | |
150 | ||
151 | JSValueRef exception = 0; | |
152 | JSRetainPtr<JSStringRef> lineNumberPropertyName(Adopt, QScriptConverter::toString("line")); | |
153 | JSValueRef lineNumber = JSObjectGetProperty(m_context, const_cast<JSObjectRef>(m_exception), lineNumberPropertyName.get(), &exception); | |
154 | int result = JSValueToNumber(m_context, lineNumber, &exception); | |
155 | return exception ? -1 : result; | |
156 | } | |
157 | ||
158 | QStringList QScriptEnginePrivate::uncaughtExceptionBacktrace() const | |
159 | { | |
160 | if (!hasUncaughtException() || !JSValueIsObject(m_context, m_exception)) | |
161 | return QStringList(); | |
162 | ||
163 | JSValueRef exception = 0; | |
164 | JSRetainPtr<JSStringRef> fileNamePropertyName(Adopt, QScriptConverter::toString("sourceURL")); | |
165 | JSRetainPtr<JSStringRef> lineNumberPropertyName(Adopt, QScriptConverter::toString("line")); | |
166 | JSValueRef jsFileName = JSObjectGetProperty(m_context, const_cast<JSObjectRef>(m_exception), fileNamePropertyName.get(), &exception); | |
167 | JSValueRef jsLineNumber = JSObjectGetProperty(m_context, const_cast<JSObjectRef>(m_exception), lineNumberPropertyName.get(), &exception); | |
168 | JSRetainPtr<JSStringRef> fileName(Adopt, JSValueToStringCopy(m_context, jsFileName, &exception)); | |
169 | int lineNumber = JSValueToNumber(m_context, jsLineNumber, &exception); | |
170 | return QStringList(QString::fromLatin1("<anonymous>()@%0:%1") | |
171 | .arg(QScriptConverter::toString(fileName.get())) | |
172 | .arg(QScriptConverter::toString(exception ? -1 : lineNumber))); | |
173 | } | |
174 | ||
f9bf01c6 A |
175 | void QScriptEnginePrivate::collectGarbage() |
176 | { | |
177 | JSGarbageCollect(m_context); | |
178 | } | |
179 | ||
4e4e5a6f A |
180 | void QScriptEnginePrivate::reportAdditionalMemoryCost(int cost) |
181 | { | |
182 | if (cost > 0) | |
183 | JSReportExtraMemoryCost(m_context, cost); | |
184 | } | |
185 | ||
f9bf01c6 A |
186 | JSValueRef QScriptEnginePrivate::makeJSValue(double number) const |
187 | { | |
188 | return JSValueMakeNumber(m_context, number); | |
189 | } | |
190 | ||
191 | JSValueRef QScriptEnginePrivate::makeJSValue(int number) const | |
192 | { | |
193 | return JSValueMakeNumber(m_context, number); | |
194 | } | |
195 | ||
196 | JSValueRef QScriptEnginePrivate::makeJSValue(uint number) const | |
197 | { | |
198 | return JSValueMakeNumber(m_context, number); | |
199 | } | |
200 | ||
201 | JSValueRef QScriptEnginePrivate::makeJSValue(const QString& string) const | |
202 | { | |
4e4e5a6f A |
203 | JSStringRef tmp = QScriptConverter::toString(string); |
204 | JSValueRef result = JSValueMakeString(m_context, tmp); | |
205 | JSStringRelease(tmp); | |
206 | return result; | |
f9bf01c6 A |
207 | } |
208 | ||
209 | JSValueRef QScriptEnginePrivate::makeJSValue(bool value) const | |
210 | { | |
211 | return JSValueMakeBoolean(m_context, value); | |
212 | } | |
213 | ||
214 | JSValueRef QScriptEnginePrivate::makeJSValue(QScriptValue::SpecialValue value) const | |
215 | { | |
216 | if (value == QScriptValue::NullValue) | |
217 | return JSValueMakeNull(m_context); | |
218 | return JSValueMakeUndefined(m_context); | |
219 | } | |
220 | ||
4e4e5a6f A |
221 | QScriptStringPrivate* QScriptEnginePrivate::toStringHandle(const QString& str) const |
222 | { | |
223 | return new QScriptStringPrivate(str); | |
224 | } | |
225 | ||
14957cd0 | 226 | QScriptEnginePrivate::operator JSGlobalContextRef() const |
f9bf01c6 | 227 | { |
14957cd0 | 228 | Q_ASSERT(this); |
f9bf01c6 A |
229 | return m_context; |
230 | } | |
231 | ||
14957cd0 A |
232 | bool QScriptEnginePrivate::isDate(JSValueRef value) const |
233 | { | |
234 | return m_originalGlobalObject.isDate(value); | |
235 | } | |
236 | ||
237 | bool QScriptEnginePrivate::isArray(JSValueRef value) const | |
238 | { | |
239 | return m_originalGlobalObject.isArray(value); | |
240 | } | |
241 | ||
242 | bool QScriptEnginePrivate::isError(JSValueRef value) const | |
243 | { | |
244 | return m_originalGlobalObject.isError(value); | |
245 | } | |
246 | ||
247 | inline bool QScriptEnginePrivate::objectHasOwnProperty(JSObjectRef object, JSStringRef property) const | |
248 | { | |
249 | // FIXME We need a JSC C API function for this. | |
250 | return m_originalGlobalObject.objectHasOwnProperty(object, property); | |
251 | } | |
252 | ||
253 | inline QVector<JSStringRef> QScriptEnginePrivate::objectGetOwnPropertyNames(JSObjectRef object) const | |
254 | { | |
255 | // FIXME We can't use C API function JSObjectGetPropertyNames as it returns only enumerable properties. | |
256 | return m_originalGlobalObject.objectGetOwnPropertyNames(object); | |
257 | } | |
258 | ||
f9bf01c6 | 259 | #endif |