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