1 /****************************************************************************
2 **
3 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the Qt Solutions component.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
10 **
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
13 ** met:
14 **   * Redistributions of source code must retain the above copyright
15 **     notice, this list of conditions and the following disclaimer.
16 **   * Redistributions in binary form must reproduce the above copyright
17 **     notice, this list of conditions and the following disclaimer in
18 **     the documentation and/or other materials provided with the
19 **     distribution.
20 **   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
21 **     of its contributors may be used to endorse or promote products derived
22 **     from this software without specific prior written permission.
23 **
24 **
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 
42 #ifndef QSCRIPTENGINE_P_H
43 #define QSCRIPTENGINE_P_H
44 
45 #include "qscriptenginefwd_p.h"
46 
47 
48 #include <QDateTime>
49 #include <QMutex>
50 #include <QLinkedList>
51 #include <QString>
52 #include <QVector>
53 #include <QHash>
54 #include <qnumeric.h>
55 
56 #include "qscriptengine.h"
57 #include "qscriptnameid_p.h"
58 #include "qscriptobjectfwd_p.h"
59 #include "qscriptrepository_p.h"
60 #include "qscriptgc_p.h"
61 #include "qscriptecmaarray_p.h"
62 #include "qscriptecmadate_p.h"
63 #include "qscriptecmaobject_p.h"
64 #include "qscriptecmaboolean_p.h"
65 #include "qscriptecmanumber_p.h"
66 #include "qscriptecmastring_p.h"
67 #include "qscriptecmafunction_p.h"
68 #include "qscriptextvariant_p.h"
69 #include "qscriptextqobject_p.h"
70 #include "qscriptvalue_p.h"
71 #include "qscriptcontextfwd_p.h"
72 
73 #include <math.h>
74 
75 QT_BEGIN_NAMESPACE
76 
77 //
78 //  W A R N I N G
79 //  -------------
80 //
81 // This file is not part of the Qt API.  It exists purely as an
82 // implementation detail.  This header file may change from version to
83 // version without notice, or even be removed.
84 //
85 // We mean it.
86 //
87 
88 namespace QScript {
89 
90 class ArgumentsObjectData: public QScriptObjectData
91 {
92 public:
ArgumentsObjectData()93     ArgumentsObjectData() : length(0) {}
~ArgumentsObjectData()94     virtual ~ArgumentsObjectData() {}
95 
96 public: // attributes
97     QScriptValueImpl activation;
98     uint length;
99 };
100 
101 } // namespace QScript
102 
get(QScriptEngine * q)103 inline QScriptEnginePrivate *QScriptEnginePrivate::get(QScriptEngine *q)
104 {
105     if (q)
106         return q->d_func();
107     return 0;
108 }
109 
get(const QScriptEngine * q)110 inline const QScriptEnginePrivate *QScriptEnginePrivate::get(const QScriptEngine *q)
111 {
112     if (q)
113         return q->d_func();
114     return 0;
115 }
116 
get(QScriptEnginePrivate * d)117 inline QScriptEngine *QScriptEnginePrivate::get(QScriptEnginePrivate *d)
118 {
119     return d->q_func();
120 }
121 
toString(QScriptNameIdImpl * id)122 inline QString QScriptEnginePrivate::toString(QScriptNameIdImpl *id)
123 {
124     if (! id)
125         return QString();
126 
127     return id->s;
128 }
129 
memberName(const QScript::Member & member)130 inline QString QScriptEnginePrivate::memberName(const QScript::Member &member) const
131 {
132     return toString(member.nameId());
133 }
134 
newReference(QScriptValueImpl * o,int mode)135 inline void QScriptEnginePrivate::newReference(QScriptValueImpl *o, int mode)
136 {
137     Q_ASSERT(o);
138     o->m_type = QScript::ReferenceType;
139     o->m_int_value = (mode);
140 }
141 
newActivation(QScriptValueImpl * o)142 inline void QScriptEnginePrivate::newActivation(QScriptValueImpl *o)
143 {
144     Q_ASSERT(o);
145     newObject(o, nullValue(), m_class_activation);
146 }
147 
newPointer(QScriptValueImpl * o,void * ptr)148 inline void QScriptEnginePrivate::newPointer(QScriptValueImpl *o, void *ptr)
149 {
150     Q_ASSERT(o);
151     o->m_type = QScript::PointerType;
152     o->m_ptr_value = ptr;
153 }
154 
newInteger(QScriptValueImpl * o,int i)155 inline void QScriptEnginePrivate::newInteger(QScriptValueImpl *o, int i)
156 {
157     Q_ASSERT(o);
158     o->m_type = QScript::IntegerType;
159     o->m_int_value = (i);
160 }
161 
newNameId(QScriptValueImpl * o,const QString & s)162 inline void QScriptEnginePrivate::newNameId(QScriptValueImpl *o, const QString &s)
163 {
164     Q_ASSERT(o);
165     o->m_type = QScript::StringType;
166     o->m_string_value = (nameId(s, /*persistent=*/false));
167 }
168 
newString(QScriptValueImpl * o,const QString & s)169 inline void QScriptEnginePrivate::newString(QScriptValueImpl *o, const QString &s)
170 {
171     Q_ASSERT(o);
172     o->m_type = QScript::StringType;
173     QScriptNameIdImpl *entry = new QScriptNameIdImpl(s);
174     m_tempStringRepository.append(entry);
175     o->m_string_value = (entry);
176     m_newAllocatedTempStringRepositoryChars += s.length();
177 }
178 
newNameId(QScriptValueImpl * o,QScriptNameIdImpl * id)179 inline void QScriptEnginePrivate::newNameId(QScriptValueImpl *o, QScriptNameIdImpl *id)
180 {
181     Q_ASSERT(o);
182     o->m_type = QScript::StringType;
183     o->m_string_value = (id);
184 }
185 
idTable()186 inline const QScript::IdTable *QScriptEnginePrivate::idTable() const
187 {
188     return &m_id_table;
189 }
190 
convertToNativeDouble(const QScriptValueImpl & value)191 inline qsreal QScriptEnginePrivate::convertToNativeDouble(const QScriptValueImpl &value)
192 {
193     Q_ASSERT (value.isValid());
194 
195     if (value.isNumber())
196         return value.m_number_value;
197 
198     return convertToNativeDouble_helper(value);
199 }
200 
convertToNativeInt32(const QScriptValueImpl & value)201 inline qint32 QScriptEnginePrivate::convertToNativeInt32(const QScriptValueImpl &value)
202 {
203     Q_ASSERT (value.isValid());
204 
205     return toInt32 (convertToNativeDouble(value));
206 }
207 
208 
convertToNativeBoolean(const QScriptValueImpl & value)209 inline bool QScriptEnginePrivate::convertToNativeBoolean(const QScriptValueImpl &value)
210 {
211     Q_ASSERT (value.isValid());
212 
213     if (value.isBoolean())
214         return value.m_bool_value;
215 
216     return convertToNativeBoolean_helper(value);
217 }
218 
convertToNativeString(const QScriptValueImpl & value)219 inline QString QScriptEnginePrivate::convertToNativeString(const QScriptValueImpl &value)
220 {
221     Q_ASSERT (value.isValid());
222 
223     if (value.isString())
224         return value.m_string_value->s;
225 
226     return convertToNativeString_helper(value);
227 }
228 
toInteger(qsreal n)229 inline qsreal QScriptEnginePrivate::toInteger(qsreal n)
230 {
231     if (qIsNaN(n))
232         return 0;
233 
234     if (n == 0 || qIsInf(n))
235         return n;
236 
237     int sign = n < 0 ? -1 : 1;
238     return sign * ::floor(::fabs(n));
239 }
240 
toInt32(qsreal n)241 inline qint32 QScriptEnginePrivate::toInt32(qsreal n)
242 {
243     if (qIsNaN(n) || qIsInf(n) || (n == 0))
244         return 0;
245 
246     double sign = (n < 0) ? -1.0 : 1.0;
247     qsreal abs_n = fabs(n);
248 
249     n = ::fmod(sign * ::floor(abs_n), D32);
250     const double D31 = D32 / 2.0;
251 
252     if (sign == -1 && n < -D31)
253         n += D32;
254 
255     else if (sign != -1 && n >= D31)
256         n -= D32;
257 
258     return qint32 (n);
259 }
260 
toUint32(qsreal n)261 inline quint32 QScriptEnginePrivate::toUint32(qsreal n)
262 {
263     if (qIsNaN(n) || qIsInf(n) || (n == 0))
264         return 0;
265 
266     double sign = (n < 0) ? -1.0 : 1.0;
267     qsreal abs_n = fabs(n);
268 
269     n = ::fmod(sign * ::floor(abs_n), D32);
270 
271     if (n < 0)
272         n += D32;
273 
274     return quint32 (n);
275 }
276 
toUint16(qsreal n)277 inline quint16 QScriptEnginePrivate::toUint16(qsreal n)
278 {
279     if (qIsNaN(n) || qIsInf(n) || (n == 0))
280         return 0;
281 
282     double sign = (n < 0) ? -1.0 : 1.0;
283     qsreal abs_n = fabs(n);
284 
285     n = ::fmod(sign * ::floor(abs_n), D16);
286 
287     if (n < 0)
288         n += D16;
289 
290     return quint16 (n);
291 }
292 
abstractSyntaxTree()293 inline QScript::AST::Node *QScriptEnginePrivate::abstractSyntaxTree() const
294 {
295     return m_abstractSyntaxTree;
296 }
297 
nodePool()298 inline QScript::MemoryPool *QScriptEnginePrivate::nodePool()
299 {
300     return m_pool;
301 }
302 
setNodePool(QScript::MemoryPool * pool)303 inline void QScriptEnginePrivate::setNodePool(QScript::MemoryPool *pool)
304 {
305     m_pool = pool;
306 }
307 
lexer()308 inline QScript::Lexer *QScriptEnginePrivate::lexer()
309 {
310     return m_lexer;
311 }
312 
setLexer(QScript::Lexer * lexer)313 inline void QScriptEnginePrivate::setLexer(QScript::Lexer *lexer)
314 {
315     m_lexer = lexer;
316 }
317 
allocObject()318 inline QScriptObject *QScriptEnginePrivate::allocObject()
319 {
320     return objectAllocator(m_objectGeneration);
321 }
322 
currentContext()323 inline QScriptContextPrivate *QScriptEnginePrivate::currentContext() const
324 {
325     return m_context;
326 }
327 
pushContext()328 inline QScriptContextPrivate *QScriptEnginePrivate::pushContext()
329 {
330     QScriptContext *context = m_frameRepository.get();
331     QScriptContextPrivate *ctx_p = QScriptContextPrivate::get(context);
332     ctx_p->init(m_context);
333     m_context = ctx_p;
334 #ifndef Q_SCRIPT_NO_EVENT_NOTIFY
335     notifyContextPush();
336 #endif
337     return m_context;
338 }
339 
popContext()340 inline void QScriptEnginePrivate::popContext()
341 {
342     Q_ASSERT(m_context != 0);
343 #ifndef Q_SCRIPT_NO_EVENT_NOTIFY
344     notifyContextPop();
345 #endif
346     QScriptContextPrivate *context = m_context;
347     m_context = context->parentContext();
348     if (m_context) {
349         QScriptContextPrivate *p1 = m_context;
350         QScriptContextPrivate *p2 = context;
351         if ((p1->m_state != QScriptContext::ExceptionState)
352             || (p2->m_state == QScriptContext::ExceptionState)) {
353             // propagate the state
354             p1->m_result = p2->m_result;
355             p1->m_state = p2->m_state;
356             // only update errorLineNumber if there actually was an exception
357             if (p2->m_state == QScriptContext::ExceptionState) {
358                 if (p2->errorLineNumber != -1)
359                     p1->errorLineNumber = p2->errorLineNumber;
360                 else
361                     p1->errorLineNumber = p1->currentLine;
362             }
363         }
364     }
365     m_frameRepository.release(QScriptContextPrivate::get(context));
366 }
367 
maybeGC()368 inline void QScriptEnginePrivate::maybeGC()
369 {
370     if (objectAllocator.blocked())
371         return;
372 
373     bool do_string_gc = ((m_stringRepository.size() - m_oldStringRepositorySize) > 256)
374                         || (m_newAllocatedStringRepositoryChars > 0x800000);
375     do_string_gc |= ((m_tempStringRepository.size() - m_oldTempStringRepositorySize) > 1024)
376                     || (m_newAllocatedTempStringRepositoryChars > 0x800000);
377 
378     if (! do_string_gc && ! objectAllocator.poll())
379         return;
380 
381     maybeGC_helper(do_string_gc);
382 }
383 
adjustBytesAllocated(int bytes)384 inline void QScriptEnginePrivate::adjustBytesAllocated(int bytes)
385 {
386     objectAllocator.adjustBytesAllocated(bytes);
387 }
388 
blockGC(bool block)389 inline bool QScriptEnginePrivate::blockGC(bool block)
390 {
391     return objectAllocator.blockGC(block);
392 }
393 
markString(QScriptNameIdImpl * id,int)394 inline void QScriptEnginePrivate::markString(QScriptNameIdImpl *id, int /*generation*/)
395 {
396     id->used = true;
397 }
398 
createFunction(QScriptFunction * fun)399 inline QScriptValueImpl QScriptEnginePrivate::createFunction(QScriptFunction *fun)
400 {
401     QScriptValueImpl v;
402     newFunction(&v, fun);
403     return v;
404 }
405 
newArray(const QScript::Array & value)406 inline QScriptValueImpl QScriptEnginePrivate::newArray(const QScript::Array &value)
407 {
408     QScriptValueImpl v;
409     newArray(&v, value);
410     return v;
411 }
412 
newArray(uint length)413 inline QScriptValueImpl QScriptEnginePrivate::newArray(uint length)
414 {
415     QScriptValueImpl v;
416     QScript::Array a(this);
417     a.resize(length);
418     newArray(&v, a);
419     return v;
420 }
421 
registerClass(const QString & pname,int type)422 inline QScriptClassInfo *QScriptEnginePrivate::registerClass(const QString &pname, int type)
423 {
424     if (type == -1)
425         type = ++m_class_prev_id;
426 
427     QScriptClassInfo *oc = new QScriptClassInfo(this, QScriptClassInfo::Type(type), pname);
428     m_allocated_classes.append(oc);
429 
430     return oc;
431 }
432 
registerClass(const QString & name)433 inline QScriptClassInfo *QScriptEnginePrivate::registerClass(const QString &name)
434 {
435     return registerClass(name, -1);
436 }
437 
createFunction(QScriptInternalFunctionSignature fun,int length,QScriptClassInfo * classInfo,const QString & name)438 inline QScriptValueImpl QScriptEnginePrivate::createFunction(QScriptInternalFunctionSignature fun,
439                                        int length, QScriptClassInfo *classInfo, const QString &name)
440 {
441     return createFunction(new QScript::C2Function(fun, length, classInfo, name));
442 }
443 
newFunction(QScriptValueImpl * o,QScriptFunction * function)444 inline void QScriptEnginePrivate::newFunction(QScriptValueImpl *o, QScriptFunction *function)
445 {
446     QScriptValueImpl proto;
447     if (functionConstructor)
448         proto = functionConstructor->publicPrototype;
449     else {
450         // creating the Function prototype object
451         Q_ASSERT(objectConstructor);
452         proto = objectConstructor->publicPrototype;
453     }
454     newObject(o, proto, m_class_function);
455     o->setObjectData(function);
456 }
457 
newConstructor(QScriptValueImpl * ctor,QScriptFunction * function,QScriptValueImpl & proto)458 inline void QScriptEnginePrivate::newConstructor(QScriptValueImpl *ctor,
459                                           QScriptFunction *function,
460                                           QScriptValueImpl &proto)
461 {
462     newFunction(ctor, function);
463     ctor->setProperty(m_id_table.id_prototype, proto,
464                       QScriptValue::Undeletable
465                       | QScriptValue::ReadOnly
466                       | QScriptValue::SkipInEnumeration);
467     proto.setProperty(m_id_table.id_constructor, *ctor,
468                       QScriptValue::Undeletable
469                       | QScriptValue::SkipInEnumeration);
470 }
471 
newArguments(QScriptValueImpl * object,const QScriptValueImpl & activation,uint length,const QScriptValueImpl & callee)472 inline void QScriptEnginePrivate::newArguments(QScriptValueImpl *object,
473                                              const QScriptValueImpl &activation,
474                                              uint length,
475                                              const QScriptValueImpl &callee)
476 {
477     QScript::ArgumentsObjectData *data = new QScript::ArgumentsObjectData();
478     data->activation = activation;
479     data->length = length;
480     newObject(object, m_class_arguments);
481     object->setObjectData(data);
482     object->setProperty(m_id_table.id_callee, callee,
483                         QScriptValue::SkipInEnumeration);
484     object->setProperty(m_id_table.id_length, QScriptValueImpl(length),
485                         QScriptValue::SkipInEnumeration);
486 }
487 
convertToNativeFunction(const QScriptValueImpl & object)488 inline QScriptFunction *QScriptEnginePrivate::convertToNativeFunction(const QScriptValueImpl &object)
489 {
490     if (object.isFunction())
491         return static_cast<QScriptFunction*> (object.objectData());
492     return 0;
493 }
494 
toPublic(const QScriptValueImpl & value)495 inline QScriptValue QScriptEnginePrivate::toPublic(const QScriptValueImpl &value)
496 {
497     if (!value.isValid())
498         return QScriptValue();
499 
500     QScriptValuePrivate *p = registerValue(value);
501     QScriptValue v;
502     QScriptValuePrivate::init(v, p);
503     return v;
504 }
505 
toImpl(const QScriptValue & value)506 inline QScriptValueImpl QScriptEnginePrivate::toImpl(const QScriptValue &value)
507 {
508     QScriptValuePrivate *p = QScriptValuePrivate::get(value);
509     if (!p)
510         return QScriptValueImpl();
511     if (p->value.type() == QScript::LazyStringType)
512         return toImpl_helper(value);
513     return p->value;
514 }
515 
toImplList(const QScriptValueList & lst)516 inline QScriptValueImplList QScriptEnginePrivate::toImplList(const QScriptValueList &lst)
517 {
518     QScriptValueImplList result;
519     QScriptValueList::const_iterator it;
520     for (it = lst.constBegin(); it != lst.constEnd(); ++it)
521         result.append(toImpl(*it));
522     return result;
523 }
524 
toObject(const QScriptValueImpl & value)525 inline QScriptValueImpl QScriptEnginePrivate::toObject(const QScriptValueImpl &value)
526 {
527     if (value.isObject() || !value.isValid())
528         return value;
529     return toObject_helper(value);
530 }
531 
toPrimitive(const QScriptValueImpl & object,QScriptValueImpl::TypeHint hint)532 inline QScriptValueImpl QScriptEnginePrivate::toPrimitive(const QScriptValueImpl &object,
533                                                           QScriptValueImpl::TypeHint hint)
534 {
535     Q_ASSERT(object.isValid());
536 
537     if (! object.isObject())
538         return object;
539 
540     return toPrimitive_helper(object, hint);
541 }
542 
toDateTime(const QScriptValueImpl & value)543 inline QDateTime QScriptEnginePrivate::toDateTime(const QScriptValueImpl &value) const
544 {
545     return dateConstructor->toDateTime(value);
546 }
547 
newArray(QScriptValueImpl * object,const QScript::Array & value)548 inline void QScriptEnginePrivate::newArray(QScriptValueImpl *object, const QScript::Array &value)
549 {
550     arrayConstructor->newArray(object, value);
551 }
552 
newObject(QScriptValueImpl * o,const QScriptValueImpl & proto,QScriptClassInfo * oc)553 inline void QScriptEnginePrivate::newObject(QScriptValueImpl *o, const QScriptValueImpl &proto,
554                       QScriptClassInfo *oc)
555 {
556     Q_ASSERT(o != 0);
557 
558     QScriptObject *od = allocObject();
559     od->reset();
560     od->m_id = ++m_next_object_id;
561     if (proto.isValid())
562         od->m_prototype = proto;
563     else {
564         Q_ASSERT(objectConstructor);
565         od->m_prototype = objectConstructor->publicPrototype;
566     }
567 
568     o->m_type = QScript::ObjectType;
569     od->m_class = (oc ? oc : m_class_object);
570     o->m_object_value = od;
571 }
572 
newObject(QScriptValueImpl * o,QScriptClassInfo * oc)573 inline void QScriptEnginePrivate::newObject(QScriptValueImpl *o, QScriptClassInfo *oc)
574 {
575     newObject(o, objectConstructor->publicPrototype, oc);
576 }
577 
newObject()578 inline QScriptValueImpl QScriptEnginePrivate::newObject()
579 {
580     QScriptValueImpl v;
581     newObject(&v);
582     return v;
583 }
584 
newVariant(QScriptValueImpl * out,const QVariant & value,bool setDefaultPrototype)585 inline void QScriptEnginePrivate::newVariant(QScriptValueImpl *out,
586                                              const QVariant &value,
587                                              bool setDefaultPrototype)
588 {
589     Q_ASSERT(variantConstructor != 0);
590     variantConstructor->newVariant(out, value);
591     if (setDefaultPrototype) {
592         QScriptValueImpl proto = defaultPrototype(value.userType());
593         if (proto.isValid())
594             out->setPrototype(proto);
595     }
596 }
597 
598 #ifndef QT_NO_QOBJECT
599 #  ifndef Q_SCRIPT_NO_QMETAOBJECT_CACHE
cachedMetaObject(const QMetaObject * meta)600 inline QScriptMetaObject *QScriptEnginePrivate::cachedMetaObject(const QMetaObject *meta)
601 {
602     QScriptMetaObject *value = m_cachedMetaObjects.value(meta);
603     if (!value) {
604         value = new QScriptMetaObject;
605         m_cachedMetaObjects.insert(meta, value);
606     }
607     return value;
608 }
609 #  endif
610 #endif // !QT_NO_QOBJECT
611 
nameId(const QString & str,bool persistent)612 inline QScriptNameIdImpl *QScriptEnginePrivate::nameId(const QString &str, bool persistent)
613 {
614     QScriptNameIdImpl *entry = toStringEntry(str);
615     if (! entry)
616         entry = insertStringEntry(str);
617 
618     Q_ASSERT(entry->unique);
619 
620     if (persistent)
621         entry->persistent = true;
622 
623     return entry;
624 }
625 
intern(const QChar * u,int s)626 inline QScriptNameIdImpl *QScriptEnginePrivate::intern(const QChar *u, int s)
627 {
628     QString tmp(u, s);
629     return nameId(tmp, /*persistent=*/ true);
630 }
631 
valueFromVariant(const QVariant & v)632 inline QScriptValueImpl QScriptEnginePrivate::valueFromVariant(const QVariant &v)
633 {
634     QScriptValueImpl result = create(v.userType(), v.data());
635     Q_ASSERT(result.isValid());
636     return result;
637 }
638 
undefinedValue()639 inline QScriptValueImpl QScriptEnginePrivate::undefinedValue()
640 {
641     return m_undefinedValue;
642 }
643 
nullValue()644 inline QScriptValueImpl QScriptEnginePrivate::nullValue()
645 {
646     return m_nullValue;
647 }
648 
defaultPrototype(int metaTypeId)649 inline QScriptValueImpl QScriptEnginePrivate::defaultPrototype(int metaTypeId) const
650 {
651     QScriptCustomTypeInfo info = m_customTypes.value(metaTypeId);
652     return info.prototype;
653 }
654 
setDefaultPrototype(int metaTypeId,const QScriptValueImpl & prototype)655 inline void QScriptEnginePrivate::setDefaultPrototype(int metaTypeId, const QScriptValueImpl &prototype)
656 {
657     QScriptCustomTypeInfo info = m_customTypes.value(metaTypeId);
658     info.prototype = prototype;
659     m_customTypes.insert(metaTypeId, info);
660 }
661 
_q_scriptHash(const QString & key)662 inline uint _q_scriptHash(const QString &key)
663 {
664     const QChar *p = key.unicode();
665     int n = qMin(key.size(), 128);
666     uint h = key.size();
667     uint g;
668 
669     while (n--) {
670         h = (h << 4) + (*p++).unicode();
671         if ((g = (h & 0xf0000000)) != 0)
672             h ^= g >> 23;
673         h &= ~g;
674     }
675     return h;
676 }
677 
toStringEntry(const QString & s)678 inline QScriptNameIdImpl *QScriptEnginePrivate::toStringEntry(const QString &s)
679 {
680     uint h = _q_scriptHash(s) % m_string_hash_size;
681 
682     for (QScriptNameIdImpl *entry = m_string_hash_base[h]; entry && entry->h == h; entry = entry->next) {
683         if (entry->s == s)
684             return entry;
685     }
686 
687     return 0;
688 }
689 
lessThan(const QScriptValueImpl & lhs,const QScriptValueImpl & rhs)690 inline bool QScriptEnginePrivate::lessThan(const QScriptValueImpl &lhs, const QScriptValueImpl &rhs)
691 {
692     return QScriptContextPrivate::lt_cmp(lhs, rhs);
693 }
694 
equals(const QScriptValueImpl & lhs,const QScriptValueImpl & rhs)695 inline bool QScriptEnginePrivate::equals(const QScriptValueImpl &lhs, const QScriptValueImpl &rhs)
696 {
697     return QScriptContextPrivate::eq_cmp(lhs, rhs);
698 }
699 
strictlyEquals(const QScriptValueImpl & lhs,const QScriptValueImpl & rhs)700 inline bool QScriptEnginePrivate::strictlyEquals(const QScriptValueImpl &lhs, const QScriptValueImpl &rhs)
701 {
702     return QScriptContextPrivate::strict_eq_cmp(lhs, rhs);
703 }
704 
unregisterValue(QScriptValuePrivate * p)705 inline void QScriptEnginePrivate::unregisterValue(QScriptValuePrivate *p)
706 {
707     QScriptValueImpl &v = p->value;
708     Q_ASSERT(v.isValid());
709     if (v.isString()) {
710         QScriptNameIdImpl *id = v.stringValue();
711         m_stringHandles.remove(id);
712     } else if (v.isObject()) {
713         QScriptObject *instance = v.objectValue();
714         m_objectHandles.remove(instance);
715     } else {
716         int i = m_otherHandles.indexOf(p);
717         Q_ASSERT(i != -1);
718         m_otherHandles.remove(i);
719     }
720     m_handleRepository.release(p);
721 }
722 
globalObject()723 inline QScriptValueImpl QScriptEnginePrivate::globalObject() const
724 {
725     return m_globalObject;
726 }
727 
hasUncaughtException()728 inline bool QScriptEnginePrivate::hasUncaughtException() const
729 {
730     return (currentContext()->state() == QScriptContext::ExceptionState);
731 }
732 
uncaughtException()733 inline QScriptValueImpl QScriptEnginePrivate::uncaughtException() const
734 {
735     if (!hasUncaughtException())
736         return QScriptValueImpl();
737     return currentContext()->returnValue();
738 }
739 
maybeProcessEvents()740 inline void QScriptEnginePrivate::maybeProcessEvents()
741 {
742     if (m_processEventsInterval > 0 && ++m_processEventIncr > 512) {
743         m_processEventIncr = 0;
744         processEvents();
745     }
746 }
747 
shouldAbort()748 inline bool QScriptEnginePrivate::shouldAbort() const
749 {
750     return m_abort;
751 }
752 
resetAbortFlag()753 inline void QScriptEnginePrivate::resetAbortFlag()
754 {
755     m_abort = false;
756 }
757 
758 #ifndef Q_SCRIPT_NO_EVENT_NOTIFY
759 
shouldNotify()760 inline bool QScriptEnginePrivate::shouldNotify() const
761 {
762     return m_agent != 0;
763 }
764 
notifyScriptLoad(qint64 id,const QString & program,const QString & fileName,int lineNumber)765 inline void QScriptEnginePrivate::notifyScriptLoad(
766     qint64 id, const QString &program,
767     const QString &fileName, int lineNumber)
768 {
769     if (shouldNotify())
770         notifyScriptLoad_helper(id, program, fileName, lineNumber);
771 }
772 
notifyScriptUnload(qint64 id)773 inline void QScriptEnginePrivate::notifyScriptUnload(qint64 id)
774 {
775     if (shouldNotify())
776         notifyScriptUnload_helper(id);
777 }
778 
notifyPositionChange(QScriptContextPrivate * ctx)779 inline void QScriptEnginePrivate::notifyPositionChange(QScriptContextPrivate *ctx)
780 {
781     Q_ASSERT(m_agent != 0);
782     notifyPositionChange_helper(ctx);
783 }
784 
notifyContextPush()785 inline void QScriptEnginePrivate::notifyContextPush()
786 {
787     if (shouldNotify())
788         notifyContextPush_helper();
789 }
790 
notifyContextPop()791 inline void QScriptEnginePrivate::notifyContextPop()
792 {
793     if (shouldNotify())
794         notifyContextPop_helper();
795 }
796 
notifyFunctionEntry(QScriptContextPrivate * ctx)797 inline void QScriptEnginePrivate::notifyFunctionEntry(QScriptContextPrivate *ctx)
798 {
799     if (shouldNotify())
800         notifyFunctionEntry_helper(ctx);
801 }
802 
notifyFunctionExit(QScriptContextPrivate * ctx)803 inline void QScriptEnginePrivate::notifyFunctionExit(QScriptContextPrivate *ctx)
804 {
805     if (shouldNotify())
806         notifyFunctionExit_helper(ctx);
807 }
808 
notifyException(QScriptContextPrivate * ctx)809 inline void QScriptEnginePrivate::notifyException(QScriptContextPrivate *ctx)
810 {
811     if (shouldNotify())
812         notifyException_helper(ctx);
813 }
814 
notifyExceptionCatch(QScriptContextPrivate * ctx)815 inline void QScriptEnginePrivate::notifyExceptionCatch(QScriptContextPrivate *ctx)
816 {
817     if (shouldNotify())
818         notifyExceptionCatch_helper(ctx);
819 }
820 
821 #endif // Q_SCRIPT_NO_EVENT_NOTIFY
822 
823 QT_END_NAMESPACE
824 
825 
826 #endif
827