From e441692b0b8f8fffdfdfa8a21c570adcd5cbae7a Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 16 Sep 2013 22:02:27 +0200 Subject: Further work towards an exact GC Add some more convenience in the helper classes in qscopedvalue_p.h Make accesses to CallData safer, and change ExecutionEngine::newObject() to return a safe pointer. Change-Id: I980909754ce9681cf6faa1355bab3a1e5d6dd186 Reviewed-by: Simon Hausmann --- src/imports/localstorage/plugin.cpp | 40 ++--- src/imports/xmllistmodel/qqmlxmllistmodel.cpp | 5 +- src/particles/qquickv4particledata.cpp | 38 +++-- src/qml/jsapi/qjsengine.cpp | 2 +- src/qml/jsruntime/qv4argumentsobject.cpp | 6 +- src/qml/jsruntime/qv4arrayobject.cpp | 141 ++++++++-------- src/qml/jsruntime/qv4context.cpp | 6 +- src/qml/jsruntime/qv4context_p.h | 18 +- src/qml/jsruntime/qv4dateobject.cpp | 93 +++++----- src/qml/jsruntime/qv4engine.cpp | 14 +- src/qml/jsruntime/qv4engine_p.h | 6 +- src/qml/jsruntime/qv4errorobject_p.h | 5 + src/qml/jsruntime/qv4functionobject.cpp | 85 +++++----- src/qml/jsruntime/qv4functionobject_p.h | 5 + src/qml/jsruntime/qv4global_p.h | 5 + src/qml/jsruntime/qv4globalobject.cpp | 45 ++--- src/qml/jsruntime/qv4globalobject_p.h | 2 +- src/qml/jsruntime/qv4include.cpp | 5 +- src/qml/jsruntime/qv4jsonobject.cpp | 32 ++-- src/qml/jsruntime/qv4managed_p.h | 53 +++--- src/qml/jsruntime/qv4mm.cpp | 2 +- src/qml/jsruntime/qv4numberobject.cpp | 17 +- src/qml/jsruntime/qv4object_p.h | 15 +- src/qml/jsruntime/qv4objectproto.cpp | 190 ++++++++++++--------- src/qml/jsruntime/qv4runtime.cpp | 5 +- src/qml/jsruntime/qv4scopedvalue_p.h | 158 +++++++++++++---- src/qml/jsruntime/qv4serialize.cpp | 4 +- src/qml/jsruntime/qv4string_p.h | 15 +- src/qml/jsruntime/qv4stringobject.cpp | 40 ++--- src/qml/jsruntime/qv4value.cpp | 30 ++++ src/qml/jsruntime/qv4value_def_p.h | 31 ++++ src/qml/jsruntime/qv4value_p.h | 18 ++ src/qml/qml/qqmlcomponent.cpp | 5 +- src/qml/qml/qqmllocale.cpp | 26 ++- src/qml/qml/qqmlvaluetypewrapper.cpp | 5 +- src/qml/qml/qqmlxmlhttprequest.cpp | 104 +++++++----- src/qml/qml/v8/qqmlbuiltinfunctions.cpp | 7 +- src/qml/qml/v8/qv4domerrors.cpp | 5 +- src/qml/qml/v8/qv4sqlerrors.cpp | 5 +- src/qml/qml/v8/qv8engine.cpp | 10 +- src/qml/types/qqmldelegatemodel.cpp | 18 +- src/qml/types/qquickworkerscript.cpp | 29 ++-- src/qml/util/qqmladaptormodel.cpp | 10 +- src/quick/items/context2d/qquickcontext2d.cpp | 235 +++++++++++++++++++------- src/quick/items/qquickitem.cpp | 10 +- 45 files changed, 1000 insertions(+), 600 deletions(-) diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp index 246ddd96c5..900a5a09a3 100644 --- a/src/imports/localstorage/plugin.cpp +++ b/src/imports/localstorage/plugin.cpp @@ -201,12 +201,13 @@ static QString qmlsqldatabase_databaseFile(const QString& connectionName, QV8Eng static ReturnedValue qmlsqldatabase_rows_index(QQmlSqlDatabaseWrapper *r, ExecutionEngine *v4, quint32 index, bool *hasProperty = 0) { + Scope scope(v4); QV8Engine *v8 = v4->v8Engine; if (r->sqlQuery.at() == (int)index || r->sqlQuery.seek(index)) { QSqlRecord record = r->sqlQuery.record(); // XXX optimize - Object *row = v4->newObject(); + Scoped row(scope, v4->newObject()); for (int ii = 0; ii < record.count(); ++ii) { QVariant v = record.value(ii); if (v.isNull()) { @@ -217,11 +218,11 @@ static ReturnedValue qmlsqldatabase_rows_index(QQmlSqlDatabaseWrapper *r, Execut } if (hasProperty) *hasProperty = true; - return Value::fromObject(row).asReturnedValue(); + return row.asReturnedValue(); } else { if (hasProperty) *hasProperty = false; - return Value::undefinedValue().asReturnedValue(); + return Encode::undefined(); } } @@ -247,7 +248,7 @@ static ReturnedValue qmlsqldatabase_rows_item(SimpleCallContext *ctx) static ReturnedValue qmlsqldatabase_executeSql(SimpleCallContext *ctx) { QV4::Scope scope(ctx); - QQmlSqlDatabaseWrapper *r = ctx->thisObject.as(); + Scoped r(scope, ctx->thisObject); if (!r || r->type != QQmlSqlDatabaseWrapper::Query) V4THROW_REFERENCE("Not a SQLDatabase::Query object"); @@ -258,7 +259,7 @@ static ReturnedValue qmlsqldatabase_executeSql(SimpleCallContext *ctx) QSqlDatabase db = r->database; - QString sql = ctx->argument(0).toQStringNoThrow(); + QString sql = ctx->argumentCount ? ctx->arguments[0].toQString() : QString(); if (r->readonly && !sql.startsWith(QLatin1String("SELECT"),Qt::CaseInsensitive)) { V4THROW_SQL(SQLEXCEPTION_SYNTAX_ERR, QQmlEngine::tr("Read-only Transaction")); @@ -303,8 +304,8 @@ static ReturnedValue qmlsqldatabase_executeSql(SimpleCallContext *ctx) rows->database = db; rows->sqlQuery = query; - Object *resultObject = ctx->engine->newObject(); - result = Value::fromObject(resultObject); + Scoped resultObject(scope, ctx->engine->newObject()); + result = resultObject.asValue(); // XXX optimize resultObject->put(ctx->engine->newIdentifier("rowsAffected"), Value::fromInt32(query.numRowsAffected())); resultObject->put(ctx->engine->newIdentifier("insertId"), engine->toString(query.lastInsertId().toString())); @@ -328,16 +329,16 @@ static ReturnedValue qmlsqldatabase_changeVersion(SimpleCallContext *ctx) Scope scope(ctx); - QQmlSqlDatabaseWrapper *r = ctx->thisObject.as(); + Scoped r(scope, ctx->thisObject); if (!r || r->type != QQmlSqlDatabaseWrapper::Database) V4THROW_REFERENCE("Not a SQLDatabase object"); QV8Engine *engine = ctx->engine->v8Engine; QSqlDatabase db = r->database; - QString from_version = ctx->arguments[0].toQStringNoThrow(); - QString to_version = ctx->arguments[1].toQStringNoThrow(); - Value callback = ctx->argument(2); + QString from_version = ctx->arguments[0].toQString(); + QString to_version = ctx->arguments[1].toQString(); + Scoped callback(scope, ctx->argument(2)); if (from_version != r->version) V4THROW_SQL(SQLEXCEPTION_VERSION_ERR, QQmlEngine::tr("Version mismatch: expected %1, found %2").arg(from_version).arg(r->version)); @@ -350,7 +351,7 @@ static ReturnedValue qmlsqldatabase_changeVersion(SimpleCallContext *ctx) w->inTransaction = true; bool ok = true; - if (FunctionObject *f = callback.asFunctionObject()) { + if (!!callback) { ok = false; db.transaction(); @@ -358,7 +359,7 @@ static ReturnedValue qmlsqldatabase_changeVersion(SimpleCallContext *ctx) callData->thisObject = engine->global(); callData->args[0] = Value::fromObject(w); try { - f->call(callData); + callback->call(callData); } catch (Exception &) { db.rollback(); throw; @@ -442,24 +443,25 @@ static ReturnedValue qmlsqldatabase_read_transaction(SimpleCallContext *ctx) QQmlSqlDatabaseData::QQmlSqlDatabaseData(QV8Engine *engine) { ExecutionEngine *v4 = QV8Engine::getV4(engine); + Scope scope(v4); { - Object *proto = v4->newObject(); + Scoped proto(scope, v4->newObject()); proto->defineDefaultProperty(v4, QStringLiteral("transaction"), qmlsqldatabase_transaction); proto->defineDefaultProperty(v4, QStringLiteral("readTransaction"), qmlsqldatabase_read_transaction); Property *p = proto->insertMember(v4->newString(QStringLiteral("version")), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); p->setGetter(v4->newBuiltinFunction(v4->rootContext, v4->newString(QStringLiteral("version")), qmlsqldatabase_version)); proto->defineDefaultProperty(v4, QStringLiteral("changeVersion"), qmlsqldatabase_changeVersion); - databaseProto = Value::fromObject(proto); + databaseProto = proto; } { - Object *proto = v4->newObject(); + Scoped proto(scope, v4->newObject()); proto->defineDefaultProperty(v4, QStringLiteral("executeSql"), qmlsqldatabase_executeSql); - queryProto = Value::fromObject(proto); + queryProto = proto; } { - Object *proto = v4->newObject(); + Scoped proto(scope, v4->newObject()); proto->defineDefaultProperty(v4, QStringLiteral("item"), qmlsqldatabase_rows_item); Property *p = proto->insertMember(v4->newString(QStringLiteral("length")), Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); @@ -468,7 +470,7 @@ QQmlSqlDatabaseData::QQmlSqlDatabaseData(QV8Engine *engine) Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); p->setGetter(v4->newBuiltinFunction(v4->rootContext, v4->newString(QStringLiteral("forwardOnly")), qmlsqldatabase_rows_forwardOnly)); p->setSetter(v4->newBuiltinFunction(v4->rootContext, v4->newString(QStringLiteral("setForwardOnly")), qmlsqldatabase_rows_setForwardOnly)); - rowsProto = Value::fromObject(proto); + rowsProto = proto; } } diff --git a/src/imports/xmllistmodel/qqmlxmllistmodel.cpp b/src/imports/xmllistmodel/qqmlxmllistmodel.cpp index 9f6437625d..f87273be40 100644 --- a/src/imports/xmllistmodel/qqmlxmllistmodel.cpp +++ b/src/imports/xmllistmodel/qqmlxmllistmodel.cpp @@ -923,13 +923,14 @@ QQmlV4Handle QQuickXmlListModel::get(int index) const QQmlEngine *engine = qmlContext(this)->engine(); QV8Engine *v8engine = QQmlEnginePrivate::getV8Engine(engine); ExecutionEngine *v4engine = QV8Engine::getV4(v8engine); - Object *o = v4engine->newObject(); + Scope scope(v4engine); + Scoped o(scope, v4engine->newObject()); for (int ii = 0; ii < d->roleObjects.count(); ++ii) { Property *p = o->insertMember(v4engine->newIdentifier(d->roleObjects[ii]->name()), PropertyAttributes()); p->value = Value::fromReturnedValue(v8engine->fromVariant(d->data.value(ii).value(index))); } - return QQmlV4Handle(Value::fromObject(o)); + return QQmlV4Handle(o.asValue()); } /*! diff --git a/src/particles/qquickv4particledata.cpp b/src/particles/qquickv4particledata.cpp index 1a574600e0..23018677ea 100644 --- a/src/particles/qquickv4particledata.cpp +++ b/src/particles/qquickv4particledata.cpp @@ -328,7 +328,8 @@ static QV4::ReturnedValue particleData_curSize(QV4::SimpleCallContext *ctx) } #define COLOR_GETTER_AND_SETTER(VAR, NAME) static QV4::ReturnedValue particleData_get_ ## NAME (QV4::SimpleCallContext *ctx) \ { \ - QV4ParticleData *r = ctx->thisObject.as(); \ + QV4::Scope scope(ctx); \ + QV4::Scoped r(scope, ctx->thisObject); \ if (!r || !r->datum) \ ctx->throwError(QStringLiteral("Not a valid ParticleData object")); \ \ @@ -337,18 +338,21 @@ static QV4::ReturnedValue particleData_curSize(QV4::SimpleCallContext *ctx) \ static QV4::ReturnedValue particleData_set_ ## NAME (QV4::SimpleCallContext *ctx)\ {\ - QV4ParticleData *r = ctx->thisObject.as(); \ + QV4::Scope scope(ctx); \ + QV4::Scoped r(scope, ctx->thisObject); \ if (!r || !r->datum)\ ctx->throwError(QStringLiteral("Not a valid ParticleData object"));\ \ - r->datum->color. VAR = qMin(255, qMax(0, (int)floor(ctx->argument(0).toNumber() * 255.0)));\ + double d = ctx->argumentCount ? ctx->arguments[0].toNumber() : 0; \ + r->datum->color. VAR = qMin(255, qMax(0, (int)floor(d * 255.0)));\ return QV4::Encode::undefined(); \ } #define SEMIBOOL_GETTER_AND_SETTER(VARIABLE) static QV4::ReturnedValue particleData_get_ ## VARIABLE (QV4::SimpleCallContext *ctx) \ { \ - QV4ParticleData *r = ctx->thisObject.as(); \ + QV4::Scope scope(ctx); \ + QV4::Scoped r(scope, ctx->thisObject); \ if (!r || !r->datum) \ ctx->throwError(QStringLiteral("Not a valid ParticleData object")); \ \ @@ -357,17 +361,19 @@ static QV4::ReturnedValue particleData_set_ ## NAME (QV4::SimpleCallContext *ctx \ static QV4::ReturnedValue particleData_set_ ## VARIABLE (QV4::SimpleCallContext *ctx)\ {\ - QV4ParticleData *r = ctx->thisObject.as(); \ + QV4::Scope scope(ctx); \ + QV4::Scoped r(scope, ctx->thisObject); \ if (!r || !r->datum)\ ctx->throwError(QStringLiteral("Not a valid ParticleData object"));\ \ - r->datum-> VARIABLE = ctx->argument(0).toBoolean() ? 1.0 : 0.0;\ + r->datum-> VARIABLE = (ctx->argumentCount && ctx->arguments[0].toBoolean()) ? 1.0 : 0.0;\ return QV4::Encode::undefined(); \ } #define FLOAT_GETTER_AND_SETTER(VARIABLE) static QV4::ReturnedValue particleData_get_ ## VARIABLE (QV4::SimpleCallContext *ctx) \ { \ - QV4ParticleData *r = ctx->thisObject.as(); \ + QV4::Scope scope(ctx); \ + QV4::Scoped r(scope, ctx->thisObject); \ if (!r || !r->datum) \ ctx->throwError(QStringLiteral("Not a valid ParticleData object")); \ \ @@ -376,17 +382,19 @@ static QV4::ReturnedValue particleData_set_ ## VARIABLE (QV4::SimpleCallContext \ static QV4::ReturnedValue particleData_set_ ## VARIABLE (QV4::SimpleCallContext *ctx)\ {\ - QV4ParticleData *r = ctx->thisObject.as(); \ + QV4::Scope scope(ctx); \ + QV4::Scoped r(scope, ctx->thisObject); \ if (!r || !r->datum)\ ctx->throwError(QStringLiteral("Not a valid ParticleData object"));\ \ - r->datum-> VARIABLE = ctx->argument(0).toNumber();\ + r->datum-> VARIABLE = ctx->argumentCount ? ctx->arguments[0].toNumber() : qSNaN();\ return QV4::Encode::undefined(); \ } #define FAKE_FLOAT_GETTER_AND_SETTER(VARIABLE, GETTER, SETTER) static QV4::ReturnedValue particleData_get_ ## VARIABLE (QV4::SimpleCallContext *ctx) \ { \ - QV4ParticleData *r = ctx->thisObject.as(); \ + QV4::Scope scope(ctx); \ + QV4::Scoped r(scope, ctx->thisObject); \ if (!r || !r->datum) \ ctx->throwError(QStringLiteral("Not a valid ParticleData object")); \ \ @@ -395,11 +403,12 @@ static QV4::ReturnedValue particleData_set_ ## VARIABLE (QV4::SimpleCallContext \ static QV4::ReturnedValue particleData_set_ ## VARIABLE (QV4::SimpleCallContext *ctx)\ {\ - QV4ParticleData *r = ctx->thisObject.as(); \ + QV4::Scope scope(ctx); \ + QV4::Scoped r(scope, ctx->thisObject); \ if (!r || !r->datum)\ ctx->throwError(QStringLiteral("Not a valid ParticleData object"));\ \ - r->datum-> SETTER ( ctx->argument(0).toNumber() );\ + r->datum-> SETTER (ctx->argumentCount ? ctx->arguments[0].toNumber() : qSNaN());\ return QV4::Encode::undefined(); \ } @@ -444,7 +453,8 @@ FAKE_FLOAT_GETTER_AND_SETTER(curAY, curAY, setInstantaneousAY) QV8ParticleDataDeletable::QV8ParticleDataDeletable(QV8Engine *engine) { QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); - QV4::Object *p = v4->newObject(); + QV4::Scope scope(v4); + QV4::Scoped p(scope, v4->newObject()); p->defineDefaultProperty(v4, QStringLiteral("discard"), particleData_discard); p->defineDefaultProperty(v4, QStringLiteral("lifeLeft"), particleData_lifeLeft); @@ -485,7 +495,7 @@ QV8ParticleDataDeletable::QV8ParticleDataDeletable(QV8Engine *engine) REGISTER_ACCESSOR(p, v4, blue, blue); REGISTER_ACCESSOR(p, v4, alpha, alpha); - proto = QV4::Value::fromObject(p); + proto = p; } QV8ParticleDataDeletable::~QV8ParticleDataDeletable() diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp index b66dd51648..f99463256e 100644 --- a/src/qml/jsapi/qjsengine.cpp +++ b/src/qml/jsapi/qjsengine.cpp @@ -286,7 +286,7 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in */ QJSValue QJSEngine::newObject() { - return new QJSValuePrivate(d->m_v4Engine->newObject()); + return new QJSValuePrivate(d->m_v4Engine->newObject()->getPointer()); } /*! diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp index 6c028de372..62937921aa 100644 --- a/src/qml/jsruntime/qv4argumentsobject.cpp +++ b/src/qml/jsruntime/qv4argumentsobject.cpp @@ -84,12 +84,12 @@ ArgumentsObject::ArgumentsObject(CallContext *context) ensureArrayAttributes(); context->engine->requireArgumentsAccessors(numAccessors); for (uint i = 0; i < (uint)numAccessors; ++i) { - mappedArguments.append(context->argument(i)); + mappedArguments.append(context->arguments[i]); arrayData[i] = context->engine->argumentsAccessors.at(i); arrayAttributes[i] = Attr_Accessor; } for (uint i = numAccessors; i < argCount; ++i) { - arrayData[i] = Property::fromValue(context->argument(i)); + arrayData[i] = Property::fromValue(context->arguments[i]); arrayAttributes[i] = Attr_Data; } arrayDataLen = argCount; @@ -160,7 +160,7 @@ ReturnedValue ArgumentsGetterFunction::call(Managed *getter, CallData *callData) getter->engine()->current->throwTypeError(); assert(g->index < o->context->argumentCount); - return o->context->argument(g->index).asReturnedValue(); + return o->context->argument(g->index); } DEFINE_MANAGED_VTABLE(ArgumentsSetterFunction); diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index 1f09b97d5c..ce6bdca627 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -131,9 +131,8 @@ uint ArrayPrototype::getLength(ExecutionContext *ctx, Object *o) ReturnedValue ArrayPrototype::method_isArray(SimpleCallContext *ctx) { - Value arg = ctx->argument(0); - bool isArray = arg.asArrayObject(); - return Value::fromBoolean(isArray).asReturnedValue(); + bool isArray = ctx->argumentCount ? ctx->arguments[0].asArrayObject() : false; + return Encode(isArray); } ReturnedValue ArrayPrototype::method_toString(SimpleCallContext *ctx) @@ -174,13 +173,11 @@ ReturnedValue ArrayPrototype::method_concat(SimpleCallContext *ctx) } for (uint i = 0; i < ctx->argumentCount; ++i) { - Value arg = ctx->argument(i); - - if (ArrayObject *elt = arg.asArrayObject()) + if (ArrayObject *elt = ctx->arguments[i].asArrayObject()) result->arrayConcat(elt); else - result->arraySet(getLength(ctx, result.getPointer()), arg); + result->arraySet(getLength(ctx, result.getPointer()), ctx->arguments[i]); } return result.asReturnedValue(); @@ -189,13 +186,13 @@ ReturnedValue ArrayPrototype::method_concat(SimpleCallContext *ctx) ReturnedValue ArrayPrototype::method_join(SimpleCallContext *ctx) { Scope scope(ctx); - Value arg = ctx->argument(0); + ScopedValue arg(scope, ctx->argument(0)); QString r4; - if (arg.isUndefined()) + if (arg->isUndefined()) r4 = QStringLiteral(","); else - r4 = arg.toString(ctx)->toQString(); + r4 = arg->toQString(); Scoped self(scope, ctx->thisObject); ScopedValue length(scope, self->get(ctx->engine->id_length)); @@ -276,9 +273,9 @@ ReturnedValue ArrayPrototype::method_push(SimpleCallContext *ctx) if (len + ctx->argumentCount < len) { // ughh... double l = len; - for (double i = 0; i < ctx->argumentCount; ++i) { + for (int i = 0; i < ctx->argumentCount; ++i) { Value idx = Value::fromDouble(l + i); - instance->put(idx.toString(ctx), ctx->argument(i)); + instance->put(idx.toString(ctx), ctx->arguments[i]); } double newLen = l + ctx->argumentCount; if (!instance->isArrayObject()) @@ -290,7 +287,7 @@ ReturnedValue ArrayPrototype::method_push(SimpleCallContext *ctx) if (!instance->protoHasArray() && instance->arrayDataLen <= len) { for (uint i = 0; i < ctx->argumentCount; ++i) { - Value v = ctx->argument(i); + Value v = ctx->arguments[i]; if (!instance->sparseArray) { if (len >= instance->arrayAlloc) @@ -307,7 +304,7 @@ ReturnedValue ArrayPrototype::method_push(SimpleCallContext *ctx) } } else { for (uint i = 0; i < ctx->argumentCount; ++i) - instance->putIndexed(len + i, ctx->argument(i)); + instance->putIndexed(len + i, ctx->arguments[i]); len += ctx->argumentCount; } if (instance->isArrayObject()) @@ -408,7 +405,7 @@ ReturnedValue ArrayPrototype::method_slice(SimpleCallContext *ctx) Scoped result(scope, ctx->engine->newArrayObject()); uint len = ArrayPrototype::getLength(ctx, o); - double s = ctx->argument(0).toInteger(); + double s = ScopedValue(scope, ctx->argument(0))->toInteger(); uint start; if (s < 0) start = (uint)qMax(len + s, 0.); @@ -417,8 +414,8 @@ ReturnedValue ArrayPrototype::method_slice(SimpleCallContext *ctx) else start = (uint) s; uint end = len; - if (!ctx->argument(1).isUndefined()) { - double e = ctx->argument(1).toInteger(); + if (ctx->argumentCount > 1 && !ctx->arguments[1].isUndefined()) { + double e = ctx->arguments[1].toInteger(); if (e < 0) end = (uint)qMax(len + e, 0.); else if (e > len) @@ -442,12 +439,13 @@ ReturnedValue ArrayPrototype::method_slice(SimpleCallContext *ctx) ReturnedValue ArrayPrototype::method_sort(SimpleCallContext *ctx) { - Object *instance = ctx->thisObject.toObject(ctx); + Scope scope(ctx); + Scoped instance(scope, ctx->thisObject.toObject(ctx)); - uint len = getLength(ctx, instance); + uint len = getLength(ctx, instance.getPointer()); - Value comparefn = ctx->argument(0); - instance->arraySort(ctx, instance, comparefn, len); + ScopedValue comparefn(scope, ctx->argument(0)); + instance->arraySort(ctx, instance.getPointer(), comparefn, len); return ctx->thisObject.asReturnedValue(); } @@ -459,14 +457,14 @@ ReturnedValue ArrayPrototype::method_splice(SimpleCallContext *ctx) Scoped newArray(scope, ctx->engine->newArrayObject()); - double rs = ctx->argument(0).toInteger(); + double rs = ScopedValue(scope, ctx->argument(0))->toInteger(); uint start; if (rs < 0) start = (uint) qMax(0., len + rs); else start = (uint) qMin(rs, (double)len); - uint deleteCount = (uint)qMin(qMax(ctx->argument(1).toInteger(), 0.), (double)(len - start)); + uint deleteCount = (uint)qMin(qMax(ScopedValue(scope, ctx->argument(1))->toInteger(), 0.), (double)(len - start)); newArray->arrayReserve(deleteCount); Property *pd = newArray->arrayData; @@ -505,7 +503,7 @@ ReturnedValue ArrayPrototype::method_splice(SimpleCallContext *ctx) } for (uint i = 0; i < itemCount; ++i) - instance->putIndexed(start + i, ctx->argument(i + 2)); + instance->putIndexed(start + i, ctx->arguments[i + 2]); ctx->strictMode = true; instance->put(ctx->engine->id_length, Value::fromDouble(len - deleteCount + itemCount)); @@ -520,8 +518,9 @@ ReturnedValue ArrayPrototype::method_unshift(SimpleCallContext *ctx) uint len = getLength(ctx, instance); if (!instance->protoHasArray() && instance->arrayDataLen <= len) { + ScopedValue v(scope); for (int i = ctx->argumentCount - 1; i >= 0; --i) { - Value v = ctx->argument(i); + v = ctx->argument(i); if (!instance->sparseArray) { if (!instance->arrayOffset) @@ -551,7 +550,7 @@ ReturnedValue ArrayPrototype::method_unshift(SimpleCallContext *ctx) instance->deleteIndexedProperty(k + ctx->argumentCount - 1); } for (uint i = 0; i < ctx->argumentCount; ++i) - instance->putIndexed(i, ctx->argument(i)); + instance->putIndexed(i, ctx->arguments[i]); } uint newLen = len + ctx->argumentCount; @@ -578,14 +577,14 @@ ReturnedValue ArrayPrototype::method_indexOf(SimpleCallContext *ctx) uint fromIndex = 0; if (ctx->argumentCount >= 1) - searchValue = ctx->argument(0); + searchValue = ctx->arguments[0]; else searchValue = Value::undefinedValue(); if (ctx->argumentCount >= 2) { - double f = ctx->argument(1).toInteger(); + double f = ctx->arguments[1].toInteger(); if (f >= len) - return Value::fromInt32(-1).asReturnedValue(); + return Encode(-1); if (f < 0) f = qMax(len + f, 0.); fromIndex = (uint) f; @@ -597,9 +596,9 @@ ReturnedValue ArrayPrototype::method_indexOf(SimpleCallContext *ctx) bool exists; v = instance->getIndexed(k, &exists); if (exists && __qmljs_strict_equal(v, searchValue)) - return Value::fromDouble(k).asReturnedValue(); + return Encode(k); } - return Value::fromInt32(-1).asReturnedValue(); + return Encode(-1); } return instance->arrayIndexOf(searchValue, fromIndex, len, ctx, instance); @@ -623,13 +622,13 @@ ReturnedValue ArrayPrototype::method_lastIndexOf(SimpleCallContext *ctx) searchValue = Value::undefinedValue(); if (ctx->argumentCount >= 2) { - double f = ctx->argument(1).toInteger(); + double f = ctx->arguments[1].toInteger(); if (f > 0) f = qMin(f, (double)(len - 1)); else if (f < 0) { f = len + f; if (f < 0) - return Value::fromInt32(-1).asReturnedValue(); + return Encode(-1); } fromIndex = (uint) f + 1; } @@ -648,19 +647,17 @@ ReturnedValue ArrayPrototype::method_lastIndexOf(SimpleCallContext *ctx) ReturnedValue ArrayPrototype::method_every(SimpleCallContext *ctx) { Scope scope(ctx); - Object *instance = ctx->thisObject.toObject(ctx); + Scoped instance(scope, ctx->thisObject.toObject(ctx)); - uint len = getLength(ctx, instance); + uint len = getLength(ctx, instance.getPointer()); - FunctionObject *callback = ctx->argument(0).asFunctionObject(); + Scoped callback(scope, ctx->argument(0)); if (!callback) ctx->throwTypeError(); - Value thisArg = ctx->argument(1); - ScopedCallData callData(scope, 3); - callData->args[2] = Value::fromObject(instance); - callData->thisObject = thisArg; + callData->args[2] = instance.asValue(); + callData->thisObject = ctx->argument(1); ScopedValue r(scope); ScopedValue v(scope); @@ -682,17 +679,17 @@ ReturnedValue ArrayPrototype::method_every(SimpleCallContext *ctx) ReturnedValue ArrayPrototype::method_some(SimpleCallContext *ctx) { Scope scope(ctx); - Object *instance = ctx->thisObject.toObject(ctx); + Scoped instance(scope, ctx->thisObject.toObject(ctx)); - uint len = getLength(ctx, instance); + uint len = getLength(ctx, instance.getPointer()); - FunctionObject *callback = ctx->argument(0).asFunctionObject(); + Scoped callback(scope, ctx->argument(0)); if (!callback) ctx->throwTypeError(); ScopedCallData callData(scope, 3); callData->thisObject = ctx->argument(1); - callData->args[2] = Value::fromObject(instance); + callData->args[2] = instance; ScopedValue v(scope); for (uint k = 0; k < len; ++k) { @@ -705,25 +702,25 @@ ReturnedValue ArrayPrototype::method_some(SimpleCallContext *ctx) callData->args[1] = Value::fromDouble(k); Value r = Value::fromReturnedValue(callback->call(callData)); if (r.toBoolean()) - return Value::fromBoolean(true).asReturnedValue(); + return Encode(true); } - return Value::fromBoolean(false).asReturnedValue(); + return Encode(false); } ReturnedValue ArrayPrototype::method_forEach(SimpleCallContext *ctx) { Scope scope(ctx); - Object *instance = ctx->thisObject.toObject(ctx); + Scoped instance(scope, ctx->thisObject.toObject(ctx)); - uint len = getLength(ctx, instance); + uint len = getLength(ctx, instance.getPointer()); - FunctionObject *callback = ctx->argument(0).asFunctionObject(); + Scoped callback(scope, ctx->argument(0)); if (!callback) ctx->throwTypeError(); ScopedCallData callData(scope, 3); callData->thisObject = ctx->argument(1); - callData->args[2] = Value::fromObject(instance); + callData->args[2] = instance; ScopedValue v(scope); for (uint k = 0; k < len; ++k) { @@ -736,30 +733,28 @@ ReturnedValue ArrayPrototype::method_forEach(SimpleCallContext *ctx) callData->args[1] = Value::fromDouble(k); callback->call(callData); } - return Value::undefinedValue().asReturnedValue(); + return Encode::undefined(); } ReturnedValue ArrayPrototype::method_map(SimpleCallContext *ctx) { Scope scope(ctx); - Object *instance = ctx->thisObject.toObject(ctx); + Scoped instance(scope, ctx->thisObject.toObject(ctx)); - uint len = getLength(ctx, instance); + uint len = getLength(ctx, instance.getPointer()); - FunctionObject *callback = ctx->argument(0).asFunctionObject(); + Scoped callback(scope, ctx->argument(0)); if (!callback) ctx->throwTypeError(); - Value thisArg = ctx->argument(1); - Scoped a(scope, ctx->engine->newArrayObject()); a->arrayReserve(len); a->setArrayLengthUnchecked(len); ScopedValue mapped(scope); ScopedCallData callData(scope, 3); - callData->thisObject = thisArg; - callData->args[2] = Value::fromObject(instance); + callData->thisObject = ctx->argument(1); + callData->args[2] = instance; ScopedValue v(scope); for (uint k = 0; k < len; ++k) { @@ -779,23 +774,21 @@ ReturnedValue ArrayPrototype::method_map(SimpleCallContext *ctx) ReturnedValue ArrayPrototype::method_filter(SimpleCallContext *ctx) { Scope scope(ctx); - Object *instance = ctx->thisObject.toObject(ctx); + Scoped instance(scope, ctx->thisObject.toObject(ctx)); - uint len = getLength(ctx, instance); + uint len = getLength(ctx, instance.getPointer()); - FunctionObject *callback = ctx->argument(0).asFunctionObject(); + Scoped callback(scope, ctx->argument(0)); if (!callback) ctx->throwTypeError(); - Value thisArg = ctx->argument(1); - Scoped a(scope, ctx->engine->newArrayObject()); a->arrayReserve(len); ScopedValue selected(scope); ScopedCallData callData(scope, 3); - callData->thisObject = thisArg; - callData->args[2] = Value::fromObject(instance); + callData->thisObject = ctx->argument(1); + callData->args[2] = instance; ScopedValue v(scope); @@ -820,11 +813,11 @@ ReturnedValue ArrayPrototype::method_filter(SimpleCallContext *ctx) ReturnedValue ArrayPrototype::method_reduce(SimpleCallContext *ctx) { Scope scope(ctx); - Object *instance = ctx->thisObject.toObject(ctx); + Scoped instance(scope, ctx->thisObject.toObject(ctx)); - uint len = getLength(ctx, instance); + uint len = getLength(ctx, instance.getPointer()); - FunctionObject *callback = ctx->argument(0).asFunctionObject(); + Scoped callback(scope, ctx->argument(0)); if (!callback) ctx->throwTypeError(); @@ -849,7 +842,7 @@ ReturnedValue ArrayPrototype::method_reduce(SimpleCallContext *ctx) ScopedCallData callData(scope, 4); callData->thisObject = Value::undefinedValue(); callData->args[0] = acc; - callData->args[3] = Value::fromObject(instance); + callData->args[3] = instance; while (k < len) { bool kPresent; @@ -868,18 +861,18 @@ ReturnedValue ArrayPrototype::method_reduce(SimpleCallContext *ctx) ReturnedValue ArrayPrototype::method_reduceRight(SimpleCallContext *ctx) { Scope scope(ctx); - Object *instance = ctx->thisObject.toObject(ctx); + Scoped instance(scope, ctx->thisObject.toObject(ctx)); - uint len = getLength(ctx, instance); + uint len = getLength(ctx, instance.getPointer()); - FunctionObject *callback = ctx->argument(0).asFunctionObject(); + Scoped callback(scope, ctx->argument(0)); if (!callback) ctx->throwTypeError(); if (len == 0) { if (ctx->argumentCount == 1) ctx->throwTypeError(); - return ctx->argument(1).asReturnedValue(); + return ctx->argument(1); } uint k = len; @@ -901,7 +894,7 @@ ReturnedValue ArrayPrototype::method_reduceRight(SimpleCallContext *ctx) ScopedCallData callData(scope, 4); callData->thisObject = Value::undefinedValue(); - callData->args[3] = Value::fromObject(instance); + callData->args[3] = instance; while (k > 0) { bool kPresent; diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 6a97b9cfab..01cb2dd780 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -64,7 +64,7 @@ CallContext *ExecutionContext::newCallContext(void *stackSpace, FunctionObject * c->function = function; // ### - c->arguments = const_cast(callData->args); + c->arguments = const_cast(callData->args); c->realArgumentCount = callData->argc; c->argumentCount = callData->argc; c->thisObject = callData->thisObject; @@ -135,7 +135,7 @@ CallContext *ExecutionContext::newCallContext(FunctionObject *function, CallData std::fill(c->locals, c->locals + function->varCount, Value::undefinedValue()); c->argumentCount = qMax((uint)callData->argc, function->formalParameterCount); - c->arguments = c->locals + function->varCount; + c->arguments = static_cast(c->locals + function->varCount); if (callData->argc) ::memcpy(c->arguments, callData->args, callData->argc * sizeof(Value)); if (callData->argc < function->formalParameterCount) @@ -182,7 +182,7 @@ void ExecutionContext::createMutableBinding(String *name, bool deletable) if (ctx->type >= Type_CallContext) { CallContext *c = static_cast(ctx); if (!c->activation) - c->activation = engine->newObject(); + c->activation = engine->newObject()->getPointer(); activation = c->activation; break; } diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index 0c3b189401..fe15a53fd2 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -148,8 +148,6 @@ struct Q_QML_EXPORT ExecutionContext ReturnedValue getPropertyAndBase(String *name, Object **base); bool deleteProperty(String *name); - inline Value argument(unsigned int index = 0); - void mark(); inline CallContext *asCallContext(); @@ -160,9 +158,13 @@ struct SimpleCallContext : public ExecutionContext { void initSimpleCallContext(ExecutionEngine *engine); FunctionObject *function; - Value *arguments; + SafeValue *arguments; unsigned int realArgumentCount; unsigned int argumentCount; + + ReturnedValue argument(uint i) { + return i < argumentCount ? arguments[i].asReturnedValue() : Value::undefinedValue().asReturnedValue(); + } }; struct CallContext : public SimpleCallContext @@ -196,16 +198,6 @@ struct WithContext : public ExecutionContext void initWithContext(ExecutionContext *p, Object *with); }; -inline Value ExecutionContext::argument(unsigned int index) -{ - if (type >= Type_SimpleCallContext) { - CallContext *ctx = static_cast(this); - if (index < ctx->argumentCount) - return ctx->arguments[index]; - } - return Value::undefinedValue(); -} - inline CallContext *ExecutionContext::asCallContext() { return type >= Type_CallContext ? static_cast(this) : 0; diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index 76d712656a..14e54a2e53 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -772,20 +772,22 @@ double DatePrototype::getThisDate(ExecutionContext *ctx) ReturnedValue DatePrototype::method_parse(SimpleCallContext *ctx) { - return Encode(ParseString(ctx->argument(0).toString(ctx)->toQString())); + if (!ctx->argumentCount) + return Encode(qSNaN()); + return Encode(ParseString(ctx->arguments[0].toString(ctx)->toQString())); } ReturnedValue DatePrototype::method_UTC(SimpleCallContext *ctx) { const int numArgs = ctx->argumentCount; if (numArgs >= 2) { - double year = ctx->argument(0).toNumber(); - double month = ctx->argument(1).toNumber(); - double day = numArgs >= 3 ? ctx->argument(2).toNumber() : 1; - double hours = numArgs >= 4 ? ctx->argument(3).toNumber() : 0; - double mins = numArgs >= 5 ? ctx->argument(4).toNumber() : 0; - double secs = numArgs >= 6 ? ctx->argument(5).toNumber() : 0; - double ms = numArgs >= 7 ? ctx->argument(6).toNumber() : 0; + double year = ctx->arguments[0].toNumber(); + double month = ctx->arguments[1].toNumber(); + double day = numArgs >= 3 ? ctx->arguments[2].toNumber() : 1; + double hours = numArgs >= 4 ? ctx->arguments[3].toNumber() : 0; + double mins = numArgs >= 5 ? ctx->arguments[4].toNumber() : 0; + double secs = numArgs >= 6 ? ctx->arguments[5].toNumber() : 0; + double ms = numArgs >= 7 ? ctx->arguments[6].toNumber() : 0; if (year >= 0 && year <= 99) year += 1900; double t = MakeDate(MakeDay(year, month, day), @@ -996,22 +998,25 @@ ReturnedValue DatePrototype::method_getTimezoneOffset(SimpleCallContext *ctx) ReturnedValue DatePrototype::method_setTime(SimpleCallContext *ctx) { - DateObject *self = ctx->thisObject.asDateObject(); + Scope scope(ctx); + Scoped self(scope, ctx->thisObject); if (!self) ctx->throwTypeError(); - self->value.setDouble(TimeClip(ctx->argument(0).toNumber())); + double t = ctx->argumentCount ? ctx->arguments[0].toNumber() : qSNaN(); + self->value.setDouble(TimeClip(t)); return self->value.asReturnedValue(); } ReturnedValue DatePrototype::method_setMilliseconds(SimpleCallContext *ctx) { - DateObject *self = ctx->thisObject.asDateObject(); + Scope scope(ctx); + Scoped self(scope, ctx->thisObject); if (!self) ctx->throwTypeError(); double t = LocalTime(self->value.asDouble()); - double ms = ctx->argument(0).toNumber(); + double ms = ctx->argumentCount ? ctx->arguments[0].toNumber() : qSNaN(); self->value.setDouble(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms))))); return self->value.asReturnedValue(); } @@ -1023,7 +1028,7 @@ ReturnedValue DatePrototype::method_setUTCMilliseconds(SimpleCallContext *ctx) ctx->throwTypeError(); double t = self->value.asDouble(); - double ms = ctx->argument(0).toNumber(); + double ms = ctx->argumentCount ? ctx->arguments[0].toNumber() : qSNaN(); self->value.setDouble(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms))))); return self->value.asReturnedValue(); } @@ -1035,8 +1040,8 @@ ReturnedValue DatePrototype::method_setSeconds(SimpleCallContext *ctx) ctx->throwTypeError(); double t = LocalTime(self->value.asDouble()); - double sec = ctx->argument(0).toNumber(); - double ms = (ctx->argumentCount < 2) ? msFromTime(t) : ctx->argument(1).toNumber(); + double sec = ctx->argumentCount ? ctx->arguments[0].toNumber() : qSNaN(); + double ms = (ctx->argumentCount < 2) ? msFromTime(t) : ctx->arguments[1].toNumber(); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms)))); self->value.setDouble(t); return self->value.asReturnedValue(); @@ -1049,8 +1054,8 @@ ReturnedValue DatePrototype::method_setUTCSeconds(SimpleCallContext *ctx) ctx->throwTypeError(); double t = self->value.asDouble(); - double sec = ctx->argument(0).toNumber(); - double ms = (ctx->argumentCount < 2) ? msFromTime(t) : ctx->argument(1).toNumber(); + double sec = ctx->argumentCount ? ctx->arguments[0].toNumber() : qSNaN(); + double ms = (ctx->argumentCount < 2) ? msFromTime(t) : ctx->arguments[1].toNumber(); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms)))); self->value.setDouble(t); return self->value.asReturnedValue(); @@ -1063,9 +1068,9 @@ ReturnedValue DatePrototype::method_setMinutes(SimpleCallContext *ctx) ctx->throwTypeError(); double t = LocalTime(self->value.asDouble()); - double min = ctx->argument(0).toNumber(); - double sec = (ctx->argumentCount < 2) ? SecFromTime(t) : ctx->argument(1).toNumber(); - double ms = (ctx->argumentCount < 3) ? msFromTime(t) : ctx->argument(2).toNumber(); + double min = ctx->argumentCount ? ctx->arguments[0].toNumber() : qSNaN(); + double sec = (ctx->argumentCount < 2) ? SecFromTime(t) : ctx->arguments[1].toNumber(); + double ms = (ctx->argumentCount < 3) ? msFromTime(t) : ctx->arguments[2].toNumber(); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms)))); self->value.setDouble(t); return self->value.asReturnedValue(); @@ -1078,9 +1083,9 @@ ReturnedValue DatePrototype::method_setUTCMinutes(SimpleCallContext *ctx) ctx->throwTypeError(); double t = self->value.asDouble(); - double min = ctx->argument(0).toNumber(); - double sec = (ctx->argumentCount < 2) ? SecFromTime(t) : ctx->argument(1).toNumber(); - double ms = (ctx->argumentCount < 3) ? msFromTime(t) : ctx->argument(2).toNumber(); + double min = ctx->argumentCount ? ctx->arguments[0].toNumber() : qSNaN(); + double sec = (ctx->argumentCount < 2) ? SecFromTime(t) : ctx->arguments[1].toNumber(); + double ms = (ctx->argumentCount < 3) ? msFromTime(t) : ctx->arguments[2].toNumber(); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms)))); self->value.setDouble(t); return self->value.asReturnedValue(); @@ -1093,10 +1098,10 @@ ReturnedValue DatePrototype::method_setHours(SimpleCallContext *ctx) ctx->throwTypeError(); double t = LocalTime(self->value.asDouble()); - double hour = ctx->argument(0).toNumber(); - double min = (ctx->argumentCount < 2) ? MinFromTime(t) : ctx->argument(1).toNumber(); - double sec = (ctx->argumentCount < 3) ? SecFromTime(t) : ctx->argument(2).toNumber(); - double ms = (ctx->argumentCount < 4) ? msFromTime(t) : ctx->argument(3).toNumber(); + double hour = ctx->argumentCount ? ctx->arguments[0].toNumber() : qSNaN(); + double min = (ctx->argumentCount < 2) ? MinFromTime(t) : ctx->arguments[1].toNumber(); + double sec = (ctx->argumentCount < 3) ? SecFromTime(t) : ctx->arguments[2].toNumber(); + double ms = (ctx->argumentCount < 4) ? msFromTime(t) : ctx->arguments[3].toNumber(); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(hour, min, sec, ms)))); self->value.setDouble(t); return self->value.asReturnedValue(); @@ -1109,10 +1114,10 @@ ReturnedValue DatePrototype::method_setUTCHours(SimpleCallContext *ctx) ctx->throwTypeError(); double t = self->value.asDouble(); - double hour = ctx->argument(0).toNumber(); - double min = (ctx->argumentCount < 2) ? MinFromTime(t) : ctx->argument(1).toNumber(); - double sec = (ctx->argumentCount < 3) ? SecFromTime(t) : ctx->argument(2).toNumber(); - double ms = (ctx->argumentCount < 4) ? msFromTime(t) : ctx->argument(3).toNumber(); + double hour = ctx->argumentCount ? ctx->arguments[0].toNumber() : qSNaN(); + double min = (ctx->argumentCount < 2) ? MinFromTime(t) : ctx->arguments[1].toNumber(); + double sec = (ctx->argumentCount < 3) ? SecFromTime(t) : ctx->arguments[2].toNumber(); + double ms = (ctx->argumentCount < 4) ? msFromTime(t) : ctx->arguments[3].toNumber(); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(hour, min, sec, ms)))); self->value.setDouble(t); return self->value.asReturnedValue(); @@ -1125,7 +1130,7 @@ ReturnedValue DatePrototype::method_setDate(SimpleCallContext *ctx) ctx->throwTypeError(); double t = LocalTime(self->value.asDouble()); - double date = ctx->argument(0).toNumber(); + double date = ctx->argumentCount ? ctx->arguments[0].toNumber() : qSNaN(); t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t)))); self->value.setDouble(t); return self->value.asReturnedValue(); @@ -1138,7 +1143,7 @@ ReturnedValue DatePrototype::method_setUTCDate(SimpleCallContext *ctx) ctx->throwTypeError(); double t = self->value.asDouble(); - double date = ctx->argument(0).toNumber(); + double date = ctx->argumentCount ? ctx->arguments[0].toNumber() : qSNaN(); t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t)))); self->value.setDouble(t); return self->value.asReturnedValue(); @@ -1151,8 +1156,8 @@ ReturnedValue DatePrototype::method_setMonth(SimpleCallContext *ctx) ctx->throwTypeError(); double t = LocalTime(self->value.asDouble()); - double month = ctx->argument(0).toNumber(); - double date = (ctx->argumentCount < 2) ? DateFromTime(t) : ctx->argument(1).toNumber(); + double month = ctx->argumentCount ? ctx->arguments[0].toNumber() : qSNaN(); + double date = (ctx->argumentCount < 2) ? DateFromTime(t) : ctx->arguments[1].toNumber(); t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t)))); self->value.setDouble(t); return self->value.asReturnedValue(); @@ -1165,8 +1170,8 @@ ReturnedValue DatePrototype::method_setUTCMonth(SimpleCallContext *ctx) ctx->throwTypeError(); double t = self->value.asDouble(); - double month = ctx->argument(0).toNumber(); - double date = (ctx->argumentCount < 2) ? DateFromTime(t) : ctx->argument(1).toNumber(); + double month = ctx->argumentCount ? ctx->arguments[0].toNumber() : qSNaN(); + double date = (ctx->argumentCount < 2) ? DateFromTime(t) : ctx->arguments[1].toNumber(); t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t)))); self->value.setDouble(t); return self->value.asReturnedValue(); @@ -1183,7 +1188,7 @@ ReturnedValue DatePrototype::method_setYear(SimpleCallContext *ctx) t = 0; else t = LocalTime(t); - double year = ctx->argument(0).toNumber(); + double year = ctx->argumentCount ? ctx->arguments[0].toNumber() : qSNaN(); double r; if (std::isnan(year)) { r = qSNaN(); @@ -1205,9 +1210,9 @@ ReturnedValue DatePrototype::method_setUTCFullYear(SimpleCallContext *ctx) ctx->throwTypeError(); double t = self->value.asDouble(); - double year = ctx->argument(0).toNumber(); - double month = (ctx->argumentCount < 2) ? MonthFromTime(t) : ctx->argument(1).toNumber(); - double date = (ctx->argumentCount < 3) ? DateFromTime(t) : ctx->argument(2).toNumber(); + double year = ctx->argumentCount ? ctx->arguments[0].toNumber() : qSNaN(); + double month = (ctx->argumentCount < 2) ? MonthFromTime(t) : ctx->arguments[1].toNumber(); + double date = (ctx->argumentCount < 3) ? DateFromTime(t) : ctx->arguments[2].toNumber(); t = TimeClip(UTC(MakeDate(MakeDay(year, month, date), TimeWithinDay(t)))); self->value.setDouble(t); return self->value.asReturnedValue(); @@ -1222,9 +1227,9 @@ ReturnedValue DatePrototype::method_setFullYear(SimpleCallContext *ctx) double t = LocalTime(self->value.asDouble()); if (std::isnan(t)) t = 0; - double year = ctx->argument(0).toNumber(); - double month = (ctx->argumentCount < 2) ? MonthFromTime(t) : ctx->argument(1).toNumber(); - double date = (ctx->argumentCount < 3) ? DateFromTime(t) : ctx->argument(2).toNumber(); + double year = ctx->argumentCount ? ctx->arguments[0].toNumber() : qSNaN(); + double month = (ctx->argumentCount < 2) ? MonthFromTime(t) : ctx->arguments[1].toNumber(); + double date = (ctx->argumentCount < 3) ? DateFromTime(t) : ctx->arguments[2].toNumber(); t = TimeClip(UTC(MakeDate(MakeDay(year, month, date), TimeWithinDay(t)))); self->value.setDouble(t); return self->value.asReturnedValue(); diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index daa58d5e81..5bde6b8e46 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -248,7 +248,7 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory) // // set up the global object // - globalObject = newObject(); + globalObject = newObject()->getPointer(); rootContext->global = globalObject; rootContext->thisObject = Value::fromObject(globalObject); @@ -350,25 +350,25 @@ FunctionObject *ExecutionEngine::newBuiltinFunction(ExecutionContext *scope, Str return f; } -BoundFunction *ExecutionEngine::newBoundFunction(ExecutionContext *scope, FunctionObject *target, Value boundThis, const QVector &boundArgs) +Returned *ExecutionEngine::newBoundFunction(ExecutionContext *scope, FunctionObject *target, Value boundThis, const QVector &boundArgs) { assert(target); BoundFunction *f = new (memoryManager) BoundFunction(scope, target, boundThis, boundArgs); - return f; + return f->asReturned(); } -Object *ExecutionEngine::newObject() +Returned *ExecutionEngine::newObject() { Object *object = new (memoryManager) Object(this); - return object; + return object->asReturned(); } -Object *ExecutionEngine::newObject(InternalClass *internalClass) +Returned *ExecutionEngine::newObject(InternalClass *internalClass) { Object *object = new (memoryManager) Object(internalClass); - return object; + return object->asReturned(); } String *ExecutionEngine::newString(const QString &s) diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 297f756033..d00ef0ea35 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -262,10 +262,10 @@ struct Q_QML_EXPORT ExecutionEngine ExecutionContext *popContext(); FunctionObject *newBuiltinFunction(ExecutionContext *scope, String *name, ReturnedValue (*code)(SimpleCallContext *)); - BoundFunction *newBoundFunction(ExecutionContext *scope, FunctionObject *target, Value boundThis, const QVector &boundArgs); + Returned *newBoundFunction(ExecutionContext *scope, FunctionObject *target, Value boundThis, const QVector &boundArgs); - Object *newObject(); - Object *newObject(InternalClass *internalClass); + Returned *newObject(); + Returned *newObject(InternalClass *internalClass); String *newString(const QString &s); String *newIdentifier(const QString &text); diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h index 73d9362a6d..fb526e9b1e 100644 --- a/src/qml/jsruntime/qv4errorobject_p.h +++ b/src/qml/jsruntime/qv4errorobject_p.h @@ -77,6 +77,11 @@ struct ErrorObject: Object { static void destroy(Managed *that) { static_cast(that)->~ErrorObject(); } }; +template<> +inline ErrorObject *value_cast(const Value &v) { + return v.asErrorObject(); +} + struct EvalErrorObject: ErrorObject { EvalErrorObject(ExecutionEngine *engine, const Value &message); }; diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 0cf235475e..011ea34b7d 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -92,9 +92,10 @@ FunctionObject::FunctionObject(ExecutionContext *scope, String *name, bool creat #endif if (createProto) { - Object *proto = scope->engine->newObject(scope->engine->protoClass); + Scope s(scope); + Scoped proto(s, scope->engine->newObject(scope->engine->protoClass)); proto->memberData[Index_ProtoConstructor].value = Value::fromObject(this); - memberData[Index_Prototype].value = Value::fromObject(proto); + memberData[Index_Prototype].value = proto.asValue(); } if (name) @@ -158,16 +159,16 @@ bool FunctionObject::hasInstance(Managed *that, const Value &value) ReturnedValue FunctionObject::construct(Managed *that, CallData *) { - FunctionObject *f = static_cast(that); - ExecutionEngine *v4 = f->engine(); + ExecutionEngine *v4 = that->engine(); Scope scope(v4); + Scoped f(scope, that, Scoped::Cast); InternalClass *ic = v4->objectClass; Scoped proto(scope, f->get(v4->id_prototype)); if (!!proto) ic = v4->emptyClass->changePrototype(proto.getPointer()); - Object *obj = v4->newObject(ic); - return Value::fromObject(obj).asReturnedValue(); + Scoped obj(scope, v4->newObject(ic)); + return obj.asReturnedValue(); } ReturnedValue FunctionObject::call(Managed *, CallData *) @@ -298,20 +299,19 @@ ReturnedValue FunctionPrototype::method_apply(SimpleCallContext *ctx) if (!o) ctx->throwTypeError(); - Value thisArg = ctx->argument(0); - Value arg = ctx->argument(1); + ScopedValue arg(scope, ctx->argument(1)); - Object *arr = arg.asObject(); + Scoped arr(scope, arg); quint32 len; if (!arr) { len = 0; - if (!arg.isNullOrUndefined()) { + if (!arg->isNullOrUndefined()) { ctx->throwTypeError(); return Encode::undefined(); } } else { - len = ArrayPrototype::getLength(ctx, arr); + len = ArrayPrototype::getLength(ctx, arr.getPointer()); } ScopedCallData callData(scope, len); @@ -329,14 +329,13 @@ ReturnedValue FunctionPrototype::method_apply(SimpleCallContext *ctx) } } - callData->thisObject = thisArg; + callData->thisObject = ctx->argument(0); return o->call(callData); } ReturnedValue FunctionPrototype::method_call(SimpleCallContext *ctx) { Scope scope(ctx); - Value thisArg = ctx->argument(0); FunctionObject *o = ctx->thisObject.asFunctionObject(); if (!o) @@ -347,24 +346,23 @@ ReturnedValue FunctionPrototype::method_call(SimpleCallContext *ctx) std::copy(ctx->arguments + 1, ctx->arguments + ctx->argumentCount, callData->args); } - callData->thisObject = thisArg; + callData->thisObject = ctx->argument(0); return o->call(callData); } ReturnedValue FunctionPrototype::method_bind(SimpleCallContext *ctx) { - FunctionObject *target = ctx->thisObject.asFunctionObject(); + Scope scope(ctx); + Scoped target(scope, ctx->thisObject); if (!target) ctx->throwTypeError(); - Value boundThis = ctx->argument(0); + ScopedValue boundThis(scope, ctx->argument(0)); QVector boundArgs; for (uint i = 1; i < ctx->argumentCount; ++i) - boundArgs += ctx->argument(i); + boundArgs += ctx->arguments[i]; - - BoundFunction *f = ctx->engine->newBoundFunction(ctx->engine->rootContext, target, boundThis, boundArgs); - return Value::fromObject(f).asReturnedValue(); + return ctx->engine->newBoundFunction(ctx->engine->rootContext, target.getPointer(), boundThis, boundArgs)->asReturnedValue(); } @@ -411,19 +409,19 @@ ScriptFunction::ScriptFunction(ExecutionContext *scope, Function *function) ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData) { - ScriptFunction *f = static_cast(that); - ExecutionEngine *v4 = f->engine(); + ExecutionEngine *v4 = that->engine(); Scope scope(v4); + Scoped f(scope, static_cast(that)); InternalClass *ic = v4->objectClass; Value proto = f->memberData[Index_Prototype].value; if (proto.isObject()) ic = v4->emptyClass->changePrototype(proto.objectValue()); - Object *obj = v4->newObject(ic); + Scoped obj(scope, v4->newObject(ic)); ExecutionContext *context = v4->current; - callData->thisObject = Value::fromObject(obj); - ExecutionContext *ctx = context->newCallContext(f, callData); + callData->thisObject = obj.asValue(); + ExecutionContext *ctx = context->newCallContext(f.getPointer(), callData); ScopedValue result(scope); SAVE_JS_STACK(f->scope); @@ -438,7 +436,7 @@ ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData) if (result->isObject()) return result.asReturnedValue(); - return Value::fromObject(obj).asReturnedValue(); + return obj.asReturnedValue(); } ReturnedValue ScriptFunction::call(Managed *that, CallData *callData) @@ -507,35 +505,32 @@ SimpleScriptFunction::SimpleScriptFunction(ExecutionContext *scope, Function *fu ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData) { - SimpleScriptFunction *f = static_cast(that); - ExecutionEngine *v4 = f->engine(); + ExecutionEngine *v4 = that->engine(); Scope scope(v4); + Scoped f(scope, static_cast(that)); InternalClass *ic = v4->objectClass; - Value proto = f->memberData[Index_Prototype].value; - if (proto.isObject()) - ic = v4->emptyClass->changePrototype(proto.objectValue()); - Object *obj = v4->newObject(ic); + Scoped proto(scope, f->memberData[Index_Prototype].value); + if (!!proto) + ic = v4->emptyClass->changePrototype(proto.getPointer()); + Scoped obj(scope, v4->newObject(ic)); ExecutionContext *context = v4->current; void *stackSpace = alloca(requiredMemoryForExecutionContectSimple(f)); - callData->thisObject = Value::fromObject(obj); - ExecutionContext *ctx = context->newCallContext(stackSpace, f, callData); + callData->thisObject = obj; + ExecutionContext *ctx = context->newCallContext(stackSpace, f.getPointer(), callData); - ScopedValue result(scope); - SAVE_JS_STACK(f->scope); try { - result = f->function->code(ctx, f->function->codeData); + Scoped result(scope, f->function->code(ctx, f->function->codeData)); + ctx->engine->popContext(); + + if (!result) + return obj.asReturnedValue(); + return result.asReturnedValue(); } catch (Exception &ex) { ex.partiallyUnwindContext(context); throw; } - CHECK_JS_STACK(f->scope); - ctx->engine->popContext(); - - if (result->isObject()) - return result.asReturnedValue(); - return Value::fromObject(obj).asReturnedValue(); } ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData) @@ -598,7 +593,7 @@ ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData) ctx.strictMode = f->scope->strictMode; // ### needed? scope or parent context? ctx.thisObject = callData->thisObject; // ### const_cast - ctx.arguments = const_cast(callData->args); + ctx.arguments = const_cast(callData->args); ctx.argumentCount = callData->argc; v4->pushContext(&ctx); @@ -626,7 +621,7 @@ ReturnedValue IndexedBuiltinFunction::call(Managed *that, CallData *callData) ctx.strictMode = f->scope->strictMode; // ### needed? scope or parent context? ctx.thisObject = callData->thisObject; // ### const_cast - ctx.arguments = const_cast(callData->args); + ctx.arguments = const_cast(callData->args); ctx.argumentCount = callData->argc; v4->pushContext(&ctx); diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index 333b95ad74..a0f4cf9463 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -142,6 +142,11 @@ protected: { static_cast(that)->~FunctionObject(); } }; +template<> +inline FunctionObject *value_cast(const Value &v) { + return v.asFunctionObject(); +} + struct FunctionCtor: FunctionObject { Q_MANAGED diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h index 096187d91f..389468cc39 100644 --- a/src/qml/jsruntime/qv4global_p.h +++ b/src/qml/jsruntime/qv4global_p.h @@ -105,6 +105,11 @@ struct QObjectWrapper; // will return it in a register on all platforms. // It will be returned in rax on x64, [eax,edx] on x86 and [r0,r1] on arm typedef quint64 ReturnedValue; +template struct Scoped; +template struct Returned; +struct CallData; +struct ScopedValue; +struct ValueRef; namespace Global { enum { diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp index e0cbee11ca..9ec70f59be 100644 --- a/src/qml/jsruntime/qv4globalobject.cpp +++ b/src/qml/jsruntime/qv4globalobject.cpp @@ -444,7 +444,7 @@ ReturnedValue EvalFunction::call(Managed *that, CallData *callData) { // indirect call // ### const_cast - return static_cast(that)->evalCall(callData->thisObject, const_cast(callData->args), callData->argc, false); + return static_cast(that)->evalCall(callData->thisObject, const_cast(static_cast(callData->args)), callData->argc, false); } @@ -465,14 +465,15 @@ static inline int toInt(const QChar &qc, int R) } // parseInt [15.1.2.2] -ReturnedValue GlobalFunctions::method_parseInt(SimpleCallContext *context) +ReturnedValue GlobalFunctions::method_parseInt(SimpleCallContext *ctx) { - Value string = context->argument(0); - Value radix = context->argument(1); - int R = radix.isUndefined() ? 0 : radix.toInt32(); + Scope scope(ctx); + ScopedValue string(scope, ctx->argument(0)); + ScopedValue radix(scope, ctx->argument(1)); + int R = radix->isUndefined() ? 0 : radix->toInt32(); // [15.1.2.2] step by step: - String *inputString = string.toString(context); // 1 + String *inputString = string->toString(ctx); // 1 QString trimmed = inputString->toQString().trimmed(); // 2 const QChar *pos = trimmed.constData(); const QChar *end = pos + trimmed.length(); @@ -544,12 +545,12 @@ ReturnedValue GlobalFunctions::method_parseInt(SimpleCallContext *context) } // parseFloat [15.1.2.3] -ReturnedValue GlobalFunctions::method_parseFloat(SimpleCallContext *context) +ReturnedValue GlobalFunctions::method_parseFloat(SimpleCallContext *ctx) { - Value string = context->argument(0); + Scope scope(ctx); // [15.1.2.3] step by step: - String *inputString = string.toString(context); // 1 + Scoped inputString(scope, ctx->argument(0), Scoped::Convert); QString trimmed = inputString->toQString().trimmed(); // 2 // 4: @@ -570,24 +571,30 @@ ReturnedValue GlobalFunctions::method_parseFloat(SimpleCallContext *context) } /// isNaN [15.1.2.4] -ReturnedValue GlobalFunctions::method_isNaN(SimpleCallContext *context) +ReturnedValue GlobalFunctions::method_isNaN(SimpleCallContext *ctx) { - const Value &v = context->argument(0); - if (v.integerCompatible()) + if (!ctx->argumentCount) + // undefined gets converted to NaN + return Encode(true); + + if (ctx->arguments[0].integerCompatible()) return Encode(false); - double d = v.toNumber(); + double d = ctx->arguments[0].toNumber(); return Encode((bool)std::isnan(d)); } /// isFinite [15.1.2.5] -ReturnedValue GlobalFunctions::method_isFinite(SimpleCallContext *context) +ReturnedValue GlobalFunctions::method_isFinite(SimpleCallContext *ctx) { - const Value &v = context->argument(0); - if (v.integerCompatible()) + if (!ctx->argumentCount) + // undefined gets converted to NaN + return Encode(false); + + if (ctx->arguments[0].integerCompatible()) return Encode(true); - double d = v.toNumber(); + double d = ctx->arguments[0].toNumber(); return Encode((bool)std::isfinite(d)); } @@ -656,7 +663,7 @@ ReturnedValue GlobalFunctions::method_escape(SimpleCallContext *context) if (!context->argumentCount) return Value::fromString(context, QStringLiteral("undefined")).asReturnedValue(); - QString str = context->argument(0).toString(context)->toQString(); + QString str = context->arguments[0].toString(context)->toQString(); return Value::fromString(context, escape(str)).asReturnedValue(); } @@ -665,6 +672,6 @@ ReturnedValue GlobalFunctions::method_unescape(SimpleCallContext *context) if (!context->argumentCount) return Value::fromString(context, QStringLiteral("undefined")).asReturnedValue(); - QString str = context->argument(0).toString(context)->toQString(); + QString str = context->arguments[0].toString(context)->toQString(); return Value::fromString(context, unescape(str)).asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4globalobject_p.h b/src/qml/jsruntime/qv4globalobject_p.h index 90b3395baa..f49c8ebbb8 100644 --- a/src/qml/jsruntime/qv4globalobject_p.h +++ b/src/qml/jsruntime/qv4globalobject_p.h @@ -64,7 +64,7 @@ struct GlobalFunctions static ReturnedValue method_parseInt(SimpleCallContext *context); static ReturnedValue method_parseFloat(SimpleCallContext *context); static ReturnedValue method_isNaN(SimpleCallContext *context); - static ReturnedValue method_isFinite(SimpleCallContext *context); + static ReturnedValue method_isFinite(SimpleCallContext *ctx); static ReturnedValue method_decodeURI(SimpleCallContext *context); static ReturnedValue method_decodeURIComponent(SimpleCallContext *context); static ReturnedValue method_encodeURI(SimpleCallContext *context); diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp index 740bb406f3..4d9573b990 100644 --- a/src/qml/jsruntime/qv4include.cpp +++ b/src/qml/jsruntime/qv4include.cpp @@ -84,9 +84,10 @@ QV4Include::~QV4Include() QV4::ReturnedValue QV4Include::resultValue(QV4::ExecutionEngine *v4, Status status) { + QV4::Scope scope(v4); // XXX It seems inefficient to create this object from scratch each time. - QV4::Object *o = v4->newObject(); + QV4::Scoped o(scope, v4->newObject()); o->put(v4->newString("OK"), QV4::Value::fromInt32(Ok)); o->put(v4->newString("LOADING"), QV4::Value::fromInt32(Loading)); o->put(v4->newString("NETWORK_ERROR"), QV4::Value::fromInt32(NetworkError)); @@ -94,7 +95,7 @@ QV4::ReturnedValue QV4Include::resultValue(QV4::ExecutionEngine *v4, Status stat o->put(v4->newString("status"), QV4::Value::fromInt32(status)); - return QV4::Value::fromObject(o).asReturnedValue(); + return o.asReturnedValue(); } void QV4Include::callback(const QV4::Value &callback, const QV4::Value &status) diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp index 2bb755b537..aa6b261928 100644 --- a/src/qml/jsruntime/qv4jsonobject.cpp +++ b/src/qml/jsruntime/qv4jsonobject.cpp @@ -713,13 +713,12 @@ QString Stringify::Str(const QString &key, Value value) } if (replacerFunction) { - Object *holder = ctx->engine->newObject(); - Value holderValue = Value::fromObject(holder); + Scoped holder(scope, ctx->engine->newObject()); holder->put(ctx, QString(), value); ScopedCallData callData(scope, 2); callData->args[0] = Value::fromString(ctx, key); callData->args[1] = value; - callData->thisObject = holderValue; + callData->thisObject = holder; value = Value::fromReturnedValue(replacerFunction->call(callData)); } @@ -878,12 +877,14 @@ JsonObject::JsonObject(ExecutionContext *context) ReturnedValue JsonObject::method_parse(SimpleCallContext *ctx) { - QString jtext = ctx->argument(0).toString(ctx)->toQString(); + Scope scope(ctx); + ScopedValue v(scope, ctx->argument(0)); + QString jtext = v->toString(ctx)->toQString(); DEBUG << "parsing source = " << jtext; JsonParser parser(ctx, jtext.constData(), jtext.length()); QJsonParseError error; - Value result = parser.parse(&error); + ScopedValue result(scope, parser.parse(&error)); if (error.error != QJsonParseError::NoError) { DEBUG << "parse error" << error.errorString(); ctx->throwSyntaxError("JSON.parse: Parse error"); @@ -898,7 +899,7 @@ ReturnedValue JsonObject::method_stringify(SimpleCallContext *ctx) Stringify stringify(ctx); - Object *o = ctx->argument(1).asObject(); + Scoped o(scope, ctx->argument(1)); if (o) { stringify.replacerFunction = o->asFunctionObject(); if (o->isArrayObject()) { @@ -917,20 +918,21 @@ ReturnedValue JsonObject::method_stringify(SimpleCallContext *ctx) } } - Value s = ctx->argument(2); - if (NumberObject *n = s.asNumberObject()) + ScopedValue s(scope, ctx->argument(2)); + if (NumberObject *n = s->asNumberObject()) s = n->value; - else if (StringObject *so = s.asStringObject()) + else if (StringObject *so = s->asStringObject()) s = so->value; - if (s.isNumber()) { - stringify.gap = QString(qMin(10, (int)s.toInteger()), ' '); - } else if (s.isString()) { - stringify.gap = s.stringValue()->toQString().left(10); + if (s->isNumber()) { + stringify.gap = QString(qMin(10, (int)s->toInteger()), ' '); + } else if (s->isString()) { + stringify.gap = s->stringValue()->toQString().left(10); } - QString result = stringify.Str(QString(), ctx->argument(0)); + ScopedValue arg0(scope, ctx->argument(0)); + QString result = stringify.Str(QString(), arg0); if (result.isEmpty()) return Encode::undefined(); return Value::fromString(ctx, result).asReturnedValue(); @@ -978,7 +980,7 @@ QJsonValue JsonObject::toJsonValue(const QV4::Value &value, QV4::ReturnedValue JsonObject::fromJsonObject(ExecutionEngine *engine, const QJsonObject &object) { Scope scope(engine); - Scoped o(scope, Value::fromObject(engine->newObject())); + Scoped o(scope, engine->newObject()); for (QJsonObject::const_iterator it = object.begin(); it != object.end(); ++it) o->put(engine->newString(it.key()), Value::fromReturnedValue(fromJsonValue(engine, it.value()))); return o.asReturnedValue(); diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h index f13f699748..4c1675ef88 100644 --- a/src/qml/jsruntime/qv4managed_p.h +++ b/src/qml/jsruntime/qv4managed_p.h @@ -89,21 +89,6 @@ struct GCDeletable bool lastCall; }; -struct CallData -{ - // below is to be compatible with Value. Initialize tag to 0 -#if Q_BYTE_ORDER != Q_LITTLE_ENDIAN - uint tag; -#endif - int argc; -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - uint tag; -#endif - - Value thisObject; - Value args[1]; -}; - struct ManagedVTable { ReturnedValue (*call)(Managed *, CallData *data); @@ -245,14 +230,8 @@ public: return vtbl == &T::static_vtbl ? static_cast(this) : 0; } - template - static T *cast(const Value &v) { - return v.as(); - } - static Managed *cast(const Value &v) { - return v.asManaged(); - } - + String *asString() { return type == Type_String ? reinterpret_cast(this) : 0; } + Object *asObject() { return type != Type_String ? reinterpret_cast(this) : 0; } ArrayObject *asArrayObject() { return type == Type_ArrayObject ? reinterpret_cast(this) : 0; } FunctionObject *asFunctionObject() { return type == Type_FunctionObject ? reinterpret_cast(this) : 0; } BooleanObject *asBooleanObject() { return type == Type_BooleanObject ? reinterpret_cast(this) : 0; } @@ -353,6 +332,34 @@ private: friend struct ObjectIterator; }; +template<> +inline Managed *value_cast(const Value &v) { + return v.asManaged(); +} + +template +inline T *managed_cast(Managed *m) +{ + return m->as(); +} + +template<> +inline String *managed_cast(Managed *m) +{ + return m->asString(); +} +template<> +inline Object *managed_cast(Managed *m) +{ + return m->asObject(); +} +template<> +inline FunctionObject *managed_cast(Managed *m) +{ + return m->asFunctionObject(); +} + + inline ReturnedValue Managed::construct(CallData *d) { return vtbl->construct(this, d); } diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/jsruntime/qv4mm.cpp index 2d53fa3fe5..a7e485a2a2 100644 --- a/src/qml/jsruntime/qv4mm.cpp +++ b/src/qml/jsruntime/qv4mm.cpp @@ -340,7 +340,7 @@ std::size_t MemoryManager::sweep(bool lastSweep) } if (Managed *m = weak->value.asManaged()) { if (!m->markBit) { - weak->value = Value::emptyValue(); + weak->value = Value::undefinedValue(); PersistentValuePrivate *n = weak->next; weak->removeFromList(); weak = n; diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp index 3702428553..b9b64cf534 100644 --- a/src/qml/jsruntime/qv4numberobject.cpp +++ b/src/qml/jsruntime/qv4numberobject.cpp @@ -110,9 +110,8 @@ ReturnedValue NumberPrototype::method_toString(SimpleCallContext *ctx) { double num = thisNumberValue(ctx).asDouble(); - Value arg = ctx->argument(0); - if (!arg.isUndefined()) { - int radix = arg.toInt32(); + if (ctx->argumentCount && !ctx->arguments[0].isUndefined()) { + int radix = ctx->arguments[0].toInt32(); if (radix < 2 || radix > 36) { ctx->throwError(QString::fromLatin1("Number.prototype.toString: %0 is not a valid radix") .arg(radix)); @@ -180,7 +179,7 @@ ReturnedValue NumberPrototype::method_toFixed(SimpleCallContext *ctx) double fdigits = 0; if (ctx->argumentCount > 0) - fdigits = ctx->argument(0).toInteger(); + fdigits = ctx->arguments[0].toInteger(); if (std::isnan(fdigits)) fdigits = 0; @@ -204,11 +203,10 @@ ReturnedValue NumberPrototype::method_toExponential(SimpleCallContext *ctx) { double d = thisNumberValue(ctx).asDouble(); - Value fraction = ctx->argument(0); int fdigits = -1; - if (!fraction.isUndefined()) { - int fdigits = ctx->argument(0).toInt32(); + if (ctx->argumentCount && !ctx->arguments[0].isUndefined()) { + int fdigits = ctx->arguments[0].toInt32(); if (fdigits < 0 || fdigits > 20) { String *error = ctx->engine->newString(QStringLiteral("Number.prototype.toExponential: fractionDigits out of range")); ctx->throwRangeError(Value::fromString(error)); @@ -229,11 +227,10 @@ ReturnedValue NumberPrototype::method_toPrecision(SimpleCallContext *ctx) ScopedValue v(scope, thisNumberValue(ctx)); - Value prec = ctx->argument(0); - if (prec.isUndefined()) + if (!ctx->argumentCount || ctx->arguments[0].isUndefined()) return __qmljs_to_string(v, ctx); - double precision = prec.toInt32(); + double precision = ctx->arguments[0].toInt32(); if (precision < 1 || precision > 21) { String *error = ctx->engine->newString(QStringLiteral("Number.prototype.toPrecision: precision out of range")); ctx->throwRangeError(Value::fromString(error)); diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 7cb3fe45c2..83c7d864ff 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -178,10 +178,6 @@ struct Q_QML_EXPORT Object: Managed { inline ExecutionEngine *engine() const { return internalClass->engine; } - static Object *cast(const Value &v) { - return v.asObject(); - } - // Array handling uint allocArrayValue() { @@ -464,6 +460,17 @@ inline void Object::arraySet(uint index, const Property *pd) *arrayInsert(index) = *pd; } +template<> +inline Object *value_cast(const Value &v) { + return v.asObject(); +} + +template<> +inline ReturnedValue value_convert(ExecutionContext *ctx, const Value &v) +{ + return v.toObject(ctx)->asReturnedValue(); +} + } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index 073d588e56..82215e4fc5 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -85,11 +85,11 @@ ReturnedValue ObjectCtor::construct(Managed *that, CallData *callData) Scope scope(v4); ObjectCtor *ctor = static_cast(that); if (!callData->argc || callData->args[0].isUndefined() || callData->args[0].isNull()) { - Object *obj = v4->newObject(); + Scoped obj(scope, v4->newObject()); Scoped proto(scope, ctor->get(v4->id_prototype)); if (!!proto) obj->setPrototype(proto.getPointer()); - return Value::fromObject(obj).asReturnedValue(); + return obj.asReturnedValue(); } return Value::fromReturnedValue(__qmljs_to_object(v4->current, ValueRef(&callData->args[0]))).asReturnedValue(); } @@ -97,7 +97,7 @@ ReturnedValue ObjectCtor::construct(Managed *that, CallData *callData) ReturnedValue ObjectCtor::call(Managed *m, CallData *callData) { if (!callData->argc || callData->args[0].isUndefined() || callData->args[0].isNull()) - return Value::fromObject(m->engine()->newObject()).asReturnedValue(); + return m->engine()->newObject()->asReturnedValue(); return __qmljs_to_object(m->engine()->current, ValueRef(&callData->args[0])); } @@ -137,23 +137,26 @@ void ObjectPrototype::init(ExecutionContext *ctx, const Value &ctor) ReturnedValue ObjectPrototype::method_getPrototypeOf(SimpleCallContext *ctx) { - Value o = ctx->argument(0); - if (! o.isObject()) + Scope scope(ctx); + Scoped o(scope, ctx->argument(0)); + if (!o) ctx->throwTypeError(); - Object *p = o.objectValue()->prototype(); - return p ? Value::fromObject(p).asReturnedValue() : Encode::null(); + Scoped p(scope, o->prototype()); + return !!p ? p->asReturnedValue() : Encode::null(); } ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(SimpleCallContext *ctx) { - Value O = ctx->argument(0); - if (!O.isObject()) + Scope scope(ctx); + Scoped O(scope, ctx->argument(0)); + if (!O) ctx->throwTypeError(); - String *name = ctx->argument(1).toString(ctx); + ScopedValue v(scope, ctx->argument(1)); + Scoped name(scope, v->toString(ctx)); PropertyAttributes attrs; - Property *desc = O.objectValue()->__getOwnProperty__(name, &attrs); + Property *desc = O->__getOwnProperty__(name.getPointer(), &attrs); return fromPropertyDescriptor(ctx, desc, attrs); } @@ -169,36 +172,37 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyNames(SimpleCallContext *con ReturnedValue ObjectPrototype::method_create(SimpleCallContext *ctx) { - Value O = ctx->argument(0); - if (!O.isObject() && !O.isNull()) + Scope scope(ctx); + ScopedValue O(scope, ctx->argument(0)); + if (!O->isObject() && !O->isNull()) ctx->throwTypeError(); - Object *newObject = ctx->engine->newObject(); - newObject->setPrototype(O.asObject()); + Scoped newObject(scope, ctx->engine->newObject()); + newObject->setPrototype(O->asObject()); - Value objValue = Value::fromObject(newObject); - if (ctx->argumentCount > 1 && !ctx->argument(1).isUndefined()) { - ctx->arguments[0] = objValue; - method_defineProperties(ctx); + if (ctx->argumentCount > 1 && !ctx->arguments[1].isUndefined()) { + ctx->arguments[0] = newObject.asValue(); + return method_defineProperties(ctx); } - return objValue.asReturnedValue(); + return newObject.asReturnedValue(); } ReturnedValue ObjectPrototype::method_defineProperty(SimpleCallContext *ctx) { - Value O = ctx->argument(0); - if (!O.isObject()) + Scope scope(ctx); + Scoped O(scope, ctx->argument(0)); + if (!O) ctx->throwTypeError(); - String *name = ctx->argument(1).toString(ctx); + Scoped name(scope, ctx->argument(1), Scoped::Convert); - Value attributes = ctx->argument(2); + ScopedValue attributes(scope, ctx->argument(2)); Property pd; PropertyAttributes attrs; toPropertyDescriptor(ctx, attributes, &pd, &attrs); - if (!O.objectValue()->__defineOwnProperty__(ctx, name, pd, attrs)) + if (!O->__defineOwnProperty__(ctx, name.getPointer(), pd, attrs)) ctx->throwTypeError(); return O.asReturnedValue(); @@ -206,13 +210,14 @@ ReturnedValue ObjectPrototype::method_defineProperty(SimpleCallContext *ctx) ReturnedValue ObjectPrototype::method_defineProperties(SimpleCallContext *ctx) { - Value O = ctx->argument(0); - if (!O.isObject()) + Scope scope(ctx); + Scoped O(scope, ctx->argument(0)); + if (!O) ctx->throwTypeError(); - Object *o = ctx->argument(1).toObject(ctx); + Scoped o(scope, ctx->argument(1), Scoped::Convert); - ObjectIterator it(o, ObjectIterator::EnumerableOnly); + ObjectIterator it(o.getPointer(), ObjectIterator::EnumerableOnly); while (1) { uint index; String *name; @@ -225,9 +230,9 @@ ReturnedValue ObjectPrototype::method_defineProperties(SimpleCallContext *ctx) toPropertyDescriptor(ctx, Value::fromReturnedValue(o->getValue(pd, attrs)), &n, &nattrs); bool ok; if (name) - ok = O.objectValue()->__defineOwnProperty__(ctx, name, n, nattrs); + ok = O->__defineOwnProperty__(ctx, name, n, nattrs); else - ok = O.objectValue()->__defineOwnProperty__(ctx, index, n, nattrs); + ok = O->__defineOwnProperty__(ctx, index, n, nattrs); if (!ok) ctx->throwTypeError(); } @@ -237,10 +242,11 @@ ReturnedValue ObjectPrototype::method_defineProperties(SimpleCallContext *ctx) ReturnedValue ObjectPrototype::method_seal(SimpleCallContext *ctx) { - if (!ctx->argument(0).isObject()) + Scope scope(ctx); + Scoped o(scope, ctx->argument(0)); + if (!o) ctx->throwTypeError(); - Object *o = ctx->argument(0).objectValue(); o->extensible = false; o->internalClass = o->internalClass->sealed(); @@ -251,15 +257,16 @@ ReturnedValue ObjectPrototype::method_seal(SimpleCallContext *ctx) o->arrayAttributes[i].setConfigurable(false); } - return ctx->argument(0).asReturnedValue(); + return o.asReturnedValue(); } ReturnedValue ObjectPrototype::method_freeze(SimpleCallContext *ctx) { - if (!ctx->argument(0).isObject()) + Scope scope(ctx); + Scoped o(scope, ctx->argument(0)); + if (!o) ctx->throwTypeError(); - Object *o = ctx->argument(0).objectValue(); o->extensible = false; o->internalClass = o->internalClass->frozen(); @@ -271,25 +278,27 @@ ReturnedValue ObjectPrototype::method_freeze(SimpleCallContext *ctx) if (o->arrayAttributes[i].isData()) o->arrayAttributes[i].setWritable(false); } - return ctx->argument(0).asReturnedValue(); + return o.asReturnedValue(); } ReturnedValue ObjectPrototype::method_preventExtensions(SimpleCallContext *ctx) { - if (!ctx->argument(0).isObject()) + Scope scope(ctx); + Scoped o(scope, ctx->argument(0)); + if (!o) ctx->throwTypeError(); - Object *o = ctx->argument(0).objectValue(); o->extensible = false; - return ctx->argument(0).asReturnedValue(); + return o.asReturnedValue(); } ReturnedValue ObjectPrototype::method_isSealed(SimpleCallContext *ctx) { - if (!ctx->argument(0).isObject()) + Scope scope(ctx); + Scoped o(scope, ctx->argument(0)); + if (!o) ctx->throwTypeError(); - Object *o = ctx->argument(0).objectValue(); if (o->extensible) return Encode(false); @@ -313,10 +322,11 @@ ReturnedValue ObjectPrototype::method_isSealed(SimpleCallContext *ctx) ReturnedValue ObjectPrototype::method_isFrozen(SimpleCallContext *ctx) { - if (!ctx->argument(0).isObject()) + Scope scope(ctx); + Scoped o(scope, ctx->argument(0)); + if (!o) ctx->throwTypeError(); - Object *o = ctx->argument(0).objectValue(); if (o->extensible) return Encode(false); @@ -340,24 +350,24 @@ ReturnedValue ObjectPrototype::method_isFrozen(SimpleCallContext *ctx) ReturnedValue ObjectPrototype::method_isExtensible(SimpleCallContext *ctx) { - if (!ctx->argument(0).isObject()) + Scope scope(ctx); + Scoped o(scope, ctx->argument(0)); + if (!o) ctx->throwTypeError(); - Object *o = ctx->argument(0).objectValue(); return Encode((bool)o->extensible); } ReturnedValue ObjectPrototype::method_keys(SimpleCallContext *ctx) { - if (!ctx->argument(0).isObject()) - ctx->throwTypeError(); - Scope scope(ctx); - Object *o = ctx->argument(0).objectValue(); + Scoped o(scope, ctx->argument(0)); + if (!o) + ctx->throwTypeError(); Scoped a(scope, ctx->engine->newArrayObject()); - ObjectIterator it(o, ObjectIterator::EnumerableOnly); + ObjectIterator it(o.getPointer(), ObjectIterator::EnumerableOnly); ScopedValue name(scope); while (1) { name = it.nextPropertyNameAsString(); @@ -401,24 +411,26 @@ ReturnedValue ObjectPrototype::method_valueOf(SimpleCallContext *ctx) ReturnedValue ObjectPrototype::method_hasOwnProperty(SimpleCallContext *ctx) { - String *P = ctx->argument(0).toString(ctx); - Object *O = ctx->thisObject.toObject(ctx); - bool r = O->__getOwnProperty__(P) != 0; + Scope scope(ctx); + Scoped P(scope, ctx->argument(0), Scoped::Convert); + Scoped O(scope, ctx->thisObject, Scoped::Convert); + bool r = O->__getOwnProperty__(P.getPointer()) != 0; if (!r) - r = !O->query(P).isEmpty(); + r = !O->query(P.getPointer()).isEmpty(); return Encode(r); } ReturnedValue ObjectPrototype::method_isPrototypeOf(SimpleCallContext *ctx) { - Value V = ctx->argument(0); - if (! V.isObject()) + Scope scope(ctx); + Scoped V(scope, ctx->argument(0)); + if (!V) return Encode(false); - Object *O = ctx->thisObject.toObject(ctx); - Object *proto = V.objectValue()->prototype(); + Scoped O(scope, ctx->thisObject, Scoped::Convert); + Scoped proto(scope, V->prototype()); while (proto) { - if (O == proto) + if (O.getPointer() == proto.getPointer()) return Encode(true); proto = proto->prototype(); } @@ -427,11 +439,12 @@ ReturnedValue ObjectPrototype::method_isPrototypeOf(SimpleCallContext *ctx) ReturnedValue ObjectPrototype::method_propertyIsEnumerable(SimpleCallContext *ctx) { - String *p = ctx->argument(0).toString(ctx); + Scope scope(ctx); + Scoped p(scope, ctx->argument(0), Scoped::Convert); - Object *o = ctx->thisObject.toObject(ctx); + Scoped o(scope, ctx->thisObject, Scoped::Convert); PropertyAttributes attrs; - o->__getOwnProperty__(p, &attrs); + o->__getOwnProperty__(p.getPointer(), &attrs); return Encode(attrs.isEnumerable()); } @@ -439,21 +452,23 @@ ReturnedValue ObjectPrototype::method_defineGetter(SimpleCallContext *ctx) { if (ctx->argumentCount < 2) ctx->throwTypeError(); - String *prop = ctx->argument(0).toString(ctx); - FunctionObject *f = ctx->argument(1).asFunctionObject(); + Scope scope(ctx); + Scoped prop(scope, ctx->argument(0), Scoped::Convert); + + Scoped f(scope, ctx->argument(1)); if (!f) ctx->throwTypeError(); - Object *o = ctx->thisObject.asObject(); + Scoped o(scope, ctx->thisObject); if (!o) { if (!ctx->thisObject.isUndefined()) return Encode::undefined(); o = ctx->engine->globalObject; } - Property pd = Property::fromAccessor(f, 0); - o->__defineOwnProperty__(ctx, prop, pd, Attr_Accessor); + Property pd = Property::fromAccessor(f.getPointer(), 0); + o->__defineOwnProperty__(ctx, prop.getPointer(), pd, Attr_Accessor); return Encode::undefined(); } @@ -461,21 +476,23 @@ ReturnedValue ObjectPrototype::method_defineSetter(SimpleCallContext *ctx) { if (ctx->argumentCount < 2) ctx->throwTypeError(); - String *prop = ctx->argument(0).toString(ctx); - FunctionObject *f = ctx->argument(1).asFunctionObject(); + Scope scope(ctx); + Scoped prop(scope, ctx->argument(0), Scoped::Convert); + + Scoped f(scope, ctx->argument(1)); if (!f) ctx->throwTypeError(); - Object *o = ctx->thisObject.asObject(); + Scoped o(scope, ctx->thisObject); if (!o) { if (!ctx->thisObject.isUndefined()) return Encode::undefined(); o = ctx->engine->globalObject; } - Property pd = Property::fromAccessor(0, f); - o->__defineOwnProperty__(ctx, prop, pd, Attr_Accessor); + Property pd = Property::fromAccessor(0, f.getPointer()); + o->__defineOwnProperty__(ctx, prop.getPointer(), pd, Attr_Accessor); return Encode::undefined(); } @@ -490,20 +507,23 @@ ReturnedValue ObjectPrototype::method_get_proto(SimpleCallContext *ctx) ReturnedValue ObjectPrototype::method_set_proto(SimpleCallContext *ctx) { - Object *o = ctx->thisObject.asObject(); - if (!o) + Scope scope(ctx); + Scoped o(scope, ctx->thisObject); + if (!o || !ctx->argumentCount) ctx->throwTypeError(); - Value proto = ctx->argument(0); - bool ok = false; - if (proto.isNull()) { + if (ctx->arguments[0].isNull()) { o->setPrototype(0); - ok = true; - } else if (Object *p = proto.asObject()) { - if (o->prototype() == p) { + return Encode::undefined(); + } + + Scoped p(scope, ctx->arguments[0]); + bool ok = false; + if (!!p) { + if (o->prototype() == p.getPointer()) { ok = true; } else if (o->extensible) { - ok = o->setPrototype(p); + ok = o->setPrototype(p.getPointer()); } } if (!ok) @@ -532,6 +552,7 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, Value v, Prope if (o->__hasProperty__(ctx->engine->id_get)) { ScopedValue get(scope, o->get(ctx->engine->id_get)); FunctionObject *f = get->asFunctionObject(); + qDebug() << "get" << (void *)get.asReturnedValue() << f; if (f) { desc->setGetter(f); } else if (get->isUndefined()) { @@ -581,8 +602,9 @@ ReturnedValue ObjectPrototype::fromPropertyDescriptor(ExecutionContext *ctx, con return Encode::undefined(); ExecutionEngine *engine = ctx->engine; + Scope scope(engine); // Let obj be the result of creating a new object as if by the expression new Object() where Object is the standard built-in constructor with that name. - Object *o = engine->newObject(); + Scoped o(scope, engine->newObject()); Property pd; if (attrs.isData()) { @@ -601,7 +623,7 @@ ReturnedValue ObjectPrototype::fromPropertyDescriptor(ExecutionContext *ctx, con pd.value = Value::fromBoolean(attrs.isConfigurable()); o->__defineOwnProperty__(ctx, engine->newString(QStringLiteral("configurable")), pd, Attr_Data); - return Value::fromObject(o).asReturnedValue(); + return o.asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 2bd201e2a1..446ea9df3a 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1196,8 +1196,9 @@ void __qmljs_builtin_define_getter_setter(ExecutionContext *ctx, const ValueRef ReturnedValue __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, const QV4::Value *args, int classId) { + Scope scope(ctx); QV4::InternalClass *klass = ctx->compilationUnit->runtimeClasses[classId]; - Object *o = ctx->engine->newObject(klass); + Scoped o(scope, ctx->engine->newObject(klass)); for (int i = 0; i < klass->size; ++i) { if (klass->propertyData[i].isData()) @@ -1210,7 +1211,7 @@ ReturnedValue __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, } } - return Value::fromObject(o).asReturnedValue(); + return o.asReturnedValue(); } QV4::ReturnedValue __qmljs_builtin_setup_arguments_object(ExecutionContext *ctx) diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index 1e05b6170c..711c79eb1d 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -51,32 +51,6 @@ QT_BEGIN_NAMESPACE namespace QV4 { -struct ScopedValueArray { - ScopedValueArray(ExecutionEngine *e, int size) - : engine(e) -#ifndef QT_NO_DEBUG - , size(size) -#endif - { - ptr = e->stackPush(size); - } - - ~ScopedValueArray() { -#ifndef QT_NO_DEBUG - engine->stackPop(size); - Q_ASSERT(engine->jsStackTop == ptr); -#else - engine->jsStackTop = ptr; -#endif - } - - ExecutionEngine *engine; -#ifndef QT_NO_DEBUG - int size; -#endif - Value *ptr; -}; - struct ScopedValue; struct Scope { @@ -189,6 +163,9 @@ struct ScopedValue template struct Scoped { + enum _Convert { Convert }; + enum _Cast { Cast }; + inline void setPointer(Managed *p) { #if QT_POINTER_SIZE == 8 ptr->val = (quint64)p; @@ -209,7 +186,24 @@ struct Scoped Scoped(const Scope &scope, const Value &v) { ptr = scope.engine->jsStackTop++; - setPointer(T::cast(v)); + setPointer(value_cast(v)); +#ifndef QT_NO_DEBUG + ++scope.size; +#endif + } + Scoped(const Scope &scope, const ScopedValue &v) + { + ptr = scope.engine->jsStackTop++; + setPointer(value_cast(*v.ptr)); +#ifndef QT_NO_DEBUG + ++scope.size; +#endif + } + + Scoped(const Scope &scope, const Value &v, _Convert) + { + ptr = scope.engine->jsStackTop++; + ptr->val = value_convert(scope.engine->current, v); #ifndef QT_NO_DEBUG ++scope.size; #endif @@ -225,6 +219,16 @@ struct Scoped ++scope.size; #endif } + template + Scoped(const Scope &scope, X *t, _Cast) + { + ptr = scope.engine->jsStackTop++; + setPointer(managed_cast(t)); +#ifndef QT_NO_DEBUG + ++scope.size; +#endif + } + template Scoped(const Scope &scope, Returned *x) { @@ -238,21 +242,29 @@ struct Scoped Scoped(const Scope &scope, const ReturnedValue &v) { ptr = scope.engine->jsStackTop++; - setPointer(T::cast(QV4::Value::fromReturnedValue(v))); + setPointer(value_cast(QV4::Value::fromReturnedValue(v))); +#ifndef QT_NO_DEBUG + ++scope.size; +#endif + } + Scoped(const Scope &scope, const ReturnedValue &v, _Convert) + { + ptr = scope.engine->jsStackTop++; + ptr->val = value_convert(scope.engine->current, QV4::Value::fromReturnedValue(v)); #ifndef QT_NO_DEBUG ++scope.size; #endif } Scoped &operator=(const Value &v) { - setPointer(T::cast(v)); + setPointer(value_cast(v)); return *this; } Scoped &operator=(const ValueRef &v); Scoped &operator=(const ReturnedValue &v) { - setPointer(T::cast(QV4::Value::fromReturnedValue(v))); + setPointer(value_cast(QV4::Value::fromReturnedValue(v))); return *this; } @@ -280,7 +292,7 @@ struct Scoped bool operator!() const { return !ptr->managed(); } - operator bool() const { + operator void *() const { return ptr->managed(); } @@ -307,6 +319,21 @@ struct Scoped Value *ptr; }; +struct CallData +{ + // below is to be compatible with Value. Initialize tag to 0 +#if Q_BYTE_ORDER != Q_LITTLE_ENDIAN + uint tag; +#endif + int argc; +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN + uint tag; +#endif + + SafeValue thisObject; + SafeValue args[1]; +}; + struct ScopedCallData { ScopedCallData(Scope &scope, int argc) { @@ -388,7 +415,7 @@ template inline Scoped::Scoped(const Scope &scope, const ValueRef &v) { ptr = scope.engine->jsStackTop++; - setPointer(T::cast(*v.operator ->())); + setPointer(value_cast(*v.operator ->())); #ifndef QT_NO_DEBUG ++scope.size; #endif @@ -397,11 +424,10 @@ inline Scoped::Scoped(const Scope &scope, const ValueRef &v) template inline Scoped &Scoped::operator=(const ValueRef &v) { - setPointer(T::cast(*v.operator ->())); + setPointer(value_cast(*v.operator ->())); return *this; } - struct CallDataRef { CallDataRef(const ScopedCallData &c) : ptr(c.ptr) {} @@ -474,6 +500,70 @@ struct Encode : private Value { } }; +inline SafeValue &SafeValue::operator =(const ScopedValue &v) +{ + val = v.ptr->val; + return *this; +} + +template +inline SafeValue &SafeValue::operator=(Returned *t) +{ + val = t->getPointer()->asReturnedValue(); + return *this; +} + +template +inline SafeValue &SafeValue::operator=(const Scoped &t) +{ + val = t.ptr->val; + return *this; +} + +template +inline Returned *SafeValue::as() +{ + return Returned::create(value_cast(*this)); +} + +template +PersistentValue::PersistentValue(Returned *obj) + : d(new PersistentValuePrivate(QV4::Value::fromManaged(obj->getPointer()))) +{ +} + +template +inline PersistentValue::PersistentValue(const Scoped &obj) + : d(new PersistentValuePrivate(*obj.ptr)) +{ +} + +template +inline PersistentValue &PersistentValue::operator=(Returned *obj) +{ + return operator=(QV4::Value::fromManaged(obj->getPointer()).asReturnedValue()); +} + +template +inline PersistentValue &PersistentValue::operator=(const Scoped &obj) +{ + return operator=(*obj.ptr); +} + + +template +inline WeakValue::WeakValue(Returned *obj) + : d(new PersistentValuePrivate(QV4::Value::fromManaged(obj->getPointer()), /*engine*/0, /*weak*/true)) +{ +} + +template +inline WeakValue &WeakValue::operator=(Returned *obj) +{ + return operator=(QV4::Value::fromManaged(obj->getPointer()).asReturnedValue()); +} + + } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4serialize.cpp b/src/qml/jsruntime/qv4serialize.cpp index 41481ac1b8..35022acfd5 100644 --- a/src/qml/jsruntime/qv4serialize.cpp +++ b/src/qml/jsruntime/qv4serialize.cpp @@ -328,7 +328,7 @@ ReturnedValue Serialize::deserialize(const char *&data, QV8Engine *engine) case WorkerObject: { quint32 size = headersize(header); - QV4::Object *o = v4->newObject(); + Scoped o(scope, v4->newObject()); ScopedValue name(scope); ScopedValue value(scope); for (quint32 ii = 0; ii < size; ++ii) { @@ -336,7 +336,7 @@ ReturnedValue Serialize::deserialize(const char *&data, QV8Engine *engine) value = deserialize(data, engine); o->put(name->asString(), value); } - return QV4::Value::fromObject(o).asReturnedValue(); + return o.asReturnedValue(); } case WorkerInt32: return QV4::Encode((qint32)popUint32(data)); diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h index 7dd912a41f..7ad428a502 100644 --- a/src/qml/jsruntime/qv4string_p.h +++ b/src/qml/jsruntime/qv4string_p.h @@ -120,10 +120,6 @@ struct Q_QML_EXPORT String : public Managed { return _text.length(); } - static String *cast(const Value &v) { - return v.asString(); - } - QString _text; mutable Identifier *identifier; mutable uint stringHash; @@ -142,6 +138,17 @@ protected: static bool isEqualTo(Managed *that, Managed *o); }; +template<> +inline String *value_cast(const Value &v) { + return v.asString(); +} + +template<> +inline ReturnedValue value_convert(ExecutionContext *ctx, const Value &v) +{ + return v.toString(ctx)->asReturnedValue(); +} + } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index 811c5b26b9..afd6e440dc 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -472,8 +472,8 @@ ReturnedValue StringPrototype::method_replace(SimpleCallContext *ctx) uint *matchOffsets = _matchOffsets; uint nMatchOffsets = 0; - Value searchValue = ctx->argument(0); - RegExpObject *regExp = searchValue.as(); + ScopedValue searchValue(scope, ctx->argument(0)); + Scoped regExp(scope, searchValue); if (regExp) { uint offset = 0; while (true) { @@ -501,7 +501,7 @@ ReturnedValue StringPrototype::method_replace(SimpleCallContext *ctx) numCaptures = regExp->value->captureCount(); } else { numCaptures = 1; - QString searchString = searchValue.toString(ctx)->toQString(); + QString searchString = searchValue->toString(ctx)->toQString(); int idx = string.indexOf(searchString); if (idx != -1) { numStringMatches = 1; @@ -512,9 +512,10 @@ ReturnedValue StringPrototype::method_replace(SimpleCallContext *ctx) } QString result; - Value replaceValue = ctx->argument(1); ScopedValue replacement(scope); - if (FunctionObject* searchCallback = replaceValue.asFunctionObject()) { + ScopedValue replaceValue(scope, ctx->argument(1)); + Scoped searchCallback(scope, replaceValue); + if (!!searchCallback) { result.reserve(string.length() + 10*numStringMatches); ScopedCallData callData(scope, numCaptures + 2); callData->thisObject = Value::undefinedValue(); @@ -542,7 +543,7 @@ ReturnedValue StringPrototype::method_replace(SimpleCallContext *ctx) } result += string.midRef(lastEnd); } else { - QString newString = replaceValue.toString(ctx)->toQString(); + QString newString = replaceValue->toString(ctx)->toQString(); result.reserve(string.length() + numStringMatches*newString.size()); int lastEnd = 0; @@ -595,9 +596,9 @@ ReturnedValue StringPrototype::method_slice(SimpleCallContext *ctx) const QString text = getThisString(ctx); const double length = text.length(); - double start = ctx->argument(0).toInteger(); - double end = ctx->argument(1).isUndefined() - ? length : ctx->argument(1).toInteger(); + double start = ctx->argumentCount ? ctx->arguments[0].toInteger() : 0; + double end = (ctx->argumentCount < 2 || ctx->arguments[1].isUndefined()) + ? length : ctx->arguments[1].toInteger(); if (start < 0) start = qMax(length + start, 0.); @@ -625,32 +626,33 @@ ReturnedValue StringPrototype::method_split(SimpleCallContext *ctx) else text = ctx->thisObject.toString(ctx)->toQString(); - Value separatorValue = ctx->argumentCount > 0 ? ctx->argument(0) : Value::undefinedValue(); - Value limitValue = ctx->argumentCount > 1 ? ctx->argument(1) : Value::undefinedValue(); + ScopedValue separatorValue(scope, ctx->argument(0)); + ScopedValue limitValue(scope, ctx->argument(1)); Scoped array(scope, ctx->engine->newArrayObject()); - if (separatorValue.isUndefined()) { - if (limitValue.isUndefined()) { + if (separatorValue->isUndefined()) { + if (limitValue->isUndefined()) { array->push_back(Value::fromString(ctx, text)); return array.asReturnedValue(); } - return Value::fromString(ctx, text.left(limitValue.toInteger())).asReturnedValue(); + return Value::fromString(ctx, text.left(limitValue->toInteger())).asReturnedValue(); } - uint limit = limitValue.isUndefined() ? UINT_MAX : limitValue.toUInt32(); + uint limit = limitValue->isUndefined() ? UINT_MAX : limitValue->toUInt32(); if (limit == 0) return array.asReturnedValue(); - if (RegExpObject* re = separatorValue.as()) { + Scoped re(scope, separatorValue); + if (!!re) { if (re->value->pattern().isEmpty()) { - re = 0; + re = (RegExpObject *)0; separatorValue = Value::fromString(ctx, QString()); } } - if (RegExpObject* re = separatorValue.as()) { + if (!!re) { uint offset = 0; uint* matchOffsets = (uint*)alloca(re->value->captureCount() * 2 * sizeof(uint)); while (true) { @@ -675,7 +677,7 @@ ReturnedValue StringPrototype::method_split(SimpleCallContext *ctx) if (array->arrayLength() < limit) array->push_back(Value::fromString(ctx, text.mid(offset))); } else { - QString separator = separatorValue.toString(ctx)->toQString(); + QString separator = separatorValue->toString(ctx)->toQString(); if (separator.isEmpty()) { for (uint i = 0; i < qMin(limit, uint(text.length())); ++i) array->push_back(Value::fromString(ctx, text.mid(i, 1))); diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp index f97aa66669..570ba9e82e 100644 --- a/src/qml/jsruntime/qv4value.cpp +++ b/src/qml/jsruntime/qv4value.cpp @@ -288,6 +288,11 @@ PersistentValue::PersistentValue(const Value &val) { } +PersistentValue::PersistentValue(const ScopedValue &val) + : d(new PersistentValuePrivate(*val.operator ->())) +{ +} + PersistentValue::PersistentValue(ReturnedValue val) : d(new PersistentValuePrivate(Value::fromReturnedValue(val))) { @@ -326,6 +331,16 @@ PersistentValue &PersistentValue::operator =(const Value &other) return *this; } +PersistentValue &PersistentValue::operator =(const ScopedValue &other) +{ + return operator=(*other.operator ->()); +} + +PersistentValue &PersistentValue::operator =(const ValueRef other) +{ + return operator=(*other.operator ->()); +} + PersistentValue &PersistentValue::operator =(const ReturnedValue &other) { if (!d) { @@ -354,6 +369,11 @@ WeakValue::WeakValue(const WeakValue &other) d->ref(); } +WeakValue::WeakValue(ReturnedValue val) + : d(new PersistentValuePrivate(Value::fromReturnedValue(val), /*engine*/0, /*weak*/true)) +{ +} + WeakValue &WeakValue::operator=(const WeakValue &other) { if (d == other.d) @@ -380,6 +400,16 @@ WeakValue &WeakValue::operator =(const Value &other) return *this; } +WeakValue &WeakValue::operator =(const ReturnedValue &other) +{ + if (!d) { + d = new PersistentValuePrivate(Value::fromReturnedValue(other), /*engine*/0, /*weak*/true); + return *this; + } + d = d->detach(Value::fromReturnedValue(other), /*weak*/true); + return *this; +} + WeakValue::~WeakValue() { diff --git a/src/qml/jsruntime/qv4value_def_p.h b/src/qml/jsruntime/qv4value_def_p.h index 76f694c0e9..7d97d4531e 100644 --- a/src/qml/jsruntime/qv4value_def_p.h +++ b/src/qml/jsruntime/qv4value_def_p.h @@ -341,6 +341,37 @@ struct Q_QML_EXPORT Value inline void mark() const; }; +struct SafeValue : public Value +{ + SafeValue &operator =(const ScopedValue &v); + template + SafeValue &operator=(Returned *t); + SafeValue &operator=(ReturnedValue v) { + val = v; + return *this; + } + template + SafeValue &operator=(const Scoped &t); + SafeValue &operator=(const Value &v) { + val = v.val; + return *this; + } + + template + Returned *as(); +}; + +template +T *value_cast(const Value &v) +{ + return v.as(); +} + +template +ReturnedValue value_convert(ExecutionContext *ctx, const Value &v); + + + } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index de00a2264c..6cefe13ae6 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -372,11 +372,22 @@ public: PersistentValue() : d(0) {} PersistentValue(const Value &val); + PersistentValue(const ScopedValue &val); PersistentValue(ReturnedValue val); + template + PersistentValue(Returned *obj); + template + PersistentValue(const Scoped &obj); PersistentValue(const PersistentValue &other); PersistentValue &operator=(const PersistentValue &other); PersistentValue &operator=(const Value &other); + PersistentValue &operator=(const ScopedValue &other); + PersistentValue &operator=(const ValueRef other); PersistentValue &operator =(const ReturnedValue &other); + template + PersistentValue &operator=(Returned *obj); + template + PersistentValue &operator=(const Scoped &obj); ~PersistentValue(); Value value() const { @@ -408,8 +419,15 @@ public: WeakValue() : d(0) {} WeakValue(const Value &val); WeakValue(const WeakValue &other); + WeakValue(ReturnedValue val); + template + WeakValue(Returned *obj); WeakValue &operator=(const WeakValue &other); WeakValue &operator=(const Value &other); + WeakValue &operator =(const ReturnedValue &other); + template + WeakValue &operator=(Returned *obj); + ~WeakValue(); Value value() const { diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 5ed75a1e06..149cbf2c49 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -1408,7 +1408,8 @@ void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::Valu QQmlComponentExtension::QQmlComponentExtension(QV8Engine *engine) { QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); - QV4::Object *proto = v4->newObject(); + QV4::Scope scope(v4); + QV4::Scoped proto(scope, v4->newObject()); QV4::Property *s = proto->insertMember(v4->newString(QStringLiteral("onStatusChanged")), QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable); s->setGetter(V4FUNCTION(QmlIncubatorObject::method_get_statusChanged, v4)); @@ -1421,7 +1422,7 @@ QQmlComponentExtension::QQmlComponentExtension(QV8Engine *engine) s->setGetter(V4FUNCTION(QmlIncubatorObject::method_get_object, v4)); proto->defineDefaultProperty(v4, QStringLiteral("forceCompletion"), QmlIncubatorObject::method_forceCompletion); - incubationProto = QV4::Value::fromObject(proto); + incubationProto = proto; } QV4::ReturnedValue QmlIncubatorObject::method_get_object(QV4::SimpleCallContext *ctx) diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp index 405411e65c..d4998ec5ba 100644 --- a/src/qml/qml/qqmllocale.cpp +++ b/src/qml/qml/qqmllocale.cpp @@ -112,7 +112,7 @@ private: DEFINE_MANAGED_VTABLE(QQmlLocaleData); #define GET_LOCALE_DATA_RESOURCE(OBJECT) \ - QQmlLocaleData *r = OBJECT.as(); \ + QV4::Scoped r(scope, OBJECT.as()); \ if (!r) \ V4THROW_ERROR("Not a valid Locale object") @@ -140,6 +140,8 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleString(QV4::SimpleCallConte if (ctx->argumentCount > 2) return QV4::DatePrototype::method_toLocaleString(ctx); + QV4::Scope scope(ctx); + QV4::DateObject *date = ctx->thisObject.asDateObject(); if (!date) return QV4::DatePrototype::method_toLocaleString(ctx); @@ -182,6 +184,8 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleTimeString(QV4::SimpleCallC if (ctx->argumentCount > 2) return QV4::DatePrototype::method_toLocaleTimeString(ctx); + QV4::Scope scope(ctx); + QV4::DateObject *date = ctx->thisObject.asDateObject(); if (!date) return QV4::DatePrototype::method_toLocaleTimeString(ctx); @@ -225,6 +229,8 @@ QV4::ReturnedValue QQmlDateExtension::method_toLocaleDateString(QV4::SimpleCallC if (ctx->argumentCount > 2) return QV4::DatePrototype::method_toLocaleDateString(ctx); + QV4::Scope scope(ctx); + QV4::DateObject *dateObj = ctx->thisObject.asDateObject(); if (!dateObj) return QV4::DatePrototype::method_toLocaleDateString(ctx); @@ -273,6 +279,8 @@ QV4::ReturnedValue QQmlDateExtension::method_fromLocaleString(QV4::SimpleCallCon return QV4::Encode(engine->newDateObject(dt)); } + QV4::Scope scope(ctx); + if (ctx->argumentCount < 1 || ctx->argumentCount > 3 || !isLocaleObject(ctx->arguments[0])) V4THROW_ERROR("Locale: Date.fromLocaleString(): Invalid arguments"); @@ -315,6 +323,8 @@ QV4::ReturnedValue QQmlDateExtension::method_fromLocaleTimeString(QV4::SimpleCal if (ctx->argumentCount < 1 || ctx->argumentCount > 3 || !isLocaleObject(ctx->arguments[0])) V4THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid arguments"); + QV4::Scope scope(ctx); + GET_LOCALE_DATA_RESOURCE(ctx->arguments[0]); QLocale::FormatType enumFormat = QLocale::LongFormat; @@ -355,6 +365,8 @@ QV4::ReturnedValue QQmlDateExtension::method_fromLocaleDateString(QV4::SimpleCal if (ctx->argumentCount < 1 || ctx->argumentCount > 3 || !isLocaleObject(ctx->arguments[0])) V4THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid arguments"); + QV4::Scope scope(ctx); + GET_LOCALE_DATA_RESOURCE(ctx->arguments[0]); QLocale::FormatType enumFormat = QLocale::LongFormat; @@ -414,6 +426,8 @@ QV4::ReturnedValue QQmlNumberExtension::method_toLocaleString(QV4::SimpleCallCon if (!isLocaleObject(ctx->arguments[0])) return QV4::NumberPrototype::method_toLocaleString(ctx); // Use the default Number toLocaleString() + QV4::Scope scope(ctx); + GET_LOCALE_DATA_RESOURCE(ctx->arguments[0]); quint16 format = 'f'; @@ -450,6 +464,8 @@ QV4::ReturnedValue QQmlNumberExtension::method_toLocaleCurrencyString(QV4::Simpl if (!isLocaleObject(ctx->arguments[0])) V4THROW_ERROR("Locale: Number.toLocaleCurrencyString(): Invalid arguments"); + QV4::Scope scope(ctx); + GET_LOCALE_DATA_RESOURCE(ctx->arguments[0]); QString symbol; @@ -470,6 +486,8 @@ QV4::ReturnedValue QQmlNumberExtension::method_fromLocaleString(QV4::SimpleCallC int numberIdx = 0; QLocale locale; + QV4::Scope scope(ctx); + if (ctx->argumentCount == 2) { if (!isLocaleObject(ctx->arguments[0])) V4THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments"); @@ -671,8 +689,8 @@ public: QV8LocaleDataDeletable::QV8LocaleDataDeletable(QV8Engine *engine) { QV4::ExecutionEngine *eng = QV8Engine::getV4(engine); - QV4::Object *o = eng->newObject(); - prototype = QV4::Value::fromObject(o); + QV4::Scope scope(eng); + QV4::Scoped o(scope, eng->newObject()); o->defineDefaultProperty(eng, QStringLiteral("dateFormat"), QQmlLocaleData::method_dateFormat, 0); o->defineDefaultProperty(eng, QStringLiteral("standaloneDayName"), QQmlLocaleData::method_standaloneDayName, 0); @@ -699,6 +717,8 @@ QV8LocaleDataDeletable::QV8LocaleDataDeletable(QV8Engine *engine) o->defineAccessorProperty(eng, QStringLiteral("amText"), QQmlLocaleData::method_get_amText, 0); o->defineAccessorProperty(eng, QStringLiteral("measurementSystem"), QQmlLocaleData::method_get_measurementSystem, 0); o->defineAccessorProperty(eng, QStringLiteral("exponential"), QQmlLocaleData::method_get_exponential, 0); + + prototype = o; } QV8LocaleDataDeletable::~QV8LocaleDataDeletable() diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index f89ce15a57..b5073763b8 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -134,9 +134,10 @@ void QmlValueTypeWrapper::initProto(ExecutionEngine *v4) if (v4->qmlExtensions()->valueTypeWrapperPrototype) return; - Object *o = v4->newObject(); + Scope scope(v4); + Scoped o(scope, v4->newObject()); o->defineDefaultProperty(v4, QStringLiteral("toString"), method_toString, 1); - v4->qmlExtensions()->valueTypeWrapperPrototype = o; + v4->qmlExtensions()->valueTypeWrapperPrototype = o.getPointer(); } ReturnedValue QmlValueTypeWrapper::create(QV8Engine *v8, QObject *object, int property, QQmlValueType *type) diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index dc98bd176e..bef943fd51 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -65,6 +65,7 @@ #include #include +#include using namespace QV4; @@ -99,15 +100,15 @@ static inline QQmlXMLHttpRequestData *xhrdata(QV8Engine *engine) return (QQmlXMLHttpRequestData *)engine->xmlHttpRequestData(); } -static Value constructMeObject(const Value &thisObj, QV8Engine *e) +static ReturnedValue constructMeObject(const Value &thisObj, QV8Engine *e) { ExecutionEngine *v4 = QV8Engine::getV4(e); Scope scope(v4); - Object *meObj = v4->newObject(); + Scoped meObj(scope, v4->newObject()); meObj->put(v4->newString(QStringLiteral("ThisObject")), thisObj); ScopedValue v(scope, QmlContextWrapper::qmlScope(e, e->callingContext(), 0)); meObj->put(v4->newString(QStringLiteral("ActivationObject")), v); - return Value::fromObject(meObj); + return meObj.asReturnedValue(); } QQmlXMLHttpRequestData::QQmlXMLHttpRequestData() @@ -625,10 +626,11 @@ Value Element::prototype(ExecutionEngine *engine) { QQmlXMLHttpRequestData *d = xhrdata(engine->v8Engine); if (d->elementPrototype.isEmpty()) { - Object *p = engine->newObject(); + Scope scope(engine); + Scoped p(scope, engine->newObject()); p->setPrototype(NodePrototype::getProto(engine).asObject()); p->defineAccessorProperty(engine, QStringLiteral("tagName"), NodePrototype::method_get_nodeName, 0); - d->elementPrototype = Value::fromObject(p); + d->elementPrototype = p; engine->v8Engine->freezeObject(d->elementPrototype.value()); } return d->elementPrototype.value(); @@ -638,12 +640,13 @@ Value Attr::prototype(ExecutionEngine *engine) { QQmlXMLHttpRequestData *d = xhrdata(engine->v8Engine); if (d->attrPrototype.isEmpty()) { - Object *p = engine->newObject(); + Scope scope(engine); + Scoped p(scope, engine->newObject()); p->setPrototype(NodePrototype::getProto(engine).asObject()); p->defineAccessorProperty(engine, QStringLiteral("name"), method_name, 0); p->defineAccessorProperty(engine, QStringLiteral("value"), method_value, 0); p->defineAccessorProperty(engine, QStringLiteral("ownerElement"), method_ownerElement, 0); - d->attrPrototype = Value::fromObject(p); + d->attrPrototype = p; engine->v8Engine->freezeObject(d->attrPrototype.value()); } return d->attrPrototype.value(); @@ -693,11 +696,12 @@ Value CharacterData::prototype(ExecutionEngine *v4) { QQmlXMLHttpRequestData *d = xhrdata(v4->v8Engine); if (d->characterDataPrototype.isEmpty()) { - Object *p = v4->newObject(); + Scope scope(v4); + Scoped p(scope, v4->newObject()); p->setPrototype(NodePrototype::getProto(v4).asObject()); p->defineAccessorProperty(v4, QStringLiteral("data"), NodePrototype::method_get_nodeValue, 0); p->defineAccessorProperty(v4, QStringLiteral("length"), method_length, 0); - d->characterDataPrototype = Value::fromObject(p); + d->characterDataPrototype = p; v4->v8Engine->freezeObject(d->characterDataPrototype); } return d->characterDataPrototype.value(); @@ -725,11 +729,12 @@ Value Text::prototype(ExecutionEngine *v4) { QQmlXMLHttpRequestData *d = xhrdata(v4->v8Engine); if (d->textPrototype.isEmpty()) { - Object *p = v4->newObject(); + Scope scope(v4); + Scoped p(scope, v4->newObject()); p->setPrototype(CharacterData::prototype(v4).asObject()); p->defineAccessorProperty(v4, QStringLiteral("isElementContentWhitespace"), method_isElementContentWhitespace, 0); p->defineAccessorProperty(v4, QStringLiteral("wholeText"), method_wholeText, 0); - d->textPrototype = Value::fromObject(p); + d->textPrototype = p; v4->v8Engine->freezeObject(d->textPrototype); } return d->textPrototype.value(); @@ -740,9 +745,10 @@ Value CDATA::prototype(ExecutionEngine *v4) // ### why not just use TextProto??? QQmlXMLHttpRequestData *d = xhrdata(v4->v8Engine); if (d->cdataPrototype.isEmpty()) { - Object *p = v4->newObject(); + Scope scope(v4); + Scoped p(scope, v4->newObject()); p->setPrototype(Text::prototype(v4).asObject()); - d->cdataPrototype = Value::fromObject(p); + d->cdataPrototype = p; v4->v8Engine->freezeObject(d->cdataPrototype); } return d->cdataPrototype.value(); @@ -752,13 +758,14 @@ Value Document::prototype(ExecutionEngine *v4) { QQmlXMLHttpRequestData *d = xhrdata(v4->v8Engine); if (d->documentPrototype.isEmpty()) { - Object *p = v4->newObject(); + Scope scope(v4); + Scoped p(scope, v4->newObject()); p->setPrototype(NodePrototype::getProto(v4).asObject()); p->defineAccessorProperty(v4, QStringLiteral("xmlVersion"), method_xmlVersion, 0); p->defineAccessorProperty(v4, QStringLiteral("xmlEncoding"), method_xmlEncoding, 0); p->defineAccessorProperty(v4, QStringLiteral("xmlStandalone"), method_xmlStandalone, 0); p->defineAccessorProperty(v4, QStringLiteral("documentElement"), method_documentElement, 0); - d->documentPrototype = Value::fromObject(p); + d->documentPrototype = p; v4->v8Engine->freezeObject(d->documentPrototype); } return d->documentPrototype.value(); @@ -1016,9 +1023,9 @@ public: int replyStatus() const; QString replyStatusText() const; - Value open(const Value &me, const QString &, const QUrl &); - Value send(const Value &me, const QByteArray &); - Value abort(const Value &me); + ReturnedValue open(const ValueRef me, const QString &, const QUrl &); + ReturnedValue send(const ValueRef me, const QByteArray &); + ReturnedValue abort(const ValueRef me); void addHeader(const QString &, const QString &); QString header(const QString &name); @@ -1060,11 +1067,11 @@ private: #endif void readEncoding(); - Value getMe() const; - void setMe(const Value &me); + ReturnedValue getMe() const; + void setMe(const ValueRef me); PersistentValue m_me; - void dispatchCallback(const Value &me); + void dispatchCallback(const ValueRef me); void printError(const Exception &e); int m_status; @@ -1115,8 +1122,7 @@ QString QQmlXMLHttpRequest::replyStatusText() const return m_statusText; } -Value QQmlXMLHttpRequest::open(const Value &me, const QString &method, - const QUrl &url) +ReturnedValue QQmlXMLHttpRequest::open(const ValueRef me, const QString &method, const QUrl &url) { destroyNetwork(); m_sendFlag = false; @@ -1127,7 +1133,7 @@ Value QQmlXMLHttpRequest::open(const Value &me, const QString &method, m_state = Opened; m_addedHeaders.clear(); dispatchCallback(me); - return Value::undefinedValue(); + return Encode::undefined(); } void QQmlXMLHttpRequest::addHeader(const QString &name, const QString &value) @@ -1241,7 +1247,7 @@ void QQmlXMLHttpRequest::requestFromUrl(const QUrl &url) this, SLOT(finished())); } -Value QQmlXMLHttpRequest::send(const Value &me, const QByteArray &data) +ReturnedValue QQmlXMLHttpRequest::send(const ValueRef me, const QByteArray &data) { m_errorFlag = false; m_sendFlag = true; @@ -1252,10 +1258,10 @@ Value QQmlXMLHttpRequest::send(const Value &me, const QByteArray &data) requestFromUrl(m_url); - return Value::undefinedValue(); + return Encode::undefined(); } -Value QQmlXMLHttpRequest::abort(const Value &me) +ReturnedValue QQmlXMLHttpRequest::abort(const ValueRef me) { destroyNetwork(); m_responseEntityBody = QByteArray(); @@ -1273,15 +1279,15 @@ Value QQmlXMLHttpRequest::abort(const Value &me) m_state = Unsent; - return Value::undefinedValue(); + return Encode::undefined(); } -Value QQmlXMLHttpRequest::getMe() const +ReturnedValue QQmlXMLHttpRequest::getMe() const { - return m_me.value(); + return m_me.value().asReturnedValue(); } -void QQmlXMLHttpRequest::setMe(const Value &me) +void QQmlXMLHttpRequest::setMe(const ValueRef me) { m_me = me; } @@ -1293,18 +1299,22 @@ void QQmlXMLHttpRequest::readyRead() m_statusText = QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray()); + Scope scope(v4); + ScopedValue me(scope, m_me.value()); + // ### We assume if this is called the headers are now available if (m_state < HeadersReceived) { m_state = HeadersReceived; fillHeadersList (); - dispatchCallback(m_me.value()); + dispatchCallback(me); } bool wasEmpty = m_responseEntityBody.isEmpty(); m_responseEntityBody.append(m_network->readAll()); if (wasEmpty && !m_responseEntityBody.isEmpty()) m_state = Loading; - dispatchCallback(m_me.value()); + + dispatchCallback(me); } static const char *errorToString(QNetworkReply::NetworkError error) @@ -1335,6 +1345,9 @@ void QQmlXMLHttpRequest::error(QNetworkReply::NetworkError error) qWarning().nospace() << " " << error << ' ' << errorToString(error) << ' ' << m_statusText; } + Scope scope(v4); + ScopedValue me(scope, m_me.value()); + if (error == QNetworkReply::ContentAccessDenied || error == QNetworkReply::ContentOperationNotPermittedError || error == QNetworkReply::ContentNotFoundError || @@ -1342,7 +1355,7 @@ void QQmlXMLHttpRequest::error(QNetworkReply::NetworkError error) error == QNetworkReply::ContentReSendError || error == QNetworkReply::UnknownContentError) { m_state = Loading; - dispatchCallback(m_me.value()); + dispatchCallback(me); } else { m_errorFlag = true; m_responseEntityBody = QByteArray(); @@ -1350,7 +1363,7 @@ void QQmlXMLHttpRequest::error(QNetworkReply::NetworkError error) m_state = Done; - dispatchCallback(m_me.value()); + dispatchCallback(me); } #define XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION 15 @@ -1405,7 +1418,9 @@ void QQmlXMLHttpRequest::finished() dispatchCallback(m_me); - setMe(Value::emptyValue()); + Scope scope(v4); + ScopedValue v(scope, Value::emptyValue()); + setMe(v); } @@ -1483,12 +1498,12 @@ const QByteArray &QQmlXMLHttpRequest::rawResponseBody() const return m_responseEntityBody; } -void QQmlXMLHttpRequest::dispatchCallback(const Value &me) +void QQmlXMLHttpRequest::dispatchCallback(const ValueRef me) { ExecutionContext *ctx = v4->current; QV4::Scope scope(v4); try { - Object *o = me.asObject(); + Scoped o(scope, me); if (!o) ctx->throwError(QStringLiteral("QQmlXMLHttpRequest: internal error: empty ThisObject")); @@ -1631,7 +1646,9 @@ DEFINE_MANAGED_VTABLE(QQmlXMLHttpRequestCtor); void QQmlXMLHttpRequestCtor::setupProto() { ExecutionEngine *v4 = engine(); - proto = v4->newObject(); + Scope scope(v4); + Scoped p(scope, v4->newObject()); + proto = p.getPointer(); // Methods proto->defineDefaultProperty(v4, QStringLiteral("open"), method_open); @@ -1704,7 +1721,8 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_open(SimpleCallContext *ctx) if (!username.isNull()) url.setUserName(username); if (!password.isNull()) url.setPassword(password); - return r->open(constructMeObject(ctx->thisObject, engine), method, url).asReturnedValue(); + ScopedValue meObject(scope, constructMeObject(ctx->thisObject, engine)); + return r->open(meObject, method, url); } ReturnedValue QQmlXMLHttpRequestCtor::method_setRequestHeader(SimpleCallContext *ctx) @@ -1774,7 +1792,8 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_send(SimpleCallContext *ctx) if (ctx->argumentCount > 0) data = ctx->arguments[0].toQStringNoThrow().toUtf8(); - return r->send(constructMeObject(ctx->thisObject, engine), data).asReturnedValue(); + ScopedValue meObject(scope, constructMeObject(ctx->thisObject, engine)); + return r->send(meObject, data); } ReturnedValue QQmlXMLHttpRequestCtor::method_abort(SimpleCallContext *ctx) @@ -1786,7 +1805,8 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_abort(SimpleCallContext *ctx) V4THROW_REFERENCE("Not an XMLHttpRequest object"); QQmlXMLHttpRequest *r = w->request; - return r->abort(constructMeObject(ctx->thisObject, ctx->engine->v8Engine)).asReturnedValue(); + ScopedValue meObject(scope, constructMeObject(ctx->thisObject, ctx->engine->v8Engine)); + return r->abort(meObject); } ReturnedValue QQmlXMLHttpRequestCtor::method_getResponseHeader(SimpleCallContext *ctx) diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index 6389ad2715..40b5075ddd 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -962,12 +962,12 @@ ReturnedValue QtObject::method_createQmlObject(SimpleCallContext *ctx) for (int ii = 0; ii < errors.count(); ++ii) { const QQmlError &error = errors.at(ii); errorstr += QLatin1String("\n ") + error.toString(); - QV4::Object *qmlerror = v4->newObject(); + QV4::Scoped qmlerror(scope, v4->newObject()); qmlerror->put(v4->newString("lineNumber"), QV4::Value::fromInt32(error.line())); qmlerror->put(v4->newString("columnNumber"), QV4::Value::fromInt32(error.column())); qmlerror->put(v4->newString("fileName"), Value::fromString(v4->newString(error.url().toString()))); qmlerror->put(v4->newString("message"), Value::fromString(v4->newString(error.description()))); - qmlerrors->putIndexed(ii, QV4::Value::fromObject(qmlerror)); + qmlerrors->putIndexed(ii, qmlerror.asValue()); } Scoped errorObject(scope, v4->newErrorObject(Value::fromString(v4->newString(errorstr)))); @@ -1001,7 +1001,8 @@ ReturnedValue QtObject::method_createQmlObject(SimpleCallContext *ctx) url = context->resolvedUrl(url); QObject *parentArg = 0; - if (QV4::QObjectWrapper *qobjectWrapper = ctx->arguments[1].as()) + QV4::Scoped qobjectWrapper(scope, ctx->arguments[1]); + if (!!qobjectWrapper) parentArg = qobjectWrapper->object(); if (!parentArg) V4THROW_ERROR("Qt.createQmlObject(): Missing parent object"); diff --git a/src/qml/qml/v8/qv4domerrors.cpp b/src/qml/qml/v8/qv4domerrors.cpp index 63c79f85c2..f89831fa2f 100644 --- a/src/qml/qml/v8/qv4domerrors.cpp +++ b/src/qml/qml/v8/qv4domerrors.cpp @@ -48,7 +48,8 @@ using namespace QV4; void qt_add_domexceptions(ExecutionEngine *e) { - Object *domexception = e->newObject(); + Scope scope(e); + Scoped domexception(scope, e->newObject()); domexception->defineReadonlyProperty(e, QStringLiteral("INDEX_SIZE_ERR"), Value::fromInt32(DOMEXCEPTION_INDEX_SIZE_ERR)); domexception->defineReadonlyProperty(e, QStringLiteral("DOMSTRING_SIZE_ERR"), Value::fromInt32(DOMEXCEPTION_DOMSTRING_SIZE_ERR)); domexception->defineReadonlyProperty(e, QStringLiteral("HIERARCHY_REQUEST_ERR"), Value::fromInt32(DOMEXCEPTION_HIERARCHY_REQUEST_ERR)); @@ -66,7 +67,7 @@ void qt_add_domexceptions(ExecutionEngine *e) domexception->defineReadonlyProperty(e, QStringLiteral("INVALID_ACCESS_ERR"), Value::fromInt32(DOMEXCEPTION_INVALID_ACCESS_ERR)); domexception->defineReadonlyProperty(e, QStringLiteral("VALIDATION_ERR"), Value::fromInt32(DOMEXCEPTION_VALIDATION_ERR)); domexception->defineReadonlyProperty(e, QStringLiteral("TYPE_MISMATCH_ERR"), Value::fromInt32(DOMEXCEPTION_TYPE_MISMATCH_ERR)); - e->globalObject->defineDefaultProperty(e->current, QStringLiteral("DOMException"), Value::fromObject(domexception)); + e->globalObject->defineDefaultProperty(e->current, QStringLiteral("DOMException"), domexception.asValue()); } QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qv4sqlerrors.cpp b/src/qml/qml/v8/qv4sqlerrors.cpp index bd5a9fdc83..a203fd9980 100644 --- a/src/qml/qml/v8/qv4sqlerrors.cpp +++ b/src/qml/qml/v8/qv4sqlerrors.cpp @@ -49,7 +49,8 @@ using namespace QV4; void qt_add_sqlexceptions(QV4::ExecutionEngine *engine) { - Object *sqlexception = engine->newObject(); + Scope scope(engine); + Scoped sqlexception(scope, engine->newObject()); sqlexception->defineReadonlyProperty(engine, QStringLiteral("UNKNOWN_ERR"), Value::fromInt32(SQLEXCEPTION_UNKNOWN_ERR)); sqlexception->defineReadonlyProperty(engine, QStringLiteral("DATABASE_ERR"), Value::fromInt32(SQLEXCEPTION_DATABASE_ERR)); sqlexception->defineReadonlyProperty(engine, QStringLiteral("VERSION_ERR"), Value::fromInt32(SQLEXCEPTION_VERSION_ERR)); @@ -58,7 +59,7 @@ void qt_add_sqlexceptions(QV4::ExecutionEngine *engine) sqlexception->defineReadonlyProperty(engine, QStringLiteral("SYNTAX_ERR"), Value::fromInt32(SQLEXCEPTION_SYNTAX_ERR)); sqlexception->defineReadonlyProperty(engine, QStringLiteral("CONSTRAINT_ERR"), Value::fromInt32(SQLEXCEPTION_CONSTRAINT_ERR)); sqlexception->defineReadonlyProperty(engine, QStringLiteral("TIMEOUT_ERR"), Value::fromInt32(SQLEXCEPTION_TIMEOUT_ERR)); - engine->globalObject->defineDefaultProperty(engine->current, QStringLiteral("SQLException"), Value::fromObject(sqlexception)); + engine->globalObject->defineDefaultProperty(engine->current, QStringLiteral("SQLException"), sqlexception.asValue()); } QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp index 08bbd4c960..b62d8c173d 100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@ -212,10 +212,11 @@ static QV4::ReturnedValue arrayFromVariantList(QV8Engine *engine, const QVariant static QV4::ReturnedValue objectFromVariantMap(QV8Engine *engine, const QVariantMap &map) { QV4::ExecutionEngine *e = QV8Engine::getV4(engine); - QV4::Object *o = e->newObject(); + QV4::Scope scope(e); + QV4::Scoped o(scope, e->newObject()); for (QVariantMap::ConstIterator iter = map.begin(); iter != map.end(); ++iter) o->put(e->newString(iter.key()), QV4::Value::fromReturnedValue(engine->fromVariant(iter.value()))); - return QV4::Value::fromObject(o).asReturnedValue(); + return o.asReturnedValue(); } Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax); @@ -566,13 +567,14 @@ QVariantList QV8Engine::variantListFromJS(QV4::ArrayObject *a, // the QVariantMap converted to JS, recursively. QV4::ReturnedValue QV8Engine::variantMapToJS(const QVariantMap &vmap) { - QV4::Object *o = m_v4Engine->newObject(); + QV4::Scope scope(m_v4Engine); + QV4::Scoped o(scope, m_v4Engine->newObject()); QVariantMap::const_iterator it; for (it = vmap.constBegin(); it != vmap.constEnd(); ++it) { QV4::Property *p = o->insertMember(m_v4Engine->newIdentifier(it.key()), QV4::Attr_Data); p->value = QV4::Value::fromReturnedValue(variantToJS(it.value())); } - return QV4::Value::fromObject(o).asReturnedValue(); + return o.asReturnedValue(); } // Converts a JS Object to a QVariantMap. diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 0457adb348..b9f78da96e 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -83,10 +83,12 @@ struct DelegateModelGroupFunction: QV4::FunctionObject static QV4::ReturnedValue call(QV4::Managed *that, QV4::CallData *callData) { - DelegateModelGroupFunction *f = static_cast(that); - QQmlDelegateModelItemObject *o = callData->thisObject.as(); + QV4::ExecutionEngine *v4 = that->engine(); + QV4::Scope scope(v4); + QV4::Scoped f(scope, that, QV4::Scoped::Cast); + QV4::Scoped o(scope, callData->thisObject); if (!o) - that->engine()->current->throwTypeError(QStringLiteral("Not a valid VisualData object")); + v4->current->throwTypeError(QStringLiteral("Not a valid VisualData object")); QV4::Value v = callData->argc ? callData->args[0] : QV4::Value::undefinedValue(); return f->code(o->item, f->flag, v); @@ -1622,8 +1624,9 @@ void QQmlDelegateModelItemMetaType::initializePrototype() { QQmlDelegateModelEngineData *data = engineData(v8Engine); QV4::ExecutionEngine *v4 = QV8Engine::getV4(v8Engine); + QV4::Scope scope(v4); - QV4::Object *proto = v4->newObject(); + QV4::Scoped proto(scope, v4->newObject()); proto->defineAccessorProperty(v4, QStringLiteral("model"), QQmlDelegateModelItem::get_model, 0); proto->defineAccessorProperty(v4, QStringLiteral("groups"), QQmlDelegateModelItem::get_groups, QQmlDelegateModelItem::set_groups); QV4::Property *p = proto->insertMember(v4->newString(QStringLiteral("isUnresolved")), @@ -1656,7 +1659,7 @@ void QQmlDelegateModelItemMetaType::initializePrototype() p = proto->insertMember(v4->newString(propertyName), QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable); p->setGetter(new (v4->memoryManager) DelegateModelGroupFunction(v4->rootContext, i + 1, QQmlDelegateModelItem::get_index)); } - modelItemProto = QV4::Value::fromObject(proto); + modelItemProto = proto; } int QQmlDelegateModelItemMetaType::parseGroups(const QStringList &groups) const @@ -3233,15 +3236,16 @@ private: QQmlDelegateModelEngineData::QQmlDelegateModelEngineData(QV8Engine *e) { QV4::ExecutionEngine *v4 = QV8Engine::getV4(e); + QV4::Scope scope(v4); - QV4::Object *proto = v4->newObject(); + QV4::Scoped proto(scope, v4->newObject()); QV4::Property *p = proto->insertMember(v4->newString(QStringLiteral("index")), QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable); p->setGetter(v4->newBuiltinFunction(v4->rootContext, v4->id_undefined, QQmlDelegateModelGroupChange::method_get_index)); p = proto->insertMember(v4->newString(QStringLiteral("count")), QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable); p->setGetter(v4->newBuiltinFunction(v4->rootContext, v4->id_undefined, QQmlDelegateModelGroupChange::method_get_count)); p = proto->insertMember(v4->newString(QStringLiteral("moveId")), QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable); p->setGetter(v4->newBuiltinFunction(v4->rootContext, v4->id_undefined, QQmlDelegateModelGroupChange::method_get_moveId)); - changeProto = QV4::Value::fromObject(proto); + changeProto = proto; } QQmlDelegateModelEngineData::~QQmlDelegateModelEngineData() diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp index 4e39682d84..d80df760fa 100644 --- a/src/qml/types/qquickworkerscript.cpp +++ b/src/qml/types/qquickworkerscript.cpp @@ -177,7 +177,7 @@ public: }; QHash workers; - QV4::Value getWorker(WorkerScript *); + QV4::ReturnedValue getWorker(WorkerScript *); int m_nextId; @@ -282,9 +282,9 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::method_sendMessage(QV4::Simp { WorkerEngine *engine = (WorkerEngine*)ctx->engine->v8Engine; - int id = ctx->argument(1).toInt32(); + int id = ctx->argumentCount > 1 ? ctx->arguments[1].toInt32() : 0; - QByteArray data = QV4::Serialize::serialize(ctx->argument(2), engine); + QByteArray data = QV4::Serialize::serialize(ctx->argumentCount > 2 ? ctx->arguments[2] : QV4::Value::undefinedValue(), engine); QMutexLocker locker(&engine->p->m_lock); WorkerScript *script = engine->p->workers.value(id); @@ -298,27 +298,29 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::method_sendMessage(QV4::Simp } // Requires handle scope and context scope -QV4::Value QQuickWorkerScriptEnginePrivate::getWorker(WorkerScript *script) +QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::getWorker(WorkerScript *script) { if (!script->initialized) { script->initialized = true; QV4::ExecutionEngine *v4 = QV8Engine::getV4(workerEngine); + QV4::Scope scope(v4); script->object = QV4::QmlContextWrapper::urlScope(workerEngine, script->source); - QV4::QmlContextWrapper *w = script->object.value().asObject()->as(); + QV4::Scoped w(scope, script->object.value()); + Q_ASSERT(!!w); w->setReadOnly(false); - QV4::Object *api = v4->newObject(); + QV4::Scoped api(scope, v4->newObject()); api->put(v4->newString("sendMessage"), workerEngine->sendFunction(script->id)); - script->object.value().asObject()->put(v4->newString("WorkerScript"), QV4::Value::fromObject(api)); + script->object.value().asObject()->put(v4->newString("WorkerScript"), api.asValue()); w->setReadOnly(true); } - return script->object.value(); + return script->object.value().asReturnedValue(); } bool QQuickWorkerScriptEnginePrivate::event(QEvent *event) @@ -386,12 +388,15 @@ void QQuickWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url) if (!script) return; script->source = url; - QV4::Value activation = getWorker(script); - if (activation.isEmpty()) - return; QV4::ExecutionEngine *v4 = QV8Engine::getV4(workerEngine); - QV4::Script program(v4, activation.asObject(), sourceCode, url.toString()); + QV4::Scope scope(v4); + + QV4::Scoped activation(scope, getWorker(script)); + if (!activation) + return; + + QV4::Script program(v4, activation.getPointer(), sourceCode, url.toString()); QV4::ExecutionContext *ctx = v4->current; try { diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp index 9812e2a4a6..add422b8da 100644 --- a/src/qml/util/qqmladaptormodel.cpp +++ b/src/qml/util/qqmladaptormodel.cpp @@ -213,7 +213,8 @@ public: void initializeConstructor(QQmlAdaptorModelEngineData *const data) { QV4::ExecutionEngine *v4 = data->v4; - QV4::Object *proto = v4->newObject(); + QV4::Scope scope(v4); + QV4::Scoped proto(scope, v4->newObject()); QV4::Property *p = proto->insertMember(v4->newString(QStringLiteral("index")), QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable); p->setGetter(v4->newBuiltinFunction(v4->rootContext, v4->id_undefined, get_index)); @@ -232,7 +233,7 @@ public: p->setGetter(new (v4->memoryManager) QV4::IndexedBuiltinFunction(v4->rootContext, propertyId, QQmlDMCachedModelData::get_property)); p->setSetter(new (v4->memoryManager) QV4::IndexedBuiltinFunction(v4->rootContext, propertyId, QQmlDMCachedModelData::set_property)); } - prototype = QV4::Value::fromObject(proto); + prototype = proto.asValue(); } // QAbstractDynamicMetaObject @@ -955,7 +956,8 @@ void QQmlAdaptorModel::objectDestroyed(QObject *) QQmlAdaptorModelEngineData::QQmlAdaptorModelEngineData(QV8Engine *e) : v4(QV8Engine::getV4(e)) { - QV4::Object *proto = v4->newObject(); + QV4::Scope scope(v4); + QV4::Scoped proto(scope, v4->newObject()); QV4::Property *p = proto->insertMember(v4->newString(QStringLiteral("index")), QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable); p->setGetter(v4->newBuiltinFunction(v4->rootContext, v4->id_undefined, get_index)); @@ -963,7 +965,7 @@ QQmlAdaptorModelEngineData::QQmlAdaptorModelEngineData(QV8Engine *e) QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable); p->setGetter(v4->newBuiltinFunction(v4->rootContext, v4->id_undefined, QQmlDMListAccessorData::get_modelData)); p->setSetter(v4->newBuiltinFunction(v4->rootContext, v4->id_undefined, QQmlDMListAccessorData::set_modelData)); - listItemProto = QV4::Value::fromObject(proto); + listItemProto = proto; } QQmlAdaptorModelEngineData::~QQmlAdaptorModelEngineData() diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index 3a84404d66..82fbbd0862 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -941,6 +941,8 @@ static QV4::Value qt_create_image_data(qreal w, qreal h, QV8Engine* engine, cons */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_get_canvas(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -955,6 +957,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_get_canvas(QV4::SimpleCall */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_restore(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -968,6 +972,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_restore(QV4::SimpleCallCon */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_reset(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -1008,6 +1014,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_reset(QV4::SimpleCallConte */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_save(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -1036,6 +1044,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_save(QV4::SimpleCallContex */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_rotate(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -1063,6 +1073,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_rotate(QV4::SimpleCallCont */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_scale(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -1107,6 +1119,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_scale(QV4::SimpleCallConte */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_setTransform(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -1135,6 +1149,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_setTransform(QV4::SimpleCa */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_transform(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -1181,6 +1197,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_translate(QV4::SimpleCallC */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_resetTransform(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -1198,6 +1216,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_resetTransform(QV4::Simple */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_shear(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -1225,10 +1245,12 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_globalAlpha(QV4::SimpleCallCont QV4::ReturnedValue QQuickJSContext2D::method_set_globalAlpha(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT_SETTER(r) - double globalAlpha = ctx->argument(0).toNumber(); + double globalAlpha = ctx->argumentCount ? ctx->arguments[0].toNumber() : qSNaN(); if (!qIsFinite(globalAlpha)) return QV4::Encode::undefined(); @@ -1268,6 +1290,8 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_globalAlpha(QV4::SimpleCallCont */ QV4::ReturnedValue QQuickJSContext2D::method_get_globalCompositeOperation(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -1276,10 +1300,15 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_globalCompositeOperation(QV4::S QV4::ReturnedValue QQuickJSContext2D::method_set_globalCompositeOperation(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT_SETTER(r) - QString mode = ctx->argument(0).toQStringNoThrow(); + if (!ctx->argumentCount) + ctx->throwTypeError(); + + QString mode = ctx->arguments[0].toQString(); QPainter::CompositionMode cm = qt_composite_mode_from_string(mode); if (cm == QPainter::CompositionMode_SourceOver && mode != QStringLiteral("source-over")) return QV4::Encode::undefined(); @@ -1316,6 +1345,8 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_globalCompositeOperation(QV4::S */ QV4::ReturnedValue QQuickJSContext2D::method_get_fillStyle(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -1336,20 +1367,22 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_fillStyle(QV4::SimpleCallContex QV4::ReturnedValue QQuickJSContext2D::method_set_fillStyle(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT_SETTER(r) - QV4::Value value = ctx->argument(0); + QV4::ScopedValue value(scope, ctx->argument(0)); QV8Engine *engine = ctx->engine->v8Engine; - if (value.asObject()) { + if (value->asObject()) { QColor color = engine->toVariant(value, qMetaTypeId()).value(); if (color.isValid()) { r->context->state.fillStyle = color; r->context->buffer()->setFillStyle(color); r->context->m_fillStyle = value; } else { - QQuickContext2DStyle *style = value.as(); + QQuickContext2DStyle *style = value->as(); if (style && style->brush != r->context->state.fillStyle) { r->context->state.fillStyle = style->brush; r->context->buffer()->setFillStyle(style->brush, style->patternRepeatX, style->patternRepeatY); @@ -1358,7 +1391,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_fillStyle(QV4::SimpleCallContex r->context->state.fillPatternRepeatY = style->patternRepeatY; } } - } else if (value.isString()) { + } else if (value->isString()) { QColor color = qt_color_from_string(value); if (color.isValid() && r->context->state.fillStyle != QBrush(color)) { r->context->state.fillStyle = QBrush(color); @@ -1382,6 +1415,8 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_fillStyle(QV4::SimpleCallContex */ QV4::ReturnedValue QQuickJSContext2D::method_get_fillRule(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -1391,16 +1426,18 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_fillRule(QV4::SimpleCallContext QV4::ReturnedValue QQuickJSContext2D::method_set_fillRule(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT_SETTER(r) - QV4::Value value = ctx->argument(0); + QV4::ScopedValue value(scope, ctx->argument(0)); - if ((value.isString() && value.toQStringNoThrow() == QStringLiteral("WindingFill")) - || (value.isInt32() && value.integerValue() == Qt::WindingFill)) { + if ((value->isString() && value->toQString() == QStringLiteral("WindingFill")) + || (value->isInt32() && value->integerValue() == Qt::WindingFill)) { r->context->state.fillRule = Qt::WindingFill; - } else if ((value.isString() && value.toQStringNoThrow() == QStringLiteral("OddEvenFill")) - || (value.isInt32() && value.integerValue() == Qt::OddEvenFill)) { + } else if ((value->isString() && value->toQStringNoThrow() == QStringLiteral("OddEvenFill")) + || (value->isInt32() && value->integerValue() == Qt::OddEvenFill)) { r->context->state.fillRule = Qt::OddEvenFill; } else { //error @@ -1423,6 +1460,8 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_fillRule(QV4::SimpleCallContext */ QV4::ReturnedValue QQuickJSContext2D::method_get_strokeStyle(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -1443,20 +1482,22 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_strokeStyle(QV4::SimpleCallCont QV4::ReturnedValue QQuickJSContext2D::method_set_strokeStyle(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT_SETTER(r) QV8Engine *engine = ctx->engine->v8Engine; - QV4::Value value = ctx->argument(0); + QV4::ScopedValue value(scope, ctx->argument(0)); - if (value.asObject()) { + if (value->asObject()) { QColor color = engine->toVariant(value, qMetaTypeId()).value(); if (color.isValid()) { r->context->state.fillStyle = color; r->context->buffer()->setStrokeStyle(color); r->context->m_strokeStyle = value; } else { - QQuickContext2DStyle *style = value.as(); + QQuickContext2DStyle *style = value->as(); if (style && style->brush != r->context->state.strokeStyle) { r->context->state.strokeStyle = style->brush; r->context->buffer()->setStrokeStyle(style->brush, style->patternRepeatX, style->patternRepeatY); @@ -1466,7 +1507,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_strokeStyle(QV4::SimpleCallCont } } - } else if (value.isString()) { + } else if (value->isString()) { QColor color = qt_color_from_string(value); if (color.isValid() && r->context->state.strokeStyle != QBrush(color)) { r->context->state.strokeStyle = QBrush(color); @@ -1496,13 +1537,13 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_strokeStyle(QV4::SimpleCallCont QV4::ReturnedValue QQuickJSContext2DPrototype::method_createLinearGradient(QV4::SimpleCallContext *ctx) { - QV4::Scope scope(ctx); + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) QV8Engine *engine = ctx->engine->v8Engine; - QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); if (ctx->argumentCount == 4) { qreal x0 = ctx->arguments[0].toNumber(); @@ -1542,13 +1583,13 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createLinearGradient(QV4:: QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(QV4::SimpleCallContext *ctx) { - QV4::Scope scope(ctx); + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) QV8Engine *engine = ctx->engine->v8Engine; - QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); if (ctx->argumentCount == 6) { qreal x0 = ctx->arguments[0].toNumber(); @@ -1596,13 +1637,13 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(QV4:: QV4::ReturnedValue QQuickJSContext2DPrototype::method_createConicalGradient(QV4::SimpleCallContext *ctx) { - QV4::Scope scope(ctx); + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) QV8Engine *engine = ctx->engine->v8Engine; - QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); if (ctx->argumentCount == 6) { qreal x = ctx->arguments[0].toNumber(); @@ -1671,13 +1712,12 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createConicalGradient(QV4: */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(QV4::SimpleCallContext *ctx) { - QQuickJSContext2D *r = ctx->thisObject.as(); + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); + QV4::Scoped r(scope, ctx->thisObject); CHECK_CONTEXT(r) - QV8Engine *engine = ctx->engine->v8Engine; - QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); - QV4::Scope scope(v4); if (ctx->argumentCount == 2) { QQuickContext2DStyle *pattern = new (v4->memoryManager) QQuickContext2DStyle(v4); @@ -1743,6 +1783,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(QV4::SimpleC */ QV4::ReturnedValue QQuickJSContext2D::method_get_lineCap(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -1760,10 +1802,12 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_lineCap(QV4::SimpleCallContext QV4::ReturnedValue QQuickJSContext2D::method_set_lineCap(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT_SETTER(r) - QString lineCap = ctx->argument(0).toQStringNoThrow(); + QString lineCap = ctx->arguments[0].toQString(); Qt::PenCapStyle cap; if (lineCap == QStringLiteral("round")) cap = Qt::RoundCap; @@ -1797,6 +1841,8 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_lineCap(QV4::SimpleCallContext */ QV4::ReturnedValue QQuickJSContext2D::method_get_lineJoin(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -1814,10 +1860,15 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_lineJoin(QV4::SimpleCallContext QV4::ReturnedValue QQuickJSContext2D::method_set_lineJoin(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT_SETTER(r) - QString lineJoin = ctx->argument(0).toQStringNoThrow(); + if (!ctx->argumentCount) + ctx->throwTypeError(); + + QString lineJoin = ctx->arguments[0].toQString(); Qt::PenJoinStyle join; if (lineJoin == QStringLiteral("round")) join = Qt::RoundJoin; @@ -1841,6 +1892,8 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_lineJoin(QV4::SimpleCallContext */ QV4::ReturnedValue QQuickJSContext2D::method_get_lineWidth(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -1849,10 +1902,12 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_lineWidth(QV4::SimpleCallContex QV4::ReturnedValue QQuickJSContext2D::method_set_lineWidth(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT_SETTER(r) - qreal w = ctx->argument(0).toNumber(); + qreal w = ctx->argumentCount ? ctx->arguments[0].toNumber() : -1; if (w > 0 && qIsFinite(w) && w != r->context->state.lineWidth) { r->context->state.lineWidth = w; @@ -1868,6 +1923,8 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_lineWidth(QV4::SimpleCallContex */ QV4::ReturnedValue QQuickJSContext2D::method_get_miterLimit(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -1876,10 +1933,12 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_miterLimit(QV4::SimpleCallConte QV4::ReturnedValue QQuickJSContext2D::method_set_miterLimit(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT_SETTER(r) - qreal ml = ctx->argument(0).toNumber(); + qreal ml = ctx->argumentCount ? ctx->arguments[0].toNumber() : -1; if (ml > 0 && qIsFinite(ml) && ml != r->context->state.miterLimit) { r->context->state.miterLimit = ml; @@ -1895,6 +1954,8 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_miterLimit(QV4::SimpleCallConte */ QV4::ReturnedValue QQuickJSContext2D::method_get_shadowBlur(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -1903,10 +1964,12 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_shadowBlur(QV4::SimpleCallConte QV4::ReturnedValue QQuickJSContext2D::method_set_shadowBlur(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT_SETTER(r) - qreal blur = ctx->argument(0).toNumber(); + qreal blur = ctx->argumentCount ? ctx->arguments[0].toNumber() : -1; if (blur > 0 && qIsFinite(blur) && blur != r->context->state.shadowBlur) { r->context->state.shadowBlur = blur; @@ -1921,6 +1984,8 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_shadowBlur(QV4::SimpleCallConte */ QV4::ReturnedValue QQuickJSContext2D::method_get_shadowColor(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -1929,10 +1994,14 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_shadowColor(QV4::SimpleCallCont QV4::ReturnedValue QQuickJSContext2D::method_set_shadowColor(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT_SETTER(r) - QColor color = qt_color_from_string(ctx->argument(0)); + QColor color; + if (ctx->argumentCount) + color = qt_color_from_string(ctx->arguments[0]); if (color.isValid() && color != r->context->state.shadowColor) { r->context->state.shadowColor = color; @@ -1950,6 +2019,8 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_shadowColor(QV4::SimpleCallCont */ QV4::ReturnedValue QQuickJSContext2D::method_get_shadowOffsetX(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -1958,10 +2029,12 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_shadowOffsetX(QV4::SimpleCallCo QV4::ReturnedValue QQuickJSContext2D::method_set_shadowOffsetX(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT_SETTER(r) - qreal offsetX = ctx->argument(0).toNumber(); + qreal offsetX = ctx->argumentCount ? ctx->arguments[0].toNumber() : qSNaN(); if (qIsFinite(offsetX) && offsetX != r->context->state.shadowOffsetX) { r->context->state.shadowOffsetX = offsetX; r->context->buffer()->setShadowOffsetX(offsetX); @@ -1976,6 +2049,8 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_shadowOffsetX(QV4::SimpleCallCo */ QV4::ReturnedValue QQuickJSContext2D::method_get_shadowOffsetY(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -1984,10 +2059,12 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_shadowOffsetY(QV4::SimpleCallCo QV4::ReturnedValue QQuickJSContext2D::method_set_shadowOffsetY(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT_SETTER(r) - qreal offsetY = ctx->argument(0).toNumber(); + qreal offsetY = ctx->argumentCount ? ctx->arguments[0].toNumber() : qSNaN(); if (qIsFinite(offsetY) && offsetY != r->context->state.shadowOffsetY) { r->context->state.shadowOffsetY = offsetY; r->context->buffer()->setShadowOffsetY(offsetY); @@ -1997,6 +2074,8 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_shadowOffsetY(QV4::SimpleCallCo QV4::ReturnedValue QQuickJSContext2D::method_get_path(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -2005,16 +2084,18 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_path(QV4::SimpleCallContext *ct QV4::ReturnedValue QQuickJSContext2D::method_set_path(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT_SETTER(r) - QV4::Value value = ctx->argument(0); + QV4::ScopedValue value(scope, ctx->argument(0)); r->context->beginPath(); - if (QV4::QObjectWrapper *qobjectWrapper = value.as()) { + if (QV4::QObjectWrapper *qobjectWrapper =value->as()) { if (QQuickPath *path = qobject_cast(qobjectWrapper->object())) r->context->m_path = path->path(); } else { - QString path = value.toQStringNoThrow(); + QString path =value->toQStringNoThrow(); QQuickSvgParser::parsePathDataFast(path, r->context->m_path); } r->context->m_v4path = value; @@ -2028,6 +2109,8 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_path(QV4::SimpleCallContext *ct */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_clearRect(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -2048,6 +2131,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_clearRect(QV4::SimpleCallC */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_fillRect(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -2068,6 +2153,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_fillRect(QV4::SimpleCallCo */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_strokeRect(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -2100,7 +2187,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_strokeRect(QV4::SimpleCall */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_arc(QV4::SimpleCallContext *ctx) { - QV4::Scope scope(ctx); + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -2151,7 +2239,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_arc(QV4::SimpleCallContext */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_arcTo(QV4::SimpleCallContext *ctx) { - QV4::Scope scope(ctx); + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -2178,11 +2267,11 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_arcTo(QV4::SimpleCallConte */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_beginPath(QV4::SimpleCallContext *ctx) { - QV4::Scope scope(ctx); + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) - r->context->beginPath(); return ctx->thisObject.asReturnedValue(); @@ -2209,7 +2298,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_beginPath(QV4::SimpleCallC */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_bezierCurveTo(QV4::SimpleCallContext *ctx) { - QV4::Scope scope(ctx); + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -2257,7 +2347,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_bezierCurveTo(QV4::SimpleC */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_clip(QV4::SimpleCallContext *ctx) { - QV4::Scope scope(ctx); + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -2274,7 +2365,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_clip(QV4::SimpleCallContex */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_closePath(QV4::SimpleCallContext *ctx) { - QV4::Scope scope(ctx); + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -2295,7 +2387,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_closePath(QV4::SimpleCallC */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_fill(QV4::SimpleCallContext *ctx) { - QV4::Scope scope(ctx); + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r); r->context->fill(); @@ -2487,6 +2580,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_stroke(QV4::SimpleCallCont */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_isPointInPath(QV4::SimpleCallContext *ctx) { + QV4::ExecutionEngine *v4 = ctx->engine; + QV4::Scope scope(v4); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT(r) @@ -2555,8 +2650,8 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_font(QV4::SimpleCallContext *ct QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT_SETTER(r) - QString fs = ctx->argument(0).toQStringNoThrow(); - QFont font = qt_font_from_string(fs, r->context->state.font); + QV4::Scoped s(scope, ctx->argument(0), QV4::Scoped::Convert); + QFont font = qt_font_from_string(s->toQString(), r->context->state.font); if (font != r->context->state.font) { r->context->state.font = font; } @@ -2605,7 +2700,8 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_textAlign(QV4::SimpleCallContex QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT_SETTER(r) - QString textAlign = ctx->argument(0).toQStringNoThrow(); + QV4::Scoped s(scope, ctx->argument(0), QV4::Scoped::Convert); + QString textAlign = s->toQString(); QQuickContext2D::TextAlignType ta; if (textAlign == QStringLiteral("start")) @@ -2669,7 +2765,8 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_textBaseline(QV4::SimpleCallCon QV4::Scope scope(ctx); QQuickJSContext2D *r = ctx->thisObject.as(); CHECK_CONTEXT_SETTER(r) - QString textBaseline = ctx->argument(0).toQStringNoThrow(); + QV4::Scoped s(scope, ctx->argument(0), QV4::Scoped::Convert); + QString textBaseline = s->toQString(); QQuickContext2D::TextBaseLineType tb; if (textBaseline == QStringLiteral("alphabetic")) @@ -2767,9 +2864,9 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_measureText(QV4::SimpleCal if (ctx->argumentCount == 1) { QFontMetrics fm(r->context->state.font); uint width = fm.width(ctx->arguments[0].toQStringNoThrow()); - QV4::Object *tm = ctx->engine->newObject(); + QV4::Scoped tm(scope, ctx->engine->newObject()); tm->put(ctx->engine->newIdentifier(QStringLiteral("width")), QV4::Value::fromDouble(width)); - return QV4::Value::fromObject(tm).asReturnedValue(); + return tm.asReturnedValue(); } return QV4::Encode::undefined(); } @@ -2850,14 +2947,15 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::SimpleCallC QQmlRefPointer pixmap; - if (ctx->arguments[0].isString()) { - QUrl url(ctx->arguments[0].toQStringNoThrow()); + QV4::ScopedValue arg(scope, ctx->arguments[0]); + if (arg->isString()) { + QUrl url(arg->toQString()); if (!url.isValid()) V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch"); pixmap = r->context->createPixmap(url); - } else if (ctx->arguments[0].isObject()) { - if (QV4::QObjectWrapper *qobjectWrapper = ctx->arguments[0].as()) { + } else if (arg->isObject()) { + if (QV4::QObjectWrapper *qobjectWrapper = arg->as()) { if (QQuickImage *imageItem = qobject_cast(qobjectWrapper->object())) { pixmap.take(r->context->createPixmap(imageItem->source())); } else if (QQuickCanvasItem *canvas = qobject_cast(qobjectWrapper->object())) { @@ -2867,7 +2965,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::SimpleCallC } else { V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch"); } - } else if (QQuickJSContext2DImageData *imageData = ctx->arguments[0].as()) { + } else if (QQuickJSContext2DImageData *imageData = arg->as()) { QQuickJSContext2DPixelData *pix = imageData->pixelData.as(); if (pix && !pix->image.isNull()) { pixmap.take(new QQuickCanvasPixmap(pix->image, r->context->canvas()->window())); @@ -2875,7 +2973,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::SimpleCallC V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch"); } } else { - QUrl url(ctx->arguments[0].toQStringNoThrow()); + QUrl url(arg->toQStringNoThrow()); if (url.isValid()) pixmap = r->context->createPixmap(url); else @@ -3039,6 +3137,8 @@ QV4::ReturnedValue QQuickJSContext2DPixelData::proto_get_length(QV4::SimpleCallC QV4::ReturnedValue QQuickJSContext2DPixelData::getIndexed(QV4::Managed *m, uint index, bool *hasProperty) { + QV4::ExecutionEngine *v4 = m->engine(); + QV4::Scope scope(v4); QQuickJSContext2DPixelData *r = m->as(); if (!m) m->engine()->current->throwTypeError(); @@ -3069,6 +3169,8 @@ QV4::ReturnedValue QQuickJSContext2DPixelData::getIndexed(QV4::Managed *m, uint void QQuickJSContext2DPixelData::putIndexed(QV4::Managed *m, uint index, const QV4::Value &value) { + QV4::ExecutionEngine *v4 = m->engine(); + QV4::Scope scope(v4); QQuickJSContext2DPixelData *r = m->as(); if (!r) m->engine()->current->throwTypeError(); @@ -3127,15 +3229,16 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createImageData(QV4::Simpl QV8Engine *engine = ctx->engine->v8Engine; if (ctx->argumentCount == 1) { - if (QQuickJSContext2DImageData *imgData = ctx->arguments[0].as()) { + QV4::ScopedValue arg0(scope, ctx->arguments[0]); + if (QQuickJSContext2DImageData *imgData = arg0->as()) { QQuickJSContext2DPixelData *pa = imgData->pixelData.as(); if (pa) { qreal w = pa->image.width(); qreal h = pa->image.height(); return qt_create_image_data(w, h, engine, QImage()).asReturnedValue(); } - } else if (ctx->arguments[0].isString()) { - QImage image = r->context->createPixmap(QUrl(ctx->arguments[0].toQStringNoThrow()))->image(); + } else if (arg0->isString()) { + QImage image = r->context->createPixmap(QUrl(arg0->toQStringNoThrow()))->image(); return qt_create_image_data(image.width(), image.height(), engine, image).asReturnedValue(); } } else if (ctx->argumentCount == 2) { @@ -3195,7 +3298,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_putImageData(QV4::SimpleCa if (ctx->argumentCount != 3 && ctx->argumentCount != 7) return QV4::Encode::undefined(); - if (!ctx->arguments[0].isObject()) + QV4::ScopedValue arg0(scope, ctx->arguments[0]); + if (!arg0->isObject()) V4THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "Context2D::putImageData, the image data type mismatch"); qreal dx = ctx->arguments[1].toNumber(); @@ -3205,7 +3309,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_putImageData(QV4::SimpleCa if (!qIsFinite(dx) || !qIsFinite(dy)) V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "putImageData() : Invalid arguments"); - QQuickJSContext2DImageData *imageData = ctx->arguments[0].as(); + QQuickJSContext2DImageData *imageData = arg0->as(); if (!imageData) return ctx->thisObject.asReturnedValue(); @@ -4048,8 +4152,9 @@ QImage QQuickContext2D::toImage(const QRectF& bounds) QQuickContext2DEngineData::QQuickContext2DEngineData(QV8Engine *engine) { QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); + QV4::Scope scope(v4); - QV4::Object *proto = new (v4->memoryManager) QQuickJSContext2DPrototype(v4); + QV4::Scoped proto(scope, new (v4->memoryManager) QQuickJSContext2DPrototype(v4)); proto->defineAccessorProperty(v4, QStringLiteral("strokeStyle"), QQuickJSContext2D::method_get_strokeStyle, QQuickJSContext2D::method_set_strokeStyle); proto->defineAccessorProperty(v4, QStringLiteral("font"), QQuickJSContext2D::method_get_font, QQuickJSContext2D::method_set_font); proto->defineAccessorProperty(v4, QStringLiteral("fillRule"), QQuickJSContext2D::method_get_fillRule, QQuickJSContext2D::method_set_fillRule); @@ -4067,15 +4172,15 @@ QQuickContext2DEngineData::QQuickContext2DEngineData(QV8Engine *engine) proto->defineAccessorProperty(v4, QStringLiteral("lineWidth"), QQuickJSContext2D::method_get_lineWidth, QQuickJSContext2D::method_set_lineWidth); proto->defineAccessorProperty(v4, QStringLiteral("textAlign"), QQuickJSContext2D::method_get_textAlign, QQuickJSContext2D::method_set_textAlign); proto->defineAccessorProperty(v4, QStringLiteral("shadowBlur"), QQuickJSContext2D::method_get_shadowBlur, QQuickJSContext2D::method_set_shadowBlur); - contextPrototype = QV4::Value::fromObject(proto); + contextPrototype = proto; proto = v4->newObject(); proto->defineDefaultProperty(v4, QStringLiteral("addColorStop"), QQuickContext2DStyle::gradient_proto_addColorStop, 0); - gradientProto = QV4::Value::fromObject(proto); + gradientProto = proto; proto = v4->newObject(); proto->defineAccessorProperty(v4->id_length, QQuickJSContext2DPixelData::proto_get_length, 0); - pixelArrayProto = QV4::Value::fromObject(proto); + pixelArrayProto = proto; } QQuickContext2DEngineData::~QQuickContext2DEngineData() diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 98a87a4bcf..341339e7b9 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -3878,8 +3878,9 @@ void QQuickItem::mapFromItem(QQmlV4Function *args) const } QV4::ExecutionEngine *v4 = QV8Engine::getV4(args->engine()); - QV4::Object *rv = v4->newObject(); - args->setReturnValue(QV4::Value::fromObject(rv)); + QV4::Scope scope(v4); + QV4::Scoped rv(scope, v4->newObject()); + args->setReturnValue(rv.asValue()); qreal x = (args->length() > 1) ? (*args)[1].asDouble() : 0; qreal y = (args->length() > 2) ? (*args)[2].asDouble() : 0; @@ -3952,8 +3953,9 @@ void QQuickItem::mapToItem(QQmlV4Function *args) const } QV4::ExecutionEngine *v4 = QV8Engine::getV4(args->engine()); - QV4::Object *rv = v4->newObject(); - args->setReturnValue(QV4::Value::fromObject(rv)); + QV4::Scope scope(v4); + QV4::Scoped rv(scope, v4->newObject()); + args->setReturnValue(rv.asValue()); qreal x = (args->length() > 1) ? (*args)[1].asDouble() : 0; qreal y = (args->length() > 2) ? (*args)[2].asDouble() : 0; -- cgit v1.2.3