Changeset 62377 in webkit
- Timestamp:
- Jul 2, 2010 3:37:31 AM (14 years ago)
- Location:
- trunk/JavaScriptCore/qt
- Files:
-
- 1 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/qt/api/qscriptengine.cpp
r62078 r62377 97 97 98 98 /*! 99 Returns true if the last script evaluation resulted in an uncaught 100 exception; otherwise returns false. 101 102 The exception state is cleared when evaluate() is called. 103 104 \sa uncaughtException(), uncaughtExceptionLineNumber(), 105 uncaughtExceptionBacktrace() 106 */ 107 bool QScriptEngine::hasUncaughtException() const 108 { 109 return d_ptr->hasUncaughtException(); 110 } 111 112 /*! 113 Returns the current uncaught exception, or an invalid QScriptValue 114 if there is no uncaught exception. 115 116 The exception value is typically an \c{Error} object; in that case, 117 you can call toString() on the return value to obtain an error 118 message. 119 120 \sa hasUncaughtException(), uncaughtExceptionLineNumber(), 121 uncaughtExceptionBacktrace() 122 */ 123 QScriptValue QScriptEngine::uncaughtException() const 124 { 125 return QScriptValuePrivate::get(d_ptr->uncaughtException()); 126 } 127 128 /*! 129 Clears any uncaught exceptions in this engine. 130 131 \sa hasUncaughtException() 132 */ 133 void QScriptEngine::clearExceptions() 134 { 135 d_ptr->clearExceptions(); 136 } 137 138 /*! 139 Returns the line number where the last uncaught exception occurred. 140 141 Line numbers are 1-based, unless a different base was specified as 142 the second argument to evaluate(). 143 144 \sa hasUncaughtException(), uncaughtExceptionBacktrace() 145 */ 146 int QScriptEngine::uncaughtExceptionLineNumber() const 147 { 148 return d_ptr->uncaughtExceptionLineNumber(); 149 } 150 151 /*! 152 Returns a human-readable backtrace of the last uncaught exception. 153 154 Each line is of the form \c{<function-name>(<arguments>)@<file-name>:<line-number>}. 155 156 \sa uncaughtException() 157 */ 158 QStringList QScriptEngine::uncaughtExceptionBacktrace() const 159 { 160 return d_ptr->uncaughtExceptionBacktrace(); 161 } 162 163 /*! 99 164 Runs the garbage collector. 100 165 -
trunk/JavaScriptCore/qt/api/qscriptengine.h
r62078 r62377 43 43 QScriptValue evaluate(const QScriptProgram& program); 44 44 45 bool hasUncaughtException() const; 46 QScriptValue uncaughtException() const; 47 void clearExceptions(); 48 int uncaughtExceptionLineNumber() const; 49 QStringList uncaughtExceptionBacktrace() const; 50 45 51 void collectGarbage(); 46 52 void reportAdditionalMemoryCost(int cost); -
trunk/JavaScriptCore/qt/api/qscriptengine_p.cpp
r62078 r62377 32 32 : q_ptr(const_cast<QScriptEngine*>(engine)) 33 33 , m_context(JSGlobalContextCreate(0)) 34 , m_exception(0) 34 35 { 35 36 } … … 37 38 QScriptEnginePrivate::~QScriptEnginePrivate() 38 39 { 40 if (m_exception) 41 JSValueUnprotect(m_context, m_exception); 39 42 JSGlobalContextRelease(m_context); 40 43 } … … 78 81 } 79 82 83 QScriptValuePrivate* QScriptEnginePrivate::uncaughtException() const 84 { 85 return m_exception ? new QScriptValuePrivate(this, m_exception) : new QScriptValuePrivate(); 86 } 87 80 88 QScriptValuePrivate* QScriptEnginePrivate::newObject() const 81 89 { … … 85 93 QScriptValuePrivate* QScriptEnginePrivate::newArray(uint length) const 86 94 { 87 JSObjectRef array = JSObjectMakeArray(m_context, /* argumentCount */ 0, /* arguments */ 0, /* exception */ 0); 95 JSValueRef exception = 0; 96 JSObjectRef array = JSObjectMakeArray(m_context, /* argumentCount */ 0, /* arguments */ 0, &exception); 88 97 89 if (length > 0) { 90 JSRetainPtr<JSStringRef> lengthRef(Adopt, JSStringCreateWithUTF8CString("length")); 91 JSObjectSetProperty(m_context, array, lengthRef.get(), JSValueMakeNumber(m_context, length), kJSPropertyAttributeNone, /* exception */ 0); 98 if (!exception) { 99 if (length > 0) { 100 JSRetainPtr<JSStringRef> lengthRef(Adopt, JSStringCreateWithUTF8CString("length")); 101 // array is an Array instance, so an exception should not occure here. 102 JSObjectSetProperty(m_context, array, lengthRef.get(), JSValueMakeNumber(m_context, length), kJSPropertyAttributeNone, /* exception */ 0); 103 } 104 } else { 105 setException(exception, NotNullException); 106 return new QScriptValuePrivate(); 92 107 } 93 108 -
trunk/JavaScriptCore/qt/api/qscriptengine_p.h
r62078 r62377 27 27 #include "qscriptvalue.h" 28 28 #include <JavaScriptCore/JavaScript.h> 29 #include <JavaScriptCore/JSRetainPtr.h> 29 30 #include <JSBasePrivate.h> 30 31 #include <QtCore/qshareddata.h> 31 32 #include <QtCore/qstring.h> 33 #include <QtCore/qstringlist.h> 32 34 33 35 class QScriptEngine; … … 42 44 ~QScriptEnginePrivate(); 43 45 46 enum SetExceptionFlag { 47 IgnoreNullException = 0x01, 48 NotNullException = 0x02, 49 }; 50 44 51 QScriptSyntaxCheckResultPrivate* checkSyntax(const QString& program); 45 52 QScriptValuePrivate* evaluate(const QString& program, const QString& fileName, int lineNumber); 46 53 QScriptValuePrivate* evaluate(const QScriptProgramPrivate* program); 47 54 inline JSValueRef evaluate(JSStringRef program, JSStringRef fileName, int lineNumber); 55 56 inline bool hasUncaughtException() const; 57 QScriptValuePrivate* uncaughtException() const; 58 inline void clearExceptions(); 59 inline void setException(JSValueRef exception, const /* SetExceptionFlags */ unsigned flags = IgnoreNullException); 60 inline int uncaughtExceptionLineNumber() const; 61 inline QStringList uncaughtExceptionBacktrace() const; 48 62 49 63 inline void collectGarbage(); … … 67 81 QScriptEngine* q_ptr; 68 82 JSGlobalContextRef m_context; 83 JSValueRef m_exception; 69 84 }; 70 85 … … 79 94 JSValueRef exception; 80 95 JSValueRef result = JSEvaluateScript(m_context, program, /* Global Object */ 0, fileName, lineNumber, &exception); 81 if (!result) 96 if (!result) { 97 setException(exception, NotNullException); 82 98 return exception; // returns an exception 99 } 100 clearExceptions(); 83 101 return result; 102 } 103 104 bool QScriptEnginePrivate::hasUncaughtException() const 105 { 106 return m_exception; 107 } 108 109 void QScriptEnginePrivate::clearExceptions() 110 { 111 if (m_exception) 112 JSValueUnprotect(m_context, m_exception); 113 m_exception = 0; 114 } 115 116 void QScriptEnginePrivate::setException(JSValueRef exception, const /* SetExceptionFlags */ unsigned flags) 117 { 118 if (!((flags & NotNullException) || exception)) 119 return; 120 Q_ASSERT(exception); 121 122 if (m_exception) 123 JSValueUnprotect(m_context, m_exception); 124 JSValueProtect(m_context, exception); 125 m_exception = exception; 126 } 127 128 int QScriptEnginePrivate::uncaughtExceptionLineNumber() const 129 { 130 if (!hasUncaughtException() || !JSValueIsObject(m_context, m_exception)) 131 return -1; 132 133 JSValueRef exception = 0; 134 JSRetainPtr<JSStringRef> lineNumberPropertyName(Adopt, QScriptConverter::toString("line")); 135 JSValueRef lineNumber = JSObjectGetProperty(m_context, const_cast<JSObjectRef>(m_exception), lineNumberPropertyName.get(), &exception); 136 int result = JSValueToNumber(m_context, lineNumber, &exception); 137 return exception ? -1 : result; 138 } 139 140 QStringList QScriptEnginePrivate::uncaughtExceptionBacktrace() const 141 { 142 if (!hasUncaughtException() || !JSValueIsObject(m_context, m_exception)) 143 return QStringList(); 144 145 JSValueRef exception = 0; 146 JSRetainPtr<JSStringRef> fileNamePropertyName(Adopt, QScriptConverter::toString("sourceURL")); 147 JSRetainPtr<JSStringRef> lineNumberPropertyName(Adopt, QScriptConverter::toString("line")); 148 JSValueRef jsFileName = JSObjectGetProperty(m_context, const_cast<JSObjectRef>(m_exception), fileNamePropertyName.get(), &exception); 149 JSValueRef jsLineNumber = JSObjectGetProperty(m_context, const_cast<JSObjectRef>(m_exception), lineNumberPropertyName.get(), &exception); 150 JSRetainPtr<JSStringRef> fileName(Adopt, JSValueToStringCopy(m_context, jsFileName, &exception)); 151 int lineNumber = JSValueToNumber(m_context, jsLineNumber, &exception); 152 return QStringList(QString::fromLatin1("<anonymous>()@%0:%1") 153 .arg(QScriptConverter::toString(fileName.get())) 154 .arg(QScriptConverter::toString(exception ? -1 : lineNumber))); 84 155 } 85 156 -
trunk/JavaScriptCore/qt/api/qscriptvalue_p.h
r62119 r62377 446 446 case JSPrimitive: 447 447 case JSObject: 448 JSRetainPtr<JSStringRef> ptr(Adopt, JSValueToStringCopy(*m_engine, *this, /* exception */ 0)); 448 JSValueRef exception = 0; 449 JSRetainPtr<JSStringRef> ptr(Adopt, JSValueToStringCopy(*m_engine, *this, &exception)); 450 m_engine->setException(exception); 449 451 return QScriptConverter::toString(ptr.get()); 450 452 } … … 460 462 case JSPrimitive: 461 463 case JSObject: 462 return JSValueToNumber(*m_engine, *this, /* exception */ 0); 464 { 465 JSValueRef exception = 0; 466 qsreal result = JSValueToNumber(*m_engine, *this, &exception); 467 m_engine->setException(exception); 468 return result; 469 } 463 470 case CNumber: 464 471 return u.m_number; … … 589 596 if (engine != this->engine()) 590 597 qWarning("QScriptEngine::toObject: cannot convert value created in a different engine"); 591 JSObjectRef object = JSValueToObject(*m_engine, *this, /* exception */ 0); 598 JSValueRef exception = 0; 599 JSObjectRef object = JSValueToObject(*m_engine, *this, &exception); 592 600 if (object) 593 601 return new QScriptValuePrivate(m_engine.constData(), object); 602 else 603 m_engine->setException(exception, QScriptEnginePrivate::NotNullException); 604 594 605 } 595 606 return new QScriptValuePrivate; … … 676 687 } 677 688 678 return JSValueIsEqual(*m_engine, *this, *other, /* exception */ 0); 689 JSValueRef exception = 0; 690 bool result = JSValueIsEqual(*m_engine, *this, *other, &exception); 691 m_engine->setException(exception); 692 return result; 679 693 } 680 694 … … 720 734 if (!isJSBased() || !other->isObject()) 721 735 return false; 722 return JSValueIsInstanceOfConstructor(*m_engine, *this, *other, /* exception */ 0); 736 JSValueRef exception = 0; 737 bool result = JSValueIsInstanceOfConstructor(*m_engine, *this, *other, &exception); 738 m_engine->setException(exception); 739 return result; 723 740 } 724 741 … … 814 831 JSValueRef exception = 0; 815 832 JSValueRef result = JSObjectCallAsFunction(*m_engine, *this, /* thisObject */ 0, argc, argv.constData(), &exception); 816 if (!result && exception) 833 if (!result && exception) { 834 m_engine->setException(exception); 817 835 return new QScriptValuePrivate(engine(), exception); 836 } 818 837 if (result && !exception) 819 838 return new QScriptValuePrivate(engine(), result); … … 856 875 JSObjectRef globalObject = JSContextGetGlobalObject(*m_engine); 857 876 JSStringRef errorAttrName = QScriptConverter::toString(name); 858 JSValueRef error = JSObjectGetProperty(*m_engine, globalObject, errorAttrName, /* exception */ 0); 877 JSValueRef exception = 0; 878 JSValueRef error = JSObjectGetProperty(*m_engine, globalObject, errorAttrName, &exception); 859 879 JSStringRelease(errorAttrName); 860 return JSValueIsInstanceOfConstructor(*m_engine, *this, JSValueToObject(*m_engine, error, /* exception */ 0), /* exception */ 0); 880 bool result = JSValueIsInstanceOfConstructor(*m_engine, *this, JSValueToObject(*m_engine, error, &exception), &exception); 881 m_engine->setException(exception); 882 return result; 861 883 } 862 884 -
trunk/JavaScriptCore/qt/tests/qscriptengine/tst_qscriptengine.cpp
r62078 r62377 49 49 void toObjectTwoEngines(); 50 50 void newArray(); 51 void uncaughtException(); 51 52 }; 52 53 … … 433 434 } 434 435 436 void tst_QScriptEngine::uncaughtException() 437 { 438 QScriptEngine eng; 439 QScriptValue fun = eng.evaluate("(function foo () { return null; });"); 440 QVERIFY(!eng.uncaughtException().isValid()); 441 QVERIFY(fun.isFunction()); 442 QScriptValue throwFun = eng.evaluate("( function() { throw new Error('Pong'); });"); 443 QVERIFY(throwFun.isFunction()); 444 { 445 eng.evaluate("a = 10"); 446 QVERIFY(!eng.hasUncaughtException()); 447 QVERIFY(!eng.uncaughtException().isValid()); 448 } 449 { 450 eng.evaluate("1 = 2"); 451 QVERIFY(eng.hasUncaughtException()); 452 eng.clearExceptions(); 453 QVERIFY(!eng.hasUncaughtException()); 454 } 455 { 456 // Check if the call or toString functions can remove the last exception. 457 QVERIFY(throwFun.call().isError()); 458 QVERIFY(eng.hasUncaughtException()); 459 QScriptValue exception = eng.uncaughtException(); 460 fun.call(); 461 exception.toString(); 462 QVERIFY(eng.hasUncaughtException()); 463 QVERIFY(eng.uncaughtException().strictlyEquals(exception)); 464 } 465 eng.clearExceptions(); 466 { 467 // Check if in the call function a new exception can override an existing one. 468 throwFun.call(); 469 QVERIFY(eng.hasUncaughtException()); 470 QScriptValue exception = eng.uncaughtException(); 471 throwFun.call(); 472 QVERIFY(eng.hasUncaughtException()); 473 QVERIFY(!exception.strictlyEquals(eng.uncaughtException())); 474 } 475 { 476 eng.evaluate("throwFun = (function foo () { throw new Error('bla') });"); 477 eng.evaluate("1;\nthrowFun();"); 478 QVERIFY(eng.hasUncaughtException()); 479 QCOMPARE(eng.uncaughtExceptionLineNumber(), 1); 480 eng.clearExceptions(); 481 QVERIFY(!eng.hasUncaughtException()); 482 } 483 for (int x = 1; x < 4; ++x) { 484 QScriptValue ret = eng.evaluate("a = 10;\nb = 20;\n0 = 0;\n", 485 QString::fromLatin1("FooScript") + QString::number(x), 486 /* lineNumber */ x); 487 QVERIFY(eng.hasUncaughtException()); 488 QCOMPARE(eng.uncaughtExceptionLineNumber(), x + 2); 489 QVERIFY(eng.uncaughtException().strictlyEquals(ret)); 490 QVERIFY(eng.hasUncaughtException()); 491 QVERIFY(eng.uncaughtException().strictlyEquals(ret)); 492 QString backtrace = QString::fromLatin1("<anonymous>()@FooScript") + QString::number(x) + ":" + QString::number(x + 2); 493 QCOMPARE(eng.uncaughtExceptionBacktrace().join(""), backtrace); 494 QVERIFY(fun.call().isNull()); 495 QVERIFY(eng.hasUncaughtException()); 496 QCOMPARE(eng.uncaughtExceptionLineNumber(), x + 2); 497 QVERIFY(eng.uncaughtException().strictlyEquals(ret)); 498 eng.clearExceptions(); 499 QVERIFY(!eng.hasUncaughtException()); 500 QCOMPARE(eng.uncaughtExceptionLineNumber(), -1); 501 QVERIFY(!eng.uncaughtException().isValid()); 502 eng.evaluate("2 = 3"); 503 QVERIFY(eng.hasUncaughtException()); 504 QScriptValue ret2 = throwFun.call(); 505 QVERIFY(ret2.isError()); 506 QVERIFY(eng.hasUncaughtException()); 507 QVERIFY(eng.uncaughtException().strictlyEquals(ret2)); 508 QCOMPARE(eng.uncaughtExceptionLineNumber(), 1); 509 eng.clearExceptions(); 510 QVERIFY(!eng.hasUncaughtException()); 511 eng.evaluate("1 + 2"); 512 QVERIFY(!eng.hasUncaughtException()); 513 } 514 } 515 435 516 QTEST_MAIN(tst_QScriptEngine) 436 517 #include "tst_qscriptengine.moc"
Note: See TracChangeset
for help on using the changeset viewer.