source: trunk/src/script/api/qscriptengine_p.h@ 1168

Last change on this file since 1168 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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