Changeset 846 for trunk/src/script/api/qscriptengine.cpp
- Timestamp:
- May 5, 2011, 5:36:53 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/vendor/nokia/qt/4.7.2 (added) merged: 845 /branches/vendor/nokia/qt/current merged: 844 /branches/vendor/nokia/qt/4.6.3 removed
- Property svn:mergeinfo changed
-
trunk/src/script/api/qscriptengine.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 25 25 #include "qscriptengine.h" 26 26 #include "qscriptsyntaxchecker_p.h" 27 #include "qnumeric.h"28 27 29 28 #include "qscriptengine_p.h" … … 42 41 #include <QtCore/qmetaobject.h> 43 42 43 #include <math.h> 44 44 45 #include "CodeBlock.h" 45 46 #include "Error.h" 46 #include "JSArray.h"47 #include "JSLock.h"48 47 #include "Interpreter.h" 49 #include "DateConstructor.h" 50 #include "RegExpConstructor.h" 51 48 49 #include "ExceptionHelpers.h" 52 50 #include "PrototypeFunction.h" 53 51 #include "InitializeThreading.h" … … 58 56 #include "JSFunction.h" 59 57 #include "Parser.h" 58 #include "PropertyNameArray.h" 60 59 #include "Operations.h" 61 60 62 #include "utils/qscriptdate_p.h"63 61 #include "bridge/qscriptfunction_p.h" 64 #include "bridge/qscriptobject_p.h"65 62 #include "bridge/qscriptclassobject_p.h" 66 63 #include "bridge/qscriptvariant_p.h" … … 68 65 #include "bridge/qscriptglobalobject_p.h" 69 66 #include "bridge/qscriptactivationobject_p.h" 67 #include "bridge/qscriptstaticscopeobject_p.h" 70 68 71 69 #ifndef QT_NO_QOBJECT … … 155 153 that case, you can call toString() on the error object to obtain an 156 154 error message. The current uncaught exception is also available 157 through uncaughtException(). You can obtain a human-readable 158 backtrace of the exception with uncaughtExceptionBacktrace(). 155 through uncaughtException(). 159 156 Calling clearExceptions() will cause any uncaught exceptions to be 160 157 cleared. … … 265 262 isEvaluating(). 266 263 264 \section1 Garbage Collection 265 266 Qt Script objects may be garbage collected when they are no longer 267 referenced. There is no guarantee as to when automatic garbage 268 collection will take place. 269 270 The collectGarbage() function can be called to explicitly request 271 garbage collection. 272 273 The reportAdditionalMemoryCost() function can be called to indicate 274 that a Qt Script object occupies memory that isn't managed by the 275 scripting environment. Reporting the additional cost makes it more 276 likely that the garbage collector will be triggered. This can be 277 useful, for example, when many custom, native Qt Script objects are 278 allocated. 279 267 280 \section1 Core Debugging/Tracing Facilities 268 281 … … 282 295 This enum specifies the ownership when wrapping a C++ value, e.g. by using newQObject(). 283 296 284 \value QtOwnership The standard Qt ownership rules apply, i.e. the associated object will never be explicitly deleted by the script engine. This is the default. (QObject ownership is explained in \l{Object Trees and Object Ownership}.) 285 \value ScriptOwnership The value is owned by the script environment. The associated data will be deleted when appropriate (i.e. after the garbage collector has discovered that there are no more live references to the value). 286 \value AutoOwnership If the associated object has a parent, the Qt ownership rules apply (QtOwnership); otherwise, the object is owned by the script environment (ScriptOwnership). 297 \value QtOwnership The standard Qt ownership rules apply, i.e. the 298 associated object will never be explicitly deleted by the script 299 engine. This is the default. (QObject ownership is explained in 300 \l{Object Trees & Ownership}.) 301 302 \value ScriptOwnership The value is owned by the script 303 environment. The associated data will be deleted when appropriate 304 (i.e. after the garbage collector has discovered that there are no 305 more live references to the value). 306 307 \value AutoOwnership If the associated object has a parent, the Qt 308 ownership rules apply (QtOwnership); otherwise, the object is 309 owned by the script environment (ScriptOwnership). 310 287 311 */ 288 312 … … 297 321 \value ExcludeSuperClassContents Shorthand form for ExcludeSuperClassMethods | ExcludeSuperClassProperties 298 322 \value ExcludeDeleteLater The script object will not expose the QObject::deleteLater() slot. 323 \value ExcludeSlots The script object will not expose the QObject's slots. 299 324 \value AutoCreateDynamicProperties Properties that don't already exist in the QObject will be created as dynamic properties of that object, rather than as properties of the script object. 300 325 \value PreferExistingWrapperObject If a wrapper object with the requested configuration already exists, return that object. … … 329 354 namespace QScript 330 355 { 356 357 static const qsreal D32 = 4294967296.0; 358 359 qint32 ToInt32(qsreal n) 360 { 361 if (qIsNaN(n) || qIsInf(n) || (n == 0)) 362 return 0; 363 364 qsreal sign = (n < 0) ? -1.0 : 1.0; 365 qsreal abs_n = fabs(n); 366 367 n = ::fmod(sign * ::floor(abs_n), D32); 368 const double D31 = D32 / 2.0; 369 370 if (sign == -1 && n < -D31) 371 n += D32; 372 373 else if (sign != -1 && n >= D31) 374 n -= D32; 375 376 return qint32 (n); 377 } 378 379 quint32 ToUInt32(qsreal n) 380 { 381 if (qIsNaN(n) || qIsInf(n) || (n == 0)) 382 return 0; 383 384 qsreal sign = (n < 0) ? -1.0 : 1.0; 385 qsreal abs_n = fabs(n); 386 387 n = ::fmod(sign * ::floor(abs_n), D32); 388 389 if (n < 0) 390 n += D32; 391 392 return quint32 (n); 393 } 394 395 quint16 ToUInt16(qsreal n) 396 { 397 static const qsreal D16 = 65536.0; 398 399 if (qIsNaN(n) || qIsInf(n) || (n == 0)) 400 return 0; 401 402 qsreal sign = (n < 0) ? -1.0 : 1.0; 403 qsreal abs_n = fabs(n); 404 405 n = ::fmod(sign * ::floor(abs_n), D16); 406 407 if (n < 0) 408 n += D16; 409 410 return quint16 (n); 411 } 412 413 qsreal ToInteger(qsreal n) 414 { 415 if (qIsNaN(n)) 416 return 0; 417 418 if (n == 0 || qIsInf(n)) 419 return n; 420 421 int sign = n < 0 ? -1 : 1; 422 return sign * ::floor(::fabs(n)); 423 } 424 425 #ifdef Q_CC_MSVC 426 // MSVC2008 crashes if these are inlined. 427 428 QString ToString(qsreal value) 429 { 430 return JSC::UString::from(value); 431 } 432 433 qsreal ToNumber(const QString &value) 434 { 435 return ((JSC::UString)value).toDouble(); 436 } 437 438 #endif 439 440 static const qsreal MsPerSecond = 1000.0; 441 442 static inline int MsFromTime(qsreal t) 443 { 444 int r = int(::fmod(t, MsPerSecond)); 445 return (r >= 0) ? r : r + int(MsPerSecond); 446 } 447 448 /*! 449 \internal 450 Converts a JS date value (milliseconds) to a QDateTime (local time). 451 */ 452 QDateTime MsToDateTime(JSC::ExecState *exec, qsreal t) 453 { 454 if (qIsNaN(t)) 455 return QDateTime(); 456 JSC::GregorianDateTime tm; 457 JSC::msToGregorianDateTime(exec, t, /*output UTC=*/true, tm); 458 int ms = MsFromTime(t); 459 QDateTime convertedUTC = QDateTime(QDate(tm.year + 1900, tm.month + 1, tm.monthDay), 460 QTime(tm.hour, tm.minute, tm.second, ms), Qt::UTC); 461 return convertedUTC.toLocalTime(); 462 } 463 464 /*! 465 \internal 466 Converts a QDateTime to a JS date value (milliseconds). 467 */ 468 qsreal DateTimeToMs(JSC::ExecState *exec, const QDateTime &dt) 469 { 470 if (!dt.isValid()) 471 return qSNaN(); 472 QDateTime utc = dt.toUTC(); 473 QDate date = utc.date(); 474 QTime time = utc.time(); 475 JSC::GregorianDateTime tm; 476 tm.year = date.year() - 1900; 477 tm.month = date.month() - 1; 478 tm.monthDay = date.day(); 479 tm.weekDay = date.dayOfWeek(); 480 tm.yearDay = date.dayOfYear(); 481 tm.hour = time.hour(); 482 tm.minute = time.minute(); 483 tm.second = time.second(); 484 return JSC::gregorianDateTimeToMS(exec, tm, time.msec(), /*inputIsUTC=*/true); 485 } 331 486 332 487 void GlobalClientData::mark(JSC::MarkStack& markStack) … … 484 639 slot = arg1; 485 640 else { 486 // ### don't go via QScriptValue487 641 QScript::SaveFrameHelper saveFrame(engine, exec); 488 QScriptValue tmp = engine->scriptValueFromJSCValue(arg0); 489 QString propertyName(arg1.toString(exec)); 490 slot = engine->scriptValueToJSCValue(tmp.property(propertyName, QScriptValue::ResolvePrototype)); 642 JSC::UString propertyName = QScriptEnginePrivate::toString(exec, arg1); 643 slot = QScriptEnginePrivate::property(exec, arg0, propertyName, QScriptValue::ResolvePrototype); 491 644 } 492 645 } … … 568 721 slot = arg1; 569 722 else { 570 // ### don't go via QScriptValue571 723 QScript::SaveFrameHelper saveFrame(engine, exec); 572 QScriptValue tmp = engine->scriptValueFromJSCValue(arg0); 573 QString propertyName = arg1.toString(exec); 574 slot = engine->scriptValueToJSCValue(tmp.property(propertyName, QScriptValue::ResolvePrototype)); 724 JSC::UString propertyName = QScriptEnginePrivate::toString(exec, arg1); 725 slot = QScriptEnginePrivate::property(exec, arg0, propertyName, QScriptValue::ResolvePrototype); 575 726 } 576 727 } … … 633 784 static JSC::JSValue JSC_HOST_CALL functionQsTr(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); 634 785 static JSC::JSValue JSC_HOST_CALL functionQsTrNoOp(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); 786 static JSC::JSValue JSC_HOST_CALL functionQsTrId(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); 787 static JSC::JSValue JSC_HOST_CALL functionQsTrIdNoOp(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&); 635 788 636 789 JSC::JSValue JSC_HOST_CALL functionQsTranslate(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args) … … 649 802 return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): fifth argument (n) must be a number"); 650 803 #ifndef QT_NO_QOBJECT 651 QString context(args.at(0).toString(exec));804 JSC::UString context = args.at(0).toString(exec); 652 805 #endif 653 QString text(args.at(1).toString(exec));806 JSC::UString text = args.at(1).toString(exec); 654 807 #ifndef QT_NO_QOBJECT 655 QString comment;808 JSC::UString comment; 656 809 if (args.size() > 2) 657 810 comment = args.at(2).toString(exec); 658 811 QCoreApplication::Encoding encoding = QCoreApplication::CodecForTr; 659 812 if (args.size() > 3) { 660 QString encStr(args.at(3).toString(exec));661 if (encStr == QLatin1String("CodecForTr"))813 JSC::UString encStr = args.at(3).toString(exec); 814 if (encStr == "CodecForTr") 662 815 encoding = QCoreApplication::CodecForTr; 663 else if (encStr == QLatin1String("UnicodeUTF8"))816 else if (encStr == "UnicodeUTF8") 664 817 encoding = QCoreApplication::UnicodeUTF8; 665 818 else … … 670 823 n = args.at(4).toInt32(exec); 671 824 #endif 672 QString result;825 JSC::UString result; 673 826 #ifndef QT_NO_QOBJECT 674 result = QCoreApplication::translate( context.toLatin1().constData(),675 text.toLatin1().constData(),676 comment.toLatin1().constData(),827 result = QCoreApplication::translate(QScript::convertToLatin1(context).constData(), 828 QScript::convertToLatin1(text).constData(), 829 QScript::convertToLatin1(comment).constData(), 677 830 encoding, n); 678 831 #else … … 700 853 return JSC::throwError(exec, JSC::GeneralError, "qsTr(): third argument (n) must be a number"); 701 854 #ifndef QT_NO_QOBJECT 702 QString context; 855 QScriptEnginePrivate *engine = scriptEngineFromExec(exec); 856 JSC::UString context; 703 857 // The first non-empty source URL in the call stack determines the translation context. 704 858 { 705 JSC::ExecState *frame = exec-> removeHostCallFrameFlag();859 JSC::ExecState *frame = exec->callerFrame()->removeHostCallFrameFlag(); 706 860 while (frame) { 707 if (frame->codeBlock() && frame->codeBlock()->source() 861 if (frame->codeBlock() && QScriptEnginePrivate::hasValidCodeBlockRegister(frame) 862 && frame->codeBlock()->source() 708 863 && !frame->codeBlock()->source()->url().isEmpty()) { 709 context = QFileInfo(frame->codeBlock()->source()->url()).baseName();864 context = engine->translationContextFromUrl(frame->codeBlock()->source()->url()); 710 865 break; 711 866 } … … 714 869 } 715 870 #endif 716 QString text(args.at(0).toString(exec));871 JSC::UString text = args.at(0).toString(exec); 717 872 #ifndef QT_NO_QOBJECT 718 QString comment;873 JSC::UString comment; 719 874 if (args.size() > 1) 720 875 comment = args.at(1).toString(exec); … … 723 878 n = args.at(2).toInt32(exec); 724 879 #endif 725 QString result;880 JSC::UString result; 726 881 #ifndef QT_NO_QOBJECT 727 result = QCoreApplication::translate( context.toLatin1().constData(),728 text.toLatin1().constData(),729 comment.toLatin1().constData(),882 result = QCoreApplication::translate(QScript::convertToLatin1(context).constData(), 883 QScript::convertToLatin1(text).constData(), 884 QScript::convertToLatin1(comment).constData(), 730 885 QCoreApplication::CodecForTr, n); 731 886 #else … … 736 891 737 892 JSC::JSValue JSC_HOST_CALL functionQsTrNoOp(JSC::ExecState *, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args) 893 { 894 if (args.size() < 1) 895 return JSC::jsUndefined(); 896 return args.at(0); 897 } 898 899 JSC::JSValue JSC_HOST_CALL functionQsTrId(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args) 900 { 901 if (args.size() < 1) 902 return JSC::throwError(exec, JSC::GeneralError, "qsTrId() requires at least one argument"); 903 if (!args.at(0).isString()) 904 return JSC::throwError(exec, JSC::TypeError, "qsTrId(): first argument (id) must be a string"); 905 if ((args.size() > 1) && !args.at(1).isNumber()) 906 return JSC::throwError(exec, JSC::TypeError, "qsTrId(): second argument (n) must be a number"); 907 JSC::UString id = args.at(0).toString(exec); 908 int n = -1; 909 if (args.size() > 1) 910 n = args.at(1).toInt32(exec); 911 return JSC::jsString(exec, qtTrId(QScript::convertToLatin1(id).constData(), n)); 912 } 913 914 JSC::JSValue JSC_HOST_CALL functionQsTrIdNoOp(JSC::ExecState *, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args) 738 915 { 739 916 if (args.size() < 1) … … 793 970 } 794 971 JSC::initializeThreading(); 795 972 JSC::IdentifierTable *oldTable = JSC::currentIdentifierTable(); 796 973 globalData = JSC::JSGlobalData::create().releaseRef(); 797 974 globalData->clientData = new QScript::GlobalClientData(this); … … 801 978 802 979 scriptObjectStructure = QScriptObject::createStructure(globalObject->objectPrototype()); 980 staticScopeObjectStructure = QScriptStaticScopeObject::createStructure(JSC::jsNull()); 803 981 804 982 qobjectPrototype = new (exec) QScript::QObjectPrototype(exec, QScript::QObjectPrototype::createStructure(globalObject->objectPrototype()), globalObject->prototypeFunctionStructure()); … … 829 1007 agentLineNumber = -1; 830 1008 processEventsInterval = -1; 1009 cachedTranslationUrl = JSC::UString(); 1010 cachedTranslationContext = JSC::UString(); 1011 JSC::setCurrentIdentifierTable(oldTable); 831 1012 } 832 1013 833 1014 QScriptEnginePrivate::~QScriptEnginePrivate() 834 1015 { 1016 QScript::APIShim shim(this); 1017 835 1018 //disconnect all loadedScripts and generate all jsc::debugger::scriptUnload events 836 1019 QHash<intptr_t,QScript::UStringSourceProviderWithFeedback*>::const_iterator it; … … 841 1024 delete ownedAgents.takeFirst(); 842 1025 1026 detachAllRegisteredScriptPrograms(); 843 1027 detachAllRegisteredScriptValues(); 844 1028 detachAllRegisteredScriptStrings(); 845 1029 qDeleteAll(m_qobjectData); 846 1030 qDeleteAll(m_typeInfos); 847 JSC::JSLock lock(false);848 1031 globalData->heap.destroy(); 849 1032 globalData->deref(); … … 855 1038 } 856 1039 857 QScriptValue QScriptEnginePrivate::scriptValueFromVariant(const QVariant &v) 858 { 859 Q_Q(QScriptEngine); 860 QScriptValue result = q->create(v.userType(), v.data()); 861 Q_ASSERT(result.isValid()); 862 return result; 863 } 864 865 QVariant QScriptEnginePrivate::scriptValueToVariant(const QScriptValue &value, int targetType) 1040 QVariant QScriptEnginePrivate::jscValueToVariant(JSC::ExecState *exec, JSC::JSValue value, int targetType) 866 1041 { 867 1042 QVariant v(targetType, (void *)0); 868 if ( QScriptEnginePrivate::convert(value, targetType, v.data(), this))1043 if (convertValue(exec, value, targetType, v.data())) 869 1044 return v; 870 1045 if (uint(targetType) == QVariant::LastType) 871 return value.toVariant();872 if ( value.isVariant()) {873 v = va lue.toVariant();1046 return toVariant(exec, value); 1047 if (isVariant(value)) { 1048 v = variantValue(value); 874 1049 if (v.canConvert(QVariant::Type(targetType))) { 875 1050 v.convert(QVariant::Type(targetType)); … … 882 1057 } 883 1058 } 884 885 1059 return QVariant(); 886 1060 } 887 1061 888 JSC::JSValue QScriptEnginePrivate::jscValueFromVariant(const QVariant &v) 889 { 890 // ### it's inefficient to convert to QScriptValue and then to JSValue 891 QScriptValue vv = scriptValueFromVariant(v); 892 QScriptValuePrivate *p = QScriptValuePrivate::get(vv); 893 switch (p->type) { 894 case QScriptValuePrivate::JavaScriptCore: 895 return p->jscValue; 896 case QScriptValuePrivate::Number: 897 return JSC::jsNumber(currentFrame, p->numberValue); 898 case QScriptValuePrivate::String: { 899 JSC::UString str = p->stringValue; 900 return JSC::jsString(currentFrame, str); 901 } 902 } 903 return JSC::JSValue(); 904 } 905 906 QVariant QScriptEnginePrivate::jscValueToVariant(JSC::JSValue value, int targetType) 907 { 908 // ### it's inefficient to convert to QScriptValue and then to QVariant 909 return scriptValueToVariant(scriptValueFromJSCValue(value), targetType); 910 } 911 912 QScriptValue QScriptEnginePrivate::arrayFromStringList(const QStringList &lst) 913 { 914 Q_Q(QScriptEngine); 915 QScriptValue arr = q->newArray(lst.size()); 1062 JSC::JSValue QScriptEnginePrivate::arrayFromStringList(JSC::ExecState *exec, const QStringList &lst) 1063 { 1064 JSC::JSValue arr = newArray(exec, lst.size()); 916 1065 for (int i = 0; i < lst.size(); ++i) 917 arr.setProperty(i, QScriptValue(q, lst.at(i)));1066 setProperty(exec, arr, i, JSC::jsString(exec, lst.at(i))); 918 1067 return arr; 919 1068 } 920 1069 921 QStringList QScriptEnginePrivate::stringListFromArray( const QScriptValue &arr)1070 QStringList QScriptEnginePrivate::stringListFromArray(JSC::ExecState *exec, JSC::JSValue arr) 922 1071 { 923 1072 QStringList lst; 924 uint len = arr.property(QLatin1String("length")).toUInt32();1073 uint len = toUInt32(exec, property(exec, arr, exec->propertyNames().length)); 925 1074 for (uint i = 0; i < len; ++i) 926 lst.append( arr.property(i).toString());1075 lst.append(toString(exec, property(exec, arr, i))); 927 1076 return lst; 928 1077 } 929 1078 930 QScriptValue QScriptEnginePrivate::arrayFromVariantList(const QVariantList &lst) 931 { 932 Q_Q(QScriptEngine); 933 QScriptValue arr = q->newArray(lst.size()); 1079 JSC::JSValue QScriptEnginePrivate::arrayFromVariantList(JSC::ExecState *exec, const QVariantList &lst) 1080 { 1081 JSC::JSValue arr = newArray(exec, lst.size()); 934 1082 for (int i = 0; i < lst.size(); ++i) 935 arr.setProperty(i, scriptValueFromVariant(lst.at(i)));1083 setProperty(exec, arr, i, jscValueFromVariant(exec, lst.at(i))); 936 1084 return arr; 937 1085 } 938 1086 939 QVariantList QScriptEnginePrivate::variantListFromArray(const QScriptValue &arr) 940 { 1087 QVariantList QScriptEnginePrivate::variantListFromArray(JSC::ExecState *exec, JSC::JSArray *arr) 1088 { 1089 QScriptEnginePrivate *eng = QScript::scriptEngineFromExec(exec); 1090 if (eng->visitedConversionObjects.contains(arr)) 1091 return QVariantList(); // Avoid recursion. 1092 eng->visitedConversionObjects.insert(arr); 941 1093 QVariantList lst; 942 uint len = arr.property(QLatin1String("length")).toUInt32();1094 uint len = toUInt32(exec, property(exec, arr, exec->propertyNames().length)); 943 1095 for (uint i = 0; i < len; ++i) 944 lst.append(arr.property(i).toVariant()); 1096 lst.append(toVariant(exec, property(exec, arr, i))); 1097 eng->visitedConversionObjects.remove(arr); 945 1098 return lst; 946 1099 } 947 1100 948 QScriptValue QScriptEnginePrivate::objectFromVariantMap(const QVariantMap &vmap) 949 { 950 Q_Q(QScriptEngine); 951 QScriptValue obj = q->newObject(); 1101 JSC::JSValue QScriptEnginePrivate::objectFromVariantMap(JSC::ExecState *exec, const QVariantMap &vmap) 1102 { 1103 JSC::JSValue obj = JSC::constructEmptyObject(exec); 952 1104 QVariantMap::const_iterator it; 953 1105 for (it = vmap.constBegin(); it != vmap.constEnd(); ++it) 954 obj.setProperty(it.key(), scriptValueFromVariant(it.value()));1106 setProperty(exec, obj, it.key(), jscValueFromVariant(exec, it.value())); 955 1107 return obj; 956 1108 } 957 1109 958 QVariantMap QScriptEnginePrivate::variantMapFromObject(const QScriptValue &obj) 959 { 1110 QVariantMap QScriptEnginePrivate::variantMapFromObject(JSC::ExecState *exec, JSC::JSObject *obj) 1111 { 1112 QScriptEnginePrivate *eng = QScript::scriptEngineFromExec(exec); 1113 if (eng->visitedConversionObjects.contains(obj)) 1114 return QVariantMap(); // Avoid recursion. 1115 eng->visitedConversionObjects.insert(obj); 1116 JSC::PropertyNameArray propertyNames(exec); 1117 obj->getOwnPropertyNames(exec, propertyNames, JSC::IncludeDontEnumProperties); 960 1118 QVariantMap vmap; 961 QScriptValueIterator it(obj); 962 while (it.hasNext()) { 963 it.next(); 964 vmap.insert(it.name(), it.value().toVariant()); 965 } 1119 JSC::PropertyNameArray::const_iterator it = propertyNames.begin(); 1120 for( ; it != propertyNames.end(); ++it) 1121 vmap.insert(it->ustring(), toVariant(exec, property(exec, obj, *it))); 1122 eng->visitedConversionObjects.remove(obj); 966 1123 return vmap; 967 1124 } … … 1160 1317 void QScriptEnginePrivate::collectGarbage() 1161 1318 { 1162 JSC::JSLock lock(false); 1163 globalData->heap.collect(); 1319 QScript::APIShim shim(this); 1320 globalData->heap.collectAllGarbage(); 1321 } 1322 1323 void QScriptEnginePrivate::reportAdditionalMemoryCost(int size) 1324 { 1325 if (size > 0) 1326 globalData->heap.reportExtraMemoryCost(size); 1164 1327 } 1165 1328 … … 1183 1346 { 1184 1347 Q_Q(QScriptEngine); 1185 JSC::JSLock lock(false); // ### hmmm1186 1348 QBoolBlocker inEvalBlocker(inEval, true); 1187 1349 q->currentContext()->activationObject(); //force the creation of a context for native function; … … 1192 1354 1193 1355 q->clearExceptions(); 1194 JSC::DynamicGlobalObjectScope dynamicGlobalObjectScope(exec, exec->scopeChain()->globalObject ());1356 JSC::DynamicGlobalObjectScope dynamicGlobalObjectScope(exec, exec->scopeChain()->globalObject); 1195 1357 1196 1358 if (compile) { … … 1296 1458 } 1297 1459 1298 bool QScriptEnginePrivate::convertToNativeQObject( const QScriptValue &value,1460 bool QScriptEnginePrivate::convertToNativeQObject(JSC::ExecState *exec, JSC::JSValue value, 1299 1461 const QByteArray &targetType, 1300 1462 void **result) … … 1302 1464 if (!targetType.endsWith('*')) 1303 1465 return false; 1304 if (QObject *qobject = value.toQObject()) {1466 if (QObject *qobject = toQObject(exec, value)) { 1305 1467 int start = targetType.startsWith("const ") ? 6 : 0; 1306 1468 QByteArray className = targetType.mid(start, targetType.size()-start-1); … … 1417 1579 #endif 1418 1580 1581 void QScriptEnginePrivate::detachAllRegisteredScriptPrograms() 1582 { 1583 QSet<QScriptProgramPrivate*>::const_iterator it; 1584 for (it = registeredScriptPrograms.constBegin(); it != registeredScriptPrograms.constEnd(); ++it) 1585 (*it)->detachFromEngine(); 1586 registeredScriptPrograms.clear(); 1587 } 1588 1419 1589 void QScriptEnginePrivate::detachAllRegisteredScriptValues() 1420 1590 { … … 1443 1613 } 1444 1614 1445 #ifdef QT_NO_QOBJECT1446 1447 QScriptEngine::QScriptEngine()1448 : d_ptr(new QScriptEnginePrivate)1449 {1450 d_ptr->q_ptr = this;1451 }1452 1453 /*! \internal1454 */1455 QScriptEngine::QScriptEngine(QScriptEnginePrivate &dd)1456 : d_ptr(&dd)1457 {1458 d_ptr->q_ptr = this;1459 }1460 #else1461 1462 /*!1463 Constructs a QScriptEngine object.1464 1465 The globalObject() is initialized to have properties as described in1466 \l{ECMA-262}, Section 15.1.1467 */1468 QScriptEngine::QScriptEngine()1469 : QObject(*new QScriptEnginePrivate, 0)1470 {1471 }1472 1473 /*!1474 Constructs a QScriptEngine object with the given \a parent.1475 1476 The globalObject() is initialized to have properties as described in1477 \l{ECMA-262}, Section 15.1.1478 */1479 1480 QScriptEngine::QScriptEngine(QObject *parent)1481 : QObject(*new QScriptEnginePrivate, parent)1482 {1483 }1484 1485 /*! \internal1486 */1487 QScriptEngine::QScriptEngine(QScriptEnginePrivate &dd, QObject *parent)1488 : QObject(dd, parent)1489 {1490 }1491 #endif1492 1493 /*!1494 Destroys this QScriptEngine.1495 */1496 QScriptEngine::~QScriptEngine()1497 {1498 #ifdef QT_NO_QOBJECT1499 delete d_ptr;1500 d_ptr = 0;1501 #endif1502 }1503 1504 /*!1505 Returns this engine's Global Object.1506 1507 By default, the Global Object contains the built-in objects that are1508 part of \l{ECMA-262}, such as Math, Date and String. Additionally,1509 you can set properties of the Global Object to make your own1510 extensions available to all script code. Non-local variables in1511 script code will be created as properties of the Global Object, as1512 well as local variables in global code.1513 */1514 QScriptValue QScriptEngine::globalObject() const1515 {1516 Q_D(const QScriptEngine);1517 JSC::JSObject *result = d->globalObject();1518 return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue(result);1519 }1520 1521 /*!1522 \since 4.51523 1524 Sets this engine's Global Object to be the given \a object.1525 If \a object is not a valid script object, this function does1526 nothing.1527 1528 When setting a custom global object, you may want to use1529 QScriptValueIterator to copy the properties of the standard Global1530 Object; alternatively, you can set the internal prototype of your1531 custom object to be the original Global Object.1532 */1533 void QScriptEngine::setGlobalObject(const QScriptValue &object)1534 {1535 Q_D(QScriptEngine);1536 if (!object.isObject())1537 return;1538 JSC::JSObject *jscObject = JSC::asObject(d->scriptValueToJSCValue(object));1539 d->setGlobalObject(jscObject);1540 }1541 1542 /*!1543 Returns a QScriptValue of the primitive type Null.1544 1545 \sa undefinedValue()1546 */1547 QScriptValue QScriptEngine::nullValue()1548 {1549 Q_D(QScriptEngine);1550 return d->scriptValueFromJSCValue(JSC::jsNull());1551 }1552 1553 /*!1554 Returns a QScriptValue of the primitive type Undefined.1555 1556 \sa nullValue()1557 */1558 QScriptValue QScriptEngine::undefinedValue()1559 {1560 Q_D(QScriptEngine);1561 return d->scriptValueFromJSCValue(JSC::jsUndefined());1562 }1563 1564 /*!1565 Creates a constructor function from \a fun, with the given \a length.1566 The \c{prototype} property of the resulting function is set to be the1567 given \a prototype. The \c{constructor} property of \a prototype is1568 set to be the resulting function.1569 1570 When a function is called as a constructor (e.g. \c{new Foo()}), the1571 `this' object associated with the function call is the new object1572 that the function is expected to initialize; the prototype of this1573 default constructed object will be the function's public1574 \c{prototype} property. If you always want the function to behave as1575 a constructor (e.g. \c{Foo()} should also create a new object), or1576 if you need to create your own object rather than using the default1577 `this' object, you should make sure that the prototype of your1578 object is set correctly; either by setting it manually, or, when1579 wrapping a custom type, by having registered the defaultPrototype()1580 of that type. Example:1581 1582 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 91583 1584 To wrap a custom type and provide a constructor for it, you'd typically1585 do something like this:1586 1587 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 101588 */1589 QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun,1590 const QScriptValue &prototype,1591 int length)1592 {1593 Q_D(QScriptEngine);1594 JSC::ExecState* exec = d->currentFrame;1595 JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun);1596 QScriptValue result = d->scriptValueFromJSCValue(function);1597 result.setProperty(QLatin1String("prototype"), prototype, QScriptValue::Undeletable);1598 const_cast<QScriptValue&>(prototype)1599 .setProperty(QLatin1String("constructor"), result,1600 QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);1601 return result;1602 }1603 1604 1615 #ifndef QT_NO_REGEXP 1605 1616 1606 Q_DECL_IMPORT extern QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax); 1607 1608 /*! 1609 Creates a QtScript object of class RegExp with the given 1610 \a regexp. 1611 1612 \sa QScriptValue::toRegExp() 1613 */ 1614 QScriptValue QScriptEngine::newRegExp(const QRegExp ®exp) 1615 { 1616 Q_D(QScriptEngine); 1617 JSC::ExecState* exec = d->currentFrame; 1617 Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax); 1618 1619 JSC::JSValue QScriptEnginePrivate::newRegExp(JSC::ExecState *exec, const QRegExp ®exp) 1620 { 1618 1621 JSC::JSValue buf[2]; 1619 1622 JSC::ArgList args(buf, sizeof(buf)); … … 1648 1651 case ']': 1649 1652 inBracket = false; 1650 1653 break; 1651 1654 default: 1652 1655 break; … … 1663 1666 buf[0] = JSC::jsString(exec, jscPattern); 1664 1667 buf[1] = JSC::jsString(exec, jscFlags); 1665 JSC::JSObject* result = JSC::constructRegExp(exec, args); 1666 return d->scriptValueFromJSCValue(result); 1667 } 1668 1669 #endif // QT_NO_REGEXP 1670 1671 /*! 1672 Creates a QtScript object holding the given variant \a value. 1673 1674 If a default prototype has been registered with the meta type id of 1675 \a value, then the prototype of the created object will be that 1676 prototype; otherwise, the prototype will be the Object prototype 1677 object. 1678 1679 \sa setDefaultPrototype(), QScriptValue::toVariant() 1680 */ 1681 QScriptValue QScriptEngine::newVariant(const QVariant &value) 1682 { 1683 Q_D(QScriptEngine); 1684 JSC::ExecState* exec = d->currentFrame; 1685 QScriptObject *obj = new (exec) QScriptObject(d->variantWrapperObjectStructure); 1686 obj->setDelegate(new QScript::QVariantDelegate(value)); 1687 QScriptValue result = d->scriptValueFromJSCValue(obj); 1688 QScriptValue proto = defaultPrototype(value.userType()); 1689 if (proto.isValid()) 1690 result.setPrototype(proto); 1691 return result; 1692 } 1693 1694 /*! 1695 \since 4.4 1696 \overload 1697 1698 Initializes the given Qt Script \a object to hold the given variant 1699 \a value, and returns the \a object. 1700 1701 This function enables you to "promote" a plain Qt Script object 1702 (created by the newObject() function) to a variant, or to replace 1703 the variant contained inside an object previously created by the 1704 newVariant() function. 1705 1706 The prototype() of the \a object will remain unchanged. 1707 1708 If \a object is not an object, this function behaves like the normal 1709 newVariant(), i.e. it creates a new script object and returns it. 1710 1711 This function is useful when you want to provide a script 1712 constructor for a C++ type. If your constructor is invoked in a 1713 \c{new} expression (QScriptContext::isCalledAsConstructor() returns 1714 true), you can pass QScriptContext::thisObject() (the default 1715 constructed script object) to this function to initialize the new 1716 object. 1717 */ 1718 QScriptValue QScriptEngine::newVariant(const QScriptValue &object, 1719 const QVariant &value) 1720 { 1721 if (!object.isObject()) 1722 return newVariant(value); 1723 JSC::JSObject *jscObject = JSC::asObject(QScriptValuePrivate::get(object)->jscValue); 1724 if (!jscObject->inherits(&QScriptObject::info)) { 1725 qWarning("QScriptEngine::newVariant(): changing class of non-QScriptObject not supported"); 1726 return QScriptValue(); 1727 } 1728 QScriptObject *jscScriptObject = static_cast<QScriptObject*>(jscObject); 1729 if (!object.isVariant()) { 1730 jscScriptObject->setDelegate(new QScript::QVariantDelegate(value)); 1731 } else { 1732 QScriptValuePrivate::get(object)->setVariantValue(value); 1733 } 1734 return object; 1735 } 1736 1737 #ifndef QT_NO_QOBJECT 1738 /*! 1739 Creates a QtScript object that wraps the given QObject \a 1740 object, using the given \a ownership. The given \a options control 1741 various aspects of the interaction with the resulting script object. 1742 1743 Signals and slots, properties and children of \a object are 1744 available as properties of the created QScriptValue. For more 1745 information, see the \l{QtScript} documentation. 1746 1747 If \a object is a null pointer, this function returns nullValue(). 1748 1749 If a default prototype has been registered for the \a object's class 1750 (or its superclass, recursively), the prototype of the new script 1751 object will be set to be that default prototype. 1752 1753 If the given \a object is deleted outside of QtScript's control, any 1754 attempt to access the deleted QObject's members through the QtScript 1755 wrapper object (either by script code or C++) will result in a 1756 script exception. 1757 1758 \sa QScriptValue::toQObject() 1759 */ 1760 QScriptValue QScriptEngine::newQObject(QObject *object, ValueOwnership ownership, 1761 const QObjectWrapOptions &options) 1762 { 1763 Q_D(QScriptEngine); 1764 JSC::JSValue jscQObject = d->newQObject(object, ownership, options); 1765 return d->scriptValueFromJSCValue(jscQObject); 1766 } 1767 1768 /*! 1769 \since 4.4 1770 \overload 1771 1772 Initializes the given \a scriptObject to hold the given \a qtObject, 1773 and returns the \a scriptObject. 1774 1775 This function enables you to "promote" a plain Qt Script object 1776 (created by the newObject() function) to a QObject proxy, or to 1777 replace the QObject contained inside an object previously created by 1778 the newQObject() function. 1779 1780 The prototype() of the \a scriptObject will remain unchanged. 1781 1782 If \a scriptObject is not an object, this function behaves like the 1783 normal newQObject(), i.e. it creates a new script object and returns 1784 it. 1785 1786 This function is useful when you want to provide a script 1787 constructor for a QObject-based class. If your constructor is 1788 invoked in a \c{new} expression 1789 (QScriptContext::isCalledAsConstructor() returns true), you can pass 1790 QScriptContext::thisObject() (the default constructed script object) 1791 to this function to initialize the new object. 1792 */ 1793 QScriptValue QScriptEngine::newQObject(const QScriptValue &scriptObject, 1794 QObject *qtObject, 1795 ValueOwnership ownership, 1796 const QObjectWrapOptions &options) 1797 { 1798 if (!scriptObject.isObject()) 1799 return newQObject(qtObject, ownership, options); 1800 JSC::JSObject *jscObject = JSC::asObject(QScriptValuePrivate::get(scriptObject)->jscValue); 1801 if (!jscObject->inherits(&QScriptObject::info)) { 1802 qWarning("QScriptEngine::newQObject(): changing class of non-QScriptObject not supported"); 1803 return QScriptValue(); 1804 } 1805 QScriptObject *jscScriptObject = static_cast<QScriptObject*>(jscObject); 1806 if (!scriptObject.isQObject()) { 1807 jscScriptObject->setDelegate(new QScript::QObjectDelegate(qtObject, ownership, options)); 1808 } else { 1809 QScript::QObjectDelegate *delegate = static_cast<QScript::QObjectDelegate*>(jscScriptObject->delegate()); 1810 delegate->setValue(qtObject); 1811 delegate->setOwnership(ownership); 1812 delegate->setOptions(options); 1813 } 1814 return scriptObject; 1815 } 1816 1817 #endif // QT_NO_QOBJECT 1818 1819 /*! 1820 Creates a QtScript object of class Object. 1821 1822 The prototype of the created object will be the Object 1823 prototype object. 1824 1825 \sa newArray(), QScriptValue::setProperty() 1826 */ 1827 QScriptValue QScriptEngine::newObject() 1828 { 1829 Q_D(QScriptEngine); 1830 JSC::ExecState* exec = d->currentFrame; 1831 JSC::JSObject *result = new (exec)QScriptObject(d->scriptObjectStructure); 1832 return d->scriptValueFromJSCValue(result); 1833 } 1834 1835 /*! 1836 \since 4.4 1837 \overload 1838 1839 Creates a QtScript Object of the given class, \a scriptClass. 1840 1841 The prototype of the created object will be the Object 1842 prototype object. 1843 1844 \a data, if specified, is set as the internal data of the 1845 new object (using QScriptValue::setData()). 1846 1847 \sa QScriptValue::scriptClass() 1848 */ 1849 QScriptValue QScriptEngine::newObject(QScriptClass *scriptClass, 1850 const QScriptValue &data) 1851 { 1852 Q_D(QScriptEngine); 1853 JSC::ExecState* exec = d->currentFrame; 1854 QScriptObject *result = new (exec) QScriptObject(d->scriptObjectStructure); 1855 result->setDelegate(new QScript::ClassObjectDelegate(scriptClass)); 1856 QScriptValue scriptObject = d->scriptValueFromJSCValue(result); 1857 scriptObject.setData(data); 1858 QScriptValue proto = scriptClass->prototype(); 1859 if (proto.isValid()) 1860 scriptObject.setPrototype(proto); 1861 return scriptObject; 1862 } 1863 1864 /*! 1865 \internal 1866 */ 1867 QScriptValue QScriptEngine::newActivationObject() 1868 { 1869 qWarning("QScriptEngine::newActivationObject() not implemented"); 1870 // ### JSActivation or JSVariableObject? 1871 return QScriptValue(); 1872 } 1873 1874 /*! 1875 Creates a QScriptValue that wraps a native (C++) function. \a fun 1876 must be a C++ function with signature QScriptEngine::FunctionSignature. \a 1877 length is the number of arguments that \a fun expects; this becomes 1878 the \c{length} property of the created QScriptValue. 1879 1880 Note that \a length only gives an indication of the number of 1881 arguments that the function expects; an actual invocation of a 1882 function can include any number of arguments. You can check the 1883 \l{QScriptContext::argumentCount()}{argumentCount()} of the 1884 QScriptContext associated with the invocation to determine the 1885 actual number of arguments passed. 1886 1887 A \c{prototype} property is automatically created for the resulting 1888 function object, to provide for the possibility that the function 1889 will be used as a constructor. 1890 1891 By combining newFunction() and the property flags 1892 QScriptValue::PropertyGetter and QScriptValue::PropertySetter, you 1893 can create script object properties that behave like normal 1894 properties in script code, but are in fact accessed through 1895 functions (analogous to how properties work in \l{Qt's Property 1896 System}). Example: 1897 1898 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 11 1899 1900 When the property \c{foo} of the script object is subsequently 1901 accessed in script code, \c{getSetFoo()} will be invoked to handle 1902 the access. In this particular case, we chose to store the "real" 1903 value of \c{foo} as a property of the accessor function itself; you 1904 are of course free to do whatever you like in this function. 1905 1906 In the above example, a single native function was used to handle 1907 both reads and writes to the property; the argument count is used to 1908 determine if we are handling a read or write. You can also use two 1909 separate functions; just specify the relevant flag 1910 (QScriptValue::PropertyGetter or QScriptValue::PropertySetter) when 1911 setting the property, e.g.: 1912 1913 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 12 1914 1915 \sa QScriptValue::call() 1916 */ 1917 QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, int length) 1918 { 1919 Q_D(QScriptEngine); 1920 JSC::ExecState* exec = d->currentFrame; 1921 JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun); 1922 QScriptValue result = d->scriptValueFromJSCValue(function); 1923 QScriptValue proto = newObject(); 1924 result.setProperty(QLatin1String("prototype"), proto, QScriptValue::Undeletable); 1925 proto.setProperty(QLatin1String("constructor"), result, 1926 QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); 1927 return result; 1928 } 1929 1930 /*! 1931 \internal 1932 \since 4.4 1933 */ 1934 QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionWithArgSignature fun, void *arg) 1935 { 1936 Q_D(QScriptEngine); 1937 JSC::ExecState* exec = d->currentFrame; 1938 JSC::JSValue function = new (exec)QScript::FunctionWithArgWrapper(exec, /*length=*/0, JSC::Identifier(exec, ""), fun, arg); 1939 QScriptValue result = d->scriptValueFromJSCValue(function); 1940 QScriptValue proto = newObject(); 1941 result.setProperty(QLatin1String("prototype"), proto, QScriptValue::Undeletable); 1942 proto.setProperty(QLatin1String("constructor"), result, 1943 QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); 1944 return result; 1945 } 1946 1947 /*! 1948 Creates a QtScript object of class Array with the given \a length. 1949 1950 \sa newObject() 1951 */ 1952 QScriptValue QScriptEngine::newArray(uint length) 1953 { 1954 Q_D(QScriptEngine); 1955 JSC::ExecState* exec = d->currentFrame; 1956 JSC::JSArray* result = JSC::constructEmptyArray(exec, length); 1957 return d->scriptValueFromJSCValue(result); 1958 } 1959 1960 /*! 1961 Creates a QtScript object of class RegExp with the given 1962 \a pattern and \a flags. 1963 1964 The legal flags are 'g' (global), 'i' (ignore case), and 'm' 1965 (multiline). 1966 */ 1967 QScriptValue QScriptEngine::newRegExp(const QString &pattern, const QString &flags) 1968 { 1969 Q_D(QScriptEngine); 1970 JSC::ExecState* exec = d->currentFrame; 1668 return JSC::constructRegExp(exec, args); 1669 } 1670 1671 #endif 1672 1673 JSC::JSValue QScriptEnginePrivate::newRegExp(JSC::ExecState *exec, const QString &pattern, const QString &flags) 1674 { 1971 1675 JSC::JSValue buf[2]; 1972 1676 JSC::ArgList args(buf, sizeof(buf)); … … 1982 1686 buf[0] = JSC::jsString(exec, jscPattern); 1983 1687 buf[1] = JSC::jsString(exec, jscFlags); 1984 JSC::JSObject* result = JSC::constructRegExp(exec, args); 1985 return d->scriptValueFromJSCValue(result); 1688 return JSC::constructRegExp(exec, args); 1689 } 1690 1691 JSC::JSValue QScriptEnginePrivate::newVariant(const QVariant &value) 1692 { 1693 QScriptObject *obj = new (currentFrame) QScriptObject(variantWrapperObjectStructure); 1694 obj->setDelegate(new QScript::QVariantDelegate(value)); 1695 JSC::JSValue proto = defaultPrototype(value.userType()); 1696 if (proto) 1697 obj->setPrototype(proto); 1698 return obj; 1699 } 1700 1701 JSC::JSValue QScriptEnginePrivate::newVariant(JSC::JSValue objectValue, 1702 const QVariant &value) 1703 { 1704 if (!isObject(objectValue)) 1705 return newVariant(value); 1706 JSC::JSObject *jscObject = JSC::asObject(objectValue); 1707 if (!jscObject->inherits(&QScriptObject::info)) { 1708 qWarning("QScriptEngine::newVariant(): changing class of non-QScriptObject not supported"); 1709 return JSC::JSValue(); 1710 } 1711 QScriptObject *jscScriptObject = static_cast<QScriptObject*>(jscObject); 1712 if (!isVariant(objectValue)) { 1713 jscScriptObject->setDelegate(new QScript::QVariantDelegate(value)); 1714 } else { 1715 setVariantValue(objectValue, value); 1716 } 1717 return objectValue; 1718 } 1719 1720 #ifndef QT_NO_REGEXP 1721 1722 QRegExp QScriptEnginePrivate::toRegExp(JSC::ExecState *exec, JSC::JSValue value) 1723 { 1724 if (!isRegExp(value)) 1725 return QRegExp(); 1726 QString pattern = toString(exec, property(exec, value, "source", QScriptValue::ResolvePrototype)); 1727 Qt::CaseSensitivity kase = Qt::CaseSensitive; 1728 if (toBool(exec, property(exec, value, "ignoreCase", QScriptValue::ResolvePrototype))) 1729 kase = Qt::CaseInsensitive; 1730 return QRegExp(pattern, kase, QRegExp::RegExp2); 1731 } 1732 1733 #endif 1734 1735 QVariant QScriptEnginePrivate::toVariant(JSC::ExecState *exec, JSC::JSValue value) 1736 { 1737 if (!value) { 1738 return QVariant(); 1739 } else if (isObject(value)) { 1740 if (isVariant(value)) 1741 return variantValue(value); 1742 #ifndef QT_NO_QOBJECT 1743 else if (isQObject(value)) 1744 return qVariantFromValue(toQObject(exec, value)); 1745 #endif 1746 else if (isDate(value)) 1747 return QVariant(toDateTime(exec, value)); 1748 #ifndef QT_NO_REGEXP 1749 else if (isRegExp(value)) 1750 return QVariant(toRegExp(exec, value)); 1751 #endif 1752 else if (isArray(value)) 1753 return variantListFromArray(exec, JSC::asArray(value)); 1754 else if (QScriptDeclarativeClass *dc = declarativeClass(value)) 1755 return dc->toVariant(declarativeObject(value)); 1756 return variantMapFromObject(exec, JSC::asObject(value)); 1757 } else if (value.isNumber()) { 1758 return QVariant(toNumber(exec, value)); 1759 } else if (value.isString()) { 1760 return QVariant(toString(exec, value)); 1761 } else if (value.isBoolean()) { 1762 return QVariant(toBool(exec, value)); 1763 } 1764 return QVariant(); 1765 } 1766 1767 JSC::JSValue QScriptEnginePrivate::propertyHelper(JSC::ExecState *exec, JSC::JSValue value, const JSC::Identifier &id, int resolveMode) 1768 { 1769 JSC::JSValue result; 1770 if (!(resolveMode & QScriptValue::ResolvePrototype)) { 1771 // Look in the object's own properties 1772 JSC::JSObject *object = JSC::asObject(value); 1773 JSC::PropertySlot slot(object); 1774 if (object->getOwnPropertySlot(exec, id, slot)) 1775 result = slot.getValue(exec, id); 1776 } 1777 if (!result && (resolveMode & QScriptValue::ResolveScope)) { 1778 // ### check if it's a function object and look in the scope chain 1779 JSC::JSValue scope = property(exec, value, "__qt_scope__", QScriptValue::ResolveLocal); 1780 if (isObject(scope)) 1781 result = property(exec, scope, id, resolveMode); 1782 } 1783 return result; 1784 } 1785 1786 JSC::JSValue QScriptEnginePrivate::propertyHelper(JSC::ExecState *exec, JSC::JSValue value, quint32 index, int resolveMode) 1787 { 1788 JSC::JSValue result; 1789 if (!(resolveMode & QScriptValue::ResolvePrototype)) { 1790 // Look in the object's own properties 1791 JSC::JSObject *object = JSC::asObject(value); 1792 JSC::PropertySlot slot(object); 1793 if (object->getOwnPropertySlot(exec, index, slot)) 1794 result = slot.getValue(exec, index); 1795 } 1796 return result; 1797 } 1798 1799 void QScriptEnginePrivate::setProperty(JSC::ExecState *exec, JSC::JSValue objectValue, const JSC::Identifier &id, 1800 JSC::JSValue value, const QScriptValue::PropertyFlags &flags) 1801 { 1802 JSC::JSObject *thisObject = JSC::asObject(objectValue); 1803 JSC::JSValue setter = thisObject->lookupSetter(exec, id); 1804 JSC::JSValue getter = thisObject->lookupGetter(exec, id); 1805 if ((flags & QScriptValue::PropertyGetter) || (flags & QScriptValue::PropertySetter)) { 1806 if (!value) { 1807 // deleting getter/setter 1808 if ((flags & QScriptValue::PropertyGetter) && (flags & QScriptValue::PropertySetter)) { 1809 // deleting both: just delete the property 1810 thisObject->deleteProperty(exec, id); 1811 } else if (flags & QScriptValue::PropertyGetter) { 1812 // preserve setter, if there is one 1813 thisObject->deleteProperty(exec, id); 1814 if (setter && setter.isObject()) 1815 thisObject->defineSetter(exec, id, JSC::asObject(setter)); 1816 } else { // flags & QScriptValue::PropertySetter 1817 // preserve getter, if there is one 1818 thisObject->deleteProperty(exec, id); 1819 if (getter && getter.isObject()) 1820 thisObject->defineGetter(exec, id, JSC::asObject(getter)); 1821 } 1822 } else { 1823 if (value.isObject()) { // ### should check if it has callData() 1824 // defining getter/setter 1825 if (id == exec->propertyNames().underscoreProto) { 1826 qWarning("QScriptValue::setProperty() failed: " 1827 "cannot set getter or setter of native property `__proto__'"); 1828 } else { 1829 if (flags & QScriptValue::PropertyGetter) 1830 thisObject->defineGetter(exec, id, JSC::asObject(value)); 1831 if (flags & QScriptValue::PropertySetter) 1832 thisObject->defineSetter(exec, id, JSC::asObject(value)); 1833 } 1834 } else { 1835 qWarning("QScriptValue::setProperty(): getter/setter must be a function"); 1836 } 1837 } 1838 } else { 1839 // setting the value 1840 if (getter && getter.isObject() && !(setter && setter.isObject())) { 1841 qWarning("QScriptValue::setProperty() failed: " 1842 "property '%s' has a getter but no setter", 1843 qPrintable(QString(id.ustring()))); 1844 return; 1845 } 1846 if (!value) { 1847 // ### check if it's a getter/setter property 1848 thisObject->deleteProperty(exec, id); 1849 } else if (flags != QScriptValue::KeepExistingFlags) { 1850 if (thisObject->hasOwnProperty(exec, id)) 1851 thisObject->deleteProperty(exec, id); // ### hmmm - can't we just update the attributes? 1852 thisObject->putWithAttributes(exec, id, value, propertyFlagsToJSCAttributes(flags)); 1853 } else { 1854 JSC::PutPropertySlot slot; 1855 thisObject->put(exec, id, value, slot); 1856 } 1857 } 1858 } 1859 1860 void QScriptEnginePrivate::setProperty(JSC::ExecState *exec, JSC::JSValue objectValue, quint32 index, 1861 JSC::JSValue value, const QScriptValue::PropertyFlags &flags) 1862 { 1863 if (!value) { 1864 JSC::asObject(objectValue)->deleteProperty(exec, index); 1865 } else { 1866 if ((flags & QScriptValue::PropertyGetter) || (flags & QScriptValue::PropertySetter)) { 1867 // fall back to string-based setProperty(), since there is no 1868 // JSC::JSObject::defineGetter(unsigned) 1869 setProperty(exec, objectValue, JSC::Identifier::from(exec, index), value, flags); 1870 } else { 1871 if (flags != QScriptValue::KeepExistingFlags) { 1872 // if (JSC::asObject(d->jscValue)->hasOwnProperty(exec, arrayIndex)) 1873 // JSC::asObject(d->jscValue)->deleteProperty(exec, arrayIndex); 1874 unsigned attribs = 0; 1875 if (flags & QScriptValue::ReadOnly) 1876 attribs |= JSC::ReadOnly; 1877 if (flags & QScriptValue::SkipInEnumeration) 1878 attribs |= JSC::DontEnum; 1879 if (flags & QScriptValue::Undeletable) 1880 attribs |= JSC::DontDelete; 1881 attribs |= flags & QScriptValue::UserRange; 1882 JSC::asObject(objectValue)->putWithAttributes(exec, index, value, attribs); 1883 } else { 1884 JSC::asObject(objectValue)->put(exec, index, value); 1885 } 1886 } 1887 } 1888 } 1889 1890 QScriptValue::PropertyFlags QScriptEnginePrivate::propertyFlags(JSC::ExecState *exec, JSC::JSValue value, const JSC::Identifier &id, 1891 const QScriptValue::ResolveFlags &mode) 1892 { 1893 JSC::JSObject *object = JSC::asObject(value); 1894 unsigned attribs = 0; 1895 JSC::PropertyDescriptor descriptor; 1896 if (object->getOwnPropertyDescriptor(exec, id, descriptor)) 1897 attribs = descriptor.attributes(); 1898 else { 1899 if ((mode & QScriptValue::ResolvePrototype) && object->prototype() && object->prototype().isObject()) { 1900 JSC::JSValue proto = object->prototype(); 1901 return propertyFlags(exec, proto, id, mode); 1902 } 1903 return 0; 1904 } 1905 QScriptValue::PropertyFlags result = 0; 1906 if (attribs & JSC::ReadOnly) 1907 result |= QScriptValue::ReadOnly; 1908 if (attribs & JSC::DontEnum) 1909 result |= QScriptValue::SkipInEnumeration; 1910 if (attribs & JSC::DontDelete) 1911 result |= QScriptValue::Undeletable; 1912 //We cannot rely on attribs JSC::Setter/Getter because they are not necesserly set by JSC (bug?) 1913 if (attribs & JSC::Getter || !object->lookupGetter(exec, id).isUndefinedOrNull()) 1914 result |= QScriptValue::PropertyGetter; 1915 if (attribs & JSC::Setter || !object->lookupSetter(exec, id).isUndefinedOrNull()) 1916 result |= QScriptValue::PropertySetter; 1917 #ifndef QT_NO_QOBJECT 1918 if (attribs & QScript::QObjectMemberAttribute) 1919 result |= QScriptValue::QObjectMember; 1920 #endif 1921 result |= QScriptValue::PropertyFlag(attribs & QScriptValue::UserRange); 1922 return result; 1923 } 1924 1925 QScriptString QScriptEnginePrivate::toStringHandle(const JSC::Identifier &name) 1926 { 1927 QScriptString result; 1928 QScriptStringPrivate *p = new QScriptStringPrivate(this, name, QScriptStringPrivate::HeapAllocated); 1929 QScriptStringPrivate::init(result, p); 1930 registerScriptString(p); 1931 return result; 1932 } 1933 1934 #ifdef QT_NO_QOBJECT 1935 1936 QScriptEngine::QScriptEngine() 1937 : d_ptr(new QScriptEnginePrivate) 1938 { 1939 d_ptr->q_ptr = this; 1940 } 1941 1942 /*! \internal 1943 */ 1944 QScriptEngine::QScriptEngine(QScriptEnginePrivate &dd) 1945 : d_ptr(&dd) 1946 { 1947 d_ptr->q_ptr = this; 1948 } 1949 #else 1950 1951 /*! 1952 Constructs a QScriptEngine object. 1953 1954 The globalObject() is initialized to have properties as described in 1955 \l{ECMA-262}, Section 15.1. 1956 */ 1957 QScriptEngine::QScriptEngine() 1958 : QObject(*new QScriptEnginePrivate, 0) 1959 { 1960 } 1961 1962 /*! 1963 Constructs a QScriptEngine object with the given \a parent. 1964 1965 The globalObject() is initialized to have properties as described in 1966 \l{ECMA-262}, Section 15.1. 1967 */ 1968 1969 QScriptEngine::QScriptEngine(QObject *parent) 1970 : QObject(*new QScriptEnginePrivate, parent) 1971 { 1972 } 1973 1974 /*! \internal 1975 */ 1976 QScriptEngine::QScriptEngine(QScriptEnginePrivate &dd, QObject *parent) 1977 : QObject(dd, parent) 1978 { 1979 } 1980 #endif 1981 1982 /*! 1983 Destroys this QScriptEngine. 1984 */ 1985 QScriptEngine::~QScriptEngine() 1986 { 1987 #ifdef QT_NO_QOBJECT 1988 delete d_ptr; 1989 d_ptr = 0; 1990 #endif 1991 } 1992 1993 /*! 1994 Returns this engine's Global Object. 1995 1996 By default, the Global Object contains the built-in objects that are 1997 part of \l{ECMA-262}, such as Math, Date and String. Additionally, 1998 you can set properties of the Global Object to make your own 1999 extensions available to all script code. Non-local variables in 2000 script code will be created as properties of the Global Object, as 2001 well as local variables in global code. 2002 */ 2003 QScriptValue QScriptEngine::globalObject() const 2004 { 2005 Q_D(const QScriptEngine); 2006 QScript::APIShim shim(const_cast<QScriptEnginePrivate*>(d)); 2007 JSC::JSObject *result = d->globalObject(); 2008 return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue(result); 2009 } 2010 2011 /*! 2012 \since 4.5 2013 2014 Sets this engine's Global Object to be the given \a object. 2015 If \a object is not a valid script object, this function does 2016 nothing. 2017 2018 When setting a custom global object, you may want to use 2019 QScriptValueIterator to copy the properties of the standard Global 2020 Object; alternatively, you can set the internal prototype of your 2021 custom object to be the original Global Object. 2022 */ 2023 void QScriptEngine::setGlobalObject(const QScriptValue &object) 2024 { 2025 Q_D(QScriptEngine); 2026 if (!object.isObject()) 2027 return; 2028 QScript::APIShim shim(d); 2029 JSC::JSObject *jscObject = JSC::asObject(d->scriptValueToJSCValue(object)); 2030 d->setGlobalObject(jscObject); 2031 } 2032 2033 /*! 2034 Returns a QScriptValue of the primitive type Null. 2035 2036 \sa undefinedValue() 2037 */ 2038 QScriptValue QScriptEngine::nullValue() 2039 { 2040 Q_D(QScriptEngine); 2041 return d->scriptValueFromJSCValue(JSC::jsNull()); 2042 } 2043 2044 /*! 2045 Returns a QScriptValue of the primitive type Undefined. 2046 2047 \sa nullValue() 2048 */ 2049 QScriptValue QScriptEngine::undefinedValue() 2050 { 2051 Q_D(QScriptEngine); 2052 return d->scriptValueFromJSCValue(JSC::jsUndefined()); 2053 } 2054 2055 /*! 2056 Creates a constructor function from \a fun, with the given \a length. 2057 The \c{prototype} property of the resulting function is set to be the 2058 given \a prototype. The \c{constructor} property of \a prototype is 2059 set to be the resulting function. 2060 2061 When a function is called as a constructor (e.g. \c{new Foo()}), the 2062 `this' object associated with the function call is the new object 2063 that the function is expected to initialize; the prototype of this 2064 default constructed object will be the function's public 2065 \c{prototype} property. If you always want the function to behave as 2066 a constructor (e.g. \c{Foo()} should also create a new object), or 2067 if you need to create your own object rather than using the default 2068 `this' object, you should make sure that the prototype of your 2069 object is set correctly; either by setting it manually, or, when 2070 wrapping a custom type, by having registered the defaultPrototype() 2071 of that type. Example: 2072 2073 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 9 2074 2075 To wrap a custom type and provide a constructor for it, you'd typically 2076 do something like this: 2077 2078 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 10 2079 */ 2080 QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, 2081 const QScriptValue &prototype, 2082 int length) 2083 { 2084 Q_D(QScriptEngine); 2085 QScript::APIShim shim(d); 2086 JSC::ExecState* exec = d->currentFrame; 2087 JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun); 2088 QScriptValue result = d->scriptValueFromJSCValue(function); 2089 result.setProperty(QLatin1String("prototype"), prototype, QScriptValue::Undeletable); 2090 const_cast<QScriptValue&>(prototype) 2091 .setProperty(QLatin1String("constructor"), result, 2092 QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); 2093 return result; 2094 } 2095 2096 #ifndef QT_NO_REGEXP 2097 2098 /*! 2099 Creates a QtScript object of class RegExp with the given 2100 \a regexp. 2101 2102 \sa QScriptValue::toRegExp() 2103 */ 2104 QScriptValue QScriptEngine::newRegExp(const QRegExp ®exp) 2105 { 2106 Q_D(QScriptEngine); 2107 QScript::APIShim shim(d); 2108 return d->scriptValueFromJSCValue(d->newRegExp(d->currentFrame, regexp)); 2109 } 2110 2111 #endif // QT_NO_REGEXP 2112 2113 /*! 2114 Creates a QtScript object holding the given variant \a value. 2115 2116 If a default prototype has been registered with the meta type id of 2117 \a value, then the prototype of the created object will be that 2118 prototype; otherwise, the prototype will be the Object prototype 2119 object. 2120 2121 \sa setDefaultPrototype(), QScriptValue::toVariant(), reportAdditionalMemoryCost() 2122 */ 2123 QScriptValue QScriptEngine::newVariant(const QVariant &value) 2124 { 2125 Q_D(QScriptEngine); 2126 QScript::APIShim shim(d); 2127 return d->scriptValueFromJSCValue(d->newVariant(value)); 2128 } 2129 2130 /*! 2131 \since 4.4 2132 \overload 2133 2134 Initializes the given Qt Script \a object to hold the given variant 2135 \a value, and returns the \a object. 2136 2137 This function enables you to "promote" a plain Qt Script object 2138 (created by the newObject() function) to a variant, or to replace 2139 the variant contained inside an object previously created by the 2140 newVariant() function. 2141 2142 The prototype() of the \a object will remain unchanged. 2143 2144 If \a object is not an object, this function behaves like the normal 2145 newVariant(), i.e. it creates a new script object and returns it. 2146 2147 This function is useful when you want to provide a script 2148 constructor for a C++ type. If your constructor is invoked in a 2149 \c{new} expression (QScriptContext::isCalledAsConstructor() returns 2150 true), you can pass QScriptContext::thisObject() (the default 2151 constructed script object) to this function to initialize the new 2152 object. 2153 2154 \sa reportAdditionalMemoryCost() 2155 */ 2156 QScriptValue QScriptEngine::newVariant(const QScriptValue &object, 2157 const QVariant &value) 2158 { 2159 Q_D(QScriptEngine); 2160 QScript::APIShim shim(d); 2161 JSC::JSValue jsObject = d->scriptValueToJSCValue(object); 2162 return d->scriptValueFromJSCValue(d->newVariant(jsObject, value)); 2163 } 2164 2165 #ifndef QT_NO_QOBJECT 2166 /*! 2167 Creates a QtScript object that wraps the given QObject \a 2168 object, using the given \a ownership. The given \a options control 2169 various aspects of the interaction with the resulting script object. 2170 2171 Signals and slots, properties and children of \a object are 2172 available as properties of the created QScriptValue. For more 2173 information, see the \l{QtScript} documentation. 2174 2175 If \a object is a null pointer, this function returns nullValue(). 2176 2177 If a default prototype has been registered for the \a object's class 2178 (or its superclass, recursively), the prototype of the new script 2179 object will be set to be that default prototype. 2180 2181 If the given \a object is deleted outside of QtScript's control, any 2182 attempt to access the deleted QObject's members through the QtScript 2183 wrapper object (either by script code or C++) will result in a 2184 script exception. 2185 2186 \sa QScriptValue::toQObject(), reportAdditionalMemoryCost() 2187 */ 2188 QScriptValue QScriptEngine::newQObject(QObject *object, ValueOwnership ownership, 2189 const QObjectWrapOptions &options) 2190 { 2191 Q_D(QScriptEngine); 2192 QScript::APIShim shim(d); 2193 JSC::JSValue jscQObject = d->newQObject(object, ownership, options); 2194 return d->scriptValueFromJSCValue(jscQObject); 2195 } 2196 2197 /*! 2198 \since 4.4 2199 \overload 2200 2201 Initializes the given \a scriptObject to hold the given \a qtObject, 2202 and returns the \a scriptObject. 2203 2204 This function enables you to "promote" a plain Qt Script object 2205 (created by the newObject() function) to a QObject proxy, or to 2206 replace the QObject contained inside an object previously created by 2207 the newQObject() function. 2208 2209 The prototype() of the \a scriptObject will remain unchanged. 2210 2211 If \a scriptObject is not an object, this function behaves like the 2212 normal newQObject(), i.e. it creates a new script object and returns 2213 it. 2214 2215 This function is useful when you want to provide a script 2216 constructor for a QObject-based class. If your constructor is 2217 invoked in a \c{new} expression 2218 (QScriptContext::isCalledAsConstructor() returns true), you can pass 2219 QScriptContext::thisObject() (the default constructed script object) 2220 to this function to initialize the new object. 2221 2222 \sa reportAdditionalMemoryCost() 2223 */ 2224 QScriptValue QScriptEngine::newQObject(const QScriptValue &scriptObject, 2225 QObject *qtObject, 2226 ValueOwnership ownership, 2227 const QObjectWrapOptions &options) 2228 { 2229 Q_D(QScriptEngine); 2230 if (!scriptObject.isObject()) 2231 return newQObject(qtObject, ownership, options); 2232 QScript::APIShim shim(d); 2233 JSC::JSObject *jscObject = JSC::asObject(QScriptValuePrivate::get(scriptObject)->jscValue); 2234 if (!jscObject->inherits(&QScriptObject::info)) { 2235 qWarning("QScriptEngine::newQObject(): changing class of non-QScriptObject not supported"); 2236 return QScriptValue(); 2237 } 2238 QScriptObject *jscScriptObject = static_cast<QScriptObject*>(jscObject); 2239 if (!scriptObject.isQObject()) { 2240 jscScriptObject->setDelegate(new QScript::QObjectDelegate(qtObject, ownership, options)); 2241 } else { 2242 QScript::QObjectDelegate *delegate = static_cast<QScript::QObjectDelegate*>(jscScriptObject->delegate()); 2243 delegate->setValue(qtObject); 2244 delegate->setOwnership(ownership); 2245 delegate->setOptions(options); 2246 } 2247 return scriptObject; 2248 } 2249 2250 #endif // QT_NO_QOBJECT 2251 2252 /*! 2253 Creates a QtScript object of class Object. 2254 2255 The prototype of the created object will be the Object 2256 prototype object. 2257 2258 \sa newArray(), QScriptValue::setProperty() 2259 */ 2260 QScriptValue QScriptEngine::newObject() 2261 { 2262 Q_D(QScriptEngine); 2263 QScript::APIShim shim(d); 2264 return d->scriptValueFromJSCValue(d->newObject()); 2265 } 2266 2267 /*! 2268 \since 4.4 2269 \overload 2270 2271 Creates a QtScript Object of the given class, \a scriptClass. 2272 2273 The prototype of the created object will be the Object 2274 prototype object. 2275 2276 \a data, if specified, is set as the internal data of the 2277 new object (using QScriptValue::setData()). 2278 2279 \sa QScriptValue::scriptClass(), reportAdditionalMemoryCost() 2280 */ 2281 QScriptValue QScriptEngine::newObject(QScriptClass *scriptClass, 2282 const QScriptValue &data) 2283 { 2284 Q_D(QScriptEngine); 2285 QScript::APIShim shim(d); 2286 JSC::ExecState* exec = d->currentFrame; 2287 QScriptObject *result = new (exec) QScriptObject(d->scriptObjectStructure); 2288 result->setDelegate(new QScript::ClassObjectDelegate(scriptClass)); 2289 QScriptValue scriptObject = d->scriptValueFromJSCValue(result); 2290 scriptObject.setData(data); 2291 QScriptValue proto = scriptClass->prototype(); 2292 if (proto.isValid()) 2293 scriptObject.setPrototype(proto); 2294 return scriptObject; 2295 } 2296 2297 /*! 2298 \internal 2299 */ 2300 QScriptValue QScriptEngine::newActivationObject() 2301 { 2302 qWarning("QScriptEngine::newActivationObject() not implemented"); 2303 // ### JSActivation or JSVariableObject? 2304 return QScriptValue(); 2305 } 2306 2307 /*! 2308 Creates a QScriptValue that wraps a native (C++) function. \a fun 2309 must be a C++ function with signature QScriptEngine::FunctionSignature. \a 2310 length is the number of arguments that \a fun expects; this becomes 2311 the \c{length} property of the created QScriptValue. 2312 2313 Note that \a length only gives an indication of the number of 2314 arguments that the function expects; an actual invocation of a 2315 function can include any number of arguments. You can check the 2316 \l{QScriptContext::argumentCount()}{argumentCount()} of the 2317 QScriptContext associated with the invocation to determine the 2318 actual number of arguments passed. 2319 2320 A \c{prototype} property is automatically created for the resulting 2321 function object, to provide for the possibility that the function 2322 will be used as a constructor. 2323 2324 By combining newFunction() and the property flags 2325 QScriptValue::PropertyGetter and QScriptValue::PropertySetter, you 2326 can create script object properties that behave like normal 2327 properties in script code, but are in fact accessed through 2328 functions (analogous to how properties work in \l{Qt's Property 2329 System}). Example: 2330 2331 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 11 2332 2333 When the property \c{foo} of the script object is subsequently 2334 accessed in script code, \c{getSetFoo()} will be invoked to handle 2335 the access. In this particular case, we chose to store the "real" 2336 value of \c{foo} as a property of the accessor function itself; you 2337 are of course free to do whatever you like in this function. 2338 2339 In the above example, a single native function was used to handle 2340 both reads and writes to the property; the argument count is used to 2341 determine if we are handling a read or write. You can also use two 2342 separate functions; just specify the relevant flag 2343 (QScriptValue::PropertyGetter or QScriptValue::PropertySetter) when 2344 setting the property, e.g.: 2345 2346 \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 12 2347 2348 \sa QScriptValue::call() 2349 */ 2350 QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, int length) 2351 { 2352 Q_D(QScriptEngine); 2353 QScript::APIShim shim(d); 2354 JSC::ExecState* exec = d->currentFrame; 2355 JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun); 2356 QScriptValue result = d->scriptValueFromJSCValue(function); 2357 QScriptValue proto = newObject(); 2358 result.setProperty(QLatin1String("prototype"), proto, QScriptValue::Undeletable); 2359 proto.setProperty(QLatin1String("constructor"), result, 2360 QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); 2361 return result; 2362 } 2363 2364 /*! 2365 \internal 2366 \since 4.4 2367 */ 2368 QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionWithArgSignature fun, void *arg) 2369 { 2370 Q_D(QScriptEngine); 2371 QScript::APIShim shim(d); 2372 JSC::ExecState* exec = d->currentFrame; 2373 JSC::JSValue function = new (exec)QScript::FunctionWithArgWrapper(exec, /*length=*/0, JSC::Identifier(exec, ""), fun, arg); 2374 QScriptValue result = d->scriptValueFromJSCValue(function); 2375 QScriptValue proto = newObject(); 2376 result.setProperty(QLatin1String("prototype"), proto, QScriptValue::Undeletable); 2377 proto.setProperty(QLatin1String("constructor"), result, 2378 QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); 2379 return result; 2380 } 2381 2382 /*! 2383 Creates a QtScript object of class Array with the given \a length. 2384 2385 \sa newObject() 2386 */ 2387 QScriptValue QScriptEngine::newArray(uint length) 2388 { 2389 Q_D(QScriptEngine); 2390 QScript::APIShim shim(d); 2391 return d->scriptValueFromJSCValue(d->newArray(d->currentFrame, length)); 2392 } 2393 2394 /*! 2395 Creates a QtScript object of class RegExp with the given 2396 \a pattern and \a flags. 2397 2398 The legal flags are 'g' (global), 'i' (ignore case), and 'm' 2399 (multiline). 2400 */ 2401 QScriptValue QScriptEngine::newRegExp(const QString &pattern, const QString &flags) 2402 { 2403 Q_D(QScriptEngine); 2404 QScript::APIShim shim(d); 2405 return d->scriptValueFromJSCValue(d->newRegExp(d->currentFrame, pattern, flags)); 1986 2406 } 1987 2407 … … 1994 2414 { 1995 2415 Q_D(QScriptEngine); 1996 JSC::ExecState* exec = d->currentFrame; 1997 JSC::JSValue val = JSC::jsNumber(exec, value); 1998 JSC::ArgList args(&val, 1); 1999 JSC::JSObject *result = JSC::constructDate(exec, args); 2000 return d->scriptValueFromJSCValue(result); 2416 QScript::APIShim shim(d); 2417 return d->scriptValueFromJSCValue(d->newDate(d->currentFrame, value)); 2001 2418 } 2002 2419 … … 2008 2425 QScriptValue QScriptEngine::newDate(const QDateTime &value) 2009 2426 { 2010 return newDate(QScript::FromDateTime(value)); 2427 Q_D(QScriptEngine); 2428 QScript::APIShim shim(d); 2429 return d->scriptValueFromJSCValue(d->newDate(d->currentFrame, value)); 2011 2430 } 2012 2431 … … 2031 2450 { 2032 2451 Q_D(QScriptEngine); 2452 QScript::APIShim shim(d); 2033 2453 JSC::JSValue jscCtor = d->scriptValueToJSCValue(ctor); 2034 2454 JSC::JSValue jscQMetaObject = d->newQMetaObject(metaObject, jscCtor); … … 2205 2625 { 2206 2626 Q_D(QScriptEngine); 2627 QScript::APIShim shim(d); 2207 2628 WTF::PassRefPtr<QScript::UStringSourceProviderWithFeedback> provider 2208 2629 = QScript::UStringSourceProviderWithFeedback::create(program, fileName, lineNumber, d); … … 2211 2632 2212 2633 JSC::ExecState* exec = d->currentFrame; 2213 JSC::EvalExecutable executable(exec, source);2634 WTF::RefPtr<JSC::EvalExecutable> executable = JSC::EvalExecutable::create(exec, source); 2214 2635 bool compile = true; 2215 return d->scriptValueFromJSCValue(d->evaluateHelper(exec, sourceId, &executable, compile)); 2216 } 2217 2218 /*! 2219 \internal 2220 \since 4.6 2636 return d->scriptValueFromJSCValue(d->evaluateHelper(exec, sourceId, executable.get(), compile)); 2637 } 2638 2639 /*! 2640 \since 4.7 2221 2641 2222 2642 Evaluates the given \a program and returns the result of the … … 2230 2650 return QScriptValue(); 2231 2651 2652 QScript::APIShim shim(d); 2232 2653 JSC::ExecState* exec = d->currentFrame; 2233 2654 JSC::EvalExecutable *executable = program_d->executable(exec, d); … … 2281 2702 { 2282 2703 Q_D(QScriptEngine); 2704 QScript::APIShim shim(d); 2283 2705 2284 2706 JSC::CallFrame* newFrame = d->pushContext(d->currentFrame, d->currentFrame->globalData().dynamicGlobalObject, … … 2341 2763 newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee); 2342 2764 } else { 2343 JSC::JSObject *jscObject = originalGlobalObject(); 2344 JSC::ScopeChainNode *scn = new JSC::ScopeChainNode(0, jscObject, &exec->globalData(), jscObject); 2345 newCallFrame->init(0, /*vPC=*/0, scn, exec, flags | ShouldRestoreCallFrame, argc, callee); 2765 newCallFrame->init(0, /*vPC=*/0, globalExec()->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee); 2346 2766 } 2347 2767 } else { … … 2372 2792 agent()->contextPop(); 2373 2793 Q_D(QScriptEngine); 2794 QScript::APIShim shim(d); 2374 2795 if (d->currentFrame->returnPC() != 0 || d->currentFrame->codeBlock() != 0 2375 2796 || !currentContext()->parentContext()) { … … 2407 2828 The exception state is cleared when evaluate() is called. 2408 2829 2409 \sa uncaughtException(), uncaughtExceptionLineNumber(), 2410 uncaughtExceptionBacktrace() 2830 \sa uncaughtException(), uncaughtExceptionLineNumber() 2411 2831 */ 2412 2832 bool QScriptEngine::hasUncaughtException() const … … 2426 2846 2427 2847 \sa hasUncaughtException(), uncaughtExceptionLineNumber(), 2428 uncaughtExceptionBacktrace()2429 2848 */ 2430 2849 QScriptValue QScriptEngine::uncaughtException() const … … 2446 2865 the second argument to evaluate(). 2447 2866 2448 \sa hasUncaughtException() , uncaughtExceptionBacktrace()2867 \sa hasUncaughtException() 2449 2868 */ 2450 2869 int QScriptEngine::uncaughtExceptionLineNumber() const … … 2458 2877 Returns a human-readable backtrace of the last uncaught exception. 2459 2878 2460 Each line is of the form \c{<function-name>(<arguments>)@<file-name>:<line-number>}.2879 It is in the form \c{<function-name>()@<file-name>:<line-number>}. 2461 2880 2462 2881 \sa uncaughtException() … … 2567 2986 { 2568 2987 Q_D(QScriptEngine); 2569 return d->create(type, ptr);2570 } 2571 2572 QScriptValue QScriptEnginePrivate::create(int type, const void *ptr) 2573 { 2574 Q_Q(QScriptEngine); 2988 QScript::APIShim shim(d); 2989 return d->scriptValueFromJSCValue(d->create(d->currentFrame, type, ptr)); 2990 } 2991 2992 JSC::JSValue QScriptEnginePrivate::create(JSC::ExecState *exec, int type, const void *ptr) 2993 { 2575 2994 Q_ASSERT(ptr != 0); 2576 QScriptValue result; 2577 QScriptTypeInfo *info = m_typeInfos.value(type); 2995 JSC::JSValue result; 2996 QScriptEnginePrivate *eng = exec ? QScript::scriptEngineFromExec(exec) : 0; 2997 QScriptTypeInfo *info = eng ? eng->m_typeInfos.value(type) : 0; 2578 2998 if (info && info->marshal) { 2579 result = info->marshal(q, ptr);2999 result = eng->scriptValueToJSCValue(info->marshal(eng->q_func(), ptr)); 2580 3000 } else { 2581 3001 // check if it's one of the types we know 2582 3002 switch (QMetaType::Type(type)) { 2583 3003 case QMetaType::Void: 2584 return QScriptValue(q, QScriptValue::UndefinedValue);3004 return JSC::jsUndefined(); 2585 3005 case QMetaType::Bool: 2586 return QScriptValue(q,*reinterpret_cast<const bool*>(ptr));3006 return JSC::jsBoolean(*reinterpret_cast<const bool*>(ptr)); 2587 3007 case QMetaType::Int: 2588 return QScriptValue(q, *reinterpret_cast<const int*>(ptr));3008 return JSC::jsNumber(exec, *reinterpret_cast<const int*>(ptr)); 2589 3009 case QMetaType::UInt: 2590 return QScriptValue(q, *reinterpret_cast<const uint*>(ptr));3010 return JSC::jsNumber(exec, *reinterpret_cast<const uint*>(ptr)); 2591 3011 case QMetaType::LongLong: 2592 return QScriptValue(q, qsreal(*reinterpret_cast<const qlonglong*>(ptr)));3012 return JSC::jsNumber(exec, qsreal(*reinterpret_cast<const qlonglong*>(ptr))); 2593 3013 case QMetaType::ULongLong: 2594 3014 #if defined(Q_OS_WIN) && defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 12008804 2595 3015 #pragma message("** NOTE: You need the Visual Studio Processor Pack to compile support for 64bit unsigned integers.") 2596 return QScriptValue(q, qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr)));3016 return JSC::jsNumber(exec, qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr))); 2597 3017 #elif defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) 2598 return QScriptValue(q, qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr)));3018 return JSC::jsNumber(exec, qsreal((qlonglong)*reinterpret_cast<const qulonglong*>(ptr))); 2599 3019 #else 2600 return QScriptValue(q, qsreal(*reinterpret_cast<const qulonglong*>(ptr)));3020 return JSC::jsNumber(exec, qsreal(*reinterpret_cast<const qulonglong*>(ptr))); 2601 3021 #endif 2602 3022 case QMetaType::Double: 2603 return QScriptValue(q, qsreal(*reinterpret_cast<const double*>(ptr)));3023 return JSC::jsNumber(exec, qsreal(*reinterpret_cast<const double*>(ptr))); 2604 3024 case QMetaType::QString: 2605 return QScriptValue(q, *reinterpret_cast<const QString*>(ptr));3025 return JSC::jsString(exec, *reinterpret_cast<const QString*>(ptr)); 2606 3026 case QMetaType::Float: 2607 return QScriptValue(q, *reinterpret_cast<const float*>(ptr));3027 return JSC::jsNumber(exec, *reinterpret_cast<const float*>(ptr)); 2608 3028 case QMetaType::Short: 2609 return QScriptValue(q, *reinterpret_cast<const short*>(ptr));3029 return JSC::jsNumber(exec, *reinterpret_cast<const short*>(ptr)); 2610 3030 case QMetaType::UShort: 2611 return QScriptValue(q, *reinterpret_cast<const unsigned short*>(ptr));3031 return JSC::jsNumber(exec, *reinterpret_cast<const unsigned short*>(ptr)); 2612 3032 case QMetaType::Char: 2613 return QScriptValue(q, *reinterpret_cast<const char*>(ptr));3033 return JSC::jsNumber(exec, *reinterpret_cast<const char*>(ptr)); 2614 3034 case QMetaType::UChar: 2615 return QScriptValue(q, *reinterpret_cast<const unsigned char*>(ptr));3035 return JSC::jsNumber(exec, *reinterpret_cast<const unsigned char*>(ptr)); 2616 3036 case QMetaType::QChar: 2617 return QScriptValue(q, (*reinterpret_cast<const QChar*>(ptr)).unicode());3037 return JSC::jsNumber(exec, (*reinterpret_cast<const QChar*>(ptr)).unicode()); 2618 3038 case QMetaType::QStringList: 2619 result = arrayFromStringList( *reinterpret_cast<const QStringList *>(ptr));3039 result = arrayFromStringList(exec, *reinterpret_cast<const QStringList *>(ptr)); 2620 3040 break; 2621 3041 case QMetaType::QVariantList: 2622 result = arrayFromVariantList( *reinterpret_cast<const QVariantList *>(ptr));3042 result = arrayFromVariantList(exec, *reinterpret_cast<const QVariantList *>(ptr)); 2623 3043 break; 2624 3044 case QMetaType::QVariantMap: 2625 result = objectFromVariantMap( *reinterpret_cast<const QVariantMap *>(ptr));3045 result = objectFromVariantMap(exec, *reinterpret_cast<const QVariantMap *>(ptr)); 2626 3046 break; 2627 3047 case QMetaType::QDateTime: 2628 result = q->newDate(*reinterpret_cast<const QDateTime *>(ptr));3048 result = newDate(exec, *reinterpret_cast<const QDateTime *>(ptr)); 2629 3049 break; 2630 3050 case QMetaType::QDate: 2631 result = q->newDate(QDateTime(*reinterpret_cast<const QDate *>(ptr)));3051 result = newDate(exec, QDateTime(*reinterpret_cast<const QDate *>(ptr))); 2632 3052 break; 2633 3053 #ifndef QT_NO_REGEXP 2634 3054 case QMetaType::QRegExp: 2635 result = q->newRegExp(*reinterpret_cast<const QRegExp *>(ptr));3055 result = newRegExp(exec, *reinterpret_cast<const QRegExp *>(ptr)); 2636 3056 break; 2637 3057 #endif … … 2639 3059 case QMetaType::QObjectStar: 2640 3060 case QMetaType::QWidgetStar: 2641 result = q->newQObject(*reinterpret_cast<QObject* const *>(ptr));3061 result = eng->newQObject(*reinterpret_cast<QObject* const *>(ptr)); 2642 3062 break; 2643 3063 #endif 3064 case QMetaType::QVariant: 3065 result = jscValueFromVariant(exec, *reinterpret_cast<const QVariant*>(ptr)); 3066 break; 2644 3067 default: 2645 3068 if (type == qMetaTypeId<QScriptValue>()) { 2646 result = *reinterpret_cast<const QScriptValue*>(ptr);2647 if (!result .isValid())2648 return QScriptValue(q, QScriptValue::UndefinedValue);3069 result = eng->scriptValueToJSCValue(*reinterpret_cast<const QScriptValue*>(ptr)); 3070 if (!result) 3071 return JSC::jsUndefined(); 2649 3072 } 2650 3073 … … 2652 3075 // lazy registration of some common list types 2653 3076 else if (type == qMetaTypeId<QObjectList>()) { 2654 qScriptRegisterSequenceMetaType<QObjectList>( q);2655 return create( type, ptr);3077 qScriptRegisterSequenceMetaType<QObjectList>(eng->q_func()); 3078 return create(exec, type, ptr); 2656 3079 } 2657 3080 #endif 2658 3081 else if (type == qMetaTypeId<QList<int> >()) { 2659 qScriptRegisterSequenceMetaType<QList<int> >( q);2660 return create( type, ptr);3082 qScriptRegisterSequenceMetaType<QList<int> >(eng->q_func()); 3083 return create(exec, type, ptr); 2661 3084 } 2662 3085 2663 3086 else { 2664 3087 QByteArray typeName = QMetaType::typeName(type); 2665 if (typeName == "QVariant")2666 result = scriptValueFromVariant(*reinterpret_cast<const QVariant*>(ptr));2667 3088 if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(ptr)) 2668 return QScriptValue(q, QScriptValue::NullValue);3089 return JSC::jsNull(); 2669 3090 else 2670 result = q->newVariant(QVariant(type, ptr));3091 result = eng->newVariant(QVariant(type, ptr)); 2671 3092 } 2672 3093 } 2673 3094 } 2674 if (result .isObject() && info && info->prototype2675 && JSC::JSValue::strictEqual( scriptValueToJSCValue(result.prototype()),originalGlobalObject()->objectPrototype())) {2676 result.setPrototype(scriptValueFromJSCValue(info->prototype));3095 if (result && result.isObject() && info && info->prototype 3096 && JSC::JSValue::strictEqual(exec, JSC::asObject(result)->prototype(), eng->originalGlobalObject()->objectPrototype())) { 3097 JSC::asObject(result)->setPrototype(info->prototype); 2677 3098 } 2678 3099 return result; 2679 3100 } 2680 3101 2681 bool QScriptEnginePrivate::convert(const QScriptValue &value, 2682 int type, void *ptr, 2683 QScriptEnginePrivate *eng) 2684 { 2685 if (!eng) 2686 eng = QScriptValuePrivate::getEngine(value); 3102 bool QScriptEnginePrivate::convertValue(JSC::ExecState *exec, JSC::JSValue value, 3103 int type, void *ptr) 3104 { 3105 QScriptEnginePrivate *eng = exec ? QScript::scriptEngineFromExec(exec) : 0; 2687 3106 if (eng) { 2688 3107 QScriptTypeInfo *info = eng->m_typeInfos.value(type); 2689 3108 if (info && info->demarshal) { 2690 info->demarshal( value, ptr);3109 info->demarshal(eng->scriptValueFromJSCValue(value), ptr); 2691 3110 return true; 2692 3111 } … … 2696 3115 switch (QMetaType::Type(type)) { 2697 3116 case QMetaType::Bool: 2698 *reinterpret_cast<bool*>(ptr) = value.toBoolean();3117 *reinterpret_cast<bool*>(ptr) = toBool(exec, value); 2699 3118 return true; 2700 3119 case QMetaType::Int: 2701 *reinterpret_cast<int*>(ptr) = value.toInt32();3120 *reinterpret_cast<int*>(ptr) = toInt32(exec, value); 2702 3121 return true; 2703 3122 case QMetaType::UInt: 2704 *reinterpret_cast<uint*>(ptr) = value.toUInt32();3123 *reinterpret_cast<uint*>(ptr) = toUInt32(exec, value); 2705 3124 return true; 2706 3125 case QMetaType::LongLong: 2707 *reinterpret_cast<qlonglong*>(ptr) = qlonglong( value.toInteger());3126 *reinterpret_cast<qlonglong*>(ptr) = qlonglong(toInteger(exec, value)); 2708 3127 return true; 2709 3128 case QMetaType::ULongLong: 2710 *reinterpret_cast<qulonglong*>(ptr) = qulonglong( value.toInteger());3129 *reinterpret_cast<qulonglong*>(ptr) = qulonglong(toInteger(exec, value)); 2711 3130 return true; 2712 3131 case QMetaType::Double: 2713 *reinterpret_cast<double*>(ptr) = value.toNumber();3132 *reinterpret_cast<double*>(ptr) = toNumber(exec, value); 2714 3133 return true; 2715 3134 case QMetaType::QString: … … 2717 3136 *reinterpret_cast<QString*>(ptr) = QString(); 2718 3137 else 2719 *reinterpret_cast<QString*>(ptr) = value.toString();3138 *reinterpret_cast<QString*>(ptr) = toString(exec, value); 2720 3139 return true; 2721 3140 case QMetaType::Float: 2722 *reinterpret_cast<float*>(ptr) = value.toNumber();3141 *reinterpret_cast<float*>(ptr) = toNumber(exec, value); 2723 3142 return true; 2724 3143 case QMetaType::Short: 2725 *reinterpret_cast<short*>(ptr) = short( value.toInt32());3144 *reinterpret_cast<short*>(ptr) = short(toInt32(exec, value)); 2726 3145 return true; 2727 3146 case QMetaType::UShort: 2728 *reinterpret_cast<unsigned short*>(ptr) = value.toUInt16();3147 *reinterpret_cast<unsigned short*>(ptr) = QScript::ToUInt16(toNumber(exec, value)); 2729 3148 return true; 2730 3149 case QMetaType::Char: 2731 *reinterpret_cast<char*>(ptr) = char( value.toInt32());3150 *reinterpret_cast<char*>(ptr) = char(toInt32(exec, value)); 2732 3151 return true; 2733 3152 case QMetaType::UChar: 2734 *reinterpret_cast<unsigned char*>(ptr) = (unsigned char)( value.toInt32());3153 *reinterpret_cast<unsigned char*>(ptr) = (unsigned char)(toInt32(exec, value)); 2735 3154 return true; 2736 3155 case QMetaType::QChar: 2737 3156 if (value.isString()) { 2738 QString str = value.toString();3157 QString str = toString(exec, value); 2739 3158 *reinterpret_cast<QChar*>(ptr) = str.isEmpty() ? QChar() : str.at(0); 2740 3159 } else { 2741 *reinterpret_cast<QChar*>(ptr) = QChar( value.toUInt16());3160 *reinterpret_cast<QChar*>(ptr) = QChar(QScript::ToUInt16(toNumber(exec, value))); 2742 3161 } 2743 3162 return true; 2744 3163 case QMetaType::QDateTime: 2745 if ( value.isDate()) {2746 *reinterpret_cast<QDateTime *>(ptr) = value.toDateTime();3164 if (isDate(value)) { 3165 *reinterpret_cast<QDateTime *>(ptr) = toDateTime(exec, value); 2747 3166 return true; 2748 3167 } break; 2749 3168 case QMetaType::QDate: 2750 if ( value.isDate()) {2751 *reinterpret_cast<QDate *>(ptr) = value.toDateTime().date();3169 if (isDate(value)) { 3170 *reinterpret_cast<QDate *>(ptr) = toDateTime(exec, value).date(); 2752 3171 return true; 2753 3172 } break; 2754 3173 #ifndef QT_NO_REGEXP 2755 3174 case QMetaType::QRegExp: 2756 if ( value.isRegExp()) {2757 *reinterpret_cast<QRegExp *>(ptr) = value.toRegExp();3175 if (isRegExp(value)) { 3176 *reinterpret_cast<QRegExp *>(ptr) = toRegExp(exec, value); 2758 3177 return true; 2759 3178 } break; … … 2761 3180 #ifndef QT_NO_QOBJECT 2762 3181 case QMetaType::QObjectStar: 2763 if ( value.isQObject() || value.isNull()) {2764 *reinterpret_cast<QObject* *>(ptr) = value.toQObject();3182 if (isQObject(value) || value.isNull()) { 3183 *reinterpret_cast<QObject* *>(ptr) = toQObject(exec, value); 2765 3184 return true; 2766 3185 } break; 2767 3186 case QMetaType::QWidgetStar: 2768 if ( value.isQObject() || value.isNull()) {2769 QObject *qo = value.toQObject();3187 if (isQObject(value) || value.isNull()) { 3188 QObject *qo = toQObject(exec, value); 2770 3189 if (!qo || qo->isWidgetType()) { 2771 3190 *reinterpret_cast<QWidget* *>(ptr) = reinterpret_cast<QWidget*>(qo); … … 2775 3194 #endif 2776 3195 case QMetaType::QStringList: 2777 if ( value.isArray()) {2778 *reinterpret_cast<QStringList *>(ptr) = stringListFromArray( value);3196 if (isArray(value)) { 3197 *reinterpret_cast<QStringList *>(ptr) = stringListFromArray(exec, value); 2779 3198 return true; 2780 3199 } break; 2781 3200 case QMetaType::QVariantList: 2782 if ( value.isArray()) {2783 *reinterpret_cast<QVariantList *>(ptr) = variantListFromArray( value);3201 if (isArray(value)) { 3202 *reinterpret_cast<QVariantList *>(ptr) = variantListFromArray(exec, JSC::asArray(value)); 2784 3203 return true; 2785 3204 } break; 2786 3205 case QMetaType::QVariantMap: 2787 if ( value.isObject()) {2788 *reinterpret_cast<QVariantMap *>(ptr) = variantMapFromObject( value);3206 if (isObject(value)) { 3207 *reinterpret_cast<QVariantMap *>(ptr) = variantMapFromObject(exec, JSC::asObject(value)); 2789 3208 return true; 2790 3209 } break; 3210 case QMetaType::QVariant: 3211 *reinterpret_cast<QVariant*>(ptr) = toVariant(exec, value); 3212 return true; 2791 3213 default: 2792 3214 ; … … 2795 3217 QByteArray name = QMetaType::typeName(type); 2796 3218 #ifndef QT_NO_QOBJECT 2797 if (convertToNativeQObject( value, name, reinterpret_cast<void* *>(ptr)))3219 if (convertToNativeQObject(exec, value, name, reinterpret_cast<void* *>(ptr))) 2798 3220 return true; 2799 3221 #endif 2800 if ( value.isVariant() && name.endsWith('*')) {3222 if (isVariant(value) && name.endsWith('*')) { 2801 3223 int valueType = QMetaType::type(name.left(name.size()-1)); 2802 QVariant &var = QScriptValuePrivate::get(value)->variantValue();3224 QVariant &var = variantValue(value); 2803 3225 if (valueType == var.userType()) { 2804 3226 *reinterpret_cast<void* *>(ptr) = var.data(); … … 2806 3228 } else { 2807 3229 // look in the prototype chain 2808 QScriptValue proto = value.prototype();3230 JSC::JSValue proto = JSC::asObject(value)->prototype(); 2809 3231 while (proto.isObject()) { 2810 3232 bool canCast = false; 2811 if ( proto.isVariant()) {2812 canCast = (type == proto.toVariant().userType())2813 || (valueType && (valueType == proto.toVariant().userType()));3233 if (isVariant(proto)) { 3234 canCast = (type == variantValue(proto).userType()) 3235 || (valueType && (valueType == variantValue(proto).userType())); 2814 3236 } 2815 3237 #ifndef QT_NO_QOBJECT 2816 else if ( proto.isQObject()) {3238 else if (isQObject(proto)) { 2817 3239 QByteArray className = name.left(name.size()-1); 2818 if (QObject *qobject = proto.toQObject())3240 if (QObject *qobject = toQObject(exec, proto)) 2819 3241 canCast = qobject->qt_metacast(className) != 0; 2820 3242 } … … 2828 3250 return true; 2829 3251 } 2830 proto = proto.prototype();3252 proto = JSC::asObject(proto)->prototype(); 2831 3253 } 2832 3254 } … … 2837 3259 if (!eng) 2838 3260 return false; 2839 *reinterpret_cast<QScriptValue*>(ptr) = value; 2840 return true; 2841 } else if (name == "QVariant") { 2842 *reinterpret_cast<QVariant*>(ptr) = value.toVariant(); 3261 *reinterpret_cast<QScriptValue*>(ptr) = eng->scriptValueFromJSCValue(value); 2843 3262 return true; 2844 3263 } … … 2850 3269 return false; 2851 3270 qScriptRegisterSequenceMetaType<QObjectList>(eng->q_func()); 2852 return convert (value, type, ptr, eng);3271 return convertValue(exec, value, type, ptr); 2853 3272 } 2854 3273 #endif … … 2857 3276 return false; 2858 3277 qScriptRegisterSequenceMetaType<QList<int> >(eng->q_func()); 2859 return convert (value, type, ptr, eng);3278 return convertValue(exec, value, type, ptr); 2860 3279 } 2861 3280 … … 2869 3288 } 2870 3289 3290 bool QScriptEnginePrivate::convertNumber(qsreal value, int type, void *ptr) 3291 { 3292 switch (QMetaType::Type(type)) { 3293 case QMetaType::Bool: 3294 *reinterpret_cast<bool*>(ptr) = QScript::ToBool(value); 3295 return true; 3296 case QMetaType::Int: 3297 *reinterpret_cast<int*>(ptr) = QScript::ToInt32(value); 3298 return true; 3299 case QMetaType::UInt: 3300 *reinterpret_cast<uint*>(ptr) = QScript::ToUInt32(value); 3301 return true; 3302 case QMetaType::LongLong: 3303 *reinterpret_cast<qlonglong*>(ptr) = qlonglong(QScript::ToInteger(value)); 3304 return true; 3305 case QMetaType::ULongLong: 3306 *reinterpret_cast<qulonglong*>(ptr) = qulonglong(QScript::ToInteger(value)); 3307 return true; 3308 case QMetaType::Double: 3309 *reinterpret_cast<double*>(ptr) = value; 3310 return true; 3311 case QMetaType::QString: 3312 *reinterpret_cast<QString*>(ptr) = QScript::ToString(value); 3313 return true; 3314 case QMetaType::Float: 3315 *reinterpret_cast<float*>(ptr) = value; 3316 return true; 3317 case QMetaType::Short: 3318 *reinterpret_cast<short*>(ptr) = short(QScript::ToInt32(value)); 3319 return true; 3320 case QMetaType::UShort: 3321 *reinterpret_cast<unsigned short*>(ptr) = QScript::ToUInt16(value); 3322 return true; 3323 case QMetaType::Char: 3324 *reinterpret_cast<char*>(ptr) = char(QScript::ToInt32(value)); 3325 return true; 3326 case QMetaType::UChar: 3327 *reinterpret_cast<unsigned char*>(ptr) = (unsigned char)(QScript::ToInt32(value)); 3328 return true; 3329 case QMetaType::QChar: 3330 *reinterpret_cast<QChar*>(ptr) = QChar(QScript::ToUInt16(value)); 3331 return true; 3332 default: 3333 break; 3334 } 3335 return false; 3336 } 3337 3338 bool QScriptEnginePrivate::convertString(const QString &value, int type, void *ptr) 3339 { 3340 switch (QMetaType::Type(type)) { 3341 case QMetaType::Bool: 3342 *reinterpret_cast<bool*>(ptr) = QScript::ToBool(value); 3343 return true; 3344 case QMetaType::Int: 3345 *reinterpret_cast<int*>(ptr) = QScript::ToInt32(value); 3346 return true; 3347 case QMetaType::UInt: 3348 *reinterpret_cast<uint*>(ptr) = QScript::ToUInt32(value); 3349 return true; 3350 case QMetaType::LongLong: 3351 *reinterpret_cast<qlonglong*>(ptr) = qlonglong(QScript::ToInteger(value)); 3352 return true; 3353 case QMetaType::ULongLong: 3354 *reinterpret_cast<qulonglong*>(ptr) = qulonglong(QScript::ToInteger(value)); 3355 return true; 3356 case QMetaType::Double: 3357 *reinterpret_cast<double*>(ptr) = QScript::ToNumber(value); 3358 return true; 3359 case QMetaType::QString: 3360 *reinterpret_cast<QString*>(ptr) = value; 3361 return true; 3362 case QMetaType::Float: 3363 *reinterpret_cast<float*>(ptr) = QScript::ToNumber(value); 3364 return true; 3365 case QMetaType::Short: 3366 *reinterpret_cast<short*>(ptr) = short(QScript::ToInt32(value)); 3367 return true; 3368 case QMetaType::UShort: 3369 *reinterpret_cast<unsigned short*>(ptr) = QScript::ToUInt16(value); 3370 return true; 3371 case QMetaType::Char: 3372 *reinterpret_cast<char*>(ptr) = char(QScript::ToInt32(value)); 3373 return true; 3374 case QMetaType::UChar: 3375 *reinterpret_cast<unsigned char*>(ptr) = (unsigned char)(QScript::ToInt32(value)); 3376 return true; 3377 case QMetaType::QChar: 3378 *reinterpret_cast<QChar*>(ptr) = QChar(QScript::ToUInt16(value)); 3379 return true; 3380 default: 3381 break; 3382 } 3383 return false; 3384 } 3385 2871 3386 bool QScriptEnginePrivate::hasDemarshalFunction(int type) const 2872 3387 { … … 2875 3390 } 2876 3391 3392 JSC::UString QScriptEnginePrivate::translationContextFromUrl(const JSC::UString &url) 3393 { 3394 if (url != cachedTranslationUrl) { 3395 cachedTranslationContext = QFileInfo(url).baseName(); 3396 cachedTranslationUrl = url; 3397 } 3398 return cachedTranslationContext; 3399 } 3400 2877 3401 /*! 2878 3402 \internal … … 2881 3405 { 2882 3406 Q_D(QScriptEngine); 2883 return QScriptEnginePrivate::convert(value, type, ptr, d); 3407 QScript::APIShim shim(d); 3408 return QScriptEnginePrivate::convertValue(d->currentFrame, d->scriptValueToJSCValue(value), type, ptr); 2884 3409 } 2885 3410 … … 2889 3414 bool QScriptEngine::convertV2(const QScriptValue &value, int type, void *ptr) 2890 3415 { 2891 return QScriptEnginePrivate::convert(value, type, ptr, /*engine=*/0); 3416 QScriptValuePrivate *vp = QScriptValuePrivate::get(value); 3417 if (vp) { 3418 switch (vp->type) { 3419 case QScriptValuePrivate::JavaScriptCore: { 3420 if (vp->engine) { 3421 QScript::APIShim shim(vp->engine); 3422 return QScriptEnginePrivate::convertValue(vp->engine->currentFrame, vp->jscValue, type, ptr); 3423 } else { 3424 return QScriptEnginePrivate::convertValue(0, vp->jscValue, type, ptr); 3425 } 3426 } 3427 case QScriptValuePrivate::Number: 3428 return QScriptEnginePrivate::convertNumber(vp->numberValue, type, ptr); 3429 case QScriptValuePrivate::String: 3430 return QScriptEnginePrivate::convertString(vp->stringValue, type, ptr); 3431 } 3432 } 3433 return false; 2892 3434 } 2893 3435 … … 2900 3442 { 2901 3443 Q_D(QScriptEngine); 3444 QScript::APIShim shim(d); 2902 3445 QScriptTypeInfo *info = d->m_typeInfos.value(type); 2903 3446 if (!info) { … … 2925 3468 \row \o qsTranslate() \o QCoreApplication::translate() 2926 3469 \row \o QT_TRANSLATE_NOOP() \o QT_TRANSLATE_NOOP() 3470 \row \o qsTrId() (since 4.7) \o qtTrId() 3471 \row \o QT_TRID_NOOP() (since 4.7) \o QT_TRID_NOOP() 2927 3472 \endtable 2928 3473 … … 2932 3477 { 2933 3478 Q_D(QScriptEngine); 3479 QScript::APIShim shim(d); 2934 3480 JSC::ExecState* exec = d->currentFrame; 2935 3481 JSC::JSValue jscObject = d->scriptValueToJSCValue(object); … … 2940 3486 JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 5, JSC::Identifier(exec, "qsTranslate"), QScript::functionQsTranslate)); 2941 3487 JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 2, JSC::Identifier(exec, "QT_TRANSLATE_NOOP"), QScript::functionQsTranslateNoOp)); 2942 JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC:: PrototypeFunction(exec, glob->prototypeFunctionStructure(), 3, JSC::Identifier(exec, "qsTr"), QScript::functionQsTr));3488 JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 3, JSC::Identifier(exec, "qsTr"), QScript::functionQsTr)); 2943 3489 JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "QT_TR_NOOP"), QScript::functionQsTrNoOp)); 3490 JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "qsTrId"), QScript::functionQsTrId)); 3491 JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "QT_TRID_NOOP"), QScript::functionQsTrIdNoOp)); 2944 3492 2945 3493 glob->stringPrototype()->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "arg"), QScript::stringProtoFuncArg)); … … 2965 3513 #else 2966 3514 Q_D(QScriptEngine); 3515 QScript::APIShim shim(d); 2967 3516 if (d->importedExtensions.contains(extension)) 2968 3517 return undefinedValue(); // already imported … … 3461 4010 request that garbage collection should be performed as soon as 3462 4011 possible. 4012 4013 \sa reportAdditionalMemoryCost() 3463 4014 */ 3464 4015 void QScriptEngine::collectGarbage() … … 3466 4017 Q_D(QScriptEngine); 3467 4018 d->collectGarbage(); 4019 } 4020 4021 /*! 4022 \since 4.7 4023 4024 Reports an additional memory cost of the given \a size, measured in 4025 bytes, to the garbage collector. 4026 4027 This function can be called to indicate that a Qt Script object has 4028 memory associated with it that isn't managed by Qt Script itself. 4029 Reporting the additional cost makes it more likely that the garbage 4030 collector will be triggered. 4031 4032 Note that if the additional memory is shared with objects outside 4033 the scripting environment, the cost should not be reported, since 4034 collecting the Qt Script object would not cause the memory to be 4035 freed anyway. 4036 4037 Negative \a size values are ignored, i.e. this function can't be 4038 used to report that the additional memory has been deallocated. 4039 4040 \sa collectGarbage() 4041 */ 4042 void QScriptEngine::reportAdditionalMemoryCost(int size) 4043 { 4044 Q_D(QScriptEngine); 4045 d->reportAdditionalMemoryCost(size); 3468 4046 } 3469 4047 … … 3548 4126 { 3549 4127 Q_D(QScriptEngine); 3550 4128 if (!isEvaluating()) 4129 return; 4130 d->abortResult = result; 3551 4131 d->timeoutChecker()->setShouldAbort(true); 3552 d->abortResult = result;4132 JSC::throwError(d->currentFrame, JSC::createInterruptedExecutionException(&d->currentFrame->globalData()).toObject(d->currentFrame)); 3553 4133 } 3554 4134 … … 3576 4156 return false; 3577 4157 QScriptEnginePrivate *engine = QScriptEnginePrivate::get(function.engine()); 4158 QScript::APIShim shim(engine); 3578 4159 JSC::JSValue jscReceiver = engine->scriptValueToJSCValue(receiver); 3579 4160 JSC::JSValue jscFunction = engine->scriptValueToJSCValue(function); … … 3602 4183 return false; 3603 4184 QScriptEnginePrivate *engine = QScriptEnginePrivate::get(function.engine()); 4185 QScript::APIShim shim(engine); 3604 4186 JSC::JSValue jscReceiver = engine->scriptValueToJSCValue(receiver); 3605 4187 JSC::JSValue jscFunction = engine->scriptValueToJSCValue(function); … … 3646 4228 return; 3647 4229 } 4230 QScript::APIShim shim(d); 3648 4231 if (d->activeAgent) 3649 4232 QScriptEngineAgentPrivate::get(d->activeAgent)->detach(); … … 3681 4264 { 3682 4265 Q_D(QScriptEngine); 3683 QScriptString result; 3684 QScriptStringPrivate *p = new QScriptStringPrivate(d, JSC::Identifier(d->currentFrame, str), QScriptStringPrivate::HeapAllocated); 3685 QScriptStringPrivate::init(result, p); 3686 d->registerScriptString(p); 3687 return result; 4266 QScript::APIShim shim(d); 4267 return d->toStringHandle(JSC::Identifier(d->currentFrame, str)); 3688 4268 } 3689 4269 … … 3710 4290 { 3711 4291 Q_D(QScriptEngine); 4292 QScript::APIShim shim(d); 3712 4293 JSC::JSValue jscValue = d->scriptValueToJSCValue(value); 3713 4294 if (!jscValue || jscValue.isUndefined() || jscValue.isNull()) … … 3861 4442 #endif 3862 4443 4444 #ifdef Q_CC_MSVC 4445 // Try to prevent compiler from crashing. 4446 #pragma optimize("", off) 4447 #endif 4448 3863 4449 QT_END_NAMESPACE
Note:
See TracChangeset
for help on using the changeset viewer.