]> git.saurik.com Git - apple/javascriptcore.git/blame - qt/api/qscriptvalue_p.h
JavaScriptCore-721.26.tar.gz
[apple/javascriptcore.git] / qt / api / qscriptvalue_p.h
CommitLineData
f9bf01c6
A
1/*
2 Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18*/
19
20#ifndef qscriptvalue_p_h
21#define qscriptvalue_p_h
22
23#include "qscriptconverter_p.h"
24#include "qscriptengine_p.h"
25#include "qscriptvalue.h"
26#include <JavaScriptCore/JavaScript.h>
4e4e5a6f
A
27#include <JavaScriptCore/JSRetainPtr.h>
28#include <QtCore/qmath.h>
29#include <QtCore/qnumeric.h>
f9bf01c6
A
30#include <QtCore/qshareddata.h>
31#include <QtCore/qvarlengtharray.h>
32
33class QScriptEngine;
34class QScriptValue;
35
36/*
37 \internal
38 \class QScriptValuePrivate
39
40 Implementation of QScriptValue.
41 The implementation is based on a state machine. The states names are included in
4e4e5a6f 42 QScriptValuePrivate::State. Each method should check for the current state and then perform a
f9bf01c6
A
43 correct action.
44
4e4e5a6f 45 State:
f9bf01c6
A
46 Invalid -> QSVP is invalid, no assumptions should be made about class members (apart from m_value).
47 CString -> QSVP is created from QString or const char* and no JSC engine has been associated yet.
48 Current value is kept in m_string,
49 CNumber -> QSVP is created from int, uint, double... and no JSC engine has been bind yet. Current
50 value is kept in m_number
51 CBool -> QSVP is created from bool and no JSC engine has been associated yet. Current value is kept
52 in m_number
53 CSpecial -> QSVP is Undefined or Null, but a JSC engine hasn't been associated yet, current value
54 is kept in m_number (cast of QScriptValue::SpecialValue)
55 JSValue -> QSVP is associated with engine, but there is no information about real type, the state
56 have really short live cycle. Normally it is created as a function call result.
4e4e5a6f 57 JSPrimitive -> QSVP is associated with engine, and it is sure that it isn't a JavaScript object.
f9bf01c6
A
58 JSObject -> QSVP is associated with engine, and it is sure that it is a JavaScript object.
59
60 Each state keep all necessary information to invoke all methods, if not it should be changed to
61 a proper state. Changed state shouldn't be reverted.
62*/
63
64class QScriptValuePrivate : public QSharedData {
65public:
66 inline static QScriptValuePrivate* get(const QScriptValue& q);
67 inline static QScriptValue get(const QScriptValuePrivate* d);
68 inline static QScriptValue get(QScriptValuePrivate* d);
69
70 inline ~QScriptValuePrivate();
71
72 inline QScriptValuePrivate();
73 inline QScriptValuePrivate(const QString& string);
74 inline QScriptValuePrivate(bool value);
75 inline QScriptValuePrivate(int number);
76 inline QScriptValuePrivate(uint number);
77 inline QScriptValuePrivate(qsreal number);
78 inline QScriptValuePrivate(QScriptValue::SpecialValue value);
79
4e4e5a6f
A
80 inline QScriptValuePrivate(const QScriptEnginePrivate* engine, bool value);
81 inline QScriptValuePrivate(const QScriptEnginePrivate* engine, int value);
82 inline QScriptValuePrivate(const QScriptEnginePrivate* engine, uint value);
83 inline QScriptValuePrivate(const QScriptEnginePrivate* engine, qsreal value);
84 inline QScriptValuePrivate(const QScriptEnginePrivate* engine, const QString& value);
85 inline QScriptValuePrivate(const QScriptEnginePrivate* engine, QScriptValue::SpecialValue value);
f9bf01c6
A
86
87 inline QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value);
88 inline QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value, JSObjectRef object);
89
90 inline bool isValid() const;
91 inline bool isBool();
92 inline bool isNumber();
93 inline bool isNull();
94 inline bool isString();
95 inline bool isUndefined();
96 inline bool isError();
97 inline bool isObject();
98 inline bool isFunction();
99
100 inline QString toString() const;
101 inline qsreal toNumber() const;
102 inline bool toBool() const;
103 inline qsreal toInteger() const;
104 inline qint32 toInt32() const;
105 inline quint32 toUInt32() const;
106 inline quint16 toUInt16() const;
107
108 inline bool equals(QScriptValuePrivate* other);
109 inline bool strictlyEquals(const QScriptValuePrivate* other) const;
110 inline bool assignEngine(QScriptEnginePrivate* engine);
111
112 inline QScriptValuePrivate* call(const QScriptValuePrivate* , const QScriptValueList& args);
113
114 inline JSGlobalContextRef context() const;
115 inline JSValueRef value() const;
116 inline JSObjectRef object() const;
117 inline QScriptEnginePrivate* engine() const;
118
119private:
120 // Please, update class documentation when you change the enum.
4e4e5a6f 121 enum State {
f9bf01c6
A
122 Invalid = 0,
123 CString = 0x1000,
124 CNumber,
125 CBool,
126 CSpecial,
127 JSValue = 0x2000, // JS values are equal or higher then this value.
4e4e5a6f 128 JSPrimitive,
f9bf01c6
A
129 JSObject
130 } m_state;
131 QScriptEnginePtr m_engine;
132 QString m_string;
133 qsreal m_number;
134 JSValueRef m_value;
135 JSObjectRef m_object;
136
137 inline void setValue(JSValueRef);
138
139 inline bool inherits(const char*);
4e4e5a6f 140 inline State refinedJSValue();
f9bf01c6
A
141
142 inline bool isJSBased() const;
143 inline bool isNumberBased() const;
144 inline bool isStringBased() const;
145};
146
147QScriptValuePrivate* QScriptValuePrivate::get(const QScriptValue& q) { return q.d_ptr.data(); }
148
149QScriptValue QScriptValuePrivate::get(const QScriptValuePrivate* d)
150{
151 return QScriptValue(const_cast<QScriptValuePrivate*>(d));
152}
153
154QScriptValue QScriptValuePrivate::get(QScriptValuePrivate* d)
155{
156 return QScriptValue(d);
157}
158
159QScriptValuePrivate::~QScriptValuePrivate()
160{
161 if (m_value)
162 JSValueUnprotect(context(), m_value);
163}
164
165QScriptValuePrivate::QScriptValuePrivate()
166 : m_state(Invalid)
167 , m_value(0)
168{
169}
170
171QScriptValuePrivate::QScriptValuePrivate(const QString& string)
172 : m_state(CString)
173 , m_string(string)
174 , m_value(0)
175{
176}
177
178QScriptValuePrivate::QScriptValuePrivate(bool value)
179 : m_state(CBool)
180 , m_number(value)
181 , m_value(0)
182{
183}
184
185QScriptValuePrivate::QScriptValuePrivate(int number)
186 : m_state(CNumber)
187 , m_number(number)
188 , m_value(0)
189{
190}
191
192QScriptValuePrivate::QScriptValuePrivate(uint number)
193 : m_state(CNumber)
194 , m_number(number)
195 , m_value(0)
196{
197}
198
199QScriptValuePrivate::QScriptValuePrivate(qsreal number)
200 : m_state(CNumber)
201 , m_number(number)
202 , m_value(0)
203{
204}
205
206QScriptValuePrivate::QScriptValuePrivate(QScriptValue::SpecialValue value)
207 : m_state(CSpecial)
208 , m_number(value)
209 , m_value(0)
210{
211}
212
4e4e5a6f
A
213QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, bool value)
214 : m_state(JSPrimitive)
215 , m_engine(const_cast<QScriptEnginePrivate*>(engine))
216 , m_value(engine->makeJSValue(value))
f9bf01c6 217{
4e4e5a6f
A
218 Q_ASSERT(engine);
219 JSValueProtect(context(), m_value);
f9bf01c6
A
220}
221
4e4e5a6f
A
222QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, int value)
223 : m_state(JSPrimitive)
224 , m_engine(const_cast<QScriptEnginePrivate*>(engine))
225 , m_value(m_engine->makeJSValue(value))
f9bf01c6 226{
4e4e5a6f
A
227 Q_ASSERT(engine);
228 JSValueProtect(context(), m_value);
f9bf01c6
A
229}
230
4e4e5a6f
A
231QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, uint value)
232 : m_state(JSPrimitive)
233 , m_engine(const_cast<QScriptEnginePrivate*>(engine))
234 , m_value(m_engine->makeJSValue(value))
f9bf01c6 235{
4e4e5a6f
A
236 Q_ASSERT(engine);
237 JSValueProtect(context(), m_value);
f9bf01c6
A
238}
239
4e4e5a6f
A
240QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, qsreal value)
241 : m_state(JSPrimitive)
242 , m_engine(const_cast<QScriptEnginePrivate*>(engine))
243 , m_value(m_engine->makeJSValue(value))
f9bf01c6 244{
4e4e5a6f
A
245 Q_ASSERT(engine);
246 JSValueProtect(context(), m_value);
f9bf01c6
A
247}
248
4e4e5a6f
A
249QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, const QString& value)
250 : m_state(JSPrimitive)
251 , m_engine(const_cast<QScriptEnginePrivate*>(engine))
252 , m_value(m_engine->makeJSValue(value))
f9bf01c6 253{
4e4e5a6f
A
254 Q_ASSERT(engine);
255 JSValueProtect(context(), m_value);
f9bf01c6
A
256}
257
4e4e5a6f
A
258QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, QScriptValue::SpecialValue value)
259 : m_state(JSPrimitive)
260 , m_engine(const_cast<QScriptEnginePrivate*>(engine))
261 , m_value(m_engine->makeJSValue(value))
f9bf01c6 262{
4e4e5a6f
A
263 Q_ASSERT(engine);
264 JSValueProtect(context(), m_value);
f9bf01c6
A
265}
266
267QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value)
268 : m_state(JSValue)
269 , m_engine(const_cast<QScriptEnginePrivate*>(engine))
270 , m_value(value)
271{
272 Q_ASSERT(engine);
4e4e5a6f 273 Q_ASSERT(value);
f9bf01c6
A
274 JSValueProtect(context(), m_value);
275}
276
277QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value, JSObjectRef object)
278 : m_state(JSObject)
279 , m_engine(const_cast<QScriptEnginePrivate*>(engine))
280 , m_value(value)
281 , m_object(object)
282{
283 Q_ASSERT(engine);
4e4e5a6f
A
284 Q_ASSERT(value);
285 Q_ASSERT(object);
f9bf01c6
A
286 JSValueProtect(context(), m_value);
287}
288
289bool QScriptValuePrivate::isValid() const { return m_state != Invalid; }
290
291bool QScriptValuePrivate::isBool()
292{
293 switch (m_state) {
294 case CBool:
295 return true;
296 case JSValue:
4e4e5a6f 297 if (refinedJSValue() != JSPrimitive)
f9bf01c6
A
298 return false;
299 // Fall-through.
4e4e5a6f 300 case JSPrimitive:
f9bf01c6
A
301 return JSValueIsBoolean(context(), value());
302 default:
303 return false;
304 }
305}
306
307bool QScriptValuePrivate::isNumber()
308{
309 switch (m_state) {
310 case CNumber:
4e4e5a6f 311 return true;
f9bf01c6 312 case JSValue:
4e4e5a6f 313 if (refinedJSValue() != JSPrimitive)
f9bf01c6
A
314 return false;
315 // Fall-through.
4e4e5a6f 316 case JSPrimitive:
f9bf01c6
A
317 return JSValueIsNumber(context(), value());
318 default:
319 return false;
320 }
321}
322
323bool QScriptValuePrivate::isNull()
324{
325 switch (m_state) {
326 case CSpecial:
327 return m_number == static_cast<int>(QScriptValue::NullValue);
328 case JSValue:
4e4e5a6f 329 if (refinedJSValue() != JSPrimitive)
f9bf01c6
A
330 return false;
331 // Fall-through.
4e4e5a6f 332 case JSPrimitive:
f9bf01c6
A
333 return JSValueIsNull(context(), value());
334 default:
335 return false;
336 }
337}
338
339bool QScriptValuePrivate::isString()
340{
341 switch (m_state) {
342 case CString:
343 return true;
344 case JSValue:
4e4e5a6f 345 if (refinedJSValue() != JSPrimitive)
f9bf01c6
A
346 return false;
347 // Fall-through.
4e4e5a6f 348 case JSPrimitive:
f9bf01c6
A
349 return JSValueIsString(context(), value());
350 default:
351 return false;
352 }
353}
354
355bool QScriptValuePrivate::isUndefined()
356{
357 switch (m_state) {
358 case CSpecial:
359 return m_number == static_cast<int>(QScriptValue::UndefinedValue);
360 case JSValue:
4e4e5a6f 361 if (refinedJSValue() != JSPrimitive)
f9bf01c6
A
362 return false;
363 // Fall-through.
4e4e5a6f 364 case JSPrimitive:
f9bf01c6
A
365 return JSValueIsUndefined(context(), value());
366 default:
367 return false;
368 }
369}
370
371bool QScriptValuePrivate::isError()
372{
373 switch (m_state) {
374 case JSValue:
4e4e5a6f 375 if (refinedJSValue() != JSObject)
f9bf01c6
A
376 return false;
377 // Fall-through.
378 case JSObject:
379 return inherits("Error");
380 default:
381 return false;
382 }
383}
384
385bool QScriptValuePrivate::isObject()
386{
387 switch (m_state) {
f9bf01c6 388 case JSValue:
4e4e5a6f
A
389 return refinedJSValue() == JSObject;
390 case JSObject:
f9bf01c6 391 return true;
4e4e5a6f 392
f9bf01c6
A
393 default:
394 return false;
395 }
396}
397
398bool QScriptValuePrivate::isFunction()
399{
400 switch (m_state) {
401 case JSValue:
4e4e5a6f 402 if (refinedJSValue() != JSObject)
f9bf01c6 403 return false;
f9bf01c6
A
404 // Fall-through.
405 case JSObject:
406 return JSObjectIsFunction(context(), object());
407 default:
408 return false;
409 }
410}
411
412QString QScriptValuePrivate::toString() const
413{
414 switch (m_state) {
415 case Invalid:
416 return QString();
417 case CBool:
418 return m_number ? QString::fromLatin1("true") : QString::fromLatin1("false");
419 case CString:
420 return m_string;
421 case CNumber:
4e4e5a6f 422 return QScriptConverter::toString(m_number);
f9bf01c6
A
423 case CSpecial:
424 return m_number == QScriptValue::NullValue ? QString::fromLatin1("null") : QString::fromLatin1("undefined");
425 case JSValue:
4e4e5a6f 426 case JSPrimitive:
f9bf01c6 427 case JSObject:
4e4e5a6f
A
428 JSRetainPtr<JSStringRef> ptr(Adopt, JSValueToStringCopy(context(), value(), /* exception */ 0));
429 return QScriptConverter::toString(ptr.get());
f9bf01c6
A
430 }
431
432 Q_ASSERT_X(false, "toString()", "Not all states are included in the previous switch statement.");
433 return QString(); // Avoid compiler warning.
434}
435
436qsreal QScriptValuePrivate::toNumber() const
437{
f9bf01c6
A
438 switch (m_state) {
439 case JSValue:
4e4e5a6f 440 case JSPrimitive:
f9bf01c6
A
441 case JSObject:
442 return JSValueToNumber(context(), value(), /* exception */ 0);
443 case CNumber:
f9bf01c6 444 return m_number;
4e4e5a6f
A
445 case CBool:
446 return m_number ? 1 : 0;
f9bf01c6 447 case Invalid:
4e4e5a6f 448 return 0;
f9bf01c6 449 case CSpecial:
4e4e5a6f 450 return m_number == QScriptValue::NullValue ? 0 : qQNaN();
f9bf01c6 451 case CString:
4e4e5a6f
A
452 bool ok;
453 qsreal result = m_string.toDouble(&ok);
454 if (ok)
455 return result;
456 result = m_string.toInt(&ok, 0); // Try other bases.
457 if (ok)
458 return result;
459 if (m_string == "Infinity" || m_string == "-Infinity")
460 return qInf();
461 return m_string.length() ? qQNaN() : 0;
f9bf01c6
A
462 }
463
464 Q_ASSERT_X(false, "toNumber()", "Not all states are included in the previous switch statement.");
465 return 0; // Avoid compiler warning.
466}
467
468bool QScriptValuePrivate::toBool() const
469{
470 switch (m_state) {
471 case JSValue:
4e4e5a6f 472 case JSPrimitive:
f9bf01c6 473 return JSValueToBoolean(context(), value());
4e4e5a6f
A
474 case JSObject:
475 return true;
f9bf01c6 476 case CNumber:
4e4e5a6f 477 return !(qIsNaN(m_number) || !m_number);
f9bf01c6
A
478 case CBool:
479 return m_number;
480 case Invalid:
481 case CSpecial:
482 return false;
483 case CString:
4e4e5a6f 484 return m_string.length();
f9bf01c6
A
485 }
486
487 Q_ASSERT_X(false, "toBool()", "Not all states are included in the previous switch statement.");
488 return false; // Avoid compiler warning.
489}
490
491qsreal QScriptValuePrivate::toInteger() const
492{
4e4e5a6f
A
493 qsreal result = toNumber();
494 if (qIsNaN(result))
495 return 0;
496 if (qIsInf(result))
497 return result;
498 return (result > 0) ? qFloor(result) : -1 * qFloor(-result);
f9bf01c6
A
499}
500
501qint32 QScriptValuePrivate::toInt32() const
502{
4e4e5a6f
A
503 qsreal result = toInteger();
504 // Orginaly it should look like that (result == 0 || qIsInf(result) || qIsNaN(result)), but
505 // some of these operation are invoked in toInteger subcall.
506 if (qIsInf(result))
507 return 0;
508 return result;
f9bf01c6
A
509}
510
511quint32 QScriptValuePrivate::toUInt32() const
512{
4e4e5a6f
A
513 qsreal result = toInteger();
514 // Orginaly it should look like that (result == 0 || qIsInf(result) || qIsNaN(result)), but
515 // some of these operation are invoked in toInteger subcall.
516 if (qIsInf(result))
517 return 0;
518 return result;
f9bf01c6
A
519}
520
521quint16 QScriptValuePrivate::toUInt16() const
522{
4e4e5a6f 523 return toInt32();
f9bf01c6
A
524}
525
526
527bool QScriptValuePrivate::equals(QScriptValuePrivate* other)
528{
529 if (!isValid() || !other->isValid())
530 return false;
531
532 if ((m_state == other->m_state) && !isJSBased()) {
533 if (isNumberBased())
534 return m_number == other->m_number;
535 return m_string == other->m_string;
536 }
537
538 if (isJSBased() && !other->isJSBased()) {
539 if (!other->assignEngine(engine())) {
540 qWarning("equals(): Cannot compare to a value created in a different engine");
541 return false;
542 }
543 } else if (!isJSBased() && other->isJSBased()) {
544 if (!other->assignEngine(other->engine())) {
545 qWarning("equals(): Cannot compare to a value created in a different engine");
546 return false;
547 }
548 }
549
550 return JSValueIsEqual(context(), value(), other->value(), /* exception */ 0);
551}
552
553bool QScriptValuePrivate::strictlyEquals(const QScriptValuePrivate* other) const
554{
555 if (m_state != other->m_state)
556 return false;
557 if (isJSBased()) {
558 if (other->engine() != engine()) {
559 qWarning("strictlyEquals(): Cannot compare to a value created in a different engine");
560 return false;
561 }
562 return JSValueIsStrictEqual(context(), value(), other->value());
563 }
564 if (isStringBased())
565 return m_string == other->m_string;
566 if (isNumberBased())
567 return m_number == other->m_number;
568
569 return false; // Invalid state.
570}
571
572/*!
573 Tries to assign \a engine to this value. Returns true on success; otherwise returns false.
574*/
575bool QScriptValuePrivate::assignEngine(QScriptEnginePrivate* engine)
576{
577 JSValueRef value;
578 switch (m_state) {
579 case CBool:
580 value = engine->makeJSValue(static_cast<bool>(m_number));
581 break;
582 case CString:
583 value = engine->makeJSValue(m_string);
584 break;
585 case CNumber:
586 value = engine->makeJSValue(m_number);
587 break;
588 case CSpecial:
589 value = engine->makeJSValue(static_cast<QScriptValue::SpecialValue>(m_number));
590 break;
591 default:
592 if (!isJSBased())
593 Q_ASSERT_X(!isJSBased(), "assignEngine()", "Not all states are included in the previous switch statement.");
594 else
595 qWarning("JSValue can't be rassigned to an another engine.");
596 return false;
597 }
598 m_engine = engine;
4e4e5a6f 599 m_state = JSPrimitive;
f9bf01c6
A
600 setValue(value);
601 return true;
602}
603
604QScriptValuePrivate* QScriptValuePrivate::call(const QScriptValuePrivate*, const QScriptValueList& args)
605{
606 switch (m_state) {
607 case JSValue:
4e4e5a6f 608 if (refinedJSValue() != JSObject)
f9bf01c6 609 return new QScriptValuePrivate;
f9bf01c6
A
610 // Fall-through.
611 case JSObject:
612 {
613 // Convert all arguments and bind to the engine.
614 int argc = args.size();
615 QVarLengthArray<JSValueRef, 8> argv(argc);
616 QScriptValueList::const_iterator i = args.constBegin();
617 for (int j = 0; i != args.constEnd(); j++, i++) {
618 QScriptValuePrivate* value = QScriptValuePrivate::get(*i);
619 if (!value->assignEngine(engine())) {
620 qWarning("QScriptValue::call() failed: cannot call function with values created in a different engine");
621 return new QScriptValuePrivate;
622 }
623 argv[j] = value->value();
624 }
625
626 // Make the call
627 JSValueRef exception = 0;
628 JSValueRef result = JSObjectCallAsFunction(context(), object(), /* thisObject */ 0, argc, argv.constData(), &exception);
629 if (!result && exception)
630 return new QScriptValuePrivate(engine(), exception);
631 if (result && !exception)
632 return new QScriptValuePrivate(engine(), result);
633 }
634 // this QSV is not a function <-- !result && !exception. Fall-through.
635 default:
636 return new QScriptValuePrivate;
637 }
638}
639
640QScriptEnginePrivate* QScriptValuePrivate::engine() const
641{
642 // As long as m_engine is an autoinitializated pointer we can safely return it without
643 // checking current state.
644 return m_engine.data();
645}
646
647JSGlobalContextRef QScriptValuePrivate::context() const
648{
649 Q_ASSERT(isJSBased());
650 return m_engine->context();
651}
652
653JSValueRef QScriptValuePrivate::value() const
654{
655 Q_ASSERT(isJSBased());
656 return m_value;
657}
658
659JSObjectRef QScriptValuePrivate::object() const
660{
661 Q_ASSERT(m_state == JSObject);
662 return m_object;
663}
664
665void QScriptValuePrivate::setValue(JSValueRef value)
666{
667 if (m_value)
668 JSValueUnprotect(context(), m_value);
669 if (value)
670 JSValueProtect(context(), value);
671 m_value = value;
672}
673
674/*!
675 \internal
676 Returns true if QSV is created from constructor with the given \a name, it has to be a
677 built-in type.
678*/
679bool QScriptValuePrivate::inherits(const char* name)
680{
681 Q_ASSERT(isJSBased());
682 JSObjectRef globalObject = JSContextGetGlobalObject(context());
4e4e5a6f
A
683 JSStringRef errorAttrName = QScriptConverter::toString(name);
684 JSValueRef error = JSObjectGetProperty(context(), globalObject, errorAttrName, /* exception */ 0);
685 JSStringRelease(errorAttrName);
f9bf01c6
A
686 return JSValueIsInstanceOfConstructor(context(), value(), JSValueToObject(context(), error, /* exception */ 0), /* exception */ 0);
687}
688
4e4e5a6f
A
689/*!
690 \internal
691 Refines the state of this QScriptValuePrivate. Returns the new state.
692*/
693QScriptValuePrivate::State QScriptValuePrivate::refinedJSValue()
694{
695 Q_ASSERT(m_state == JSValue);
696 if (!JSValueIsObject(context(), value())) {
697 m_state = JSPrimitive;
698 } else {
699 m_state = JSObject;
700 // We are sure that value is an JSObject, so we can const_cast safely without
701 // calling JSC C API (JSValueToObject(context(), value(), /* exceptions */ 0)).
702 m_object = const_cast<JSObjectRef>(m_value);
703 }
704 return m_state;
705}
706
f9bf01c6
A
707/*!
708 \internal
709 Returns true if QSV have an engine associated.
710*/
711bool QScriptValuePrivate::isJSBased() const { return m_state >= JSValue; }
712
713/*!
714 \internal
715 Returns true if current value of QSV is placed in m_number.
716*/
717bool QScriptValuePrivate::isNumberBased() const { return !isJSBased() && !isStringBased() && m_state != Invalid; }
718
719/*!
720 \internal
721 Returns true if current value of QSV is placed in m_string.
722*/
723bool QScriptValuePrivate::isStringBased() const { return m_state == CString; }
724
725#endif // qscriptvalue_p_h