diff options
Diffstat (limited to 'src/imports/localstorage/plugin.cpp')
-rw-r--r-- | src/imports/localstorage/plugin.cpp | 464 |
1 files changed, 233 insertions, 231 deletions
diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp index 4877c4cfca..5bb8099b2e 100644 --- a/src/imports/localstorage/plugin.cpp +++ b/src/imports/localstorage/plugin.cpp @@ -54,34 +54,26 @@ #include <QtCore/qcryptographichash.h> #include <QtCore/qsettings.h> #include <QtCore/qdir.h> -#include <private/qv8sqlerrors_p.h> - - -#define V8THROW_SQL(error, desc) \ -{ \ - v8::Local<v8::Value> v = v8::Exception::Error(engine->toString(desc)); \ - v->ToObject()->Set(v8::String::New("code"), v8::Integer::New(error)); \ - v8::ThrowException(v); \ - return v8::Handle<v8::Value>(); \ -} - -#define V8THROW_SQL_VOID(error, desc) \ -{ \ - v8::Local<v8::Value> v = v8::Exception::Error(engine->toString(desc)); \ - v->ToObject()->Set(v8::String::New("code"), v8::Integer::New(error)); \ - v8::ThrowException(v); \ - return; \ +#include <private/qv4sqlerrors_p.h> +#include <private/qv4engine_p.h> +#include <private/qv4object_p.h> +#include <private/qv4functionobject_p.h> +#include <private/qv4objectproto_p.h> + +using namespace QV4; + +#define V4THROW_SQL(error, desc) { \ + Value v = Value::fromString(ctx, desc); \ + Object *ex = ctx->engine->newErrorObject(v); \ + ex->put(ctx->engine->newIdentifier(QStringLiteral("code")), Value::fromInt32(error)); \ + ctx->throwError(Value::fromObject(ex)); \ } -#define V8THROW_REFERENCE(string) { \ - v8::ThrowException(v8::Exception::ReferenceError(v8::String::New(string))); \ - return v8::Handle<v8::Value>(); \ +#define V4THROW_REFERENCE(string) { \ + Value v = Value::fromString(ctx, string); \ + ctx->throwReferenceError(v); \ } -#define V8THROW_REFERENCE_VOID(string) { \ - v8::ThrowException(v8::Exception::ReferenceError(v8::String::New(string))); \ - return; \ -} class QQmlSqlDatabaseData : public QV8Engine::Deletable { @@ -89,23 +81,32 @@ public: QQmlSqlDatabaseData(QV8Engine *engine); ~QQmlSqlDatabaseData(); - v8::Persistent<v8::Function> constructor; - v8::Persistent<v8::Function> queryConstructor; - v8::Persistent<v8::Function> rowsConstructor; + PersistentValue databaseProto; + PersistentValue queryProto; + PersistentValue rowsProto; }; V8_DEFINE_EXTENSION(QQmlSqlDatabaseData, databaseData) -class QV8SqlDatabaseResource : public QV8ObjectResource +class QQmlSqlDatabaseWrapper : public Object { - V8_RESOURCE_TYPE(SQLDatabaseType) + Q_MANAGED public: enum Type { Database, Query, Rows }; - QV8SqlDatabaseResource(QV8Engine *e) - : QV8ObjectResource(e), type(Database), inTransaction(false), readonly(false), forwardOnly(false) {} + QQmlSqlDatabaseWrapper(QV8Engine *e) + : Object(QV8Engine::getV4(e)), type(Database), inTransaction(false), readonly(false), forwardOnly(false) + { + vtbl = &static_vtbl; + prototype = QV8Engine::getV4(e)->objectPrototype; + } + + ~QQmlSqlDatabaseWrapper() { + } - ~QV8SqlDatabaseResource() { + static Value getIndexed(Managed *m, uint index, bool *hasProperty); + static void destroy(Managed *that) { + static_cast<QQmlSqlDatabaseWrapper *>(that)->~QQmlSqlDatabaseWrapper(); } Type type; @@ -116,62 +117,61 @@ public: bool inTransaction; // type == Query bool readonly; // type == Query - QSqlQuery query; // type == Rows + QSqlQuery sqlQuery; // type == Rows bool forwardOnly; // type == Rows }; -static v8::Handle<v8::Value> qmlsqldatabase_version(v8::Local<v8::String> /* property */, const v8::AccessorInfo& info) +DEFINE_MANAGED_VTABLE(QQmlSqlDatabaseWrapper); + +static Value qmlsqldatabase_version(SimpleCallContext *ctx) { - QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(info.This()); - if (!r || r->type != QV8SqlDatabaseResource::Database) - V8THROW_REFERENCE("Not a SQLDatabase object"); + QQmlSqlDatabaseWrapper *r = ctx->thisObject.as<QQmlSqlDatabaseWrapper>(); + if (!r || r->type != QQmlSqlDatabaseWrapper::Database) + V4THROW_REFERENCE("Not a SQLDatabase object"); - return r->engine->toString(r->version); + return Value::fromString(ctx->engine->newString(r->version)); } -static v8::Handle<v8::Value> qmlsqldatabase_rows_length(v8::Local<v8::String> /* property */, const v8::AccessorInfo& info) +static Value qmlsqldatabase_rows_length(SimpleCallContext *ctx) { - QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(info.This()); - if (!r || r->type != QV8SqlDatabaseResource::Rows) - V8THROW_REFERENCE("Not a SQLDatabase::Rows object"); + QQmlSqlDatabaseWrapper *r = ctx->thisObject.as<QQmlSqlDatabaseWrapper>(); + if (!r || r->type != QQmlSqlDatabaseWrapper::Rows) + V4THROW_REFERENCE("Not a SQLDatabase::Rows object"); - int s = r->query.size(); + int s = r->sqlQuery.size(); if (s < 0) { // Inefficient - if (r->query.last()) { - s = r->query.at() + 1; + if (r->sqlQuery.last()) { + s = r->sqlQuery.at() + 1; } else { s = 0; } } - return v8::Integer::New(s); + return Value::fromInt32(s); } -static v8::Handle<v8::Value> qmlsqldatabase_rows_forwardOnly(v8::Local<v8::String> /* property */, - const v8::AccessorInfo& info) +static Value qmlsqldatabase_rows_forwardOnly(SimpleCallContext *ctx) { - QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(info.This()); - if (!r || r->type != QV8SqlDatabaseResource::Rows) - V8THROW_REFERENCE("Not a SQLDatabase::Rows object"); - return v8::Boolean::New(r->query.isForwardOnly()); + QQmlSqlDatabaseWrapper *r = ctx->thisObject.as<QQmlSqlDatabaseWrapper>(); + if (!r || r->type != QQmlSqlDatabaseWrapper::Rows) + V4THROW_REFERENCE("Not a SQLDatabase::Rows object"); + return Value::fromBoolean(r->sqlQuery.isForwardOnly()); } -static void qmlsqldatabase_rows_setForwardOnly(v8::Local<v8::String> /* property */, - v8::Local<v8::Value> value, - const v8::AccessorInfo& info) +static Value qmlsqldatabase_rows_setForwardOnly(SimpleCallContext *ctx) { - QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(info.This()); - if (!r || r->type != QV8SqlDatabaseResource::Rows) - V8THROW_REFERENCE_VOID("Not a SQLDatabase::Rows object"); - - r->query.setForwardOnly(value->BooleanValue()); + QQmlSqlDatabaseWrapper *r = ctx->thisObject.as<QQmlSqlDatabaseWrapper>(); + if (!r || r->type != QQmlSqlDatabaseWrapper::Rows) + V4THROW_REFERENCE("Not a SQLDatabase::Rows object"); + if (ctx->argumentCount < 1) + ctx->throwTypeError(); + + r->sqlQuery.setForwardOnly(ctx->arguments[0].toBoolean()); + return Value::undefinedValue(); } QQmlSqlDatabaseData::~QQmlSqlDatabaseData() { - qPersistentDispose(constructor); - qPersistentDispose(queryConstructor); - qPersistentDispose(rowsConstructor); } static QString qmlsqldatabase_databasesPath(QV8Engine *engine) @@ -190,103 +190,113 @@ static QString qmlsqldatabase_databaseFile(const QString& connectionName, QV8Eng return qmlsqldatabase_databasesPath(engine) + QDir::separator() + connectionName; } -static v8::Handle<v8::Value> qmlsqldatabase_rows_index(QV8SqlDatabaseResource *r, uint32_t index) +static Value qmlsqldatabase_rows_index(QQmlSqlDatabaseWrapper *r, ExecutionEngine *v4, uint32_t index, bool *hasProperty = 0) { - if (r->query.at() == (int)index || r->query.seek(index)) { + QV8Engine *v8 = v4->v8Engine; - QSqlRecord record = r->query.record(); + if (r->sqlQuery.at() == (int)index || r->sqlQuery.seek(index)) { + QSqlRecord record = r->sqlQuery.record(); // XXX optimize - v8::Local<v8::Object> row = v8::Object::New(); + Object *row = v4->newObject(); for (int ii = 0; ii < record.count(); ++ii) { QVariant v = record.value(ii); if (v.isNull()) { - row->Set(r->engine->toString(record.fieldName(ii)), v8::Null()); + row->put(v4->newIdentifier(record.fieldName(ii)), Value::nullValue()); } else { - row->Set(r->engine->toString(record.fieldName(ii)), - r->engine->fromVariant(v)); + row->put(v4->newIdentifier(record.fieldName(ii)), v8->fromVariant(v)); } } - return row; + if (hasProperty) + *hasProperty = true; + return Value::fromObject(row); } else { - return v8::Undefined(); + if (hasProperty) + *hasProperty = false; + return Value::undefinedValue(); } } -static v8::Handle<v8::Value> qmlsqldatabase_rows_index(uint32_t index, const v8::AccessorInfo& info) +Value QQmlSqlDatabaseWrapper::getIndexed(Managed *m, uint index, bool *hasProperty) { - QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(info.This()); - if (!r || r->type != QV8SqlDatabaseResource::Rows) - V8THROW_REFERENCE("Not a SQLDatabase::Rows object"); + QQmlSqlDatabaseWrapper *r = m->as<QQmlSqlDatabaseWrapper>(); + if (!r || r->type != QQmlSqlDatabaseWrapper::Rows) + return Object::getIndexed(m, index, hasProperty); - return qmlsqldatabase_rows_index(r, index); + return qmlsqldatabase_rows_index(r, m->engine(), index, hasProperty); } -static v8::Handle<v8::Value> qmlsqldatabase_rows_item(const v8::Arguments& args) +static Value qmlsqldatabase_rows_item(SimpleCallContext *ctx) { - QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(args.This()); - if (!r || r->type != QV8SqlDatabaseResource::Rows) - V8THROW_REFERENCE("Not a SQLDatabase::Rows object"); + QQmlSqlDatabaseWrapper *r = ctx->thisObject.as<QQmlSqlDatabaseWrapper>(); + if (!r || r->type != QQmlSqlDatabaseWrapper::Rows) + V4THROW_REFERENCE("Not a SQLDatabase::Rows object"); - return qmlsqldatabase_rows_index(r, args.Length()?args[0]->Uint32Value():0); + return qmlsqldatabase_rows_index(r, ctx->engine, ctx->argumentCount ? ctx->arguments[0].toUInt32() : 0); } -static v8::Handle<v8::Value> qmlsqldatabase_executeSql(const v8::Arguments& args) +static Value qmlsqldatabase_executeSql(SimpleCallContext *ctx) { - QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(args.This()); - if (!r || r->type != QV8SqlDatabaseResource::Query) - V8THROW_REFERENCE("Not a SQLDatabase::Query object"); + QQmlSqlDatabaseWrapper *r = ctx->thisObject.as<QQmlSqlDatabaseWrapper>(); + if (!r || r->type != QQmlSqlDatabaseWrapper::Query) + V4THROW_REFERENCE("Not a SQLDatabase::Query object"); - QV8Engine *engine = r->engine; + QV8Engine *engine = ctx->engine->v8Engine; if (!r->inTransaction) - V8THROW_SQL(SQLEXCEPTION_DATABASE_ERR,QQmlEngine::tr("executeSql called outside transaction()")); + V4THROW_SQL(SQLEXCEPTION_DATABASE_ERR,QQmlEngine::tr("executeSql called outside transaction()")); QSqlDatabase db = r->database; - QString sql = engine->toString(args[0]); + QString sql = ctx->argument(0).toQString(); if (r->readonly && !sql.startsWith(QLatin1String("SELECT"),Qt::CaseInsensitive)) { - V8THROW_SQL(SQLEXCEPTION_SYNTAX_ERR, QQmlEngine::tr("Read-only Transaction")); + V4THROW_SQL(SQLEXCEPTION_SYNTAX_ERR, QQmlEngine::tr("Read-only Transaction")); } QSqlQuery query(db); bool err = false; - v8::Handle<v8::Value> result = v8::Undefined(); + Value result = Value::undefinedValue(); if (query.prepare(sql)) { - if (args.Length() > 1) { - v8::Local<v8::Value> values = args[1]; - if (values->IsArray()) { - v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(values); - uint32_t size = array->Length(); + if (ctx->argumentCount > 1) { + Value values = ctx->arguments[1]; + if (ArrayObject *array = values.asArrayObject()) { + uint32_t size = array->arrayLength(); for (uint32_t ii = 0; ii < size; ++ii) - query.bindValue(ii, engine->toVariant(array->Get(ii), -1)); - } else if (values->IsObject() && !values->ToObject()->GetExternalResource()) { - v8::Local<v8::Object> object = values->ToObject(); - v8::Local<v8::Array> names = object->GetPropertyNames(); - uint32_t size = names->Length(); - for (uint32_t ii = 0; ii < size; ++ii) - query.bindValue(engine->toString(names->Get(ii)), - engine->toVariant(object->Get(names->Get(ii)), -1)); + query.bindValue(ii, engine->toVariant(array->getIndexed(ii), -1)); + } else if (Object *object = values.asObject()) { + ObjectIterator it(object, ObjectIterator::WithProtoChain|ObjectIterator::EnumerableOnly); + while (1) { + Value value; + Value key = it.nextPropertyName(&value); + if (key.isNull()) + break; + QVariant v = engine->toVariant(value, -1); + if (key.isString()) { + query.bindValue(key.stringValue()->toQString(), v); + } else { + assert(key.isInteger()); + query.bindValue(key.integerValue(), v); + } + } } else { query.bindValue(0, engine->toVariant(values, -1)); } } if (query.exec()) { - v8::Handle<v8::Object> rows = databaseData(engine)->rowsConstructor->NewInstance(); - QV8SqlDatabaseResource *r = new QV8SqlDatabaseResource(engine); - r->type = QV8SqlDatabaseResource::Rows; - r->database = db; - r->query = query; - rows->SetExternalResource(r); - - v8::Local<v8::Object> resultObject = v8::Object::New(); - result = resultObject; + QQmlSqlDatabaseWrapper *rows = new (ctx->engine->memoryManager) QQmlSqlDatabaseWrapper(engine); + rows->prototype = databaseData(engine)->rowsProto.value().asObject(); + rows->type = QQmlSqlDatabaseWrapper::Rows; + rows->database = db; + rows->sqlQuery = query; + + Object *resultObject = ctx->engine->newObject(); + result = Value::fromObject(resultObject); // XXX optimize - resultObject->Set(v8::String::New("rowsAffected"), v8::Integer::New(query.numRowsAffected())); - resultObject->Set(v8::String::New("insertId"), engine->toString(query.lastInsertId().toString())); - resultObject->Set(v8::String::New("rows"), rows); + resultObject->put(ctx->engine->newIdentifier("rowsAffected"), Value::fromInt32(query.numRowsAffected())); + resultObject->put(ctx->engine->newIdentifier("insertId"), engine->toString(query.lastInsertId().toString())); + resultObject->put(ctx->engine->newIdentifier("rows"), Value::fromObject(rows)); } else { err = true; } @@ -294,153 +304,152 @@ static v8::Handle<v8::Value> qmlsqldatabase_executeSql(const v8::Arguments& args err = true; } if (err) - V8THROW_SQL(SQLEXCEPTION_DATABASE_ERR,query.lastError().text()); + V4THROW_SQL(SQLEXCEPTION_DATABASE_ERR,query.lastError().text()); return result; } -static v8::Handle<v8::Value> qmlsqldatabase_changeVersion(const v8::Arguments& args) +static Value qmlsqldatabase_changeVersion(SimpleCallContext *ctx) { - if (args.Length() < 2) - return v8::Undefined(); + if (ctx->argumentCount < 2) + return Value::undefinedValue(); - QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(args.This()); - if (!r || r->type != QV8SqlDatabaseResource::Database) - V8THROW_REFERENCE("Not a SQLDatabase object"); + QQmlSqlDatabaseWrapper *r = ctx->thisObject.as<QQmlSqlDatabaseWrapper>(); + if (!r || r->type != QQmlSqlDatabaseWrapper::Database) + V4THROW_REFERENCE("Not a SQLDatabase object"); - QV8Engine *engine = r->engine; + QV8Engine *engine = ctx->engine->v8Engine; QSqlDatabase db = r->database; - QString from_version = engine->toString(args[0]); - QString to_version = engine->toString(args[1]); - v8::Handle<v8::Value> callback = args[2]; + QString from_version = ctx->arguments[0].toQString(); + QString to_version = ctx->arguments[1].toQString(); + Value callback = ctx->argument(2); if (from_version != r->version) - V8THROW_SQL(SQLEXCEPTION_VERSION_ERR, QQmlEngine::tr("Version mismatch: expected %1, found %2").arg(from_version).arg(r->version)); + V4THROW_SQL(SQLEXCEPTION_VERSION_ERR, QQmlEngine::tr("Version mismatch: expected %1, found %2").arg(from_version).arg(r->version)); - v8::Local<v8::Object> instance = databaseData(engine)->queryConstructor->NewInstance(); - QV8SqlDatabaseResource *r2 = new QV8SqlDatabaseResource(engine); - r2->type = QV8SqlDatabaseResource::Query; - r2->database = db; - r2->version = r->version; - r2->inTransaction = true; - instance->SetExternalResource(r2); + QQmlSqlDatabaseWrapper *w = new (ctx->engine->memoryManager) QQmlSqlDatabaseWrapper(engine); + w->prototype = databaseData(engine)->queryProto.value().asObject(); + w->type = QQmlSqlDatabaseWrapper::Query; + w->database = db; + w->version = r->version; + w->inTransaction = true; bool ok = true; - if (callback->IsFunction()) { + if (FunctionObject *f = callback.asFunctionObject()) { ok = false; db.transaction(); - v8::TryCatch tc; - v8::Handle<v8::Value> callbackArgs[] = { instance }; - v8::Handle<v8::Function>::Cast(callback)->Call(engine->global(), 1, callbackArgs); - - if (tc.HasCaught()) { + Value callbackArgs[] = { Value::fromObject(w) }; + try { + f->call(engine->global(), callbackArgs, 1); + } catch (Exception &) { db.rollback(); - tc.ReThrow(); - return v8::Handle<v8::Value>(); - } else if (!db.commit()) { + throw; + } + if (!db.commit()) { db.rollback(); - V8THROW_SQL(SQLEXCEPTION_UNKNOWN_ERR,QQmlEngine::tr("SQL transaction failed")); + V4THROW_SQL(SQLEXCEPTION_UNKNOWN_ERR,QQmlEngine::tr("SQL transaction failed")); } else { ok = true; } } - r2->inTransaction = false; + w->inTransaction = false; if (ok) { - r2->version = to_version; + w->version = to_version; #ifndef QT_NO_SETTINGS QSettings ini(qmlsqldatabase_databaseFile(db.connectionName(),engine) + QLatin1String(".ini"), QSettings::IniFormat); ini.setValue(QLatin1String("Version"), to_version); #endif } - return v8::Undefined(); + return Value::undefinedValue(); } -static v8::Handle<v8::Value> qmlsqldatabase_transaction_shared(const v8::Arguments& args, bool readOnly) +static Value qmlsqldatabase_transaction_shared(SimpleCallContext *ctx, bool readOnly) { - QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(args.This()); - if (!r || r->type != QV8SqlDatabaseResource::Database) - V8THROW_REFERENCE("Not a SQLDatabase object"); + QQmlSqlDatabaseWrapper *r = ctx->thisObject.as<QQmlSqlDatabaseWrapper>(); + if (!r || r->type != QQmlSqlDatabaseWrapper::Database) + V4THROW_REFERENCE("Not a SQLDatabase object"); - QV8Engine *engine = r->engine; + QV8Engine *engine = ctx->engine->v8Engine; - if (args.Length() == 0 || !args[0]->IsFunction()) - V8THROW_SQL(SQLEXCEPTION_UNKNOWN_ERR,QQmlEngine::tr("transaction: missing callback")); + FunctionObject *callback = ctx->argumentCount ? ctx->arguments[0].asFunctionObject() : 0; + if (!callback) + V4THROW_SQL(SQLEXCEPTION_UNKNOWN_ERR, QQmlEngine::tr("transaction: missing callback")); QSqlDatabase db = r->database; - v8::Handle<v8::Function> callback = v8::Handle<v8::Function>::Cast(args[0]); - v8::Local<v8::Object> instance = databaseData(engine)->queryConstructor->NewInstance(); - QV8SqlDatabaseResource *q = new QV8SqlDatabaseResource(engine); - q->type = QV8SqlDatabaseResource::Query; - q->database = db; - q->readonly = readOnly; - q->inTransaction = true; - instance->SetExternalResource(q); + QQmlSqlDatabaseWrapper *w = new (ctx->engine->memoryManager) QQmlSqlDatabaseWrapper(engine); + w->prototype = databaseData(engine)->queryProto.value().asObject(); + w->type = QQmlSqlDatabaseWrapper::Query; + w->database = db; + w->version = r->version; + w->readonly = readOnly; + w->inTransaction = true; db.transaction(); - v8::TryCatch tc; - v8::Handle<v8::Value> callbackArgs[] = { instance }; - callback->Call(engine->global(), 1, callbackArgs); - - q->inTransaction = false; - - if (tc.HasCaught()) { - db.rollback(); - tc.ReThrow(); - return v8::Handle<v8::Value>(); - } else if (!db.commit()) { - db.rollback(); + if (callback) { + Value callbackArgs[] = { Value::fromObject(w) }; + try { + callback->call(engine->global(), callbackArgs, 1); + } catch (Exception &) { + w->inTransaction = false; + db.rollback(); + throw; + } + + w->inTransaction = false; + + if (!db.commit()) + db.rollback(); } - return v8::Undefined(); + return Value::undefinedValue(); } -static v8::Handle<v8::Value> qmlsqldatabase_transaction(const v8::Arguments& args) +static Value qmlsqldatabase_transaction(SimpleCallContext *ctx) { - return qmlsqldatabase_transaction_shared(args, false); + return qmlsqldatabase_transaction_shared(ctx, false); } -static v8::Handle<v8::Value> qmlsqldatabase_read_transaction(const v8::Arguments& args) +static Value qmlsqldatabase_read_transaction(SimpleCallContext *ctx) { - return qmlsqldatabase_transaction_shared(args, true); + return qmlsqldatabase_transaction_shared(ctx, true); } QQmlSqlDatabaseData::QQmlSqlDatabaseData(QV8Engine *engine) { + ExecutionEngine *v4 = QV8Engine::getV4(engine); { - v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); - ft->InstanceTemplate()->SetHasExternalResource(true); - ft->PrototypeTemplate()->Set(v8::String::New("transaction"), - V8FUNCTION(qmlsqldatabase_transaction, engine)); - ft->PrototypeTemplate()->Set(v8::String::New("readTransaction"), - V8FUNCTION(qmlsqldatabase_read_transaction, engine)); - ft->PrototypeTemplate()->SetAccessor(v8::String::New("version"), qmlsqldatabase_version); - ft->PrototypeTemplate()->Set(v8::String::New("changeVersion"), - V8FUNCTION(qmlsqldatabase_changeVersion, engine)); - constructor = qPersistentNew<v8::Function>(ft->GetFunction()); + Object *proto = 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); } { - v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); - ft->InstanceTemplate()->SetHasExternalResource(true); - ft->PrototypeTemplate()->Set(v8::String::New("executeSql"), - V8FUNCTION(qmlsqldatabase_executeSql, engine)); - queryConstructor = qPersistentNew<v8::Function>(ft->GetFunction()); + Object *proto = v4->newObject(); + proto->defineDefaultProperty(v4, QStringLiteral("executeSql"), qmlsqldatabase_executeSql); + queryProto = Value::fromObject(proto); } { - v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); - ft->InstanceTemplate()->SetHasExternalResource(true); - ft->PrototypeTemplate()->Set(v8::String::New("item"), V8FUNCTION(qmlsqldatabase_rows_item, engine)); - ft->PrototypeTemplate()->SetAccessor(v8::String::New("length"), qmlsqldatabase_rows_length); - ft->InstanceTemplate()->SetAccessor(v8::String::New("forwardOnly"), qmlsqldatabase_rows_forwardOnly, - qmlsqldatabase_rows_setForwardOnly); - ft->InstanceTemplate()->SetIndexedPropertyHandler(qmlsqldatabase_rows_index); - rowsConstructor = qPersistentNew<v8::Function>(ft->GetFunction()); + Object *proto = v4->newObject(); + proto->defineDefaultProperty(v4, QStringLiteral("item"), qmlsqldatabase_rows_item); + Property *p = proto->insertMember(v4->newString(QStringLiteral("length")), + Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable); + p->setGetter(v4->newBuiltinFunction(v4->rootContext, v4->newString(QStringLiteral("length")), qmlsqldatabase_rows_length)); + p = proto->insertMember(v4->newString(QStringLiteral("forwardOnly")), + 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); } } @@ -597,25 +606,26 @@ public: ~QQuickLocalStorage() { } - Q_INVOKABLE void openDatabaseSync(QQmlV8Function* args); + Q_INVOKABLE void openDatabaseSync(QQmlV4Function* args); }; -void QQuickLocalStorage::openDatabaseSync(QQmlV8Function *args) +void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args) { #ifndef QT_NO_SETTINGS QV8Engine *engine = args->engine(); + ExecutionContext *ctx = QV8Engine::getV4(engine)->current; if (engine->engine()->offlineStoragePath().isEmpty()) - V8THROW_SQL_VOID(SQLEXCEPTION_DATABASE_ERR, QQmlEngine::tr("SQL: can't create database, offline storage is disabled.")); + V4THROW_SQL(SQLEXCEPTION_DATABASE_ERR, QQmlEngine::tr("SQL: can't create database, offline storage is disabled.")); qmlsqldatabase_initDatabasesPath(engine); QSqlDatabase database; - QString dbname = engine->toString((*args)[0]); - QString dbversion = engine->toString((*args)[1]); - QString dbdescription = engine->toString((*args)[2]); - int dbestimatedsize = (*args)[3]->Int32Value(); - v8::Handle<v8::Value> dbcreationCallback = (*args)[4]; + QString dbname = (*args)[0].toQString(); + QString dbversion = (*args)[1].toQString(); + QString dbdescription = (*args)[2].toQString(); + int dbestimatedsize = (*args)[3].toInt32(); + FunctionObject *dbcreationCallback = (*args)[4].asFunctionObject(); QCryptographicHash md5(QCryptographicHash::Md5); md5.addData(dbname.toUtf8()); @@ -632,13 +642,13 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV8Function *args) database = QSqlDatabase::database(dbid); version = ini.value(QLatin1String("Version")).toString(); if (version != dbversion && !dbversion.isEmpty() && !version.isEmpty()) - V8THROW_SQL_VOID(SQLEXCEPTION_VERSION_ERR, QQmlEngine::tr("SQL: database version mismatch")); + V4THROW_SQL(SQLEXCEPTION_VERSION_ERR, QQmlEngine::tr("SQL: database version mismatch")); } else { created = !QFile::exists(basename+QLatin1String(".sqlite")); database = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), dbid); if (created) { ini.setValue(QLatin1String("Name"), dbname); - if (dbcreationCallback->IsFunction()) + if (dbcreationCallback) version = QString(); ini.setValue(QLatin1String("Version"), version); ini.setValue(QLatin1String("Description"), dbdescription); @@ -647,7 +657,7 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV8Function *args) } else { if (!dbversion.isEmpty() && ini.value(QLatin1String("Version")) != dbversion) { // Incompatible - V8THROW_SQL_VOID(SQLEXCEPTION_VERSION_ERR,QQmlEngine::tr("SQL: database version mismatch")); + V4THROW_SQL(SQLEXCEPTION_VERSION_ERR,QQmlEngine::tr("SQL: database version mismatch")); } version = ini.value(QLatin1String("Version")).toString(); } @@ -657,25 +667,17 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV8Function *args) database.open(); } - v8::Local<v8::Object> instance = databaseData(engine)->constructor->NewInstance(); - - QV8SqlDatabaseResource *r = new QV8SqlDatabaseResource(engine); - r->database = database; - r->version = version; - instance->SetExternalResource(r); - - if (created && dbcreationCallback->IsFunction()) { - v8::TryCatch tc; - v8::Handle<v8::Function> callback = v8::Handle<v8::Function>::Cast(dbcreationCallback); - v8::Handle<v8::Value> args[] = { instance }; - callback->Call(engine->global(), 1, args); - if (tc.HasCaught()) { - tc.ReThrow(); - return; - } + QQmlSqlDatabaseWrapper *db = new (ctx->engine->memoryManager) QQmlSqlDatabaseWrapper(engine); + db->prototype = databaseData(engine)->databaseProto.value().asObject(); + db->database = database; + db->version = version; + + if (created && dbcreationCallback) { + Value args[] = { Value::fromObject(db) }; + dbcreationCallback->call(engine->global(), args, 1); } - args->returnValue(instance); + args->setReturnValue(Value::fromObject(db)); #endif // QT_NO_SETTINGS } |