From a723c7ae756ba567c2f818bb77a83c24373d3438 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 9 Sep 2013 14:33:28 +0200 Subject: Use a ReturnedValue when converting to String or Object Also rename Value::toQString() to Value::toQStringNoThrow(), and add a throwing toQString() method for JS use. Change-Id: I821b33fc61abb7d08839df965fd337685f61a545 Reviewed-by: Simon Hausmann --- src/imports/localstorage/plugin.cpp | 12 +- src/qml/jsapi/qjsvalue.cpp | 2 +- src/qml/jsruntime/qv4errorobject.cpp | 4 +- src/qml/jsruntime/qv4include.cpp | 2 +- src/qml/jsruntime/qv4jsonobject.cpp | 4 +- src/qml/jsruntime/qv4numberobject.cpp | 4 +- src/qml/jsruntime/qv4objectproto.cpp | 6 +- src/qml/jsruntime/qv4qobjectwrapper.cpp | 4 +- src/qml/jsruntime/qv4runtime.cpp | 128 ++++++++++++++++++--- src/qml/jsruntime/qv4runtime_p.h | 107 +++-------------- src/qml/jsruntime/qv4scopedvalue_p.h | 39 +++++-- src/qml/jsruntime/qv4sequenceobject.cpp | 4 +- src/qml/jsruntime/qv4stringobject.cpp | 8 +- src/qml/jsruntime/qv4value.cpp | 58 +++++++--- src/qml/jsruntime/qv4value_def_p.h | 1 + src/qml/qml/ftw/qhashedstring_p.h | 2 +- src/qml/qml/qqmlboundsignal.cpp | 2 +- src/qml/qml/qqmljavascriptexpression.cpp | 6 +- src/qml/qml/qqmllocale.cpp | 12 +- src/qml/qml/qqmlproperty.cpp | 2 +- src/qml/qml/qqmlxmlhttprequest.cpp | 16 +-- src/qml/qml/v8/qqmlbuiltinfunctions.cpp | 44 +++---- src/qml/qml/v8/qv8engine.cpp | 2 +- src/qml/types/qqmldelegatemodel.cpp | 4 +- src/qmltest/quicktestresult.cpp | 2 +- src/quick/items/context2d/qquickcanvasitem.cpp | 2 +- src/quick/items/context2d/qquickcontext2d.cpp | 38 +++--- src/quick/items/qquickitem.cpp | 4 +- src/quick/items/qquickloader.cpp | 2 +- src/quick/util/qquickglobal.cpp | 2 +- .../auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 2 +- tools/v4/main.cpp | 2 +- 32 files changed, 296 insertions(+), 231 deletions(-) diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp index 405acd0f7c..6aef93771d 100644 --- a/src/imports/localstorage/plugin.cpp +++ b/src/imports/localstorage/plugin.cpp @@ -248,7 +248,7 @@ static Value qmlsqldatabase_executeSql(SimpleCallContext *ctx) QSqlDatabase db = r->database; - QString sql = ctx->argument(0).toQString(); + QString sql = ctx->argument(0).toQStringNoThrow(); if (r->readonly && !sql.startsWith(QLatin1String("SELECT"),Qt::CaseInsensitive)) { V4THROW_SQL(SQLEXCEPTION_SYNTAX_ERR, QQmlEngine::tr("Read-only Transaction")); @@ -322,8 +322,8 @@ static Value qmlsqldatabase_changeVersion(SimpleCallContext *ctx) QV8Engine *engine = ctx->engine->v8Engine; QSqlDatabase db = r->database; - QString from_version = ctx->arguments[0].toQString(); - QString to_version = ctx->arguments[1].toQString(); + QString from_version = ctx->arguments[0].toQStringNoThrow(); + QString to_version = ctx->arguments[1].toQStringNoThrow(); Value callback = ctx->argument(2); if (from_version != r->version) @@ -626,9 +626,9 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args) QSqlDatabase database; - QString dbname = (*args)[0].toQString(); - QString dbversion = (*args)[1].toQString(); - QString dbdescription = (*args)[2].toQString(); + QString dbname = (*args)[0].toQStringNoThrow(); + QString dbversion = (*args)[1].toQStringNoThrow(); + QString dbdescription = (*args)[2].toQStringNoThrow(); int dbestimatedsize = (*args)[3].toInt32(); FunctionObject *dbcreationCallback = (*args)[4].asFunctionObject(); diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp index f18814cedf..beff645005 100644 --- a/src/qml/jsapi/qjsvalue.cpp +++ b/src/qml/jsapi/qjsvalue.cpp @@ -360,7 +360,7 @@ bool QJSValue::isVariant() const */ QString QJSValue::toString() const { - return d->value.toQString(); + return d->value.toQStringNoThrow(); } /*! diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp index 6174c9a7f5..96c5f67120 100644 --- a/src/qml/jsruntime/qv4errorobject.cpp +++ b/src/qml/jsruntime/qv4errorobject.cpp @@ -338,12 +338,12 @@ Value ErrorPrototype::method_toString(SimpleCallContext *ctx) if (name->isUndefined()) qname = QString::fromLatin1("Error"); else - qname = __qmljs_to_string(name, ctx).stringValue()->toQString(); + qname = name->toQString(); ScopedValue message(scope, o->get(ctx->engine->newString(QString::fromLatin1("message")))); QString qmessage; if (!message->isUndefined()) - qmessage = __qmljs_to_string(message, ctx).stringValue()->toQString(); + qmessage = message->toQString(); QString str; if (qname.isEmpty()) { diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp index 647cc7d2cb..7a5ca8e0ab 100644 --- a/src/qml/jsruntime/qv4include.cpp +++ b/src/qml/jsruntime/qv4include.cpp @@ -183,7 +183,7 @@ QV4::Value QV4Include::include(QV4::SimpleCallContext *ctx) if (!context || !context->isJSContext) V4THROW_ERROR("Qt.include(): Can only be called from JavaScript files"); - QUrl url(ctx->engine->resolvedUrl(ctx->arguments[0].toQString())); + QUrl url(ctx->engine->resolvedUrl(ctx->arguments[0].toQStringNoThrow())); QV4::Value callbackFunction = QV4::Value::undefinedValue(); if (ctx->argumentCount >= 2 && ctx->arguments[1].asFunctionObject()) diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp index ef1f500580..32b7ba73cc 100644 --- a/src/qml/jsruntime/qv4jsonobject.cpp +++ b/src/qml/jsruntime/qv4jsonobject.cpp @@ -786,7 +786,7 @@ QString Stringify::JO(Object *o) Value name = it.nextPropertyNameAsString(&v); if (name.isNull()) break; - QString key = name.toQString(); + QString key = name.toQStringNoThrow(); QString member = makeMember(key, v); if (!member.isEmpty()) partial += member; @@ -997,7 +997,7 @@ QJsonObject JsonObject::toJsonObject(QV4::Object *o, V4ObjectSet &visitedObjects if (name.isNull()) break; - QString key = name.toQString(); + QString key = name.toQStringNoThrow(); if (!v.asFunctionObject()) result.insert(key, toJsonValue(v, visitedObjects)); } diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp index ffcbca2ce5..fe60be7075 100644 --- a/src/qml/jsruntime/qv4numberobject.cpp +++ b/src/qml/jsruntime/qv4numberobject.cpp @@ -196,7 +196,7 @@ Value NumberPrototype::method_toFixed(SimpleCallContext *ctx) else if (v < 1.e21) str = QString::number(v, 'f', int (fdigits)); else - return __qmljs_string_from_number(ctx, v); + return __qmljs_string_from_number(ctx, v).get(); return Value::fromString(ctx, str); } @@ -231,7 +231,7 @@ Value NumberPrototype::method_toPrecision(SimpleCallContext *ctx) Value prec = ctx->argument(0); if (prec.isUndefined()) - return __qmljs_to_string(v, ctx); + return __qmljs_to_string(v, ctx).get(); double precision = prec.toInt32(); if (precision < 1 || precision > 21) { diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index 2f8f6375f0..fc6b30ef1f 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -90,14 +90,14 @@ Value ObjectCtor::construct(Managed *that, CallData *callData) obj->setPrototype(proto.objectValue()); return Value::fromObject(obj); } - return __qmljs_to_object(v4->current, ValueRef(&callData->args[0])); + return __qmljs_to_object(v4->current, ValueRef(&callData->args[0])).get(); } Value ObjectCtor::call(Managed *m, CallData *callData) { if (!callData->argc || callData->args[0].isUndefined() || callData->args[0].isNull()) return Value::fromObject(m->engine()->newObject()); - return __qmljs_to_object(m->engine()->current, ValueRef(&callData->args[0])); + return __qmljs_to_object(m->engine()->current, ValueRef(&callData->args[0])).get(); } void ObjectPrototype::init(ExecutionContext *ctx, const Value &ctor) @@ -373,7 +373,7 @@ Value ObjectPrototype::method_toString(SimpleCallContext *ctx) } else if (ctx->thisObject.isNull()) { return Value::fromString(ctx, QStringLiteral("[object Null]")); } else { - Value obj = __qmljs_to_object(ctx, ValueRef(&ctx->thisObject)); + Value obj = __qmljs_to_object(ctx, ValueRef(&ctx->thisObject)).get(); QString className = obj.objectValue()->className(); return Value::fromString(ctx, QString::fromUtf8("[object %1]").arg(className)); } diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 1e868ef3fe..10a2c3de44 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -507,7 +507,7 @@ bool QObjectWrapper::setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlC } else if (result->propType == QMetaType::Double && value.isNumber()) { PROPERTY_STORE(double, double(value.asDouble())); } else if (result->propType == QMetaType::QString && value.isString()) { - PROPERTY_STORE(QString, value.toQString()); + PROPERTY_STORE(QString, value.toQStringNoThrow()); } else if (result->isVarProperty()) { QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object); Q_ASSERT(vmemo); @@ -1503,7 +1503,7 @@ void CallArgument::fromValue(int callType, QV8Engine *engine, const QV4::Value & if (value.isNull() || value.isUndefined()) qstringPtr = new (&allocData) QString(); else - qstringPtr = new (&allocData) QString(value.toQString()); + qstringPtr = new (&allocData) QString(value.toQStringNoThrow()); type = callType; } else if (callType == QMetaType::QObjectStar) { qobjectPtr = 0; diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 8d49a2a6c9..fe140d7aba 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -542,7 +542,7 @@ double __qmljs_string_to_number(const QString &string) return d; } -Value __qmljs_string_from_number(ExecutionContext *ctx, double number) +ReturnedValue __qmljs_string_from_number(ExecutionContext *ctx, double number) { QString qstr; __qmljs_numberToString(&qstr, number, 10); @@ -563,7 +563,7 @@ String *__qmljs_string_concat(ExecutionContext *ctx, String *first, String *seco return ctx->engine->newString(newStr); } -Value __qmljs_object_default_value(Object *object, int typeHint) +ReturnedValue __qmljs_object_default_value(Object *object, int typeHint) { if (typeHint == PREFERREDTYPE_HINT) { if (object->asDateObject()) @@ -644,16 +644,14 @@ String *__qmljs_convert_to_string(ExecutionContext *ctx, const ValueRef value) case Value::String_Type: return value->stringValue(); case Value::Object_Type: { - Value prim = __qmljs_to_primitive(value, STRING_HINT); - if (prim.isPrimitive()) - return __qmljs_convert_to_string(ctx, ValueRef(&prim)); - else - ctx->throwTypeError(); + ValueScope scope(ctx); + ScopedValue prim(scope, __qmljs_to_primitive(value, STRING_HINT)); + return __qmljs_convert_to_string(ctx, prim); } case Value::Integer_Type: - return __qmljs_string_from_number(ctx, value->int_32).stringValue(); + return __qmljs_string_from_number(ctx, value->int_32).get().stringValue(); default: // double - return __qmljs_string_from_number(ctx, value->doubleValue()).stringValue(); + return __qmljs_string_from_number(ctx, value->doubleValue()).get().stringValue(); } // switch } @@ -684,7 +682,7 @@ void __qmljs_get_element(ExecutionContext *ctx, ValueRef result, const ValueRef } if (object->isNullOrUndefined()) { - QString message = QStringLiteral("Cannot read property '%1' of %2").arg(index->toQString()).arg(object->toQString()); + QString message = QStringLiteral("Cannot read property '%1' of %2").arg(index->toQStringNoThrow()).arg(object->toQStringNoThrow()); ctx->throwTypeError(message); } @@ -789,7 +787,7 @@ void __qmljs_get_property(ExecutionContext *ctx, ValueRef result, const ValueRef res = m->get(name); } else { if (object->isNullOrUndefined()) { - QString message = QStringLiteral("Cannot read property '%1' of %2").arg(name->toQString()).arg(object->toQString()); + QString message = QStringLiteral("Cannot read property '%1' of %2").arg(name->toQString()).arg(object->toQStringNoThrow()); ctx->throwTypeError(message); } @@ -828,11 +826,13 @@ uint __qmljs_equal_helper(const ValueRef x, const ValueRef y) Value ny = Value::fromDouble((double) y->booleanValue()); return __qmljs_cmp_eq(x, ValueRef(&ny)); } else if ((x->isNumber() || x->isString()) && y->isObject()) { - Value py = __qmljs_to_primitive(y, PREFERREDTYPE_HINT); - return __qmljs_cmp_eq(x, ValueRef(&py)); + ValueScope scope(y->objectValue()->engine()); + ScopedValue py(scope, __qmljs_to_primitive(y, PREFERREDTYPE_HINT)); + return __qmljs_cmp_eq(x, py); } else if (x->isObject() && (y->isNumber() || y->isString())) { - Value px = __qmljs_to_primitive(x, PREFERREDTYPE_HINT); - return __qmljs_cmp_eq(ValueRef(&px), y); + ValueScope scope(x->objectValue()->engine()); + ScopedValue px(scope, __qmljs_to_primitive(x, PREFERREDTYPE_HINT)); + return __qmljs_cmp_eq(px, y); } return false; @@ -853,6 +853,98 @@ Bool __qmljs_strict_equal(const ValueRef x, const ValueRef y) return false; } +QV4::Bool __qmljs_cmp_gt(const QV4::ValueRef l, const QV4::ValueRef r) +{ + TRACE2(l, r); + if (QV4::Value::integerCompatible(*l, *r)) + return l->integerValue() > r->integerValue(); + if (QV4::Value::bothDouble(*l, *r)) + return l->doubleValue() > r->doubleValue(); + if (l->isString() && r->isString()) + return r->stringValue()->compare(l->stringValue()); + + if (l->isObject() || r->isObject()) { + QV4::ExecutionEngine *e = (l->isObject() ? l->objectValue() : r->objectValue())->engine(); + QV4::ValueScope scope(e); + QV4::ScopedValue pl(scope, __qmljs_to_primitive(l, QV4::NUMBER_HINT)); + QV4::ScopedValue pr(scope, __qmljs_to_primitive(r, QV4::NUMBER_HINT)); + return __qmljs_cmp_gt(pl, pr); + } + + double dl = __qmljs_to_number(l); + double dr = __qmljs_to_number(r); + return dl > dr; +} + +QV4::Bool __qmljs_cmp_lt(const QV4::ValueRef l, const QV4::ValueRef r) +{ + TRACE2(l, r); + if (QV4::Value::integerCompatible(*l, *r)) + return l->integerValue() < r->integerValue(); + if (QV4::Value::bothDouble(*l, *r)) + return l->doubleValue() < r->doubleValue(); + if (l->isString() && r->isString()) + return l->stringValue()->compare(r->stringValue()); + + if (l->isObject() || r->isObject()) { + QV4::ExecutionEngine *e = (l->isObject() ? l->objectValue() : r->objectValue())->engine(); + QV4::ValueScope scope(e); + QV4::ScopedValue pl(scope, __qmljs_to_primitive(l, QV4::NUMBER_HINT)); + QV4::ScopedValue pr(scope, __qmljs_to_primitive(r, QV4::NUMBER_HINT)); + return __qmljs_cmp_lt(pl, pr); + } + + double dl = __qmljs_to_number(l); + double dr = __qmljs_to_number(r); + return dl < dr; +} + +QV4::Bool __qmljs_cmp_ge(const QV4::ValueRef l, const QV4::ValueRef r) +{ + TRACE2(l, r); + if (QV4::Value::integerCompatible(*l, *r)) + return l->integerValue() >= r->integerValue(); + if (QV4::Value::bothDouble(*l, *r)) + return l->doubleValue() >= r->doubleValue(); + if (l->isString() && r->isString()) + return !l->stringValue()->compare(r->stringValue()); + + if (l->isObject() || r->isObject()) { + QV4::ExecutionEngine *e = (l->isObject() ? l->objectValue() : r->objectValue())->engine(); + QV4::ValueScope scope(e); + QV4::ScopedValue pl(scope, __qmljs_to_primitive(l, QV4::NUMBER_HINT)); + QV4::ScopedValue pr(scope, __qmljs_to_primitive(r, QV4::NUMBER_HINT)); + return __qmljs_cmp_ge(pl, pr); + } + + double dl = __qmljs_to_number(l); + double dr = __qmljs_to_number(r); + return dl >= dr; +} + +QV4::Bool __qmljs_cmp_le(const QV4::ValueRef l, const QV4::ValueRef r) +{ + TRACE2(l, r); + if (QV4::Value::integerCompatible(*l, *r)) + return l->integerValue() <= r->integerValue(); + if (QV4::Value::bothDouble(*l, *r)) + return l->doubleValue() <= r->doubleValue(); + if (l->isString() && r->isString()) + return !r->stringValue()->compare(l->stringValue()); + + if (l->isObject() || r->isObject()) { + QV4::ExecutionEngine *e = (l->isObject() ? l->objectValue() : r->objectValue())->engine(); + QV4::ValueScope scope(e); + QV4::ScopedValue pl(scope, __qmljs_to_primitive(l, QV4::NUMBER_HINT)); + QV4::ScopedValue pr(scope, __qmljs_to_primitive(r, QV4::NUMBER_HINT)); + return __qmljs_cmp_le(pl, pr); + } + + double dl = __qmljs_to_number(l); + double dr = __qmljs_to_number(r); + return dl <= dr; +} + void __qmljs_call_global_lookup(ExecutionContext *context, ValueRef result, uint index, CallDataRef callData) { @@ -891,7 +983,7 @@ void __qmljs_call_activation_property(ExecutionContext *context, ValueRef result if (!o) { QString objectAsString = QStringLiteral("[null]"); if (base) - objectAsString = Value::fromObject(base).toQString(); + objectAsString = Value::fromObject(base).toQStringNoThrow(); QString msg = QStringLiteral("Property '%1' of object %2 is not a function").arg(name->toQString()).arg(objectAsString); context->throwTypeError(msg); } @@ -913,7 +1005,7 @@ void __qmljs_call_property(ExecutionContext *context, ValueRef result, String *n Managed *baseObject = callData->thisObject.asManaged(); if (!baseObject) { if (callData->thisObject.isNullOrUndefined()) { - QString message = QStringLiteral("Cannot call method '%1' of %2").arg(name->toQString()).arg(callData->thisObject.toQString()); + QString message = QStringLiteral("Cannot call method '%1' of %2").arg(name->toQString()).arg(callData->thisObject.toQStringNoThrow()); context->throwTypeError(message); } @@ -923,7 +1015,7 @@ void __qmljs_call_property(ExecutionContext *context, ValueRef result, String *n FunctionObject *o = baseObject->get(name).asFunctionObject(); if (!o) { - QString error = QString("Property '%1' of object %2 is not a function").arg(name->toQString(), callData->thisObject.toQString()); + QString error = QString("Property '%1' of object %2 is not a function").arg(name->toQString(), callData->thisObject.toQStringNoThrow()); context->throwTypeError(error); } diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h index 14d123e512..1196dd6005 100644 --- a/src/qml/jsruntime/qv4runtime_p.h +++ b/src/qml/jsruntime/qv4runtime_p.h @@ -153,11 +153,11 @@ void __qmljs_init_closure(QV4::ExecutionContext *ctx, QV4::ValueRef result, int // strings Q_QML_EXPORT double __qmljs_string_to_number(const QString &s); -QV4::Value __qmljs_string_from_number(QV4::ExecutionContext *ctx, double number); +QV4::ReturnedValue __qmljs_string_from_number(QV4::ExecutionContext *ctx, double number); QV4::String *__qmljs_string_concat(QV4::ExecutionContext *ctx, QV4::String *first, QV4::String *second); // objects -Q_QML_EXPORT QV4::Value __qmljs_object_default_value(QV4::Object *object, int typeHint); +Q_QML_EXPORT ReturnedValue __qmljs_object_default_value(QV4::Object *object, int typeHint); void __qmljs_set_activation_property(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::ValueRef value); void __qmljs_set_property(QV4::ExecutionContext *ctx, const QV4::ValueRef object, QV4::String *name, const QV4::ValueRef value); void __qmljs_get_property(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef object, QV4::String *name); @@ -175,13 +175,13 @@ void __qmljs_foreach_iterator_object(QV4::ExecutionContext *ctx, QV4::ValueRef r void __qmljs_foreach_next_property_name(QV4::ValueRef result, const ValueRef foreach_iterator); // type conversion and testing -QV4::Value __qmljs_to_primitive(const ValueRef value, int typeHint); +QV4::ReturnedValue __qmljs_to_primitive(const ValueRef value, int typeHint); Q_QML_EXPORT QV4::Bool __qmljs_to_boolean(const QV4::ValueRef value); double __qmljs_to_number(const QV4::ValueRef value); -QV4::Value __qmljs_to_string(const ValueRef value, QV4::ExecutionContext *ctx); +QV4::ReturnedValue __qmljs_to_string(const ValueRef value, QV4::ExecutionContext *ctx); Q_QML_EXPORT QV4::String *__qmljs_convert_to_string(QV4::ExecutionContext *ctx, const ValueRef value); void __qmljs_numberToString(QString *result, double num, int radix = 10); -QV4::Value __qmljs_to_object(QV4::ExecutionContext *ctx, const ValueRef value); +ReturnedValue __qmljs_to_object(QV4::ExecutionContext *ctx, const ValueRef value); QV4::Object *__qmljs_convert_to_object(QV4::ExecutionContext *ctx, const ValueRef value); QV4::Bool __qmljs_equal_helper(const ValueRef x, const ValueRef y); @@ -277,10 +277,10 @@ void __qmljs_inplace_shr_member(QV4::ExecutionContext *ctx, const QV4::ValueRef void __qmljs_inplace_ushr_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs); typedef QV4::Bool (*CmpOp)(const QV4::ValueRef left, const QV4::ValueRef right); -QV4::Bool __qmljs_cmp_gt(const QV4::ValueRef left, const QV4::ValueRef right); -QV4::Bool __qmljs_cmp_lt(const QV4::ValueRef left, const QV4::ValueRef right); -QV4::Bool __qmljs_cmp_ge(const QV4::ValueRef left, const QV4::ValueRef right); -QV4::Bool __qmljs_cmp_le(const QV4::ValueRef left, const QV4::ValueRef right); +QV4::Bool __qmljs_cmp_gt(const QV4::ValueRef l, const QV4::ValueRef r); +QV4::Bool __qmljs_cmp_lt(const QV4::ValueRef l, const QV4::ValueRef r); +QV4::Bool __qmljs_cmp_ge(const QV4::ValueRef l, const QV4::ValueRef r); +QV4::Bool __qmljs_cmp_le(const QV4::ValueRef l, const QV4::ValueRef r); QV4::Bool __qmljs_cmp_eq(const QV4::ValueRef left, const QV4::ValueRef right); QV4::Bool __qmljs_cmp_ne(const QV4::ValueRef left, const QV4::ValueRef right); QV4::Bool __qmljs_cmp_se(const QV4::ValueRef left, const QV4::ValueRef right); @@ -291,11 +291,11 @@ QV4::Bool __qmljs_cmp_instanceof(QV4::ExecutionContext *ctx, const QV4::ValueRef QV4::Bool __qmljs_cmp_in(QV4::ExecutionContext *ctx, const QV4::ValueRef left, const QV4::ValueRef right); // type conversion and testing -inline QV4::Value __qmljs_to_primitive(const QV4::ValueRef value, int typeHint) +inline ReturnedValue __qmljs_to_primitive(const QV4::ValueRef value, int typeHint) { QV4::Object *o = value->asObject(); if (!o) - return *value; + return value; return __qmljs_object_default_value(o, typeHint); } @@ -304,14 +304,14 @@ inline double __qmljs_to_number(const ValueRef value) return value->toNumber(); } -inline QV4::Value __qmljs_to_string(const QV4::ValueRef value, QV4::ExecutionContext *ctx) +inline QV4::ReturnedValue __qmljs_to_string(const QV4::ValueRef value, QV4::ExecutionContext *ctx) { if (value->isString()) return *value; return QV4::Value::fromString(__qmljs_convert_to_string(ctx, value)); } -inline QV4::Value __qmljs_to_object(QV4::ExecutionContext *ctx, const QV4::ValueRef value) +inline QV4::ReturnedValue __qmljs_to_object(QV4::ExecutionContext *ctx, const QV4::ValueRef value) { if (value->isObject()) return *value; @@ -584,87 +584,6 @@ inline void __qmljs_sne(ValueRef result, const QV4::ValueRef left, const QV4::Va *result = QV4::Value::fromBoolean(r); } -inline QV4::Bool __qmljs_cmp_gt(const QV4::ValueRef left, const QV4::ValueRef right) -{ - TRACE2(left, right); - if (QV4::Value::integerCompatible(*left, *right)) - return left->integerValue() > right->integerValue(); - - // Safe, as l & r are primitive values - QV4::Value l = __qmljs_to_primitive(left, QV4::NUMBER_HINT); - QV4::Value r = __qmljs_to_primitive(right, QV4::NUMBER_HINT); - - if (QV4::Value::bothDouble(l, r)) { - return l.doubleValue() > r.doubleValue(); - } else if (l.isString() && r.isString()) { - return r.stringValue()->compare(l.stringValue()); - } else { - double dl = __qmljs_to_number(ValueRef(&l)); - double dr = __qmljs_to_number(ValueRef(&r)); - return dl > dr; - } -} - -inline QV4::Bool __qmljs_cmp_lt(const QV4::ValueRef left, const QV4::ValueRef right) -{ - TRACE2(left, right); - if (QV4::Value::integerCompatible(*left, *right)) - return left->integerValue() < right->integerValue(); - - QV4::Value l = __qmljs_to_primitive(left, QV4::NUMBER_HINT); - QV4::Value r = __qmljs_to_primitive(right, QV4::NUMBER_HINT); - - if (QV4::Value::bothDouble(l, r)) { - return l.doubleValue() < r.doubleValue(); - } else if (l.isString() && r.isString()) { - return l.stringValue()->compare(r.stringValue()); - } else { - double dl = __qmljs_to_number(ValueRef(&l)); - double dr = __qmljs_to_number(ValueRef(&r)); - return dl < dr; - } -} - -inline QV4::Bool __qmljs_cmp_ge(const QV4::ValueRef left, const QV4::ValueRef right) -{ - TRACE2(left, right); - if (QV4::Value::integerCompatible(*left, *right)) - return left->integerValue() >= right->integerValue(); - - QV4::Value l = __qmljs_to_primitive(left, QV4::NUMBER_HINT); - QV4::Value r = __qmljs_to_primitive(right, QV4::NUMBER_HINT); - - if (QV4::Value::bothDouble(l, r)) { - return l.doubleValue() >= r.doubleValue(); - } else if (l.isString() && r.isString()) { - return !l.stringValue()->compare(r.stringValue()); - } else { - double dl = __qmljs_to_number(ValueRef(&l)); - double dr = __qmljs_to_number(ValueRef(&r)); - return dl >= dr; - } -} - -inline QV4::Bool __qmljs_cmp_le(const QV4::ValueRef left, const QV4::ValueRef right) -{ - TRACE2(left, right); - if (QV4::Value::integerCompatible(*left, *right)) - return left->integerValue() <= right->integerValue(); - - QV4::Value l = __qmljs_to_primitive(left, QV4::NUMBER_HINT); - QV4::Value r = __qmljs_to_primitive(right, QV4::NUMBER_HINT); - - if (QV4::Value::bothDouble(l, r)) { - return l.doubleValue() <= r.doubleValue(); - } else if (l.isString() && r.isString()) { - return !r.stringValue()->compare(l.stringValue()); - } else { - double dl = __qmljs_to_number(ValueRef(&l)); - double dr = __qmljs_to_number(ValueRef(&r)); - return dl <= dr; - } -} - inline QV4::Bool __qmljs_cmp_eq(const QV4::ValueRef left, const QV4::ValueRef right) { TRACE2(left, right); diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index a0e0d784a7..b77774cbeb 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -103,18 +103,21 @@ struct ValueScope { struct ScopedValue; struct ValueRef; +struct ReturnedValue; struct ReturnedValue { - ReturnedValue(const Value &v) - : v(v) {} - // no destructor - + inline ReturnedValue(const Value &v); + inline ReturnedValue(const ValueRef &v); + inline ReturnedValue(const ScopedValue &v); + // no destructor or copy constructor! + // ### remove me! + Value get() const { Value v; v.val = rawValue; return v; } private: friend struct ValueRef; friend struct ScopedValue; - QV4::Value v; + quint64 rawValue; }; struct ScopedValue @@ -133,7 +136,7 @@ struct ScopedValue ScopedValue(const ValueScope &scope, const ReturnedValue &v) { ptr = scope.engine->jsStackTop++; - *ptr = v.v; + ptr->val = v.rawValue; } ScopedValue &operator=(const Value &v) { @@ -142,7 +145,7 @@ struct ScopedValue } ScopedValue &operator=(const ReturnedValue &v) { - *ptr = v.v; + ptr->val = v.rawValue; return *this; } @@ -155,6 +158,10 @@ struct ScopedValue return ptr; } + const Value *operator->() const { + return ptr; + } + operator const Value &() const { return *ptr; } @@ -218,7 +225,7 @@ struct ValueRef { ValueRef &operator=(const Value &v) { *ptr = v; return *this; } ValueRef &operator=(const ReturnedValue &v) { - *ptr = v.v; + ptr->val = v.rawValue; return *this; } @@ -245,6 +252,7 @@ struct ValueRef { // ### get rid of this one! ValueRef(Value *v) { ptr = v; } private: + friend class ReturnedValue; Value *ptr; }; @@ -280,6 +288,21 @@ private: CallData *ptr; }; +inline ReturnedValue::ReturnedValue(const Value &v) + : rawValue(v.val) +{ +} + +inline ReturnedValue::ReturnedValue(const ValueRef &v) + : rawValue(v.ptr->val) +{ +} + +inline ReturnedValue::ReturnedValue(const ScopedValue &v) + : rawValue(v.ptr->val) +{ +} + } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index 29ca34910c..d07277aa5d 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -136,7 +136,7 @@ template ElementType convertValueToElement(const QV4::Val template <> QString convertValueToElement(const QV4::Value &value) { - return value.toQString(); + return value.toQStringNoThrow(); } template <> int convertValueToElement(const QV4::Value &value) @@ -146,7 +146,7 @@ template <> int convertValueToElement(const QV4::Value &value) template <> QUrl convertValueToElement(const QV4::Value &value) { - return QUrl(value.toQString()); + return QUrl(value.toQStringNoThrow()); } template <> qreal convertValueToElement(const QV4::Value &value) diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index 0a9cb32e6f..d595533714 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -320,10 +320,8 @@ Value StringPrototype::method_lastIndexOf(SimpleCallContext *context) const QString value = getThisString(context, context->thisObject); QString searchString; - if (context->argumentCount) { - Value v = __qmljs_to_string(ValueRef(&context->arguments[0]), context); - searchString = v.stringValue()->toQString(); - } + if (context->argumentCount) + searchString = context->arguments[0].toQString(); ScopedValue posArg(scope, context->argumentCount > 1 ? context->arguments[1] : Value::undefinedValue()); double position = __qmljs_to_number(posArg); @@ -789,7 +787,7 @@ Value StringPrototype::method_trim(SimpleCallContext *ctx) if (ctx->thisObject.isNull() || ctx->thisObject.isUndefined()) ctx->throwTypeError(); - QString s = __qmljs_to_string(ValueRef(&ctx->thisObject), ctx).stringValue()->toQString(); + QString s = ctx->thisObject.toQString(); const QChar *chars = s.constData(); int start, end; for (start = 0; start < s.length(); ++start) { diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp index 718b87d2c9..0347188ae0 100644 --- a/src/qml/jsruntime/qv4value.cpp +++ b/src/qml/jsruntime/qv4value.cpp @@ -119,30 +119,29 @@ double Value::toInteger() const double Value::toNumber() const { - QV4::Value v = *this; - - redo: - switch (v.type()) { + switch (type()) { case QV4::Value::Undefined_Type: return std::numeric_limits::quiet_NaN(); case QV4::Value::Null_Type: return 0; case QV4::Value::Boolean_Type: - return (v.booleanValue() ? 1. : 0.); + return (booleanValue() ? 1. : 0.); case QV4::Value::Integer_Type: - return v.int_32; + return int_32; case QV4::Value::String_Type: - return __qmljs_string_to_number(v.toQString()); + return __qmljs_string_to_number(stringValue()->toQString()); case QV4::Value::Object_Type: { - v = __qmljs_to_primitive(ValueRef::fromRawValue(this), QV4::NUMBER_HINT); - goto redo; + ExecutionContext *ctx = objectValue()->internalClass->engine->current; + ValueScope scope(ctx); + ScopedValue prim(scope, __qmljs_to_primitive(ValueRef::fromRawValue(this), NUMBER_HINT)); + return prim->toNumber(); } default: // double - return v.doubleValue(); + return doubleValue(); } } -QString Value::toQString() const +QString Value::toQStringNoThrow() const { switch (type()) { case Value::Undefined_Type: @@ -162,14 +161,14 @@ QString Value::toQString() const try { ScopedValue prim(scope, __qmljs_to_primitive(ValueRef::fromRawValue(this), STRING_HINT)); if (prim->isPrimitive()) - return prim->toQString(); + return prim->toQStringNoThrow(); } catch (Exception &e) { e.accept(ctx); try { ScopedValue ex(scope, e.value()); ScopedValue prim(scope, __qmljs_to_primitive(ex, STRING_HINT)); if (prim->isPrimitive()) - return prim->toQString(); + return prim->toQStringNoThrow(); } catch(Exception &e) { e.accept(ctx); } @@ -189,6 +188,39 @@ QString Value::toQString() const } // switch } +QString Value::toQString() const +{ + switch (type()) { + case Value::Undefined_Type: + return QStringLiteral("undefined"); + case Value::Null_Type: + return QStringLiteral("null"); + case Value::Boolean_Type: + if (booleanValue()) + return QStringLiteral("true"); + else + return QStringLiteral("false"); + case Value::String_Type: + return stringValue()->toQString(); + case Value::Object_Type: { + ExecutionContext *ctx = objectValue()->internalClass->engine->current; + ValueScope scope(ctx); + ScopedValue prim(scope, __qmljs_to_primitive(ValueRef::fromRawValue(this), STRING_HINT)); + return prim->toQString(); + } + case Value::Integer_Type: { + QString str; + __qmljs_numberToString(&str, (double)int_32, 10); + return str; + } + default: { // double + QString str; + __qmljs_numberToString(&str, doubleValue(), 10); + return str; + } + } // switch +} + bool Value::sameValue(Value other) const { if (val == other.val) return true; diff --git a/src/qml/jsruntime/qv4value_def_p.h b/src/qml/jsruntime/qv4value_def_p.h index 7d037f3d49..7ca7a8c756 100644 --- a/src/qml/jsruntime/qv4value_def_p.h +++ b/src/qml/jsruntime/qv4value_def_p.h @@ -215,6 +215,7 @@ struct Q_QML_EXPORT Value bool toBoolean() const; double toInteger() const; double toNumber() const; + QString toQStringNoThrow() const; QString toQString() const; String *toString(ExecutionContext *ctx) const; Object *toObject(ExecutionContext *ctx) const; diff --git a/src/qml/qml/ftw/qhashedstring_p.h b/src/qml/qml/ftw/qhashedstring_p.h index 9b7215f0ae..e39e695c99 100644 --- a/src/qml/qml/ftw/qhashedstring_p.h +++ b/src/qml/qml/ftw/qhashedstring_p.h @@ -233,7 +233,7 @@ public: inline quint16 *utf16Data() const { return (quint16 *)strData->data(); } inline bool equals(const QV4::Value &string) const { - QString s = string.toQString(); + QString s = string.toQStringNoThrow(); if (isQString()) { QStringDataPtr dd; dd.ptr = strData; diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp index 08344c4c60..b7cb52bdbc 100644 --- a/src/qml/qml/qqmlboundsignal.cpp +++ b/src/qml/qml/qqmlboundsignal.cpp @@ -115,7 +115,7 @@ QString QQmlBoundSignalExpression::expression() const { if (m_expressionFunctionValid) { Q_ASSERT (context() && engine()); - return m_v8function.value().toQString(); + return m_v8function.value().toQStringNoThrow(); } else { return m_expression; } diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp index 2974bbcfbe..c86309027f 100644 --- a/src/qml/qml/qqmljavascriptexpression.cpp +++ b/src/qml/qml/qqmljavascriptexpression.cpp @@ -86,7 +86,7 @@ void QQmlDelayedError::setErrorObject(QObject *object) void QQmlDelayedError::setError(const QV4::Exception &e) { - m_error.setDescription(e.value().toQString()); + m_error.setDescription(e.value().toQStringNoThrow()); QV4::ExecutionEngine::StackTrace trace = e.stackTrace(); if (!trace.isEmpty()) { QV4::ExecutionEngine::StackFrame frame = trace.first(); @@ -311,9 +311,9 @@ void QQmlJavaScriptExpression::exceptionToError(const QV4::Exception &e, QQmlErr } QV4::ErrorObject *errorObj = e.value().asErrorObject(); if (errorObj && errorObj->asSyntaxError()) - error.setDescription(errorObj->get(errorObj->engine()->newString("message")).toQString()); + error.setDescription(errorObj->get(errorObj->engine()->newString("message")).toQStringNoThrow()); else - error.setDescription(e.value().toQString()); + error.setDescription(e.value().toQStringNoThrow()); } QV4::PersistentValue diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp index 7f68ccc324..4cdcb96857 100644 --- a/src/qml/qml/qqmllocale.cpp +++ b/src/qml/qml/qqmllocale.cpp @@ -280,7 +280,7 @@ QV4::Value QQmlDateExtension::fromLocaleString(QV4::SimpleCallContext *ctx) QLocale::FormatType enumFormat = QLocale::LongFormat; QDateTime dt; - QString dateString = ctx->arguments[1].toQString(); + QString dateString = ctx->arguments[1].toQStringNoThrow(); if (ctx->argumentCount == 3) { if (ctx->arguments[2].isString()) { QString format = ctx->arguments[2].stringValue()->toQString(); @@ -319,7 +319,7 @@ QV4::Value QQmlDateExtension::fromLocaleTimeString(QV4::SimpleCallContext *ctx) QLocale::FormatType enumFormat = QLocale::LongFormat; QTime tm; - QString dateString = ctx->arguments[1].toQString(); + QString dateString = ctx->arguments[1].toQStringNoThrow(); if (ctx->argumentCount == 3) { if (ctx->arguments[2].isString()) { QString format = ctx->arguments[2].stringValue()->toQString(); @@ -359,7 +359,7 @@ QV4::Value QQmlDateExtension::fromLocaleDateString(QV4::SimpleCallContext *ctx) QLocale::FormatType enumFormat = QLocale::LongFormat; QDate dt; - QString dateString = ctx->arguments[1].toQString(); + QString dateString = ctx->arguments[1].toQStringNoThrow(); if (ctx->argumentCount == 3) { if (ctx->arguments[2].isString()) { QString format = ctx->arguments[2].stringValue()->toQString(); @@ -456,7 +456,7 @@ QV4::Value QQmlNumberExtension::toLocaleCurrencyString(QV4::SimpleCallContext *c if (ctx->argumentCount > 1) { if (!ctx->arguments[1].isString()) V4THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments"); - symbol = ctx->arguments[1].toQString(); + symbol = ctx->arguments[1].toQStringNoThrow(); } return QV4::Value::fromString(ctx, r->locale.toCurrencyString(number, symbol)); @@ -831,8 +831,8 @@ QV4::Value QQmlLocale::localeCompare(QV4::SimpleCallContext *ctx) if (!ctx->thisObject.isString() && !ctx->thisObject.asStringObject()) return QV4::StringPrototype::method_localeCompare(ctx); - QString thisString = ctx->thisObject.toQString(); - QString thatString = ctx->arguments[0].toQString(); + QString thisString = ctx->thisObject.toQStringNoThrow(); + QString thatString = ctx->arguments[0].toQStringNoThrow(); return QV4::Value::fromInt32(QString::localeAwareCompare(thisString, thatString)); } diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp index cf1b5ffd18..f821687f63 100644 --- a/src/qml/qml/qqmlproperty.cpp +++ b/src/qml/qml/qqmlproperty.cpp @@ -1497,7 +1497,7 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object, break; case QMetaType::QString: if (result.isString()) - QUICK_STORE(QString, result.toQString()) + QUICK_STORE(QString, result.toQStringNoThrow()) break; default: break; diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index ddc7a4894b..1d62eabf9a 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -1645,7 +1645,7 @@ Value QQmlXMLHttpRequestCtor::method_open(SimpleCallContext *ctx) QV8Engine *engine = ctx->engine->v8Engine; // Argument 0 - Method - QString method = ctx->arguments[0].toQString().toUpper(); + QString method = ctx->arguments[0].toQStringNoThrow().toUpper(); if (method != QLatin1String("GET") && method != QLatin1String("PUT") && method != QLatin1String("HEAD") && @@ -1654,7 +1654,7 @@ Value QQmlXMLHttpRequestCtor::method_open(SimpleCallContext *ctx) V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Unsupported HTTP method type"); // Argument 1 - URL - QUrl url = QUrl(ctx->arguments[1].toQString()); + QUrl url = QUrl(ctx->arguments[1].toQStringNoThrow()); if (url.isRelative()) url = engine->callingContext()->resolvedUrl(url); @@ -1666,9 +1666,9 @@ Value QQmlXMLHttpRequestCtor::method_open(SimpleCallContext *ctx) // Argument 3/4 - user/pass (optional) QString username, password; if (ctx->argumentCount > 3) - username = ctx->arguments[3].toQString(); + username = ctx->arguments[3].toQStringNoThrow(); if (ctx->argumentCount > 4) - password = ctx->arguments[4].toQString(); + password = ctx->arguments[4].toQStringNoThrow(); // Clear the fragment (if any) url.setFragment(QString()); @@ -1693,8 +1693,8 @@ Value QQmlXMLHttpRequestCtor::method_setRequestHeader(SimpleCallContext *ctx) if (r->readyState() != QQmlXMLHttpRequest::Opened || r->sendFlag()) V4THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state"); - QString name = ctx->arguments[0].toQString(); - QString value = ctx->arguments[1].toQString(); + QString name = ctx->arguments[0].toQStringNoThrow(); + QString value = ctx->arguments[1].toQStringNoThrow(); // ### Check that name and value are well formed @@ -1741,7 +1741,7 @@ Value QQmlXMLHttpRequestCtor::method_send(SimpleCallContext *ctx) QByteArray data; if (ctx->argumentCount > 0) - data = ctx->arguments[0].toQString().toUtf8(); + data = ctx->arguments[0].toQStringNoThrow().toUtf8(); return r->send(constructMeObject(ctx->thisObject, engine), data); } @@ -1773,7 +1773,7 @@ Value QQmlXMLHttpRequestCtor::method_getResponseHeader(SimpleCallContext *ctx) r->readyState() != QQmlXMLHttpRequest::HeadersReceived) V4THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state"); - return engine->toString(r->header(ctx->arguments[0].toQString())); + return engine->toString(r->header(ctx->arguments[0].toQStringNoThrow())); } Value QQmlXMLHttpRequestCtor::method_getAllResponseHeaders(SimpleCallContext *ctx) diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index 2321e27bc6..35a63ba000 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -826,7 +826,7 @@ Value QtObject::method_openUrlExternally(QV4::SimpleCallContext *ctx) QV8Engine *v8engine = ctx->engine->v8Engine; - QUrl url(method_resolvedUrl(ctx).toQString()); + QUrl url(method_resolvedUrl(ctx).toQStringNoThrow()); return v8engine->fromVariant(QQml_guiProvider()->openUrlExternally(url)); } @@ -875,7 +875,7 @@ Value QtObject::method_md5(SimpleCallContext *ctx) if (ctx->argumentCount != 1) V4THROW_ERROR("Qt.md5(): Invalid arguments"); - QByteArray data = ctx->arguments[0].toQString().toUtf8(); + QByteArray data = ctx->arguments[0].toQStringNoThrow().toUtf8(); QByteArray result = QCryptographicHash::hash(data, QCryptographicHash::Md5); return Value::fromString(ctx, QLatin1String(result.toHex())); } @@ -889,7 +889,7 @@ Value QtObject::method_btoa(SimpleCallContext *ctx) if (ctx->argumentCount != 1) V4THROW_ERROR("Qt.btoa(): Invalid arguments"); - QByteArray data = ctx->arguments[0].toQString().toUtf8(); + QByteArray data = ctx->arguments[0].toQStringNoThrow().toUtf8(); return Value::fromString(ctx, QLatin1String(data.toBase64())); } @@ -903,7 +903,7 @@ Value QtObject::method_atob(SimpleCallContext *ctx) if (ctx->argumentCount != 1) V4THROW_ERROR("Qt.atob(): Invalid arguments"); - QByteArray data = ctx->arguments[0].toQString().toLatin1(); + QByteArray data = ctx->arguments[0].toQStringNoThrow().toLatin1(); return Value::fromString(ctx, QString::fromUtf8(QByteArray::fromBase64(data))); } @@ -986,13 +986,13 @@ Value QtObject::method_createQmlObject(SimpleCallContext *ctx) effectiveContext = context->asQQmlContext(); Q_ASSERT(context && effectiveContext); - QString qml = ctx->arguments[0].toQString(); + QString qml = ctx->arguments[0].toQStringNoThrow(); if (qml.isEmpty()) return QV4::Value::nullValue(); QUrl url; if (ctx->argumentCount > 2) - url = QUrl(ctx->arguments[2].toQString()); + url = QUrl(ctx->arguments[2].toQStringNoThrow()); else url = QUrl(QLatin1String("inline")); @@ -1089,7 +1089,7 @@ Value QtObject::method_createComponent(SimpleCallContext *ctx) effectiveContext = 0; Q_ASSERT(context); - QString arg = ctx->arguments[0].toQString(); + QString arg = ctx->arguments[0].toQStringNoThrow(); if (arg.isEmpty()) return QV4::Value::nullValue(); @@ -1166,7 +1166,7 @@ Value QtObject::method_locale(SimpleCallContext *ctx) QV8Engine *v8engine = ctx->engine->v8Engine; if (ctx->argumentCount == 1) - code = ctx->arguments[0].toQString(); + code = ctx->arguments[0].toQStringNoThrow(); return QQmlLocale::locale(v8engine, code); } @@ -1370,9 +1370,9 @@ static QV4::Value writeToConsole(ConsoleLogTypes logType, SimpleCallContext *ctx QV4::Value value = ctx->arguments[i]; if (value.asArrayObject()) - result.append(QStringLiteral("[") + value.toQString() + QStringLiteral("]")); + result.append(QStringLiteral("[") + value.toQStringNoThrow() + QStringLiteral("]")); else - result.append(value.toQString()); + result.append(value.toQStringNoThrow()); } if (printStack) { @@ -1467,7 +1467,7 @@ QV4::Value ConsoleObject::method_time(SimpleCallContext *ctx) QV8Engine *v8engine = ctx->engine->v8Engine; - QString name = ctx->arguments[0].toQString(); + QString name = ctx->arguments[0].toQStringNoThrow(); v8engine->startTimer(name); return QV4::Value::undefinedValue(); } @@ -1479,7 +1479,7 @@ QV4::Value ConsoleObject::method_timeEnd(SimpleCallContext *ctx) QV8Engine *v8engine = ctx->engine->v8Engine; - QString name = ctx->arguments[0].toQString(); + QString name = ctx->arguments[0].toQStringNoThrow(); bool wasRunning; qint64 elapsed = v8engine->stopTimer(name, &wasRunning); if (wasRunning) { @@ -1493,7 +1493,7 @@ QV4::Value ConsoleObject::method_count(SimpleCallContext *ctx) // first argument: name to print. Ignore any additional arguments QString name; if (ctx->argumentCount > 0) - name = ctx->arguments[0].toQString(); + name = ctx->arguments[0].toQStringNoThrow(); QV4::ExecutionEngine *v4 = ctx->engine; QV8Engine *v8engine = ctx->engine->v8Engine; @@ -1545,7 +1545,7 @@ QV4::Value ConsoleObject::method_assert(SimpleCallContext *ctx) if (i != 1) message.append(QLatin1Char(' ')); - message.append(ctx->arguments[i].toQString()); + message.append(ctx->arguments[i].toQStringNoThrow()); } QString stack = jsStack(v4); @@ -1627,10 +1627,10 @@ Value GlobalExtensions::method_qsTranslate(SimpleCallContext *ctx) if ((ctx->argumentCount > 2) && !ctx->arguments[2].isString()) V4THROW_ERROR("qsTranslate(): third argument (disambiguation) must be a string"); - QString context = ctx->arguments[0].toQString(); - QString text = ctx->arguments[1].toQString(); + QString context = ctx->arguments[0].toQStringNoThrow(); + QString text = ctx->arguments[1].toQStringNoThrow(); QString comment; - if (ctx->argumentCount > 2) comment = ctx->arguments[2].toQString(); + if (ctx->argumentCount > 2) comment = ctx->arguments[2].toQStringNoThrow(); int i = 3; if (ctx->argumentCount > i && ctx->arguments[i].isString()) { @@ -1714,10 +1714,10 @@ Value GlobalExtensions::method_qsTr(SimpleCallContext *ctx) int lastSlash = path.lastIndexOf(QLatin1Char('/')); QString context = (lastSlash > -1) ? path.mid(lastSlash + 1, path.length()-lastSlash-5) : QString(); - QString text = ctx->arguments[0].toQString(); + QString text = ctx->arguments[0].toQStringNoThrow(); QString comment; if (ctx->argumentCount > 1) - comment = ctx->arguments[1].toQString(); + comment = ctx->arguments[1].toQStringNoThrow(); int n = -1; if (ctx->argumentCount > 2) n = ctx->arguments[2].toInt32(); @@ -1800,7 +1800,7 @@ Value GlobalExtensions::method_qsTrId(SimpleCallContext *ctx) if (ctx->argumentCount > 1) n = ctx->arguments[1].toInt32(); - return Value::fromString(ctx, qtTrId(ctx->arguments[0].toQString().toUtf8().constData(), n)); + return Value::fromString(ctx, qtTrId(ctx->arguments[0].toQStringNoThrow().toUtf8().constData(), n)); } /*! @@ -1839,7 +1839,7 @@ QV4::Value GlobalExtensions::method_gc(SimpleCallContext *ctx) Value GlobalExtensions::string_arg(SimpleCallContext *ctx) { - QString value = ctx->thisObject.toQString(); + QString value = ctx->thisObject.toQStringNoThrow(); if (ctx->argumentCount != 1) V4THROW_ERROR("String.arg(): Invalid arguments"); @@ -1851,7 +1851,7 @@ Value GlobalExtensions::string_arg(SimpleCallContext *ctx) else if (arg.isBoolean()) return Value::fromString(ctx, value.arg(arg.booleanValue())); - return Value::fromString(ctx, value.arg(arg.toQString())); + return Value::fromString(ctx, value.arg(arg.toQStringNoThrow())); } diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp index 5b43dd6192..57adeb98af 100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@ -587,7 +587,7 @@ QVariantMap QV8Engine::variantMapFromJS(QV4::Object *o, if (name.isNull()) break; - QString key = name.toQString(); + QString key = name.toQStringNoThrow(); result.insert(key, variantFromJS(v, visitedObjects)); } diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index bc52da6151..f3a4179374 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -1556,7 +1556,7 @@ bool QQmlDelegateModelPrivate::insert(Compositor::insert_iterator &before, const QV4::Value propertyName = it.nextPropertyNameAsString(&value); if (propertyName.isNull()) break; - cacheItem->setValue(propertyName.toQString(), m_cacheMetaType->v8Engine->toVariant(value, QVariant::Invalid)); + cacheItem->setValue(propertyName.toQStringNoThrow(), m_cacheMetaType->v8Engine->toVariant(value, QVariant::Invalid)); } cacheItem->groups = groups | Compositor::UnresolvedFlag | Compositor::CacheFlag; @@ -1678,7 +1678,7 @@ int QQmlDelegateModelItemMetaType::parseGroups(const QV4::Value &groups) const } else if (QV4::ArrayObject *array = groups.asArrayObject()) { uint arrayLength = array->arrayLength(); for (uint i = 0; i < arrayLength; ++i) { - const QString groupName = array->getIndexed(i).toQString(); + const QString groupName = array->getIndexed(i).toQStringNoThrow(); int index = groupNames.indexOf(groupName); if (index != -1) groupFlags |= 2 << index; diff --git a/src/qmltest/quicktestresult.cpp b/src/qmltest/quicktestresult.cpp index d33687d248..0385389628 100644 --- a/src/qmltest/quicktestresult.cpp +++ b/src/qmltest/quicktestresult.cpp @@ -503,7 +503,7 @@ void QuickTestResult::stringify(QQmlV4Function *args) result = QLatin1String("Object"); } } else { - QString tmp = value.toQString(); + QString tmp = value.toQStringNoThrow(); if (value.asArrayObject()) result.append(QString::fromLatin1("[%1]").arg(tmp)); else diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp index 52281a4fbc..60cb3ace3e 100644 --- a/src/quick/items/context2d/qquickcanvasitem.cpp +++ b/src/quick/items/context2d/qquickcanvasitem.cpp @@ -750,7 +750,7 @@ void QQuickCanvasItem::getContext(QQmlV4Function *args) return; } - QString contextId = (*args)[0].toQString(); + QString contextId = (*args)[0].toQStringNoThrow(); if (d->context != 0) { if (d->context->contextNames().contains(contextId, Qt::CaseInsensitive)) { diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index 84c4578946..f17b3d45e6 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -128,7 +128,7 @@ static const double Q_PI = 3.14159265358979323846; // pi #define CHECK_RGBA(c) (c == '-' || c == '.' || (c >=0 && c <= 9)) QColor qt_color_from_string(const QV4::Value &name) { - QByteArray str = name.toQString().toUtf8(); + QByteArray str = name.toQStringNoThrow().toUtf8(); char *p = str.data(); int len = str.length(); @@ -1278,7 +1278,7 @@ QV4::Value QQuickJSContext2D::method_set_globalCompositeOperation(QV4::SimpleCal QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT_SETTER(r) - QString mode = ctx->argument(0).toQString(); + QString mode = ctx->argument(0).toQStringNoThrow(); QPainter::CompositionMode cm = qt_composite_mode_from_string(mode); if (cm == QPainter::CompositionMode_SourceOver && mode != QStringLiteral("source-over")) return QV4::Value::undefinedValue(); @@ -1395,10 +1395,10 @@ QV4::Value QQuickJSContext2D::method_set_fillRule(QV4::SimpleCallContext *ctx) QV4::Value value = ctx->argument(0); - if ((value.isString() && value.toQString() == QStringLiteral("WindingFill")) + if ((value.isString() && value.toQStringNoThrow() == QStringLiteral("WindingFill")) || (value.isInt32() && value.integerValue() == Qt::WindingFill)) { r->context->state.fillRule = Qt::WindingFill; - } else if ((value.isString() && value.toQString() == QStringLiteral("OddEvenFill")) + } else if ((value.isString() && value.toQStringNoThrow() == QStringLiteral("OddEvenFill")) || (value.isInt32() && value.integerValue() == Qt::OddEvenFill)) { r->context->state.fillRule = Qt::OddEvenFill; } else { @@ -1694,13 +1694,13 @@ QV4::Value QQuickJSContext2DPrototype::method_createPattern(QV4::SimpleCallConte patternTexture = pixelData->image; } } else { - patternTexture = r->context->createPixmap(QUrl(ctx->arguments[0].toQString()))->image(); + patternTexture = r->context->createPixmap(QUrl(ctx->arguments[0].toQStringNoThrow()))->image(); } if (!patternTexture.isNull()) { pattern->brush.setTextureImage(patternTexture); - QString repetition = ctx->arguments[1].toQString(); + QString repetition = ctx->arguments[1].toQStringNoThrow(); if (repetition == QStringLiteral("repeat") || repetition.isEmpty()) { pattern->patternRepeatX = true; pattern->patternRepeatY = true; @@ -1758,7 +1758,7 @@ QV4::Value QQuickJSContext2D::method_set_lineCap(QV4::SimpleCallContext *ctx) QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT_SETTER(r) - QString lineCap = ctx->argument(0).toQString(); + QString lineCap = ctx->argument(0).toQStringNoThrow(); Qt::PenCapStyle cap; if (lineCap == QStringLiteral("round")) cap = Qt::RoundCap; @@ -1812,7 +1812,7 @@ QV4::Value QQuickJSContext2D::method_set_lineJoin(QV4::SimpleCallContext *ctx) QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT_SETTER(r) - QString lineJoin = ctx->argument(0).toQString(); + QString lineJoin = ctx->argument(0).toQStringNoThrow(); Qt::PenJoinStyle join; if (lineJoin == QStringLiteral("round")) join = Qt::RoundJoin; @@ -2009,7 +2009,7 @@ QV4::Value QQuickJSContext2D::method_set_path(QV4::SimpleCallContext *ctx) if (QQuickPath *path = qobject_cast(qobjectWrapper->object())) r->context->m_path = path->path(); } else { - QString path = value.toQString(); + QString path = value.toQStringNoThrow(); QQuickSvgParser::parsePathDataFast(path, r->context->m_path); } r->context->m_v4path = value; @@ -2435,7 +2435,7 @@ QV4::Value QQuickJSContext2DPrototype::method_text(QV4::SimpleCallContext *ctx) if (!qIsFinite(x) || !qIsFinite(y)) return ctx->thisObject; - r->context->text(ctx->arguments[0].toQString(), x, y); + r->context->text(ctx->arguments[0].toQStringNoThrow(), x, y); } return ctx->thisObject; } @@ -2533,7 +2533,7 @@ QV4::Value QQuickJSContext2D::method_set_font(QV4::SimpleCallContext *ctx) QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT_SETTER(r) - QString fs = ctx->argument(0).toQString(); + QString fs = ctx->argument(0).toQStringNoThrow(); QFont font = qt_font_from_string(fs, r->context->state.font); if (font != r->context->state.font) { r->context->state.font = font; @@ -2581,7 +2581,7 @@ QV4::Value QQuickJSContext2D::method_set_textAlign(QV4::SimpleCallContext *ctx) QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT_SETTER(r) - QString textAlign = ctx->argument(0).toQString(); + QString textAlign = ctx->argument(0).toQStringNoThrow(); QQuickContext2D::TextAlignType ta; if (textAlign == QStringLiteral("start")) @@ -2643,7 +2643,7 @@ QV4::Value QQuickJSContext2D::method_set_textBaseline(QV4::SimpleCallContext *ct { QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT_SETTER(r) - QString textBaseline = ctx->argument(0).toQString(); + QString textBaseline = ctx->argument(0).toQStringNoThrow(); QQuickContext2D::TextBaseLineType tb; if (textBaseline == QStringLiteral("alphabetic")) @@ -2683,7 +2683,7 @@ QV4::Value QQuickJSContext2DPrototype::method_fillText(QV4::SimpleCallContext *c qreal y = ctx->arguments[2].toNumber(); if (!qIsFinite(x) || !qIsFinite(y)) return ctx->thisObject; - QPainterPath textPath = r->context->createTextGlyphs(x, y, ctx->arguments[0].toQString()); + QPainterPath textPath = r->context->createTextGlyphs(x, y, ctx->arguments[0].toQStringNoThrow()); r->context->buffer()->fill(textPath); } return ctx->thisObject; @@ -2702,7 +2702,7 @@ QV4::Value QQuickJSContext2DPrototype::method_strokeText(QV4::SimpleCallContext CHECK_CONTEXT(r) if (ctx->argumentCount == 3) - r->context->drawText(ctx->arguments[0].toQString(), ctx->arguments[1].toNumber(), ctx->arguments[2].toNumber(), false); + r->context->drawText(ctx->arguments[0].toQStringNoThrow(), ctx->arguments[1].toNumber(), ctx->arguments[2].toNumber(), false); return ctx->thisObject; } @@ -2737,7 +2737,7 @@ QV4::Value QQuickJSContext2DPrototype::method_measureText(QV4::SimpleCallContext if (ctx->argumentCount == 1) { QFontMetrics fm(r->context->state.font); - uint width = fm.width(ctx->arguments[0].toQString()); + uint width = fm.width(ctx->arguments[0].toQStringNoThrow()); QV4::Object *tm = ctx->engine->newObject(); tm->put(ctx->engine->newIdentifier(QStringLiteral("width")), QV4::Value::fromDouble(width)); return QV4::Value::fromObject(tm); @@ -2821,7 +2821,7 @@ QV4::Value QQuickJSContext2DPrototype::method_drawImage(QV4::SimpleCallContext * QQmlRefPointer pixmap; if (ctx->arguments[0].isString()) { - QUrl url(ctx->arguments[0].toQString()); + QUrl url(ctx->arguments[0].toQStringNoThrow()); if (!url.isValid()) V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch"); @@ -2845,7 +2845,7 @@ QV4::Value QQuickJSContext2DPrototype::method_drawImage(QV4::SimpleCallContext * V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch"); } } else { - QUrl url(ctx->arguments[0].toQString()); + QUrl url(ctx->arguments[0].toQStringNoThrow()); if (url.isValid()) pixmap = r->context->createPixmap(url); else @@ -3100,7 +3100,7 @@ QV4::Value QQuickJSContext2DPrototype::method_createImageData(QV4::SimpleCallCon return qt_create_image_data(w, h, engine, QImage()); } } else if (ctx->arguments[0].isString()) { - QImage image = r->context->createPixmap(QUrl(ctx->arguments[0].toQString()))->image(); + QImage image = r->context->createPixmap(QUrl(ctx->arguments[0].toQStringNoThrow()))->image(); return qt_create_image_data(image.width(), image.height(), engine, image); } } else if (ctx->argumentCount == 2) { diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 01625756cd..d27a964e4e 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -3871,7 +3871,7 @@ void QQuickItem::mapFromItem(QQmlV4Function *args) const } if (!itemObj && !item.isNull()) { - qmlInfo(this) << "mapFromItem() given argument \"" << item.toQString() + qmlInfo(this) << "mapFromItem() given argument \"" << item.toQStringNoThrow() << "\" which is neither null nor an Item"; return; } @@ -3945,7 +3945,7 @@ void QQuickItem::mapToItem(QQmlV4Function *args) const } if (!itemObj && !item.isNull()) { - qmlInfo(this) << "mapToItem() given argument \"" << item.toQString() + qmlInfo(this) << "mapToItem() given argument \"" << item.toQStringNoThrow() << "\" which is neither null nor an Item"; return; } diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp index 8f4dc0bd17..a24439cb19 100644 --- a/src/quick/items/qquickloader.cpp +++ b/src/quick/items/qquickloader.cpp @@ -922,7 +922,7 @@ void QQuickLoader::geometryChanged(const QRectF &newGeometry, const QRectF &oldG QUrl QQuickLoaderPrivate::resolveSourceUrl(QQmlV4Function *args) { - QString arg = (*args)[0].toQString(); + QString arg = (*args)[0].toQStringNoThrow(); if (arg.isEmpty()) return QUrl(); diff --git a/src/quick/util/qquickglobal.cpp b/src/quick/util/qquickglobal.cpp index c8f8574f9d..117b89e88b 100644 --- a/src/quick/util/qquickglobal.cpp +++ b/src/quick/util/qquickglobal.cpp @@ -348,7 +348,7 @@ public: if (ok) *ok = true; } if (vfam.isString()) { - retn.setFamily(vfam.toQString()); + retn.setFamily(vfam.toQStringNoThrow()); if (ok) *ok = true; } if (vital.isBoolean()) { diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 5e1f83a43a..b9ef6d0910 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -2445,7 +2445,7 @@ void tst_qqmlecmascript::callQtInvokables() { QV4::Value ret = EVALUATE("object.method_NoArgs_QScriptValue()"); QVERIFY(ret.isString()); - QCOMPARE(ret.toQString(), QString("Hello world")); + QCOMPARE(ret.toQStringNoThrow(), QString("Hello world")); QCOMPARE(o->error(), false); QCOMPARE(o->invoked(), 6); QCOMPARE(o->actuals().count(), 0); diff --git a/tools/v4/main.cpp b/tools/v4/main.cpp index a49c7093cf..c6fa1c986f 100644 --- a/tools/v4/main.cpp +++ b/tools/v4/main.cpp @@ -80,7 +80,7 @@ struct Print: FunctionObject static Value call(Managed *, CallData *callData) { for (int i = 0; i < callData->argc; ++i) { - QString s = callData->args[i].toQString(); + QString s = callData->args[i].toQStringNoThrow(); if (i) std::cout << ' '; std::cout << qPrintable(s); -- cgit v1.2.3