1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2015 The Qt Company Ltd. |
4 | ** Contact: http://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtScript 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 | #ifndef QSCRIPTENGINE_P_H |
41 | #define QSCRIPTENGINE_P_H |
42 | |
43 | // |
44 | // W A R N I N G |
45 | // ------------- |
46 | // |
47 | // This file is not part of the Qt API. It exists purely as an |
48 | // implementation detail. This header file may change from version to |
49 | // version without notice, or even be removed. |
50 | // |
51 | // We mean it. |
52 | // |
53 | |
54 | #include "private/qobject_p.h" |
55 | |
56 | #include <QtCore/qdatetime.h> |
57 | #include <QtCore/qhash.h> |
58 | #include <QtCore/qnumeric.h> |
59 | #include <QtCore/qregexp.h> |
60 | #include <QtCore/qset.h> |
61 | #include <QtCore/qstringlist.h> |
62 | #include "qscriptvalue_p.h" |
63 | #include "qscriptstring_p.h" |
64 | #include "bridge/qscriptclassobject_p.h" |
65 | #include "bridge/qscriptdeclarativeclass_p.h" |
66 | #include "bridge/qscriptdeclarativeobject_p.h" |
67 | #include "bridge/qscriptobject_p.h" |
68 | #include "bridge/qscriptqobject_p.h" |
69 | #include "bridge/qscriptvariant_p.h" |
70 | #include "bridge/qscriptactivationobject_p.h" |
71 | |
72 | #include "DateConstructor.h" |
73 | #include "DateInstance.h" |
74 | #include "Debugger.h" |
75 | #include "ErrorInstance.h" |
76 | #include "JSArray.h" |
77 | #include "Executable.h" |
78 | #include "Lexer.h" |
79 | #include "RefPtr.h" |
80 | #include "RegExpConstructor.h" |
81 | #include "RegExpObject.h" |
82 | #include "SourceProvider.h" |
83 | #include "Structure.h" |
84 | #include "UString.h" |
85 | #include "JSGlobalObject.h" |
86 | #include "JSValue.h" |
87 | |
88 | #include <stdlib.h> |
89 | |
90 | namespace JSC |
91 | { |
92 | class EvalExecutable; |
93 | class ExecState; |
94 | typedef ExecState CallFrame; |
95 | class JSCell; |
96 | class JSGlobalObject; |
97 | } |
98 | |
99 | |
100 | QT_BEGIN_NAMESPACE |
101 | |
102 | class QString; |
103 | class QStringList; |
104 | class QScriptContext; |
105 | class QScriptValue; |
106 | class QScriptTypeInfo; |
107 | class QScriptEngineAgent; |
108 | class QScriptEnginePrivate; |
109 | class QScriptSyntaxCheckResult; |
110 | class QScriptEngine; |
111 | class QScriptProgramPrivate; |
112 | |
113 | namespace QScript |
114 | { |
115 | class QObjectPrototype; |
116 | class QMetaObjectPrototype; |
117 | class QVariantPrototype; |
118 | #ifndef QT_NO_QOBJECT |
119 | class QObjectData; |
120 | #endif |
121 | class TimeoutCheckerProxy; |
122 | |
123 | qint32 ToInt32(qsreal); |
124 | quint32 ToUInt32(qsreal); |
125 | quint16 ToUInt16(qsreal); |
126 | qsreal ToInteger(qsreal); |
127 | |
128 | inline bool ToBool(qsreal); |
129 | inline bool ToBool(const QString &); |
130 | inline qint32 ToInt32(const QString &); |
131 | inline quint32 ToUInt32(const QString &); |
132 | inline quint16 ToUInt16(const QString &); |
133 | inline qsreal ToInteger(const QString &); |
134 | #ifdef Q_CC_MSVC |
135 | // MSVC2008 crashes if these are inlined. |
136 | qsreal ToNumber(const QString &); |
137 | QString ToString(qsreal); |
138 | #else |
139 | inline qsreal ToNumber(const QString &); |
140 | inline QString ToString(qsreal); |
141 | #endif |
142 | |
143 | QDateTime MsToDateTime(JSC::ExecState *, qsreal); |
144 | qsreal DateTimeToMs(JSC::ExecState *, const QDateTime &); |
145 | |
146 | //some conversion helper functions |
147 | inline QScriptEnginePrivate *scriptEngineFromExec(const JSC::ExecState *exec); |
148 | bool isFunction(JSC::JSValue value); |
149 | |
150 | inline void convertToLatin1_helper(const UChar *i, int length, char *s); |
151 | inline QByteArray convertToLatin1(const JSC::UString &str); |
152 | |
153 | class UStringSourceProviderWithFeedback; |
154 | |
155 | struct GlobalClientData : public JSC::JSGlobalData::ClientData |
156 | { |
157 | GlobalClientData(QScriptEnginePrivate *e) |
158 | : engine(e) {} |
159 | virtual ~GlobalClientData() {} |
160 | virtual void mark(JSC::MarkStack& markStack); |
161 | virtual void uncaughtException(JSC::ExecState*, unsigned bytecodeOffset, |
162 | JSC::JSValue); |
163 | |
164 | QScriptEnginePrivate *engine; |
165 | }; |
166 | |
167 | } // namespace QScript |
168 | |
169 | class QScriptEnginePrivate |
170 | #ifndef QT_NO_QOBJECT |
171 | : public QObjectPrivate |
172 | #endif |
173 | { |
174 | Q_DECLARE_PUBLIC(QScriptEngine) |
175 | public: |
176 | QScriptEnginePrivate(); |
177 | virtual ~QScriptEnginePrivate(); |
178 | |
179 | static QScriptEnginePrivate *get(QScriptEngine *q) { return q ? q->d_func() : 0; } |
180 | static QScriptEngine *get(QScriptEnginePrivate *d) { return d ? d->q_func() : 0; } |
181 | |
182 | static inline bool isArray(JSC::JSValue); |
183 | static inline bool isDate(JSC::JSValue); |
184 | static inline bool isError(JSC::JSValue); |
185 | static inline bool isObject(JSC::JSValue); |
186 | static inline bool isRegExp(JSC::JSValue); |
187 | static inline bool isVariant(JSC::JSValue); |
188 | static inline bool isQObject(JSC::JSValue); |
189 | static inline bool isQMetaObject(JSC::JSValue); |
190 | |
191 | static inline bool toBool(JSC::ExecState *, JSC::JSValue); |
192 | static inline qsreal toInteger(JSC::ExecState *, JSC::JSValue); |
193 | static inline qsreal toNumber(JSC::ExecState *, JSC::JSValue); |
194 | static inline qint32 toInt32(JSC::ExecState *, JSC::JSValue); |
195 | static inline quint32 toUInt32(JSC::ExecState *, JSC::JSValue); |
196 | static inline quint16 toUInt16(JSC::ExecState *, JSC::JSValue); |
197 | static inline JSC::UString toString(JSC::ExecState *, JSC::JSValue); |
198 | |
199 | static inline QDateTime toDateTime(JSC::ExecState *, JSC::JSValue); |
200 | #ifndef QT_NO_REGEXP |
201 | static QRegExp toRegExp(JSC::ExecState*, JSC::JSValue); |
202 | #endif |
203 | static QVariant toVariant(JSC::ExecState *, JSC::JSValue); |
204 | static inline QObject *toQObject(JSC::ExecState *, JSC::JSValue); |
205 | static inline const QMetaObject *toQMetaObject(JSC::ExecState *, JSC::JSValue); |
206 | |
207 | static inline JSC::JSValue property(JSC::ExecState*, JSC::JSValue, const JSC::Identifier &id, |
208 | int resolveMode = QScriptValue::ResolvePrototype); |
209 | static JSC::JSValue propertyHelper(JSC::ExecState*, JSC::JSValue, const JSC::Identifier &id, int resolveMode); |
210 | static inline JSC::JSValue property(JSC::ExecState*, JSC::JSValue, quint32 index, |
211 | int resolveMode = QScriptValue::ResolvePrototype); |
212 | static JSC::JSValue propertyHelper(JSC::ExecState*, JSC::JSValue, quint32, int resolveMode); |
213 | static inline JSC::JSValue property(JSC::ExecState*, JSC::JSValue, const JSC::UString &, int resolveMode); |
214 | static inline void setProperty(JSC::ExecState*, JSC::JSValue object, const JSC::UString &name, JSC::JSValue, |
215 | const QScriptValue::PropertyFlags &flags = QScriptValue::KeepExistingFlags); |
216 | static void setProperty(JSC::ExecState*, JSC::JSValue object, const JSC::Identifier &id, JSC::JSValue, |
217 | const QScriptValue::PropertyFlags &flags = QScriptValue::KeepExistingFlags); |
218 | static void setProperty(JSC::ExecState*, JSC::JSValue object, quint32 index, JSC::JSValue, |
219 | const QScriptValue::PropertyFlags &flags = QScriptValue::KeepExistingFlags); |
220 | static QScriptValue::PropertyFlags propertyFlags(JSC::ExecState*, JSC::JSValue value, |
221 | const JSC::Identifier &id, const QScriptValue::ResolveFlags &mode); |
222 | static inline QScriptValue::PropertyFlags propertyFlags(JSC::ExecState*, JSC::JSValue value, |
223 | const JSC::UString &name, const QScriptValue::ResolveFlags &mode); |
224 | |
225 | static bool convertValue(JSC::ExecState*, JSC::JSValue value, |
226 | int type, void *ptr); |
227 | static bool convertNumber(qsreal, int type, void *ptr); |
228 | static bool convertString(const QString &, int type, void *ptr); |
229 | static JSC::JSValue create(JSC::ExecState*, int type, const void *ptr); |
230 | bool hasDemarshalFunction(int type) const; |
231 | |
232 | inline QScriptValue scriptValueFromJSCValue(JSC::JSValue value); |
233 | inline JSC::JSValue scriptValueToJSCValue(const QScriptValue &value); |
234 | static inline unsigned propertyFlagsToJSCAttributes(const QScriptValue::PropertyFlags &flags); |
235 | |
236 | static inline JSC::JSValue jscValueFromVariant(JSC::ExecState*, const QVariant &value); |
237 | static QVariant jscValueToVariant(JSC::ExecState*, JSC::JSValue value, int targetType); |
238 | static inline QVariant &variantValue(JSC::JSValue value); |
239 | static inline void setVariantValue(JSC::JSValue objectValue, const QVariant &value); |
240 | |
241 | static JSC::JSValue arrayFromStringList(JSC::ExecState*, const QStringList &lst); |
242 | static QStringList stringListFromArray(JSC::ExecState*, JSC::JSValue arr); |
243 | |
244 | static JSC::JSValue arrayFromVariantList(JSC::ExecState*, const QVariantList &lst); |
245 | static QVariantList variantListFromArray(JSC::ExecState*, JSC::JSArray *arr); |
246 | |
247 | static JSC::JSValue objectFromVariantMap(JSC::ExecState*, const QVariantMap &vmap); |
248 | static QVariantMap variantMapFromObject(JSC::ExecState*, JSC::JSObject *obj); |
249 | |
250 | JSC::JSValue defaultPrototype(int metaTypeId) const; |
251 | void setDefaultPrototype(int metaTypeId, JSC::JSValue prototype); |
252 | |
253 | static inline QScriptContext *contextForFrame(JSC::ExecState *frame); |
254 | static inline JSC::ExecState *frameForContext(QScriptContext *context); |
255 | static inline const JSC::ExecState *frameForContext(const QScriptContext *context); |
256 | |
257 | static inline bool hasValidCodeBlockRegister(JSC::ExecState *frame); |
258 | |
259 | JSC::JSGlobalObject *originalGlobalObject() const; |
260 | JSC::JSObject *getOriginalGlobalObjectProxy(); |
261 | JSC::JSObject *customGlobalObject() const; |
262 | JSC::JSObject *globalObject() const; |
263 | void setGlobalObject(JSC::JSObject *object); |
264 | inline JSC::ExecState *globalExec() const; |
265 | JSC::JSValue toUsableValue(JSC::JSValue value); |
266 | static JSC::JSValue thisForContext(JSC::ExecState *frame); |
267 | static JSC::Register *thisRegisterForFrame(JSC::ExecState *frame); |
268 | |
269 | JSC::CallFrame *pushContext(JSC::CallFrame *exec, JSC::JSValue thisObject, const JSC::ArgList& args, |
270 | JSC::JSObject *callee, bool calledAsConstructor = false); |
271 | void popContext(); |
272 | |
273 | void mark(JSC::MarkStack& markStack); |
274 | bool isCollecting() const; |
275 | void collectGarbage(); |
276 | void reportAdditionalMemoryCost(int size); |
277 | |
278 | //flags that we set on the return value register for native function. (ie when codeBlock is 0) |
279 | enum ContextFlags { |
280 | NativeContext = 1, |
281 | CalledAsConstructorContext = 2, |
282 | HasScopeContext = 4, // Specifies that the is a QScriptActivationObject |
283 | ShouldRestoreCallFrame = 8 |
284 | }; |
285 | static uint contextFlags(JSC::ExecState *); |
286 | static void setContextFlags(JSC::ExecState *, uint); |
287 | |
288 | QScript::TimeoutCheckerProxy *timeoutChecker() const; |
289 | |
290 | void agentDeleted(QScriptEngineAgent *agent); |
291 | |
292 | static bool isLikelyStackOverflowError(JSC::ExecState *, JSC::JSValue); |
293 | void uncaughtException(JSC::ExecState *, unsigned bytecodeOffset, JSC::JSValue); |
294 | |
295 | static inline void saveException(JSC::ExecState *, JSC::JSValue *); |
296 | static inline void restoreException(JSC::ExecState *, JSC::JSValue); |
297 | |
298 | void setCurrentException(QScriptValue exception) { m_currentException = exception; } |
299 | QScriptValue currentException() const { return m_currentException; } |
300 | void clearCurrentException() |
301 | { |
302 | m_currentException.d_ptr.reset(); |
303 | uncaughtExceptionBacktrace.clear(); |
304 | uncaughtExceptionLineNumber = -1; |
305 | } |
306 | |
307 | static QScriptSyntaxCheckResult checkSyntax(const QString &program); |
308 | static bool canEvaluate(const QString &program); |
309 | |
310 | inline void registerScriptProgram(QScriptProgramPrivate *program); |
311 | inline void unregisterScriptProgram(QScriptProgramPrivate *program); |
312 | void detachAllRegisteredScriptPrograms(); |
313 | |
314 | inline QScriptValuePrivate *allocateScriptValuePrivate(size_t); |
315 | inline void freeScriptValuePrivate(QScriptValuePrivate *p); |
316 | |
317 | inline void registerScriptValue(QScriptValuePrivate *value); |
318 | inline void unregisterScriptValue(QScriptValuePrivate *value); |
319 | void detachAllRegisteredScriptValues(); |
320 | |
321 | inline void registerScriptString(QScriptStringPrivate *value); |
322 | inline void unregisterScriptString(QScriptStringPrivate *value); |
323 | void detachAllRegisteredScriptStrings(); |
324 | QScriptString toStringHandle(const JSC::Identifier &name); |
325 | |
326 | static inline JSC::JSValue newArray(JSC::ExecState *, uint length); |
327 | static inline JSC::JSValue newDate(JSC::ExecState *, qsreal value); |
328 | static inline JSC::JSValue newDate(JSC::ExecState *, const QDateTime &); |
329 | inline JSC::JSValue newObject(); |
330 | |
331 | #ifndef QT_NO_REGEXP |
332 | static JSC::JSValue newRegExp(JSC::ExecState *, const QRegExp &); |
333 | #endif |
334 | |
335 | static JSC::JSValue newRegExp(JSC::ExecState *, const QString &pattern, const QString &flags); |
336 | JSC::JSValue newVariant(const QVariant &); |
337 | JSC::JSValue newVariant(JSC::JSValue objectValue, const QVariant &); |
338 | |
339 | static inline QScriptDeclarativeClass *declarativeClass(JSC::JSValue); |
340 | static inline QScriptDeclarativeClass::Object *declarativeObject(JSC::JSValue); |
341 | |
342 | JSC::UString translationContextFromUrl(const JSC::UString &); |
343 | |
344 | #ifndef QT_NO_QOBJECT |
345 | void markQObjectData(JSC::MarkStack&); |
346 | JSC::JSValue newQObject(QObject *object, |
347 | QScriptEngine::ValueOwnership ownership = QScriptEngine::QtOwnership, |
348 | const QScriptEngine:: QObjectWrapOptions &options = {}); |
349 | JSC::JSValue newQMetaObject(const QMetaObject *metaObject, |
350 | JSC::JSValue ctor); |
351 | |
352 | static bool convertToNativeQObject(JSC::ExecState*, JSC::JSValue, |
353 | const QByteArray &targetType, |
354 | void **result); |
355 | |
356 | JSC::JSValue evaluateHelper(JSC::ExecState *exec, intptr_t sourceId, |
357 | JSC::EvalExecutable *executable, |
358 | bool &compile); |
359 | |
360 | QScript::QObjectData *qobjectData(QObject *object); |
361 | void disposeQObject(QObject *object); |
362 | void emitSignalHandlerException(); |
363 | |
364 | bool scriptConnect(QObject *sender, const char *signal, |
365 | JSC::JSValue receiver, JSC::JSValue function, |
366 | Qt::ConnectionType type); |
367 | bool scriptDisconnect(QObject *sender, const char *signal, |
368 | JSC::JSValue receiver, JSC::JSValue function); |
369 | |
370 | bool scriptConnect(QObject *sender, int index, |
371 | JSC::JSValue receiver, JSC::JSValue function, |
372 | JSC::JSValue senderWrapper, |
373 | Qt::ConnectionType type); |
374 | bool scriptDisconnect(QObject *sender, int index, |
375 | JSC::JSValue receiver, JSC::JSValue function); |
376 | |
377 | bool scriptConnect(JSC::JSValue signal, JSC::JSValue receiver, |
378 | JSC::JSValue function, Qt::ConnectionType type); |
379 | bool scriptDisconnect(JSC::JSValue signal, JSC::JSValue receiver, |
380 | JSC::JSValue function); |
381 | |
382 | // private slots |
383 | void _q_objectDestroyed(QObject *); |
384 | #endif |
385 | |
386 | JSC::JSGlobalData *globalData; |
387 | JSC::JSObject *originalGlobalObjectProxy; |
388 | JSC::ExecState *currentFrame; |
389 | |
390 | WTF::RefPtr<JSC::Structure> scriptObjectStructure; |
391 | WTF::RefPtr<JSC::Structure> staticScopeObjectStructure; |
392 | |
393 | QScript::QObjectPrototype *qobjectPrototype; |
394 | WTF::RefPtr<JSC::Structure> qobjectWrapperObjectStructure; |
395 | |
396 | QScript::QMetaObjectPrototype *qmetaobjectPrototype; |
397 | WTF::RefPtr<JSC::Structure> qmetaobjectWrapperObjectStructure; |
398 | |
399 | QScript::QVariantPrototype *variantPrototype; |
400 | WTF::RefPtr<JSC::Structure> variantWrapperObjectStructure; |
401 | |
402 | QList<QScriptEngineAgent*> ownedAgents; |
403 | QScriptEngineAgent *activeAgent; |
404 | int agentLineNumber; |
405 | QScriptValuePrivate *registeredScriptValues; |
406 | QScriptValuePrivate *freeScriptValues; |
407 | static const int maxFreeScriptValues = 256; |
408 | int freeScriptValuesCount; |
409 | QScriptStringPrivate *registeredScriptStrings; |
410 | QSet<QScriptProgramPrivate*> registeredScriptPrograms; |
411 | QHash<int, QScriptTypeInfo*> m_typeInfos; |
412 | int processEventsInterval; |
413 | QScriptValue abortResult; |
414 | bool inEval; |
415 | |
416 | JSC::UString cachedTranslationUrl; |
417 | JSC::UString cachedTranslationContext; |
418 | |
419 | QSet<QString> importedExtensions; |
420 | QSet<QString> extensionsBeingImported; |
421 | |
422 | QHash<intptr_t, QScript::UStringSourceProviderWithFeedback*> loadedScripts; |
423 | QScriptValue m_currentException; |
424 | QStringList uncaughtExceptionBacktrace; |
425 | int uncaughtExceptionLineNumber; |
426 | |
427 | QSet<JSC::JSObject*> visitedConversionObjects; |
428 | |
429 | #ifndef QT_NO_QOBJECT |
430 | QHash<QObject*, QScript::QObjectData*> m_qobjectData; |
431 | #endif |
432 | |
433 | #ifdef QT_NO_QOBJECT |
434 | QScriptEngine *q_ptr; |
435 | #endif |
436 | }; |
437 | |
438 | namespace QScript |
439 | { |
440 | |
441 | class APIShim |
442 | { |
443 | public: |
444 | APIShim(QScriptEnginePrivate *engine) |
445 | : m_engine(engine), m_oldTable(JSC::setCurrentIdentifierTable(engine->globalData->identifierTable)) |
446 | { |
447 | } |
448 | ~APIShim() |
449 | { |
450 | JSC::setCurrentIdentifierTable(m_oldTable); |
451 | } |
452 | |
453 | private: |
454 | QScriptEnginePrivate *m_engine; |
455 | JSC::IdentifierTable *m_oldTable; |
456 | }; |
457 | |
458 | /*Helper class. Main purpose is to give debugger feedback about unloading and loading scripts. |
459 | It keeps pointer to JSGlobalObject assuming that it is always the same - there is no way to update |
460 | this data. Class is internal and used as an implementation detail in and only in QScriptEngine::evaluate.*/ |
461 | class UStringSourceProviderWithFeedback: public JSC::UStringSourceProvider |
462 | { |
463 | public: |
464 | static PassRefPtr<UStringSourceProviderWithFeedback> create( |
465 | const JSC::UString& source, const JSC::UString& url, |
466 | int lineNumber, QScriptEnginePrivate* engine) |
467 | { |
468 | return adoptRef(p: new UStringSourceProviderWithFeedback(source, url, lineNumber, engine)); |
469 | } |
470 | |
471 | /* Destruction means that there is no more copies of script so create scriptUnload event |
472 | and unregister script in QScriptEnginePrivate::loadedScripts */ |
473 | virtual ~UStringSourceProviderWithFeedback() |
474 | { |
475 | if (m_ptr) { |
476 | if (JSC::Debugger* debugger = this->debugger()) |
477 | debugger->scriptUnload(id: asID()); |
478 | m_ptr->loadedScripts.remove(akey: asID()); |
479 | } |
480 | } |
481 | |
482 | /* set internal QScriptEnginePrivate pointer to null and create unloadScript event, should be called |
483 | only if QScriptEnginePrivate is about to be destroyed.*/ |
484 | void disconnectFromEngine() |
485 | { |
486 | if (JSC::Debugger* debugger = this->debugger()) |
487 | debugger->scriptUnload(id: asID()); |
488 | m_ptr = 0; |
489 | } |
490 | |
491 | int columnNumberFromOffset(int offset) const |
492 | { |
493 | for (const UChar *c = m_source.data() + offset; c >= m_source.data(); --c) { |
494 | if (JSC::Lexer::isLineTerminator(ch: *c)) |
495 | return offset - static_cast<int>(c - data()); |
496 | } |
497 | return offset + 1; |
498 | } |
499 | |
500 | protected: |
501 | UStringSourceProviderWithFeedback(const JSC::UString& source, const JSC::UString& url, |
502 | int lineNumber, QScriptEnginePrivate* engine) |
503 | : UStringSourceProvider(source, url), |
504 | m_ptr(engine) |
505 | { |
506 | if (JSC::Debugger* debugger = this->debugger()) |
507 | debugger->scriptLoad(id: asID(), program: source, fileName: url, baseLineNumber: lineNumber); |
508 | if (m_ptr) |
509 | m_ptr->loadedScripts.insert(akey: asID(), avalue: this); |
510 | } |
511 | |
512 | JSC::Debugger* debugger() |
513 | { |
514 | //if m_ptr is null it mean that QScriptEnginePrivate was destroyed and scriptUnload was called |
515 | //else m_ptr is stable and we can use it as normal pointer without hesitation |
516 | if(!m_ptr) |
517 | return 0; //we are in ~QScriptEnginePrivate |
518 | else |
519 | return m_ptr->originalGlobalObject()->debugger(); //QScriptEnginePrivate is still alive |
520 | } |
521 | |
522 | //trace global object and debugger instance |
523 | QScriptEnginePrivate* m_ptr; |
524 | }; |
525 | |
526 | class SaveFrameHelper |
527 | { |
528 | public: |
529 | SaveFrameHelper(QScriptEnginePrivate *eng, |
530 | JSC::ExecState *newFrame) |
531 | : engine(eng), oldFrame(eng->currentFrame) |
532 | { |
533 | eng->currentFrame = newFrame; |
534 | } |
535 | ~SaveFrameHelper() |
536 | { |
537 | engine->currentFrame = oldFrame; |
538 | } |
539 | private: |
540 | QScriptEnginePrivate *engine; |
541 | JSC::ExecState *oldFrame; |
542 | }; |
543 | |
544 | inline QScriptEnginePrivate *scriptEngineFromExec(const JSC::ExecState *exec) |
545 | { |
546 | return static_cast<GlobalClientData*>(exec->globalData().clientData)->engine; |
547 | } |
548 | |
549 | #ifndef Q_CC_MSVC |
550 | // MSVC2008 crashes if these are inlined. |
551 | |
552 | inline QString ToString(qsreal value) |
553 | { |
554 | return JSC::UString::from(value); |
555 | } |
556 | |
557 | inline qsreal ToNumber(const QString &value) |
558 | { |
559 | return ((JSC::UString)value).toDouble(); |
560 | } |
561 | |
562 | #endif |
563 | |
564 | inline qint32 ToInt32(const QString &value) |
565 | { |
566 | return ToInt32(ToNumber(value)); |
567 | } |
568 | |
569 | inline quint32 ToUInt32(const QString &value) |
570 | { |
571 | return ToUInt32(ToNumber(value)); |
572 | } |
573 | |
574 | inline quint16 ToUInt16(const QString &value) |
575 | { |
576 | return ToUInt16(ToNumber(value)); |
577 | } |
578 | |
579 | inline qsreal ToInteger(const QString &value) |
580 | { |
581 | return ToInteger(ToNumber(value)); |
582 | } |
583 | |
584 | inline bool ToBool(qsreal value) |
585 | { |
586 | return (value != 0) && !qIsNaN(d: value); |
587 | } |
588 | |
589 | inline bool ToBool(const QString &value) |
590 | { |
591 | return !value.isEmpty(); |
592 | } |
593 | |
594 | inline void convertToLatin1_helper(const UChar *i, int length, char *s) |
595 | { |
596 | const UChar *e = i + length; |
597 | while (i != e) |
598 | *(s++) = (uchar) *(i++); |
599 | *s = '\0'; |
600 | } |
601 | |
602 | inline QByteArray convertToLatin1(const JSC::UString &str) |
603 | { |
604 | QByteArray ba(str.size(), Qt::Uninitialized); |
605 | convertToLatin1_helper(i: str.data(), length: str.size(), s: ba.data()); |
606 | return ba; |
607 | } |
608 | |
609 | } // namespace QScript |
610 | |
611 | inline void QScriptEnginePrivate::registerScriptProgram(QScriptProgramPrivate *program) |
612 | { |
613 | Q_ASSERT(!registeredScriptPrograms.contains(program)); |
614 | registeredScriptPrograms.insert(value: program); |
615 | } |
616 | |
617 | inline void QScriptEnginePrivate::unregisterScriptProgram(QScriptProgramPrivate *program) |
618 | { |
619 | Q_ASSERT(registeredScriptPrograms.contains(program)); |
620 | registeredScriptPrograms.remove(value: program); |
621 | } |
622 | |
623 | inline QScriptValuePrivate *QScriptEnginePrivate::allocateScriptValuePrivate(size_t size) |
624 | { |
625 | if (freeScriptValues) { |
626 | QScriptValuePrivate *p = freeScriptValues; |
627 | freeScriptValues = p->next; |
628 | --freeScriptValuesCount; |
629 | return p; |
630 | } |
631 | return reinterpret_cast<QScriptValuePrivate*>(malloc(size: size)); |
632 | } |
633 | |
634 | inline void QScriptEnginePrivate::freeScriptValuePrivate(QScriptValuePrivate *p) |
635 | { |
636 | if (freeScriptValuesCount < maxFreeScriptValues) { |
637 | p->next = freeScriptValues; |
638 | freeScriptValues = p; |
639 | ++freeScriptValuesCount; |
640 | } else { |
641 | free(ptr: p); |
642 | } |
643 | } |
644 | |
645 | inline void QScriptEnginePrivate::registerScriptValue(QScriptValuePrivate *value) |
646 | { |
647 | value->prev = 0; |
648 | value->next = registeredScriptValues; |
649 | if (registeredScriptValues) |
650 | registeredScriptValues->prev = value; |
651 | registeredScriptValues = value; |
652 | } |
653 | |
654 | inline void QScriptEnginePrivate::unregisterScriptValue(QScriptValuePrivate *value) |
655 | { |
656 | if (value->prev) |
657 | value->prev->next = value->next; |
658 | if (value->next) |
659 | value->next->prev = value->prev; |
660 | if (value == registeredScriptValues) |
661 | registeredScriptValues = value->next; |
662 | value->prev = 0; |
663 | value->next = 0; |
664 | } |
665 | |
666 | inline JSC::JSValue QScriptEnginePrivate::jscValueFromVariant(JSC::ExecState *exec, const QVariant &v) |
667 | { |
668 | JSC::JSValue result = create(exec, type: v.userType(), ptr: v.data()); |
669 | Q_ASSERT(result); |
670 | return result; |
671 | } |
672 | |
673 | inline QScriptValue QScriptEnginePrivate::scriptValueFromJSCValue(JSC::JSValue value) |
674 | { |
675 | if (!value) |
676 | return QScriptValue(); |
677 | |
678 | QScriptValuePrivate *p_value = new (this)QScriptValuePrivate(this); |
679 | p_value->initFrom(value); |
680 | return QScriptValuePrivate::toPublic(d: p_value); |
681 | } |
682 | |
683 | inline JSC::JSValue QScriptEnginePrivate::scriptValueToJSCValue(const QScriptValue &value) |
684 | { |
685 | QScriptValuePrivate *vv = QScriptValuePrivate::get(q: value); |
686 | if (!vv) |
687 | return JSC::JSValue(); |
688 | if (vv->type != QScriptValuePrivate::JavaScriptCore) { |
689 | Q_ASSERT(!vv->engine || vv->engine == this); |
690 | vv->engine = this; |
691 | if (vv->type == QScriptValuePrivate::Number) { |
692 | vv->initFrom(JSC::jsNumber(exec: currentFrame, d: vv->numberValue)); |
693 | } else { //QScriptValuePrivate::String |
694 | vv->initFrom(JSC::jsString(exec: currentFrame, s: vv->stringValue)); |
695 | } |
696 | } |
697 | return vv->jscValue; |
698 | } |
699 | |
700 | inline unsigned QScriptEnginePrivate::propertyFlagsToJSCAttributes(const QScriptValue::PropertyFlags &flags) |
701 | { |
702 | unsigned attribs = 0; |
703 | if (flags & QScriptValue::ReadOnly) |
704 | attribs |= JSC::ReadOnly; |
705 | if (flags & QScriptValue::SkipInEnumeration) |
706 | attribs |= JSC::DontEnum; |
707 | if (flags & QScriptValue::Undeletable) |
708 | attribs |= JSC::DontDelete; |
709 | attribs |= flags & QScriptValue::UserRange; |
710 | return attribs; |
711 | } |
712 | |
713 | inline QScriptValuePrivate::~QScriptValuePrivate() |
714 | { |
715 | if (engine) |
716 | engine->unregisterScriptValue(value: this); |
717 | } |
718 | |
719 | inline void QScriptValuePrivate::initFrom(JSC::JSValue value) |
720 | { |
721 | if (value.isCell()) { |
722 | Q_ASSERT(engine != 0); |
723 | value = engine->toUsableValue(value); |
724 | } |
725 | type = JavaScriptCore; |
726 | jscValue = value; |
727 | if (engine) |
728 | engine->registerScriptValue(value: this); |
729 | } |
730 | |
731 | inline void QScriptValuePrivate::initFrom(qsreal value) |
732 | { |
733 | type = Number; |
734 | numberValue = value; |
735 | if (engine) |
736 | engine->registerScriptValue(value: this); |
737 | } |
738 | |
739 | inline void QScriptValuePrivate::initFrom(const QString &value) |
740 | { |
741 | type = String; |
742 | stringValue = value; |
743 | if (engine) |
744 | engine->registerScriptValue(value: this); |
745 | } |
746 | |
747 | inline JSC::JSValue QScriptEnginePrivate::property(JSC::ExecState *exec, JSC::JSValue value, const JSC::UString &name, int resolveMode) |
748 | { |
749 | return property(exec, value, JSC::Identifier(exec, name), resolveMode); |
750 | } |
751 | |
752 | inline JSC::JSValue QScriptEnginePrivate::property(JSC::ExecState *exec, JSC::JSValue value, const JSC::Identifier &id, int resolveMode) |
753 | { |
754 | Q_ASSERT(isObject(value)); |
755 | JSC::JSObject *object = JSC::asObject(value); |
756 | JSC::PropertySlot slot(object); |
757 | if ((resolveMode & QScriptValue::ResolvePrototype) && object->getPropertySlot(exec, propertyName: id, slot)) |
758 | return slot.getValue(exec, propertyName: id); |
759 | return propertyHelper(exec, value, id, resolveMode); |
760 | } |
761 | |
762 | inline JSC::JSValue QScriptEnginePrivate::property(JSC::ExecState *exec, JSC::JSValue value, quint32 index, int resolveMode) |
763 | { |
764 | Q_ASSERT(isObject(value)); |
765 | JSC::JSObject *object = JSC::asObject(value); |
766 | JSC::PropertySlot slot(object); |
767 | if ((resolveMode & QScriptValue::ResolvePrototype) && object->getPropertySlot(exec, propertyName: index, slot)) |
768 | return slot.getValue(exec, propertyName: index); |
769 | return propertyHelper(exec, value, index, resolveMode); |
770 | } |
771 | |
772 | inline QScriptValue::PropertyFlags QScriptEnginePrivate::propertyFlags(JSC::ExecState *exec, JSC::JSValue value, |
773 | const JSC::UString &name, |
774 | const QScriptValue::ResolveFlags &mode) |
775 | { |
776 | return propertyFlags(exec, value, JSC::Identifier(exec, name), mode); |
777 | } |
778 | |
779 | inline void QScriptEnginePrivate::setProperty(JSC::ExecState *exec, JSC::JSValue objectValue, const JSC::UString &name, |
780 | JSC::JSValue value, const QScriptValue::PropertyFlags &flags) |
781 | { |
782 | setProperty(exec, object: objectValue, JSC::Identifier(exec, name), value, flags); |
783 | } |
784 | |
785 | inline JSC::JSValue QScriptValuePrivate::property(const JSC::Identifier &id, const QScriptValue::ResolveFlags &resolveMode) const |
786 | { |
787 | return QScriptEnginePrivate::property(exec: engine->currentFrame, value: jscValue, id, resolveMode); |
788 | } |
789 | |
790 | inline JSC::JSValue QScriptValuePrivate::property(quint32 index, const QScriptValue::ResolveFlags &resolveMode) const |
791 | { |
792 | return QScriptEnginePrivate::property(exec: engine->currentFrame, value: jscValue, index, resolveMode); |
793 | } |
794 | |
795 | inline JSC::JSValue QScriptValuePrivate::property(const JSC::UString &name, const QScriptValue::ResolveFlags &resolveMode) const |
796 | { |
797 | JSC::ExecState *exec = engine->currentFrame; |
798 | return QScriptEnginePrivate::property(exec, value: jscValue, JSC::Identifier(exec, name), resolveMode); |
799 | } |
800 | |
801 | inline QScriptValue::PropertyFlags QScriptValuePrivate::propertyFlags( |
802 | const JSC::Identifier &id, const QScriptValue::ResolveFlags &mode) const |
803 | { |
804 | return QScriptEnginePrivate::propertyFlags(engine->currentFrame, value: jscValue, id, mode); |
805 | } |
806 | |
807 | inline void QScriptValuePrivate::setProperty(const JSC::Identifier &id, const JSC::JSValue &value, |
808 | const QScriptValue::PropertyFlags &flags) |
809 | { |
810 | QScriptEnginePrivate::setProperty(engine->currentFrame, object: jscValue, id, value, flags); |
811 | } |
812 | |
813 | inline void QScriptValuePrivate::setProperty(quint32 index, const JSC::JSValue &value, |
814 | const QScriptValue::PropertyFlags &flags) |
815 | { |
816 | QScriptEnginePrivate::setProperty(engine->currentFrame, object: jscValue, index, value, flags); |
817 | } |
818 | |
819 | inline void QScriptValuePrivate::setProperty(const JSC::UString &name, const JSC::JSValue &value, |
820 | const QScriptValue::PropertyFlags &flags) |
821 | { |
822 | JSC::ExecState *exec = engine->currentFrame; |
823 | QScriptEnginePrivate::setProperty(exec, object: jscValue, JSC::Identifier(exec, name), value, flags); |
824 | } |
825 | |
826 | inline void* QScriptValuePrivate::operator new(size_t size, QScriptEnginePrivate *engine) |
827 | { |
828 | if (engine) |
829 | return engine->allocateScriptValuePrivate(size); |
830 | return malloc(size: size); |
831 | } |
832 | |
833 | inline void QScriptValuePrivate::operator delete(void *ptr) |
834 | { |
835 | QScriptValuePrivate *d = reinterpret_cast<QScriptValuePrivate*>(ptr); |
836 | if (d->engine) |
837 | d->engine->freeScriptValuePrivate(p: d); |
838 | else |
839 | free(ptr: d); |
840 | } |
841 | |
842 | inline void QScriptEnginePrivate::saveException(JSC::ExecState *exec, JSC::JSValue *val) |
843 | { |
844 | if (exec) { |
845 | *val = exec->exception(); |
846 | exec->clearException(); |
847 | } else { |
848 | *val = JSC::JSValue(); |
849 | } |
850 | } |
851 | |
852 | inline void QScriptEnginePrivate::restoreException(JSC::ExecState *exec, JSC::JSValue val) |
853 | { |
854 | if (exec && val) |
855 | exec->setException(val); |
856 | } |
857 | |
858 | inline void QScriptEnginePrivate::registerScriptString(QScriptStringPrivate *value) |
859 | { |
860 | Q_ASSERT(value->type == QScriptStringPrivate::HeapAllocated); |
861 | value->prev = 0; |
862 | value->next = registeredScriptStrings; |
863 | if (registeredScriptStrings) |
864 | registeredScriptStrings->prev = value; |
865 | registeredScriptStrings = value; |
866 | } |
867 | |
868 | inline void QScriptEnginePrivate::unregisterScriptString(QScriptStringPrivate *value) |
869 | { |
870 | Q_ASSERT(value->type == QScriptStringPrivate::HeapAllocated); |
871 | if (value->prev) |
872 | value->prev->next = value->next; |
873 | if (value->next) |
874 | value->next->prev = value->prev; |
875 | if (value == registeredScriptStrings) |
876 | registeredScriptStrings = value->next; |
877 | value->prev = 0; |
878 | value->next = 0; |
879 | } |
880 | |
881 | inline QScriptContext *QScriptEnginePrivate::contextForFrame(JSC::ExecState *frame) |
882 | { |
883 | if (frame && frame->callerFrame()->hasHostCallFrameFlag() && !frame->callee() |
884 | && frame->callerFrame()->removeHostCallFrameFlag() == QScript::scriptEngineFromExec(exec: frame)->globalExec()) { |
885 | //skip the "fake" context created in Interpreter::execute. |
886 | frame = frame->callerFrame()->removeHostCallFrameFlag(); |
887 | } |
888 | return reinterpret_cast<QScriptContext *>(frame); |
889 | } |
890 | |
891 | inline JSC::ExecState *QScriptEnginePrivate::frameForContext(QScriptContext *context) |
892 | { |
893 | return reinterpret_cast<JSC::ExecState*>(context); |
894 | } |
895 | |
896 | inline const JSC::ExecState *QScriptEnginePrivate::frameForContext(const QScriptContext *context) |
897 | { |
898 | return reinterpret_cast<const JSC::ExecState*>(context); |
899 | } |
900 | |
901 | inline bool QScriptEnginePrivate::hasValidCodeBlockRegister(JSC::ExecState *frame) |
902 | { |
903 | #if ENABLE(JIT) |
904 | // Frames created by the VM don't have their CodeBlock register |
905 | // initialized. We can detect such frames by checking if the |
906 | // callee is a host JSFunction. |
907 | JSC::JSObject *callee = frame->callee(); |
908 | return !(callee && callee->inherits(info: &JSC::JSFunction::info) |
909 | && JSC::asFunction(value: callee)->isHostFunction()); |
910 | #else |
911 | Q_UNUSED(frame); |
912 | return true; |
913 | #endif |
914 | } |
915 | |
916 | inline JSC::ExecState *QScriptEnginePrivate::globalExec() const |
917 | { |
918 | return originalGlobalObject()->globalExec(); |
919 | } |
920 | |
921 | inline JSC::JSValue QScriptEnginePrivate::newArray(JSC::ExecState *exec, uint length) |
922 | { |
923 | return JSC::constructEmptyArray(exec, initialLength: length); |
924 | } |
925 | |
926 | inline JSC::JSValue QScriptEnginePrivate::newDate(JSC::ExecState *exec, qsreal value) |
927 | { |
928 | JSC::JSValue val = JSC::jsNumber(exec, d: value); |
929 | JSC::ArgList args(&val, 1); |
930 | return JSC::constructDate(exec, args); |
931 | } |
932 | |
933 | inline JSC::JSValue QScriptEnginePrivate::newDate(JSC::ExecState *exec, const QDateTime &value) |
934 | { |
935 | return newDate(exec, value: QScript::DateTimeToMs(exec, value)); |
936 | } |
937 | |
938 | inline JSC::JSValue QScriptEnginePrivate::newObject() |
939 | { |
940 | return new (currentFrame)QScriptObject(scriptObjectStructure); |
941 | } |
942 | |
943 | inline bool QScriptEnginePrivate::isObject(JSC::JSValue value) |
944 | { |
945 | return value && value.isObject(); |
946 | } |
947 | |
948 | inline bool QScriptEnginePrivate::isArray(JSC::JSValue value) |
949 | { |
950 | return isObject(value) && value.inherits(classInfo: &JSC::JSArray::info); |
951 | } |
952 | |
953 | inline bool QScriptEnginePrivate::isDate(JSC::JSValue value) |
954 | { |
955 | return isObject(value) && value.inherits(classInfo: &JSC::DateInstance::info); |
956 | } |
957 | |
958 | inline bool QScriptEnginePrivate::isError(JSC::JSValue value) |
959 | { |
960 | return isObject(value) && value.inherits(classInfo: &JSC::ErrorInstance::info); |
961 | } |
962 | |
963 | inline bool QScriptEnginePrivate::isRegExp(JSC::JSValue value) |
964 | { |
965 | return isObject(value) && value.inherits(classInfo: &JSC::RegExpObject::info); |
966 | } |
967 | |
968 | inline bool QScriptEnginePrivate::isVariant(JSC::JSValue value) |
969 | { |
970 | if (!isObject(value) || !value.inherits(classInfo: &QScriptObject::info)) |
971 | return false; |
972 | QScriptObject *object = static_cast<QScriptObject*>(JSC::asObject(value)); |
973 | QScriptObjectDelegate *delegate = object->delegate(); |
974 | return (delegate && (delegate->type() == QScriptObjectDelegate::Variant)); |
975 | } |
976 | |
977 | inline bool QScriptEnginePrivate::isQObject(JSC::JSValue value) |
978 | { |
979 | #ifndef QT_NO_QOBJECT |
980 | if (!isObject(value) || !value.inherits(classInfo: &QScriptObject::info)) |
981 | return false; |
982 | QScriptObject *object = static_cast<QScriptObject*>(JSC::asObject(value)); |
983 | QScriptObjectDelegate *delegate = object->delegate(); |
984 | |
985 | if (delegate) { |
986 | if (delegate->type() == QScriptObjectDelegate::QtObject |
987 | || (delegate->type() == QScriptObjectDelegate::DeclarativeClassObject |
988 | && static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->scriptClass()->isQObject())) |
989 | return true; |
990 | |
991 | if (delegate->type() == QScriptObjectDelegate::Variant) { |
992 | QVariant var = variantValue(value); |
993 | int type = var.userType(); |
994 | if ((QMetaType::typeFlags(type) & QMetaType::PointerToQObject)) |
995 | return true; |
996 | } |
997 | } |
998 | #endif |
999 | return false; |
1000 | } |
1001 | |
1002 | inline bool QScriptEnginePrivate::isQMetaObject(JSC::JSValue value) |
1003 | { |
1004 | #ifndef QT_NO_QOBJECT |
1005 | return isObject(value) && JSC::asObject(value)->inherits(info: &QScript::QMetaObjectWrapperObject::info); |
1006 | #else |
1007 | return false; |
1008 | #endif |
1009 | } |
1010 | |
1011 | inline bool QScriptEnginePrivate::toBool(JSC::ExecState *exec, JSC::JSValue value) |
1012 | { |
1013 | JSC::JSValue savedException; |
1014 | saveException(exec, val: &savedException); |
1015 | bool result = value.toBoolean(exec); |
1016 | restoreException(exec, val: savedException); |
1017 | return result; |
1018 | } |
1019 | |
1020 | inline qsreal QScriptEnginePrivate::toInteger(JSC::ExecState *exec, JSC::JSValue value) |
1021 | { |
1022 | JSC::JSValue savedException; |
1023 | saveException(exec, val: &savedException); |
1024 | qsreal result = value.toInteger(exec); |
1025 | restoreException(exec, val: savedException); |
1026 | return result; |
1027 | } |
1028 | |
1029 | inline qsreal QScriptEnginePrivate::toNumber(JSC::ExecState *exec, JSC::JSValue value) |
1030 | { |
1031 | JSC::JSValue savedException; |
1032 | saveException(exec, val: &savedException); |
1033 | qsreal result = value.toNumber(exec); |
1034 | restoreException(exec, val: savedException); |
1035 | return result; |
1036 | } |
1037 | |
1038 | inline qint32 QScriptEnginePrivate::toInt32(JSC::ExecState *exec, JSC::JSValue value) |
1039 | { |
1040 | JSC::JSValue savedException; |
1041 | saveException(exec, val: &savedException); |
1042 | qint32 result = value.toInt32(exec); |
1043 | restoreException(exec, val: savedException); |
1044 | return result; |
1045 | } |
1046 | |
1047 | inline quint32 QScriptEnginePrivate::toUInt32(JSC::ExecState *exec, JSC::JSValue value) |
1048 | { |
1049 | JSC::JSValue savedException; |
1050 | saveException(exec, val: &savedException); |
1051 | quint32 result = value.toUInt32(exec); |
1052 | restoreException(exec, val: savedException); |
1053 | return result; |
1054 | } |
1055 | |
1056 | inline quint16 QScriptEnginePrivate::toUInt16(JSC::ExecState *exec, JSC::JSValue value) |
1057 | { |
1058 | // ### no equivalent function in JSC |
1059 | return QScript::ToUInt16(toNumber(exec, value)); |
1060 | } |
1061 | |
1062 | inline JSC::UString QScriptEnginePrivate::toString(JSC::ExecState *exec, JSC::JSValue value) |
1063 | { |
1064 | if (!value) |
1065 | return JSC::UString(); |
1066 | JSC::JSValue savedException; |
1067 | saveException(exec, val: &savedException); |
1068 | JSC::UString str = value.toString(exec); |
1069 | if (exec && exec->hadException() && !str.size()) { |
1070 | JSC::JSValue savedException2; |
1071 | saveException(exec, val: &savedException2); |
1072 | str = savedException2.toString(exec); |
1073 | restoreException(exec, val: savedException2); |
1074 | } |
1075 | if (savedException) |
1076 | restoreException(exec, val: savedException); |
1077 | return str; |
1078 | } |
1079 | |
1080 | inline QDateTime QScriptEnginePrivate::toDateTime(JSC::ExecState *exec, JSC::JSValue value) |
1081 | { |
1082 | if (!isDate(value)) |
1083 | return QDateTime(); |
1084 | qsreal t = static_cast<JSC::DateInstance*>(JSC::asObject(value))->internalNumber(); |
1085 | return QScript::MsToDateTime(exec, t); |
1086 | } |
1087 | |
1088 | inline QObject *QScriptEnginePrivate::toQObject(JSC::ExecState *exec, JSC::JSValue value) |
1089 | { |
1090 | #ifndef QT_NO_QOBJECT |
1091 | if (isObject(value) && value.inherits(classInfo: &QScriptObject::info)) { |
1092 | QScriptObject *object = static_cast<QScriptObject*>(JSC::asObject(value)); |
1093 | QScriptObjectDelegate *delegate = object->delegate(); |
1094 | if (!delegate) |
1095 | return 0; |
1096 | if (delegate->type() == QScriptObjectDelegate::QtObject) |
1097 | return static_cast<QScript::QObjectDelegate*>(delegate)->value(); |
1098 | if (delegate->type() == QScriptObjectDelegate::DeclarativeClassObject) |
1099 | return static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->scriptClass()->toQObject(declarativeObject(value)); |
1100 | if (delegate->type() == QScriptObjectDelegate::Variant) { |
1101 | QVariant var = variantValue(value); |
1102 | int type = var.userType(); |
1103 | if (QMetaType::typeFlags(type) & QMetaType::PointerToQObject) |
1104 | return *reinterpret_cast<QObject* const *>(var.constData()); |
1105 | } |
1106 | } else if (isObject(value) && value.inherits(classInfo: &QScript::QScriptActivationObject::info)) { |
1107 | QScript::QScriptActivationObject *proxy = static_cast<QScript::QScriptActivationObject *>(JSC::asObject(value)); |
1108 | return toQObject(exec, value: proxy->delegate()); |
1109 | } |
1110 | #endif |
1111 | return 0; |
1112 | } |
1113 | |
1114 | inline const QMetaObject *QScriptEnginePrivate::toQMetaObject(JSC::ExecState*, JSC::JSValue value) |
1115 | { |
1116 | #ifndef QT_NO_QOBJECT |
1117 | if (isQMetaObject(value)) |
1118 | return static_cast<QScript::QMetaObjectWrapperObject*>(JSC::asObject(value))->value(); |
1119 | #endif |
1120 | return 0; |
1121 | } |
1122 | |
1123 | inline QVariant &QScriptEnginePrivate::variantValue(JSC::JSValue value) |
1124 | { |
1125 | Q_ASSERT(value.inherits(&QScriptObject::info)); |
1126 | QScriptObjectDelegate *delegate = static_cast<QScriptObject*>(JSC::asObject(value))->delegate(); |
1127 | Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::Variant)); |
1128 | return static_cast<QScript::QVariantDelegate*>(delegate)->value(); |
1129 | } |
1130 | |
1131 | inline void QScriptEnginePrivate::setVariantValue(JSC::JSValue objectValue, const QVariant &value) |
1132 | { |
1133 | Q_ASSERT(objectValue.inherits(&QScriptObject::info)); |
1134 | QScriptObjectDelegate *delegate = static_cast<QScriptObject*>(JSC::asObject(value: objectValue))->delegate(); |
1135 | Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::Variant)); |
1136 | static_cast<QScript::QVariantDelegate*>(delegate)->setValue(value); |
1137 | } |
1138 | |
1139 | inline QScriptDeclarativeClass *QScriptEnginePrivate::declarativeClass(JSC::JSValue v) |
1140 | { |
1141 | if (!QScriptEnginePrivate::isObject(value: v) || !v.inherits(classInfo: &QScriptObject::info)) |
1142 | return 0; |
1143 | QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(value: v)); |
1144 | QScriptObjectDelegate *delegate = scriptObject->delegate(); |
1145 | if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject)) |
1146 | return 0; |
1147 | return static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->scriptClass(); |
1148 | } |
1149 | |
1150 | inline QScriptDeclarativeClass::Object *QScriptEnginePrivate::declarativeObject(JSC::JSValue v) |
1151 | { |
1152 | if (!QScriptEnginePrivate::isObject(value: v) || !v.inherits(classInfo: &QScriptObject::info)) |
1153 | return 0; |
1154 | QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(value: v)); |
1155 | QScriptObjectDelegate *delegate = scriptObject->delegate(); |
1156 | if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject)) |
1157 | return 0; |
1158 | return static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->object(); |
1159 | } |
1160 | |
1161 | QT_END_NAMESPACE |
1162 | |
1163 | #endif |
1164 | |