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 {
GlobalClientDataGlobalClientData157 GlobalClientData(QScriptEnginePrivate *e)
158 : engine(e) {}
~GlobalClientDataGlobalClientData159 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
get(QScriptEngine * q)179 static QScriptEnginePrivate *get(QScriptEngine *q) { return q ? q->d_func() : 0; }
get(QScriptEnginePrivate * d)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
setCurrentException(QScriptValue exception)298 void setCurrentException(QScriptValue exception) { m_currentException = exception; }
currentException()299 QScriptValue currentException() const { return m_currentException; }
clearCurrentException()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:
APIShim(QScriptEnginePrivate * engine)444 APIShim(QScriptEnginePrivate *engine)
445 : m_engine(engine), m_oldTable(JSC::setCurrentIdentifierTable(engine->globalData->identifierTable))
446 {
447 }
~APIShim()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:
create(const JSC::UString & source,const JSC::UString & url,int lineNumber,QScriptEnginePrivate * engine)464 static PassRefPtr<UStringSourceProviderWithFeedback> create(
465 const JSC::UString& source, const JSC::UString& url,
466 int lineNumber, QScriptEnginePrivate* engine)
467 {
468 return adoptRef(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 */
~UStringSourceProviderWithFeedback()473 virtual ~UStringSourceProviderWithFeedback()
474 {
475 if (m_ptr) {
476 if (JSC::Debugger* debugger = this->debugger())
477 debugger->scriptUnload(asID());
478 m_ptr->loadedScripts.remove(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.*/
disconnectFromEngine()484 void disconnectFromEngine()
485 {
486 if (JSC::Debugger* debugger = this->debugger())
487 debugger->scriptUnload(asID());
488 m_ptr = 0;
489 }
490
columnNumberFromOffset(int offset)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(*c))
495 return offset - static_cast<int>(c - data());
496 }
497 return offset + 1;
498 }
499
500 protected:
UStringSourceProviderWithFeedback(const JSC::UString & source,const JSC::UString & url,int lineNumber,QScriptEnginePrivate * engine)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(asID(), source, url, lineNumber);
508 if (m_ptr)
509 m_ptr->loadedScripts.insert(asID(), this);
510 }
511
debugger()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:
SaveFrameHelper(QScriptEnginePrivate * eng,JSC::ExecState * newFrame)529 SaveFrameHelper(QScriptEnginePrivate *eng,
530 JSC::ExecState *newFrame)
531 : engine(eng), oldFrame(eng->currentFrame)
532 {
533 eng->currentFrame = newFrame;
534 }
~SaveFrameHelper()535 ~SaveFrameHelper()
536 {
537 engine->currentFrame = oldFrame;
538 }
539 private:
540 QScriptEnginePrivate *engine;
541 JSC::ExecState *oldFrame;
542 };
543
scriptEngineFromExec(const JSC::ExecState * exec)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
ToString(qsreal value)552 inline QString ToString(qsreal value)
553 {
554 return JSC::UString::from(value);
555 }
556
ToNumber(const QString & value)557 inline qsreal ToNumber(const QString &value)
558 {
559 return ((JSC::UString)value).toDouble();
560 }
561
562 #endif
563
ToInt32(const QString & value)564 inline qint32 ToInt32(const QString &value)
565 {
566 return ToInt32(ToNumber(value));
567 }
568
ToUInt32(const QString & value)569 inline quint32 ToUInt32(const QString &value)
570 {
571 return ToUInt32(ToNumber(value));
572 }
573
ToUInt16(const QString & value)574 inline quint16 ToUInt16(const QString &value)
575 {
576 return ToUInt16(ToNumber(value));
577 }
578
ToInteger(const QString & value)579 inline qsreal ToInteger(const QString &value)
580 {
581 return ToInteger(ToNumber(value));
582 }
583
ToBool(qsreal value)584 inline bool ToBool(qsreal value)
585 {
586 return (value != 0) && !qIsNaN(value);
587 }
588
ToBool(const QString & value)589 inline bool ToBool(const QString &value)
590 {
591 return !value.isEmpty();
592 }
593
convertToLatin1_helper(const UChar * i,int length,char * s)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
convertToLatin1(const JSC::UString & str)602 inline QByteArray convertToLatin1(const JSC::UString &str)
603 {
604 QByteArray ba(str.size(), Qt::Uninitialized);
605 convertToLatin1_helper(str.data(), str.size(), ba.data());
606 return ba;
607 }
608
609 } // namespace QScript
610
registerScriptProgram(QScriptProgramPrivate * program)611 inline void QScriptEnginePrivate::registerScriptProgram(QScriptProgramPrivate *program)
612 {
613 Q_ASSERT(!registeredScriptPrograms.contains(program));
614 registeredScriptPrograms.insert(program);
615 }
616
unregisterScriptProgram(QScriptProgramPrivate * program)617 inline void QScriptEnginePrivate::unregisterScriptProgram(QScriptProgramPrivate *program)
618 {
619 Q_ASSERT(registeredScriptPrograms.contains(program));
620 registeredScriptPrograms.remove(program);
621 }
622
allocateScriptValuePrivate(size_t size)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));
632 }
633
freeScriptValuePrivate(QScriptValuePrivate * p)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(p);
642 }
643 }
644
registerScriptValue(QScriptValuePrivate * value)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
unregisterScriptValue(QScriptValuePrivate * value)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
jscValueFromVariant(JSC::ExecState * exec,const QVariant & v)666 inline JSC::JSValue QScriptEnginePrivate::jscValueFromVariant(JSC::ExecState *exec, const QVariant &v)
667 {
668 JSC::JSValue result = create(exec, v.userType(), v.data());
669 Q_ASSERT(result);
670 return result;
671 }
672
scriptValueFromJSCValue(JSC::JSValue value)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(p_value);
681 }
682
scriptValueToJSCValue(const QScriptValue & value)683 inline JSC::JSValue QScriptEnginePrivate::scriptValueToJSCValue(const QScriptValue &value)
684 {
685 QScriptValuePrivate *vv = QScriptValuePrivate::get(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(currentFrame, vv->numberValue));
693 } else { //QScriptValuePrivate::String
694 vv->initFrom(JSC::jsString(currentFrame, vv->stringValue));
695 }
696 }
697 return vv->jscValue;
698 }
699
propertyFlagsToJSCAttributes(const QScriptValue::PropertyFlags & flags)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
~QScriptValuePrivate()713 inline QScriptValuePrivate::~QScriptValuePrivate()
714 {
715 if (engine)
716 engine->unregisterScriptValue(this);
717 }
718
initFrom(JSC::JSValue value)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(this);
729 }
730
initFrom(qsreal value)731 inline void QScriptValuePrivate::initFrom(qsreal value)
732 {
733 type = Number;
734 numberValue = value;
735 if (engine)
736 engine->registerScriptValue(this);
737 }
738
initFrom(const QString & value)739 inline void QScriptValuePrivate::initFrom(const QString &value)
740 {
741 type = String;
742 stringValue = value;
743 if (engine)
744 engine->registerScriptValue(this);
745 }
746
property(JSC::ExecState * exec,JSC::JSValue value,const JSC::UString & name,int resolveMode)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
property(JSC::ExecState * exec,JSC::JSValue value,const JSC::Identifier & id,int resolveMode)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, id, slot))
758 return slot.getValue(exec, id);
759 return propertyHelper(exec, value, id, resolveMode);
760 }
761
property(JSC::ExecState * exec,JSC::JSValue value,quint32 index,int resolveMode)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, index, slot))
768 return slot.getValue(exec, index);
769 return propertyHelper(exec, value, index, resolveMode);
770 }
771
propertyFlags(JSC::ExecState * exec,JSC::JSValue value,const JSC::UString & name,const QScriptValue::ResolveFlags & mode)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
setProperty(JSC::ExecState * exec,JSC::JSValue objectValue,const JSC::UString & name,JSC::JSValue value,const QScriptValue::PropertyFlags & flags)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, objectValue, JSC::Identifier(exec, name), value, flags);
783 }
784
property(const JSC::Identifier & id,const QScriptValue::ResolveFlags & resolveMode)785 inline JSC::JSValue QScriptValuePrivate::property(const JSC::Identifier &id, const QScriptValue::ResolveFlags &resolveMode) const
786 {
787 return QScriptEnginePrivate::property(engine->currentFrame, jscValue, id, resolveMode);
788 }
789
property(quint32 index,const QScriptValue::ResolveFlags & resolveMode)790 inline JSC::JSValue QScriptValuePrivate::property(quint32 index, const QScriptValue::ResolveFlags &resolveMode) const
791 {
792 return QScriptEnginePrivate::property(engine->currentFrame, jscValue, index, resolveMode);
793 }
794
property(const JSC::UString & name,const QScriptValue::ResolveFlags & resolveMode)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, jscValue, JSC::Identifier(exec, name), resolveMode);
799 }
800
propertyFlags(const JSC::Identifier & id,const QScriptValue::ResolveFlags & mode)801 inline QScriptValue::PropertyFlags QScriptValuePrivate::propertyFlags(
802 const JSC::Identifier &id, const QScriptValue::ResolveFlags &mode) const
803 {
804 return QScriptEnginePrivate::propertyFlags(engine->currentFrame, jscValue, id, mode);
805 }
806
setProperty(const JSC::Identifier & id,const JSC::JSValue & value,const QScriptValue::PropertyFlags & flags)807 inline void QScriptValuePrivate::setProperty(const JSC::Identifier &id, const JSC::JSValue &value,
808 const QScriptValue::PropertyFlags &flags)
809 {
810 QScriptEnginePrivate::setProperty(engine->currentFrame, jscValue, id, value, flags);
811 }
812
setProperty(quint32 index,const JSC::JSValue & value,const QScriptValue::PropertyFlags & flags)813 inline void QScriptValuePrivate::setProperty(quint32 index, const JSC::JSValue &value,
814 const QScriptValue::PropertyFlags &flags)
815 {
816 QScriptEnginePrivate::setProperty(engine->currentFrame, jscValue, index, value, flags);
817 }
818
setProperty(const JSC::UString & name,const JSC::JSValue & value,const QScriptValue::PropertyFlags & flags)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, jscValue, JSC::Identifier(exec, name), value, flags);
824 }
825
new(size_t size,QScriptEnginePrivate * engine)826 inline void* QScriptValuePrivate::operator new(size_t size, QScriptEnginePrivate *engine)
827 {
828 if (engine)
829 return engine->allocateScriptValuePrivate(size);
830 return malloc(size);
831 }
832
delete(void * ptr)833 inline void QScriptValuePrivate::operator delete(void *ptr)
834 {
835 QScriptValuePrivate *d = reinterpret_cast<QScriptValuePrivate*>(ptr);
836 if (d->engine)
837 d->engine->freeScriptValuePrivate(d);
838 else
839 free(d);
840 }
841
saveException(JSC::ExecState * exec,JSC::JSValue * val)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
restoreException(JSC::ExecState * exec,JSC::JSValue val)852 inline void QScriptEnginePrivate::restoreException(JSC::ExecState *exec, JSC::JSValue val)
853 {
854 if (exec && val)
855 exec->setException(val);
856 }
857
registerScriptString(QScriptStringPrivate * value)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
unregisterScriptString(QScriptStringPrivate * value)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
contextForFrame(JSC::ExecState * frame)881 inline QScriptContext *QScriptEnginePrivate::contextForFrame(JSC::ExecState *frame)
882 {
883 if (frame && frame->callerFrame()->hasHostCallFrameFlag() && !frame->callee()
884 && frame->callerFrame()->removeHostCallFrameFlag() == QScript::scriptEngineFromExec(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
frameForContext(QScriptContext * context)891 inline JSC::ExecState *QScriptEnginePrivate::frameForContext(QScriptContext *context)
892 {
893 return reinterpret_cast<JSC::ExecState*>(context);
894 }
895
frameForContext(const QScriptContext * context)896 inline const JSC::ExecState *QScriptEnginePrivate::frameForContext(const QScriptContext *context)
897 {
898 return reinterpret_cast<const JSC::ExecState*>(context);
899 }
900
hasValidCodeBlockRegister(JSC::ExecState * frame)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(&JSC::JSFunction::info)
909 && JSC::asFunction(callee)->isHostFunction());
910 #else
911 Q_UNUSED(frame);
912 return true;
913 #endif
914 }
915
globalExec()916 inline JSC::ExecState *QScriptEnginePrivate::globalExec() const
917 {
918 return originalGlobalObject()->globalExec();
919 }
920
newArray(JSC::ExecState * exec,uint length)921 inline JSC::JSValue QScriptEnginePrivate::newArray(JSC::ExecState *exec, uint length)
922 {
923 return JSC::constructEmptyArray(exec, length);
924 }
925
newDate(JSC::ExecState * exec,qsreal value)926 inline JSC::JSValue QScriptEnginePrivate::newDate(JSC::ExecState *exec, qsreal value)
927 {
928 JSC::JSValue val = JSC::jsNumber(exec, value);
929 JSC::ArgList args(&val, 1);
930 return JSC::constructDate(exec, args);
931 }
932
newDate(JSC::ExecState * exec,const QDateTime & value)933 inline JSC::JSValue QScriptEnginePrivate::newDate(JSC::ExecState *exec, const QDateTime &value)
934 {
935 return newDate(exec, QScript::DateTimeToMs(exec, value));
936 }
937
newObject()938 inline JSC::JSValue QScriptEnginePrivate::newObject()
939 {
940 return new (currentFrame)QScriptObject(scriptObjectStructure);
941 }
942
isObject(JSC::JSValue value)943 inline bool QScriptEnginePrivate::isObject(JSC::JSValue value)
944 {
945 return value && value.isObject();
946 }
947
isArray(JSC::JSValue value)948 inline bool QScriptEnginePrivate::isArray(JSC::JSValue value)
949 {
950 return isObject(value) && value.inherits(&JSC::JSArray::info);
951 }
952
isDate(JSC::JSValue value)953 inline bool QScriptEnginePrivate::isDate(JSC::JSValue value)
954 {
955 return isObject(value) && value.inherits(&JSC::DateInstance::info);
956 }
957
isError(JSC::JSValue value)958 inline bool QScriptEnginePrivate::isError(JSC::JSValue value)
959 {
960 return isObject(value) && value.inherits(&JSC::ErrorInstance::info);
961 }
962
isRegExp(JSC::JSValue value)963 inline bool QScriptEnginePrivate::isRegExp(JSC::JSValue value)
964 {
965 return isObject(value) && value.inherits(&JSC::RegExpObject::info);
966 }
967
isVariant(JSC::JSValue value)968 inline bool QScriptEnginePrivate::isVariant(JSC::JSValue value)
969 {
970 if (!isObject(value) || !value.inherits(&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
isQObject(JSC::JSValue value)977 inline bool QScriptEnginePrivate::isQObject(JSC::JSValue value)
978 {
979 #ifndef QT_NO_QOBJECT
980 if (!isObject(value) || !value.inherits(&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
isQMetaObject(JSC::JSValue value)1002 inline bool QScriptEnginePrivate::isQMetaObject(JSC::JSValue value)
1003 {
1004 #ifndef QT_NO_QOBJECT
1005 return isObject(value) && JSC::asObject(value)->inherits(&QScript::QMetaObjectWrapperObject::info);
1006 #else
1007 return false;
1008 #endif
1009 }
1010
toBool(JSC::ExecState * exec,JSC::JSValue value)1011 inline bool QScriptEnginePrivate::toBool(JSC::ExecState *exec, JSC::JSValue value)
1012 {
1013 JSC::JSValue savedException;
1014 saveException(exec, &savedException);
1015 bool result = value.toBoolean(exec);
1016 restoreException(exec, savedException);
1017 return result;
1018 }
1019
toInteger(JSC::ExecState * exec,JSC::JSValue value)1020 inline qsreal QScriptEnginePrivate::toInteger(JSC::ExecState *exec, JSC::JSValue value)
1021 {
1022 JSC::JSValue savedException;
1023 saveException(exec, &savedException);
1024 qsreal result = value.toInteger(exec);
1025 restoreException(exec, savedException);
1026 return result;
1027 }
1028
toNumber(JSC::ExecState * exec,JSC::JSValue value)1029 inline qsreal QScriptEnginePrivate::toNumber(JSC::ExecState *exec, JSC::JSValue value)
1030 {
1031 JSC::JSValue savedException;
1032 saveException(exec, &savedException);
1033 qsreal result = value.toNumber(exec);
1034 restoreException(exec, savedException);
1035 return result;
1036 }
1037
toInt32(JSC::ExecState * exec,JSC::JSValue value)1038 inline qint32 QScriptEnginePrivate::toInt32(JSC::ExecState *exec, JSC::JSValue value)
1039 {
1040 JSC::JSValue savedException;
1041 saveException(exec, &savedException);
1042 qint32 result = value.toInt32(exec);
1043 restoreException(exec, savedException);
1044 return result;
1045 }
1046
toUInt32(JSC::ExecState * exec,JSC::JSValue value)1047 inline quint32 QScriptEnginePrivate::toUInt32(JSC::ExecState *exec, JSC::JSValue value)
1048 {
1049 JSC::JSValue savedException;
1050 saveException(exec, &savedException);
1051 quint32 result = value.toUInt32(exec);
1052 restoreException(exec, savedException);
1053 return result;
1054 }
1055
toUInt16(JSC::ExecState * exec,JSC::JSValue value)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
toString(JSC::ExecState * exec,JSC::JSValue value)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, &savedException);
1068 JSC::UString str = value.toString(exec);
1069 if (exec && exec->hadException() && !str.size()) {
1070 JSC::JSValue savedException2;
1071 saveException(exec, &savedException2);
1072 str = savedException2.toString(exec);
1073 restoreException(exec, savedException2);
1074 }
1075 if (savedException)
1076 restoreException(exec, savedException);
1077 return str;
1078 }
1079
toDateTime(JSC::ExecState * exec,JSC::JSValue value)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
toQObject(JSC::ExecState * exec,JSC::JSValue value)1088 inline QObject *QScriptEnginePrivate::toQObject(JSC::ExecState *exec, JSC::JSValue value)
1089 {
1090 #ifndef QT_NO_QOBJECT
1091 if (isObject(value) && value.inherits(&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(&QScript::QScriptActivationObject::info)) {
1107 QScript::QScriptActivationObject *proxy = static_cast<QScript::QScriptActivationObject *>(JSC::asObject(value));
1108 return toQObject(exec, proxy->delegate());
1109 }
1110 #endif
1111 return 0;
1112 }
1113
toQMetaObject(JSC::ExecState *,JSC::JSValue value)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
variantValue(JSC::JSValue value)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
setVariantValue(JSC::JSValue objectValue,const QVariant & value)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(objectValue))->delegate();
1135 Q_ASSERT(delegate && (delegate->type() == QScriptObjectDelegate::Variant));
1136 static_cast<QScript::QVariantDelegate*>(delegate)->setValue(value);
1137 }
1138
declarativeClass(JSC::JSValue v)1139 inline QScriptDeclarativeClass *QScriptEnginePrivate::declarativeClass(JSC::JSValue v)
1140 {
1141 if (!QScriptEnginePrivate::isObject(v) || !v.inherits(&QScriptObject::info))
1142 return 0;
1143 QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(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
declarativeObject(JSC::JSValue v)1150 inline QScriptDeclarativeClass::Object *QScriptEnginePrivate::declarativeObject(JSC::JSValue v)
1151 {
1152 if (!QScriptEnginePrivate::isObject(v) || !v.inherits(&QScriptObject::info))
1153 return 0;
1154 QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(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