diff options
Diffstat (limited to 'src/script/api/qscriptengine.cpp')
-rw-r--r-- | src/script/api/qscriptengine.cpp | 258 |
1 files changed, 193 insertions, 65 deletions
diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index d2e96d1..0b8a2e4 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -42,6 +42,7 @@ #include <math.h> +#include "CodeBlock.h" #include "Error.h" #include "JSLock.h" #include "Interpreter.h" @@ -260,6 +261,22 @@ QT_BEGIN_NAMESPACE whether an engine is currently running a script by calling isEvaluating(). + \section1 Garbage Collection + + Qt Script objects may be garbage collected when they are no longer + referenced. There is no guarantee as to when automatic garbage + collection will take place. + + The collectGarbage() function can be called to explicitly request + garbage collection. + + The reportAdditionalMemoryCost() function can be called to indicate + that a Qt Script object occupies memory that isn't managed by the + scripting environment. Reporting the additional cost makes it more + likely that the garbage collector will be triggered. This can be + useful, for example, when many custom, native Qt Script objects are + allocated. + \section1 Core Debugging/Tracing Facilities Since Qt 4.4, you can be notified of events pertaining to script @@ -292,6 +309,7 @@ QT_BEGIN_NAMESPACE \value ExcludeSuperClassProperties The script object will not expose properties inherited from the superclass. \value ExcludeSuperClassContents Shorthand form for ExcludeSuperClassMethods | ExcludeSuperClassProperties \value ExcludeDeleteLater The script object will not expose the QObject::deleteLater() slot. + \value ExcludeSlots The script object will not expose the QObject's slots. \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. \value PreferExistingWrapperObject If a wrapper object with the requested configuration already exists, return that object. \value SkipMethodsInEnumeration Don't include methods (signals and slots) when enumerating the object's properties. @@ -563,7 +581,7 @@ JSC::JSValue JSC_HOST_CALL functionDisconnect(JSC::ExecState *exec, JSC::JSObjec slot = arg1; else { QScript::SaveFrameHelper saveFrame(engine, exec); - QString propertyName(QScriptEnginePrivate::toString(exec, arg1)); + JSC::UString propertyName = QScriptEnginePrivate::toString(exec, arg1); slot = QScriptEnginePrivate::property(exec, arg0, propertyName, QScriptValue::ResolvePrototype); } } @@ -645,7 +663,7 @@ JSC::JSValue JSC_HOST_CALL functionConnect(JSC::ExecState *exec, JSC::JSObject * slot = arg1; else { QScript::SaveFrameHelper saveFrame(engine, exec); - QString propertyName = QScriptEnginePrivate::toString(exec, arg1); + JSC::UString propertyName = QScriptEnginePrivate::toString(exec, arg1); slot = QScriptEnginePrivate::property(exec, arg0, propertyName, QScriptValue::ResolvePrototype); } } @@ -723,32 +741,32 @@ JSC::JSValue JSC_HOST_CALL functionQsTranslate(JSC::ExecState *exec, JSC::JSObje if ((args.size() > 4) && !args.at(4).isNumber()) return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): fifth argument (n) must be a number"); #ifndef QT_NO_QOBJECT - QString context(args.at(0).toString(exec)); + JSC::UString context = args.at(0).toString(exec); #endif - QString text(args.at(1).toString(exec)); + JSC::UString text = args.at(1).toString(exec); #ifndef QT_NO_QOBJECT - QString comment; + JSC::UString comment; if (args.size() > 2) comment = args.at(2).toString(exec); QCoreApplication::Encoding encoding = QCoreApplication::CodecForTr; if (args.size() > 3) { - QString encStr(args.at(3).toString(exec)); - if (encStr == QLatin1String("CodecForTr")) + JSC::UString encStr = args.at(3).toString(exec); + if (encStr == "CodecForTr") encoding = QCoreApplication::CodecForTr; - else if (encStr == QLatin1String("UnicodeUTF8")) + else if (encStr == "UnicodeUTF8") encoding = QCoreApplication::UnicodeUTF8; else - return JSC::throwError(exec, JSC::GeneralError, QString::fromLatin1("qsTranslate(): invalid encoding '%s'").arg(encStr)); + return JSC::throwError(exec, JSC::GeneralError, QString::fromLatin1("qsTranslate(): invalid encoding '%0'").arg(encStr)); } int n = -1; if (args.size() > 4) n = args.at(4).toInt32(exec); #endif - QString result; + JSC::UString result; #ifndef QT_NO_QOBJECT - result = QCoreApplication::translate(context.toLatin1().constData(), - text.toLatin1().constData(), - comment.toLatin1().constData(), + result = QCoreApplication::translate(QScript::convertToLatin1(context).constData(), + QScript::convertToLatin1(text).constData(), + QScript::convertToLatin1(comment).constData(), encoding, n); #else result = text; @@ -772,27 +790,37 @@ JSC::JSValue JSC_HOST_CALL functionQsTr(JSC::ExecState *exec, JSC::JSObject*, JS if ((args.size() > 1) && !args.at(1).isString()) return JSC::throwError(exec, JSC::GeneralError, "qsTr(): second argument (comment) must be a string"); if ((args.size() > 2) && !args.at(2).isNumber()) - return JSC::throwError(exec, JSC::GeneralError, "qsTranslate(): third argument (n) must be a number"); + return JSC::throwError(exec, JSC::GeneralError, "qsTr(): third argument (n) must be a number"); #ifndef QT_NO_QOBJECT - QString context; - QScriptContext *ctx = QScriptEnginePrivate::contextForFrame(exec); - if (ctx && ctx->parentContext()) - context = QFileInfo(QScriptContextInfo(ctx->parentContext()).fileName()).baseName(); + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + JSC::UString context; + // The first non-empty source URL in the call stack determines the translation context. + { + JSC::ExecState *frame = exec->removeHostCallFrameFlag(); + while (frame) { + if (frame->codeBlock() && frame->codeBlock()->source() + && !frame->codeBlock()->source()->url().isEmpty()) { + context = engine->translationContextFromUrl(frame->codeBlock()->source()->url()); + break; + } + frame = frame->callerFrame()->removeHostCallFrameFlag(); + } + } #endif - QString text(args.at(0).toString(exec)); + JSC::UString text = args.at(0).toString(exec); #ifndef QT_NO_QOBJECT - QString comment; + JSC::UString comment; if (args.size() > 1) comment = args.at(1).toString(exec); int n = -1; if (args.size() > 2) n = args.at(2).toInt32(exec); #endif - QString result; + JSC::UString result; #ifndef QT_NO_QOBJECT - result = QCoreApplication::translate(context.toLatin1().constData(), - text.toLatin1().constData(), - comment.toLatin1().constData(), + result = QCoreApplication::translate(QScript::convertToLatin1(context).constData(), + QScript::convertToLatin1(text).constData(), + QScript::convertToLatin1(comment).constData(), QCoreApplication::CodecForTr, n); #else result = text; @@ -858,7 +886,7 @@ QScriptEnginePrivate::QScriptEnginePrivate() return; } JSC::initializeThreading(); - + JSC::IdentifierTable *oldTable = JSC::currentIdentifierTable(); globalData = JSC::JSGlobalData::create().releaseRef(); globalData->clientData = new QScript::GlobalClientData(this); JSC::JSGlobalObject *globalObject = new (globalData)QScript::GlobalObject(); @@ -894,10 +922,15 @@ QScriptEnginePrivate::QScriptEnginePrivate() activeAgent = 0; agentLineNumber = -1; processEventsInterval = -1; + cachedTranslationUrl = JSC::UString(); + cachedTranslationContext = JSC::UString(); + JSC::setCurrentIdentifierTable(oldTable); } QScriptEnginePrivate::~QScriptEnginePrivate() { + QScript::APIShim shim(this); + //disconnect all loadedScripts and generate all jsc::debugger::scriptUnload events QHash<intptr_t,QScript::UStringSourceProviderWithFeedback*>::const_iterator it; for (it = loadedScripts.constBegin(); it != loadedScripts.constEnd(); ++it) @@ -988,8 +1021,7 @@ JSC::JSValue QScriptEnginePrivate::objectFromVariantMap(JSC::ExecState *exec, co QVariantMap QScriptEnginePrivate::variantMapFromObject(JSC::ExecState *exec, JSC::JSValue obj) { JSC::PropertyNameArray propertyNames(exec); - propertyNames.setShouldCache(false); - JSC::asObject(obj)->getOwnPropertyNames(exec, propertyNames, /*includeNonEnumerable=*/true); + JSC::asObject(obj)->getOwnPropertyNames(exec, propertyNames, JSC::IncludeDontEnumProperties); QVariantMap vmap; JSC::PropertyNameArray::const_iterator it = propertyNames.begin(); for( ; it != propertyNames.end(); ++it) @@ -1048,11 +1080,15 @@ void QScriptEnginePrivate::setGlobalObject(JSC::JSObject *object) if (object == globalObject()) return; QScript::GlobalObject *glob = static_cast<QScript::GlobalObject*>(originalGlobalObject()); - if (object == originalGlobalObjectProxy) + if (object == originalGlobalObjectProxy) { glob->customGlobalObject = 0; - else { + // Sync the internal prototype, since JSObject::prototype() is not virtual. + glob->setPrototype(originalGlobalObjectProxy->prototype()); + } else { Q_ASSERT(object != originalGlobalObject()); glob->customGlobalObject = object; + // Sync the internal prototype, since JSObject::prototype() is not virtual. + glob->setPrototype(object->prototype()); } } @@ -1187,7 +1223,14 @@ bool QScriptEnginePrivate::isCollecting() const void QScriptEnginePrivate::collectGarbage() { JSC::JSLock lock(false); - globalData->heap.collect(); + QScript::APIShim shim(this); + globalData->heap.collectAllGarbage(); +} + +void QScriptEnginePrivate::reportAdditionalMemoryCost(int size) +{ + if (size > 0) + globalData->heap.reportExtraMemoryCost(size); } QScript::TimeoutCheckerProxy *QScriptEnginePrivate::timeoutChecker() const @@ -1218,7 +1261,7 @@ JSC::JSValue QScriptEnginePrivate::evaluateHelper(JSC::ExecState *exec, intptr_t debugger->evaluateStart(sourceId); q->clearExceptions(); - JSC::DynamicGlobalObjectScope dynamicGlobalObjectScope(exec, exec->scopeChain()->globalObject()); + JSC::DynamicGlobalObjectScope dynamicGlobalObjectScope(exec, exec->scopeChain()->globalObject); if (compile) { JSC::JSObject* error = executable->compile(exec, exec->scopeChain()); @@ -1471,7 +1514,7 @@ void QScriptEnginePrivate::detachAllRegisteredScriptStrings() #ifndef QT_NO_REGEXP -extern QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax); +Q_DECL_IMPORT extern QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax); JSC::JSValue QScriptEnginePrivate::newRegExp(JSC::ExecState *exec, const QRegExp ®exp) { @@ -1580,9 +1623,9 @@ QRegExp QScriptEnginePrivate::toRegExp(JSC::ExecState *exec, JSC::JSValue value) { if (!isRegExp(value)) return QRegExp(); - QString pattern = toString(exec, property(exec, value, QLatin1String("source"), QScriptValue::ResolvePrototype)); + QString pattern = toString(exec, property(exec, value, "source", QScriptValue::ResolvePrototype)); Qt::CaseSensitivity kase = Qt::CaseSensitive; - if (toBool(exec, property(exec, value, QLatin1String("ignoreCase"), QScriptValue::ResolvePrototype))) + if (toBool(exec, property(exec, value, "ignoreCase", QScriptValue::ResolvePrototype))) kase = Qt::CaseInsensitive; return QRegExp(pattern, kase, QRegExp::RegExp2); } @@ -1591,7 +1634,9 @@ QRegExp QScriptEnginePrivate::toRegExp(JSC::ExecState *exec, JSC::JSValue value) QVariant QScriptEnginePrivate::toVariant(JSC::ExecState *exec, JSC::JSValue value) { - if (isObject(value)) { + if (!value) { + return QVariant(); + } else if (isObject(value)) { if (isVariant(value)) return variantValue(value); #ifndef QT_NO_QOBJECT @@ -1637,7 +1682,7 @@ JSC::JSValue QScriptEnginePrivate::propertyHelper(JSC::ExecState *exec, JSC::JSV } if (!result && (resolveMode & QScriptValue::ResolveScope)) { // ### check if it's a function object and look in the scope chain - JSC::JSValue scope = property(exec, value, QString::fromLatin1("__qt_scope__"), QScriptValue::ResolveLocal); + JSC::JSValue scope = property(exec, value, "__qt_scope__", QScriptValue::ResolveLocal); if (isObject(scope)) result = property(exec, scope, id, resolveMode); } @@ -1668,15 +1713,15 @@ void QScriptEnginePrivate::setProperty(JSC::ExecState *exec, JSC::JSValue object // deleting getter/setter if ((flags & QScriptValue::PropertyGetter) && (flags & QScriptValue::PropertySetter)) { // deleting both: just delete the property - thisObject->deleteProperty(exec, id, /*checkDontDelete=*/false); + thisObject->deleteProperty(exec, id); } else if (flags & QScriptValue::PropertyGetter) { // preserve setter, if there is one - thisObject->deleteProperty(exec, id, /*checkDontDelete=*/false); + thisObject->deleteProperty(exec, id); if (setter && setter.isObject()) thisObject->defineSetter(exec, id, JSC::asObject(setter)); } else { // flags & QScriptValue::PropertySetter // preserve getter, if there is one - thisObject->deleteProperty(exec, id, /*checkDontDelete=*/false); + thisObject->deleteProperty(exec, id); if (getter && getter.isObject()) thisObject->defineGetter(exec, id, JSC::asObject(getter)); } @@ -1706,10 +1751,10 @@ void QScriptEnginePrivate::setProperty(JSC::ExecState *exec, JSC::JSValue object } if (!value) { // ### check if it's a getter/setter property - thisObject->deleteProperty(exec, id, /*checkDontDelete=*/false); + thisObject->deleteProperty(exec, id); } else if (flags != QScriptValue::KeepExistingFlags) { if (thisObject->hasOwnProperty(exec, id)) - thisObject->deleteProperty(exec, id, /*checkDontDelete=*/false); // ### hmmm - can't we just update the attributes? + thisObject->deleteProperty(exec, id); // ### hmmm - can't we just update the attributes? unsigned attribs = 0; if (flags & QScriptValue::ReadOnly) attribs |= JSC::ReadOnly; @@ -1730,7 +1775,7 @@ void QScriptEnginePrivate::setProperty(JSC::ExecState *exec, JSC::JSValue object JSC::JSValue value, const QScriptValue::PropertyFlags &flags) { if (!value) { - JSC::asObject(objectValue)->deleteProperty(exec, index, /*checkDontDelete=*/false); + JSC::asObject(objectValue)->deleteProperty(exec, index); } else { if ((flags & QScriptValue::PropertyGetter) || (flags & QScriptValue::PropertySetter)) { // fall back to string-based setProperty(), since there is no @@ -1764,7 +1809,7 @@ QScriptValue::PropertyFlags QScriptEnginePrivate::propertyFlags(JSC::ExecState * JSC::PropertyDescriptor descriptor; if (object->getOwnPropertyDescriptor(exec, id, descriptor)) attribs = descriptor.attributes(); - else if (!object->getPropertyAttributes(exec, id, attribs)) { + else { if ((mode & QScriptValue::ResolvePrototype) && object->prototype() && object->prototype().isObject()) { JSC::JSValue proto = object->prototype(); return propertyFlags(exec, proto, id, mode); @@ -1791,6 +1836,15 @@ QScriptValue::PropertyFlags QScriptEnginePrivate::propertyFlags(JSC::ExecState * return result; } +QScriptString QScriptEnginePrivate::toStringHandle(const JSC::Identifier &name) +{ + QScriptString result; + QScriptStringPrivate *p = new QScriptStringPrivate(this, name, QScriptStringPrivate::HeapAllocated); + QScriptStringPrivate::init(result, p); + registerScriptString(p); + return result; +} + #ifdef QT_NO_QOBJECT QScriptEngine::QScriptEngine() @@ -1863,6 +1917,7 @@ QScriptEngine::~QScriptEngine() QScriptValue QScriptEngine::globalObject() const { Q_D(const QScriptEngine); + QScript::APIShim shim(const_cast<QScriptEnginePrivate*>(d)); JSC::JSObject *result = d->globalObject(); return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue(result); } @@ -1884,6 +1939,7 @@ void QScriptEngine::setGlobalObject(const QScriptValue &object) Q_D(QScriptEngine); if (!object.isObject()) return; + QScript::APIShim shim(d); JSC::JSObject *jscObject = JSC::asObject(d->scriptValueToJSCValue(object)); d->setGlobalObject(jscObject); } @@ -1940,6 +1996,7 @@ QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, int length) { Q_D(QScriptEngine); + QScript::APIShim shim(d); JSC::ExecState* exec = d->currentFrame; JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun); QScriptValue result = d->scriptValueFromJSCValue(function); @@ -1952,7 +2009,7 @@ QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, #ifndef QT_NO_REGEXP -extern QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax); +Q_DECL_IMPORT extern QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax); /*! Creates a QtScript object of class RegExp with the given @@ -1963,6 +2020,7 @@ extern QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax); QScriptValue QScriptEngine::newRegExp(const QRegExp ®exp) { Q_D(QScriptEngine); + QScript::APIShim shim(d); return d->scriptValueFromJSCValue(d->newRegExp(d->currentFrame, regexp)); } @@ -1976,11 +2034,12 @@ QScriptValue QScriptEngine::newRegExp(const QRegExp ®exp) prototype; otherwise, the prototype will be the Object prototype object. - \sa setDefaultPrototype(), QScriptValue::toVariant() + \sa setDefaultPrototype(), QScriptValue::toVariant(), reportAdditionalMemoryCost() */ QScriptValue QScriptEngine::newVariant(const QVariant &value) { Q_D(QScriptEngine); + QScript::APIShim shim(d); return d->scriptValueFromJSCValue(d->newVariant(value)); } @@ -2007,11 +2066,14 @@ QScriptValue QScriptEngine::newVariant(const QVariant &value) true), you can pass QScriptContext::thisObject() (the default constructed script object) to this function to initialize the new object. + + \sa reportAdditionalMemoryCost() */ QScriptValue QScriptEngine::newVariant(const QScriptValue &object, const QVariant &value) { Q_D(QScriptEngine); + QScript::APIShim shim(d); JSC::JSValue jsObject = d->scriptValueToJSCValue(object); return d->scriptValueFromJSCValue(d->newVariant(jsObject, value)); } @@ -2037,12 +2099,13 @@ QScriptValue QScriptEngine::newVariant(const QScriptValue &object, wrapper object (either by script code or C++) will result in a script exception. - \sa QScriptValue::toQObject() + \sa QScriptValue::toQObject(), reportAdditionalMemoryCost() */ QScriptValue QScriptEngine::newQObject(QObject *object, ValueOwnership ownership, const QObjectWrapOptions &options) { Q_D(QScriptEngine); + QScript::APIShim shim(d); JSC::JSValue jscQObject = d->newQObject(object, ownership, options); return d->scriptValueFromJSCValue(jscQObject); } @@ -2071,14 +2134,18 @@ QScriptValue QScriptEngine::newQObject(QObject *object, ValueOwnership ownership (QScriptContext::isCalledAsConstructor() returns true), you can pass QScriptContext::thisObject() (the default constructed script object) to this function to initialize the new object. + + \sa reportAdditionalMemoryCost() */ QScriptValue QScriptEngine::newQObject(const QScriptValue &scriptObject, QObject *qtObject, ValueOwnership ownership, const QObjectWrapOptions &options) { + Q_D(QScriptEngine); if (!scriptObject.isObject()) return newQObject(qtObject, ownership, options); + QScript::APIShim shim(d); JSC::JSObject *jscObject = JSC::asObject(QScriptValuePrivate::get(scriptObject)->jscValue); if (!jscObject->inherits(&QScriptObject::info)) { qWarning("QScriptEngine::newQObject(): changing class of non-QScriptObject not supported"); @@ -2109,6 +2176,7 @@ QScriptValue QScriptEngine::newQObject(const QScriptValue &scriptObject, QScriptValue QScriptEngine::newObject() { Q_D(QScriptEngine); + QScript::APIShim shim(d); return d->scriptValueFromJSCValue(d->newObject()); } @@ -2124,12 +2192,13 @@ QScriptValue QScriptEngine::newObject() \a data, if specified, is set as the internal data of the new object (using QScriptValue::setData()). - \sa QScriptValue::scriptClass() + \sa QScriptValue::scriptClass(), reportAdditionalMemoryCost() */ QScriptValue QScriptEngine::newObject(QScriptClass *scriptClass, const QScriptValue &data) { Q_D(QScriptEngine); + QScript::APIShim shim(d); JSC::ExecState* exec = d->currentFrame; QScriptObject *result = new (exec) QScriptObject(d->scriptObjectStructure); result->setDelegate(new QScript::ClassObjectDelegate(scriptClass)); @@ -2197,6 +2266,7 @@ QScriptValue QScriptEngine::newActivationObject() QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, int length) { Q_D(QScriptEngine); + QScript::APIShim shim(d); JSC::ExecState* exec = d->currentFrame; JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun); QScriptValue result = d->scriptValueFromJSCValue(function); @@ -2214,6 +2284,7 @@ QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, in QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionWithArgSignature fun, void *arg) { Q_D(QScriptEngine); + QScript::APIShim shim(d); JSC::ExecState* exec = d->currentFrame; JSC::JSValue function = new (exec)QScript::FunctionWithArgWrapper(exec, /*length=*/0, JSC::Identifier(exec, ""), fun, arg); QScriptValue result = d->scriptValueFromJSCValue(function); @@ -2232,6 +2303,7 @@ QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionWithArgSignature QScriptValue QScriptEngine::newArray(uint length) { Q_D(QScriptEngine); + QScript::APIShim shim(d); return d->scriptValueFromJSCValue(d->newArray(d->currentFrame, length)); } @@ -2245,6 +2317,7 @@ QScriptValue QScriptEngine::newArray(uint length) QScriptValue QScriptEngine::newRegExp(const QString &pattern, const QString &flags) { Q_D(QScriptEngine); + QScript::APIShim shim(d); return d->scriptValueFromJSCValue(d->newRegExp(d->currentFrame, pattern, flags)); } @@ -2256,6 +2329,7 @@ QScriptValue QScriptEngine::newRegExp(const QString &pattern, const QString &fla QScriptValue QScriptEngine::newDate(qsreal value) { Q_D(QScriptEngine); + QScript::APIShim shim(d); return d->scriptValueFromJSCValue(d->newDate(d->currentFrame, value)); } @@ -2267,6 +2341,7 @@ QScriptValue QScriptEngine::newDate(qsreal value) QScriptValue QScriptEngine::newDate(const QDateTime &value) { Q_D(QScriptEngine); + QScript::APIShim shim(d); return d->scriptValueFromJSCValue(d->newDate(d->currentFrame, value)); } @@ -2290,6 +2365,7 @@ QScriptValue QScriptEngine::newQMetaObject( const QMetaObject *metaObject, const QScriptValue &ctor) { Q_D(QScriptEngine); + QScript::APIShim shim(d); JSC::JSValue jscCtor = d->scriptValueToJSCValue(ctor); JSC::JSValue jscQMetaObject = d->newQMetaObject(metaObject, jscCtor); return d->scriptValueFromJSCValue(jscQMetaObject); @@ -2464,15 +2540,16 @@ QScriptSyntaxCheckResult QScriptEnginePrivate::checkSyntax(const QString &progra QScriptValue QScriptEngine::evaluate(const QString &program, const QString &fileName, int lineNumber) { Q_D(QScriptEngine); + QScript::APIShim shim(d); WTF::PassRefPtr<QScript::UStringSourceProviderWithFeedback> provider = QScript::UStringSourceProviderWithFeedback::create(program, fileName, lineNumber, d); intptr_t sourceId = provider->asID(); JSC::SourceCode source(provider, lineNumber); //after construction of SourceCode provider variable will be null. JSC::ExecState* exec = d->currentFrame; - JSC::EvalExecutable executable(exec, source); + WTF::RefPtr<JSC::EvalExecutable> executable = JSC::EvalExecutable::create(exec, source); bool compile = true; - return d->scriptValueFromJSCValue(d->evaluateHelper(exec, sourceId, &executable, compile)); + return d->scriptValueFromJSCValue(d->evaluateHelper(exec, sourceId, executable.get(), compile)); } /*! @@ -2489,6 +2566,7 @@ QScriptValue QScriptEngine::evaluate(const QScriptProgram &program) if (!program_d) return QScriptValue(); + QScript::APIShim shim(d); JSC::ExecState* exec = d->currentFrame; JSC::EvalExecutable *executable = program_d->executable(exec, d); bool compile = !program_d->isCompiled; @@ -2540,6 +2618,7 @@ QScriptContext *QScriptEngine::currentContext() const QScriptContext *QScriptEngine::pushContext() { Q_D(QScriptEngine); + QScript::APIShim shim(d); JSC::CallFrame* newFrame = d->pushContext(d->currentFrame, d->currentFrame->globalData().dynamicGlobalObject, JSC::ArgList(), /*callee = */0); @@ -2601,7 +2680,7 @@ JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, JSC::JSV newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee); } else { JSC::JSObject *jscObject = originalGlobalObject(); - JSC::ScopeChainNode *scn = new JSC::ScopeChainNode(0, jscObject, &exec->globalData(), jscObject); + JSC::ScopeChainNode *scn = new JSC::ScopeChainNode(0, jscObject, &exec->globalData(), exec->lexicalGlobalObject(), jscObject); newCallFrame->init(0, /*vPC=*/0, scn, exec, flags | ShouldRestoreCallFrame, argc, callee); } } else { @@ -2631,6 +2710,7 @@ void QScriptEngine::popContext() if (agent()) agent()->contextPop(); Q_D(QScriptEngine); + QScript::APIShim shim(d); if (d->currentFrame->returnPC() != 0 || d->currentFrame->codeBlock() != 0 || !currentContext()->parentContext()) { qWarning("QScriptEngine::popContext() doesn't match with pushContext()"); @@ -2826,6 +2906,7 @@ void QScriptEngine::setDefaultPrototype(int metaTypeId, const QScriptValue &prot QScriptValue QScriptEngine::create(int type, const void *ptr) { Q_D(QScriptEngine); + QScript::APIShim shim(d); return d->scriptValueFromJSCValue(d->create(d->currentFrame, type, ptr)); } @@ -2901,6 +2982,9 @@ JSC::JSValue QScriptEnginePrivate::create(JSC::ExecState *exec, int type, const result = eng->newQObject(*reinterpret_cast<QObject* const *>(ptr)); break; #endif + case QMetaType::QVariant: + result = jscValueFromVariant(exec, *reinterpret_cast<const QVariant*>(ptr)); + break; default: if (type == qMetaTypeId<QScriptValue>()) { result = eng->scriptValueToJSCValue(*reinterpret_cast<const QScriptValue*>(ptr)); @@ -2922,8 +3006,6 @@ JSC::JSValue QScriptEnginePrivate::create(JSC::ExecState *exec, int type, const else { QByteArray typeName = QMetaType::typeName(type); - if (typeName == "QVariant") - result = jscValueFromVariant(exec, *reinterpret_cast<const QVariant*>(ptr)); if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(ptr)) return JSC::jsNull(); else @@ -2932,7 +3014,7 @@ JSC::JSValue QScriptEnginePrivate::create(JSC::ExecState *exec, int type, const } } if (result && result.isObject() && info && info->prototype - && JSC::JSValue::strictEqual(JSC::asObject(result)->prototype(), eng->originalGlobalObject()->objectPrototype())) { + && JSC::JSValue::strictEqual(exec, JSC::asObject(result)->prototype(), eng->originalGlobalObject()->objectPrototype())) { JSC::asObject(result)->setPrototype(info->prototype); } return result; @@ -3046,6 +3128,9 @@ bool QScriptEnginePrivate::convertValue(JSC::ExecState *exec, JSC::JSValue value *reinterpret_cast<QVariantMap *>(ptr) = variantMapFromObject(exec, value); return true; } break; + case QMetaType::QVariant: + *reinterpret_cast<QVariant*>(ptr) = toVariant(exec, value); + return true; default: ; } @@ -3096,9 +3181,6 @@ bool QScriptEnginePrivate::convertValue(JSC::ExecState *exec, JSC::JSValue value return false; *reinterpret_cast<QScriptValue*>(ptr) = eng->scriptValueFromJSCValue(value); return true; - } else if (name == "QVariant") { - *reinterpret_cast<QVariant*>(ptr) = toVariant(exec, value); - return true; } // lazy registration of some common list types @@ -3228,12 +3310,22 @@ bool QScriptEnginePrivate::hasDemarshalFunction(int type) const return info && (info->demarshal != 0); } +JSC::UString QScriptEnginePrivate::translationContextFromUrl(const JSC::UString &url) +{ + if (url != cachedTranslationUrl) { + cachedTranslationContext = QFileInfo(url).baseName(); + cachedTranslationUrl = url; + } + return cachedTranslationContext; +} + /*! \internal */ bool QScriptEngine::convert(const QScriptValue &value, int type, void *ptr) { Q_D(QScriptEngine); + QScript::APIShim shim(d); return QScriptEnginePrivate::convertValue(d->currentFrame, d->scriptValueToJSCValue(value), type, ptr); } @@ -3246,8 +3338,12 @@ bool QScriptEngine::convertV2(const QScriptValue &value, int type, void *ptr) if (vp) { switch (vp->type) { case QScriptValuePrivate::JavaScriptCore: { - JSC::ExecState *exec = vp->engine ? vp->engine->currentFrame : 0; - return QScriptEnginePrivate::convertValue(exec, vp->jscValue, type, ptr); + if (vp->engine) { + QScript::APIShim shim(vp->engine); + return QScriptEnginePrivate::convertValue(vp->engine->currentFrame, vp->jscValue, type, ptr); + } else { + return QScriptEnginePrivate::convertValue(0, vp->jscValue, type, ptr); + } } case QScriptValuePrivate::Number: return QScriptEnginePrivate::convertNumber(vp->numberValue, type, ptr); @@ -3266,6 +3362,7 @@ void QScriptEngine::registerCustomType(int type, MarshalFunction mf, const QScriptValue &prototype) { Q_D(QScriptEngine); + QScript::APIShim shim(d); QScriptTypeInfo *info = d->m_typeInfos.value(type); if (!info) { info = new QScriptTypeInfo(); @@ -3298,15 +3395,16 @@ void QScriptEngine::registerCustomType(int type, MarshalFunction mf, void QScriptEngine::installTranslatorFunctions(const QScriptValue &object) { Q_D(QScriptEngine); + QScript::APIShim shim(d); JSC::ExecState* exec = d->currentFrame; JSC::JSValue jscObject = d->scriptValueToJSCValue(object); JSC::JSGlobalObject *glob = d->originalGlobalObject(); if (!jscObject || !jscObject.isObject()) - jscObject = glob; + jscObject = d->globalObject(); // unsigned attribs = JSC::DontEnum; JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 5, JSC::Identifier(exec, "qsTranslate"), QScript::functionQsTranslate)); JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 2, JSC::Identifier(exec, "QT_TRANSLATE_NOOP"), QScript::functionQsTranslateNoOp)); - JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 3, JSC::Identifier(exec, "qsTr"), QScript::functionQsTr)); + JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::PrototypeFunction(exec, glob->prototypeFunctionStructure(), 3, JSC::Identifier(exec, "qsTr"), QScript::functionQsTr)); JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "QT_TR_NOOP"), QScript::functionQsTrNoOp)); glob->stringPrototype()->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 1, JSC::Identifier(exec, "arg"), QScript::stringProtoFuncArg)); @@ -3331,6 +3429,7 @@ QScriptValue QScriptEngine::importExtension(const QString &extension) Q_UNUSED(extension); #else Q_D(QScriptEngine); + QScript::APIShim shim(d); if (d->importedExtensions.contains(extension)) return undefinedValue(); // already imported @@ -3827,6 +3926,8 @@ QStringList QScriptEngine::importedExtensions() const been created). However, you can call this function to explicitly request that garbage collection should be performed as soon as possible. + + \sa reportAdditionalMemoryCost() */ void QScriptEngine::collectGarbage() { @@ -3835,6 +3936,33 @@ void QScriptEngine::collectGarbage() } /*! + \since 4.7 + + Reports an additional memory cost of the given \a size, measured in + bytes, to the garbage collector. + + This function can be called to indicate that a Qt Script object has + memory associated with it that isn't managed by Qt Script itself. + Reporting the additional cost makes it more likely that the garbage + collector will be triggered. + + Note that if the additional memory is shared with objects outside + the scripting environment, the cost should not be reported, since + collecting the Qt Script object would not cause the memory to be + freed anyway. + + Negative \a size values are ignored, i.e. this function can't be + used to report that the additional memory has been deallocated. + + \sa collectGarbage() +*/ +void QScriptEngine::reportAdditionalMemoryCost(int size) +{ + Q_D(QScriptEngine); + d->reportAdditionalMemoryCost(size); +} + +/*! Sets the interval between calls to QCoreApplication::processEvents to \a interval milliseconds. @@ -3942,6 +4070,7 @@ bool qScriptConnect(QObject *sender, const char *signal, if (receiver.isObject() && (receiver.engine() != function.engine())) return false; QScriptEnginePrivate *engine = QScriptEnginePrivate::get(function.engine()); + QScript::APIShim shim(engine); JSC::JSValue jscReceiver = engine->scriptValueToJSCValue(receiver); JSC::JSValue jscFunction = engine->scriptValueToJSCValue(function); return engine->scriptConnect(sender, signal, jscReceiver, jscFunction, @@ -3968,6 +4097,7 @@ bool qScriptDisconnect(QObject *sender, const char *signal, if (receiver.isObject() && (receiver.engine() != function.engine())) return false; QScriptEnginePrivate *engine = QScriptEnginePrivate::get(function.engine()); + QScript::APIShim shim(engine); JSC::JSValue jscReceiver = engine->scriptValueToJSCValue(receiver); JSC::JSValue jscFunction = engine->scriptValueToJSCValue(function); return engine->scriptDisconnect(sender, signal, jscReceiver, jscFunction); @@ -4047,11 +4177,8 @@ QScriptEngineAgent *QScriptEngine::agent() const QScriptString QScriptEngine::toStringHandle(const QString &str) { Q_D(QScriptEngine); - QScriptString result; - QScriptStringPrivate *p = new QScriptStringPrivate(d, JSC::Identifier(d->currentFrame, str), QScriptStringPrivate::HeapAllocated); - QScriptStringPrivate::init(result, p); - d->registerScriptString(p); - return result; + QScript::APIShim shim(d); + return d->toStringHandle(JSC::Identifier(d->currentFrame, str)); } /*! @@ -4076,6 +4203,7 @@ QScriptString QScriptEngine::toStringHandle(const QString &str) QScriptValue QScriptEngine::toObject(const QScriptValue &value) { Q_D(QScriptEngine); + QScript::APIShim shim(d); JSC::JSValue jscValue = d->scriptValueToJSCValue(value); if (!jscValue || jscValue.isUndefined() || jscValue.isNull()) return QScriptValue(); |