src/script/api/qscriptengine.cpp
changeset 37 758a864f9613
parent 33 3e2da88830cd
equal deleted inserted replaced
36:ef0373b55136 37:758a864f9613
    42 
    42 
    43 #include <math.h>
    43 #include <math.h>
    44 
    44 
    45 #include "CodeBlock.h"
    45 #include "CodeBlock.h"
    46 #include "Error.h"
    46 #include "Error.h"
    47 #include "JSLock.h"
       
    48 #include "Interpreter.h"
    47 #include "Interpreter.h"
    49 
    48 
    50 #include "PrototypeFunction.h"
    49 #include "PrototypeFunction.h"
    51 #include "InitializeThreading.h"
    50 #include "InitializeThreading.h"
    52 #include "ObjectPrototype.h"
    51 #include "ObjectPrototype.h"
   150   error); in that case, the return value is the value that was thrown
   149   error); in that case, the return value is the value that was thrown
   151   (typically an \c{Error} object). You can check whether the
   150   (typically an \c{Error} object). You can check whether the
   152   evaluation caused an exception by calling hasUncaughtException(). In
   151   evaluation caused an exception by calling hasUncaughtException(). In
   153   that case, you can call toString() on the error object to obtain an
   152   that case, you can call toString() on the error object to obtain an
   154   error message. The current uncaught exception is also available
   153   error message. The current uncaught exception is also available
   155   through uncaughtException(). You can obtain a human-readable
   154   through uncaughtException().
   156   backtrace of the exception with uncaughtExceptionBacktrace().
       
   157   Calling clearExceptions() will cause any uncaught exceptions to be
   155   Calling clearExceptions() will cause any uncaught exceptions to be
   158   cleared.
   156   cleared.
   159 
   157 
   160   \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 4
   158   \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 4
   161 
   159 
   782 
   780 
   783 static JSC::JSValue JSC_HOST_CALL functionQsTranslate(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
   781 static JSC::JSValue JSC_HOST_CALL functionQsTranslate(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
   784 static JSC::JSValue JSC_HOST_CALL functionQsTranslateNoOp(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
   782 static JSC::JSValue JSC_HOST_CALL functionQsTranslateNoOp(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
   785 static JSC::JSValue JSC_HOST_CALL functionQsTr(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
   783 static JSC::JSValue JSC_HOST_CALL functionQsTr(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
   786 static JSC::JSValue JSC_HOST_CALL functionQsTrNoOp(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
   784 static JSC::JSValue JSC_HOST_CALL functionQsTrNoOp(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
       
   785 static JSC::JSValue JSC_HOST_CALL functionQsTrId(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
       
   786 static JSC::JSValue JSC_HOST_CALL functionQsTrIdNoOp(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
   787 
   787 
   788 JSC::JSValue JSC_HOST_CALL functionQsTranslate(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
   788 JSC::JSValue JSC_HOST_CALL functionQsTranslate(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
   789 {
   789 {
   790     if (args.size() < 2)
   790     if (args.size() < 2)
   791         return JSC::throwError(exec, JSC::GeneralError, "qsTranslate() requires at least two arguments");
   791         return JSC::throwError(exec, JSC::GeneralError, "qsTranslate() requires at least two arguments");
   892     if (args.size() < 1)
   892     if (args.size() < 1)
   893         return JSC::jsUndefined();
   893         return JSC::jsUndefined();
   894     return args.at(0);
   894     return args.at(0);
   895 }
   895 }
   896 
   896 
       
   897 JSC::JSValue JSC_HOST_CALL functionQsTrId(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
       
   898 {
       
   899     if (args.size() < 1)
       
   900         return JSC::throwError(exec, JSC::GeneralError, "qsTrId() requires at least one argument");
       
   901     if (!args.at(0).isString())
       
   902         return JSC::throwError(exec, JSC::TypeError, "qsTrId(): first argument (id) must be a string");
       
   903     if ((args.size() > 1) && !args.at(1).isNumber())
       
   904         return JSC::throwError(exec, JSC::TypeError, "qsTrId(): second argument (n) must be a number");
       
   905     JSC::UString id = args.at(0).toString(exec);
       
   906     int n = -1;
       
   907     if (args.size() > 1)
       
   908         n = args.at(1).toInt32(exec);
       
   909     return JSC::jsString(exec, qtTrId(QScript::convertToLatin1(id).constData(), n));
       
   910 }
       
   911 
       
   912 JSC::JSValue JSC_HOST_CALL functionQsTrIdNoOp(JSC::ExecState *, JSC::JSObject*, JSC::JSValue, const JSC::ArgList &args)
       
   913 {
       
   914     if (args.size() < 1)
       
   915         return JSC::jsUndefined();
       
   916     return args.at(0);
       
   917 }
       
   918 
   897 static JSC::JSValue JSC_HOST_CALL stringProtoFuncArg(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
   919 static JSC::JSValue JSC_HOST_CALL stringProtoFuncArg(JSC::ExecState*, JSC::JSObject*, JSC::JSValue, const JSC::ArgList&);
   898 
   920 
   899 JSC::JSValue JSC_HOST_CALL stringProtoFuncArg(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue thisObject, const JSC::ArgList &args)
   921 JSC::JSValue JSC_HOST_CALL stringProtoFuncArg(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue thisObject, const JSC::ArgList &args)
   900 {
   922 {
   901     QString value(thisObject.toString(exec));
   923     QString value(thisObject.toString(exec));
  1001 
  1023 
  1002     detachAllRegisteredScriptValues();
  1024     detachAllRegisteredScriptValues();
  1003     detachAllRegisteredScriptStrings();
  1025     detachAllRegisteredScriptStrings();
  1004     qDeleteAll(m_qobjectData);
  1026     qDeleteAll(m_qobjectData);
  1005     qDeleteAll(m_typeInfos);
  1027     qDeleteAll(m_typeInfos);
  1006     JSC::JSLock lock(false);
       
  1007     globalData->heap.destroy();
  1028     globalData->heap.destroy();
  1008     globalData->deref();
  1029     globalData->deref();
  1009     while (freeScriptValues) {
  1030     while (freeScriptValues) {
  1010         QScriptValuePrivate *p = freeScriptValues;
  1031         QScriptValuePrivate *p = freeScriptValues;
  1011         freeScriptValues = p->next;
  1032         freeScriptValues = p->next;
  1290     return globalData->heap.isBusy();
  1311     return globalData->heap.isBusy();
  1291 }
  1312 }
  1292 
  1313 
  1293 void QScriptEnginePrivate::collectGarbage()
  1314 void QScriptEnginePrivate::collectGarbage()
  1294 {
  1315 {
  1295     JSC::JSLock lock(false);
       
  1296     QScript::APIShim shim(this);
  1316     QScript::APIShim shim(this);
  1297     globalData->heap.collectAllGarbage();
  1317     globalData->heap.collectAllGarbage();
  1298 }
  1318 }
  1299 
  1319 
  1300 void QScriptEnginePrivate::reportAdditionalMemoryCost(int size)
  1320 void QScriptEnginePrivate::reportAdditionalMemoryCost(int size)
  1320 JSC::JSValue QScriptEnginePrivate::evaluateHelper(JSC::ExecState *exec, intptr_t sourceId,
  1340 JSC::JSValue QScriptEnginePrivate::evaluateHelper(JSC::ExecState *exec, intptr_t sourceId,
  1321                                                   JSC::EvalExecutable *executable,
  1341                                                   JSC::EvalExecutable *executable,
  1322                                                   bool &compile)
  1342                                                   bool &compile)
  1323 {
  1343 {
  1324     Q_Q(QScriptEngine);
  1344     Q_Q(QScriptEngine);
  1325     JSC::JSLock lock(false); // ### hmmm
       
  1326     QBoolBlocker inEvalBlocker(inEval, true);
  1345     QBoolBlocker inEvalBlocker(inEval, true);
  1327     q->currentContext()->activationObject(); //force the creation of a context for native function;
  1346     q->currentContext()->activationObject(); //force the creation of a context for native function;
  1328 
  1347 
  1329     JSC::Debugger* debugger = originalGlobalObject()->debugger();
  1348     JSC::Debugger* debugger = originalGlobalObject()->debugger();
  1330     if (debugger)
  1349     if (debugger)
  2605     bool compile = true;
  2624     bool compile = true;
  2606     return d->scriptValueFromJSCValue(d->evaluateHelper(exec, sourceId, executable.get(), compile));
  2625     return d->scriptValueFromJSCValue(d->evaluateHelper(exec, sourceId, executable.get(), compile));
  2607 }
  2626 }
  2608 
  2627 
  2609 /*!
  2628 /*!
  2610   \internal
  2629   \since 4.7
  2611   \since 4.6
       
  2612 
  2630 
  2613   Evaluates the given \a program and returns the result of the
  2631   Evaluates the given \a program and returns the result of the
  2614   evaluation.
  2632   evaluation.
  2615 */
  2633 */
  2616 QScriptValue QScriptEngine::evaluate(const QScriptProgram &program)
  2634 QScriptValue QScriptEngine::evaluate(const QScriptProgram &program)
  2798   Returns true if the last script evaluation resulted in an uncaught
  2816   Returns true if the last script evaluation resulted in an uncaught
  2799   exception; otherwise returns false.
  2817   exception; otherwise returns false.
  2800 
  2818 
  2801   The exception state is cleared when evaluate() is called.
  2819   The exception state is cleared when evaluate() is called.
  2802 
  2820 
  2803   \sa uncaughtException(), uncaughtExceptionLineNumber(),
  2821   \sa uncaughtException(), uncaughtExceptionLineNumber()
  2804       uncaughtExceptionBacktrace()
       
  2805 */
  2822 */
  2806 bool QScriptEngine::hasUncaughtException() const
  2823 bool QScriptEngine::hasUncaughtException() const
  2807 {
  2824 {
  2808     Q_D(const QScriptEngine);
  2825     Q_D(const QScriptEngine);
  2809     JSC::ExecState* exec = d->globalExec();
  2826     JSC::ExecState* exec = d->globalExec();
  2817   The exception value is typically an \c{Error} object; in that case,
  2834   The exception value is typically an \c{Error} object; in that case,
  2818   you can call toString() on the return value to obtain an error
  2835   you can call toString() on the return value to obtain an error
  2819   message.
  2836   message.
  2820 
  2837 
  2821   \sa hasUncaughtException(), uncaughtExceptionLineNumber(),
  2838   \sa hasUncaughtException(), uncaughtExceptionLineNumber(),
  2822       uncaughtExceptionBacktrace()
       
  2823 */
  2839 */
  2824 QScriptValue QScriptEngine::uncaughtException() const
  2840 QScriptValue QScriptEngine::uncaughtException() const
  2825 {
  2841 {
  2826     Q_D(const QScriptEngine);
  2842     Q_D(const QScriptEngine);
  2827     QScriptValue result;
  2843     QScriptValue result;
  2837   Returns the line number where the last uncaught exception occurred.
  2853   Returns the line number where the last uncaught exception occurred.
  2838 
  2854 
  2839   Line numbers are 1-based, unless a different base was specified as
  2855   Line numbers are 1-based, unless a different base was specified as
  2840   the second argument to evaluate().
  2856   the second argument to evaluate().
  2841 
  2857 
  2842   \sa hasUncaughtException(), uncaughtExceptionBacktrace()
  2858   \sa hasUncaughtException()
  2843 */
  2859 */
  2844 int QScriptEngine::uncaughtExceptionLineNumber() const
  2860 int QScriptEngine::uncaughtExceptionLineNumber() const
  2845 {
  2861 {
  2846     if (!hasUncaughtException())
  2862     if (!hasUncaughtException())
  2847         return -1;
  2863         return -1;
  2849 }
  2865 }
  2850 
  2866 
  2851 /*!
  2867 /*!
  2852   Returns a human-readable backtrace of the last uncaught exception.
  2868   Returns a human-readable backtrace of the last uncaught exception.
  2853 
  2869 
  2854   Each line is of the form \c{<function-name>(<arguments>)@<file-name>:<line-number>}.
  2870   It is in the form \c{<function-name>()@<file-name>:<line-number>}.
  2855 
  2871 
  2856   \sa uncaughtException()
  2872   \sa uncaughtException()
  2857 */
  2873 */
  2858 QStringList QScriptEngine::uncaughtExceptionBacktrace() const
  2874 QStringList QScriptEngine::uncaughtExceptionBacktrace() const
  2859 {
  2875 {
  3440     \header \o Script Function \o Corresponding C++ Function
  3456     \header \o Script Function \o Corresponding C++ Function
  3441     \row    \o qsTr()       \o QObject::tr()
  3457     \row    \o qsTr()       \o QObject::tr()
  3442     \row    \o QT_TR_NOOP() \o QT_TR_NOOP()
  3458     \row    \o QT_TR_NOOP() \o QT_TR_NOOP()
  3443     \row    \o qsTranslate() \o QCoreApplication::translate()
  3459     \row    \o qsTranslate() \o QCoreApplication::translate()
  3444     \row    \o QT_TRANSLATE_NOOP() \o QT_TRANSLATE_NOOP()
  3460     \row    \o QT_TRANSLATE_NOOP() \o QT_TRANSLATE_NOOP()
       
  3461     \row    \o qsTrId() (since 4.7) \o qtTrId()
       
  3462     \row    \o QT_TRID_NOOP() (since 4.7) \o QT_TRID_NOOP()
  3445     \endtable
  3463     \endtable
  3446 
  3464 
  3447   \sa {Internationalization with Qt}
  3465   \sa {Internationalization with Qt}
  3448 */
  3466 */
  3449 void QScriptEngine::installTranslatorFunctions(const QScriptValue &object)
  3467 void QScriptEngine::installTranslatorFunctions(const QScriptValue &object)
  3458 //    unsigned attribs = JSC::DontEnum;
  3476 //    unsigned attribs = JSC::DontEnum;
  3459     JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 5, JSC::Identifier(exec, "qsTranslate"), QScript::functionQsTranslate));
  3477     JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 5, JSC::Identifier(exec, "qsTranslate"), QScript::functionQsTranslate));
  3460     JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 2, JSC::Identifier(exec, "QT_TRANSLATE_NOOP"), QScript::functionQsTranslateNoOp));
  3478     JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 2, JSC::Identifier(exec, "QT_TRANSLATE_NOOP"), QScript::functionQsTranslateNoOp));
  3461     JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 3, JSC::Identifier(exec, "qsTr"), QScript::functionQsTr));
  3479     JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 3, JSC::Identifier(exec, "qsTr"), QScript::functionQsTr));
  3462     JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "QT_TR_NOOP"), QScript::functionQsTrNoOp));
  3480     JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "QT_TR_NOOP"), QScript::functionQsTrNoOp));
       
  3481     JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "qsTrId"), QScript::functionQsTrId));
       
  3482     JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "QT_TRID_NOOP"), QScript::functionQsTrIdNoOp));
  3463 
  3483 
  3464     glob->stringPrototype()->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "arg"), QScript::stringProtoFuncArg));
  3484     glob->stringPrototype()->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "arg"), QScript::stringProtoFuncArg));
  3465 }
  3485 }
  3466 
  3486 
  3467 /*!
  3487 /*!
  4194     if (agent && (agent->engine() != this)) {
  4214     if (agent && (agent->engine() != this)) {
  4195         qWarning("QScriptEngine::setAgent(): "
  4215         qWarning("QScriptEngine::setAgent(): "
  4196                  "cannot set agent belonging to different engine");
  4216                  "cannot set agent belonging to different engine");
  4197         return;
  4217         return;
  4198     }
  4218     }
       
  4219     QScript::APIShim shim(d);
  4199     if (d->activeAgent)
  4220     if (d->activeAgent)
  4200         QScriptEngineAgentPrivate::get(d->activeAgent)->detach();
  4221         QScriptEngineAgentPrivate::get(d->activeAgent)->detach();
  4201     d->activeAgent = agent;
  4222     d->activeAgent = agent;
  4202     if (agent) {
  4223     if (agent) {
  4203         QScriptEngineAgentPrivate::get(agent)->attach();
  4224         QScriptEngineAgentPrivate::get(agent)->attach();