diff options
author | Kent Hansen <khansen@trolltech.com> | 2009-06-23 11:27:33 (GMT) |
---|---|---|
committer | Kent Hansen <khansen@trolltech.com> | 2009-06-23 11:27:33 (GMT) |
commit | 4d3b9fd00e331ef913c375634242915e9e235e3d (patch) | |
tree | f678852d4b18f6ae6e2c0d88fb4590b78db4c4d8 /src/script | |
parent | fae12fe2c37f0c849af9eed0e8f54a454be85922 (diff) | |
download | Qt-4d3b9fd00e331ef913c375634242915e9e235e3d.zip Qt-4d3b9fd00e331ef913c375634242915e9e235e3d.tar.gz Qt-4d3b9fd00e331ef913c375634242915e9e235e3d.tar.bz2 |
make most of the qscriptvalue tests pass
call(), construct() etc.
Diffstat (limited to 'src/script')
-rw-r--r-- | src/script/api/qscriptengine.cpp | 11 | ||||
-rw-r--r-- | src/script/api/qscriptvalue.cpp | 207 | ||||
-rw-r--r-- | src/script/api/qscriptvalue_p.h | 2 | ||||
-rw-r--r-- | src/script/bridge/qscriptfunction.cpp | 8 | ||||
-rw-r--r-- | src/script/bridge/qscriptvariant_p.h | 2 |
5 files changed, 153 insertions, 77 deletions
diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 857019e..f4ff4b5 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -842,8 +842,8 @@ QScriptValue QScriptEngine::newRegExp(const QRegExp ®exp) if (regexp.caseSensitivity() == Qt::CaseInsensitive) flags.append(QLatin1Char('i')); JSC::UString jscFlags = QScript::qtStringToJSCUString(flags); - buf[0] = JSC::jsNontrivialString(exec, jscPattern); - buf[1] = JSC::jsNontrivialString(exec, jscFlags); + buf[0] = JSC::jsString(exec, jscPattern); + buf[1] = JSC::jsString(exec, jscFlags); JSC::JSObject* result = JSC::constructRegExp(exec, args); return d->scriptValueFromJSCValue(result); } @@ -1128,8 +1128,8 @@ QScriptValue QScriptEngine::newRegExp(const QString &pattern, const QString &fla JSC::ArgList args(buf, sizeof(buf)); JSC::UString jscPattern = QScript::qtStringToJSCUString(pattern); JSC::UString jscFlags = QScript::qtStringToJSCUString(flags); - buf[0] = JSC::jsNontrivialString(exec, jscPattern); - buf[1] = JSC::jsNontrivialString(exec, jscFlags); + buf[0] = JSC::jsString(exec, jscPattern); + buf[1] = JSC::jsString(exec, jscFlags); JSC::JSObject* result = JSC::constructRegExp(exec, args); return d->scriptValueFromJSCValue(result); } @@ -1332,6 +1332,7 @@ QScriptValue QScriptEngine::evaluate(const QString &program, const QString &file JSC::UString jscFileName = QScript::qtStringToJSCUString(fileName); JSC::ExecState* exec = d->globalObject->globalExec(); + exec->clearException(); JSC::Completion comp = JSC::evaluate(exec, exec->dynamicGlobalObject()->globalScopeChain(), JSC::makeSource(jscProgram, jscFileName, lineNumber)); if ((comp.complType() == JSC::Normal) || (comp.complType() == JSC::ReturnValue)) { @@ -1801,7 +1802,7 @@ bool QScriptEnginePrivate::convert(const QScriptValue &value, #endif if (value.isVariant() && name.endsWith('*')) { int valueType = QMetaType::type(name.left(name.size()-1)); - QVariant var = value.toVariant(); + QVariant &var = QScriptValuePrivate::get(value)->variantValue(); if (valueType == var.userType()) { *reinterpret_cast<void* *>(ptr) = var.data(); return true; diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp index c2b4bd4..41c908d 100644 --- a/src/script/api/qscriptvalue.cpp +++ b/src/script/api/qscriptvalue.cpp @@ -342,6 +342,11 @@ QScriptValue QScriptValuePrivate::property(quint32 index, int resolveMode) const return eng_p->scriptValueFromJSCValue(result); } +QVariant &QScriptValuePrivate::variantValue() const +{ + return static_cast<QScript::QVariantWrapperObject*>(JSC::asObject(jscValue))->value(); +} + /*! Constructs an invalid QScriptValue. */ @@ -821,8 +826,13 @@ void QScriptValue::setScope(const QScriptValue &scope) QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(d->engine); JSC::JSValue other = eng_p->scriptValueToJSCValue(scope); JSC::ExecState *exec = eng_p->globalObject->globalExec(); - // ### make hidden property - JSC::asObject(d->jscValue)->putDirect(JSC::Identifier(exec, "__qt_scope__"), other); + JSC::Identifier id = JSC::Identifier(exec, "__qt_scope__"); + if (!scope.isValid()) { + JSC::asObject(d->jscValue)->removeDirect(id); + } else { + // ### make hidden property + JSC::asObject(d->jscValue)->putDirect(id, other); + } } /*! @@ -1076,11 +1086,8 @@ bool QScriptValue::equals(const QScriptValue &other) const eng_p = QScriptEnginePrivate::get(other.d_ptr->engine); if (eng_p) { JSC::ExecState *exec = eng_p->globalObject->globalExec(); - Q_ASSERT_X(false, Q_FUNC_INFO, "implement me"); -#if 0 - if (JSC::equal(exec, d->jscValue, other.d_ptr->jscValue)) + if (JSC::JSValue::equal(exec, d->jscValue, other.d_ptr->jscValue)) return true; -#endif } } return QScript::Equals(*this, other); @@ -1406,7 +1413,7 @@ QVariant QScriptValue::toVariant() const case QScriptValuePrivate::JSC: if (isObject()) { if (isVariant()) - return static_cast<QScript::QVariantWrapperObject*>(JSC::asObject(d->jscValue))->value(); + return d->variantValue(); #ifndef QT_NO_QOBJECT else if (isQObject()) return qVariantFromValue(toQObject()); @@ -1833,22 +1840,47 @@ QScriptValue QScriptValue::call(const QScriptValue &thisObject, Q_D(const QScriptValue); if (!isFunction()) return QScriptValue(); + + if (thisObject.engine() && (thisObject.engine() != engine())) { + qWarning("QScriptValue::call() failed: " + "cannot call function with thisObject created in " + "a different engine"); + return QScriptValue(); + } + QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(d->engine); JSC::ExecState *exec = eng_p->globalObject->globalExec(); - JSC::ArgList jscArgs; - for (int i = 0; i < args.size(); ++i) { - Q_ASSERT_X(false, Q_FUNC_INFO, "implement me"); -#if 0 - if (!args.at(i).isValid()) - jscArgs.append(JSC::jsUndefined()); - else - jscArgs.append(eng_p->scriptValueToJSCValue(args.at(i))); -#endif - } + JSC::JSValue jscThisObject = eng_p->scriptValueToJSCValue(thisObject); if (!jscThisObject || !jscThisObject.isObject()) jscThisObject = eng_p->globalObject; - JSC::JSValue result = JSC::asFunction(d->jscValue)->call(exec, jscThisObject, jscArgs); + + QVector<JSC::JSValue> argsVector; + argsVector.resize(args.size()); + for (int i = 0; i < args.size(); ++i) { + const QScriptValue &arg = args.at(i); + if (!arg.isValid()) { + argsVector[i] = JSC::jsUndefined(); + } else if (arg.engine() && (arg.engine() != engine())) { + qWarning("QScriptValue::call() failed: " + "cannot call function with argument created in " + "a different engine"); + return QScriptValue(); + } else { + argsVector[i] = eng_p->scriptValueToJSCValue(arg); + } + } + JSC::ArgList jscArgs(argsVector.data(), argsVector.size()); + + JSC::JSValue callee = d->jscValue; + JSC::JSValue result; + JSC::CallData callData; + JSC::CallType callType = callee.getCallData(callData); + if (callType == JSC::CallTypeJS) { + result = JSC::asFunction(callee)->call(exec, jscThisObject, jscArgs); + } else if (callType == JSC::CallTypeHost) { + result = callData.native.function(exec, JSC::asObject(callee), jscThisObject, jscArgs); + } if (exec->hadException()) result = exec->exception(); return eng_p->scriptValueFromJSCValue(result); @@ -1883,6 +1915,14 @@ QScriptValue QScriptValue::call(const QScriptValue &thisObject, Q_D(QScriptValue); if (!isFunction()) return QScriptValue(); + + if (thisObject.engine() && (thisObject.engine() != engine())) { + qWarning("QScriptValue::call() failed: " + "cannot call function with thisObject created in " + "a different engine"); + return QScriptValue(); + } + QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(d->engine); JSC::ExecState *exec = eng_p->globalObject->globalExec(); @@ -1890,32 +1930,39 @@ QScriptValue QScriptValue::call(const QScriptValue &thisObject, if (!jscThisObject || !jscThisObject.isObject()) jscThisObject = eng_p->globalObject; - Q_ASSERT_X(false, Q_FUNC_INFO, "implement me"); -#if 0 - // copied from kjs/FunctionPrototype.cpp, functionProtoFuncApply() - JSC::JSValue argArray = eng_p->scriptValueToJSCValue(arguments); - JSC::ArgList applyArgs; - if (!argArray.isUndefinedOrNull()) { - if (argArray.isObject()) { - if (static_cast<JSC::JSObject*>(argArray.getObject())->classInfo() == &JSC::Arguments::info) - static_cast<JSC::Arguments*>(asArguments(argArray))->fillArgList(exec, applyArgs); - else if (exec->interpreter()->isJSArray(argArray)) - static_cast<JSC::JSArray*>(JSC::asArray(argArray))->fillArgList(exec, applyArgs); - else if (static_cast<JSC::JSObject*>(argArray.getObject())->inherits(&JSC::JSArray::info)) { - unsigned length = static_cast<JSC::JSObject*>(argArray.getObject())->get(exec, exec->propertyNames().length)->toUInt32(exec); - for (unsigned i = 0; i < length; ++i) - applyArgs.append(static_cast<JSC::JSObject*>(argArray.getObject())->get(exec, i)); - } else - return QScriptValue(); // ### throwError(exec, TypeError); - } else - return QScriptValue(); // ### throwError(exec, TypeError); + JSC::JSValue array = eng_p->scriptValueToJSCValue(arguments); + // copied from runtime/FunctionPrototype.cpp, functionProtoFuncApply() + JSC::MarkedArgumentBuffer applyArgs; + if (!array.isUndefinedOrNull()) { + if (!array.isObject()) { + return eng_p->scriptValueFromJSCValue(JSC::throwError(exec, JSC::TypeError)); + } + if (JSC::asObject(array)->classInfo() == &JSC::Arguments::info) + JSC::asArguments(array)->fillArgList(exec, applyArgs); + else if (JSC::isJSArray(&exec->globalData(), array)) + JSC::asArray(array)->fillArgList(exec, applyArgs); + else if (JSC::asObject(array)->inherits(&JSC::JSArray::info)) { + unsigned length = JSC::asArray(array)->get(exec, exec->propertyNames().length).toUInt32(exec); + for (unsigned i = 0; i < length; ++i) + applyArgs.append(JSC::asArray(array)->get(exec, i)); + } else { + Q_ASSERT_X(false, Q_FUNC_INFO, "implement me"); +// return JSC::throwError(exec, JSC::TypeError); + } } - JSC::JSValue result = static_cast<JSC::JSFunction*>(asFunction(d->jscValue))->call(exec, jscThisObject, applyArgs); + JSC::JSValue callee = d->jscValue; + JSC::JSValue result; + JSC::CallData callData; + JSC::CallType callType = callee.getCallData(callData); + if (callType == JSC::CallTypeJS) { + result = JSC::asFunction(callee)->call(exec, jscThisObject, applyArgs); + } else if (callType == JSC::CallTypeHost) { + result = callData.native.function(exec, JSC::asObject(callee), jscThisObject, applyArgs); + } if (exec->hadException()) result = exec->exception(); return eng_p->scriptValueFromJSCValue(result); -#endif } /*! @@ -1943,17 +1990,26 @@ QScriptValue QScriptValue::construct(const QScriptValueList &args) return QScriptValue(); QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(d->engine); JSC::ExecState *exec = eng_p->globalObject->globalExec(); - JSC::ArgList jscArgs; + + QVector<JSC::JSValue> argsVector; + argsVector.resize(args.size()); for (int i = 0; i < args.size(); ++i) { -#if 0 - Q_ASSERT_X(false, Q_FUNC_INFO, "implement me"); if (!args.at(i).isValid()) - jscArgs.append(JSC::jsUndefined()); + argsVector[i] = JSC::jsUndefined(); else - jscArgs.append(eng_p->scriptValueToJSCValue(args.at(i))); -#endif + argsVector[i] = eng_p->scriptValueToJSCValue(args.at(i)); + } + JSC::ArgList jscArgs(argsVector.data(), argsVector.size()); + + JSC::JSValue callee = d->jscValue; + JSC::JSValue result; + JSC::ConstructData constructData; + JSC::ConstructType constructType = callee.getConstructData(constructData); + if (constructType == JSC::ConstructTypeJS) { + result = JSC::asFunction(callee)->construct(exec, jscArgs); + } else if (constructType == JSC::ConstructTypeHost) { + result = constructData.native.function(exec, JSC::asObject(callee), jscArgs); } - JSC::JSValue result = JSC::asFunction(d->jscValue)->construct(exec, jscArgs); if (exec->hadException()) result = exec->exception(); return eng_p->scriptValueFromJSCValue(result); @@ -1982,32 +2038,40 @@ QScriptValue QScriptValue::construct(const QScriptValue &arguments) QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(d->engine); JSC::ExecState *exec = eng_p->globalObject->globalExec(); - Q_ASSERT_X(false, Q_FUNC_INFO, "implement me"); -#if 0 - // copied from kjs/FunctionPrototype.cpp, functionProtoFuncApply() - JSC::JSValue argArray = eng_p->scriptValueToJSCValue(arguments); - JSC::ArgList applyArgs; - if (!argArray.isUndefinedOrNull()) { - if (argArray.isObject()) { - if (static_cast<JSC::JSObject*>(argArray.getObject())->classInfo() == &JSC::Arguments::info) - static_cast<JSC::Arguments*>(JSC::asArguments(argArray))->fillArgList(exec, applyArgs); - else if (exec->interpreter()->isJSArray(argArray)) - static_cast<JSC::JSArray*>(JSC::asArray(argArray))->fillArgList(exec, applyArgs); - else if (static_cast<JSC::JSObject*>(argArray.getObject())->inherits(&JSC::JSArray::info)) { - unsigned length = static_cast<JSC::JSObject*>(argArray.getObject())->get(exec, exec->propertyNames().length)->toUInt32(exec); - for (unsigned i = 0; i < length; ++i) - applyArgs.append(static_cast<JSC::JSObject*>(argArray.getObject())->get(exec, i)); - } else - return QScriptValue(); // ### throwError(exec, TypeError); - } else - return QScriptValue(); // ### throwError(exec, TypeError); + JSC::JSValue array = eng_p->scriptValueToJSCValue(arguments); + // copied from runtime/FunctionPrototype.cpp, functionProtoFuncApply() + JSC::MarkedArgumentBuffer applyArgs; + if (!array.isUndefinedOrNull()) { + if (!array.isObject()) { + Q_ASSERT_X(false, Q_FUNC_INFO, "implement me"); +// return JSC::throwError(exec, JSC::TypeError); + } + if (JSC::asObject(array)->classInfo() == &JSC::Arguments::info) + JSC::asArguments(array)->fillArgList(exec, applyArgs); + else if (JSC::isJSArray(&exec->globalData(), array)) + JSC::asArray(array)->fillArgList(exec, applyArgs); + else if (JSC::asObject(array)->inherits(&JSC::JSArray::info)) { + unsigned length = JSC::asArray(array)->get(exec, exec->propertyNames().length).toUInt32(exec); + for (unsigned i = 0; i < length; ++i) + applyArgs.append(JSC::asArray(array)->get(exec, i)); + } else { + Q_ASSERT_X(false, Q_FUNC_INFO, "implement me"); +// return JSC::throwError(exec, JSC::TypeError); + } } - JSC::JSValue result = JSC::asFunction(d->jscValue)->construct(exec, applyArgs); + JSC::JSValue callee = d->jscValue; + JSC::JSValue result; + JSC::ConstructData constructData; + JSC::ConstructType constructType = callee.getConstructData(constructData); + if (constructType == JSC::ConstructTypeJS) { + result = JSC::asFunction(callee)->construct(exec, applyArgs); + } else if (constructType == JSC::ConstructTypeHost) { + result = constructData.native.function(exec, JSC::asObject(callee), applyArgs); + } if (exec->hadException()) result = exec->exception(); return eng_p->scriptValueFromJSCValue(result); -#endif } /*! @@ -2236,8 +2300,13 @@ void QScriptValue::setData(const QScriptValue &data) QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(d->engine); JSC::JSValue other = eng_p->scriptValueToJSCValue(data); JSC::ExecState *exec = eng_p->globalObject->globalExec(); - // ### make hidden property - JSC::asObject(d->jscValue)->putDirect(JSC::Identifier(exec, "__qt_data__"), other); + JSC::Identifier id = JSC::Identifier(exec, "__qt_data__"); + if (!data.isValid()) { + JSC::asObject(d->jscValue)->removeDirect(id); + } else { + // ### make hidden property + JSC::asObject(d->jscValue)->putDirect(id, other); + } } /*! diff --git a/src/script/api/qscriptvalue_p.h b/src/script/api/qscriptvalue_p.h index 31230a6..57c9bfd 100644 --- a/src/script/api/qscriptvalue_p.h +++ b/src/script/api/qscriptvalue_p.h @@ -57,6 +57,8 @@ public: bool isJSC() const; + QVariant &variantValue() const; + static QScriptValuePrivate *get(const QScriptValue &q); QScriptValue property(const QString &name, int resolveMode) const; diff --git a/src/script/bridge/qscriptfunction.cpp b/src/script/bridge/qscriptfunction.cpp index fd51df1..9634ea7 100644 --- a/src/script/bridge/qscriptfunction.cpp +++ b/src/script/bridge/qscriptfunction.cpp @@ -59,6 +59,8 @@ JSC::JSValue FunctionWrapper::proxyCall(JSC::ExecState *, JSC::JSObject *callee, /*calledAsConstructor=*/false, eng_p); QScriptContext *ctx = QScriptContextPrivate::create(ctx_p); QScriptValue result = self->data->function(ctx, self->data->engine); + if (!result.isValid()) + result = QScriptValue(QScriptValue::UndefinedValue); delete ctx; return eng_p->scriptValueToJSCValue(result); } @@ -73,10 +75,12 @@ JSC::JSObject* FunctionWrapper::proxyConstruct(JSC::ExecState *, JSC::JSObject * args, /*calledAsConstructor=*/true, eng_p); QScriptContext *ctx = QScriptContextPrivate::create(ctx_p); QScriptValue result = self->data->function(ctx, self->data->engine); + if (!result.isValid()) + result = QScriptValue(QScriptValue::UndefinedValue); delete ctx; if (result.isObject()) - return static_cast<JSC::JSObject*>(JSC::asObject(eng_p->scriptValueToJSCValue(result))); - return static_cast<JSC::JSObject*>(JSC::asObject(eng_p->scriptValueToJSCValue(object))); + return JSC::asObject(eng_p->scriptValueToJSCValue(result)); + return JSC::asObject(eng_p->scriptValueToJSCValue(object)); } FunctionWithArgWrapper::FunctionWithArgWrapper(QScriptEngine *engine, int length, const JSC::Identifier &name, diff --git a/src/script/bridge/qscriptvariant_p.h b/src/script/bridge/qscriptvariant_p.h index da0bb26..6e74a6b 100644 --- a/src/script/bridge/qscriptvariant_p.h +++ b/src/script/bridge/qscriptvariant_p.h @@ -49,7 +49,7 @@ public: virtual const JSC::ClassInfo* classInfo() const { return &info; } static const JSC::ClassInfo info; - inline const QVariant &value() const { return data->value; } + inline QVariant &value() const { return data->value; } inline void setValue(const QVariant &value) { data->value = value; } private: |