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 <simon.hausmann@digia.com>
This commit is contained in:
Lars Knoll 2013-09-16 22:02:27 +02:00 committed by The Qt Project
parent a0f8be4021
commit e441692b0b
45 changed files with 1000 additions and 600 deletions

View File

@ -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<Object> 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<QQmlSqlDatabaseWrapper>();
Scoped<QQmlSqlDatabaseWrapper> 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<Object> 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<QQmlSqlDatabaseWrapper>();
Scoped<QQmlSqlDatabaseWrapper> 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<FunctionObject> 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<Object> 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<Object> proto(scope, v4->newObject());
proto->defineDefaultProperty(v4, QStringLiteral("executeSql"), qmlsqldatabase_executeSql);
queryProto = Value::fromObject(proto);
queryProto = proto;
}
{
Object *proto = v4->newObject();
Scoped<Object> 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;
}
}

View File

@ -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<Object> 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());
}
/*!

View File

@ -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<QV4ParticleData>(); \
QV4::Scope scope(ctx); \
QV4::Scoped<QV4ParticleData> 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<QV4ParticleData>(); \
QV4::Scope scope(ctx); \
QV4::Scoped<QV4ParticleData> 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<QV4ParticleData>(); \
QV4::Scope scope(ctx); \
QV4::Scoped<QV4ParticleData> 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<QV4ParticleData>(); \
QV4::Scope scope(ctx); \
QV4::Scoped<QV4ParticleData> 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<QV4ParticleData>(); \
QV4::Scope scope(ctx); \
QV4::Scoped<QV4ParticleData> 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<QV4ParticleData>(); \
QV4::Scope scope(ctx); \
QV4::Scoped<QV4ParticleData> 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<QV4ParticleData>(); \
QV4::Scope scope(ctx); \
QV4::Scoped<QV4ParticleData> 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<QV4ParticleData>(); \
QV4::Scope scope(ctx); \
QV4::Scoped<QV4ParticleData> 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<QV4::Object> 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()

View File

@ -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());
}
/*!

View File

@ -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);

View File

@ -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<Object> 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<ArrayObject> 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<Object> 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<ArrayObject> 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<Object> instance(scope, ctx->thisObject.toObject(ctx));
uint len = getLength(ctx, instance);
uint len = getLength(ctx, instance.getPointer());
FunctionObject *callback = ctx->argument(0).asFunctionObject();
Scoped<FunctionObject> 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<Object> instance(scope, ctx->thisObject.toObject(ctx));
uint len = getLength(ctx, instance);
uint len = getLength(ctx, instance.getPointer());
FunctionObject *callback = ctx->argument(0).asFunctionObject();
Scoped<FunctionObject> 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<Object> instance(scope, ctx->thisObject.toObject(ctx));
uint len = getLength(ctx, instance);
uint len = getLength(ctx, instance.getPointer());
FunctionObject *callback = ctx->argument(0).asFunctionObject();
Scoped<FunctionObject> 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<Object> instance(scope, ctx->thisObject.toObject(ctx));
uint len = getLength(ctx, instance);
uint len = getLength(ctx, instance.getPointer());
FunctionObject *callback = ctx->argument(0).asFunctionObject();
Scoped<FunctionObject> callback(scope, ctx->argument(0));
if (!callback)
ctx->throwTypeError();
Value thisArg = ctx->argument(1);
Scoped<ArrayObject> 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<Object> instance(scope, ctx->thisObject.toObject(ctx));
uint len = getLength(ctx, instance);
uint len = getLength(ctx, instance.getPointer());
FunctionObject *callback = ctx->argument(0).asFunctionObject();
Scoped<FunctionObject> callback(scope, ctx->argument(0));
if (!callback)
ctx->throwTypeError();
Value thisArg = ctx->argument(1);
Scoped<ArrayObject> 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<Object> instance(scope, ctx->thisObject.toObject(ctx));
uint len = getLength(ctx, instance);
uint len = getLength(ctx, instance.getPointer());
FunctionObject *callback = ctx->argument(0).asFunctionObject();
Scoped<FunctionObject> 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<Object> instance(scope, ctx->thisObject.toObject(ctx));
uint len = getLength(ctx, instance);
uint len = getLength(ctx, instance.getPointer());
FunctionObject *callback = ctx->argument(0).asFunctionObject();
Scoped<FunctionObject> 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;

View File

@ -64,7 +64,7 @@ CallContext *ExecutionContext::newCallContext(void *stackSpace, FunctionObject *
c->function = function;
// ###
c->arguments = const_cast<Value *>(callData->args);
c->arguments = const_cast<SafeValue *>(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<SafeValue *>(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<CallContext *>(ctx);
if (!c->activation)
c->activation = engine->newObject();
c->activation = engine->newObject()->getPointer();
activation = c->activation;
break;
}

View File

@ -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<CallContext *>(this);
if (index < ctx->argumentCount)
return ctx->arguments[index];
}
return Value::undefinedValue();
}
inline CallContext *ExecutionContext::asCallContext()
{
return type >= Type_CallContext ? static_cast<CallContext *>(this) : 0;

View File

@ -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<DateObject> 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<DateObject> 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();

View File

@ -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<Value> &boundArgs)
Returned<BoundFunction> *ExecutionEngine::newBoundFunction(ExecutionContext *scope, FunctionObject *target, Value boundThis, const QVector<Value> &boundArgs)
{
assert(target);
BoundFunction *f = new (memoryManager) BoundFunction(scope, target, boundThis, boundArgs);
return f;
return f->asReturned<BoundFunction>();
}
Object *ExecutionEngine::newObject()
Returned<Object> *ExecutionEngine::newObject()
{
Object *object = new (memoryManager) Object(this);
return object;
return object->asReturned<Object>();
}
Object *ExecutionEngine::newObject(InternalClass *internalClass)
Returned<Object> *ExecutionEngine::newObject(InternalClass *internalClass)
{
Object *object = new (memoryManager) Object(internalClass);
return object;
return object->asReturned<Object>();
}
String *ExecutionEngine::newString(const QString &s)

View File

@ -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<Value> &boundArgs);
Returned<BoundFunction> *newBoundFunction(ExecutionContext *scope, FunctionObject *target, Value boundThis, const QVector<Value> &boundArgs);
Object *newObject();
Object *newObject(InternalClass *internalClass);
Returned<Object> *newObject();
Returned<Object> *newObject(InternalClass *internalClass);
String *newString(const QString &s);
String *newIdentifier(const QString &text);

View File

@ -77,6 +77,11 @@ struct ErrorObject: Object {
static void destroy(Managed *that) { static_cast<ErrorObject *>(that)->~ErrorObject(); }
};
template<>
inline ErrorObject *value_cast(const Value &v) {
return v.asErrorObject();
}
struct EvalErrorObject: ErrorObject {
EvalErrorObject(ExecutionEngine *engine, const Value &message);
};

View File

@ -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<Object> 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<FunctionObject *>(that);
ExecutionEngine *v4 = f->engine();
ExecutionEngine *v4 = that->engine();
Scope scope(v4);
Scoped<FunctionObject> f(scope, that, Scoped<FunctionObject>::Cast);
InternalClass *ic = v4->objectClass;
Scoped<Object> 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<Object> 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<Object> 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<FunctionObject> target(scope, ctx->thisObject);
if (!target)
ctx->throwTypeError();
Value boundThis = ctx->argument(0);
ScopedValue boundThis(scope, ctx->argument(0));
QVector<Value> 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<ScriptFunction *>(that);
ExecutionEngine *v4 = f->engine();
ExecutionEngine *v4 = that->engine();
Scope scope(v4);
Scoped<ScriptFunction> f(scope, static_cast<ScriptFunction *>(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<Object> 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<SimpleScriptFunction *>(that);
ExecutionEngine *v4 = f->engine();
ExecutionEngine *v4 = that->engine();
Scope scope(v4);
Scoped<SimpleScriptFunction> f(scope, static_cast<SimpleScriptFunction *>(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<Object> proto(scope, f->memberData[Index_Prototype].value);
if (!!proto)
ic = v4->emptyClass->changePrototype(proto.getPointer());
Scoped<Object> 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<Object> 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<Value *>(callData->args);
ctx.arguments = const_cast<SafeValue *>(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<Value *>(callData->args);
ctx.arguments = const_cast<SafeValue *>(callData->args);
ctx.argumentCount = callData->argc;
v4->pushContext(&ctx);

View File

@ -142,6 +142,11 @@ protected:
{ static_cast<FunctionObject*>(that)->~FunctionObject(); }
};
template<>
inline FunctionObject *value_cast(const Value &v) {
return v.asFunctionObject();
}
struct FunctionCtor: FunctionObject
{
Q_MANAGED

View File

@ -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<typename T> struct Scoped;
template<typename T> struct Returned;
struct CallData;
struct ScopedValue;
struct ValueRef;
namespace Global {
enum {

View File

@ -444,7 +444,7 @@ ReturnedValue EvalFunction::call(Managed *that, CallData *callData)
{
// indirect call
// ### const_cast
return static_cast<EvalFunction *>(that)->evalCall(callData->thisObject, const_cast<Value *>(callData->args), callData->argc, false);
return static_cast<EvalFunction *>(that)->evalCall(callData->thisObject, const_cast<Value *>(static_cast<const Value *>(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<String> inputString(scope, ctx->argument(0), Scoped<String>::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();
}

View File

@ -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);

View File

@ -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<QV4::Object> 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)

View File

@ -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<Object> 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<Object> 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<Object> o(scope, Value::fromObject(engine->newObject()));
Scoped<Object> 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();

View File

@ -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<const T *>(this) : 0;
}
template<typename T>
static T *cast(const Value &v) {
return v.as<T>();
}
static Managed *cast(const Value &v) {
return v.asManaged();
}
String *asString() { return type == Type_String ? reinterpret_cast<String *>(this) : 0; }
Object *asObject() { return type != Type_String ? reinterpret_cast<Object *>(this) : 0; }
ArrayObject *asArrayObject() { return type == Type_ArrayObject ? reinterpret_cast<ArrayObject *>(this) : 0; }
FunctionObject *asFunctionObject() { return type == Type_FunctionObject ? reinterpret_cast<FunctionObject *>(this) : 0; }
BooleanObject *asBooleanObject() { return type == Type_BooleanObject ? reinterpret_cast<BooleanObject *>(this) : 0; }
@ -353,6 +332,34 @@ private:
friend struct ObjectIterator;
};
template<>
inline Managed *value_cast(const Value &v) {
return v.asManaged();
}
template<typename T>
inline T *managed_cast(Managed *m)
{
return m->as<T>();
}
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);
}

View File

@ -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;

View File

@ -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));

View File

@ -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<Object>(ExecutionContext *ctx, const Value &v)
{
return v.toObject(ctx)->asReturnedValue();
}
}
QT_END_NAMESPACE

View File

@ -85,11 +85,11 @@ ReturnedValue ObjectCtor::construct(Managed *that, CallData *callData)
Scope scope(v4);
ObjectCtor *ctor = static_cast<ObjectCtor *>(that);
if (!callData->argc || callData->args[0].isUndefined() || callData->args[0].isNull()) {
Object *obj = v4->newObject();
Scoped<Object> obj(scope, v4->newObject());
Scoped<Object> 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<Object> o(scope, ctx->argument(0));
if (!o)
ctx->throwTypeError();
Object *p = o.objectValue()->prototype();
return p ? Value::fromObject(p).asReturnedValue() : Encode::null();
Scoped<Object> 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<Object> O(scope, ctx->argument(0));
if (!O)
ctx->throwTypeError();
String *name = ctx->argument(1).toString(ctx);
ScopedValue v(scope, ctx->argument(1));
Scoped<String> 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<Object> 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<Object> O(scope, ctx->argument(0));
if (!O)
ctx->throwTypeError();
String *name = ctx->argument(1).toString(ctx);
Scoped<String> name(scope, ctx->argument(1), Scoped<String>::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<Object> O(scope, ctx->argument(0));
if (!O)
ctx->throwTypeError();
Object *o = ctx->argument(1).toObject(ctx);
Scoped<Object> o(scope, ctx->argument(1), Scoped<Object>::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<Object> 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<Object> 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<Object> 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<Object> 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<Object> 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<Object> 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<Object> o(scope, ctx->argument(0));
if (!o)
ctx->throwTypeError();
Scoped<ArrayObject> 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<String> P(scope, ctx->argument(0), Scoped<String>::Convert);
Scoped<Object> O(scope, ctx->thisObject, Scoped<Object>::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<Object> V(scope, ctx->argument(0));
if (!V)
return Encode(false);
Object *O = ctx->thisObject.toObject(ctx);
Object *proto = V.objectValue()->prototype();
Scoped<Object> O(scope, ctx->thisObject, Scoped<Object>::Convert);
Scoped<Object> 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<String> p(scope, ctx->argument(0), Scoped<String>::Convert);
Object *o = ctx->thisObject.toObject(ctx);
Scoped<Object> o(scope, ctx->thisObject, Scoped<Object>::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<String> prop(scope, ctx->argument(0), Scoped<String>::Convert);
Scoped<FunctionObject> f(scope, ctx->argument(1));
if (!f)
ctx->throwTypeError();
Object *o = ctx->thisObject.asObject();
Scoped<Object> 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<String> prop(scope, ctx->argument(0), Scoped<String>::Convert);
Scoped<FunctionObject> f(scope, ctx->argument(1));
if (!f)
ctx->throwTypeError();
Object *o = ctx->thisObject.asObject();
Scoped<Object> 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<Object> 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<Object> 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<Object> 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();
}

View File

@ -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<Object> 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)

View File

@ -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<typename T>
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<T>(v));
#ifndef QT_NO_DEBUG
++scope.size;
#endif
}
Scoped(const Scope &scope, const ScopedValue &v)
{
ptr = scope.engine->jsStackTop++;
setPointer(value_cast<T>(*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<T>(scope.engine->current, v);
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@ -225,6 +219,16 @@ struct Scoped
++scope.size;
#endif
}
template<typename X>
Scoped(const Scope &scope, X *t, _Cast)
{
ptr = scope.engine->jsStackTop++;
setPointer(managed_cast<T>(t));
#ifndef QT_NO_DEBUG
++scope.size;
#endif
}
template<typename X>
Scoped(const Scope &scope, Returned<X> *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<T>(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<T>(scope.engine->current, QV4::Value::fromReturnedValue(v));
#ifndef QT_NO_DEBUG
++scope.size;
#endif
}
Scoped<T> &operator=(const Value &v) {
setPointer(T::cast(v));
setPointer(value_cast<T>(v));
return *this;
}
Scoped<T> &operator=(const ValueRef &v);
Scoped<T> &operator=(const ReturnedValue &v) {
setPointer(T::cast(QV4::Value::fromReturnedValue(v)));
setPointer(value_cast<T>(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<typename T>
inline Scoped<T>::Scoped(const Scope &scope, const ValueRef &v)
{
ptr = scope.engine->jsStackTop++;
setPointer(T::cast(*v.operator ->()));
setPointer(value_cast<T>(*v.operator ->()));
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@ -397,11 +424,10 @@ inline Scoped<T>::Scoped(const Scope &scope, const ValueRef &v)
template<typename T>
inline Scoped<T> &Scoped<T>::operator=(const ValueRef &v)
{
setPointer(T::cast(*v.operator ->()));
setPointer(value_cast<T>(*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<typename T>
inline SafeValue &SafeValue::operator=(Returned<T> *t)
{
val = t->getPointer()->asReturnedValue();
return *this;
}
template<typename T>
inline SafeValue &SafeValue::operator=(const Scoped<T> &t)
{
val = t.ptr->val;
return *this;
}
template<typename T>
inline Returned<T> *SafeValue::as()
{
return Returned<T>::create(value_cast<T>(*this));
}
template<typename T>
PersistentValue::PersistentValue(Returned<T> *obj)
: d(new PersistentValuePrivate(QV4::Value::fromManaged(obj->getPointer())))
{
}
template<typename T>
inline PersistentValue::PersistentValue(const Scoped<T> &obj)
: d(new PersistentValuePrivate(*obj.ptr))
{
}
template<typename T>
inline PersistentValue &PersistentValue::operator=(Returned<T> *obj)
{
return operator=(QV4::Value::fromManaged(obj->getPointer()).asReturnedValue());
}
template<typename T>
inline PersistentValue &PersistentValue::operator=(const Scoped<T> &obj)
{
return operator=(*obj.ptr);
}
template<typename T>
inline WeakValue::WeakValue(Returned<T> *obj)
: d(new PersistentValuePrivate(QV4::Value::fromManaged(obj->getPointer()), /*engine*/0, /*weak*/true))
{
}
template<typename T>
inline WeakValue &WeakValue::operator=(Returned<T> *obj)
{
return operator=(QV4::Value::fromManaged(obj->getPointer()).asReturnedValue());
}
}
QT_END_NAMESPACE

View File

@ -328,7 +328,7 @@ ReturnedValue Serialize::deserialize(const char *&data, QV8Engine *engine)
case WorkerObject:
{
quint32 size = headersize(header);
QV4::Object *o = v4->newObject();
Scoped<Object> 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));

View File

@ -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<String>(ExecutionContext *ctx, const Value &v)
{
return v.toString(ctx)->asReturnedValue();
}
}
QT_END_NAMESPACE

View File

@ -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<RegExpObject>();
ScopedValue searchValue(scope, ctx->argument(0));
Scoped<RegExpObject> 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<FunctionObject> 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<ArrayObject> 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<RegExpObject>()) {
Scoped<RegExpObject> 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<RegExpObject>()) {
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)));

View File

@ -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()
{

View File

@ -341,6 +341,37 @@ struct Q_QML_EXPORT Value
inline void mark() const;
};
struct SafeValue : public Value
{
SafeValue &operator =(const ScopedValue &v);
template<typename T>
SafeValue &operator=(Returned<T> *t);
SafeValue &operator=(ReturnedValue v) {
val = v;
return *this;
}
template<typename T>
SafeValue &operator=(const Scoped<T> &t);
SafeValue &operator=(const Value &v) {
val = v.val;
return *this;
}
template<typename T>
Returned<T> *as();
};
template<typename T>
T *value_cast(const Value &v)
{
return v.as<T>();
}
template<typename T>
ReturnedValue value_convert(ExecutionContext *ctx, const Value &v);
}
QT_END_NAMESPACE

View File

@ -372,11 +372,22 @@ public:
PersistentValue() : d(0) {}
PersistentValue(const Value &val);
PersistentValue(const ScopedValue &val);
PersistentValue(ReturnedValue val);
template<typename T>
PersistentValue(Returned<T> *obj);
template<typename T>
PersistentValue(const Scoped<T> &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<typename T>
PersistentValue &operator=(Returned<T> *obj);
template<typename T>
PersistentValue &operator=(const Scoped<T> &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<typename T>
WeakValue(Returned<T> *obj);
WeakValue &operator=(const WeakValue &other);
WeakValue &operator=(const Value &other);
WeakValue &operator =(const ReturnedValue &other);
template<typename T>
WeakValue &operator=(Returned<T> *obj);
~WeakValue();
Value value() const {

View File

@ -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<QV4::Object> 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)

View File

@ -112,7 +112,7 @@ private:
DEFINE_MANAGED_VTABLE(QQmlLocaleData);
#define GET_LOCALE_DATA_RESOURCE(OBJECT) \
QQmlLocaleData *r = OBJECT.as<QQmlLocaleData>(); \
QV4::Scoped<QQmlLocaleData> r(scope, OBJECT.as<QQmlLocaleData>()); \
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<QV4::Object> 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()

View File

@ -134,9 +134,10 @@ void QmlValueTypeWrapper::initProto(ExecutionEngine *v4)
if (v4->qmlExtensions()->valueTypeWrapperPrototype)
return;
Object *o = v4->newObject();
Scope scope(v4);
Scoped<Object> 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)

View File

@ -65,6 +65,7 @@
#include <QtCore/qdebug.h>
#include <private/qv4objectproto_p.h>
#include <private/qv4scopedvalue_p.h>
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<Object> 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<Object> 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<Object> 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<Object> 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<Object> 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<Object> 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<Object> 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<Object> 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<Object> 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)

View File

@ -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<QV4::Object> 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<Object> 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::QObjectWrapper>())
QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope, ctx->arguments[1]);
if (!!qobjectWrapper)
parentArg = qobjectWrapper->object();
if (!parentArg)
V4THROW_ERROR("Qt.createQmlObject(): Missing parent object");

View File

@ -48,7 +48,8 @@ using namespace QV4;
void qt_add_domexceptions(ExecutionEngine *e)
{
Object *domexception = e->newObject();
Scope scope(e);
Scoped<Object> 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

View File

@ -49,7 +49,8 @@ using namespace QV4;
void qt_add_sqlexceptions(QV4::ExecutionEngine *engine)
{
Object *sqlexception = engine->newObject();
Scope scope(engine);
Scoped<Object> 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

View File

@ -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<QV4::Object> 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<QV4::Object> 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.

View File

@ -83,10 +83,12 @@ struct DelegateModelGroupFunction: QV4::FunctionObject
static QV4::ReturnedValue call(QV4::Managed *that, QV4::CallData *callData)
{
DelegateModelGroupFunction *f = static_cast<DelegateModelGroupFunction *>(that);
QQmlDelegateModelItemObject *o = callData->thisObject.as<QQmlDelegateModelItemObject>();
QV4::ExecutionEngine *v4 = that->engine();
QV4::Scope scope(v4);
QV4::Scoped<DelegateModelGroupFunction> f(scope, that, QV4::Scoped<DelegateModelGroupFunction>::Cast);
QV4::Scoped<QQmlDelegateModelItemObject> 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<QV4::Object> 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<QV4::Object> 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()

View File

@ -177,7 +177,7 @@ public:
};
QHash<int, WorkerScript *> 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::QmlContextWrapper>();
QV4::Scoped<QV4::QmlContextWrapper> w(scope, script->object.value());
Q_ASSERT(!!w);
w->setReadOnly(false);
QV4::Object *api = v4->newObject();
QV4::Scoped<QV4::Object> 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<QV4::Object> activation(scope, getWorker(script));
if (!activation)
return;
QV4::Script program(v4, activation.getPointer(), sourceCode, url.toString());
QV4::ExecutionContext *ctx = v4->current;
try {

View File

@ -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<QV4::Object> 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<QV4::Object> 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()

View File

@ -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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QColor>()).value<QColor>();
if (color.isValid()) {
r->context->state.fillStyle = color;
r->context->buffer()->setFillStyle(color);
r->context->m_fillStyle = value;
} else {
QQuickContext2DStyle *style = value.as<QQuickContext2DStyle>();
QQuickContext2DStyle *style = value->as<QQuickContext2DStyle>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QColor>()).value<QColor>();
if (color.isValid()) {
r->context->state.fillStyle = color;
r->context->buffer()->setStrokeStyle(color);
r->context->m_strokeStyle = value;
} else {
QQuickContext2DStyle *style = value.as<QQuickContext2DStyle>();
QQuickContext2DStyle *style = value->as<QQuickContext2DStyle>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
QV4::Scoped<QQuickJSContext2D> 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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QV4::QObjectWrapper>()) {
if (QV4::QObjectWrapper *qobjectWrapper =value->as<QV4::QObjectWrapper>()) {
if (QQuickPath *path = qobject_cast<QQuickPath*>(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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
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<QQuickJSContext2D>();
CHECK_CONTEXT(r)
@ -2555,8 +2650,8 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_font(QV4::SimpleCallContext *ct
QQuickJSContext2D *r = ctx->thisObject.as<QQuickJSContext2D>();
CHECK_CONTEXT_SETTER(r)
QString fs = ctx->argument(0).toQStringNoThrow();
QFont font = qt_font_from_string(fs, r->context->state.font);
QV4::Scoped<QV4::String> s(scope, ctx->argument(0), QV4::Scoped<QV4::String>::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<QQuickJSContext2D>();
CHECK_CONTEXT_SETTER(r)
QString textAlign = ctx->argument(0).toQStringNoThrow();
QV4::Scoped<QV4::String> s(scope, ctx->argument(0), QV4::Scoped<QV4::String>::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<QQuickJSContext2D>();
CHECK_CONTEXT_SETTER(r)
QString textBaseline = ctx->argument(0).toQStringNoThrow();
QV4::Scoped<QV4::String> s(scope, ctx->argument(0), QV4::Scoped<QV4::String>::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<QV4::Object> 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<QQuickCanvasPixmap> 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<QV4::QObjectWrapper>()) {
} else if (arg->isObject()) {
if (QV4::QObjectWrapper *qobjectWrapper = arg->as<QV4::QObjectWrapper>()) {
if (QQuickImage *imageItem = qobject_cast<QQuickImage*>(qobjectWrapper->object())) {
pixmap.take(r->context->createPixmap(imageItem->source()));
} else if (QQuickCanvasItem *canvas = qobject_cast<QQuickCanvasItem*>(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<QQuickJSContext2DImageData>()) {
} else if (QQuickJSContext2DImageData *imageData = arg->as<QQuickJSContext2DImageData>()) {
QQuickJSContext2DPixelData *pix = imageData->pixelData.as<QQuickJSContext2DPixelData>();
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<QQuickJSContext2DPixelData>();
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<QQuickJSContext2DPixelData>();
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<QQuickJSContext2DImageData>()) {
QV4::ScopedValue arg0(scope, ctx->arguments[0]);
if (QQuickJSContext2DImageData *imgData = arg0->as<QQuickJSContext2DImageData>()) {
QQuickJSContext2DPixelData *pa = imgData->pixelData.as<QQuickJSContext2DPixelData>();
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>();
QQuickJSContext2DImageData *imageData = arg0->as<QQuickJSContext2DImageData>();
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<QV4::Object> 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()

View File

@ -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<QV4::Object> 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<QV4::Object> 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;