aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-09-20 08:21:42 +0200
committerSimon Hausmann <simon.hausmann@digia.com>2013-09-20 08:29:17 +0200
commitbbb78a92a910d32b2886af62c218db87325eb6ce (patch)
tree0e4b55352bb9f083826d0e80747982823f2894ed /src/qml/jsruntime
parent4b5a7b15fc6d3650c8e9b7bf619804a0a953eeba (diff)
parent8ed38c70fd29680f7981d9d23581d46cf32139d0 (diff)
Merge branch 'dev' of ssh://codereview.qt-project.org/qt/qtdeclarative into HEAD
Conflicts: src/qml/compiler/qv4isel_masm.cpp src/qml/jsruntime/qv4script.cpp src/qml/qml/qml.pri src/qml/qml/qqmltypeloader_p.h Change-Id: Ia784d855a2131e3289454f12d841ca2c65be15c1
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp15
-rw-r--r--src/qml/jsruntime/qv4argumentsobject_p.h14
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp320
-rw-r--r--src/qml/jsruntime/qv4arrayobject_p.h52
-rw-r--r--src/qml/jsruntime/qv4booleanobject.cpp16
-rw-r--r--src/qml/jsruntime/qv4booleanobject_p.h12
-rw-r--r--src/qml/jsruntime/qv4context.cpp155
-rw-r--r--src/qml/jsruntime/qv4context_p.h11
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp219
-rw-r--r--src/qml/jsruntime/qv4dateobject_p.h117
-rw-r--r--src/qml/jsruntime/qv4debugging.cpp23
-rw-r--r--src/qml/jsruntime/qv4engine.cpp99
-rw-r--r--src/qml/jsruntime/qv4engine_p.h46
-rw-r--r--src/qml/jsruntime/qv4errorobject.cpp45
-rw-r--r--src/qml/jsruntime/qv4errorobject_p.h52
-rw-r--r--src/qml/jsruntime/qv4exception.cpp3
-rw-r--r--src/qml/jsruntime/qv4exception_p.h4
-rw-r--r--src/qml/jsruntime/qv4function.cpp2
-rw-r--r--src/qml/jsruntime/qv4function_p.h6
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp154
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h78
-rw-r--r--src/qml/jsruntime/qv4global_p.h6
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp87
-rw-r--r--src/qml/jsruntime/qv4globalobject_p.h28
-rw-r--r--src/qml/jsruntime/qv4include.cpp38
-rw-r--r--src/qml/jsruntime/qv4include_p.h8
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp128
-rw-r--r--src/qml/jsruntime/qv4jsonobject_p.h10
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp305
-rw-r--r--src/qml/jsruntime/qv4lookup_p.h42
-rw-r--r--src/qml/jsruntime/qv4managed.cpp11
-rw-r--r--src/qml/jsruntime/qv4managed_p.h75
-rw-r--r--src/qml/jsruntime/qv4mathobject.cpp126
-rw-r--r--src/qml/jsruntime/qv4mathobject_p.h36
-rw-r--r--src/qml/jsruntime/qv4mm.cpp5
-rw-r--r--src/qml/jsruntime/qv4numberobject.cpp44
-rw-r--r--src/qml/jsruntime/qv4numberobject_p.h20
-rw-r--r--src/qml/jsruntime/qv4object.cpp106
-rw-r--r--src/qml/jsruntime/qv4object_p.h42
-rw-r--r--src/qml/jsruntime/qv4objectiterator.cpp20
-rw-r--r--src/qml/jsruntime/qv4objectiterator_p.h4
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp196
-rw-r--r--src/qml/jsruntime/qv4objectproto_p.h62
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp216
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h24
-rw-r--r--src/qml/jsruntime/qv4regexp.cpp8
-rw-r--r--src/qml/jsruntime/qv4regexp_p.h4
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp49
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h16
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp814
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h510
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h274
-rw-r--r--src/qml/jsruntime/qv4script.cpp38
-rw-r--r--src/qml/jsruntime/qv4script_p.h8
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp63
-rw-r--r--src/qml/jsruntime/qv4sequenceobject_p.h10
-rw-r--r--src/qml/jsruntime/qv4serialize.cpp85
-rw-r--r--src/qml/jsruntime/qv4serialize_p.h4
-rw-r--r--src/qml/jsruntime/qv4sparsearray.cpp10
-rw-r--r--src/qml/jsruntime/qv4string.cpp20
-rw-r--r--src/qml/jsruntime/qv4string_p.h11
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp160
-rw-r--r--src/qml/jsruntime/qv4stringobject_p.h48
-rw-r--r--src/qml/jsruntime/qv4value.cpp168
-rw-r--r--src/qml/jsruntime/qv4value_def_p.h208
-rw-r--r--src/qml/jsruntime/qv4value_p.h116
-rw-r--r--src/qml/jsruntime/qv4variantobject.cpp28
-rw-r--r--src/qml/jsruntime/qv4variantobject_p.h8
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp131
-rw-r--r--src/qml/jsruntime/qv4vme_moth_p.h4
70 files changed, 3103 insertions, 2774 deletions
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index 5a53c0fc3e..6c028de372 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -44,10 +44,10 @@
using namespace QV4;
-static Value throwTypeError(SimpleCallContext *ctx)
+static ReturnedValue throwTypeError(SimpleCallContext *ctx)
{
ctx->throwTypeError();
- return Value::undefinedValue();
+ return Value::undefinedValue().asReturnedValue();
}
DEFINE_MANAGED_VTABLE(ArgumentsObject);
@@ -106,6 +106,7 @@ void ArgumentsObject::destroy(Managed *that)
bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const Property &desc, PropertyAttributes attrs)
{
+ Scope scope(ctx);
uint pidx = propertyIndexFromArrayIndex(index);
Property *pd = arrayData + pidx;
Property map;
@@ -130,7 +131,7 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const
if (isMapped && attrs.isData()) {
if (!attrs.isGeneric()) {
- ScopedCallData callData(ctx->engine, 1);
+ ScopedCallData callData(scope, 1);
callData->thisObject = Value::fromObject(this);
callData->args[0] = desc.value;
map.setter()->call(callData);
@@ -148,7 +149,7 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const
DEFINE_MANAGED_VTABLE(ArgumentsGetterFunction);
-Value ArgumentsGetterFunction::call(Managed *getter, CallData *callData)
+ReturnedValue ArgumentsGetterFunction::call(Managed *getter, CallData *callData)
{
ArgumentsGetterFunction *g = static_cast<ArgumentsGetterFunction *>(getter);
Object *that = callData->thisObject.asObject();
@@ -159,12 +160,12 @@ Value ArgumentsGetterFunction::call(Managed *getter, CallData *callData)
getter->engine()->current->throwTypeError();
assert(g->index < o->context->argumentCount);
- return o->context->argument(g->index);
+ return o->context->argument(g->index).asReturnedValue();
}
DEFINE_MANAGED_VTABLE(ArgumentsSetterFunction);
-Value ArgumentsSetterFunction::call(Managed *setter, CallData *callData)
+ReturnedValue ArgumentsSetterFunction::call(Managed *setter, CallData *callData)
{
ArgumentsSetterFunction *s = static_cast<ArgumentsSetterFunction *>(setter);
Object *that = callData->thisObject.asObject();
@@ -176,7 +177,7 @@ Value ArgumentsSetterFunction::call(Managed *setter, CallData *callData)
assert(s->index < o->context->argumentCount);
o->context->arguments[s->index] = callData->argc ? callData->args[0] : Value::undefinedValue();
- return Value::undefinedValue();
+ return Value::undefinedValue().asReturnedValue();
}
void ArgumentsObject::markObjects(Managed *that)
diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h
index 66ee22c953..7862a602bd 100644
--- a/src/qml/jsruntime/qv4argumentsobject_p.h
+++ b/src/qml/jsruntime/qv4argumentsobject_p.h
@@ -50,32 +50,29 @@ namespace QV4 {
struct ArgumentsGetterFunction: FunctionObject
{
+ Q_MANAGED
uint index;
ArgumentsGetterFunction(ExecutionContext *scope, uint index)
: FunctionObject(scope), index(index) { vtbl = &static_vtbl; }
- static Value call(Managed *that, CallData *d);
-
-protected:
- static const ManagedVTable static_vtbl;
+ static ReturnedValue call(Managed *that, CallData *d);
};
struct ArgumentsSetterFunction: FunctionObject
{
+ Q_MANAGED
uint index;
ArgumentsSetterFunction(ExecutionContext *scope, uint index)
: FunctionObject(scope), index(index) { vtbl = &static_vtbl; }
- static Value call(Managed *that, CallData *callData);
-
-protected:
- static const ManagedVTable static_vtbl;
+ static ReturnedValue call(Managed *that, CallData *callData);
};
struct ArgumentsObject: Object {
+ Q_MANAGED
CallContext *context;
QVector<Value> mappedArguments;
ArgumentsObject(CallContext *context);
@@ -90,7 +87,6 @@ struct ArgumentsObject: Object {
static void markObjects(Managed *that);
protected:
- static const ManagedVTable static_vtbl;
static void destroy(Managed *);
};
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index e3b08f5941..1f09b97d5c 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -54,10 +54,11 @@ ArrayCtor::ArrayCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value ArrayCtor::construct(Managed *m, CallData *callData)
+ReturnedValue ArrayCtor::construct(Managed *m, CallData *callData)
{
ExecutionEngine *v4 = m->engine();
- ArrayObject *a = v4->newArrayObject();
+ Scope scope(v4);
+ Scoped<ArrayObject> a(scope, v4->newArrayObject());
uint len;
if (callData->argc == 1 && callData->args[0].isNumber()) {
bool ok;
@@ -77,10 +78,10 @@ Value ArrayCtor::construct(Managed *m, CallData *callData)
}
a->setArrayLengthUnchecked(len);
- return Value::fromObject(a);
+ return a.asReturnedValue();
}
-Value ArrayCtor::call(Managed *that, CallData *callData)
+ReturnedValue ArrayCtor::call(Managed *that, CallData *callData)
{
return construct(that, callData);
}
@@ -123,36 +124,41 @@ uint ArrayPrototype::getLength(ExecutionContext *ctx, Object *o)
{
if (o->isArrayObject())
return o->arrayLength();
- return o->get(ctx->engine->id_length).toUInt32();
+ Scope scope(ctx);
+ ScopedValue v(scope, o->get(ctx->engine->id_length));
+ return v->toUInt32();
}
-Value ArrayPrototype::method_isArray(SimpleCallContext *ctx)
+ReturnedValue ArrayPrototype::method_isArray(SimpleCallContext *ctx)
{
Value arg = ctx->argument(0);
bool isArray = arg.asArrayObject();
- return Value::fromBoolean(isArray);
+ return Value::fromBoolean(isArray).asReturnedValue();
}
-Value ArrayPrototype::method_toString(SimpleCallContext *ctx)
+ReturnedValue ArrayPrototype::method_toString(SimpleCallContext *ctx)
{
+ QV4::Scope scope(ctx);
QV4::Object *o = ctx->thisObject.toObject(ctx);
- FunctionObject *f = o->get(ctx->engine->newString("join")).asFunctionObject();
+ ScopedValue v(scope, o->get(ctx->engine->newString("join")));
+ FunctionObject *f = v->asFunctionObject();
if (f) {
- ScopedCallData d(ctx->engine, 0);
+ ScopedCallData d(scope, 0);
d->thisObject = ctx->thisObject;
return f->call(d);
}
return ObjectPrototype::method_toString(ctx);
}
-Value ArrayPrototype::method_toLocaleString(SimpleCallContext *ctx)
+ReturnedValue ArrayPrototype::method_toLocaleString(SimpleCallContext *ctx)
{
return method_toString(ctx);
}
-Value ArrayPrototype::method_concat(SimpleCallContext *ctx)
+ReturnedValue ArrayPrototype::method_concat(SimpleCallContext *ctx)
{
- ArrayObject *result = ctx->engine->newArrayObject();
+ Scope scope(ctx);
+ Scoped<ArrayObject> result(scope, ctx->engine->newArrayObject());
if (ArrayObject *instance = ctx->thisObject.asArrayObject()) {
result->copyArrayData(instance);
@@ -174,14 +180,15 @@ Value ArrayPrototype::method_concat(SimpleCallContext *ctx)
result->arrayConcat(elt);
else
- result->arraySet(getLength(ctx, result), arg);
+ result->arraySet(getLength(ctx, result.getPointer()), arg);
}
- return Value::fromObject(result);
+ return result.asReturnedValue();
}
-Value ArrayPrototype::method_join(SimpleCallContext *ctx)
+ReturnedValue ArrayPrototype::method_join(SimpleCallContext *ctx)
{
+ Scope scope(ctx);
Value arg = ctx->argument(0);
QString r4;
@@ -190,75 +197,78 @@ Value ArrayPrototype::method_join(SimpleCallContext *ctx)
else
r4 = arg.toString(ctx)->toQString();
- Value self = ctx->thisObject;
- const Value length = self.property(ctx, ctx->engine->id_length);
- const quint32 r2 = Value::toUInt32(length.isUndefined() ? 0 : length.toNumber());
+ Scoped<Object> self(scope, ctx->thisObject);
+ ScopedValue length(scope, self->get(ctx->engine->id_length));
+ const quint32 r2 = Value::toUInt32(length->isUndefined() ? 0 : length->toNumber());
static QSet<Object *> visitedArrayElements;
- if (! r2 || visitedArrayElements.contains(self.objectValue()))
- return Value::fromString(ctx, QString());
+ if (! r2 || visitedArrayElements.contains(self.getPointer()))
+ return Value::fromString(ctx, QString()).asReturnedValue();
// avoid infinite recursion
- visitedArrayElements.insert(self.objectValue());
+ visitedArrayElements.insert(self.getPointer());
QString R;
// ### FIXME
- if (ArrayObject *a = self.asArrayObject()) {
+ if (ArrayObject *a = self->asArrayObject()) {
+ ScopedValue e(scope);
for (uint i = 0; i < a->arrayLength(); ++i) {
if (i)
R += r4;
- Value e = a->getIndexed(i);
- if (! (e.isUndefined() || e.isNull()))
- R += e.toString(ctx)->toQString();
+ e = a->getIndexed(i);
+ if (!e->isNullOrUndefined())
+ R += e->toString(ctx)->toQString();
}
} else {
//
// crazy!
//
- Value r6 = self.property(ctx, ctx->engine->newString(QStringLiteral("0")));
- if (!(r6.isUndefined() || r6.isNull()))
- R = r6.toString(ctx)->toQString();
+ ScopedValue r6(scope, self->get(ctx->engine->newString(QStringLiteral("0"))));
+ if (!r6->isNullOrUndefined())
+ R = r6->toString(ctx)->toQString();
+ ScopedValue r12(scope);
for (quint32 k = 1; k < r2; ++k) {
R += r4;
String *name = Value::fromDouble(k).toString(ctx);
- Value r12 = self.property(ctx, name);
+ r12 = self->get(name);
- if (! (r12.isUndefined() || r12.isNull()))
- R += r12.toString(ctx)->toQString();
+ if (!r12->isNullOrUndefined())
+ R += r12->toString(ctx)->toQString();
}
}
- visitedArrayElements.remove(self.objectValue());
- return Value::fromString(ctx, R);
+ visitedArrayElements.remove(self.getPointer());
+ return Value::fromString(ctx, R).asReturnedValue();
}
-Value ArrayPrototype::method_pop(SimpleCallContext *ctx)
+ReturnedValue ArrayPrototype::method_pop(SimpleCallContext *ctx)
{
+ Scope scope(ctx);
Object *instance = ctx->thisObject.toObject(ctx);
uint len = getLength(ctx, instance);
if (!len) {
if (!instance->isArrayObject())
instance->put(ctx->engine->id_length, Value::fromInt32(0));
- return Value::undefinedValue();
+ return Value::undefinedValue().asReturnedValue();
}
- Value result = instance->getIndexed(len - 1);
+ ScopedValue result(scope, instance->getIndexed(len - 1));
instance->deleteIndexedProperty(len - 1);
if (instance->isArrayObject())
instance->setArrayLengthUnchecked(len - 1);
else
instance->put(ctx->engine->id_length, Value::fromDouble(len - 1));
- return result;
+ return result.asReturnedValue();
}
-Value ArrayPrototype::method_push(SimpleCallContext *ctx)
+ReturnedValue ArrayPrototype::method_push(SimpleCallContext *ctx)
{
Object *instance = ctx->thisObject.toObject(ctx);
uint len = getLength(ctx, instance);
@@ -275,7 +285,7 @@ Value ArrayPrototype::method_push(SimpleCallContext *ctx)
instance->put(ctx->engine->id_length, Value::fromDouble(newLen));
else
ctx->throwRangeError(Value::fromString(ctx, QStringLiteral("Array.prototype.push: Overflow")));
- return Value::fromDouble(newLen);
+ return Value::fromDouble(newLen).asReturnedValue();
}
if (!instance->protoHasArray() && instance->arrayDataLen <= len) {
@@ -306,22 +316,25 @@ Value ArrayPrototype::method_push(SimpleCallContext *ctx)
instance->put(ctx->engine->id_length, Value::fromDouble(len));
if (len < INT_MAX)
- return Value::fromInt32(len);
- return Value::fromDouble((double)len);
+ return Value::fromInt32(len).asReturnedValue();
+ return Value::fromDouble((double)len).asReturnedValue();
}
-Value ArrayPrototype::method_reverse(SimpleCallContext *ctx)
+ReturnedValue ArrayPrototype::method_reverse(SimpleCallContext *ctx)
{
+ Scope scope(ctx);
Object *instance = ctx->thisObject.toObject(ctx);
uint length = getLength(ctx, instance);
int lo = 0, hi = length - 1;
+ ScopedValue lval(scope);
+ ScopedValue hval(scope);
for (; lo < hi; ++lo, --hi) {
bool loExists, hiExists;
- Value lval = instance->getIndexed(lo, &loExists);
- Value hval = instance->getIndexed(hi, &hiExists);
+ lval = instance->getIndexed(lo, &loExists);
+ hval = instance->getIndexed(hi, &hiExists);
if (hiExists)
instance->putIndexed(lo, hval);
else
@@ -331,18 +344,19 @@ Value ArrayPrototype::method_reverse(SimpleCallContext *ctx)
else
instance->deleteIndexedProperty(hi);
}
- return Value::fromObject(instance);
+ return Value::fromObject(instance).asReturnedValue();
}
-Value ArrayPrototype::method_shift(SimpleCallContext *ctx)
+ReturnedValue ArrayPrototype::method_shift(SimpleCallContext *ctx)
{
+ Scope scope(ctx);
Object *instance = ctx->thisObject.toObject(ctx);
uint len = getLength(ctx, instance);
if (!len) {
if (!instance->isArrayObject())
instance->put(ctx->engine->id_length, Value::fromInt32(0));
- return Value::undefinedValue();
+ return Value::undefinedValue().asReturnedValue();
}
Property *front = 0;
@@ -350,7 +364,7 @@ Value ArrayPrototype::method_shift(SimpleCallContext *ctx)
if (pidx < UINT_MAX && (!instance->arrayAttributes || !instance->arrayAttributes[0].isGeneric()))
front = instance->arrayData + pidx;
- Value result = front ? instance->getValue(front, instance->arrayAttributes ? instance->arrayAttributes[pidx] : Attr_Data) : Value::undefinedValue();
+ Value result = front ? Value::fromReturnedValue(instance->getValue(front, instance->arrayAttributes ? instance->arrayAttributes[pidx] : Attr_Data)) : Value::undefinedValue();
if (!instance->protoHasArray() && instance->arrayDataLen <= len) {
if (!instance->sparseArray) {
@@ -367,10 +381,11 @@ Value ArrayPrototype::method_shift(SimpleCallContext *ctx)
instance->freeArrayValue(idx);
}
} else {
+ ScopedValue v(scope);
// do it the slow way
for (uint k = 1; k < len; ++k) {
bool exists;
- Value v = instance->getIndexed(k, &exists);
+ v = instance->getIndexed(k, &exists);
if (exists)
instance->putIndexed(k - 1, v);
else
@@ -383,15 +398,16 @@ Value ArrayPrototype::method_shift(SimpleCallContext *ctx)
instance->setArrayLengthUnchecked(len - 1);
else
instance->put(ctx->engine->id_length, Value::fromDouble(len - 1));
- return result;
+ return result.asReturnedValue();
}
-Value ArrayPrototype::method_slice(SimpleCallContext *ctx)
+ReturnedValue ArrayPrototype::method_slice(SimpleCallContext *ctx)
{
+ Scope scope(ctx);
Object *o = ctx->thisObject.toObject(ctx);
- ArrayObject *result = ctx->engine->newArrayObject();
- uint len = o->get(ctx->engine->id_length).toUInt32();
+ Scoped<ArrayObject> result(scope, ctx->engine->newArrayObject());
+ uint len = ArrayPrototype::getLength(ctx, o);
double s = ctx->argument(0).toInteger();
uint start;
if (s < 0)
@@ -411,19 +427,20 @@ Value ArrayPrototype::method_slice(SimpleCallContext *ctx)
end = (uint) e;
}
+ ScopedValue v(scope);
uint n = 0;
for (uint i = start; i < end; ++i) {
bool exists;
- Value v = o->getIndexed(i, &exists);
+ v = o->getIndexed(i, &exists);
if (exists) {
result->arraySet(n, v);
}
++n;
}
- return Value::fromObject(result);
+ return result.asReturnedValue();
}
-Value ArrayPrototype::method_sort(SimpleCallContext *ctx)
+ReturnedValue ArrayPrototype::method_sort(SimpleCallContext *ctx)
{
Object *instance = ctx->thisObject.toObject(ctx);
@@ -431,15 +448,16 @@ Value ArrayPrototype::method_sort(SimpleCallContext *ctx)
Value comparefn = ctx->argument(0);
instance->arraySort(ctx, instance, comparefn, len);
- return ctx->thisObject;
+ return ctx->thisObject.asReturnedValue();
}
-Value ArrayPrototype::method_splice(SimpleCallContext *ctx)
+ReturnedValue ArrayPrototype::method_splice(SimpleCallContext *ctx)
{
+ Scope scope(ctx);
Object *instance = ctx->thisObject.toObject(ctx);
uint len = getLength(ctx, instance);
- ArrayObject *newArray = ctx->engine->newArrayObject();
+ Scoped<ArrayObject> newArray(scope, ctx->engine->newArrayObject());
double rs = ctx->argument(0).toInteger();
uint start;
@@ -453,7 +471,7 @@ Value ArrayPrototype::method_splice(SimpleCallContext *ctx)
newArray->arrayReserve(deleteCount);
Property *pd = newArray->arrayData;
for (uint i = 0; i < deleteCount; ++i) {
- pd->value = instance->getIndexed(start + i);
+ pd->value = Value::fromReturnedValue(instance->getIndexed(start + i));
++pd;
}
newArray->arrayDataLen = deleteCount;
@@ -461,10 +479,11 @@ Value ArrayPrototype::method_splice(SimpleCallContext *ctx)
uint itemCount = ctx->argumentCount < 2 ? 0 : ctx->argumentCount - 2;
+ ScopedValue v(scope);
if (itemCount < deleteCount) {
for (uint k = start; k < len - deleteCount; ++k) {
bool exists;
- Value v = instance->getIndexed(k + deleteCount, &exists);
+ v = instance->getIndexed(k + deleteCount, &exists);
if (exists)
instance->putIndexed(k + itemCount, v);
else
@@ -476,7 +495,7 @@ Value ArrayPrototype::method_splice(SimpleCallContext *ctx)
uint k = len - deleteCount;
while (k > start) {
bool exists;
- Value v = instance->getIndexed(k + deleteCount - 1, &exists);
+ v = instance->getIndexed(k + deleteCount - 1, &exists);
if (exists)
instance->putIndexed(k + itemCount - 1, v);
else
@@ -491,11 +510,12 @@ Value ArrayPrototype::method_splice(SimpleCallContext *ctx)
ctx->strictMode = true;
instance->put(ctx->engine->id_length, Value::fromDouble(len - deleteCount + itemCount));
- return Value::fromObject(newArray);
+ return newArray.asReturnedValue();
}
-Value ArrayPrototype::method_unshift(SimpleCallContext *ctx)
+ReturnedValue ArrayPrototype::method_unshift(SimpleCallContext *ctx)
{
+ Scope scope(ctx);
Object *instance = ctx->thisObject.toObject(ctx);
uint len = getLength(ctx, instance);
@@ -521,9 +541,10 @@ Value ArrayPrototype::method_unshift(SimpleCallContext *ctx)
}
}
} else {
+ ScopedValue v(scope);
for (uint k = len; k > 0; --k) {
bool exists;
- Value v = instance->getIndexed(k - 1, &exists);
+ v = instance->getIndexed(k - 1, &exists);
if (exists)
instance->putIndexed(k + ctx->argumentCount - 1, v);
else
@@ -540,18 +561,18 @@ Value ArrayPrototype::method_unshift(SimpleCallContext *ctx)
instance->put(ctx->engine->id_length, Value::fromDouble(newLen));
if (newLen < INT_MAX)
- return Value::fromInt32(newLen);
- return Value::fromDouble((double)newLen);
+ return Value::fromInt32(newLen).asReturnedValue();
+ return Value::fromDouble((double)newLen).asReturnedValue();
}
-Value ArrayPrototype::method_indexOf(SimpleCallContext *ctx)
+ReturnedValue ArrayPrototype::method_indexOf(SimpleCallContext *ctx)
{
- ValueScope scope(ctx);
+ Scope scope(ctx);
Object *instance = ctx->thisObject.toObject(ctx);
uint len = getLength(ctx, instance);
if (!len)
- return Value::fromInt32(-1);
+ return Value::fromInt32(-1).asReturnedValue();
ScopedValue searchValue(scope);
uint fromIndex = 0;
@@ -564,7 +585,7 @@ Value ArrayPrototype::method_indexOf(SimpleCallContext *ctx)
if (ctx->argumentCount >= 2) {
double f = ctx->argument(1).toInteger();
if (f >= len)
- return Value::fromInt32(-1);
+ return Value::fromInt32(-1).asReturnedValue();
if (f < 0)
f = qMax(len + f, 0.);
fromIndex = (uint) f;
@@ -576,22 +597,22 @@ Value ArrayPrototype::method_indexOf(SimpleCallContext *ctx)
bool exists;
v = instance->getIndexed(k, &exists);
if (exists && __qmljs_strict_equal(v, searchValue))
- return Value::fromDouble(k);
+ return Value::fromDouble(k).asReturnedValue();
}
- return Value::fromInt32(-1);
+ return Value::fromInt32(-1).asReturnedValue();
}
return instance->arrayIndexOf(searchValue, fromIndex, len, ctx, instance);
}
-Value ArrayPrototype::method_lastIndexOf(SimpleCallContext *ctx)
+ReturnedValue ArrayPrototype::method_lastIndexOf(SimpleCallContext *ctx)
{
- ValueScope scope(ctx);
+ Scope scope(ctx);
Object *instance = ctx->thisObject.toObject(ctx);
uint len = getLength(ctx, instance);
if (!len)
- return Value::fromInt32(-1);
+ return Value::fromInt32(-1).asReturnedValue();
ScopedValue searchValue(scope);
uint fromIndex = len;
@@ -608,7 +629,7 @@ Value ArrayPrototype::method_lastIndexOf(SimpleCallContext *ctx)
else if (f < 0) {
f = len + f;
if (f < 0)
- return Value::fromInt32(-1);
+ return Value::fromInt32(-1).asReturnedValue();
}
fromIndex = (uint) f + 1;
}
@@ -619,13 +640,14 @@ Value ArrayPrototype::method_lastIndexOf(SimpleCallContext *ctx)
bool exists;
v = instance->getIndexed(k, &exists);
if (exists && __qmljs_strict_equal(v, searchValue))
- return Value::fromDouble(k);
+ return Value::fromDouble(k).asReturnedValue();
}
- return Value::fromInt32(-1);
+ return Value::fromInt32(-1).asReturnedValue();
}
-Value ArrayPrototype::method_every(SimpleCallContext *ctx)
+ReturnedValue ArrayPrototype::method_every(SimpleCallContext *ctx)
{
+ Scope scope(ctx);
Object *instance = ctx->thisObject.toObject(ctx);
uint len = getLength(ctx, instance);
@@ -636,26 +658,30 @@ Value ArrayPrototype::method_every(SimpleCallContext *ctx)
Value thisArg = ctx->argument(1);
+ ScopedCallData callData(scope, 3);
+ callData->args[2] = Value::fromObject(instance);
+ callData->thisObject = thisArg;
+ ScopedValue r(scope);
+ ScopedValue v(scope);
+
bool ok = true;
for (uint k = 0; ok && k < len; ++k) {
bool exists;
- Value v = instance->getIndexed(k, &exists);
+ v = instance->getIndexed(k, &exists);
if (!exists)
continue;
- ScopedCallData callData(ctx->engine, 3);
callData->args[0] = v;
callData->args[1] = Value::fromDouble(k);
- callData->args[2] = Value::fromObject(instance);
- callData->thisObject = thisArg;
- Value r = callback->call(callData);
- ok = r.toBoolean();
+ r = callback->call(callData);
+ ok = r->toBoolean();
}
- return Value::fromBoolean(ok);
+ return Value::fromBoolean(ok).asReturnedValue();
}
-Value ArrayPrototype::method_some(SimpleCallContext *ctx)
+ReturnedValue ArrayPrototype::method_some(SimpleCallContext *ctx)
{
+ Scope scope(ctx);
Object *instance = ctx->thisObject.toObject(ctx);
uint len = getLength(ctx, instance);
@@ -664,28 +690,29 @@ Value ArrayPrototype::method_some(SimpleCallContext *ctx)
if (!callback)
ctx->throwTypeError();
- Value thisArg = ctx->argument(1);
+ ScopedCallData callData(scope, 3);
+ callData->thisObject = ctx->argument(1);
+ callData->args[2] = Value::fromObject(instance);
+ ScopedValue v(scope);
for (uint k = 0; k < len; ++k) {
bool exists;
- Value v = instance->getIndexed(k, &exists);
+ v = instance->getIndexed(k, &exists);
if (!exists)
continue;
- ScopedCallData callData(ctx->engine, 3);
- callData->thisObject = thisArg;
callData->args[0] = v;
callData->args[1] = Value::fromDouble(k);
- callData->args[2] = Value::fromObject(instance);
- Value r = callback->call(callData);
+ Value r = Value::fromReturnedValue(callback->call(callData));
if (r.toBoolean())
- return Value::fromBoolean(true);
+ return Value::fromBoolean(true).asReturnedValue();
}
- return Value::fromBoolean(false);
+ return Value::fromBoolean(false).asReturnedValue();
}
-Value ArrayPrototype::method_forEach(SimpleCallContext *ctx)
+ReturnedValue ArrayPrototype::method_forEach(SimpleCallContext *ctx)
{
+ Scope scope(ctx);
Object *instance = ctx->thisObject.toObject(ctx);
uint len = getLength(ctx, instance);
@@ -694,26 +721,27 @@ Value ArrayPrototype::method_forEach(SimpleCallContext *ctx)
if (!callback)
ctx->throwTypeError();
- Value thisArg = ctx->argument(1);
+ ScopedCallData callData(scope, 3);
+ callData->thisObject = ctx->argument(1);
+ callData->args[2] = Value::fromObject(instance);
+ ScopedValue v(scope);
for (uint k = 0; k < len; ++k) {
bool exists;
- Value v = instance->getIndexed(k, &exists);
+ v = instance->getIndexed(k, &exists);
if (!exists)
continue;
- ScopedCallData callData(ctx->engine, 3);
- callData->thisObject = thisArg;
callData->args[0] = v;
callData->args[1] = Value::fromDouble(k);
- callData->args[2] = Value::fromObject(instance);
callback->call(callData);
}
- return Value::undefinedValue();
+ return Value::undefinedValue().asReturnedValue();
}
-Value ArrayPrototype::method_map(SimpleCallContext *ctx)
+ReturnedValue ArrayPrototype::method_map(SimpleCallContext *ctx)
{
+ Scope scope(ctx);
Object *instance = ctx->thisObject.toObject(ctx);
uint len = getLength(ctx, instance);
@@ -724,29 +752,33 @@ Value ArrayPrototype::method_map(SimpleCallContext *ctx)
Value thisArg = ctx->argument(1);
- ArrayObject *a = ctx->engine->newArrayObject();
+ 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);
+
+ ScopedValue v(scope);
for (uint k = 0; k < len; ++k) {
bool exists;
- Value v = instance->getIndexed(k, &exists);
+ v = instance->getIndexed(k, &exists);
if (!exists)
continue;
- ScopedCallData callData(ctx->engine, 3);
- callData->thisObject = thisArg;
callData->args[0] = v;
callData->args[1] = Value::fromDouble(k);
- callData->args[2] = Value::fromObject(instance);
- Value mapped = callback->call(callData);
+ mapped = callback->call(callData);
a->arraySet(k, mapped);
}
- return Value::fromObject(a);
+ return a.asReturnedValue();
}
-Value ArrayPrototype::method_filter(SimpleCallContext *ctx)
+ReturnedValue ArrayPrototype::method_filter(SimpleCallContext *ctx)
{
+ Scope scope(ctx);
Object *instance = ctx->thisObject.toObject(ctx);
uint len = getLength(ctx, instance);
@@ -757,32 +789,37 @@ Value ArrayPrototype::method_filter(SimpleCallContext *ctx)
Value thisArg = ctx->argument(1);
- ArrayObject *a = ctx->engine->newArrayObject();
+ 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);
+
+ ScopedValue v(scope);
+
uint to = 0;
for (uint k = 0; k < len; ++k) {
bool exists;
- Value v = instance->getIndexed(k, &exists);
+ v = instance->getIndexed(k, &exists);
if (!exists)
continue;
- ScopedCallData callData(ctx->engine, 3);
- callData->thisObject = thisArg;
callData->args[0] = v;
callData->args[1] = Value::fromDouble(k);
- callData->args[2] = Value::fromObject(instance);
- Value selected = callback->call(callData);
- if (selected.toBoolean()) {
+ selected = callback->call(callData);
+ if (selected->toBoolean()) {
a->arraySet(to, v);
++to;
}
}
- return Value::fromObject(a);
+ return a.asReturnedValue();
}
-Value ArrayPrototype::method_reduce(SimpleCallContext *ctx)
+ReturnedValue ArrayPrototype::method_reduce(SimpleCallContext *ctx)
{
+ Scope scope(ctx);
Object *instance = ctx->thisObject.toObject(ctx);
uint len = getLength(ctx, instance);
@@ -792,13 +829,15 @@ Value ArrayPrototype::method_reduce(SimpleCallContext *ctx)
ctx->throwTypeError();
uint k = 0;
- Value acc;
+ ScopedValue acc(scope);
+ ScopedValue v(scope);
+
if (ctx->argumentCount > 1) {
acc = ctx->argument(1);
} else {
bool kPresent = false;
while (k < len && !kPresent) {
- Value v = instance->getIndexed(k, &kPresent);
+ v = instance->getIndexed(k, &kPresent);
if (kPresent)
acc = v;
++k;
@@ -807,25 +846,28 @@ Value ArrayPrototype::method_reduce(SimpleCallContext *ctx)
ctx->throwTypeError();
}
+ ScopedCallData callData(scope, 4);
+ callData->thisObject = Value::undefinedValue();
+ callData->args[0] = acc;
+ callData->args[3] = Value::fromObject(instance);
+
while (k < len) {
bool kPresent;
- Value v = instance->getIndexed(k, &kPresent);
+ v = instance->getIndexed(k, &kPresent);
if (kPresent) {
- ScopedCallData callData(ctx->engine, 4);
- callData->thisObject = Value::undefinedValue();
callData->args[0] = acc;
callData->args[1] = v;
callData->args[2] = Value::fromDouble(k);
- callData->args[3] = Value::fromObject(instance);
acc = callback->call(callData);
}
++k;
}
- return acc;
+ return acc.asReturnedValue();
}
-Value ArrayPrototype::method_reduceRight(SimpleCallContext *ctx)
+ReturnedValue ArrayPrototype::method_reduceRight(SimpleCallContext *ctx)
{
+ Scope scope(ctx);
Object *instance = ctx->thisObject.toObject(ctx);
uint len = getLength(ctx, instance);
@@ -837,17 +879,18 @@ Value ArrayPrototype::method_reduceRight(SimpleCallContext *ctx)
if (len == 0) {
if (ctx->argumentCount == 1)
ctx->throwTypeError();
- return ctx->argument(1);
+ return ctx->argument(1).asReturnedValue();
}
uint k = len;
- Value acc;
+ ScopedValue acc(scope);
+ ScopedValue v(scope);
if (ctx->argumentCount > 1) {
acc = ctx->argument(1);
} else {
bool kPresent = false;
while (k > 0 && !kPresent) {
- Value v = instance->getIndexed(k - 1, &kPresent);
+ v = instance->getIndexed(k - 1, &kPresent);
if (kPresent)
acc = v;
--k;
@@ -856,20 +899,21 @@ Value ArrayPrototype::method_reduceRight(SimpleCallContext *ctx)
ctx->throwTypeError();
}
+ ScopedCallData callData(scope, 4);
+ callData->thisObject = Value::undefinedValue();
+ callData->args[3] = Value::fromObject(instance);
+
while (k > 0) {
bool kPresent;
- Value v = instance->getIndexed(k - 1, &kPresent);
+ v = instance->getIndexed(k - 1, &kPresent);
if (kPresent) {
- ScopedCallData callData(ctx->engine, 4);
- callData->thisObject = Value::undefinedValue();
callData->args[0] = acc;
callData->args[1] = v;
callData->args[2] = Value::fromDouble(k - 1);
- callData->args[3] = Value::fromObject(instance);
acc = callback->call(callData);
}
--k;
}
- return acc;
+ return acc.asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h
index 354ddd0380..a38a87f1f3 100644
--- a/src/qml/jsruntime/qv4arrayobject_p.h
+++ b/src/qml/jsruntime/qv4arrayobject_p.h
@@ -51,13 +51,11 @@ namespace QV4 {
struct ArrayCtor: FunctionObject
{
+ Q_MANAGED
ArrayCtor(ExecutionContext *scope);
- static Value construct(Managed *m, CallData *callData);
- static Value call(Managed *that, CallData *callData);
-
-protected:
- static const ManagedVTable static_vtbl;
+ static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue call(Managed *that, CallData *callData);
};
struct ArrayPrototype: ArrayObject
@@ -68,28 +66,28 @@ struct ArrayPrototype: ArrayObject
static uint getLength(ExecutionContext *ctx, Object *o);
- static Value method_isArray(SimpleCallContext *ctx);
- static Value method_toString(SimpleCallContext *ctx);
- static Value method_toLocaleString(SimpleCallContext *ctx);
- static Value method_concat(SimpleCallContext *ctx);
- static Value method_join(SimpleCallContext *ctx);
- static Value method_pop(SimpleCallContext *ctx);
- static Value method_push(SimpleCallContext *ctx);
- static Value method_reverse(SimpleCallContext *ctx);
- static Value method_shift(SimpleCallContext *ctx);
- static Value method_slice(SimpleCallContext *ctx);
- static Value method_sort(SimpleCallContext *ctx);
- static Value method_splice(SimpleCallContext *ctx);
- static Value method_unshift(SimpleCallContext *ctx);
- static Value method_indexOf(SimpleCallContext *ctx);
- static Value method_lastIndexOf(SimpleCallContext *ctx);
- static Value method_every(SimpleCallContext *ctx);
- static Value method_some(SimpleCallContext *ctx);
- static Value method_forEach(SimpleCallContext *ctx);
- static Value method_map(SimpleCallContext *ctx);
- static Value method_filter(SimpleCallContext *ctx);
- static Value method_reduce(SimpleCallContext *ctx);
- static Value method_reduceRight(SimpleCallContext *ctx);
+ static ReturnedValue method_isArray(SimpleCallContext *ctx);
+ static ReturnedValue method_toString(SimpleCallContext *ctx);
+ static ReturnedValue method_toLocaleString(SimpleCallContext *ctx);
+ static ReturnedValue method_concat(SimpleCallContext *ctx);
+ static ReturnedValue method_join(SimpleCallContext *ctx);
+ static ReturnedValue method_pop(SimpleCallContext *ctx);
+ static ReturnedValue method_push(SimpleCallContext *ctx);
+ static ReturnedValue method_reverse(SimpleCallContext *ctx);
+ static ReturnedValue method_shift(SimpleCallContext *ctx);
+ static ReturnedValue method_slice(SimpleCallContext *ctx);
+ static ReturnedValue method_sort(SimpleCallContext *ctx);
+ static ReturnedValue method_splice(SimpleCallContext *ctx);
+ static ReturnedValue method_unshift(SimpleCallContext *ctx);
+ static ReturnedValue method_indexOf(SimpleCallContext *ctx);
+ static ReturnedValue method_lastIndexOf(SimpleCallContext *ctx);
+ static ReturnedValue method_every(SimpleCallContext *ctx);
+ static ReturnedValue method_some(SimpleCallContext *ctx);
+ static ReturnedValue method_forEach(SimpleCallContext *ctx);
+ static ReturnedValue method_map(SimpleCallContext *ctx);
+ static ReturnedValue method_filter(SimpleCallContext *ctx);
+ static ReturnedValue method_reduce(SimpleCallContext *ctx);
+ static ReturnedValue method_reduceRight(SimpleCallContext *ctx);
};
diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp
index 6b77db3ca7..86ddebd6c3 100644
--- a/src/qml/jsruntime/qv4booleanobject.cpp
+++ b/src/qml/jsruntime/qv4booleanobject.cpp
@@ -51,16 +51,16 @@ BooleanCtor::BooleanCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value BooleanCtor::construct(Managed *m, CallData *callData)
+ReturnedValue BooleanCtor::construct(Managed *m, CallData *callData)
{
bool n = callData->argc ? callData->args[0].toBoolean() : false;
- return Value::fromObject(m->engine()->newBooleanObject(Value::fromBoolean(n)));
+ return Encode(m->engine()->newBooleanObject(Value::fromBoolean(n)));
}
-Value BooleanCtor::call(Managed *, CallData *callData)
+ReturnedValue BooleanCtor::call(Managed *, CallData *callData)
{
bool value = callData->argc ? callData->args[0].toBoolean() : 0;
- return Value::fromBoolean(value);
+ return Encode(value);
}
void BooleanPrototype::init(ExecutionContext *ctx, const Value &ctor)
@@ -72,7 +72,7 @@ void BooleanPrototype::init(ExecutionContext *ctx, const Value &ctor)
defineDefaultProperty(ctx, QStringLiteral("valueOf"), method_valueOf);
}
-Value BooleanPrototype::method_toString(SimpleCallContext *ctx)
+ReturnedValue BooleanPrototype::method_toString(SimpleCallContext *ctx)
{
bool result;
if (ctx->thisObject.isBoolean()) {
@@ -84,14 +84,14 @@ Value BooleanPrototype::method_toString(SimpleCallContext *ctx)
result = thisObject->value.booleanValue();
}
- return Value::fromString(ctx, QLatin1String(result ? "true" : "false"));
+ return Value::fromString(ctx, QLatin1String(result ? "true" : "false")).asReturnedValue();
}
-Value BooleanPrototype::method_valueOf(SimpleCallContext *ctx)
+ReturnedValue BooleanPrototype::method_valueOf(SimpleCallContext *ctx)
{
BooleanObject *thisObject = ctx->thisObject.asBooleanObject();
if (!thisObject)
ctx->throwTypeError();
- return thisObject->value;
+ return thisObject->value.asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4booleanobject_p.h b/src/qml/jsruntime/qv4booleanobject_p.h
index 35ecf25b6f..ef74834a5c 100644
--- a/src/qml/jsruntime/qv4booleanobject_p.h
+++ b/src/qml/jsruntime/qv4booleanobject_p.h
@@ -51,13 +51,11 @@ namespace QV4 {
struct BooleanCtor: FunctionObject
{
+ Q_MANAGED
BooleanCtor(ExecutionContext *scope);
- static Value construct(Managed *, CallData *callData);
- static Value call(Managed *that, CallData *callData);
-
-protected:
- static const ManagedVTable static_vtbl;
+ static ReturnedValue construct(Managed *, CallData *callData);
+ static ReturnedValue call(Managed *that, CallData *callData);
};
struct BooleanPrototype: BooleanObject
@@ -65,8 +63,8 @@ struct BooleanPrototype: BooleanObject
BooleanPrototype(InternalClass *ic): BooleanObject(ic) {}
void init(ExecutionContext *ctx, const Value &ctor);
- static Value method_toString(SimpleCallContext *ctx);
- static Value method_valueOf(SimpleCallContext *ctx);
+ static ReturnedValue method_toString(SimpleCallContext *ctx);
+ static ReturnedValue method_valueOf(SimpleCallContext *ctx);
};
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 1e42a186a0..56701457e4 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -363,6 +363,7 @@ void ExecutionContext::mark()
void ExecutionContext::setProperty(String *name, const Value& value)
{
+ Scope scope(this);
for (ExecutionContext *ctx = this; ctx; ctx = ctx->outer) {
if (ctx->type == Type_WithContext) {
Object *w = static_cast<WithContext *>(ctx)->withObject;
@@ -398,17 +399,21 @@ void ExecutionContext::setProperty(String *name, const Value& value)
}
}
}
- if (strictMode || name->isEqualTo(engine->id_this))
- throwReferenceError(Value::fromString(name));
+ if (strictMode || name->isEqualTo(engine->id_this)) {
+ Scoped<String> n(scope, name);
+ throwReferenceError(n);
+ }
engine->globalObject->put(name, value);
}
-Value ExecutionContext::getProperty(String *name)
+ReturnedValue ExecutionContext::getProperty(String *name)
{
+ Scope scope(this);
+ ScopedValue v(scope);
name->makeIdentifier();
if (name->isEqualTo(engine->id_this))
- return thisObject;
+ return thisObject.asReturnedValue();
bool hasWith = false;
bool hasCatchScope = false;
@@ -417,9 +422,9 @@ Value ExecutionContext::getProperty(String *name)
Object *w = static_cast<WithContext *>(ctx)->withObject;
hasWith = true;
bool hasProperty = false;
- Value v = w->get(name, &hasProperty);
+ v = w->get(name, &hasProperty);
if (hasProperty) {
- return v;
+ return v.asReturnedValue();
}
continue;
}
@@ -428,7 +433,7 @@ Value ExecutionContext::getProperty(String *name)
hasCatchScope = true;
CatchContext *c = static_cast<CatchContext *>(ctx);
if (c->exceptionVarName->isEqualTo(name))
- return c->exceptionValue;
+ return c->exceptionValue.asReturnedValue();
}
else if (ctx->type >= Type_CallContext) {
@@ -437,40 +442,43 @@ Value ExecutionContext::getProperty(String *name)
if (f->needsActivation || hasWith || hasCatchScope) {
for (unsigned int i = 0; i < f->varCount; ++i)
if (f->varList[i]->isEqualTo(name))
- return c->locals[i];
+ return c->locals[i].asReturnedValue();
for (int i = (int)f->formalParameterCount - 1; i >= 0; --i)
if (f->formalParameterList[i]->isEqualTo(name))
- return c->arguments[i];
+ return c->arguments[i].asReturnedValue();
}
if (c->activation) {
bool hasProperty = false;
- Value v = c->activation->get(name, &hasProperty);
+ v = c->activation->get(name, &hasProperty);
if (hasProperty)
- return v;
+ return v.asReturnedValue();
}
if (f->function && f->function->isNamedExpression()
&& name->isEqualTo(f->function->name))
- return Value::fromObject(c->function);
+ return Value::fromObject(c->function).asReturnedValue();
}
else if (ctx->type == Type_GlobalContext) {
GlobalContext *g = static_cast<GlobalContext *>(ctx);
bool hasProperty = false;
- Value v = g->global->get(name, &hasProperty);
+ v = g->global->get(name, &hasProperty);
if (hasProperty)
- return v;
+ return v.asReturnedValue();
}
}
- throwReferenceError(Value::fromString(name));
- return Value::undefinedValue();
+ Scoped<String> n(scope, name);
+ throwReferenceError(n);
+ return Value::undefinedValue().asReturnedValue();
}
-Value ExecutionContext::getPropertyNoThrow(String *name)
+ReturnedValue ExecutionContext::getPropertyNoThrow(String *name)
{
+ Scope scope(this);
+ ScopedValue v(scope);
name->makeIdentifier();
if (name->isEqualTo(engine->id_this))
- return thisObject;
+ return thisObject.asReturnedValue();
bool hasWith = false;
bool hasCatchScope = false;
@@ -479,9 +487,9 @@ Value ExecutionContext::getPropertyNoThrow(String *name)
Object *w = static_cast<WithContext *>(ctx)->withObject;
hasWith = true;
bool hasProperty = false;
- Value v = w->get(name, &hasProperty);
+ v = w->get(name, &hasProperty);
if (hasProperty) {
- return v;
+ return v.asReturnedValue();
}
continue;
}
@@ -490,7 +498,7 @@ Value ExecutionContext::getPropertyNoThrow(String *name)
hasCatchScope = true;
CatchContext *c = static_cast<CatchContext *>(ctx);
if (c->exceptionVarName->isEqualTo(name))
- return c->exceptionValue;
+ return c->exceptionValue.asReturnedValue();
}
else if (ctx->type >= Type_CallContext) {
@@ -499,40 +507,42 @@ Value ExecutionContext::getPropertyNoThrow(String *name)
if (f->needsActivation || hasWith || hasCatchScope) {
for (unsigned int i = 0; i < f->varCount; ++i)
if (f->varList[i]->isEqualTo(name))
- return c->locals[i];
+ return c->locals[i].asReturnedValue();
for (int i = (int)f->formalParameterCount - 1; i >= 0; --i)
if (f->formalParameterList[i]->isEqualTo(name))
- return c->arguments[i];
+ return c->arguments[i].asReturnedValue();
}
if (c->activation) {
bool hasProperty = false;
- Value v = c->activation->get(name, &hasProperty);
+ v = c->activation->get(name, &hasProperty);
if (hasProperty)
- return v;
+ return v.asReturnedValue();
}
if (f->function && f->function->isNamedExpression()
&& name->isEqualTo(f->function->name))
- return Value::fromObject(c->function);
+ return Value::fromObject(c->function).asReturnedValue();
}
else if (ctx->type == Type_GlobalContext) {
GlobalContext *g = static_cast<GlobalContext *>(ctx);
bool hasProperty = false;
- Value v = g->global->get(name, &hasProperty);
+ v = g->global->get(name, &hasProperty);
if (hasProperty)
- return v;
+ return v.asReturnedValue();
}
}
- return Value::undefinedValue();
+ return Value::undefinedValue().asReturnedValue();
}
-Value ExecutionContext::getPropertyAndBase(String *name, Object **base)
+ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Object **base)
{
+ Scope scope(this);
+ ScopedValue v(scope);
*base = 0;
name->makeIdentifier();
if (name->isEqualTo(engine->id_this))
- return thisObject;
+ return thisObject.asReturnedValue();
bool hasWith = false;
bool hasCatchScope = false;
@@ -541,10 +551,10 @@ Value ExecutionContext::getPropertyAndBase(String *name, Object **base)
Object *w = static_cast<WithContext *>(ctx)->withObject;
hasWith = true;
bool hasProperty = false;
- Value v = w->get(name, &hasProperty);
+ v = w->get(name, &hasProperty);
if (hasProperty) {
*base = w;
- return v;
+ return v.asReturnedValue();
}
continue;
}
@@ -553,7 +563,7 @@ Value ExecutionContext::getPropertyAndBase(String *name, Object **base)
hasCatchScope = true;
CatchContext *c = static_cast<CatchContext *>(ctx);
if (c->exceptionVarName->isEqualTo(name))
- return c->exceptionValue;
+ return c->exceptionValue.asReturnedValue();
}
else if (ctx->type >= Type_CallContext) {
@@ -562,102 +572,119 @@ Value ExecutionContext::getPropertyAndBase(String *name, Object **base)
if (f->needsActivation || hasWith || hasCatchScope) {
for (unsigned int i = 0; i < f->varCount; ++i)
if (f->varList[i]->isEqualTo(name))
- return c->locals[i];
+ return c->locals[i].asReturnedValue();
for (int i = (int)f->formalParameterCount - 1; i >= 0; --i)
if (f->formalParameterList[i]->isEqualTo(name))
- return c->arguments[i];
+ return c->arguments[i].asReturnedValue();
}
if (c->activation) {
bool hasProperty = false;
- Value v = c->activation->get(name, &hasProperty);
+ v = c->activation->get(name, &hasProperty);
if (hasProperty) {
if (ctx->type == Type_QmlContext)
*base = c->activation;
- return v;
+ return v.asReturnedValue();
}
}
if (f->function && f->function->isNamedExpression()
&& name->isEqualTo(f->function->name))
- return Value::fromObject(c->function);
+ return Value::fromObject(c->function).asReturnedValue();
}
else if (ctx->type == Type_GlobalContext) {
GlobalContext *g = static_cast<GlobalContext *>(ctx);
bool hasProperty = false;
- Value v = g->global->get(name, &hasProperty);
+ v = g->global->get(name, &hasProperty);
if (hasProperty)
- return v;
+ return v.asReturnedValue();
}
}
- throwReferenceError(Value::fromString(name));
- return Value::undefinedValue();
+ Scoped<String> n(scope, name);
+ throwReferenceError(n);
+ return Value::undefinedValue().asReturnedValue();
}
-void ExecutionContext::throwError(const Value &value)
+void ExecutionContext::throwError(const ValueRef value)
{
- ValueScope scope(this);
- ScopedValue v(scope, value);
- __qmljs_throw(this, v);
+ __qmljs_throw(this, value);
}
void ExecutionContext::throwError(const QString &message)
{
- Value v = Value::fromString(this, message);
- throwError(Value::fromObject(engine->newErrorObject(v)));
+ Scope scope(this);
+ ScopedValue v(scope, Value::fromString(this, message));
+ v = engine->newErrorObject(v);
+ throwError(v);
}
void ExecutionContext::throwSyntaxError(const QString &message, const QString &fileName, int line, int column)
{
- Object *error = engine->newSyntaxErrorObject(message, fileName, line, column);
- throwError(Value::fromObject(error));
+ Scope scope(this);
+ Scoped<Object> error(scope, engine->newSyntaxErrorObject(message, fileName, line, column));
+ throwError(error);
}
void ExecutionContext::throwSyntaxError(const QString &message)
{
- Object *error = engine->newSyntaxErrorObject(message);
- throwError(Value::fromObject(error));
+ Scope scope(this);
+ Scoped<Object> error(scope, engine->newSyntaxErrorObject(message));
+ throwError(error);
}
void ExecutionContext::throwTypeError()
{
- throwError(Value::fromObject(engine->newTypeErrorObject(QStringLiteral("Type error"))));
+ Scope scope(this);
+ Scoped<Object> error(scope, engine->newTypeErrorObject(QStringLiteral("Type error")));
+ throwError(error);
}
void ExecutionContext::throwTypeError(const QString &message)
{
- throwError(Value::fromObject(engine->newTypeErrorObject(message)));
+ Scope scope(this);
+ Scoped<Object> error(scope, engine->newTypeErrorObject(message));
+ throwError(error);
}
void ExecutionContext::throwUnimplemented(const QString &message)
{
- Value v = Value::fromString(this, QStringLiteral("Unimplemented ") + message);
- throwError(Value::fromObject(engine->newErrorObject(v)));
+ Scope scope(this);
+ ScopedValue v(scope, Value::fromString(this, QStringLiteral("Unimplemented ") + message));
+ v = engine->newErrorObject(v);
+ throwError(v);
}
-void ExecutionContext::throwReferenceError(Value value)
+void ExecutionContext::throwReferenceError(const ValueRef value)
{
- String *s = value.toString(this);
+ Scope scope(this);
+ Scoped<String> s(scope, value->toString(this));
QString msg = s->toQString() + QStringLiteral(" is not defined");
- throwError(Value::fromObject(engine->newReferenceErrorObject(msg)));
+ Scoped<Object> error(scope, engine->newReferenceErrorObject(msg));
+ throwError(error);
}
void ExecutionContext::throwReferenceError(const QString &message, const QString &fileName, int line, int column)
{
+ Scope scope(this);
QString msg = message + QStringLiteral(" is not defined");
- throwError(Value::fromObject(engine->newReferenceErrorObject(msg, fileName, line, column)));
+ Scoped<Object> error(scope, engine->newReferenceErrorObject(msg, fileName, line, column));
+ throwError(error);
}
void ExecutionContext::throwRangeError(Value value)
{
- String *s = value.toString(this);
+ Scope scope(this);
+ Scoped<String> s(scope, value.toString(this));
QString msg = s->toQString() + QStringLiteral(" out of range");
- throwError(Value::fromObject(engine->newRangeErrorObject(msg)));
+ Scoped<Object> error(scope, engine->newRangeErrorObject(msg));
+ throwError(error);
}
void ExecutionContext::throwURIError(Value msg)
{
- throwError(Value::fromObject(engine->newURIErrorObject(msg)));
+ Scope scope(this);
+ Scoped<Object> error(scope, engine->newURIErrorObject(msg));
+ throwError(error);
}
void SimpleCallContext::initSimpleCallContext(ExecutionEngine *engine)
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index fe10e33c5e..0c3b189401 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -54,6 +54,7 @@ struct ExecutionEngine;
struct DeclarativeEnvironment;
struct Lookup;
struct Function;
+struct ValueRef;
namespace CompiledData {
struct CompilationUnit;
@@ -129,22 +130,22 @@ struct Q_QML_EXPORT ExecutionContext
void createMutableBinding(String *name, bool deletable);
- void Q_NORETURN throwError(const Value &value);
+ void Q_NORETURN throwError(const QV4::ValueRef value);
void Q_NORETURN throwError(const QString &message);
void Q_NORETURN throwSyntaxError(const QString &message);
void Q_NORETURN throwSyntaxError(const QString &message, const QString &fileName, int line, int column);
void Q_NORETURN throwTypeError();
void Q_NORETURN throwTypeError(const QString &message);
- void Q_NORETURN throwReferenceError(Value value);
+ void Q_NORETURN throwReferenceError(const ValueRef value);
void Q_NORETURN throwReferenceError(const QString &value, const QString &fileName, int line, int column);
void Q_NORETURN throwRangeError(Value value);
void Q_NORETURN throwURIError(Value msg);
void Q_NORETURN throwUnimplemented(const QString &message);
void setProperty(String *name, const Value &value);
- Value getProperty(String *name);
- Value getPropertyNoThrow(String *name);
- Value getPropertyAndBase(String *name, Object **base);
+ ReturnedValue getProperty(String *name);
+ ReturnedValue getPropertyNoThrow(String *name);
+ ReturnedValue getPropertyAndBase(String *name, Object **base);
bool deleteProperty(String *name);
inline Value argument(unsigned int index = 0);
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index 1ef4aec246..76d712656a 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -634,11 +634,14 @@ static double getLocalTZA()
#endif
}
+DEFINE_MANAGED_VTABLE(DateObject);
+
DateObject::DateObject(ExecutionEngine *engine, const QDateTime &date)
: Object(engine->dateClass)
{
+ vtbl = &static_vtbl;
type = Type_DateObject;
- value = Value::fromDouble(date.toMSecsSinceEpoch());
+ value.setDouble(date.isValid() ? date.toMSecsSinceEpoch() : qSNaN());
}
QDateTime DateObject::toQDateTime() const
@@ -654,7 +657,7 @@ DateCtor::DateCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value DateCtor::construct(Managed *m, CallData *callData)
+ReturnedValue DateCtor::construct(Managed *m, CallData *callData)
{
double t = 0;
@@ -662,7 +665,7 @@ Value DateCtor::construct(Managed *m, CallData *callData)
t = currentTime();
else if (callData->argc == 1) {
- ValueScope scope(m->engine());
+ Scope scope(m->engine());
ScopedValue arg(scope, callData->args[0]);
if (DateObject *d = arg->asDateObject())
arg = d->value;
@@ -689,14 +692,13 @@ Value DateCtor::construct(Managed *m, CallData *callData)
t = TimeClip(UTC(t));
}
- Object *o = m->engine()->newDateObject(Value::fromDouble(t));
- return Value::fromObject(o);
+ return Encode(m->engine()->newDateObject(Value::fromDouble(t)));
}
-Value DateCtor::call(Managed *m, CallData *)
+ReturnedValue DateCtor::call(Managed *m, CallData *)
{
double t = currentTime();
- return Value::fromString(m->engine()->current, ToString(t));
+ return Value::fromString(m->engine()->current, ToString(t)).asReturnedValue();
}
void DatePrototype::init(ExecutionContext *ctx, const Value &ctor)
@@ -768,12 +770,12 @@ double DatePrototype::getThisDate(ExecutionContext *ctx)
}
}
-Value DatePrototype::method_parse(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_parse(SimpleCallContext *ctx)
{
- return Value::fromDouble(ParseString(ctx->argument(0).toString(ctx)->toQString()));
+ return Encode(ParseString(ctx->argument(0).toString(ctx)->toQString()));
}
-Value DatePrototype::method_UTC(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_UTC(SimpleCallContext *ctx)
{
const int numArgs = ctx->argumentCount;
if (numArgs >= 2) {
@@ -788,221 +790,221 @@ Value DatePrototype::method_UTC(SimpleCallContext *ctx)
year += 1900;
double t = MakeDate(MakeDay(year, month, day),
MakeTime(hours, mins, secs, ms));
- return Value::fromDouble(TimeClip(t));
+ return Encode(TimeClip(t));
}
- return Value::undefinedValue();
+ return Encode::undefined();
}
-Value DatePrototype::method_now(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_now(SimpleCallContext *ctx)
{
Q_UNUSED(ctx);
double t = currentTime();
- return Value::fromDouble(t);
+ return Encode(t);
}
-Value DatePrototype::method_toString(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_toString(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
- return Value::fromString(ctx, ToString(t));
+ return Value::fromString(ctx, ToString(t)).asReturnedValue();
}
-Value DatePrototype::method_toDateString(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_toDateString(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
- return Value::fromString(ctx, ToDateString(t));
+ return Value::fromString(ctx, ToDateString(t)).asReturnedValue();
}
-Value DatePrototype::method_toTimeString(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_toTimeString(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
- return Value::fromString(ctx, ToTimeString(t));
+ return Value::fromString(ctx, ToTimeString(t)).asReturnedValue();
}
-Value DatePrototype::method_toLocaleString(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_toLocaleString(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
- return Value::fromString(ctx, ToLocaleString(t));
+ return Value::fromString(ctx, ToLocaleString(t)).asReturnedValue();
}
-Value DatePrototype::method_toLocaleDateString(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_toLocaleDateString(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
- return Value::fromString(ctx, ToLocaleDateString(t));
+ return Value::fromString(ctx, ToLocaleDateString(t)).asReturnedValue();
}
-Value DatePrototype::method_toLocaleTimeString(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_toLocaleTimeString(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
- return Value::fromString(ctx, ToLocaleTimeString(t));
+ return Value::fromString(ctx, ToLocaleTimeString(t)).asReturnedValue();
}
-Value DatePrototype::method_valueOf(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_valueOf(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
- return Value::fromDouble(t);
+ return Encode(t);
}
-Value DatePrototype::method_getTime(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_getTime(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
- return Value::fromDouble(t);
+ return Encode(t);
}
-Value DatePrototype::method_getYear(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_getYear(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
if (! std::isnan(t))
t = YearFromTime(LocalTime(t)) - 1900;
- return Value::fromDouble(t);
+ return Encode(t);
}
-Value DatePrototype::method_getFullYear(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_getFullYear(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
if (! std::isnan(t))
t = YearFromTime(LocalTime(t));
- return Value::fromDouble(t);
+ return Encode(t);
}
-Value DatePrototype::method_getUTCFullYear(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_getUTCFullYear(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
if (! std::isnan(t))
t = YearFromTime(t);
- return Value::fromDouble(t);
+ return Encode(t);
}
-Value DatePrototype::method_getMonth(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_getMonth(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
if (! std::isnan(t))
t = MonthFromTime(LocalTime(t));
- return Value::fromDouble(t);
+ return Encode(t);
}
-Value DatePrototype::method_getUTCMonth(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_getUTCMonth(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
if (! std::isnan(t))
t = MonthFromTime(t);
- return Value::fromDouble(t);
+ return Encode(t);
}
-Value DatePrototype::method_getDate(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_getDate(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
if (! std::isnan(t))
t = DateFromTime(LocalTime(t));
- return Value::fromDouble(t);
+ return Encode(t);
}
-Value DatePrototype::method_getUTCDate(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_getUTCDate(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
if (! std::isnan(t))
t = DateFromTime(t);
- return Value::fromDouble(t);
+ return Encode(t);
}
-Value DatePrototype::method_getDay(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_getDay(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
if (! std::isnan(t))
t = WeekDay(LocalTime(t));
- return Value::fromDouble(t);
+ return Encode(t);
}
-Value DatePrototype::method_getUTCDay(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_getUTCDay(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
if (! std::isnan(t))
t = WeekDay(t);
- return Value::fromDouble(t);
+ return Encode(t);
}
-Value DatePrototype::method_getHours(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_getHours(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
if (! std::isnan(t))
t = HourFromTime(LocalTime(t));
- return Value::fromDouble(t);
+ return Encode(t);
}
-Value DatePrototype::method_getUTCHours(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_getUTCHours(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
if (! std::isnan(t))
t = HourFromTime(t);
- return Value::fromDouble(t);
+ return Encode(t);
}
-Value DatePrototype::method_getMinutes(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_getMinutes(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
if (! std::isnan(t))
t = MinFromTime(LocalTime(t));
- return Value::fromDouble(t);
+ return Encode(t);
}
-Value DatePrototype::method_getUTCMinutes(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_getUTCMinutes(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
if (! std::isnan(t))
t = MinFromTime(t);
- return Value::fromDouble(t);
+ return Encode(t);
}
-Value DatePrototype::method_getSeconds(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_getSeconds(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
if (! std::isnan(t))
t = SecFromTime(LocalTime(t));
- return Value::fromDouble(t);
+ return Encode(t);
}
-Value DatePrototype::method_getUTCSeconds(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_getUTCSeconds(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
if (! std::isnan(t))
t = SecFromTime(t);
- return Value::fromDouble(t);
+ return Encode(t);
}
-Value DatePrototype::method_getMilliseconds(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_getMilliseconds(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
if (! std::isnan(t))
t = msFromTime(LocalTime(t));
- return Value::fromDouble(t);
+ return Encode(t);
}
-Value DatePrototype::method_getUTCMilliseconds(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_getUTCMilliseconds(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
if (! std::isnan(t))
t = msFromTime(t);
- return Value::fromDouble(t);
+ return Encode(t);
}
-Value DatePrototype::method_getTimezoneOffset(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_getTimezoneOffset(SimpleCallContext *ctx)
{
double t = getThisDate(ctx);
if (! std::isnan(t))
t = (t - LocalTime(t)) / msPerMinute;
- return Value::fromDouble(t);
+ return Encode(t);
}
-Value DatePrototype::method_setTime(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_setTime(SimpleCallContext *ctx)
{
DateObject *self = ctx->thisObject.asDateObject();
if (!self)
ctx->throwTypeError();
self->value.setDouble(TimeClip(ctx->argument(0).toNumber()));
- return self->value;
+ return self->value.asReturnedValue();
}
-Value DatePrototype::method_setMilliseconds(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_setMilliseconds(SimpleCallContext *ctx)
{
DateObject *self = ctx->thisObject.asDateObject();
if (!self)
@@ -1011,10 +1013,10 @@ Value DatePrototype::method_setMilliseconds(SimpleCallContext *ctx)
double t = LocalTime(self->value.asDouble());
double ms = ctx->argument(0).toNumber();
self->value.setDouble(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)))));
- return self->value;
+ return self->value.asReturnedValue();
}
-Value DatePrototype::method_setUTCMilliseconds(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_setUTCMilliseconds(SimpleCallContext *ctx)
{
DateObject *self = ctx->thisObject.asDateObject();
if (!self)
@@ -1023,10 +1025,10 @@ Value DatePrototype::method_setUTCMilliseconds(SimpleCallContext *ctx)
double t = self->value.asDouble();
double ms = ctx->argument(0).toNumber();
self->value.setDouble(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)))));
- return self->value;
+ return self->value.asReturnedValue();
}
-Value DatePrototype::method_setSeconds(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_setSeconds(SimpleCallContext *ctx)
{
DateObject *self = ctx->thisObject.asDateObject();
if (!self)
@@ -1037,10 +1039,10 @@ Value DatePrototype::method_setSeconds(SimpleCallContext *ctx)
double ms = (ctx->argumentCount < 2) ? msFromTime(t) : ctx->argument(1).toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms))));
self->value.setDouble(t);
- return self->value;
+ return self->value.asReturnedValue();
}
-Value DatePrototype::method_setUTCSeconds(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_setUTCSeconds(SimpleCallContext *ctx)
{
DateObject *self = ctx->thisObject.asDateObject();
if (!self)
@@ -1051,10 +1053,10 @@ Value DatePrototype::method_setUTCSeconds(SimpleCallContext *ctx)
double ms = (ctx->argumentCount < 2) ? msFromTime(t) : ctx->argument(1).toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms))));
self->value.setDouble(t);
- return self->value;
+ return self->value.asReturnedValue();
}
-Value DatePrototype::method_setMinutes(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_setMinutes(SimpleCallContext *ctx)
{
DateObject *self = ctx->thisObject.asDateObject();
if (!self)
@@ -1066,10 +1068,10 @@ Value DatePrototype::method_setMinutes(SimpleCallContext *ctx)
double ms = (ctx->argumentCount < 3) ? msFromTime(t) : ctx->argument(2).toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms))));
self->value.setDouble(t);
- return self->value;
+ return self->value.asReturnedValue();
}
-Value DatePrototype::method_setUTCMinutes(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_setUTCMinutes(SimpleCallContext *ctx)
{
DateObject *self = ctx->thisObject.asDateObject();
if (!self)
@@ -1081,10 +1083,10 @@ Value DatePrototype::method_setUTCMinutes(SimpleCallContext *ctx)
double ms = (ctx->argumentCount < 3) ? msFromTime(t) : ctx->argument(2).toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms))));
self->value.setDouble(t);
- return self->value;
+ return self->value.asReturnedValue();
}
-Value DatePrototype::method_setHours(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_setHours(SimpleCallContext *ctx)
{
DateObject *self = ctx->thisObject.asDateObject();
if (!self)
@@ -1097,10 +1099,10 @@ Value DatePrototype::method_setHours(SimpleCallContext *ctx)
double ms = (ctx->argumentCount < 4) ? msFromTime(t) : ctx->argument(3).toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(hour, min, sec, ms))));
self->value.setDouble(t);
- return self->value;
+ return self->value.asReturnedValue();
}
-Value DatePrototype::method_setUTCHours(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_setUTCHours(SimpleCallContext *ctx)
{
DateObject *self = ctx->thisObject.asDateObject();
if (!self)
@@ -1113,10 +1115,10 @@ Value DatePrototype::method_setUTCHours(SimpleCallContext *ctx)
double ms = (ctx->argumentCount < 4) ? msFromTime(t) : ctx->argument(3).toNumber();
t = TimeClip(UTC(MakeDate(Day(t), MakeTime(hour, min, sec, ms))));
self->value.setDouble(t);
- return self->value;
+ return self->value.asReturnedValue();
}
-Value DatePrototype::method_setDate(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_setDate(SimpleCallContext *ctx)
{
DateObject *self = ctx->thisObject.asDateObject();
if (!self)
@@ -1126,10 +1128,10 @@ Value DatePrototype::method_setDate(SimpleCallContext *ctx)
double date = ctx->argument(0).toNumber();
t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t))));
self->value.setDouble(t);
- return self->value;
+ return self->value.asReturnedValue();
}
-Value DatePrototype::method_setUTCDate(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_setUTCDate(SimpleCallContext *ctx)
{
DateObject *self = ctx->thisObject.asDateObject();
if (!self)
@@ -1139,10 +1141,10 @@ Value DatePrototype::method_setUTCDate(SimpleCallContext *ctx)
double date = ctx->argument(0).toNumber();
t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t))));
self->value.setDouble(t);
- return self->value;
+ return self->value.asReturnedValue();
}
-Value DatePrototype::method_setMonth(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_setMonth(SimpleCallContext *ctx)
{
DateObject *self = ctx->thisObject.asDateObject();
if (!self)
@@ -1153,10 +1155,10 @@ Value DatePrototype::method_setMonth(SimpleCallContext *ctx)
double date = (ctx->argumentCount < 2) ? DateFromTime(t) : ctx->argument(1).toNumber();
t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t))));
self->value.setDouble(t);
- return self->value;
+ return self->value.asReturnedValue();
}
-Value DatePrototype::method_setUTCMonth(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_setUTCMonth(SimpleCallContext *ctx)
{
DateObject *self = ctx->thisObject.asDateObject();
if (!self)
@@ -1167,10 +1169,10 @@ Value DatePrototype::method_setUTCMonth(SimpleCallContext *ctx)
double date = (ctx->argumentCount < 2) ? DateFromTime(t) : ctx->argument(1).toNumber();
t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t))));
self->value.setDouble(t);
- return self->value;
+ return self->value.asReturnedValue();
}
-Value DatePrototype::method_setYear(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_setYear(SimpleCallContext *ctx)
{
DateObject *self = ctx->thisObject.asDateObject();
if (!self)
@@ -1193,10 +1195,10 @@ Value DatePrototype::method_setYear(SimpleCallContext *ctx)
r = TimeClip(r);
}
self->value.setDouble(r);
- return self->value;
+ return self->value.asReturnedValue();
}
-Value DatePrototype::method_setUTCFullYear(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_setUTCFullYear(SimpleCallContext *ctx)
{
DateObject *self = ctx->thisObject.asDateObject();
if (!self)
@@ -1208,10 +1210,10 @@ Value DatePrototype::method_setUTCFullYear(SimpleCallContext *ctx)
double date = (ctx->argumentCount < 3) ? DateFromTime(t) : ctx->argument(2).toNumber();
t = TimeClip(UTC(MakeDate(MakeDay(year, month, date), TimeWithinDay(t))));
self->value.setDouble(t);
- return self->value;
+ return self->value.asReturnedValue();
}
-Value DatePrototype::method_setFullYear(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_setFullYear(SimpleCallContext *ctx)
{
DateObject *self = ctx->thisObject.asDateObject();
if (!self)
@@ -1225,17 +1227,17 @@ Value DatePrototype::method_setFullYear(SimpleCallContext *ctx)
double date = (ctx->argumentCount < 3) ? DateFromTime(t) : ctx->argument(2).toNumber();
t = TimeClip(UTC(MakeDate(MakeDay(year, month, date), TimeWithinDay(t))));
self->value.setDouble(t);
- return self->value;
+ return self->value.asReturnedValue();
}
-Value DatePrototype::method_toUTCString(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_toUTCString(SimpleCallContext *ctx)
{
DateObject *self = ctx->thisObject.asDateObject();
if (!self)
ctx->throwTypeError();
double t = self->value.asDouble();
- return Value::fromString(ctx, ToUTCString(t));
+ return Value::fromString(ctx, ToUTCString(t)).asReturnedValue();
}
static void addZeroPrefixedInt(QString &str, int num, int nDigits)
@@ -1251,7 +1253,7 @@ static void addZeroPrefixedInt(QString &str, int num, int nDigits)
}
}
-Value DatePrototype::method_toISOString(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_toISOString(SimpleCallContext *ctx)
{
DateObject *self = ctx->thisObject.asDateObject();
if (!self)
@@ -1265,7 +1267,7 @@ Value DatePrototype::method_toISOString(SimpleCallContext *ctx)
int year = (int)YearFromTime(t);
if (year < 0 || year > 9999) {
if (qAbs(year) >= 1000000)
- return Value::fromString(ctx, QStringLiteral("Invalid Date"));
+ return Value::fromString(ctx, QStringLiteral("Invalid Date")).asReturnedValue();
result += year < 0 ? '-' : '+';
year = qAbs(year);
addZeroPrefixedInt(result, year, 6);
@@ -1286,24 +1288,25 @@ Value DatePrototype::method_toISOString(SimpleCallContext *ctx)
addZeroPrefixedInt(result, msFromTime(t), 3);
result += 'Z';
- return Value::fromString(ctx, result);
+ return Value::fromString(ctx, result).asReturnedValue();
}
-Value DatePrototype::method_toJSON(SimpleCallContext *ctx)
+ReturnedValue DatePrototype::method_toJSON(SimpleCallContext *ctx)
{
- ValueScope scope(ctx);
+ Scope scope(ctx);
ScopedValue O(scope, __qmljs_to_object(ctx, ValueRef(&ctx->thisObject)));
ScopedValue tv(scope, __qmljs_to_primitive(O, NUMBER_HINT));
if (tv->isNumber() && !std::isfinite(tv->toNumber()))
- return Value::nullValue();
+ return Encode::null();
- FunctionObject *toIso = O->objectValue()->get(ctx->engine->newString(QStringLiteral("toISOString"))).asFunctionObject();
+ ScopedValue v(scope, O->objectValue()->get(ctx->engine->newString(QStringLiteral("toISOString"))));
+ FunctionObject *toIso = v->asFunctionObject();
if (!toIso)
ctx->throwTypeError();
- ScopedCallData callData(ctx->engine, 0);
+ ScopedCallData callData(scope, 0);
callData->thisObject = ctx->thisObject;
return toIso->call(callData);
}
diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h
index 573326adc4..45a9420a41 100644
--- a/src/qml/jsruntime/qv4dateobject_p.h
+++ b/src/qml/jsruntime/qv4dateobject_p.h
@@ -52,25 +52,30 @@ class QDateTime;
namespace QV4 {
struct DateObject: Object {
+ Q_MANAGED
Value value;
- DateObject(ExecutionEngine *engine, const Value &value): Object(engine->dateClass), value(value) { type = Type_DateObject; }
+ DateObject(ExecutionEngine *engine, const Value &value): Object(engine->dateClass), value(value) {
+ vtbl = &static_vtbl;
+ type = Type_DateObject;
+ }
DateObject(ExecutionEngine *engine, const QDateTime &value);
QDateTime toQDateTime() const;
protected:
- DateObject(InternalClass *ic): Object(ic), value(Value::fromDouble(qSNaN())) { type = Type_DateObject; }
+ DateObject(InternalClass *ic): Object(ic), value(Value::fromDouble(qSNaN())) {
+ vtbl = &static_vtbl;
+ type = Type_DateObject;
+ }
};
struct DateCtor: FunctionObject
{
+ Q_MANAGED
DateCtor(ExecutionContext *scope);
- static Value construct(Managed *, CallData *callData);
- static Value call(Managed *that, CallData *);
-
-protected:
- static const ManagedVTable static_vtbl;
+ static ReturnedValue construct(Managed *, CallData *callData);
+ static ReturnedValue call(Managed *that, CallData *);
};
struct DatePrototype: DateObject
@@ -80,55 +85,55 @@ struct DatePrototype: DateObject
static double getThisDate(ExecutionContext *ctx);
- static Value method_parse(SimpleCallContext *ctx);
- static Value method_UTC(SimpleCallContext *ctx);
- static Value method_now(SimpleCallContext *ctx);
-
- static Value method_toString(SimpleCallContext *ctx);
- static Value method_toDateString(SimpleCallContext *ctx);
- static Value method_toTimeString(SimpleCallContext *ctx);
- static Value method_toLocaleString(SimpleCallContext *ctx);
- static Value method_toLocaleDateString(SimpleCallContext *ctx);
- static Value method_toLocaleTimeString(SimpleCallContext *ctx);
- static Value method_valueOf(SimpleCallContext *ctx);
- static Value method_getTime(SimpleCallContext *ctx);
- static Value method_getYear(SimpleCallContext *ctx);
- static Value method_getFullYear(SimpleCallContext *ctx);
- static Value method_getUTCFullYear(SimpleCallContext *ctx);
- static Value method_getMonth(SimpleCallContext *ctx);
- static Value method_getUTCMonth(SimpleCallContext *ctx);
- static Value method_getDate(SimpleCallContext *ctx);
- static Value method_getUTCDate(SimpleCallContext *ctx);
- static Value method_getDay(SimpleCallContext *ctx);
- static Value method_getUTCDay(SimpleCallContext *ctx);
- static Value method_getHours(SimpleCallContext *ctx);
- static Value method_getUTCHours(SimpleCallContext *ctx);
- static Value method_getMinutes(SimpleCallContext *ctx);
- static Value method_getUTCMinutes(SimpleCallContext *ctx);
- static Value method_getSeconds(SimpleCallContext *ctx);
- static Value method_getUTCSeconds(SimpleCallContext *ctx);
- static Value method_getMilliseconds(SimpleCallContext *ctx);
- static Value method_getUTCMilliseconds(SimpleCallContext *ctx);
- static Value method_getTimezoneOffset(SimpleCallContext *ctx);
- static Value method_setTime(SimpleCallContext *ctx);
- static Value method_setMilliseconds(SimpleCallContext *ctx);
- static Value method_setUTCMilliseconds(SimpleCallContext *ctx);
- static Value method_setSeconds(SimpleCallContext *ctx);
- static Value method_setUTCSeconds(SimpleCallContext *ctx);
- static Value method_setMinutes(SimpleCallContext *ctx);
- static Value method_setUTCMinutes(SimpleCallContext *ctx);
- static Value method_setHours(SimpleCallContext *ctx);
- static Value method_setUTCHours(SimpleCallContext *ctx);
- static Value method_setDate(SimpleCallContext *ctx);
- static Value method_setUTCDate(SimpleCallContext *ctx);
- static Value method_setMonth(SimpleCallContext *ctx);
- static Value method_setUTCMonth(SimpleCallContext *ctx);
- static Value method_setYear(SimpleCallContext *ctx);
- static Value method_setFullYear(SimpleCallContext *ctx);
- static Value method_setUTCFullYear(SimpleCallContext *ctx);
- static Value method_toUTCString(SimpleCallContext *ctx);
- static Value method_toISOString(SimpleCallContext *ctx);
- static Value method_toJSON(SimpleCallContext *ctx);
+ static ReturnedValue method_parse(SimpleCallContext *ctx);
+ static ReturnedValue method_UTC(SimpleCallContext *ctx);
+ static ReturnedValue method_now(SimpleCallContext *ctx);
+
+ static ReturnedValue method_toString(SimpleCallContext *ctx);
+ static ReturnedValue method_toDateString(SimpleCallContext *ctx);
+ static ReturnedValue method_toTimeString(SimpleCallContext *ctx);
+ static ReturnedValue method_toLocaleString(SimpleCallContext *ctx);
+ static ReturnedValue method_toLocaleDateString(SimpleCallContext *ctx);
+ static ReturnedValue method_toLocaleTimeString(SimpleCallContext *ctx);
+ static ReturnedValue method_valueOf(SimpleCallContext *ctx);
+ static ReturnedValue method_getTime(SimpleCallContext *ctx);
+ static ReturnedValue method_getYear(SimpleCallContext *ctx);
+ static ReturnedValue method_getFullYear(SimpleCallContext *ctx);
+ static ReturnedValue method_getUTCFullYear(SimpleCallContext *ctx);
+ static ReturnedValue method_getMonth(SimpleCallContext *ctx);
+ static ReturnedValue method_getUTCMonth(SimpleCallContext *ctx);
+ static ReturnedValue method_getDate(SimpleCallContext *ctx);
+ static ReturnedValue method_getUTCDate(SimpleCallContext *ctx);
+ static ReturnedValue method_getDay(SimpleCallContext *ctx);
+ static ReturnedValue method_getUTCDay(SimpleCallContext *ctx);
+ static ReturnedValue method_getHours(SimpleCallContext *ctx);
+ static ReturnedValue method_getUTCHours(SimpleCallContext *ctx);
+ static ReturnedValue method_getMinutes(SimpleCallContext *ctx);
+ static ReturnedValue method_getUTCMinutes(SimpleCallContext *ctx);
+ static ReturnedValue method_getSeconds(SimpleCallContext *ctx);
+ static ReturnedValue method_getUTCSeconds(SimpleCallContext *ctx);
+ static ReturnedValue method_getMilliseconds(SimpleCallContext *ctx);
+ static ReturnedValue method_getUTCMilliseconds(SimpleCallContext *ctx);
+ static ReturnedValue method_getTimezoneOffset(SimpleCallContext *ctx);
+ static ReturnedValue method_setTime(SimpleCallContext *ctx);
+ static ReturnedValue method_setMilliseconds(SimpleCallContext *ctx);
+ static ReturnedValue method_setUTCMilliseconds(SimpleCallContext *ctx);
+ static ReturnedValue method_setSeconds(SimpleCallContext *ctx);
+ static ReturnedValue method_setUTCSeconds(SimpleCallContext *ctx);
+ static ReturnedValue method_setMinutes(SimpleCallContext *ctx);
+ static ReturnedValue method_setUTCMinutes(SimpleCallContext *ctx);
+ static ReturnedValue method_setHours(SimpleCallContext *ctx);
+ static ReturnedValue method_setUTCHours(SimpleCallContext *ctx);
+ static ReturnedValue method_setDate(SimpleCallContext *ctx);
+ static ReturnedValue method_setUTCDate(SimpleCallContext *ctx);
+ static ReturnedValue method_setMonth(SimpleCallContext *ctx);
+ static ReturnedValue method_setUTCMonth(SimpleCallContext *ctx);
+ static ReturnedValue method_setYear(SimpleCallContext *ctx);
+ static ReturnedValue method_setFullYear(SimpleCallContext *ctx);
+ static ReturnedValue method_setUTCFullYear(SimpleCallContext *ctx);
+ static ReturnedValue method_toUTCString(SimpleCallContext *ctx);
+ static ReturnedValue method_toISOString(SimpleCallContext *ctx);
+ static ReturnedValue method_toJSON(SimpleCallContext *ctx);
static void timezoneUpdated();
};
diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp
index 10f22a11b8..34b72e95fb 100644
--- a/src/qml/jsruntime/qv4debugging.cpp
+++ b/src/qml/jsruntime/qv4debugging.cpp
@@ -46,6 +46,8 @@
#include "qv4instr_moth_p.h"
#include <iostream>
+#include <algorithm>
+
using namespace QV4;
using namespace QV4::Debugging;
@@ -207,14 +209,16 @@ static void realDumpValue(QV4::Value v, QV4::ExecutionContext *ctx, std::string
{
using namespace QV4;
using namespace std;
+
+ Scope scope(ctx);
+
cout << prefix << "tag: " << hex << v.tag << dec << endl << prefix << "\t-> ";
switch (v.type()) {
- case Value::Undefined_Type: cout << "Undefined" << endl; return;
- case Value::Null_Type: cout << "Null" << endl; return;
+ case Value::Undefined_Type: cout << "Undefined"; return;
+ case Value::Null_Type: cout << "Null"; return;
case Value::Boolean_Type: cout << "Boolean"; break;
case Value::Integer_Type: cout << "Integer"; break;
- case Value::Object_Type: cout << "Object"; break;
- case Value::String_Type: cout << "String"; break;
+ case Value::Managed_Type: cout << v.managed()->className().toUtf8().data(); break;
default: cout << "UNKNOWN" << endl; return;
}
cout << endl;
@@ -269,11 +273,12 @@ static void realDumpValue(QV4::Value v, QV4::ExecutionContext *ctx, std::string
cout << prefix << "properties:" << endl;
ForEachIteratorObject it(ctx, o);
- for (Value name = it.nextPropertyName(); !name.isNull(); name = it.nextPropertyName()) {
- cout << prefix << "\t\"" << qPrintable(name.stringValue()->toQString()) << "\"" << endl;
+ QV4::ScopedValue name(scope);
+ for (name = it.nextPropertyName(); !name->isNull(); name = it.nextPropertyName()) {
+ cout << prefix << "\t\"" << qPrintable(name->stringValue()->toQString()) << "\"" << endl;
PropertyAttributes attrs;
- Property *d = o->__getOwnProperty__(name.stringValue(), &attrs);
- Value pval = o->getValue(d, attrs);
+ Property *d = o->__getOwnProperty__(name->stringValue(), &attrs);
+ Value pval = Value::fromReturnedValue(o->getValue(d, attrs));
cout << prefix << "\tvalue:" << endl;
realDumpValue(pval, ctx, prefix + "\t");
}
@@ -331,7 +336,7 @@ void Debugger::BreakPoints::add(const QString &fileName, int lineNumber)
QList<int> &lines = (*this)[fileName];
if (!lines.contains(lineNumber)) {
lines.append(lineNumber);
- qSort(lines);
+ std::sort(lines.begin(), lines.end());
}
}
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 638609de37..1a084905ae 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -338,9 +338,9 @@ ExecutionContext *ExecutionEngine::pushGlobalContext()
return current;
}
-FunctionObject *ExecutionEngine::newBuiltinFunction(ExecutionContext *scope, String *name, Value (*code)(SimpleCallContext *))
+FunctionObject *ExecutionEngine::newBuiltinFunction(ExecutionContext *scope, String *name, ReturnedValue (*code)(SimpleCallContext *))
{
- BuiltinFunctionOld *f = new (memoryManager) BuiltinFunctionOld(scope, name, code);
+ BuiltinFunction *f = new (memoryManager) BuiltinFunction(scope, name, code);
return f;
}
@@ -375,25 +375,25 @@ String *ExecutionEngine::newIdentifier(const QString &text)
return identifierTable->insertString(text);
}
-Object *ExecutionEngine::newStringObject(const Value &value)
+Returned<Object> *ExecutionEngine::newStringObject(const Value &value)
{
StringObject *object = new (memoryManager) StringObject(this, value);
- return object;
+ return object->asReturned<Object>();
}
-Object *ExecutionEngine::newNumberObject(const Value &value)
+Returned<Object> *ExecutionEngine::newNumberObject(const Value &value)
{
NumberObject *object = new (memoryManager) NumberObject(this, value);
- return object;
+ return object->asReturned<Object>();
}
-Object *ExecutionEngine::newBooleanObject(const Value &value)
+Returned<Object> *ExecutionEngine::newBooleanObject(const Value &value)
{
Object *object = new (memoryManager) BooleanObject(this, value);
- return object;
+ return object->asReturned<Object>();
}
-ArrayObject *ExecutionEngine::newArrayObject(int count)
+Returned<ArrayObject> *ExecutionEngine::newArrayObject(int count)
{
ArrayObject *object = new (memoryManager) ArrayObject(this);
@@ -402,35 +402,35 @@ ArrayObject *ExecutionEngine::newArrayObject(int count)
object->arrayReserve(count);
object->setArrayLengthUnchecked(count);
}
- return object;
+ return object->asReturned<ArrayObject>();
}
-ArrayObject *ExecutionEngine::newArrayObject(const QStringList &list)
+Returned<ArrayObject> *ExecutionEngine::newArrayObject(const QStringList &list)
{
ArrayObject *object = new (memoryManager) ArrayObject(this, list);
- return object;
+ return object->asReturned<ArrayObject>();
}
-ArrayObject *ExecutionEngine::newArrayObject(InternalClass *ic)
+Returned<ArrayObject> *ExecutionEngine::newArrayObject(InternalClass *ic)
{
ArrayObject *object = new (memoryManager) ArrayObject(ic);
- return object;
+ return object->asReturned<ArrayObject>();
}
-DateObject *ExecutionEngine::newDateObject(const Value &value)
+Returned<DateObject> *ExecutionEngine::newDateObject(const Value &value)
{
DateObject *object = new (memoryManager) DateObject(this, value);
- return object;
+ return object->asReturned<DateObject>();
}
-DateObject *ExecutionEngine::newDateObject(const QDateTime &dt)
+Returned<DateObject> *ExecutionEngine::newDateObject(const QDateTime &dt)
{
DateObject *object = new (memoryManager) DateObject(this, dt);
- return object;
+ return object->asReturned<DateObject>();
}
-RegExpObject *ExecutionEngine::newRegExpObject(const QString &pattern, int flags)
+Returned<RegExpObject> *ExecutionEngine::newRegExpObject(const QString &pattern, int flags)
{
bool global = (flags & QQmlJS::V4IR::RegExp::RegExp_Global);
bool ignoreCase = false;
@@ -443,72 +443,81 @@ RegExpObject *ExecutionEngine::newRegExpObject(const QString &pattern, int flags
return newRegExpObject(RegExp::create(this, pattern, ignoreCase, multiline), global);
}
-RegExpObject *ExecutionEngine::newRegExpObject(RegExp* re, bool global)
+Returned<RegExpObject> *ExecutionEngine::newRegExpObject(RegExp* re, bool global)
{
RegExpObject *object = new (memoryManager) RegExpObject(this, re, global);
- return object;
+ return object->asReturned<RegExpObject>();
}
-RegExpObject *ExecutionEngine::newRegExpObject(const QRegExp &re)
+Returned<RegExpObject> *ExecutionEngine::newRegExpObject(const QRegExp &re)
{
RegExpObject *object = new (memoryManager) RegExpObject(this, re);
- return object;
+ return object->asReturned<RegExpObject>();
}
-Object *ExecutionEngine::newErrorObject(const Value &value)
+Returned<Object> *ExecutionEngine::newErrorObject(const Value &value)
{
ErrorObject *object = new (memoryManager) ErrorObject(errorClass, value);
- return object;
+ return object->asReturned<Object>();
}
-Object *ExecutionEngine::newSyntaxErrorObject(const QString &message)
+Returned<Object> *ExecutionEngine::newSyntaxErrorObject(const QString &message)
{
- return new (memoryManager) SyntaxErrorObject(this, Value::fromString(this, message));
+ Object *error = new (memoryManager) SyntaxErrorObject(this, Value::fromString(this, message));
+ return error->asReturned<Object>();
}
-Object *ExecutionEngine::newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column)
+Returned<Object> *ExecutionEngine::newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column)
{
- return new (memoryManager) SyntaxErrorObject(this, message, fileName, line, column);
+ Object *error = new (memoryManager) SyntaxErrorObject(this, message, fileName, line, column);
+ return error->asReturned<Object>();
}
-Object *ExecutionEngine::newReferenceErrorObject(const QString &message)
+Returned<Object> *ExecutionEngine::newReferenceErrorObject(const QString &message)
{
- return new (memoryManager) ReferenceErrorObject(this, message);
+ Object *o = new (memoryManager) ReferenceErrorObject(this, message);
+ return o->asReturned<Object>();
}
-Object *ExecutionEngine::newReferenceErrorObject(const QString &message, const QString &fileName, int lineNumber, int columnNumber)
+Returned<Object> *ExecutionEngine::newReferenceErrorObject(const QString &message, const QString &fileName, int lineNumber, int columnNumber)
{
- return new (memoryManager) ReferenceErrorObject(this, message, fileName, lineNumber, columnNumber);
+ Object *o = new (memoryManager) ReferenceErrorObject(this, message, fileName, lineNumber, columnNumber);
+ return o->asReturned<Object>();
}
-Object *ExecutionEngine::newTypeErrorObject(const QString &message)
+Returned<Object> *ExecutionEngine::newTypeErrorObject(const QString &message)
{
- return new (memoryManager) TypeErrorObject(this, message);
+ Object *o = new (memoryManager) TypeErrorObject(this, message);
+ return o->asReturned<Object>();
}
-Object *ExecutionEngine::newRangeErrorObject(const QString &message)
+Returned<Object> *ExecutionEngine::newRangeErrorObject(const QString &message)
{
- return new (memoryManager) RangeErrorObject(this, message);
+ Object *o = new (memoryManager) RangeErrorObject(this, message);
+ return o->asReturned<Object>();
}
-Object *ExecutionEngine::newURIErrorObject(Value message)
+Returned<Object> *ExecutionEngine::newURIErrorObject(Value message)
{
- return new (memoryManager) URIErrorObject(this, message);
+ Object *o = new (memoryManager) URIErrorObject(this, message);
+ return o->asReturned<Object>();
}
-Object *ExecutionEngine::newVariantObject(const QVariant &v)
+Returned<Object> *ExecutionEngine::newVariantObject(const QVariant &v)
{
- return new (memoryManager) VariantObject(this, v);
+ Object *o = new (memoryManager) VariantObject(this, v);
+ return o->asReturned<Object>();
}
-Object *ExecutionEngine::newForEachIteratorObject(ExecutionContext *ctx, Object *o)
+Returned<Object> *ExecutionEngine::newForEachIteratorObject(ExecutionContext *ctx, Object *o)
{
- return new (memoryManager) ForEachIteratorObject(ctx, o);
+ Object *obj = new (memoryManager) ForEachIteratorObject(ctx, o);
+ return obj->asReturned<Object>();
}
-Object *ExecutionEngine::qmlContextObject() const
+Returned<Object> *ExecutionEngine::qmlContextObject() const
{
ExecutionContext *ctx = current;
@@ -525,7 +534,7 @@ Object *ExecutionEngine::qmlContextObject() const
if (ctx->type != ExecutionContext::Type_QmlContext)
return 0;
- return static_cast<CallContext *>(ctx)->activation;
+ return static_cast<CallContext *>(ctx)->activation->asReturned<Object>();
}
namespace {
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 1dbffa28aa..297f756033 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -261,7 +261,7 @@ struct Q_QML_EXPORT ExecutionEngine
void pushContext(SimpleCallContext *context);
ExecutionContext *popContext();
- FunctionObject *newBuiltinFunction(ExecutionContext *scope, String *name, Value (*code)(SimpleCallContext *));
+ FunctionObject *newBuiltinFunction(ExecutionContext *scope, String *name, ReturnedValue (*code)(SimpleCallContext *));
BoundFunction *newBoundFunction(ExecutionContext *scope, FunctionObject *target, Value boundThis, const QVector<Value> &boundArgs);
Object *newObject();
@@ -270,35 +270,35 @@ struct Q_QML_EXPORT ExecutionEngine
String *newString(const QString &s);
String *newIdentifier(const QString &text);
- Object *newStringObject(const Value &value);
- Object *newNumberObject(const Value &value);
- Object *newBooleanObject(const Value &value);
+ Returned<Object> *newStringObject(const Value &value);
+ Returned<Object> *newNumberObject(const Value &value);
+ Returned<Object> *newBooleanObject(const Value &value);
- ArrayObject *newArrayObject(int count = 0);
- ArrayObject *newArrayObject(const QStringList &list);
- ArrayObject *newArrayObject(InternalClass *ic);
+ Returned<ArrayObject> *newArrayObject(int count = 0);
+ Returned<ArrayObject> *newArrayObject(const QStringList &list);
+ Returned<ArrayObject> *newArrayObject(InternalClass *ic);
- DateObject *newDateObject(const Value &value);
- DateObject *newDateObject(const QDateTime &dt);
+ Returned<DateObject> *newDateObject(const Value &value);
+ Returned<DateObject> *newDateObject(const QDateTime &dt);
- RegExpObject *newRegExpObject(const QString &pattern, int flags);
- RegExpObject *newRegExpObject(RegExp* re, bool global);
- RegExpObject *newRegExpObject(const QRegExp &re);
+ Returned<RegExpObject> *newRegExpObject(const QString &pattern, int flags);
+ Returned<RegExpObject> *newRegExpObject(RegExp* re, bool global);
+ Returned<RegExpObject> *newRegExpObject(const QRegExp &re);
- Object *newErrorObject(const Value &value);
- Object *newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column);
- Object *newSyntaxErrorObject(const QString &message);
- Object *newReferenceErrorObject(const QString &message);
- Object *newReferenceErrorObject(const QString &message, const QString &fileName, int lineNumber, int columnNumber);
- Object *newTypeErrorObject(const QString &message);
- Object *newRangeErrorObject(const QString &message);
- Object *newURIErrorObject(Value message);
+ Returned<Object> *newErrorObject(const Value &value);
+ Returned<Object> *newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column);
+ Returned<Object> *newSyntaxErrorObject(const QString &message);
+ Returned<Object> *newReferenceErrorObject(const QString &message);
+ Returned<Object> *newReferenceErrorObject(const QString &message, const QString &fileName, int lineNumber, int columnNumber);
+ Returned<Object> *newTypeErrorObject(const QString &message);
+ Returned<Object> *newRangeErrorObject(const QString &message);
+ Returned<Object> *newURIErrorObject(Value message);
- Object *newVariantObject(const QVariant &v);
+ Returned<Object> *newVariantObject(const QVariant &v);
- Object *newForEachIteratorObject(ExecutionContext *ctx, Object *o);
+ Returned<Object> *newForEachIteratorObject(ExecutionContext *ctx, Object *o);
- Object *qmlContextObject() const;
+ Returned<Object> *qmlContextObject() const;
struct StackFrame {
QString source;
diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp
index 6174c9a7f5..987d5083fa 100644
--- a/src/qml/jsruntime/qv4errorobject.cpp
+++ b/src/qml/jsruntime/qv4errorobject.cpp
@@ -127,7 +127,7 @@ ErrorObject::ErrorObject(InternalClass *ic, const QString &message, const QStrin
defineDefaultProperty(ic->engine, QStringLiteral("message"), Value::fromString(ic->engine->newString(message)));
}
-Value ErrorObject::method_get_stack(SimpleCallContext *ctx)
+ReturnedValue ErrorObject::method_get_stack(SimpleCallContext *ctx)
{
ErrorObject *This = ctx->thisObject.asErrorObject();
if (!This)
@@ -148,7 +148,7 @@ Value ErrorObject::method_get_stack(SimpleCallContext *ctx)
}
This->stack = ctx->engine->newString(trace);
}
- return Value::fromString(This->stack);
+ return Value::fromString(This->stack).asReturnedValue();
}
void ErrorObject::markObjects(Managed *that)
@@ -240,12 +240,12 @@ ErrorCtor::ErrorCtor(ExecutionContext *scope, String *name)
vtbl = &static_vtbl;
}
-Value ErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue ErrorCtor::construct(Managed *m, CallData *callData)
{
- return Value::fromObject(m->engine()->newErrorObject(callData->argc ? callData->args[0] : Value::undefinedValue()));
+ return Encode(m->engine()->newErrorObject(callData->argc ? callData->args[0] : Value::undefinedValue()));
}
-Value ErrorCtor::call(Managed *that, CallData *callData)
+ReturnedValue ErrorCtor::call(Managed *that, CallData *callData)
{
return that->construct(callData);
}
@@ -256,9 +256,10 @@ EvalErrorCtor::EvalErrorCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value EvalErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue EvalErrorCtor::construct(Managed *m, CallData *callData)
{
- return Value::fromObject(new (m->engine()->memoryManager) EvalErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue()));
+ return Value::fromObject(new (m->engine()->memoryManager) EvalErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue()))
+ .asReturnedValue();
}
RangeErrorCtor::RangeErrorCtor(ExecutionContext *scope)
@@ -267,9 +268,9 @@ RangeErrorCtor::RangeErrorCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value RangeErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue RangeErrorCtor::construct(Managed *m, CallData *callData)
{
- return Value::fromObject(new (m->engine()->memoryManager) RangeErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue()));
+ return Value::fromObject(new (m->engine()->memoryManager) RangeErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue())).asReturnedValue();
}
ReferenceErrorCtor::ReferenceErrorCtor(ExecutionContext *scope)
@@ -278,9 +279,9 @@ ReferenceErrorCtor::ReferenceErrorCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value ReferenceErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue ReferenceErrorCtor::construct(Managed *m, CallData *callData)
{
- return Value::fromObject(new (m->engine()->memoryManager) ReferenceErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue()));
+ return Value::fromObject(new (m->engine()->memoryManager) ReferenceErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue())).asReturnedValue();
}
SyntaxErrorCtor::SyntaxErrorCtor(ExecutionContext *scope)
@@ -289,9 +290,9 @@ SyntaxErrorCtor::SyntaxErrorCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value SyntaxErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue SyntaxErrorCtor::construct(Managed *m, CallData *callData)
{
- return Value::fromObject(new (m->engine()->memoryManager) SyntaxErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue()));
+ return Value::fromObject(new (m->engine()->memoryManager) SyntaxErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue())).asReturnedValue();
}
TypeErrorCtor::TypeErrorCtor(ExecutionContext *scope)
@@ -300,9 +301,9 @@ TypeErrorCtor::TypeErrorCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value TypeErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue TypeErrorCtor::construct(Managed *m, CallData *callData)
{
- return Value::fromObject(new (m->engine()->memoryManager) TypeErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue()));
+ return Value::fromObject(new (m->engine()->memoryManager) TypeErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue())).asReturnedValue();
}
URIErrorCtor::URIErrorCtor(ExecutionContext *scope)
@@ -311,9 +312,9 @@ URIErrorCtor::URIErrorCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value URIErrorCtor::construct(Managed *m, CallData *callData)
+ReturnedValue URIErrorCtor::construct(Managed *m, CallData *callData)
{
- return Value::fromObject(new (m->engine()->memoryManager) URIErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue()));
+ return Value::fromObject(new (m->engine()->memoryManager) URIErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue())).asReturnedValue();
}
void ErrorPrototype::init(ExecutionEngine *engine, const Value &ctor, Object *obj)
@@ -325,9 +326,9 @@ void ErrorPrototype::init(ExecutionEngine *engine, const Value &ctor, Object *ob
obj->defineDefaultProperty(engine, QStringLiteral("message"), Value::fromString(engine, QString()));
}
-Value ErrorPrototype::method_toString(SimpleCallContext *ctx)
+ReturnedValue ErrorPrototype::method_toString(SimpleCallContext *ctx)
{
- ValueScope scope(ctx);
+ Scope scope(ctx);
Object *o = ctx->thisObject.asObject();
if (!o)
@@ -338,12 +339,12 @@ Value ErrorPrototype::method_toString(SimpleCallContext *ctx)
if (name->isUndefined())
qname = QString::fromLatin1("Error");
else
- qname = __qmljs_to_string(name, ctx).stringValue()->toQString();
+ qname = name->toQString();
ScopedValue message(scope, o->get(ctx->engine->newString(QString::fromLatin1("message"))));
QString qmessage;
if (!message->isUndefined())
- qmessage = __qmljs_to_string(message, ctx).stringValue()->toQString();
+ qmessage = message->toQString();
QString str;
if (qname.isEmpty()) {
@@ -354,5 +355,5 @@ Value ErrorPrototype::method_toString(SimpleCallContext *ctx)
str = qname + QLatin1String(": ") + qmessage;
}
- return Value::fromString(ctx, str);
+ return Value::fromString(ctx, str).asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h
index 1d82bb7ba2..73d9362a6d 100644
--- a/src/qml/jsruntime/qv4errorobject_p.h
+++ b/src/qml/jsruntime/qv4errorobject_p.h
@@ -72,7 +72,7 @@ struct ErrorObject: Object {
ExecutionEngine::StackTrace stackTrace;
String *stack;
- static Value method_get_stack(SimpleCallContext *ctx);
+ static ReturnedValue method_get_stack(SimpleCallContext *ctx);
static void markObjects(Managed *that);
static void destroy(Managed *that) { static_cast<ErrorObject *>(that)->~ErrorObject(); }
};
@@ -93,11 +93,9 @@ struct ReferenceErrorObject: ErrorObject {
};
struct SyntaxErrorObject: ErrorObject {
+ Q_MANAGED
SyntaxErrorObject(ExecutionEngine *engine, const Value &msg);
SyntaxErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber);
-
-protected:
- static const ManagedVTable static_vtbl;
};
struct TypeErrorObject: ErrorObject {
@@ -111,74 +109,60 @@ struct URIErrorObject: ErrorObject {
struct ErrorCtor: FunctionObject
{
+ Q_MANAGED
ErrorCtor(ExecutionContext *scope);
ErrorCtor(ExecutionContext *scope, String *name);
- static Value construct(Managed *, CallData *callData);
- static Value call(Managed *that, CallData *callData);
-
-protected:
- static const ManagedVTable static_vtbl;
+ static ReturnedValue construct(Managed *, CallData *callData);
+ static ReturnedValue call(Managed *that, CallData *callData);
};
struct EvalErrorCtor: ErrorCtor
{
+ Q_MANAGED
EvalErrorCtor(ExecutionContext *scope);
- static Value construct(Managed *m, CallData *callData);
-
-protected:
- static const ManagedVTable static_vtbl;
+ static ReturnedValue construct(Managed *m, CallData *callData);
};
struct RangeErrorCtor: ErrorCtor
{
+ Q_MANAGED
RangeErrorCtor(ExecutionContext *scope);
- static Value construct(Managed *m, CallData *callData);
-
-protected:
- static const ManagedVTable static_vtbl;
+ static ReturnedValue construct(Managed *m, CallData *callData);
};
struct ReferenceErrorCtor: ErrorCtor
{
+ Q_MANAGED
ReferenceErrorCtor(ExecutionContext *scope);
- static Value construct(Managed *m, CallData *callData);
-
-protected:
- static const ManagedVTable static_vtbl;
+ static ReturnedValue construct(Managed *m, CallData *callData);
};
struct SyntaxErrorCtor: ErrorCtor
{
+ Q_MANAGED
SyntaxErrorCtor(ExecutionContext *scope);
- static Value construct(Managed *m, CallData *callData);
-
-protected:
- static const ManagedVTable static_vtbl;
+ static ReturnedValue construct(Managed *m, CallData *callData);
};
struct TypeErrorCtor: ErrorCtor
{
+ Q_MANAGED
TypeErrorCtor(ExecutionContext *scope);
- static Value construct(Managed *m, CallData *callData);
-
-protected:
- static const ManagedVTable static_vtbl;
+ static ReturnedValue construct(Managed *m, CallData *callData);
};
struct URIErrorCtor: ErrorCtor
{
+ Q_MANAGED
URIErrorCtor(ExecutionContext *scope);
- static Value construct(Managed *m, CallData *callData);
-
-protected:
- static const ManagedVTable static_vtbl;
+ static ReturnedValue construct(Managed *m, CallData *callData);
};
@@ -189,7 +173,7 @@ struct ErrorPrototype: ErrorObject
void init(ExecutionEngine *engine, const Value &ctor) { init(engine, ctor, this); }
static void init(ExecutionEngine *engine, const Value &ctor, Object *obj);
- static Value method_toString(SimpleCallContext *ctx);
+ static ReturnedValue method_toString(SimpleCallContext *ctx);
};
struct EvalErrorPrototype: ErrorObject
diff --git a/src/qml/jsruntime/qv4exception.cpp b/src/qml/jsruntime/qv4exception.cpp
index 9f15c27ffc..725a046b71 100644
--- a/src/qml/jsruntime/qv4exception.cpp
+++ b/src/qml/jsruntime/qv4exception.cpp
@@ -87,7 +87,8 @@ void Exception::throwException(ExecutionContext *context, const Value &value)
}
Exception::Exception(ExecutionContext *throwingContext, const Value &exceptionValue)
- : exception(exceptionValue)
+ : e(throwingContext->engine)
+ , exception(exceptionValue)
{
this->throwingContext = throwingContext->engine->current;
accepted = false;
diff --git a/src/qml/jsruntime/qv4exception_p.h b/src/qml/jsruntime/qv4exception_p.h
index 8ba06f57f4..75246fa147 100644
--- a/src/qml/jsruntime/qv4exception_p.h
+++ b/src/qml/jsruntime/qv4exception_p.h
@@ -58,15 +58,17 @@ struct Q_QML_EXPORT Exception {
void partiallyUnwindContext(ExecutionContext *catchingContext);
- Value value() const { return exception; }
+ ReturnedValue value() const { return exception.value().asReturnedValue(); }
ExecutionEngine::StackTrace stackTrace() const { return m_stackTrace; }
+ ExecutionEngine *engine() const { return e; }
private:
void *operator new(size_t, void *p) { return p; }
explicit Exception(ExecutionContext *throwingContext, const Value &exceptionValue);
+ ExecutionEngine *e;
ExecutionContext *throwingContext;
bool accepted;
PersistentValue exception;
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index 9907f3e2ba..a7ae365d21 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE
using namespace QV4;
Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function,
- Value (*codePtr)(ExecutionContext *, const uchar *), quint32 _codeSize)
+ ReturnedValue (*codePtr)(ExecutionContext *, const uchar *), quint32 _codeSize)
: name(0)
, compiledFunction(function)
, compilationUnit(unit)
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index 1fc40d7209..b93eded3f3 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -85,7 +85,7 @@ struct Function {
const CompiledData::Function *compiledFunction;
CompiledData::CompilationUnit *compilationUnit;
- inline Value code(ExecutionContext *ctx, const uchar *data) {
+ inline ReturnedValue code(ExecutionContext *ctx, const uchar *data) {
Value *stack = ctx->engine->jsStackTop;
try {
return codePtr(ctx, data);
@@ -95,7 +95,7 @@ struct Function {
}
}
- Value (*codePtr)(ExecutionContext *, const uchar *);
+ ReturnedValue (*codePtr)(ExecutionContext *, const uchar *);
const uchar *codeData;
quint32 codeSize;
@@ -103,7 +103,7 @@ struct Function {
QVector<String *> locals;
Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function,
- Value (*codePtr)(ExecutionContext *, const uchar *), quint32 _codeSize);
+ ReturnedValue (*codePtr)(ExecutionContext *, const uchar *), quint32 _codeSize);
~Function();
inline QString sourceFile() const { return compilationUnit->fileName(); }
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 252481b7f1..0cf235475e 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -63,6 +63,7 @@
#include <cassert>
#include <typeinfo>
#include <iostream>
+#include <algorithm>
#include "qv4alloca_p.h"
using namespace QV4;
@@ -121,9 +122,10 @@ FunctionObject::~FunctionObject()
function->compilationUnit->deref();
}
-Value FunctionObject::newInstance()
+ReturnedValue FunctionObject::newInstance()
{
- ScopedCallData callData(engine(), 0);
+ Scope scope(engine());
+ ScopedCallData callData(scope, 0);
return construct(callData);
}
@@ -136,7 +138,9 @@ bool FunctionObject::hasInstance(Managed *that, const Value &value)
return false;
ExecutionContext *ctx = f->engine()->current;
- Object *o = f->get(ctx->engine->id_prototype).asObject();
+ QV4::Scope scope(ctx);
+
+ Scoped<Object> o(scope, f->get(ctx->engine->id_prototype));
if (!o)
ctx->throwTypeError();
@@ -145,29 +149,30 @@ bool FunctionObject::hasInstance(Managed *that, const Value &value)
if (! v)
break;
- else if (o == v)
+ else if (o.getPointer() == v)
return true;
}
return false;
}
-Value FunctionObject::construct(Managed *that, CallData *)
+ReturnedValue FunctionObject::construct(Managed *that, CallData *)
{
FunctionObject *f = static_cast<FunctionObject *>(that);
ExecutionEngine *v4 = f->engine();
+ Scope scope(v4);
InternalClass *ic = v4->objectClass;
- Value proto = f->get(v4->id_prototype);
- if (proto.isObject())
- ic = v4->emptyClass->changePrototype(proto.objectValue());
+ 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);
+ return Value::fromObject(obj).asReturnedValue();
}
-Value FunctionObject::call(Managed *, CallData *)
+ReturnedValue FunctionObject::call(Managed *, CallData *)
{
- return Value::undefinedValue();
+ return Encode::undefined();
}
void FunctionObject::markObjects(Managed *that)
@@ -204,7 +209,7 @@ FunctionCtor::FunctionCtor(ExecutionContext *scope)
}
// 15.3.2
-Value FunctionCtor::construct(Managed *that, CallData *callData)
+ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData)
{
FunctionCtor *f = static_cast<FunctionCtor *>(that);
MemoryManager::GCBlocker gcBlocker(f->engine()->memoryManager);
@@ -249,11 +254,11 @@ Value FunctionCtor::construct(Managed *that, CallData *callData)
QV4::CompiledData::CompilationUnit *compilationUnit = isel->compile();
QV4::Function *vmf = compilationUnit->linkToEngine(v4);
- return Value::fromObject(FunctionObject::creatScriptFunction(v4->rootContext, vmf));
+ return Value::fromObject(FunctionObject::creatScriptFunction(v4->rootContext, vmf)).asReturnedValue();
}
// 15.3.1: This is equivalent to new Function(...)
-Value FunctionCtor::call(Managed *that, CallData *callData)
+ReturnedValue FunctionCtor::call(Managed *that, CallData *callData)
{
return construct(that, callData);
}
@@ -277,17 +282,18 @@ void FunctionPrototype::init(ExecutionContext *ctx, const Value &ctor)
}
-Value FunctionPrototype::method_toString(SimpleCallContext *ctx)
+ReturnedValue FunctionPrototype::method_toString(SimpleCallContext *ctx)
{
FunctionObject *fun = ctx->thisObject.asFunctionObject();
if (!fun)
ctx->throwTypeError();
- return Value::fromString(ctx, QStringLiteral("function() { [code] }"));
+ return Value::fromString(ctx, QStringLiteral("function() { [code] }")).asReturnedValue();
}
-Value FunctionPrototype::method_apply(SimpleCallContext *ctx)
+ReturnedValue FunctionPrototype::method_apply(SimpleCallContext *ctx)
{
+ Scope scope(ctx);
FunctionObject *o = ctx->thisObject.asFunctionObject();
if (!o)
ctx->throwTypeError();
@@ -302,18 +308,18 @@ Value FunctionPrototype::method_apply(SimpleCallContext *ctx)
len = 0;
if (!arg.isNullOrUndefined()) {
ctx->throwTypeError();
- return Value::undefinedValue();
+ return Encode::undefined();
}
} else {
len = ArrayPrototype::getLength(ctx, arr);
}
- ScopedCallData callData(ctx->engine, len);
+ ScopedCallData callData(scope, len);
if (len) {
if (arr->protoHasArray() || arr->hasAccessorProperty) {
for (quint32 i = 0; i < len; ++i)
- callData->args[i] = arr->getIndexed(i);
+ callData->args[i] = Value::fromReturnedValue(arr->getIndexed(i));
} else {
int alen = qMin(len, arr->arrayDataLen);
for (quint32 i = 0; i < alen; ++i)
@@ -327,23 +333,25 @@ Value FunctionPrototype::method_apply(SimpleCallContext *ctx)
return o->call(callData);
}
-Value FunctionPrototype::method_call(SimpleCallContext *ctx)
+ReturnedValue FunctionPrototype::method_call(SimpleCallContext *ctx)
{
+ Scope scope(ctx);
Value thisArg = ctx->argument(0);
FunctionObject *o = ctx->thisObject.asFunctionObject();
if (!o)
ctx->throwTypeError();
- ScopedCallData callData(ctx->engine, ctx->argumentCount ? ctx->argumentCount - 1 : 0);
- if (ctx->argumentCount)
- qCopy(ctx->arguments + 1,
- ctx->arguments + ctx->argumentCount, callData->args);
+ ScopedCallData callData(scope, ctx->argumentCount ? ctx->argumentCount - 1 : 0);
+ if (ctx->argumentCount) {
+ std::copy(ctx->arguments + 1,
+ ctx->arguments + ctx->argumentCount, callData->args);
+ }
callData->thisObject = thisArg;
return o->call(callData);
}
-Value FunctionPrototype::method_bind(SimpleCallContext *ctx)
+ReturnedValue FunctionPrototype::method_bind(SimpleCallContext *ctx)
{
FunctionObject *target = ctx->thisObject.asFunctionObject();
if (!target)
@@ -356,14 +364,14 @@ Value FunctionPrototype::method_bind(SimpleCallContext *ctx)
BoundFunction *f = ctx->engine->newBoundFunction(ctx->engine->rootContext, target, boundThis, boundArgs);
- return Value::fromObject(f);
+ return Value::fromObject(f).asReturnedValue();
}
-static Value throwTypeError(SimpleCallContext *ctx)
+static ReturnedValue throwTypeError(SimpleCallContext *ctx)
{
ctx->throwTypeError();
- return Value::undefinedValue();
+ return 0;
}
DEFINE_MANAGED_VTABLE(ScriptFunction);
@@ -401,11 +409,11 @@ ScriptFunction::ScriptFunction(ExecutionContext *scope, Function *function)
}
}
-Value ScriptFunction::construct(Managed *that, CallData *callData)
+ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
{
ScriptFunction *f = static_cast<ScriptFunction *>(that);
- SAVE_JS_STACK(f->scope);
ExecutionEngine *v4 = f->engine();
+ Scope scope(v4);
InternalClass *ic = v4->objectClass;
Value proto = f->memberData[Index_Prototype].value;
@@ -417,27 +425,28 @@ Value ScriptFunction::construct(Managed *that, CallData *callData)
callData->thisObject = Value::fromObject(obj);
ExecutionContext *ctx = context->newCallContext(f, callData);
- Value result;
+ ScopedValue result(scope);
+ SAVE_JS_STACK(f->scope);
try {
result = f->function->code(ctx, f->function->codeData);
} catch (Exception &ex) {
ex.partiallyUnwindContext(context);
throw;
}
+ CHECK_JS_STACK(f->scope);
ctx->engine->popContext();
- CHECK_JS_STACK(f->scope);
- if (result.isObject())
- return result;
- return Value::fromObject(obj);
+ if (result->isObject())
+ return result.asReturnedValue();
+ return Value::fromObject(obj).asReturnedValue();
}
-Value ScriptFunction::call(Managed *that, CallData *callData)
+ReturnedValue ScriptFunction::call(Managed *that, CallData *callData)
{
ScriptFunction *f = static_cast<ScriptFunction *>(that);
- SAVE_JS_STACK(f->scope);
void *stackSpace;
ExecutionContext *context = f->engine()->current;
+ Scope scope(context);
CallContext *ctx = context->newCallContext(f, callData);
if (!f->strictMode && !callData->thisObject.isObject()) {
@@ -448,16 +457,17 @@ Value ScriptFunction::call(Managed *that, CallData *callData)
}
}
- Value result;
+ ScopedValue result(scope);
+ SAVE_JS_STACK(f->scope);
try {
result = f->function->code(ctx, f->function->codeData);
} catch (Exception &ex) {
ex.partiallyUnwindContext(context);
throw;
}
- ctx->engine->popContext();
CHECK_JS_STACK(f->scope);
- return result;
+ ctx->engine->popContext();
+ return result.asReturnedValue();
}
DEFINE_MANAGED_VTABLE(SimpleScriptFunction);
@@ -495,11 +505,11 @@ SimpleScriptFunction::SimpleScriptFunction(ExecutionContext *scope, Function *fu
}
}
-Value SimpleScriptFunction::construct(Managed *that, CallData *callData)
+ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData)
{
SimpleScriptFunction *f = static_cast<SimpleScriptFunction *>(that);
- SAVE_JS_STACK(f->scope);
ExecutionEngine *v4 = f->engine();
+ Scope scope(v4);
InternalClass *ic = v4->objectClass;
Value proto = f->memberData[Index_Prototype].value;
@@ -512,27 +522,28 @@ Value SimpleScriptFunction::construct(Managed *that, CallData *callData)
callData->thisObject = Value::fromObject(obj);
ExecutionContext *ctx = context->newCallContext(stackSpace, f, callData);
- Value result;
+ ScopedValue result(scope);
+ SAVE_JS_STACK(f->scope);
try {
result = f->function->code(ctx, f->function->codeData);
} catch (Exception &ex) {
ex.partiallyUnwindContext(context);
throw;
}
+ CHECK_JS_STACK(f->scope);
ctx->engine->popContext();
- CHECK_JS_STACK(f->scope);
- if (result.isObject())
- return result;
- return Value::fromObject(obj);
+ if (result->isObject())
+ return result.asReturnedValue();
+ return Value::fromObject(obj).asReturnedValue();
}
-Value SimpleScriptFunction::call(Managed *that, CallData *callData)
+ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData)
{
SimpleScriptFunction *f = static_cast<SimpleScriptFunction *>(that);
- SAVE_JS_STACK(f->scope);
void *stackSpace = alloca(requiredMemoryForExecutionContectSimple(f));
ExecutionContext *context = f->engine()->current;
+ Scope scope(context);
ExecutionContext *ctx = context->newCallContext(stackSpace, f, callData);
if (!f->strictMode && !callData->thisObject.isObject()) {
@@ -543,24 +554,25 @@ Value SimpleScriptFunction::call(Managed *that, CallData *callData)
}
}
- Value result;
+ ScopedValue result(scope);
+ SAVE_JS_STACK(f->scope);
try {
result = f->function->code(ctx, f->function->codeData);
} catch (Exception &ex) {
ex.partiallyUnwindContext(context);
throw;
}
- ctx->engine->popContext();
CHECK_JS_STACK(f->scope);
- return result;
+ ctx->engine->popContext();
+ return result.asReturnedValue();
}
-DEFINE_MANAGED_VTABLE(BuiltinFunctionOld);
+DEFINE_MANAGED_VTABLE(BuiltinFunction);
-BuiltinFunctionOld::BuiltinFunctionOld(ExecutionContext *scope, String *name, Value (*code)(SimpleCallContext *))
+BuiltinFunction::BuiltinFunction(ExecutionContext *scope, String *name, ReturnedValue (*code)(SimpleCallContext *))
: FunctionObject(scope, name)
, code(code)
{
@@ -568,16 +580,17 @@ BuiltinFunctionOld::BuiltinFunctionOld(ExecutionContext *scope, String *name, Va
isBuiltinFunction = true;
}
-Value BuiltinFunctionOld::construct(Managed *f, CallData *)
+ReturnedValue BuiltinFunction::construct(Managed *f, CallData *)
{
f->engine()->current->throwTypeError();
- return Value::undefinedValue();
+ return Encode::undefined();
}
-Value BuiltinFunctionOld::call(Managed *that, CallData *callData)
+ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData)
{
- BuiltinFunctionOld *f = static_cast<BuiltinFunctionOld *>(that);
+ BuiltinFunction *f = static_cast<BuiltinFunction *>(that);
ExecutionEngine *v4 = f->engine();
+ Scope scope(v4);
ExecutionContext *context = v4->current;
SimpleCallContext ctx;
@@ -589,7 +602,7 @@ Value BuiltinFunctionOld::call(Managed *that, CallData *callData)
ctx.argumentCount = callData->argc;
v4->pushContext(&ctx);
- Value result;
+ ScopedValue result(scope);
try {
result = f->code(&ctx);
} catch (Exception &ex) {
@@ -598,14 +611,15 @@ Value BuiltinFunctionOld::call(Managed *that, CallData *callData)
}
context->engine->popContext();
- return result;
+ return result.asReturnedValue();
}
-Value IndexedBuiltinFunction::call(Managed *that, CallData *callData)
+ReturnedValue IndexedBuiltinFunction::call(Managed *that, CallData *callData)
{
IndexedBuiltinFunction *f = static_cast<IndexedBuiltinFunction *>(that);
ExecutionEngine *v4 = f->engine();
ExecutionContext *context = v4->current;
+ Scope scope(v4);
SimpleCallContext ctx;
ctx.initSimpleCallContext(f->scope->engine);
@@ -616,7 +630,7 @@ Value IndexedBuiltinFunction::call(Managed *that, CallData *callData)
ctx.argumentCount = callData->argc;
v4->pushContext(&ctx);
- Value result;
+ ScopedValue result(scope);
try {
result = f->code(&ctx, f->index);
} catch (Exception &ex) {
@@ -625,7 +639,7 @@ Value IndexedBuiltinFunction::call(Managed *that, CallData *callData)
}
context->engine->popContext();
- return result;
+ return result.asReturnedValue();
}
DEFINE_MANAGED_VTABLE(IndexedBuiltinFunction);
@@ -639,7 +653,7 @@ BoundFunction::BoundFunction(ExecutionContext *scope, FunctionObject *target, Va
, boundArgs(boundArgs)
{
vtbl = &static_vtbl;
- int len = target->get(scope->engine->id_length).toUInt32();
+ int len = Value::fromReturnedValue(target->get(scope->engine->id_length)).toUInt32();
len -= boundArgs.size();
if (len < 0)
len = 0;
@@ -656,21 +670,23 @@ void BoundFunction::destroy(Managed *that)
static_cast<BoundFunction *>(that)->~BoundFunction();
}
-Value BoundFunction::call(Managed *that, CallData *dd)
+ReturnedValue BoundFunction::call(Managed *that, CallData *dd)
{
BoundFunction *f = static_cast<BoundFunction *>(that);
+ Scope scope(f->scope->engine);
- ScopedCallData callData(f->scope->engine, f->boundArgs.size() + dd->argc);
+ ScopedCallData callData(scope, f->boundArgs.size() + dd->argc);
callData->thisObject = f->boundThis;
memcpy(callData->args, f->boundArgs.constData(), f->boundArgs.size()*sizeof(Value));
memcpy(callData->args + f->boundArgs.size(), dd->args, dd->argc*sizeof(Value));
return f->target->call(callData);
}
-Value BoundFunction::construct(Managed *that, CallData *dd)
+ReturnedValue BoundFunction::construct(Managed *that, CallData *dd)
{
BoundFunction *f = static_cast<BoundFunction *>(that);
- ScopedCallData callData(f->scope->engine, f->boundArgs.size() + dd->argc);
+ Scope scope(f->scope->engine);
+ ScopedCallData callData(scope, f->boundArgs.size() + dd->argc);
memcpy(callData->args, f->boundArgs.constData(), f->boundArgs.size()*sizeof(Value));
memcpy(callData->args + f->boundArgs.size(), dd->args, dd->argc*sizeof(Value));
return f->target->construct(callData);
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index d694d28462..333b95ad74 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -93,6 +93,7 @@ struct InternalClass;
struct Lookup;
struct Q_QML_EXPORT FunctionObject: Object {
+ Q_MANAGED
// Used with Managed::subType
enum FunctionType {
RegularFunction = 0,
@@ -115,23 +116,26 @@ struct Q_QML_EXPORT FunctionObject: Object {
FunctionObject(ExecutionContext *scope, String *name = 0, bool createProto = false);
~FunctionObject();
- Value newInstance();
+ ReturnedValue newInstance();
- static Value construct(Managed *that, CallData *);
- static Value call(Managed *that, CallData *d);
- inline Value construct(CallData *callData) {
+ static ReturnedValue construct(Managed *that, CallData *);
+ static ReturnedValue call(Managed *that, CallData *d);
+ inline ReturnedValue construct(CallData *callData) {
return vtbl->construct(this, callData);
}
- inline Value call(CallData *callData) {
+ inline ReturnedValue call(CallData *callData) {
return vtbl->call(this, callData);
}
+ static FunctionObject *cast(const Value &v) {
+ return v.asFunctionObject();
+ }
+
static FunctionObject *creatScriptFunction(ExecutionContext *scope, Function *function);
protected:
FunctionObject(InternalClass *ic);
- static const ManagedVTable static_vtbl;
static void markObjects(Managed *that);
static bool hasInstance(Managed *that, const Value &value);
static void destroy(Managed *that)
@@ -140,13 +144,11 @@ protected:
struct FunctionCtor: FunctionObject
{
+ Q_MANAGED
FunctionCtor(ExecutionContext *scope);
- static Value construct(Managed *that, CallData *callData);
- static Value call(Managed *that, CallData *callData);
-
-protected:
- static const ManagedVTable static_vtbl;
+ static ReturnedValue construct(Managed *that, CallData *callData);
+ static ReturnedValue call(Managed *that, CallData *callData);
};
struct FunctionPrototype: FunctionObject
@@ -154,32 +156,30 @@ struct FunctionPrototype: FunctionObject
FunctionPrototype(InternalClass *ic);
void init(ExecutionContext *ctx, const Value &ctor);
- static Value method_toString(SimpleCallContext *ctx);
- static Value method_apply(SimpleCallContext *ctx);
- static Value method_call(SimpleCallContext *ctx);
- static Value method_bind(SimpleCallContext *ctx);
+ static ReturnedValue method_toString(SimpleCallContext *ctx);
+ static ReturnedValue method_apply(SimpleCallContext *ctx);
+ static ReturnedValue method_call(SimpleCallContext *ctx);
+ static ReturnedValue method_bind(SimpleCallContext *ctx);
};
-struct BuiltinFunctionOld: FunctionObject {
- Value (*code)(SimpleCallContext *);
-
- BuiltinFunctionOld(ExecutionContext *scope, String *name, Value (*code)(SimpleCallContext *));
+struct BuiltinFunction: FunctionObject {
+ Q_MANAGED
+ ReturnedValue (*code)(SimpleCallContext *);
- static Value construct(Managed *, CallData *);
- static Value call(Managed *that, CallData *callData);
+ BuiltinFunction(ExecutionContext *scope, String *name, ReturnedValue (*code)(SimpleCallContext *));
-protected:
- static const ManagedVTable static_vtbl;
+ static ReturnedValue construct(Managed *, CallData *);
+ static ReturnedValue call(Managed *that, CallData *callData);
};
struct IndexedBuiltinFunction: FunctionObject
{
Q_MANAGED
- Value (*code)(SimpleCallContext *ctx, uint index);
+ ReturnedValue (*code)(SimpleCallContext *ctx, uint index);
uint index;
- IndexedBuiltinFunction(ExecutionContext *scope, uint index, Value (*code)(SimpleCallContext *ctx, uint index))
+ IndexedBuiltinFunction(ExecutionContext *scope, uint index, ReturnedValue (*code)(SimpleCallContext *ctx, uint index))
: FunctionObject(scope, /*name*/0)
, code(code)
, index(index)
@@ -188,37 +188,34 @@ struct IndexedBuiltinFunction: FunctionObject
isBuiltinFunction = true;
}
- static Value construct(Managed *m, CallData *)
+ static ReturnedValue construct(Managed *m, CallData *)
{
m->engine()->current->throwTypeError();
- return Value::undefinedValue();
+ return Value::undefinedValue().asReturnedValue();
}
- static Value call(Managed *that, CallData *callData);
+ static ReturnedValue call(Managed *that, CallData *callData);
};
struct ScriptFunction: FunctionObject {
+ Q_MANAGED
ScriptFunction(ExecutionContext *scope, Function *function);
- static Value construct(Managed *, CallData *callData);
- static Value call(Managed *that, CallData *callData);
-
-protected:
- static const ManagedVTable static_vtbl;
+ static ReturnedValue construct(Managed *, CallData *callData);
+ static ReturnedValue call(Managed *that, CallData *callData);
};
struct SimpleScriptFunction: FunctionObject {
+ Q_MANAGED
SimpleScriptFunction(ExecutionContext *scope, Function *function);
- static Value construct(Managed *, CallData *callData);
- static Value call(Managed *that, CallData *callData);
-
-protected:
- static const ManagedVTable static_vtbl;
+ static ReturnedValue construct(Managed *, CallData *callData);
+ static ReturnedValue call(Managed *that, CallData *callData);
};
struct BoundFunction: FunctionObject {
+ Q_MANAGED
FunctionObject *target;
Value boundThis;
QVector<Value> boundArgs;
@@ -227,10 +224,9 @@ struct BoundFunction: FunctionObject {
~BoundFunction() {}
- static Value construct(Managed *, CallData *d);
- static Value call(Managed *that, CallData *dd);
+ static ReturnedValue construct(Managed *, CallData *d);
+ static ReturnedValue call(Managed *that, CallData *dd);
- static const ManagedVTable static_vtbl;
static void destroy(Managed *);
static void markObjects(Managed *that);
static bool hasInstance(Managed *that, const Value &value);
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index 4f70275c25..f610811ddf 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -98,6 +98,12 @@ struct Lookup;
struct ExecutionEngine;
struct QObjectWrapper;
+// ReturnedValue is used to return values from runtime methods
+// the type has to be a primitive type (no struct or union), so that the compiler
+// 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;
+
namespace Global {
enum {
ReservedArgumentCount = 6
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index 9764a7930f..e0cbee11ca 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -354,14 +354,15 @@ EvalFunction::EvalFunction(ExecutionContext *scope)
defineReadonlyProperty(scope->engine->id_length, Value::fromInt32(1));
}
-Value EvalFunction::evalCall(Value /*thisObject*/, Value *args, int argc, bool directCall)
+ReturnedValue EvalFunction::evalCall(Value /*thisObject*/, Value *args, int argc, bool directCall)
{
if (argc < 1)
- return Value::undefinedValue();
+ return Encode::undefined();
ExecutionContext *parentContext = engine()->current;
ExecutionEngine *engine = parentContext->engine;
ExecutionContext *ctx = parentContext;
+ Scope scope(ctx);
if (!directCall) {
// the context for eval should be the global scope, so we fake a root
@@ -370,7 +371,7 @@ Value EvalFunction::evalCall(Value /*thisObject*/, Value *args, int argc, bool d
}
if (!args[0].isString())
- return args[0];
+ return args[0].asReturnedValue();
const QString code = args[0].stringValue()->toQString();
bool inheritContext = !ctx->strictMode;
@@ -382,7 +383,7 @@ Value EvalFunction::evalCall(Value /*thisObject*/, Value *args, int argc, bool d
Function *function = script.function();
if (!function)
- return Value::undefinedValue();
+ return Encode::undefined();
strictMode = function->isStrict() || (ctx->strictMode);
@@ -391,7 +392,7 @@ Value EvalFunction::evalCall(Value /*thisObject*/, Value *args, int argc, bool d
if (strictMode) {
FunctionObject *e = FunctionObject::creatScriptFunction(ctx, function);
- ScopedCallData callData(ctx->engine, 0);
+ ScopedCallData callData(scope, 0);
callData->thisObject = ctx->thisObject;
return e->call(callData);
}
@@ -412,7 +413,7 @@ Value EvalFunction::evalCall(Value /*thisObject*/, Value *args, int argc, bool d
ctx->compiledFunction = function->compiledFunction;
ctx->runtimeStrings = function->compilationUnit->runtimeStrings;
- Value result = Value::undefinedValue();
+ ScopedValue result(scope);
try {
result = function->code(ctx, function->codeData);
} catch (Exception &ex) {
@@ -435,11 +436,11 @@ Value EvalFunction::evalCall(Value /*thisObject*/, Value *args, int argc, bool d
while (engine->current != parentContext)
engine->popContext();
- return result;
+ return result.asReturnedValue();
}
-Value EvalFunction::call(Managed *that, CallData *callData)
+ReturnedValue EvalFunction::call(Managed *that, CallData *callData)
{
// indirect call
// ### const_cast
@@ -464,7 +465,7 @@ static inline int toInt(const QChar &qc, int R)
}
// parseInt [15.1.2.2]
-Value GlobalFunctions::method_parseInt(SimpleCallContext *context)
+ReturnedValue GlobalFunctions::method_parseInt(SimpleCallContext *context)
{
Value string = context->argument(0);
Value radix = context->argument(1);
@@ -486,7 +487,7 @@ Value GlobalFunctions::method_parseInt(SimpleCallContext *context)
bool stripPrefix = true; // 7
if (R) { // 8
if (R < 2 || R > 36)
- return Value::fromDouble(std::numeric_limits<double>::quiet_NaN()); // 8a
+ return Encode(std::numeric_limits<double>::quiet_NaN()); // 8a
if (R != 16)
stripPrefix = false; // 8b
} else { // 9
@@ -503,13 +504,13 @@ Value GlobalFunctions::method_parseInt(SimpleCallContext *context)
// 11: Z is progressively built below
// 13: this is handled by the toInt function
if (pos == end) // 12
- return Value::fromDouble(std::numeric_limits<double>::quiet_NaN());
+ return Encode(std::numeric_limits<double>::quiet_NaN());
bool overflow = false;
qint64 v_overflow;
unsigned overflow_digit_count = 0;
int d = toInt(*pos++, R);
if (d == -1)
- return Value::fromDouble(std::numeric_limits<double>::quiet_NaN());
+ return Encode(std::numeric_limits<double>::quiet_NaN());
qint64 v = d;
while (pos != end) {
d = toInt(*pos++, R);
@@ -536,14 +537,14 @@ Value GlobalFunctions::method_parseInt(SimpleCallContext *context)
if (overflow) {
double result = (double) v_overflow * pow(R, overflow_digit_count);
result += v;
- return Value::fromDouble(sign * result);
+ return Encode(sign * result);
} else {
- return Value::fromDouble(sign * (double) v); // 15
+ return Encode(sign * (double) v); // 15
}
}
// parseFloat [15.1.2.3]
-Value GlobalFunctions::method_parseFloat(SimpleCallContext *context)
+ReturnedValue GlobalFunctions::method_parseFloat(SimpleCallContext *context)
{
Value string = context->argument(0);
@@ -554,47 +555,47 @@ Value GlobalFunctions::method_parseFloat(SimpleCallContext *context)
// 4:
if (trimmed.startsWith(QLatin1String("Infinity"))
|| trimmed.startsWith(QLatin1String("+Infinity")))
- return Value::fromDouble(Q_INFINITY);
+ return Encode(Q_INFINITY);
if (trimmed.startsWith("-Infinity"))
- return Value::fromDouble(-Q_INFINITY);
+ return Encode(-Q_INFINITY);
QByteArray ba = trimmed.toLatin1();
bool ok;
const char *begin = ba.constData();
const char *end = 0;
double d = qstrtod(begin, &end, &ok);
if (end - begin == 0)
- return Value::fromDouble(std::numeric_limits<double>::quiet_NaN()); // 3
+ return Encode(std::numeric_limits<double>::quiet_NaN()); // 3
else
- return Value::fromDouble(d);
+ return Encode(d);
}
/// isNaN [15.1.2.4]
-Value GlobalFunctions::method_isNaN(SimpleCallContext *context)
+ReturnedValue GlobalFunctions::method_isNaN(SimpleCallContext *context)
{
const Value &v = context->argument(0);
if (v.integerCompatible())
- return Value::fromBoolean(false);
+ return Encode(false);
double d = v.toNumber();
- return Value::fromBoolean(std::isnan(d));
+ return Encode((bool)std::isnan(d));
}
/// isFinite [15.1.2.5]
-Value GlobalFunctions::method_isFinite(SimpleCallContext *context)
+ReturnedValue GlobalFunctions::method_isFinite(SimpleCallContext *context)
{
const Value &v = context->argument(0);
if (v.integerCompatible())
- return Value::fromBoolean(true);
+ return Encode(true);
double d = v.toNumber();
- return Value::fromBoolean(std::isfinite(d));
+ return Encode((bool)std::isfinite(d));
}
/// decodeURI [15.1.3.1]
-Value GlobalFunctions::method_decodeURI(SimpleCallContext *context)
+ReturnedValue GlobalFunctions::method_decodeURI(SimpleCallContext *context)
{
if (context->argumentCount == 0)
- return Value::undefinedValue();
+ return Encode::undefined();
QString uriString = context->arguments[0].toString(context)->toQString();
bool ok;
@@ -602,14 +603,14 @@ Value GlobalFunctions::method_decodeURI(SimpleCallContext *context)
if (!ok)
context->throwURIError(Value::fromString(context, QStringLiteral("malformed URI sequence")));
- return Value::fromString(context, out);
+ return Value::fromString(context, out).asReturnedValue();
}
/// decodeURIComponent [15.1.3.2]
-Value GlobalFunctions::method_decodeURIComponent(SimpleCallContext *context)
+ReturnedValue GlobalFunctions::method_decodeURIComponent(SimpleCallContext *context)
{
if (context->argumentCount == 0)
- return Value::undefinedValue();
+ return Encode::undefined();
QString uriString = context->arguments[0].toString(context)->toQString();
bool ok;
@@ -617,14 +618,14 @@ Value GlobalFunctions::method_decodeURIComponent(SimpleCallContext *context)
if (!ok)
context->throwURIError(Value::fromString(context, QStringLiteral("malformed URI sequence")));
- return Value::fromString(context, out);
+ return Value::fromString(context, out).asReturnedValue();
}
/// encodeURI [15.1.3.3]
-Value GlobalFunctions::method_encodeURI(SimpleCallContext *context)
+ReturnedValue GlobalFunctions::method_encodeURI(SimpleCallContext *context)
{
if (context->argumentCount == 0)
- return Value::undefinedValue();
+ return Encode::undefined();
QString uriString = context->arguments[0].toString(context)->toQString();
bool ok;
@@ -632,14 +633,14 @@ Value GlobalFunctions::method_encodeURI(SimpleCallContext *context)
if (!ok)
context->throwURIError(Value::fromString(context, QStringLiteral("malformed URI sequence")));
- return Value::fromString(context, out);
+ return Value::fromString(context, out).asReturnedValue();
}
/// encodeURIComponent [15.1.3.4]
-Value GlobalFunctions::method_encodeURIComponent(SimpleCallContext *context)
+ReturnedValue GlobalFunctions::method_encodeURIComponent(SimpleCallContext *context)
{
if (context->argumentCount == 0)
- return Value::undefinedValue();
+ return Encode::undefined();
QString uriString = context->arguments[0].toString(context)->toQString();
bool ok;
@@ -647,23 +648,23 @@ Value GlobalFunctions::method_encodeURIComponent(SimpleCallContext *context)
if (!ok)
context->throwURIError(Value::fromString(context, QStringLiteral("malformed URI sequence")));
- return Value::fromString(context, out);
+ return Value::fromString(context, out).asReturnedValue();
}
-Value GlobalFunctions::method_escape(SimpleCallContext *context)
+ReturnedValue GlobalFunctions::method_escape(SimpleCallContext *context)
{
if (!context->argumentCount)
- return Value::fromString(context, QStringLiteral("undefined"));
+ return Value::fromString(context, QStringLiteral("undefined")).asReturnedValue();
QString str = context->argument(0).toString(context)->toQString();
- return Value::fromString(context, escape(str));
+ return Value::fromString(context, escape(str)).asReturnedValue();
}
-Value GlobalFunctions::method_unescape(SimpleCallContext *context)
+ReturnedValue GlobalFunctions::method_unescape(SimpleCallContext *context)
{
if (!context->argumentCount)
- return Value::fromString(context, QStringLiteral("undefined"));
+ return Value::fromString(context, QStringLiteral("undefined")).asReturnedValue();
QString str = context->argument(0).toString(context)->toQString();
- return Value::fromString(context, unescape(str));
+ return Value::fromString(context, unescape(str)).asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4globalobject_p.h b/src/qml/jsruntime/qv4globalobject_p.h
index b777bf8915..90b3395baa 100644
--- a/src/qml/jsruntime/qv4globalobject_p.h
+++ b/src/qml/jsruntime/qv4globalobject_p.h
@@ -50,29 +50,27 @@ namespace QV4 {
struct Q_QML_EXPORT EvalFunction : FunctionObject
{
+ Q_MANAGED
EvalFunction(ExecutionContext *scope);
- Value evalCall(Value thisObject, Value *args, int argc, bool directCall);
+ ReturnedValue evalCall(Value thisObject, Value *args, int argc, bool directCall);
using Managed::construct;
- static Value call(Managed *that, CallData *callData);
-
-protected:
- static const ManagedVTable static_vtbl;
+ static ReturnedValue call(Managed *that, CallData *callData);
};
struct GlobalFunctions
{
- static Value method_parseInt(SimpleCallContext *context);
- static Value method_parseFloat(SimpleCallContext *context);
- static Value method_isNaN(SimpleCallContext *context);
- static Value method_isFinite(SimpleCallContext *context);
- static Value method_decodeURI(SimpleCallContext *context);
- static Value method_decodeURIComponent(SimpleCallContext *context);
- static Value method_encodeURI(SimpleCallContext *context);
- static Value method_encodeURIComponent(SimpleCallContext *context);
- static Value method_escape(SimpleCallContext *context);
- static Value method_unescape(SimpleCallContext *context);
+ 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_decodeURI(SimpleCallContext *context);
+ static ReturnedValue method_decodeURIComponent(SimpleCallContext *context);
+ static ReturnedValue method_encodeURI(SimpleCallContext *context);
+ static ReturnedValue method_encodeURIComponent(SimpleCallContext *context);
+ static ReturnedValue method_escape(SimpleCallContext *context);
+ static ReturnedValue method_unescape(SimpleCallContext *context);
};
}
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index 647cc7d2cb..740bb406f3 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -82,7 +82,7 @@ QV4Include::~QV4Include()
delete m_reply; m_reply = 0;
}
-QV4::Value QV4Include::resultValue(QV4::ExecutionEngine *v4, Status status)
+QV4::ReturnedValue QV4Include::resultValue(QV4::ExecutionEngine *v4, Status status)
{
// XXX It seems inefficient to create this object from scratch each time.
@@ -94,7 +94,7 @@ QV4::Value QV4Include::resultValue(QV4::ExecutionEngine *v4, Status status)
o->put(v4->newString("status"), QV4::Value::fromInt32(status));
- return QV4::Value::fromObject(o);
+ return QV4::Value::fromObject(o).asReturnedValue();
}
void QV4Include::callback(const QV4::Value &callback, const QV4::Value &status)
@@ -104,8 +104,9 @@ void QV4Include::callback(const QV4::Value &callback, const QV4::Value &status)
return;
QV4::ExecutionContext *ctx = f->engine()->current;
+ QV4::Scope scope(ctx);
try {
- QV4::ScopedCallData callData(ctx->engine, 1);
+ QV4::ScopedCallData callData(scope, 1);
callData->thisObject = QV4::Value::fromObject(f->engine()->globalObject);
callData->args[0] = status;
f->call(callData);
@@ -114,9 +115,9 @@ void QV4Include::callback(const QV4::Value &callback, const QV4::Value &status)
}
}
-QV4::Value QV4Include::result()
+QV4::ReturnedValue QV4Include::result()
{
- return m_resultObject.value();
+ return m_resultObject.value().asReturnedValue();
}
#define INCLUDE_MAXIMUM_REDIRECT_RECURSION 15
@@ -148,7 +149,8 @@ void QV4Include::finished()
QV4::Script script(v4, m_qmlglobal.value().asObject(), code, m_url.toString());
QV4::ExecutionContext *ctx = v4->current;
- QV4::Object *o = m_resultObject.value().asObject();
+ QV4::Scope scope(v4);
+ QV4::Scoped<QV4::Object> o(scope, m_resultObject.value());
try {
script.parse();
script.run();
@@ -156,7 +158,8 @@ void QV4Include::finished()
} catch (QV4::Exception &e) {
e.accept(ctx);
o->put(v4->newString("status"), QV4::Value::fromInt32(Exception));
- o->put(v4->newString("exception"), e.value());
+ QV4::ScopedValue ex(scope, e.value());
+ o->put(v4->newString("exception"), ex);
}
} else {
m_resultObject.value().asObject()->put(v4->newString("status"), QV4::Value::fromInt32(NetworkError));
@@ -171,19 +174,20 @@ void QV4Include::finished()
/*
Documented in qv8engine.cpp
*/
-QV4::Value QV4Include::include(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QV4Include::method_include(QV4::SimpleCallContext *ctx)
{
if (!ctx->argumentCount)
- return QV4::Value::undefinedValue();
+ return QV4::Encode::undefined();
QV4::ExecutionEngine *v4 = ctx->engine;
+ QV4::Scope scope(v4);
QV8Engine *engine = v4->v8Engine;
QQmlContextData *context = QV4::QmlContextWrapper::callingContext(v4);
if (!context || !context->isJSContext)
V4THROW_ERROR("Qt.include(): Can only be called from JavaScript files");
- QUrl url(ctx->engine->resolvedUrl(ctx->arguments[0].toQString()));
+ QUrl url(ctx->engine->resolvedUrl(ctx->arguments[0].toQStringNoThrow()));
QV4::Value callbackFunction = QV4::Value::undefinedValue();
if (ctx->argumentCount >= 2 && ctx->arguments[1].asFunctionObject())
@@ -191,12 +195,12 @@ QV4::Value QV4Include::include(QV4::SimpleCallContext *ctx)
QString localFile = QQmlFile::urlToLocalFileOrQrc(url);
- QV4::Value result = QV4::Value::undefinedValue();
+ QV4::ScopedValue result(scope);
+ QV4::Scoped<QV4::Object> qmlcontextobject(scope, v4->qmlContextObject());
if (localFile.isEmpty()) {
-
QV4Include *i = new QV4Include(url, engine, context,
- QV4::Value::fromObject(v4->qmlContextObject()),
+ qmlcontextobject.asValue(),
callbackFunction);
result = i->result();
@@ -209,8 +213,7 @@ QV4::Value QV4Include::include(QV4::SimpleCallContext *ctx)
QString code = QString::fromUtf8(data);
QQmlScript::Parser::extractPragmas(code);
- QV4::Object *qmlglobal = v4->qmlContextObject();
- QV4::Script script(v4, qmlglobal, code, url.toString());
+ QV4::Script script(v4, qmlcontextobject.getPointer(), code, url.toString());
QV4::ExecutionContext *ctx = v4->current;
try {
@@ -220,7 +223,8 @@ QV4::Value QV4Include::include(QV4::SimpleCallContext *ctx)
} catch (QV4::Exception &e) {
e.accept(ctx);
result = resultValue(v4, Exception);
- result.asObject()->put(v4->newString("exception"), e.value());
+ QV4::ScopedValue ex(scope, e.value());
+ result->asObject()->put(v4->newString("exception"), ex);
}
} else {
result = resultValue(v4, NetworkError);
@@ -229,7 +233,7 @@ QV4::Value QV4Include::include(QV4::SimpleCallContext *ctx)
callback(callbackFunction, result);
}
- return result;
+ return result.asReturnedValue();
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4include_p.h b/src/qml/jsruntime/qv4include_p.h
index d6bbcd1a60..6e299bce91 100644
--- a/src/qml/jsruntime/qv4include_p.h
+++ b/src/qml/jsruntime/qv4include_p.h
@@ -78,9 +78,9 @@ public:
Exception = 3
};
- static QV4::Value include(QV4::SimpleCallContext *ctx);
+ static QV4::ReturnedValue method_include(QV4::SimpleCallContext *ctx);
-private slots:
+private Q_SLOTS:
void finished();
private:
@@ -88,9 +88,9 @@ private:
const QV4::Value &qmlglobal, const QV4::Value &callback);
~QV4Include();
- QV4::Value result();
+ QV4::ReturnedValue result();
- static QV4::Value resultValue(QV4::ExecutionEngine *v4, Status status = Loading);
+ static QV4::ReturnedValue resultValue(QV4::ExecutionEngine *v4, Status status = Loading);
static void callback(const QV4::Value &callback, const QV4::Value &status);
QV4::ExecutionEngine *v4;
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index ef1f500580..2bb755b537 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -77,8 +77,8 @@ private:
inline bool eatSpace();
inline QChar nextToken();
- Value parseObject();
- Value parseArray();
+ ReturnedValue parseObject();
+ ReturnedValue parseArray();
bool parseMember(Object *o);
bool parseString(QString *string);
bool parseValue(Value *val);
@@ -224,42 +224,42 @@ Value JsonParser::parse(QJsonParseError *error)
end-object
*/
-Value JsonParser::parseObject()
+ReturnedValue JsonParser::parseObject()
{
if (++nestingLevel > nestingLimit) {
lastError = QJsonParseError::DeepNesting;
- return Value::undefinedValue();
+ return Encode::undefined();
}
BEGIN << "parseObject pos=" << json;
+ Scope scope(context);
- Object *o = context->engine->newObject();
- Value objectVal = Value::fromObject(o);
+ Scoped<Object> o(scope, context->engine->newObject());
QChar token = nextToken();
while (token == Quote) {
- if (!parseMember(o))
- return Value::undefinedValue();
+ if (!parseMember(o.getPointer()))
+ return Encode::undefined();
token = nextToken();
if (token != ValueSeparator)
break;
token = nextToken();
if (token == EndObject) {
lastError = QJsonParseError::MissingObject;
- return Value::undefinedValue();
+ return Encode::undefined();
}
}
DEBUG << "end token=" << token;
if (token != EndObject) {
lastError = QJsonParseError::UnterminatedObject;
- return Value::undefinedValue();
+ return Encode::undefined();
}
END;
--nestingLevel;
- return objectVal;
+ return o.asReturnedValue();
}
/*
@@ -291,19 +291,20 @@ bool JsonParser::parseMember(Object *o)
/*
array = begin-array [ value *( value-separator value ) ] end-array
*/
-Value JsonParser::parseArray()
+ReturnedValue JsonParser::parseArray()
{
+ Scope scope(context);
BEGIN << "parseArray";
- ArrayObject *array = context->engine->newArrayObject();
+ Scoped<ArrayObject> array(scope, context->engine->newArrayObject());
if (++nestingLevel > nestingLimit) {
lastError = QJsonParseError::DeepNesting;
- return Value::undefinedValue();
+ return Encode::undefined();
}
if (!eatSpace()) {
lastError = QJsonParseError::UnterminatedArray;
- return Value::undefinedValue();
+ return Encode::undefined();
}
if (*json == EndArray) {
nextToken();
@@ -312,7 +313,7 @@ Value JsonParser::parseArray()
while (1) {
Value val;
if (!parseValue(&val))
- return Value::undefinedValue();
+ return Encode::undefined();
array->arraySet(index, val);
QChar token = nextToken();
if (token == EndArray)
@@ -322,7 +323,7 @@ Value JsonParser::parseArray()
lastError = QJsonParseError::UnterminatedArray;
else
lastError = QJsonParseError::MissingValueSeparator;
- return Value::undefinedValue();
+ return Encode::undefined();
}
++index;
}
@@ -332,7 +333,7 @@ Value JsonParser::parseArray()
END;
--nestingLevel;
- return Value::fromObject(array);
+ return array.asReturnedValue();
}
/*
@@ -401,7 +402,7 @@ bool JsonParser::parseValue(Value *val)
return true;
}
case BeginArray: {
- *val = parseArray();
+ *val = Value::fromReturnedValue(parseArray());
if (val->isUndefined())
return false;
DEBUG << "value: array";
@@ -409,7 +410,7 @@ bool JsonParser::parseValue(Value *val)
return true;
}
case BeginObject: {
- *val = parseObject();
+ *val = Value::fromReturnedValue(parseObject());
if (val->isUndefined())
return false;
DEBUG << "value: object";
@@ -698,15 +699,16 @@ static QString quote(const QString &str)
QString Stringify::Str(const QString &key, Value value)
{
+ Scope scope(ctx);
QString result;
if (Object *o = value.asObject()) {
- FunctionObject *toJSON = o->get(ctx->engine->newString(QStringLiteral("toJSON"))).asFunctionObject();
- if (toJSON) {
- ScopedCallData callData(ctx->engine, 1);
+ Scoped<FunctionObject> toJSON(scope, o->get(ctx->engine->newString(QStringLiteral("toJSON"))));
+ if (!!toJSON) {
+ ScopedCallData callData(scope, 1);
callData->thisObject = value;
callData->args[0] = Value::fromString(ctx, key);
- value = toJSON->call(callData);
+ value = Value::fromReturnedValue(toJSON->call(callData));
}
}
@@ -714,11 +716,11 @@ QString Stringify::Str(const QString &key, Value value)
Object *holder = ctx->engine->newObject();
Value holderValue = Value::fromObject(holder);
holder->put(ctx, QString(), value);
- ScopedCallData callData(ctx->engine, 2);
+ ScopedCallData callData(scope, 2);
callData->args[0] = Value::fromString(ctx, key);
callData->args[1] = value;
callData->thisObject = holderValue;
- value = replacerFunction->call(callData);
+ value = Value::fromReturnedValue(replacerFunction->call(callData));
}
if (Object *o = value.asObject()) {
@@ -772,6 +774,8 @@ QString Stringify::JO(Object *o)
if (stack.contains(o))
ctx->throwTypeError();
+ Scope scope(o->engine());
+
QString result;
stack.push(o);
QString stepback = indent;
@@ -780,13 +784,14 @@ QString Stringify::JO(Object *o)
QStringList partial;
if (propertyList.isEmpty()) {
ObjectIterator it(o, ObjectIterator::EnumerableOnly);
+ ScopedValue name(scope);
while (1) {
Value v;
- Value name = it.nextPropertyNameAsString(&v);
- if (name.isNull())
+ name = it.nextPropertyNameAsString(&v);
+ if (name->isNull())
break;
- QString key = name.toQString();
+ QString key = name->toQStringNoThrow();
QString member = makeMember(key, v);
if (!member.isEmpty())
partial += member;
@@ -794,7 +799,7 @@ QString Stringify::JO(Object *o)
} else {
for (int i = 0; i < propertyList.size(); ++i) {
bool exists;
- Value v = o->get(propertyList.at(i), &exists);
+ ScopedValue v(scope, o->get(propertyList.at(i), &exists));
if (!exists)
continue;
QString member = makeMember(propertyList.at(i)->toQString(), v);
@@ -822,6 +827,8 @@ QString Stringify::JA(ArrayObject *a)
if (stack.contains(a))
ctx->throwTypeError();
+ Scope scope(a->engine());
+
QString result;
stack.push(a);
QString stepback = indent;
@@ -829,9 +836,10 @@ QString Stringify::JA(ArrayObject *a)
QStringList partial;
uint len = a->arrayLength();
+ ScopedValue v(scope);
for (uint i = 0; i < len; ++i) {
bool exists;
- Value v = a->getIndexed(i, &exists);
+ v = a->getIndexed(i, &exists);
if (!exists) {
partial += QStringLiteral("null");
continue;
@@ -868,7 +876,7 @@ JsonObject::JsonObject(ExecutionContext *context)
}
-Value JsonObject::method_parse(SimpleCallContext *ctx)
+ReturnedValue JsonObject::method_parse(SimpleCallContext *ctx)
{
QString jtext = ctx->argument(0).toString(ctx)->toQString();
@@ -881,12 +889,12 @@ Value JsonObject::method_parse(SimpleCallContext *ctx)
ctx->throwSyntaxError("JSON.parse: Parse error");
}
- return result;
+ return result.asReturnedValue();
}
-Value JsonObject::method_stringify(SimpleCallContext *ctx)
+ReturnedValue JsonObject::method_stringify(SimpleCallContext *ctx)
{
- ValueScope scope(ctx);
+ Scope scope(ctx);
Stringify stringify(ctx);
@@ -924,28 +932,28 @@ Value JsonObject::method_stringify(SimpleCallContext *ctx)
QString result = stringify.Str(QString(), ctx->argument(0));
if (result.isEmpty())
- return Value::undefinedValue();
- return Value::fromString(ctx, result);
+ return Encode::undefined();
+ return Value::fromString(ctx, result).asReturnedValue();
}
-QV4::Value JsonObject::fromJsonValue(ExecutionEngine *engine, const QJsonValue &value)
+ReturnedValue JsonObject::fromJsonValue(ExecutionEngine *engine, const QJsonValue &value)
{
if (value.isString())
- return Value::fromString(engine->current, value.toString());
+ return Value::fromString(engine->current, value.toString()).asReturnedValue();
else if (value.isDouble())
- return Value::fromDouble(value.toDouble());
+ return Encode(value.toDouble());
else if (value.isBool())
- return Value::fromBoolean(value.toBool());
+ return Encode(value.toBool());
else if (value.isArray())
return fromJsonArray(engine, value.toArray());
else if (value.isObject())
return fromJsonObject(engine, value.toObject());
else if (value.isNull())
- return Value::nullValue();
+ return Encode::null();
else
- return Value::undefinedValue();
+ return Encode::undefined();
}
QJsonValue JsonObject::toJsonValue(const QV4::Value &value,
@@ -967,12 +975,13 @@ QJsonValue JsonObject::toJsonValue(const QV4::Value &value,
return QJsonValue(QJsonValue::Undefined);
}
-QV4::Value JsonObject::fromJsonObject(ExecutionEngine *engine, const QJsonObject &object)
+QV4::ReturnedValue JsonObject::fromJsonObject(ExecutionEngine *engine, const QJsonObject &object)
{
- Object *o = engine->newObject();
+ Scope scope(engine);
+ Scoped<Object> o(scope, Value::fromObject(engine->newObject()));
for (QJsonObject::const_iterator it = object.begin(); it != object.end(); ++it)
- o->put(engine->newString(it.key()), fromJsonValue(engine, it.value()));
- return Value::fromObject(o);
+ o->put(engine->newString(it.key()), Value::fromReturnedValue(fromJsonValue(engine, it.value())));
+ return o.asReturnedValue();
}
QJsonObject JsonObject::toJsonObject(QV4::Object *o, V4ObjectSet &visitedObjects)
@@ -981,6 +990,8 @@ QJsonObject JsonObject::toJsonObject(QV4::Object *o, V4ObjectSet &visitedObjects
if (!o || o->asFunctionObject())
return result;
+ Scope scope(o->engine());
+
if (visitedObjects.contains(o)) {
// Avoid recursion.
// For compatibility with QVariant{List,Map} conversion, we return an
@@ -991,13 +1002,14 @@ QJsonObject JsonObject::toJsonObject(QV4::Object *o, V4ObjectSet &visitedObjects
visitedObjects.insert(o);
ObjectIterator it(o, ObjectIterator::EnumerableOnly);
+ ScopedValue name(scope);
while (1) {
Value v;
- Value name = it.nextPropertyNameAsString(&v);
- if (name.isNull())
+ name = it.nextPropertyNameAsString(&v);
+ if (name->isNull())
break;
- QString key = name.toQString();
+ QString key = name->toQStringNoThrow();
if (!v.asFunctionObject())
result.insert(key, toJsonValue(v, visitedObjects));
}
@@ -1007,16 +1019,17 @@ QJsonObject JsonObject::toJsonObject(QV4::Object *o, V4ObjectSet &visitedObjects
return result;
}
-QV4::Value JsonObject::fromJsonArray(ExecutionEngine *engine, const QJsonArray &array)
+QV4::ReturnedValue JsonObject::fromJsonArray(ExecutionEngine *engine, const QJsonArray &array)
{
+ Scope scope(engine);
int size = array.size();
- ArrayObject *a = engine->newArrayObject();
+ Scoped<ArrayObject> a(scope, engine->newArrayObject());
a->arrayReserve(size);
a->arrayDataLen = size;
for (int i = 0; i < size; i++)
- a->arrayData[i].value = fromJsonValue(engine, array.at(i));
+ a->arrayData[i].value = Value::fromReturnedValue(fromJsonValue(engine, array.at(i)));
a->setArrayLengthUnchecked(size);
- return Value::fromObject(a);
+ return a.asReturnedValue();
}
QJsonArray JsonObject::toJsonArray(ArrayObject *a, V4ObjectSet &visitedObjects)
@@ -1025,6 +1038,8 @@ QJsonArray JsonObject::toJsonArray(ArrayObject *a, V4ObjectSet &visitedObjects)
if (!a)
return result;
+ Scope scope(a->engine());
+
if (visitedObjects.contains(a)) {
// Avoid recursion.
// For compatibility with QVariant{List,Map} conversion, we return an
@@ -1034,10 +1049,11 @@ QJsonArray JsonObject::toJsonArray(ArrayObject *a, V4ObjectSet &visitedObjects)
visitedObjects.insert(a);
+ ScopedValue v(scope);
quint32 length = a->arrayLength();
for (quint32 i = 0; i < length; ++i) {
- Value v = a->getIndexed(i);
- result.append(toJsonValue(v.asFunctionObject() ? QV4::Value::nullValue() : v, visitedObjects));
+ v = a->getIndexed(i);
+ result.append(toJsonValue(v->asFunctionObject() ? QV4::Value::nullValue() : v, visitedObjects));
}
visitedObjects.remove(a);
diff --git a/src/qml/jsruntime/qv4jsonobject_p.h b/src/qml/jsruntime/qv4jsonobject_p.h
index ccd99d5488..821cffcc7c 100644
--- a/src/qml/jsruntime/qv4jsonobject_p.h
+++ b/src/qml/jsruntime/qv4jsonobject_p.h
@@ -56,12 +56,12 @@ private:
public:
JsonObject(ExecutionContext *context);
- static Value method_parse(SimpleCallContext *ctx);
- static Value method_stringify(SimpleCallContext *ctx);
+ static ReturnedValue method_parse(SimpleCallContext *ctx);
+ static ReturnedValue method_stringify(SimpleCallContext *ctx);
- static QV4::Value fromJsonValue(ExecutionEngine *engine, const QJsonValue &value);
- static QV4::Value fromJsonObject(ExecutionEngine *engine, const QJsonObject &object);
- static QV4::Value fromJsonArray(ExecutionEngine *engine, const QJsonArray &array);
+ static ReturnedValue fromJsonValue(ExecutionEngine *engine, const QJsonValue &value);
+ static ReturnedValue fromJsonObject(ExecutionEngine *engine, const QJsonObject &object);
+ static ReturnedValue fromJsonArray(ExecutionEngine *engine, const QJsonArray &array);
static inline QJsonValue toJsonValue(const QV4::Value &value)
{ V4ObjectSet visitedObjects; return toJsonValue(value, visitedObjects); }
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index 2cffa55642..da078729e4 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -87,12 +87,10 @@ Property *Lookup::lookup(Object *obj, PropertyAttributes *attrs)
}
-void Lookup::getterGeneric(QV4::Lookup *l, QV4::Value *result, const QV4::Value &object)
+ReturnedValue Lookup::getterGeneric(QV4::Lookup *l, const QV4::Value &object)
{
- if (Object *o = object.asObject()) {
- o->getLookup(l, result);
- return;
- }
+ if (Object *o = object.asObject())
+ return o->getLookup(l);
ExecutionEngine *engine = l->name->engine();
Object *proto;
@@ -103,13 +101,13 @@ void Lookup::getterGeneric(QV4::Lookup *l, QV4::Value *result, const QV4::Value
case Value::Boolean_Type:
proto = engine->booleanClass->prototype;
break;
- case Value::String_Type:
+ case Value::Managed_Type:
+ Q_ASSERT(object.isString());
proto = engine->stringClass->prototype;
if (l->name == engine->id_length) {
// special case, as the property is on the object itself
l->getter = stringLengthGetter;
- stringLengthGetter(l, result, object);
- return;
+ return stringLengthGetter(l, object);
}
break;
case Value::Integer_Type:
@@ -127,119 +125,94 @@ void Lookup::getterGeneric(QV4::Lookup *l, QV4::Value *result, const QV4::Value
l->getter = Lookup::primitiveGetter0;
else if (l->level == 1)
l->getter = Lookup::primitiveGetter1;
- if (result)
- *result = p->value;
- return;
+ return p->value.asReturnedValue();
} else {
if (l->level == 0)
l->getter = Lookup::primitiveGetterAccessor0;
else if (l->level == 1)
l->getter = Lookup::primitiveGetterAccessor1;
- if (result)
- *result = p->value;
- Value res = proto->getValue(object, p, attrs);
- if (result)
- *result = res;
- return;
+ return proto->getValue(object, p, attrs);
}
}
- if (result)
- *result = Value::undefinedValue();
+ return Value::undefinedValue().asReturnedValue();
}
-void Lookup::getter0(Lookup *l, Value *result, const Value &object)
+ReturnedValue Lookup::getter0(Lookup *l, const Value &object)
{
if (Object *o = object.asObject()) {
- if (l->classList[0] == o->internalClass) {
- if (result)
- *result = o->memberData[l->index].value;
- return;
- }
+ if (l->classList[0] == o->internalClass)
+ return o->memberData[l->index].value.asReturnedValue();
}
l->getter = getterGeneric;
- getterGeneric(l, result, object);
+ return getterGeneric(l, object);
}
-void Lookup::getter1(Lookup *l, Value *result, const Value &object)
+ReturnedValue Lookup::getter1(Lookup *l, const Value &object)
{
if (Object *o = object.asObject()) {
if (l->classList[0] == o->internalClass &&
- l->classList[1] == o->prototype()->internalClass) {
- if (result)
- *result = o->prototype()->memberData[l->index].value;
- return;
- }
+ l->classList[1] == o->prototype()->internalClass)
+ return o->prototype()->memberData[l->index].value.asReturnedValue();
}
l->getter = getterGeneric;
- getterGeneric(l, result, object);
+ return getterGeneric(l, object);
}
-void Lookup::getter2(Lookup *l, Value *result, const Value &object)
+ReturnedValue Lookup::getter2(Lookup *l, const Value &object)
{
if (Object *o = object.asObject()) {
if (l->classList[0] == o->internalClass) {
o = o->prototype();
if (l->classList[1] == o->internalClass) {
o = o->prototype();
- if (l->classList[2] == o->internalClass) {
- if (result)
- *result = o->memberData[l->index].value;
- return;
- }
+ if (l->classList[2] == o->internalClass)
+ return o->memberData[l->index].value.asReturnedValue();
}
}
}
l->getter = getterGeneric;
- getterGeneric(l, result, object);
+ return getterGeneric(l, object);
}
-void Lookup::getterAccessor0(Lookup *l, Value *result, const Value &object)
+ReturnedValue Lookup::getterAccessor0(Lookup *l, const Value &object)
{
if (Object *o = object.asObject()) {
if (l->classList[0] == o->internalClass) {
- Value res;
+ Scope scope(o->engine());
FunctionObject *getter = o->memberData[l->index].getter();
- if (!getter) {
- res = Value::undefinedValue();
- } else {
- ScopedCallData callData(o->engine(), 0);
- callData->thisObject = object;
- res = getter->call(callData);
- }
- if (result)
- *result = res;
- return;
+ if (!getter)
+ return Value::undefinedValue().asReturnedValue();
+
+ ScopedCallData callData(scope, 0);
+ callData->thisObject = object;
+ return getter->call(callData);
}
}
l->getter = getterGeneric;
- getterGeneric(l, result, object);
+ return getterGeneric(l, object);
}
-void Lookup::getterAccessor1(Lookup *l, Value *result, const Value &object)
+ReturnedValue Lookup::getterAccessor1(Lookup *l, const Value &object)
{
if (Object *o = object.asObject()) {
if (l->classList[0] == o->internalClass &&
l->classList[1] == o->prototype()->internalClass) {
- Value res;
+ Scope scope(o->engine());
FunctionObject *getter = o->prototype()->memberData[l->index].getter();
- if (!getter) {
- res = Value::undefinedValue();
- } else {
- ScopedCallData callData(o->engine(), 0);
- callData->thisObject = object;
- res = getter->call(callData);
- }
- if (result)
- *result = res;
- return;
+ if (!getter)
+ return Value::undefinedValue().asReturnedValue();
+
+ ScopedCallData callData(scope, 0);
+ callData->thisObject = object;
+ return getter->call(callData);
}
}
l->getter = getterGeneric;
- getterGeneric(l, result, object);
+ return getterGeneric(l, object);
}
-void Lookup::getterAccessor2(Lookup *l, Value *result, const Value &object)
+ReturnedValue Lookup::getterAccessor2(Lookup *l, const Value &object)
{
if (Object *o = object.asObject()) {
if (l->classList[0] == o->internalClass) {
@@ -247,116 +220,98 @@ void Lookup::getterAccessor2(Lookup *l, Value *result, const Value &object)
if (l->classList[1] == o->internalClass) {
o = o->prototype();
if (l->classList[2] == o->internalClass) {
- Value res;
+ Scope scope(o->engine());
FunctionObject *getter = o->memberData[l->index].getter();
- if (!getter) {
- res = Value::undefinedValue();
- } else {
- ScopedCallData callData(o->engine(), 0);
- callData->thisObject = object;
- res = getter->call(callData);
- }
- if (result)
- *result = res;
- return;
+ if (!getter)
+ return Value::undefinedValue().asReturnedValue();
+
+ ScopedCallData callData(scope, 0);
+ callData->thisObject = object;
+ return getter->call(callData);
}
}
}
}
l->getter = getterGeneric;
- getterGeneric(l, result, object);
+ return getterGeneric(l, object);
}
-void Lookup::primitiveGetter0(Lookup *l, Value *result, const Value &object)
+ReturnedValue Lookup::primitiveGetter0(Lookup *l, const Value &object)
{
if (object.type() == l->type) {
Object *o = l->proto;
- if (l->classList[0] == o->internalClass) {
- if (result)
- *result = o->memberData[l->index].value;
- return;
- }
+ if (l->classList[0] == o->internalClass)
+ return o->memberData[l->index].value.asReturnedValue();
}
l->getter = getterGeneric;
- getterGeneric(l, result, object);
+ return getterGeneric(l, object);
}
-void Lookup::primitiveGetter1(Lookup *l, Value *result, const Value &object)
+ReturnedValue Lookup::primitiveGetter1(Lookup *l, const Value &object)
{
if (object.type() == l->type) {
Object *o = l->proto;
if (l->classList[0] == o->internalClass &&
- l->classList[1] == o->prototype()->internalClass) {
- if (result)
- *result = o->prototype()->memberData[l->index].value;
- return;
- }
+ l->classList[1] == o->prototype()->internalClass)
+ return o->prototype()->memberData[l->index].value.asReturnedValue();
}
l->getter = getterGeneric;
- getterGeneric(l, result, object);
+ return getterGeneric(l, object);
}
-void Lookup::primitiveGetterAccessor0(Lookup *l, Value *result, const Value &object)
+ReturnedValue Lookup::primitiveGetterAccessor0(Lookup *l, const Value &object)
{
if (object.type() == l->type) {
Object *o = l->proto;
if (l->classList[0] == o->internalClass) {
+ Scope scope(o->engine());
Value res;
FunctionObject *getter = o->memberData[l->index].getter();
- if (!getter) {
- res = Value::undefinedValue();
- } else {
- ScopedCallData callData(o->engine(), 0);
- callData->thisObject = object;
- res = getter->call(callData);
- }
- if (result)
- *result = res;
- return;
+ if (!getter)
+ return Value::undefinedValue().asReturnedValue();
+
+ ScopedCallData callData(scope, 0);
+ callData->thisObject = object;
+ return getter->call(callData);
}
}
l->getter = getterGeneric;
- getterGeneric(l, result, object);
+ return getterGeneric(l, object);
}
-void Lookup::primitiveGetterAccessor1(Lookup *l, Value *result, const Value &object)
+ReturnedValue Lookup::primitiveGetterAccessor1(Lookup *l, const Value &object)
{
if (object.type() == l->type) {
Object *o = l->proto;
if (l->classList[0] == o->internalClass &&
l->classList[1] == o->prototype()->internalClass) {
+ Scope scope(o->engine());
Value res;
FunctionObject *getter = o->prototype()->memberData[l->index].getter();
- if (!getter) {
- res = Value::undefinedValue();
- } else {
- ScopedCallData callData(o->engine(), 0);
- callData->thisObject = object;
- res = getter->call(callData);
- }
- if (result)
- *result = res;
- return;
+ if (!getter)
+ return Value::undefinedValue().asReturnedValue();
+
+ ScopedCallData callData(scope, 0);
+ callData->thisObject = object;
+ return getter->call(callData);
}
}
l->getter = getterGeneric;
- getterGeneric(l, result, object);
+ return getterGeneric(l, object);
}
-void Lookup::stringLengthGetter(Lookup *l, Value *result, const Value &object)
+ReturnedValue Lookup::stringLengthGetter(Lookup *l, const Value &object)
{
- if (String *s = object.asString()) {
- if (result)
- *result = Value::fromUInt32(s->length());
- return;
- }
+ if (String *s = object.asString())
+ return Value::fromUInt32(s->length()).asReturnedValue();
+
l->getter = getterGeneric;
- getterGeneric(l, result, object);
+ return getterGeneric(l, object);
}
-void Lookup::globalGetterGeneric(Lookup *l, ExecutionContext *ctx, Value *result)
+ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionContext *ctx)
{
Object *o = ctx->engine->globalObject;
PropertyAttributes attrs;
@@ -369,8 +324,7 @@ void Lookup::globalGetterGeneric(Lookup *l, ExecutionContext *ctx, Value *result
l->globalGetter = globalGetter1;
else if (l->level == 2)
l->globalGetter = globalGetter2;
- *result = p->value;
- return;
+ return p->value.asReturnedValue();
} else {
if (l->level == 0)
l->globalGetter = globalGetterAccessor0;
@@ -378,39 +332,36 @@ void Lookup::globalGetterGeneric(Lookup *l, ExecutionContext *ctx, Value *result
l->globalGetter = globalGetterAccessor1;
else if (l->level == 2)
l->globalGetter = globalGetterAccessor2;
- Value res = o->getValue(p, attrs);
- if (result)
- *result = res;
- return;
+ return o->getValue(p, attrs);
}
}
- ctx->throwReferenceError(Value::fromString(l->name));
+ Scope scope(ctx);
+ Scoped<String> n(scope, l->name);
+ ctx->throwReferenceError(n);
}
-void Lookup::globalGetter0(Lookup *l, ExecutionContext *ctx, Value *result)
+ReturnedValue Lookup::globalGetter0(Lookup *l, ExecutionContext *ctx)
{
Object *o = ctx->engine->globalObject;
- if (l->classList[0] == o->internalClass) {
- *result = o->memberData[l->index].value;
- return;
- }
+ if (l->classList[0] == o->internalClass)
+ return o->memberData[l->index].value.asReturnedValue();
+
l->globalGetter = globalGetterGeneric;
- globalGetterGeneric(l, ctx, result);
+ return globalGetterGeneric(l, ctx);
}
-void Lookup::globalGetter1(Lookup *l, ExecutionContext *ctx, Value *result)
+ReturnedValue Lookup::globalGetter1(Lookup *l, ExecutionContext *ctx)
{
Object *o = ctx->engine->globalObject;
if (l->classList[0] == o->internalClass &&
- l->classList[1] == o->prototype()->internalClass) {
- *result = o->prototype()->memberData[l->index].value;
- return;
- }
+ l->classList[1] == o->prototype()->internalClass)
+ return o->prototype()->memberData[l->index].value.asReturnedValue();
+
l->globalGetter = globalGetterGeneric;
- globalGetterGeneric(l, ctx, result);
+ return globalGetterGeneric(l, ctx);
}
-void Lookup::globalGetter2(Lookup *l, ExecutionContext *ctx, Value *result)
+ReturnedValue Lookup::globalGetter2(Lookup *l, ExecutionContext *ctx)
{
Object *o = ctx->engine->globalObject;
if (l->classList[0] == o->internalClass) {
@@ -418,53 +369,50 @@ void Lookup::globalGetter2(Lookup *l, ExecutionContext *ctx, Value *result)
if (l->classList[1] == o->internalClass) {
o = o->prototype();
if (l->classList[2] == o->internalClass) {
- *result = o->prototype()->memberData[l->index].value;
- return;
+ return o->prototype()->memberData[l->index].value.asReturnedValue();
}
}
}
l->globalGetter = globalGetterGeneric;
- globalGetterGeneric(l, ctx, result);
+ return globalGetterGeneric(l, ctx);
}
-void Lookup::globalGetterAccessor0(Lookup *l, ExecutionContext *ctx, Value *result)
+ReturnedValue Lookup::globalGetterAccessor0(Lookup *l, ExecutionContext *ctx)
{
Object *o = ctx->engine->globalObject;
if (l->classList[0] == o->internalClass) {
+ Scope scope(o->engine());
FunctionObject *getter = o->memberData[l->index].getter();
- if (!getter) {
- *result = Value::undefinedValue();
- } else {
- ScopedCallData callData(ctx->engine, 0);
- callData->thisObject = Value::undefinedValue();
- *result = getter->call(callData);
- }
- return;
+ if (!getter)
+ return Value::undefinedValue().asReturnedValue();
+
+ ScopedCallData callData(scope, 0);
+ callData->thisObject = Value::undefinedValue();
+ return getter->call(callData);
}
l->globalGetter = globalGetterGeneric;
- globalGetterGeneric(l, ctx, result);
+ return globalGetterGeneric(l, ctx);
}
-void Lookup::globalGetterAccessor1(Lookup *l, ExecutionContext *ctx, Value *result)
+ReturnedValue Lookup::globalGetterAccessor1(Lookup *l, ExecutionContext *ctx)
{
Object *o = ctx->engine->globalObject;
if (l->classList[0] == o->internalClass &&
l->classList[1] == o->prototype()->internalClass) {
+ Scope scope(o->engine());
FunctionObject *getter = o->prototype()->memberData[l->index].getter();
- if (!getter) {
- *result = Value::undefinedValue();
- } else {
- ScopedCallData callData(ctx->engine, 0);
- callData->thisObject = Value::undefinedValue();
- *result = getter->call(callData);
- }
- return;
+ if (!getter)
+ return Value::undefinedValue().asReturnedValue();
+
+ ScopedCallData callData(scope, 0);
+ callData->thisObject = Value::undefinedValue();
+ return getter->call(callData);
}
l->globalGetter = globalGetterGeneric;
- globalGetterGeneric(l, ctx, result);
+ return globalGetterGeneric(l, ctx);
}
-void Lookup::globalGetterAccessor2(Lookup *l, ExecutionContext *ctx, Value *result)
+ReturnedValue Lookup::globalGetterAccessor2(Lookup *l, ExecutionContext *ctx)
{
Object *o = ctx->engine->globalObject;
if (l->classList[0] == o->internalClass) {
@@ -472,27 +420,26 @@ void Lookup::globalGetterAccessor2(Lookup *l, ExecutionContext *ctx, Value *resu
if (l->classList[1] == o->internalClass) {
o = o->prototype();
if (l->classList[2] == o->internalClass) {
+ Scope scope(o->engine());
FunctionObject *getter = o->memberData[l->index].getter();
- if (!getter) {
- *result = Value::undefinedValue();
- } else {
- ScopedCallData callData(ctx->engine, 0);
- callData->thisObject = Value::undefinedValue();
- *result = getter->call(callData);
- }
- return;
+ if (!getter)
+ return Value::undefinedValue().asReturnedValue();
+
+ ScopedCallData callData(scope, 0);
+ callData->thisObject = Value::undefinedValue();
+ return getter->call(callData);
}
}
}
l->globalGetter = globalGetterGeneric;
- globalGetterGeneric(l, ctx, result);
+ return globalGetterGeneric(l, ctx);
}
void Lookup::setterGeneric(Lookup *l, const Value &object, const Value &value)
{
Object *o = object.asObject();
if (!o) {
- o = __qmljs_convert_to_object(l->name->engine()->current, ValueRef::fromRawValue(&object));
+ o = __qmljs_convert_to_object(l->name->engine()->current, ValueRef::fromRawValue(&object))->getPointer();
o->put(l->name, value);
return;
}
diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h
index b37738dd92..b79e91028f 100644
--- a/src/qml/jsruntime/qv4lookup_p.h
+++ b/src/qml/jsruntime/qv4lookup_p.h
@@ -55,8 +55,8 @@ namespace QV4 {
struct Lookup {
enum { Size = 4 };
union {
- void (*getter)(Lookup *l, Value *result, const Value &object);
- void (*globalGetter)(Lookup *l, ExecutionContext *ctx, Value *result);
+ ReturnedValue (*getter)(Lookup *l, const Value &object);
+ ReturnedValue (*globalGetter)(Lookup *l, ExecutionContext *ctx);
void (*setter)(Lookup *l, const Value &object, const Value &v);
};
union {
@@ -72,27 +72,27 @@ struct Lookup {
uint index;
String *name;
- static void getterGeneric(Lookup *l, Value *result, const Value &object);
- static void getter0(Lookup *l, Value *result, const Value &object);
- static void getter1(Lookup *l, Value *result, const Value &object);
- static void getter2(Lookup *l, Value *result, const Value &object);
- static void getterAccessor0(Lookup *l, Value *result, const Value &object);
- static void getterAccessor1(Lookup *l, Value *result, const Value &object);
- static void getterAccessor2(Lookup *l, Value *result, const Value &object);
+ static ReturnedValue getterGeneric(Lookup *l, const Value &object);
+ static ReturnedValue getter0(Lookup *l, const Value &object);
+ static ReturnedValue getter1(Lookup *l, const Value &object);
+ static ReturnedValue getter2(Lookup *l, const Value &object);
+ static ReturnedValue getterAccessor0(Lookup *l, const Value &object);
+ static ReturnedValue getterAccessor1(Lookup *l, const Value &object);
+ static ReturnedValue getterAccessor2(Lookup *l, const Value &object);
- static void primitiveGetter0(Lookup *l, Value *result, const Value &object);
- static void primitiveGetter1(Lookup *l, Value *result, const Value &object);
- static void primitiveGetterAccessor0(Lookup *l, Value *result, const Value &object);
- static void primitiveGetterAccessor1(Lookup *l, Value *result, const Value &object);
- static void stringLengthGetter(Lookup *l, Value *result, const Value &object);
+ static ReturnedValue primitiveGetter0(Lookup *l, const Value &object);
+ static ReturnedValue primitiveGetter1(Lookup *l, const Value &object);
+ static ReturnedValue primitiveGetterAccessor0(Lookup *l, const Value &object);
+ static ReturnedValue primitiveGetterAccessor1(Lookup *l, const Value &object);
+ static ReturnedValue stringLengthGetter(Lookup *l, const Value &object);
- static void globalGetterGeneric(Lookup *l, ExecutionContext *ctx, Value *result);
- static void globalGetter0(Lookup *l, ExecutionContext *ctx, Value *result);
- static void globalGetter1(Lookup *l, ExecutionContext *ctx, Value *result);
- static void globalGetter2(Lookup *l, ExecutionContext *ctx, Value *result);
- static void globalGetterAccessor0(Lookup *l, ExecutionContext *ctx, Value *result);
- static void globalGetterAccessor1(Lookup *l, ExecutionContext *ctx, Value *result);
- static void globalGetterAccessor2(Lookup *l, ExecutionContext *ctx, Value *result);
+ static ReturnedValue globalGetterGeneric(Lookup *l, ExecutionContext *ctx);
+ static ReturnedValue globalGetter0(Lookup *l, ExecutionContext *ctx);
+ static ReturnedValue globalGetter1(Lookup *l, ExecutionContext *ctx);
+ static ReturnedValue globalGetter2(Lookup *l, ExecutionContext *ctx);
+ static ReturnedValue globalGetterAccessor0(Lookup *l, ExecutionContext *ctx);
+ static ReturnedValue globalGetterAccessor1(Lookup *l, ExecutionContext *ctx);
+ static ReturnedValue globalGetterAccessor2(Lookup *l, ExecutionContext *ctx);
static void setterGeneric(Lookup *l, const Value &object, const Value &value);
static void setter0(Lookup *l, const Value &object, const Value &value);
diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp
index 62491ba7e5..4404f909b6 100644
--- a/src/qml/jsruntime/qv4managed.cpp
+++ b/src/qml/jsruntime/qv4managed.cpp
@@ -176,19 +176,20 @@ bool Managed::hasInstance(Managed *m, const Value &)
m->engine()->current->throwTypeError();
}
-Value Managed::construct(Managed *m, CallData *)
+ReturnedValue Managed::construct(Managed *m, CallData *)
{
m->engine()->current->throwTypeError();
}
-Value Managed::call(Managed *m, CallData *)
+ReturnedValue Managed::call(Managed *m, CallData *)
{
m->engine()->current->throwTypeError();
}
-void Managed::getLookup(Managed *m, Lookup *, Value *)
+ReturnedValue Managed::getLookup(Managed *m, Lookup *)
{
m->engine()->current->throwTypeError();
+ return 0;
}
void Managed::setLookup(Managed *m, Lookup *, const Value &)
@@ -201,12 +202,12 @@ bool Managed::isEqualTo(Managed *, Managed *)
return false;
}
-Value Managed::get(String *name, bool *hasProperty)
+ReturnedValue Managed::get(String *name, bool *hasProperty)
{
return vtbl->get(this, name, hasProperty);
}
-Value Managed::getIndexed(uint index, bool *hasProperty)
+ReturnedValue Managed::getIndexed(uint index, bool *hasProperty)
{
return vtbl->getIndexed(this, index, hasProperty);
}
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index 50325478f5..f13f699748 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -61,10 +61,25 @@ inline int qYouForgotTheQ_MANAGED_Macro(T, T) { return 0; }
template <typename T1, typename T2>
inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
+template <typename T>
+struct Returned : private T
+{
+ static Returned<T> *create(T *t) { return static_cast<Returned<T> *>(t); }
+ T *getPointer() { return this; }
+ template<typename X>
+ static T *getPointer(Returned<X> *x) { return x->getPointer(); }
+ template<typename X>
+ Returned<X> *as() { return Returned<X>::create(Returned<X>::getPointer(this)); }
+ using T::asReturnedValue;
+};
+
#define Q_MANAGED \
public: \
Q_MANAGED_CHECK \
- static const QV4::ManagedVTable static_vtbl;
+ static const QV4::ManagedVTable static_vtbl; \
+ template <typename T> \
+ QV4::Returned<T> *asReturned() { return QV4::Returned<T>::create(this); } \
+
struct GCDeletable
{
@@ -91,21 +106,21 @@ struct CallData
struct ManagedVTable
{
- Value (*call)(Managed *, CallData *data);
- Value (*construct)(Managed *, CallData *data);
+ ReturnedValue (*call)(Managed *, CallData *data);
+ ReturnedValue (*construct)(Managed *, CallData *data);
void (*markObjects)(Managed *);
void (*destroy)(Managed *);
void (*collectDeletables)(Managed *, GCDeletable **deletable);
bool (*hasInstance)(Managed *, const Value &value);
- Value (*get)(Managed *, String *name, bool *hasProperty);
- Value (*getIndexed)(Managed *, uint index, bool *hasProperty);
+ ReturnedValue (*get)(Managed *, String *name, bool *hasProperty);
+ ReturnedValue (*getIndexed)(Managed *, uint index, bool *hasProperty);
void (*put)(Managed *, String *name, const Value &value);
void (*putIndexed)(Managed *, uint index, const Value &value);
PropertyAttributes (*query)(const Managed *, String *name);
PropertyAttributes (*queryIndexed)(const Managed *, uint index);
bool (*deleteProperty)(Managed *m, String *name);
bool (*deleteIndexedProperty)(Managed *m, uint index);
- void (*getLookup)(Managed *m, Lookup *l, Value *result);
+ ReturnedValue (*getLookup)(Managed *m, Lookup *l);
void (*setLookup)(Managed *m, Lookup *l, const Value &v);
bool (*isEqualTo)(Managed *m, Managed *other);
Property *(*advanceIterator)(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attributes);
@@ -162,6 +177,7 @@ const QV4::ManagedVTable classname::static_vtbl = \
struct Q_QML_EXPORT Managed
{
+ Q_MANAGED
private:
void *operator new(size_t);
Managed(const Managed &other);
@@ -210,6 +226,9 @@ public:
template <typename T>
T *as() {
+ // ### FIXME:
+ if (!this)
+ return 0;
#if !defined(QT_NO_QOBJECT_CHECK)
reinterpret_cast<T *>(this)->qt_check_for_QMANAGED_macro(*reinterpret_cast<T *>(this));
#endif
@@ -217,12 +236,23 @@ public:
}
template <typename T>
const T *as() const {
+ // ### FIXME:
+ if (!this)
+ return 0;
#if !defined(QT_NO_QOBJECT_CHECK)
reinterpret_cast<T *>(this)->qt_check_for_QMANAGED_macro(*reinterpret_cast<T *>(const_cast<Managed *>(this)));
#endif
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();
+ }
+
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; }
@@ -252,10 +282,10 @@ public:
inline bool hasInstance(const Value &v) {
return vtbl->hasInstance(this, v);
}
- Value construct(CallData *d);
- Value call(CallData *d);
- Value get(String *name, bool *hasProperty = 0);
- Value getIndexed(uint index, bool *hasProperty = 0);
+ ReturnedValue construct(CallData *d);
+ ReturnedValue call(CallData *d);
+ ReturnedValue get(String *name, bool *hasProperty = 0);
+ ReturnedValue getIndexed(uint index, bool *hasProperty = 0);
void put(String *name, const Value &value)
{ vtbl->put(this, name, value); }
void putIndexed(uint index, const Value &value)
@@ -269,8 +299,8 @@ public:
{ return vtbl->deleteProperty(this, name); }
bool deleteIndexedProperty(uint index)
{ return vtbl->deleteIndexedProperty(this, index); }
- void getLookup(Lookup *l, Value *result)
- { vtbl->getLookup(this, l, result); }
+ ReturnedValue getLookup(Lookup *l)
+ { return vtbl->getLookup(this, l); }
void setLookup(Lookup *l, const Value &v)
{ vtbl->setLookup(this, l, v); }
@@ -281,9 +311,9 @@ public:
static void destroy(Managed *that) { that->_data = 0; }
static bool hasInstance(Managed *that, const Value &value);
- static Value construct(Managed *m, CallData *d);
- static Value call(Managed *m, CallData *);
- static void getLookup(Managed *m, Lookup *, Value *);
+ static ReturnedValue construct(Managed *m, CallData *d);
+ static ReturnedValue call(Managed *m, CallData *);
+ static ReturnedValue getLookup(Managed *m, Lookup *);
static void setLookup(Managed *m, Lookup *l, const Value &v);
static bool isEqualTo(Managed *m, Managed *other);
@@ -291,6 +321,8 @@ public:
return type;
}
+ ReturnedValue asReturnedValue() { return Value::fromManaged(this).asReturnedValue(); }
+
union {
uint _data;
struct {
@@ -311,9 +343,6 @@ public:
};
protected:
-
- static const ManagedVTable static_vtbl;
-
const ManagedVTable *vtbl;
public:
InternalClass *internalClass;
@@ -324,10 +353,12 @@ private:
friend struct ObjectIterator;
};
-// ### Not a good placement
-template<typename T>
-inline T *Value::as() const { Managed *m = isObject() ? managed() : 0; return m ? m->as<T>() : 0; }
-
+inline ReturnedValue Managed::construct(CallData *d) {
+ return vtbl->construct(this, d);
+}
+inline ReturnedValue Managed::call(CallData *d) {
+ return vtbl->call(this, d);
+}
}
diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp
index 0e7b32d429..cf2d5afd3f 100644
--- a/src/qml/jsruntime/qv4mathobject.cpp
+++ b/src/qml/jsruntime/qv4mathobject.cpp
@@ -96,112 +96,112 @@ static double copySign(double x, double y)
return x;
}
-Value MathObject::method_abs(SimpleCallContext *context)
+ReturnedValue MathObject::method_abs(SimpleCallContext *context)
{
if (!context->argumentCount)
- return Value::fromDouble(qSNaN());
+ return Encode(qSNaN());
if (context->arguments[0].isInteger()) {
int i = context->arguments[0].integerValue();
- return Value::fromInt32(i < 0 ? - i : i);
+ return Encode(i < 0 ? - i : i);
}
double v = context->arguments[0].toNumber();
if (v == 0) // 0 | -0
- return Value::fromDouble(0);
+ return Encode(0);
- return Value::fromDouble(v < 0 ? -v : v);
+ return Encode(v < 0 ? -v : v);
}
-Value MathObject::method_acos(SimpleCallContext *context)
+ReturnedValue MathObject::method_acos(SimpleCallContext *context)
{
double v = context->argumentCount ? context->arguments[0].toNumber() : 2;
if (v > 1)
- return Value::fromDouble(qSNaN());
+ return Encode(qSNaN());
- return Value::fromDouble(::acos(v));
+ return Encode(::acos(v));
}
-Value MathObject::method_asin(SimpleCallContext *context)
+ReturnedValue MathObject::method_asin(SimpleCallContext *context)
{
double v = context->argumentCount ? context->arguments[0].toNumber() : 2;
if (v > 1)
- return Value::fromDouble(qSNaN());
+ return Encode(qSNaN());
else
- return Value::fromDouble(::asin(v));
+ return Encode(::asin(v));
}
-Value MathObject::method_atan(SimpleCallContext *context)
+ReturnedValue MathObject::method_atan(SimpleCallContext *context)
{
double v = context->argumentCount ? context->arguments[0].toNumber() : qSNaN();
if (v == 0.0)
- return Value::fromDouble(v);
+ return Encode(v);
else
- return Value::fromDouble(::atan(v));
+ return Encode(::atan(v));
}
-Value MathObject::method_atan2(SimpleCallContext *context)
+ReturnedValue MathObject::method_atan2(SimpleCallContext *context)
{
double v1 = context->argumentCount ? context->arguments[0].toNumber() : qSNaN();
double v2 = context->argumentCount > 1 ? context->arguments[1].toNumber() : qSNaN();
if ((v1 < 0) && qIsFinite(v1) && qIsInf(v2) && (copySign(1.0, v2) == 1.0))
- return Value::fromDouble(copySign(0, -1.0));
+ return Encode(copySign(0, -1.0));
if ((v1 == 0.0) && (v2 == 0.0)) {
if ((copySign(1.0, v1) == 1.0) && (copySign(1.0, v2) == -1.0)) {
- return Value::fromDouble(qt_PI);
+ return Encode(qt_PI);
} else if ((copySign(1.0, v1) == -1.0) && (copySign(1.0, v2) == -1.0)) {
- return Value::fromDouble(-qt_PI);
+ return Encode(-qt_PI);
}
}
- return Value::fromDouble(::atan2(v1, v2));
+ return Encode(::atan2(v1, v2));
}
-Value MathObject::method_ceil(SimpleCallContext *context)
+ReturnedValue MathObject::method_ceil(SimpleCallContext *context)
{
double v = context->argumentCount ? context->arguments[0].toNumber() : qSNaN();
if (v < 0.0 && v > -1.0)
- return Value::fromDouble(copySign(0, -1.0));
+ return Encode(copySign(0, -1.0));
else
- return Value::fromDouble(::ceil(v));
+ return Encode(::ceil(v));
}
-Value MathObject::method_cos(SimpleCallContext *context)
+ReturnedValue MathObject::method_cos(SimpleCallContext *context)
{
double v = context->argumentCount ? context->arguments[0].toNumber() : qSNaN();
- return Value::fromDouble(::cos(v));
+ return Encode(::cos(v));
}
-Value MathObject::method_exp(SimpleCallContext *context)
+ReturnedValue MathObject::method_exp(SimpleCallContext *context)
{
double v = context->argumentCount ? context->arguments[0].toNumber() : qSNaN();
if (qIsInf(v)) {
if (copySign(1.0, v) == -1.0)
- return Value::fromDouble(0);
+ return Encode(0);
else
- return Value::fromDouble(qInf());
+ return Encode(qInf());
} else {
- return Value::fromDouble(::exp(v));
+ return Encode(::exp(v));
}
}
-Value MathObject::method_floor(SimpleCallContext *context)
+ReturnedValue MathObject::method_floor(SimpleCallContext *context)
{
double v = context->argumentCount ? context->arguments[0].toNumber() : qSNaN();
- return Value::fromDouble(::floor(v));
+ return Encode(::floor(v));
}
-Value MathObject::method_log(SimpleCallContext *context)
+ReturnedValue MathObject::method_log(SimpleCallContext *context)
{
double v = context->argumentCount ? context->arguments[0].toNumber() : qSNaN();
if (v < 0)
- return Value::fromDouble(qSNaN());
+ return Encode(qSNaN());
else
- return Value::fromDouble(::log(v));
+ return Encode(::log(v));
}
-Value MathObject::method_max(SimpleCallContext *context)
+ReturnedValue MathObject::method_max(SimpleCallContext *context)
{
double mx = -qInf();
for (unsigned i = 0; i < context->argumentCount; ++i) {
@@ -209,10 +209,10 @@ Value MathObject::method_max(SimpleCallContext *context)
if (x > mx || std::isnan(x))
mx = x;
}
- return Value::fromDouble(mx);
+ return Encode(mx);
}
-Value MathObject::method_min(SimpleCallContext *context)
+ReturnedValue MathObject::method_min(SimpleCallContext *context)
{
double mx = qInf();
for (unsigned i = 0; i < context->argumentCount; ++i) {
@@ -222,34 +222,34 @@ Value MathObject::method_min(SimpleCallContext *context)
mx = x;
}
}
- return Value::fromDouble(mx);
+ return Encode(mx);
}
-Value MathObject::method_pow(SimpleCallContext *context)
+ReturnedValue MathObject::method_pow(SimpleCallContext *context)
{
double x = context->argumentCount > 0 ? context->arguments[0].toNumber() : qSNaN();
double y = context->argumentCount > 1 ? context->arguments[1].toNumber() : qSNaN();
if (std::isnan(y))
- return Value::fromDouble(qSNaN());
+ return Encode(qSNaN());
if (y == 0) {
- return Value::fromDouble(1);
+ return Encode(1);
} else if (((x == 1) || (x == -1)) && std::isinf(y)) {
- return Value::fromDouble(qSNaN());
+ return Encode(qSNaN());
} else if (((x == 0) && copySign(1.0, x) == 1.0) && (y < 0)) {
- return Value::fromDouble(qInf());
+ return Encode(qInf());
} else if ((x == 0) && copySign(1.0, x) == -1.0) {
if (y < 0) {
if (::fmod(-y, 2.0) == 1.0)
- return Value::fromDouble(-qInf());
+ return Encode(-qInf());
else
- return Value::fromDouble(qInf());
+ return Encode(qInf());
} else if (y > 0) {
if (::fmod(y, 2.0) == 1.0)
- return Value::fromDouble(copySign(0, -1.0));
+ return Encode(copySign(0, -1.0));
else
- return Value::fromDouble(0);
+ return Encode(0);
}
}
@@ -257,54 +257,54 @@ Value MathObject::method_pow(SimpleCallContext *context)
else if (qIsInf(x) && copySign(1.0, x) == -1.0) {
if (y > 0) {
if (::fmod(y, 2.0) == 1.0)
- return Value::fromDouble(-qInf());
+ return Encode(-qInf());
else
- return Value::fromDouble(qInf());
+ return Encode(qInf());
} else if (y < 0) {
if (::fmod(-y, 2.0) == 1.0)
- return Value::fromDouble(copySign(0, -1.0));
+ return Encode(copySign(0, -1.0));
else
- return Value::fromDouble(0);
+ return Encode(0);
}
}
#endif
else {
- return Value::fromDouble(::pow(x, y));
+ return Encode(::pow(x, y));
}
// ###
- return Value::fromDouble(qSNaN());
+ return Encode(qSNaN());
}
-Value MathObject::method_random(SimpleCallContext *)
+ReturnedValue MathObject::method_random(SimpleCallContext *)
{
- return Value::fromDouble(qrand() / (double) RAND_MAX);
+ return Encode(qrand() / (double) RAND_MAX);
}
-Value MathObject::method_round(SimpleCallContext *context)
+ReturnedValue MathObject::method_round(SimpleCallContext *context)
{
double v = context->argumentCount ? context->arguments[0].toNumber() : qSNaN();
v = copySign(::floor(v + 0.5), v);
- return Value::fromDouble(v);
+ return Encode(v);
}
-Value MathObject::method_sin(SimpleCallContext *context)
+ReturnedValue MathObject::method_sin(SimpleCallContext *context)
{
double v = context->argumentCount ? context->arguments[0].toNumber() : qSNaN();
- return Value::fromDouble(::sin(v));
+ return Encode(::sin(v));
}
-Value MathObject::method_sqrt(SimpleCallContext *context)
+ReturnedValue MathObject::method_sqrt(SimpleCallContext *context)
{
double v = context->argumentCount ? context->arguments[0].toNumber() : qSNaN();
- return Value::fromDouble(::sqrt(v));
+ return Encode(::sqrt(v));
}
-Value MathObject::method_tan(SimpleCallContext *context)
+ReturnedValue MathObject::method_tan(SimpleCallContext *context)
{
double v = context->argumentCount ? context->arguments[0].toNumber() : qSNaN();
if (v == 0.0)
- return Value::fromDouble(v);
+ return Encode(v);
else
- return Value::fromDouble(::tan(v));
+ return Encode(::tan(v));
}
diff --git a/src/qml/jsruntime/qv4mathobject_p.h b/src/qml/jsruntime/qv4mathobject_p.h
index 03c36bcc68..cdadc875f9 100644
--- a/src/qml/jsruntime/qv4mathobject_p.h
+++ b/src/qml/jsruntime/qv4mathobject_p.h
@@ -51,24 +51,24 @@ struct MathObject: Object
{
MathObject(ExecutionContext *ctx);
- static Value method_abs(SimpleCallContext *context);
- static Value method_acos(SimpleCallContext *context);
- static Value method_asin(SimpleCallContext *context);
- static Value method_atan(SimpleCallContext *context);
- static Value method_atan2(SimpleCallContext *context);
- static Value method_ceil(SimpleCallContext *context);
- static Value method_cos(SimpleCallContext *context);
- static Value method_exp(SimpleCallContext *context);
- static Value method_floor(SimpleCallContext *context);
- static Value method_log(SimpleCallContext *context);
- static Value method_max(SimpleCallContext *context);
- static Value method_min(SimpleCallContext *context);
- static Value method_pow(SimpleCallContext *context);
- static Value method_random(SimpleCallContext *context);
- static Value method_round(SimpleCallContext *context);
- static Value method_sin(SimpleCallContext *context);
- static Value method_sqrt(SimpleCallContext *context);
- static Value method_tan(SimpleCallContext *context);
+ static ReturnedValue method_abs(SimpleCallContext *context);
+ static ReturnedValue method_acos(SimpleCallContext *context);
+ static ReturnedValue method_asin(SimpleCallContext *context);
+ static ReturnedValue method_atan(SimpleCallContext *context);
+ static ReturnedValue method_atan2(SimpleCallContext *context);
+ static ReturnedValue method_ceil(SimpleCallContext *context);
+ static ReturnedValue method_cos(SimpleCallContext *context);
+ static ReturnedValue method_exp(SimpleCallContext *context);
+ static ReturnedValue method_floor(SimpleCallContext *context);
+ static ReturnedValue method_log(SimpleCallContext *context);
+ static ReturnedValue method_max(SimpleCallContext *context);
+ static ReturnedValue method_min(SimpleCallContext *context);
+ static ReturnedValue method_pow(SimpleCallContext *context);
+ static ReturnedValue method_random(SimpleCallContext *context);
+ static ReturnedValue method_round(SimpleCallContext *context);
+ static ReturnedValue method_sin(SimpleCallContext *context);
+ static ReturnedValue method_sqrt(SimpleCallContext *context);
+ static ReturnedValue method_tan(SimpleCallContext *context);
};
}
diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/jsruntime/qv4mm.cpp
index 874c349c42..2d53fa3fe5 100644
--- a/src/qml/jsruntime/qv4mm.cpp
+++ b/src/qml/jsruntime/qv4mm.cpp
@@ -55,6 +55,7 @@
#include <iostream>
#include <cstdlib>
+#include <algorithm>
#include "qv4alloca_p.h"
#ifdef V4_USE_VALGRIND
@@ -215,7 +216,7 @@ Managed *MemoryManager::alloc(std::size_t size)
allocation.memory = PageAllocation::allocate(allocSize, OSAllocator::JSGCHeapPages);
allocation.chunkSize = size;
m_d->heapChunks.append(allocation);
- qSort(m_d->heapChunks);
+ std::sort(m_d->heapChunks.begin(), m_d->heapChunks.end());
char *chunk = (char *)allocation.memory.base();
char *end = chunk + allocation.memory.size() - size;
memset(chunk, 0, allocation.memory.size());
@@ -581,7 +582,7 @@ void MemoryManager::collectFromStack() const
if (genericPtr < *heapChunkBoundaries || genericPtr > *(heapChunkBoundariesEnd - 1))
continue;
- int index = qLowerBound(heapChunkBoundaries, heapChunkBoundariesEnd, genericPtr) - heapChunkBoundaries;
+ int index = std::lower_bound(heapChunkBoundaries, heapChunkBoundariesEnd, genericPtr) - heapChunkBoundaries;
// An odd index means the pointer is _before_ the end of a heap chunk and therefore valid.
assert(index >= 0 && index < m_d->heapChunks.count() * 2);
if (index & 1) {
diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp
index ffcbca2ce5..3702428553 100644
--- a/src/qml/jsruntime/qv4numberobject.cpp
+++ b/src/qml/jsruntime/qv4numberobject.cpp
@@ -56,16 +56,16 @@ NumberCtor::NumberCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value NumberCtor::construct(Managed *m, CallData *callData)
+ReturnedValue NumberCtor::construct(Managed *m, CallData *callData)
{
double dbl = callData->argc ? callData->args[0].toNumber() : 0.;
- return Value::fromObject(m->engine()->newNumberObject(Value::fromDouble(dbl)));
+ return Encode(m->engine()->newNumberObject(Value::fromDouble(dbl)));
}
-Value NumberCtor::call(Managed *, CallData *callData)
+ReturnedValue NumberCtor::call(Managed *, CallData *callData)
{
double dbl = callData->argc ? callData->args[0].toNumber() : 0.;
- return Value::fromDouble(dbl);
+ return Value::fromDouble(dbl).asReturnedValue();
}
void NumberPrototype::init(ExecutionContext *ctx, const Value &ctor)
@@ -106,7 +106,7 @@ inline Value thisNumberValue(ExecutionContext *ctx)
return n->value;
}
-Value NumberPrototype::method_toString(SimpleCallContext *ctx)
+ReturnedValue NumberPrototype::method_toString(SimpleCallContext *ctx)
{
double num = thisNumberValue(ctx).asDouble();
@@ -116,13 +116,13 @@ Value NumberPrototype::method_toString(SimpleCallContext *ctx)
if (radix < 2 || radix > 36) {
ctx->throwError(QString::fromLatin1("Number.prototype.toString: %0 is not a valid radix")
.arg(radix));
- return Value::undefinedValue();
+ return Encode::undefined();
}
if (std::isnan(num)) {
- return Value::fromString(ctx, QStringLiteral("NaN"));
+ return Value::fromString(ctx, QStringLiteral("NaN")).asReturnedValue();
} else if (qIsInf(num)) {
- return Value::fromString(ctx, QLatin1String(num < 0 ? "-Infinity" : "Infinity"));
+ return Value::fromString(ctx, QLatin1String(num < 0 ? "-Infinity" : "Infinity")).asReturnedValue();
}
if (radix != 10) {
@@ -152,28 +152,28 @@ Value NumberPrototype::method_toString(SimpleCallContext *ctx)
}
if (negative)
str.prepend(QLatin1Char('-'));
- return Value::fromString(ctx, str);
+ return Value::fromString(ctx, str).asReturnedValue();
}
}
String *str = Value::fromDouble(num).toString(ctx);
- return Value::fromString(str);
+ return Value::fromString(str).asReturnedValue();
}
-Value NumberPrototype::method_toLocaleString(SimpleCallContext *ctx)
+ReturnedValue NumberPrototype::method_toLocaleString(SimpleCallContext *ctx)
{
Value v = thisNumberValue(ctx);
String *str = v.toString(ctx);
- return Value::fromString(str);
+ return Value::fromString(str).asReturnedValue();
}
-Value NumberPrototype::method_valueOf(SimpleCallContext *ctx)
+ReturnedValue NumberPrototype::method_valueOf(SimpleCallContext *ctx)
{
- return thisNumberValue(ctx);
+ return thisNumberValue(ctx).asReturnedValue();
}
-Value NumberPrototype::method_toFixed(SimpleCallContext *ctx)
+ReturnedValue NumberPrototype::method_toFixed(SimpleCallContext *ctx)
{
double v = thisNumberValue(ctx).asDouble();
@@ -196,11 +196,11 @@ Value NumberPrototype::method_toFixed(SimpleCallContext *ctx)
else if (v < 1.e21)
str = QString::number(v, 'f', int (fdigits));
else
- return __qmljs_string_from_number(ctx, v);
- return Value::fromString(ctx, str);
+ return __qmljs_string_from_number(ctx, v)->asReturnedValue();
+ return Value::fromString(ctx, str).asReturnedValue();
}
-Value NumberPrototype::method_toExponential(SimpleCallContext *ctx)
+ReturnedValue NumberPrototype::method_toExponential(SimpleCallContext *ctx)
{
double d = thisNumberValue(ctx).asDouble();
@@ -220,12 +220,12 @@ Value NumberPrototype::method_toExponential(SimpleCallContext *ctx)
double_conversion::DoubleToStringConverter::EcmaScriptConverter().ToExponential(d, fdigits, &builder);
QString result = QString::fromLatin1(builder.Finalize());
- return Value::fromString(ctx, result);
+ return Value::fromString(ctx, result).asReturnedValue();
}
-Value NumberPrototype::method_toPrecision(SimpleCallContext *ctx)
+ReturnedValue NumberPrototype::method_toPrecision(SimpleCallContext *ctx)
{
- ValueScope scope(ctx);
+ Scope scope(ctx);
ScopedValue v(scope, thisNumberValue(ctx));
@@ -244,5 +244,5 @@ Value NumberPrototype::method_toPrecision(SimpleCallContext *ctx)
double_conversion::DoubleToStringConverter::EcmaScriptConverter().ToPrecision(v->asDouble(), precision, &builder);
QString result = QString::fromLatin1(builder.Finalize());
- return Value::fromString(ctx, result);
+ return Value::fromString(ctx, result).asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h
index a0c2a65e80..d2c4ce6569 100644
--- a/src/qml/jsruntime/qv4numberobject_p.h
+++ b/src/qml/jsruntime/qv4numberobject_p.h
@@ -51,13 +51,11 @@ namespace QV4 {
struct NumberCtor: FunctionObject
{
+ Q_MANAGED
NumberCtor(ExecutionContext *scope);
- static Value construct(Managed *that, CallData *callData);
- static Value call(Managed *, CallData *callData);
-
-protected:
- static const ManagedVTable static_vtbl;
+ static ReturnedValue construct(Managed *that, CallData *callData);
+ static ReturnedValue call(Managed *, CallData *callData);
};
struct NumberPrototype: NumberObject
@@ -65,12 +63,12 @@ struct NumberPrototype: NumberObject
NumberPrototype(InternalClass *ic): NumberObject(ic) {}
void init(ExecutionContext *ctx, const Value &ctor);
- static Value method_toString(SimpleCallContext *ctx);
- static Value method_toLocaleString(SimpleCallContext *ctx);
- static Value method_valueOf(SimpleCallContext *ctx);
- static Value method_toFixed(SimpleCallContext *ctx);
- static Value method_toExponential(SimpleCallContext *ctx);
- static Value method_toPrecision(SimpleCallContext *ctx);
+ static ReturnedValue method_toString(SimpleCallContext *ctx);
+ static ReturnedValue method_toLocaleString(SimpleCallContext *ctx);
+ static ReturnedValue method_valueOf(SimpleCallContext *ctx);
+ static ReturnedValue method_toFixed(SimpleCallContext *ctx);
+ static ReturnedValue method_toExponential(SimpleCallContext *ctx);
+ static ReturnedValue method_toPrecision(SimpleCallContext *ctx);
};
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 14584da46d..4f7e2966f1 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -127,15 +127,16 @@ void Object::put(ExecutionContext *ctx, const QString &name, const Value &value)
put(ctx->engine->newString(name), value);
}
-Value Object::getValue(const Value &thisObject, const Property *p, PropertyAttributes attrs)
+ReturnedValue Object::getValue(const Value &thisObject, const Property *p, PropertyAttributes attrs)
{
if (!attrs.isAccessor())
- return p->value;
+ return p->value.asReturnedValue();
FunctionObject *getter = p->getter();
if (!getter)
- return Value::undefinedValue();
+ return Value::undefinedValue().asReturnedValue();
- ScopedCallData callData(getter->engine(), 0);
+ Scope scope(getter->engine());
+ ScopedCallData callData(scope, 0);
callData->thisObject = thisObject;
return getter->call(callData);
}
@@ -144,7 +145,8 @@ void Object::putValue(Property *pd, PropertyAttributes attrs, const Value &value
{
if (attrs.isAccessor()) {
if (pd->set) {
- ScopedCallData callData(pd->set->engine(), 1);
+ Scope scope(pd->set->engine());
+ ScopedCallData callData(scope, 1);
callData->args[0] = value;
callData->thisObject = Value::fromObject(this);
pd->set->call(callData);
@@ -167,22 +169,20 @@ void Object::putValue(Property *pd, PropertyAttributes attrs, const Value &value
void Object::inplaceBinOp(ExecutionContext *ctx, BinOp op, String *name, const ValueRef rhs)
{
- ValueScope scope(ctx);
+ Scope scope(ctx);
ScopedValue v(scope, get(name));
- ScopedValue result(scope);
- op(result, v, rhs);
+ ScopedValue result(scope, op(v, rhs));
put(name, result);
}
void Object::inplaceBinOp(ExecutionContext *ctx, BinOp op, const ValueRef index, const ValueRef rhs)
{
- ValueScope scope(ctx);
+ Scope scope(ctx);
uint idx = index->asArrayIndex();
if (idx < UINT_MAX) {
bool hasProperty = false;
ScopedValue v(scope, getIndexed(idx, &hasProperty));
- ScopedValue result(scope);
- op(result, v, rhs);
+ ScopedValue result(scope, op(v, rhs));
putIndexed(idx, result);
return;
}
@@ -193,22 +193,20 @@ void Object::inplaceBinOp(ExecutionContext *ctx, BinOp op, const ValueRef index,
void Object::inplaceBinOp(ExecutionContext *ctx, BinOpContext op, String *name, const ValueRef rhs)
{
- ValueScope scope(ctx);
+ Scope scope(ctx);
ScopedValue v(scope, get(name));
- ScopedValue result(scope);
- op(ctx, result, v, rhs);
+ ScopedValue result(scope, op(ctx, v, rhs));
put(name, result);
}
void Object::inplaceBinOp(ExecutionContext *ctx, BinOpContext op, const ValueRef index, const ValueRef rhs)
{
- ValueScope scope(ctx);
+ Scope scope(ctx);
uint idx = index->asArrayIndex();
if (idx < UINT_MAX) {
bool hasProperty = false;
ScopedValue v(scope, getIndexed(idx, &hasProperty));
- ScopedValue result(scope);
- op(ctx, result, v, rhs);
+ ScopedValue result(scope, op(ctx, v, rhs));
putIndexed(idx, result);
return;
}
@@ -233,7 +231,7 @@ void Object::defineDefaultProperty(ExecutionEngine *engine, const QString &name,
defineDefaultProperty(engine->newIdentifier(name), value);
}
-void Object::defineDefaultProperty(ExecutionContext *context, const QString &name, Value (*code)(SimpleCallContext *), int argumentCount)
+void Object::defineDefaultProperty(ExecutionContext *context, const QString &name, ReturnedValue (*code)(SimpleCallContext *), int argumentCount)
{
Q_UNUSED(argumentCount);
String *s = context->engine->newIdentifier(name);
@@ -242,7 +240,7 @@ void Object::defineDefaultProperty(ExecutionContext *context, const QString &nam
defineDefaultProperty(s, Value::fromObject(function));
}
-void Object::defineDefaultProperty(ExecutionEngine *engine, const QString &name, Value (*code)(SimpleCallContext *), int argumentCount)
+void Object::defineDefaultProperty(ExecutionEngine *engine, const QString &name, ReturnedValue (*code)(SimpleCallContext *), int argumentCount)
{
Q_UNUSED(argumentCount);
String *s = engine->newIdentifier(name);
@@ -252,13 +250,13 @@ void Object::defineDefaultProperty(ExecutionEngine *engine, const QString &name,
}
void Object::defineAccessorProperty(ExecutionEngine *engine, const QString &name,
- Value (*getter)(SimpleCallContext *), Value (*setter)(SimpleCallContext *))
+ ReturnedValue (*getter)(SimpleCallContext *), ReturnedValue (*setter)(SimpleCallContext *))
{
String *s = engine->newString(name);
defineAccessorProperty(s, getter, setter);
}
-void Object::defineAccessorProperty(String *name, Value (*getter)(SimpleCallContext *), Value (*setter)(SimpleCallContext *))
+void Object::defineAccessorProperty(String *name, ReturnedValue (*getter)(SimpleCallContext *), ReturnedValue (*setter)(SimpleCallContext *))
{
ExecutionEngine *v4 = engine();
Property *p = insertMember(name, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
@@ -451,12 +449,12 @@ bool Object::__hasProperty__(uint index) const
return false;
}
-Value Object::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue Object::get(Managed *m, String *name, bool *hasProperty)
{
return static_cast<Object *>(m)->internalGet(name, hasProperty);
}
-Value Object::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue Object::getIndexed(Managed *m, uint index, bool *hasProperty)
{
return static_cast<Object *>(m)->internalGetIndexed(index, hasProperty);
}
@@ -512,7 +510,7 @@ bool Object::deleteIndexedProperty(Managed *m, uint index)
return static_cast<Object *>(m)->internalDeleteIndexedProperty(index);
}
-void Object::getLookup(Managed *m, Lookup *l, Value *result)
+ReturnedValue Object::getLookup(Managed *m, Lookup *l)
{
Object *o = static_cast<Object *>(m);
PropertyAttributes attrs;
@@ -525,9 +523,7 @@ void Object::getLookup(Managed *m, Lookup *l, Value *result)
l->getter = Lookup::getter1;
else if (l->level == 2)
l->getter = Lookup::getter2;
- if (result)
- *result = p->value;
- return;
+ return p->value.asReturnedValue();
} else {
if (l->level == 0)
l->getter = Lookup::getterAccessor0;
@@ -535,16 +531,10 @@ void Object::getLookup(Managed *m, Lookup *l, Value *result)
l->getter = Lookup::getterAccessor1;
else if (l->level == 2)
l->getter = Lookup::getterAccessor2;
- if (result)
- *result = p->value;
- Value res = o->getValue(p, attrs);
- if (result)
- *result = res;
- return;
+ return o->getValue(p, attrs);
}
- } else if (result) {
- *result = Value::undefinedValue();
}
+ return Value::undefinedValue().asReturnedValue();
}
void Object::setLookup(Managed *m, Lookup *l, const Value &value)
@@ -656,7 +646,7 @@ Property *Object::advanceIterator(Managed *m, ObjectIterator *it, String **name,
}
// Section 8.12.3
-Value Object::internalGet(String *name, bool *hasProperty)
+ReturnedValue Object::internalGet(String *name, bool *hasProperty)
{
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
@@ -678,10 +668,10 @@ Value Object::internalGet(String *name, bool *hasProperty)
if (hasProperty)
*hasProperty = false;
- return Value::undefinedValue();
+ return Value::undefinedValue().asReturnedValue();
}
-Value Object::internalGetIndexed(uint index, bool *hasProperty)
+ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty)
{
Property *pd = 0;
PropertyAttributes attrs = Attr_Data;
@@ -714,7 +704,7 @@ Value Object::internalGetIndexed(uint index, bool *hasProperty)
if (hasProperty)
*hasProperty = false;
- return Value::undefinedValue();
+ return Value::undefinedValue().asReturnedValue();
}
@@ -778,7 +768,8 @@ void Object::internalPut(String *name, const Value &value)
if (pd && attrs.isAccessor()) {
assert(pd->setter() != 0);
- ScopedCallData callData(engine(), 1);
+ Scope scope(engine());
+ ScopedCallData callData(scope, 1);
callData->args[0] = value;
callData->thisObject = Value::fromObject(this);
pd->setter()->call(callData);
@@ -856,7 +847,8 @@ void Object::internalPutIndexed(uint index, const Value &value)
if (pd && attrs.isAccessor()) {
assert(pd->setter() != 0);
- ScopedCallData callData(engine(), 1);
+ Scope scope(engine());
+ ScopedCallData callData(scope, 1);
callData->args[0] = value;
callData->thisObject = Value::fromObject(this);
pd->setter()->call(callData);
@@ -1116,7 +1108,7 @@ void Object::copyArrayData(Object *other)
Q_ASSERT(len);
for (uint i = 0; i < len; ++i) {
- arraySet(i, other->getIndexed(i));
+ arraySet(i, Value::fromReturnedValue(other->getIndexed(i)));
}
} else {
arrayReserve(other->arrayDataLen);
@@ -1135,9 +1127,9 @@ void Object::copyArrayData(Object *other)
}
-Value Object::arrayIndexOf(Value v, uint fromIndex, uint endIndex, ExecutionContext *ctx, Object *o)
+ReturnedValue Object::arrayIndexOf(Value v, uint fromIndex, uint endIndex, ExecutionContext *ctx, Object *o)
{
- ValueScope scope(engine());
+ Scope scope(engine());
ScopedValue value(scope);
if (o->protoHasArray() || o->arrayAttributes) {
@@ -1146,13 +1138,13 @@ Value Object::arrayIndexOf(Value v, uint fromIndex, uint endIndex, ExecutionCont
bool exists;
value = o->getIndexed(i, &exists);
if (exists && __qmljs_strict_equal(value, ValueRef(&v)))
- return Value::fromDouble(i);
+ return Encode(i);
}
} else if (sparseArray) {
for (SparseArrayNode *n = sparseArray->lowerBound(fromIndex); n != sparseArray->end() && n->key() < endIndex; n = n->nextNode()) {
value = o->getValue(arrayData + n->value, arrayAttributes ? arrayAttributes[n->value] : Attr_Data);
if (__qmljs_strict_equal(value, ValueRef(&v)))
- return Value::fromDouble(n->key());
+ return Encode(n->key());
}
} else {
if ((int) endIndex > arrayDataLen)
@@ -1164,12 +1156,12 @@ Value Object::arrayIndexOf(Value v, uint fromIndex, uint endIndex, ExecutionCont
if (!arrayAttributes || !arrayAttributes[pd - arrayData].isGeneric()) {
value = o->getValue(pd, arrayAttributes ? arrayAttributes[pd - arrayData] : Attr_Data);
if (__qmljs_strict_equal(value, ValueRef(&v)))
- return Value::fromDouble(pd - arrayData);
+ return Encode((uint)(pd - arrayData));
}
++pd;
}
}
- return Value::fromInt32(-1);
+ return Encode(-1);
}
void Object::arrayConcat(const ArrayObject *other)
@@ -1204,7 +1196,7 @@ void Object::arrayConcat(const ArrayObject *other)
if (other->arrayAttributes) {
for (int i = 0; i < arrayDataLen; ++i) {
bool exists;
- arrayData[oldSize + i].value = const_cast<ArrayObject *>(other)->getIndexed(i, &exists);
+ arrayData[oldSize + i].value = Value::fromReturnedValue(const_cast<ArrayObject *>(other)->getIndexed(i, &exists));
if (arrayAttributes)
arrayAttributes[oldSize + i] = Attr_Data;
if (!exists) {
@@ -1244,11 +1236,11 @@ void Object::arraySort(ExecutionContext *context, Object *thisObject, const Valu
while (--len > i)
if (!arrayAttributes[len].isGeneric())
break;
- arrayData[i].value = getValue(arrayData + len, arrayAttributes[len]);
+ arrayData[i].value = Value::fromReturnedValue(getValue(arrayData + len, arrayAttributes[len]));
arrayAttributes[i] = Attr_Data;
arrayAttributes[len].clear();
} else if (arrayAttributes[i].isAccessor()) {
- arrayData[i].value = getValue(arrayData + i, arrayAttributes[i]);
+ arrayData[i].value = Value::fromReturnedValue(getValue(arrayData + i, arrayAttributes[i]));
arrayAttributes[i] = Attr_Data;
}
}
@@ -1380,7 +1372,7 @@ bool Object::setArrayLength(uint newLen) {
arrayAttributes[it->value].clear();
}
}
- pd.value.tag = Value::_Empty_Type;
+ pd.value.tag = Value::Empty_Type;
pd.value.int_32 = arrayFreeList;
arrayFreeList = it->value;
bool brk = (it == begin);
@@ -1432,6 +1424,8 @@ void Object::markArrayObjects() const
}
}
+DEFINE_MANAGED_VTABLE(ArrayObject);
+
ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list)
: Object(engine->arrayClass)
{
@@ -1460,10 +1454,14 @@ QStringList ArrayObject::toQStringList() const
QStringList result;
QV4::ExecutionEngine *engine = internalClass->engine;
+ Scope scope(engine);
+ ScopedValue v(scope);
uint32_t length = arrayLength();
- for (uint32_t i = 0; i < length; ++i)
- result.append(const_cast<ArrayObject *>(this)->getIndexed(i).toString(engine->current)->toQString());
+ for (uint32_t i = 0; i < length; ++i) {
+ v = const_cast<ArrayObject *>(this)->getIndexed(i);
+ result.append(v->toString(engine->current)->toQString());
+ }
return result;
}
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index c6329b9665..7cb3fe45c2 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -105,6 +105,7 @@ typedef Value (*PropertyEnumeratorFunction)(Object *object);
typedef PropertyAttributes (*PropertyQueryFunction)(const Object *object, String *name);
struct Q_QML_EXPORT Object: Managed {
+ Q_MANAGED
uint memberDataAlloc;
Property *memberData;
@@ -149,8 +150,8 @@ struct Q_QML_EXPORT Object: Managed {
//
void put(ExecutionContext *ctx, const QString &name, const Value &value);
- static Value getValue(const Value &thisObject, const Property *p, PropertyAttributes attrs);
- Value getValue(const Property *p, PropertyAttributes attrs) const {
+ static ReturnedValue getValue(const Value &thisObject, const Property *p, PropertyAttributes attrs);
+ ReturnedValue getValue(const Property *p, PropertyAttributes attrs) const {
return getValue(Value::fromObject(const_cast<Object *>(this)), p, attrs);
}
@@ -165,10 +166,10 @@ struct Q_QML_EXPORT Object: Managed {
void defineDefaultProperty(String *name, Value value);
void defineDefaultProperty(ExecutionContext *context, const QString &name, Value value);
void defineDefaultProperty(ExecutionEngine *engine, const QString &name, Value value);
- void defineDefaultProperty(ExecutionContext *context, const QString &name, Value (*code)(SimpleCallContext *), int count = 0);
- void defineDefaultProperty(ExecutionEngine *engine, const QString &name, Value (*code)(SimpleCallContext *), int count = 0);
- void defineAccessorProperty(ExecutionEngine *engine, const QString &name, Value (*getter)(SimpleCallContext *), Value (*setter)(SimpleCallContext *));
- void defineAccessorProperty(String *name, Value (*getter)(SimpleCallContext *), Value (*setter)(SimpleCallContext *));
+ void defineDefaultProperty(ExecutionContext *context, const QString &name, ReturnedValue (*code)(SimpleCallContext *), int count = 0);
+ void defineDefaultProperty(ExecutionEngine *engine, const QString &name, ReturnedValue (*code)(SimpleCallContext *), int count = 0);
+ void defineAccessorProperty(ExecutionEngine *engine, const QString &name, ReturnedValue (*getter)(SimpleCallContext *), ReturnedValue (*setter)(SimpleCallContext *));
+ void defineAccessorProperty(String *name, ReturnedValue (*getter)(SimpleCallContext *), ReturnedValue (*setter)(SimpleCallContext *));
/* Fixed: Writable: false, Enumerable: false, Configurable: false */
void defineReadonlyProperty(ExecutionEngine *engine, const QString &name, Value value);
void defineReadonlyProperty(String *name, Value value);
@@ -177,6 +178,10 @@ 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() {
@@ -197,7 +202,7 @@ struct Q_QML_EXPORT Object: Managed {
}
void freeArrayValue(int idx) {
Property &pd = arrayData[idx];
- pd.value.tag = Value::_Empty_Type;
+ pd.value.tag = Value::Empty_Type;
pd.value.int_32 = arrayFreeList;
arrayFreeList = idx;
if (arrayAttributes)
@@ -271,13 +276,14 @@ public:
void arrayConcat(const ArrayObject *other);
void arraySort(ExecutionContext *context, Object *thisObject, const Value &comparefn, uint arrayDataLen);
- Value arrayIndexOf(Value v, uint fromIndex, uint arrayDataLen, ExecutionContext *ctx, Object *o);
+ ReturnedValue arrayIndexOf(Value v, uint fromIndex, uint arrayDataLen, ExecutionContext *ctx, Object *o);
void arrayReserve(uint n);
void ensureArrayAttributes();
inline bool protoHasArray() {
- Object *p = this;
+ Scope scope(engine());
+ Scoped<Object> p(scope, this);
while ((p = p->prototype()))
if (p->arrayDataLen)
@@ -287,9 +293,9 @@ public:
}
void ensureMemberIndex(uint idx);
- inline Value get(String *name, bool *hasProperty = 0)
+ inline ReturnedValue get(String *name, bool *hasProperty = 0)
{ return vtbl->get(this, name, hasProperty); }
- inline Value getIndexed(uint idx, bool *hasProperty = 0)
+ inline ReturnedValue getIndexed(uint idx, bool *hasProperty = 0)
{ return vtbl->getIndexed(this, idx, hasProperty); }
inline void put(String *name, const Value &v)
{ vtbl->put(this, name, v); }
@@ -307,25 +313,24 @@ public:
using Managed::setLookup;
using Managed::advanceIterator;
protected:
- static const ManagedVTable static_vtbl;
static void destroy(Managed *that);
static void markObjects(Managed *that);
- static Value get(Managed *m, String *name, bool *hasProperty);
- static Value getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
static void putIndexed(Managed *m, uint index, const Value &value);
static PropertyAttributes query(const Managed *m, String *name);
static PropertyAttributes queryIndexed(const Managed *m, uint index);
static bool deleteProperty(Managed *m, String *name);
static bool deleteIndexedProperty(Managed *m, uint index);
- static void getLookup(Managed *m, Lookup *l, Value *result);
+ static ReturnedValue getLookup(Managed *m, Lookup *l);
static void setLookup(Managed *m, Lookup *l, const Value &v);
static Property *advanceIterator(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attributes);
private:
- Value internalGet(String *name, bool *hasProperty);
- Value internalGetIndexed(uint index, bool *hasProperty);
+ ReturnedValue internalGet(String *name, bool *hasProperty);
+ ReturnedValue internalGetIndexed(uint index, bool *hasProperty);
void internalPut(String *name, const Value &value);
void internalPutIndexed(uint index, const Value &value);
bool internalDeleteProperty(String *name);
@@ -344,7 +349,7 @@ struct ForEachIteratorObject: Object {
type = Type_ForeachIteratorObject;
}
- Value nextPropertyName() { return it.nextPropertyNameAsString(); }
+ ReturnedValue nextPropertyName() { return it.nextPropertyNameAsString(); }
protected:
static void markObjects(Managed *that);
@@ -365,6 +370,7 @@ protected:
};
struct ArrayObject: Object {
+ Q_MANAGED
enum {
LengthPropertyIndex = 0
};
diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp
index 338398c0d8..f03c2d6b86 100644
--- a/src/qml/jsruntime/qv4objectiterator.cpp
+++ b/src/qml/jsruntime/qv4objectiterator.cpp
@@ -92,38 +92,38 @@ Property *ObjectIterator::next(String **name, uint *index, PropertyAttributes *a
return 0;
}
-Value ObjectIterator::nextPropertyName(Value *value)
+ReturnedValue ObjectIterator::nextPropertyName(Value *value)
{
PropertyAttributes attrs;
uint index;
String *name;
Property *p = next(&name, &index, &attrs);
if (!p)
- return Value::nullValue();
+ return Encode::null();
if (value)
- *value = object->getValue(p, attrs);
+ *value = Value::fromReturnedValue(object->getValue(p, attrs));
if (name)
- return Value::fromString(name);
+ return Value::fromString(name).asReturnedValue();
assert(index < UINT_MAX);
- return Value::fromDouble(index);
+ return Encode(index);
}
-Value ObjectIterator::nextPropertyNameAsString(Value *value)
+ReturnedValue ObjectIterator::nextPropertyNameAsString(Value *value)
{
PropertyAttributes attrs;
uint index;
String *name;
Property *p = next(&name, &index, &attrs);
if (!p)
- return Value::nullValue();
+ return Encode::null();
if (value)
- *value = object->getValue(p, attrs);
+ *value = Value::fromReturnedValue(object->getValue(p, attrs));
if (name)
- return Value::fromString(name);
+ return Value::fromString(name).asReturnedValue();
assert(index < UINT_MAX);
- return Value::fromString(object->engine()->newString(QString::number(index)));
+ return Value::fromString(object->engine()->newString(QString::number(index))).asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4objectiterator_p.h b/src/qml/jsruntime/qv4objectiterator_p.h
index 95439397f5..d5464891f1 100644
--- a/src/qml/jsruntime/qv4objectiterator_p.h
+++ b/src/qml/jsruntime/qv4objectiterator_p.h
@@ -76,8 +76,8 @@ struct Q_QML_EXPORT ObjectIterator
ObjectIterator(Object *o, uint flags);
Property *next(String **name, uint *index, PropertyAttributes *attributes = 0);
- Value nextPropertyName(Value *value = 0);
- Value nextPropertyNameAsString(Value *value = 0);
+ ReturnedValue nextPropertyName(Value *value = 0);
+ ReturnedValue nextPropertyNameAsString(Value *value = 0);
};
}
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index 2f8f6375f0..073d588e56 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -79,24 +79,25 @@ ObjectCtor::ObjectCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value ObjectCtor::construct(Managed *that, CallData *callData)
+ReturnedValue ObjectCtor::construct(Managed *that, CallData *callData)
{
- ObjectCtor *ctor = static_cast<ObjectCtor *>(that);
ExecutionEngine *v4 = that->engine();
+ Scope scope(v4);
+ ObjectCtor *ctor = static_cast<ObjectCtor *>(that);
if (!callData->argc || callData->args[0].isUndefined() || callData->args[0].isNull()) {
Object *obj = v4->newObject();
- Value proto = ctor->get(v4->id_prototype);
- if (proto.isObject())
- obj->setPrototype(proto.objectValue());
- return Value::fromObject(obj);
+ Scoped<Object> proto(scope, ctor->get(v4->id_prototype));
+ if (!!proto)
+ obj->setPrototype(proto.getPointer());
+ return Value::fromObject(obj).asReturnedValue();
}
- return __qmljs_to_object(v4->current, ValueRef(&callData->args[0]));
+ return Value::fromReturnedValue(__qmljs_to_object(v4->current, ValueRef(&callData->args[0]))).asReturnedValue();
}
-Value ObjectCtor::call(Managed *m, 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());
+ return Value::fromObject(m->engine()->newObject()).asReturnedValue();
return __qmljs_to_object(m->engine()->current, ValueRef(&callData->args[0]));
}
@@ -134,17 +135,17 @@ void ObjectPrototype::init(ExecutionContext *ctx, const Value &ctor)
p->setSetter(v4->newBuiltinFunction(v4->rootContext, v4->id___proto__, method_set_proto));
}
-Value ObjectPrototype::method_getPrototypeOf(SimpleCallContext *ctx)
+ReturnedValue ObjectPrototype::method_getPrototypeOf(SimpleCallContext *ctx)
{
Value o = ctx->argument(0);
if (! o.isObject())
ctx->throwTypeError();
Object *p = o.objectValue()->prototype();
- return p ? Value::fromObject(p) : Value::nullValue();
+ return p ? Value::fromObject(p).asReturnedValue() : Encode::null();
}
-Value ObjectPrototype::method_getOwnPropertyDescriptor(SimpleCallContext *ctx)
+ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(SimpleCallContext *ctx)
{
Value O = ctx->argument(0);
if (!O.isObject())
@@ -156,17 +157,17 @@ Value ObjectPrototype::method_getOwnPropertyDescriptor(SimpleCallContext *ctx)
return fromPropertyDescriptor(ctx, desc, attrs);
}
-Value ObjectPrototype::method_getOwnPropertyNames(SimpleCallContext *context)
+ReturnedValue ObjectPrototype::method_getOwnPropertyNames(SimpleCallContext *context)
{
Object *O = context->argumentCount ? context->arguments[0].asObject() : 0;
if (!O)
context->throwTypeError();
ArrayObject *array = getOwnPropertyNames(context->engine, context->arguments[0]);
- return Value::fromObject(array);
+ return Value::fromObject(array).asReturnedValue();
}
-Value ObjectPrototype::method_create(SimpleCallContext *ctx)
+ReturnedValue ObjectPrototype::method_create(SimpleCallContext *ctx)
{
Value O = ctx->argument(0);
if (!O.isObject() && !O.isNull())
@@ -181,10 +182,10 @@ Value ObjectPrototype::method_create(SimpleCallContext *ctx)
method_defineProperties(ctx);
}
- return objValue;
+ return objValue.asReturnedValue();
}
-Value ObjectPrototype::method_defineProperty(SimpleCallContext *ctx)
+ReturnedValue ObjectPrototype::method_defineProperty(SimpleCallContext *ctx)
{
Value O = ctx->argument(0);
if (!O.isObject())
@@ -200,10 +201,10 @@ Value ObjectPrototype::method_defineProperty(SimpleCallContext *ctx)
if (!O.objectValue()->__defineOwnProperty__(ctx, name, pd, attrs))
ctx->throwTypeError();
- return O;
+ return O.asReturnedValue();
}
-Value ObjectPrototype::method_defineProperties(SimpleCallContext *ctx)
+ReturnedValue ObjectPrototype::method_defineProperties(SimpleCallContext *ctx)
{
Value O = ctx->argument(0);
if (!O.isObject())
@@ -221,7 +222,7 @@ Value ObjectPrototype::method_defineProperties(SimpleCallContext *ctx)
break;
Property n;
PropertyAttributes nattrs;
- toPropertyDescriptor(ctx, o->getValue(pd, attrs), &n, &nattrs);
+ toPropertyDescriptor(ctx, Value::fromReturnedValue(o->getValue(pd, attrs)), &n, &nattrs);
bool ok;
if (name)
ok = O.objectValue()->__defineOwnProperty__(ctx, name, n, nattrs);
@@ -231,10 +232,10 @@ Value ObjectPrototype::method_defineProperties(SimpleCallContext *ctx)
ctx->throwTypeError();
}
- return O;
+ return O.asReturnedValue();
}
-Value ObjectPrototype::method_seal(SimpleCallContext *ctx)
+ReturnedValue ObjectPrototype::method_seal(SimpleCallContext *ctx)
{
if (!ctx->argument(0).isObject())
ctx->throwTypeError();
@@ -250,10 +251,10 @@ Value ObjectPrototype::method_seal(SimpleCallContext *ctx)
o->arrayAttributes[i].setConfigurable(false);
}
- return ctx->argument(0);
+ return ctx->argument(0).asReturnedValue();
}
-Value ObjectPrototype::method_freeze(SimpleCallContext *ctx)
+ReturnedValue ObjectPrototype::method_freeze(SimpleCallContext *ctx)
{
if (!ctx->argument(0).isObject())
ctx->throwTypeError();
@@ -270,169 +271,171 @@ Value ObjectPrototype::method_freeze(SimpleCallContext *ctx)
if (o->arrayAttributes[i].isData())
o->arrayAttributes[i].setWritable(false);
}
- return ctx->argument(0);
+ return ctx->argument(0).asReturnedValue();
}
-Value ObjectPrototype::method_preventExtensions(SimpleCallContext *ctx)
+ReturnedValue ObjectPrototype::method_preventExtensions(SimpleCallContext *ctx)
{
if (!ctx->argument(0).isObject())
ctx->throwTypeError();
Object *o = ctx->argument(0).objectValue();
o->extensible = false;
- return ctx->argument(0);
+ return ctx->argument(0).asReturnedValue();
}
-Value ObjectPrototype::method_isSealed(SimpleCallContext *ctx)
+ReturnedValue ObjectPrototype::method_isSealed(SimpleCallContext *ctx)
{
if (!ctx->argument(0).isObject())
ctx->throwTypeError();
Object *o = ctx->argument(0).objectValue();
if (o->extensible)
- return Value::fromBoolean(false);
+ return Encode(false);
if (o->internalClass != o->internalClass->sealed())
- return Value::fromBoolean(false);
+ return Encode(false);
if (!o->arrayDataLen)
- return Value::fromBoolean(true);
+ return Encode(true);
if (!o->arrayAttributes)
- return Value::fromBoolean(false);
+ return Encode(false);
for (uint i = 0; i < o->arrayDataLen; ++i) {
if (!o->arrayAttributes[i].isGeneric())
if (o->arrayAttributes[i].isConfigurable())
- return Value::fromBoolean(false);
+ return Encode(false);
}
- return Value::fromBoolean(true);
+ return Encode(true);
}
-Value ObjectPrototype::method_isFrozen(SimpleCallContext *ctx)
+ReturnedValue ObjectPrototype::method_isFrozen(SimpleCallContext *ctx)
{
if (!ctx->argument(0).isObject())
ctx->throwTypeError();
Object *o = ctx->argument(0).objectValue();
if (o->extensible)
- return Value::fromBoolean(false);
+ return Encode(false);
if (o->internalClass != o->internalClass->frozen())
- return Value::fromBoolean(false);
+ return Encode(false);
if (!o->arrayDataLen)
- return Value::fromBoolean(true);
+ return Encode(true);
if (!o->arrayAttributes)
- return Value::fromBoolean(false);
+ return Encode(false);
for (uint i = 0; i < o->arrayDataLen; ++i) {
if (!o->arrayAttributes[i].isGeneric())
if (o->arrayAttributes[i].isConfigurable() || o->arrayAttributes[i].isWritable())
- return Value::fromBoolean(false);
+ return Encode(false);
}
- return Value::fromBoolean(true);
+ return Encode(true);
}
-Value ObjectPrototype::method_isExtensible(SimpleCallContext *ctx)
+ReturnedValue ObjectPrototype::method_isExtensible(SimpleCallContext *ctx)
{
if (!ctx->argument(0).isObject())
ctx->throwTypeError();
Object *o = ctx->argument(0).objectValue();
- return Value::fromBoolean(o->extensible);
+ return Encode((bool)o->extensible);
}
-Value ObjectPrototype::method_keys(SimpleCallContext *ctx)
+ReturnedValue ObjectPrototype::method_keys(SimpleCallContext *ctx)
{
if (!ctx->argument(0).isObject())
ctx->throwTypeError();
+ Scope scope(ctx);
Object *o = ctx->argument(0).objectValue();
- ArrayObject *a = ctx->engine->newArrayObject();
+ Scoped<ArrayObject> a(scope, ctx->engine->newArrayObject());
ObjectIterator it(o, ObjectIterator::EnumerableOnly);
+ ScopedValue name(scope);
while (1) {
- Value name = it.nextPropertyNameAsString();
- if (name.isNull())
+ name = it.nextPropertyNameAsString();
+ if (name->isNull())
break;
a->push_back(name);
}
- return Value::fromObject(a);
+ return a.asReturnedValue();
}
-Value ObjectPrototype::method_toString(SimpleCallContext *ctx)
+ReturnedValue ObjectPrototype::method_toString(SimpleCallContext *ctx)
{
if (ctx->thisObject.isUndefined()) {
- return Value::fromString(ctx, QStringLiteral("[object Undefined]"));
+ return Value::fromString(ctx, QStringLiteral("[object Undefined]")).asReturnedValue();
} else if (ctx->thisObject.isNull()) {
- return Value::fromString(ctx, QStringLiteral("[object Null]"));
+ return Value::fromString(ctx, QStringLiteral("[object Null]")).asReturnedValue();
} else {
- Value obj = __qmljs_to_object(ctx, ValueRef(&ctx->thisObject));
+ Value obj = Value::fromReturnedValue(__qmljs_to_object(ctx, ValueRef(&ctx->thisObject)));
QString className = obj.objectValue()->className();
- return Value::fromString(ctx, QString::fromUtf8("[object %1]").arg(className));
+ return Value::fromString(ctx, QString::fromUtf8("[object %1]").arg(className)).asReturnedValue();
}
}
-Value ObjectPrototype::method_toLocaleString(SimpleCallContext *ctx)
+ReturnedValue ObjectPrototype::method_toLocaleString(SimpleCallContext *ctx)
{
+ Scope scope(ctx);
Object *o = ctx->thisObject.toObject(ctx);
- Value ts = o->get(ctx->engine->newString(QStringLiteral("toString")));
- FunctionObject *f = ts.asFunctionObject();
+ Scoped<FunctionObject> f(scope, o->get(ctx->engine->newString(QStringLiteral("toString"))));
if (!f)
ctx->throwTypeError();
- ScopedCallData callData(ctx->engine, 0);
+ ScopedCallData callData(scope, 0);
callData->thisObject = Value::fromObject(o);
return f->call(callData);
}
-Value ObjectPrototype::method_valueOf(SimpleCallContext *ctx)
+ReturnedValue ObjectPrototype::method_valueOf(SimpleCallContext *ctx)
{
- return Value::fromObject(ctx->thisObject.toObject(ctx));
+ return Value::fromObject(ctx->thisObject.toObject(ctx)).asReturnedValue();
}
-Value ObjectPrototype::method_hasOwnProperty(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;
if (!r)
r = !O->query(P).isEmpty();
- return Value::fromBoolean(r);
+ return Encode(r);
}
-Value ObjectPrototype::method_isPrototypeOf(SimpleCallContext *ctx)
+ReturnedValue ObjectPrototype::method_isPrototypeOf(SimpleCallContext *ctx)
{
Value V = ctx->argument(0);
if (! V.isObject())
- return Value::fromBoolean(false);
+ return Encode(false);
Object *O = ctx->thisObject.toObject(ctx);
Object *proto = V.objectValue()->prototype();
while (proto) {
if (O == proto)
- return Value::fromBoolean(true);
+ return Encode(true);
proto = proto->prototype();
}
- return Value::fromBoolean(false);
+ return Encode(false);
}
-Value ObjectPrototype::method_propertyIsEnumerable(SimpleCallContext *ctx)
+ReturnedValue ObjectPrototype::method_propertyIsEnumerable(SimpleCallContext *ctx)
{
String *p = ctx->argument(0).toString(ctx);
Object *o = ctx->thisObject.toObject(ctx);
PropertyAttributes attrs;
o->__getOwnProperty__(p, &attrs);
- return Value::fromBoolean(attrs.isEnumerable());
+ return Encode(attrs.isEnumerable());
}
-Value ObjectPrototype::method_defineGetter(SimpleCallContext *ctx)
+ReturnedValue ObjectPrototype::method_defineGetter(SimpleCallContext *ctx)
{
if (ctx->argumentCount < 2)
ctx->throwTypeError();
@@ -445,16 +448,16 @@ Value ObjectPrototype::method_defineGetter(SimpleCallContext *ctx)
Object *o = ctx->thisObject.asObject();
if (!o) {
if (!ctx->thisObject.isUndefined())
- return Value::undefinedValue();
+ return Encode::undefined();
o = ctx->engine->globalObject;
}
Property pd = Property::fromAccessor(f, 0);
o->__defineOwnProperty__(ctx, prop, pd, Attr_Accessor);
- return Value::undefinedValue();
+ return Encode::undefined();
}
-Value ObjectPrototype::method_defineSetter(SimpleCallContext *ctx)
+ReturnedValue ObjectPrototype::method_defineSetter(SimpleCallContext *ctx)
{
if (ctx->argumentCount < 2)
ctx->throwTypeError();
@@ -467,25 +470,25 @@ Value ObjectPrototype::method_defineSetter(SimpleCallContext *ctx)
Object *o = ctx->thisObject.asObject();
if (!o) {
if (!ctx->thisObject.isUndefined())
- return Value::undefinedValue();
+ return Encode::undefined();
o = ctx->engine->globalObject;
}
Property pd = Property::fromAccessor(0, f);
o->__defineOwnProperty__(ctx, prop, pd, Attr_Accessor);
- return Value::undefinedValue();
+ return Encode::undefined();
}
-Value ObjectPrototype::method_get_proto(SimpleCallContext *ctx)
+ReturnedValue ObjectPrototype::method_get_proto(SimpleCallContext *ctx)
{
Object *o = ctx->thisObject.asObject();
if (!o)
ctx->throwTypeError();
- return Value::fromObject(o->prototype());
+ return Value::fromObject(o->prototype()).asReturnedValue();
}
-Value ObjectPrototype::method_set_proto(SimpleCallContext *ctx)
+ReturnedValue ObjectPrototype::method_set_proto(SimpleCallContext *ctx)
{
Object *o = ctx->thisObject.asObject();
if (!o)
@@ -505,7 +508,7 @@ Value ObjectPrototype::method_set_proto(SimpleCallContext *ctx)
}
if (!ok)
ctx->throwTypeError(QStringLiteral("Cyclic __proto__ value"));
- return Value::undefinedValue();
+ return Encode::undefined();
}
void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, Value v, Property *desc, PropertyAttributes *attrs)
@@ -513,6 +516,7 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, Value v, Prope
if (!v.isObject())
ctx->throwTypeError();
+ Scope scope(ctx);
Object *o = v.objectValue();
attrs->clear();
@@ -520,17 +524,17 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, Value v, Prope
desc->setSetter(0);
if (o->__hasProperty__(ctx->engine->id_enumerable))
- attrs->setEnumerable(o->get(ctx->engine->id_enumerable).toBoolean());
+ attrs->setEnumerable(Value::fromReturnedValue(o->get(ctx->engine->id_enumerable)).toBoolean());
if (o->__hasProperty__(ctx->engine->id_configurable))
- attrs->setConfigurable(o->get(ctx->engine->id_configurable).toBoolean());
+ attrs->setConfigurable(Value::fromReturnedValue(o->get(ctx->engine->id_configurable)).toBoolean());
if (o->__hasProperty__(ctx->engine->id_get)) {
- Value get = o->get(ctx->engine->id_get);
- FunctionObject *f = get.asFunctionObject();
+ ScopedValue get(scope, o->get(ctx->engine->id_get));
+ FunctionObject *f = get->asFunctionObject();
if (f) {
desc->setGetter(f);
- } else if (get.isUndefined()) {
+ } else if (get->isUndefined()) {
desc->setGetter((FunctionObject *)0x1);
} else {
ctx->throwTypeError();
@@ -539,11 +543,11 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, Value v, Prope
}
if (o->__hasProperty__(ctx->engine->id_set)) {
- Value set = o->get(ctx->engine->id_set);
- FunctionObject *f = set.asFunctionObject();
+ ScopedValue set(scope, o->get(ctx->engine->id_set));
+ FunctionObject *f = set->asFunctionObject();
if (f) {
desc->setSetter(f);
- } else if (set.isUndefined()) {
+ } else if (set->isUndefined()) {
desc->setSetter((FunctionObject *)0x1);
} else {
ctx->throwTypeError();
@@ -554,7 +558,7 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, Value v, Prope
if (o->__hasProperty__(ctx->engine->id_writable)) {
if (attrs->isAccessor())
ctx->throwTypeError();
- attrs->setWritable(o->get(ctx->engine->id_writable).toBoolean());
+ attrs->setWritable(Value::fromReturnedValue(o->get(ctx->engine->id_writable)).toBoolean());
// writable forces it to be a data descriptor
desc->value = Value::undefinedValue();
}
@@ -562,7 +566,7 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, Value v, Prope
if (o->__hasProperty__(ctx->engine->id_value)) {
if (attrs->isAccessor())
ctx->throwTypeError();
- desc->value = o->get(ctx->engine->id_value);
+ desc->value = Value::fromReturnedValue(o->get(ctx->engine->id_value));
attrs->setType(PropertyAttributes::Data);
}
@@ -571,10 +575,10 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, Value v, Prope
}
-Value ObjectPrototype::fromPropertyDescriptor(ExecutionContext *ctx, const Property *desc, PropertyAttributes attrs)
+ReturnedValue ObjectPrototype::fromPropertyDescriptor(ExecutionContext *ctx, const Property *desc, PropertyAttributes attrs)
{
if (!desc)
- return Value::undefinedValue();
+ return Encode::undefined();
ExecutionEngine *engine = ctx->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.
@@ -597,23 +601,25 @@ Value ObjectPrototype::fromPropertyDescriptor(ExecutionContext *ctx, const Prope
pd.value = Value::fromBoolean(attrs.isConfigurable());
o->__defineOwnProperty__(ctx, engine->newString(QStringLiteral("configurable")), pd, Attr_Data);
- return Value::fromObject(o);
+ return Value::fromObject(o).asReturnedValue();
}
ArrayObject *ObjectPrototype::getOwnPropertyNames(ExecutionEngine *v4, const Value &o)
{
- ArrayObject *array = v4->newArrayObject();
+ Scope scope(v4);
+ Scoped<ArrayObject> array(scope, v4->newArrayObject());
Object *O = o.asObject();
if (!O)
- return array;
+ return array.getPointer();
ObjectIterator it(O, ObjectIterator::NoFlags);
+ ScopedValue name(scope);
while (1) {
- Value name = it.nextPropertyNameAsString();
- if (name.isNull())
+ name = it.nextPropertyNameAsString();
+ if (name->isNull())
break;
array->push_back(name);
}
- return array;
+ return array.getPointer();
}
diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h
index 33a115f203..311d53864f 100644
--- a/src/qml/jsruntime/qv4objectproto_p.h
+++ b/src/qml/jsruntime/qv4objectproto_p.h
@@ -51,13 +51,11 @@ namespace QV4 {
struct ObjectCtor: FunctionObject
{
+ Q_MANAGED
ObjectCtor(ExecutionContext *scope);
- static Value construct(Managed *that, CallData *callData);
- static Value call(Managed *that, CallData *callData);
-
-protected:
- static const ManagedVTable static_vtbl;
+ static ReturnedValue construct(Managed *that, CallData *callData);
+ static ReturnedValue call(Managed *that, CallData *callData);
};
struct ObjectPrototype: Object
@@ -66,35 +64,35 @@ struct ObjectPrototype: Object
void init(ExecutionContext *ctx, const Value &ctor);
- static Value method_getPrototypeOf(SimpleCallContext *ctx);
- static Value method_getOwnPropertyDescriptor(SimpleCallContext *ctx);
- static Value method_getOwnPropertyNames(SimpleCallContext *context);
- static Value method_create(SimpleCallContext *ctx);
- static Value method_defineProperty(SimpleCallContext *ctx);
- static Value method_defineProperties(SimpleCallContext *ctx);
- static Value method_seal(SimpleCallContext *ctx);
- static Value method_freeze(SimpleCallContext *ctx);
- static Value method_preventExtensions(SimpleCallContext *ctx);
- static Value method_isSealed(SimpleCallContext *ctx);
- static Value method_isFrozen(SimpleCallContext *ctx);
- static Value method_isExtensible(SimpleCallContext *ctx);
- static Value method_keys(SimpleCallContext *ctx);
-
- static Value method_toString(SimpleCallContext *ctx);
- static Value method_toLocaleString(SimpleCallContext *ctx);
- static Value method_valueOf(SimpleCallContext *ctx);
- static Value method_hasOwnProperty(SimpleCallContext *ctx);
- static Value method_isPrototypeOf(SimpleCallContext *ctx);
- static Value method_propertyIsEnumerable(SimpleCallContext *ctx);
-
- static Value method_defineGetter(SimpleCallContext *ctx);
- static Value method_defineSetter(SimpleCallContext *ctx);
-
- static Value method_get_proto(SimpleCallContext *ctx);
- static Value method_set_proto(SimpleCallContext *ctx);
+ static ReturnedValue method_getPrototypeOf(SimpleCallContext *ctx);
+ static ReturnedValue method_getOwnPropertyDescriptor(SimpleCallContext *ctx);
+ static ReturnedValue method_getOwnPropertyNames(SimpleCallContext *context);
+ static ReturnedValue method_create(SimpleCallContext *ctx);
+ static ReturnedValue method_defineProperty(SimpleCallContext *ctx);
+ static ReturnedValue method_defineProperties(SimpleCallContext *ctx);
+ static ReturnedValue method_seal(SimpleCallContext *ctx);
+ static ReturnedValue method_freeze(SimpleCallContext *ctx);
+ static ReturnedValue method_preventExtensions(SimpleCallContext *ctx);
+ static ReturnedValue method_isSealed(SimpleCallContext *ctx);
+ static ReturnedValue method_isFrozen(SimpleCallContext *ctx);
+ static ReturnedValue method_isExtensible(SimpleCallContext *ctx);
+ static ReturnedValue method_keys(SimpleCallContext *ctx);
+
+ static ReturnedValue method_toString(SimpleCallContext *ctx);
+ static ReturnedValue method_toLocaleString(SimpleCallContext *ctx);
+ static ReturnedValue method_valueOf(SimpleCallContext *ctx);
+ static ReturnedValue method_hasOwnProperty(SimpleCallContext *ctx);
+ static ReturnedValue method_isPrototypeOf(SimpleCallContext *ctx);
+ static ReturnedValue method_propertyIsEnumerable(SimpleCallContext *ctx);
+
+ static ReturnedValue method_defineGetter(SimpleCallContext *ctx);
+ static ReturnedValue method_defineSetter(SimpleCallContext *ctx);
+
+ static ReturnedValue method_get_proto(SimpleCallContext *ctx);
+ static ReturnedValue method_set_proto(SimpleCallContext *ctx);
static void toPropertyDescriptor(ExecutionContext *ctx, Value v, Property *desc, PropertyAttributes *attrs);
- static Value fromPropertyDescriptor(ExecutionContext *ctx, const Property *desc, PropertyAttributes attrs);
+ static ReturnedValue fromPropertyDescriptor(ExecutionContext *ctx, const Property *desc, PropertyAttributes attrs);
static ArrayObject *getOwnPropertyNames(ExecutionEngine *v4, const Value &o);
};
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 1e868ef3fe..d774014073 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -138,30 +138,16 @@ struct ReadAccessor {
}
};
-static inline QV4::Value valueToHandle(QV4::ExecutionEngine *, int v)
-{ return QV4::Value::fromInt32(v); }
-static inline QV4::Value valueToHandle(QV4::ExecutionEngine *, uint v)
-{ return QV4::Value::fromUInt32(v); }
-static inline QV4::Value valueToHandle(QV4::ExecutionEngine *, bool v)
-{ return QV4::Value::fromBoolean(v); }
-static inline QV4::Value valueToHandle(QV4::ExecutionEngine *e, const QString &v)
-{ return QV4::Value::fromString(e, v); }
-static inline QV4::Value valueToHandle(QV4::ExecutionEngine *, float v)
-{ return QV4::Value::fromDouble(v); }
-static inline QV4::Value valueToHandle(QV4::ExecutionEngine *, double v)
-{ return QV4::Value::fromDouble(v); }
-static inline QV4::Value valueToHandle(QV4::ExecutionEngine *e, QObject *v)
-{ return QV4::QObjectWrapper::wrap(e, v); }
-
// Load value properties
template<void (*ReadFunction)(QObject *, const QQmlPropertyData &,
void *, QQmlNotifier **)>
-static QV4::Value LoadProperty(QV8Engine *engine, QObject *object,
+static QV4::ReturnedValue LoadProperty(QV8Engine *engine, QObject *object,
const QQmlPropertyData &property,
QQmlNotifier **notifier)
{
Q_ASSERT(!property.isFunction());
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
+ QV4::Scope scope(v4);
if (property.isQObject()) {
QObject *rv = 0;
@@ -172,35 +158,35 @@ static QV4::Value LoadProperty(QV8Engine *engine, QObject *object,
} else if (property.propType == QMetaType::QReal) {
qreal v = 0;
ReadFunction(object, property, &v, notifier);
- return valueToHandle(v4, v);
+ return QV4::Encode(v);
} else if (property.propType == QMetaType::Int || property.isEnum()) {
int v = 0;
ReadFunction(object, property, &v, notifier);
- return valueToHandle(v4, v);
+ return QV4::Encode(v);
} else if (property.propType == QMetaType::Bool) {
bool v = false;
ReadFunction(object, property, &v, notifier);
- return valueToHandle(v4, v);
+ return QV4::Encode(v);
} else if (property.propType == QMetaType::QString) {
QString v;
ReadFunction(object, property, &v, notifier);
- return valueToHandle(v4, v);
+ return Value::fromString(v4, v).asReturnedValue();
} else if (property.propType == QMetaType::UInt) {
uint v = 0;
ReadFunction(object, property, &v, notifier);
- return valueToHandle(v4, v);
+ return QV4::Encode(v);
} else if (property.propType == QMetaType::Float) {
float v = 0;
ReadFunction(object, property, &v, notifier);
- return valueToHandle(v4, v);
+ return QV4::Encode(v);
} else if (property.propType == QMetaType::Double) {
double v = 0;
ReadFunction(object, property, &v, notifier);
- return valueToHandle(v4, v);
+ return QV4::Encode(v);
} else if (property.isV4Handle()) {
QQmlV4Handle handle;
ReadFunction(object, property, &handle, notifier);
- return handle.toValue();
+ return handle.toValue().asReturnedValue();
} else if (property.propType == qMetaTypeId<QJSValue>()) {
QJSValue v;
ReadFunction(object, property, &v, notifier);
@@ -225,16 +211,16 @@ static QV4::Value LoadProperty(QV8Engine *engine, QObject *object,
// see if it's a sequence type
bool succeeded = false;
- QV4::Value retn = QV4::SequencePrototype::newSequence(v4, property.propType, object, property.coreIndex, &succeeded);
+ QV4::ScopedValue retn(scope, QV4::SequencePrototype::newSequence(v4, property.propType, object, property.coreIndex, &succeeded));
if (succeeded)
- return retn;
+ return retn.asReturnedValue();
}
if (property.propType == QMetaType::UnknownType) {
QMetaProperty p = object->metaObject()->property(property.coreIndex);
qWarning("QMetaProperty::read: Unable to handle unregistered datatype '%s' for property "
"'%s::%s'", p.typeName(), object->metaObject()->className(), p.name());
- return QV4::Value::undefinedValue();
+ return QV4::Encode::undefined();
} else {
QVariant v(property.propType, (void *)0);
ReadFunction(object, property, v.data(), notifier);
@@ -271,20 +257,23 @@ QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QQmlCont
return result;
}
-Value QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, String *name, QObjectWrapper::RevisionMode revisionMode, bool *hasProperty, bool includeImports)
+ReturnedValue QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, String *name, QObjectWrapper::RevisionMode revisionMode,
+ bool *hasProperty, bool includeImports)
{
if (QQmlData::wasDeleted(m_object)) {
if (hasProperty)
*hasProperty = false;
- return QV4::Value::undefinedValue();
+ return QV4::Encode::undefined();
}
+ QV4:Scope scope(ctx);
+
if (name->isEqualTo(m_destroy) || name->isEqualTo(m_toString)) {
int index = name->isEqualTo(m_destroy) ? QV4::QObjectMethod::DestroyMethod : QV4::QObjectMethod::ToStringMethod;
- QV4::Value method = QV4::QObjectMethod::create(ctx->engine->rootContext, m_object, index);
+ QV4::ScopedValue method(scope, QV4::QObjectMethod::create(ctx->engine->rootContext, m_object, index));
if (hasProperty)
*hasProperty = true;
- return method;
+ return method.asReturnedValue();
}
QQmlPropertyData local;
@@ -301,7 +290,7 @@ Value QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextData *qml
if (r.isValid()) {
if (r.scriptIndex != -1) {
- return QV4::Value::undefinedValue();
+ return QV4::Encode::undefined();
} else if (r.type) {
return QmlTypeWrapper::create(ctx->engine->v8Engine, m_object, r.type, QmlTypeWrapper::ExcludeEnums);
} else if (r.importNamespace) {
@@ -321,7 +310,7 @@ Value QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextData *qml
if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(result)) {
if (hasProperty)
*hasProperty = false;
- return QV4::Value::undefinedValue();
+ return QV4::Encode::undefined();
}
}
@@ -334,18 +323,20 @@ Value QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextData *qml
Q_ASSERT(vmemo);
return vmemo->vmeMethod(result->coreIndex);
} else if (result->isV4Function()) {
- return QV4::QObjectMethod::create(ctx->engine->rootContext, m_object, result->coreIndex, QV4::Value::fromObject(ctx->engine->qmlContextObject()));
+ QV4::Scoped<QV4::Object> qmlcontextobject(scope, ctx->engine->qmlContextObject());
+ return QV4::QObjectMethod::create(ctx->engine->rootContext, m_object, result->coreIndex,
+ qmlcontextobject.asValue()).asReturnedValue();
} else if (result->isSignalHandler()) {
QV4::QmlSignalHandler *handler = new (ctx->engine->memoryManager) QV4::QmlSignalHandler(ctx->engine, m_object, result->coreIndex);
QV4::String *connect = ctx->engine->newIdentifier(QStringLiteral("connect"));
QV4::String *disconnect = ctx->engine->newIdentifier(QStringLiteral("disconnect"));
- handler->put(connect, ctx->engine->functionClass->prototype->get(connect));
- handler->put(disconnect, ctx->engine->functionClass->prototype->get(disconnect));
+ handler->put(connect, QV4::Value::fromReturnedValue(ctx->engine->functionClass->prototype->get(connect)));
+ handler->put(disconnect, QV4::Value::fromReturnedValue(ctx->engine->functionClass->prototype->get(disconnect)));
- return QV4::Value::fromObject(handler);
+ return QV4::Value::fromObject(handler).asReturnedValue();
} else {
- return QV4::QObjectMethod::create(ctx->engine->rootContext, m_object, result->coreIndex);
+ return QV4::QObjectMethod::create(ctx->engine->rootContext, m_object, result->coreIndex).asReturnedValue();
}
}
@@ -358,15 +349,16 @@ Value QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextData *qml
if (ep && ep->propertyCapture && result->accessors->notifier)
nptr = &n;
- QV4::Value rv = LoadProperty<ReadAccessor::Accessor>(ctx->engine->v8Engine, m_object, *result, nptr);
+ QV4::ScopedValue rv(scope, LoadProperty<ReadAccessor::Accessor>(ctx->engine->v8Engine, m_object, *result, nptr));
if (result->accessors->notifier) {
- if (n) ep->captureProperty(n);
+ if (n)
+ ep->captureProperty(n);
} else {
ep->captureProperty(m_object, result->coreIndex, result->notifyIndex);
}
- return rv;
+ return rv.asReturnedValue();
}
if (ep && !result->isConstant())
@@ -383,25 +375,26 @@ Value QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextData *qml
}
}
-Value QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, QObject *object, String *name, QObjectWrapper::RevisionMode revisionMode, bool *hasProperty)
+ReturnedValue QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, QObject *object, String *name, QObjectWrapper::RevisionMode revisionMode, bool *hasProperty)
{
+ QV4::Scope scope(ctx);
if (QQmlData::wasDeleted(object)) {
if (hasProperty)
*hasProperty = false;
- return QV4::Value::nullValue();
+ return QV4::Encode::null();
}
if (!QQmlData::get(object, true)) {
if (hasProperty)
*hasProperty = false;
- return QV4::Value::nullValue();
+ return QV4::Encode::null();
}
- QObjectWrapper *wrapper = wrap(ctx->engine, object).as<QV4::QObjectWrapper>();
+ QV4::Scoped<QObjectWrapper> wrapper(scope, wrap(ctx->engine, object));
if (!wrapper) {
if (hasProperty)
*hasProperty = false;
- return QV4::Value::nullValue();
+ return QV4::Encode::null();
}
return wrapper->getQmlProperty(ctx, qmlContext, name, revisionMode, hasProperty);
}
@@ -507,7 +500,7 @@ bool QObjectWrapper::setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlC
} else if (result->propType == QMetaType::Double && value.isNumber()) {
PROPERTY_STORE(double, double(value.asDouble()));
} else if (result->propType == QMetaType::QString && value.isString()) {
- PROPERTY_STORE(QString, value.toQString());
+ PROPERTY_STORE(QString, value.toQStringNoThrow());
} else if (result->isVarProperty()) {
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmemo);
@@ -540,57 +533,59 @@ bool QObjectWrapper::setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlC
return true;
}
-Value QObjectWrapper::wrap(ExecutionEngine *engine, QObject *object)
+ReturnedValue QObjectWrapper::wrap(ExecutionEngine *engine, QObject *object)
{
if (QQmlData::wasDeleted(object))
- return QV4::Value::nullValue();
+ return QV4::Encode::null();
QQmlData *ddata = QQmlData::get(object, true);
if (!ddata)
- return QV4::Value::undefinedValue();
+ return QV4::Encode::undefined();
+
+ Scope scope(engine);
if (ddata->jsEngineId == engine->m_engineId && !ddata->jsWrapper.isEmpty()) {
// We own the JS object
- return ddata->jsWrapper.value();
+ return ddata->jsWrapper.value().asReturnedValue();
} else if (ddata->jsWrapper.isEmpty() &&
(ddata->jsEngineId == engine->m_engineId || // We own the QObject
ddata->jsEngineId == 0 || // No one owns the QObject
!ddata->hasTaintedV8Object)) { // Someone else has used the QObject, but it isn't tainted
- QV4::Value rv = create(engine, ddata, object);
+ QV4::ScopedValue rv(scope, create(engine, ddata, object));
ddata->jsWrapper = rv;
ddata->jsEngineId = engine->m_engineId;
- return rv;
+ return rv.asReturnedValue();
} else {
// If this object is tainted, we have to check to see if it is in our
// tainted object list
- Object *alternateWrapper = 0;
+ Scoped<Object> alternateWrapper(scope, (Object *)0);
if (engine->m_multiplyWrappedQObjects && ddata->hasTaintedV8Object)
- alternateWrapper = engine->m_multiplyWrappedQObjects->value(object);
+ alternateWrapper = Value::fromObject(engine->m_multiplyWrappedQObjects->value(object));
// If our tainted handle doesn't exist or has been collected, and there isn't
// a handle in the ddata, we can assume ownership of the ddata->v8object
if (ddata->jsWrapper.isEmpty() && !alternateWrapper) {
- QV4::Value result = create(engine, ddata, object);
+ QV4::ScopedValue result(scope, create(engine, ddata, object));
ddata->jsWrapper = result;
ddata->jsEngineId = engine->m_engineId;
- return result;
+ return result.asReturnedValue();
}
if (!alternateWrapper) {
- alternateWrapper = create(engine, ddata, object).asObject();
+ alternateWrapper = create(engine, ddata, object);
if (!engine->m_multiplyWrappedQObjects)
engine->m_multiplyWrappedQObjects = new MultiplyWrappedQObjectMap;
- engine->m_multiplyWrappedQObjects->insert(object, alternateWrapper);
+ engine->m_multiplyWrappedQObjects->insert(object, alternateWrapper.getPointer());
ddata->hasTaintedV8Object = true;
}
- return QV4::Value::fromObject(alternateWrapper);
+ return alternateWrapper.asReturnedValue();
}
}
-QV4::Value QObjectWrapper::create(ExecutionEngine *engine, QQmlData *ddata, QObject *object)
+ReturnedValue QObjectWrapper::create(ExecutionEngine *engine, QQmlData *ddata, QObject *object)
{
QQmlEngine *qmlEngine = engine->v8Engine->engine();
if (!ddata->propertyCache && qmlEngine) {
@@ -598,10 +593,10 @@ QV4::Value QObjectWrapper::create(ExecutionEngine *engine, QQmlData *ddata, QObj
if (ddata->propertyCache) ddata->propertyCache->addref();
}
- return Value::fromObject(new (engine->memoryManager) QV4::QObjectWrapper(engine, object));
+ return Value::fromObject(new (engine->memoryManager) QV4::QObjectWrapper(engine, object)).asReturnedValue();
}
-QV4::Value QObjectWrapper::get(Managed *m, String *name, bool *hasProperty)
+QV4::ReturnedValue QObjectWrapper::get(Managed *m, String *name, bool *hasProperty)
{
QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
ExecutionEngine *v4 = m->engine();
@@ -655,7 +650,7 @@ Property *QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, String
++it->arrayIndex;
if (attributes)
*attributes = QV4::Attr_Data;
- it->tmpDynamicProperty.value = that->get(*name);
+ it->tmpDynamicProperty.value = QV4::Value::fromReturnedValue(that->get(*name));
return &it->tmpDynamicProperty;
}
const int methodCount = mo->methodCount();
@@ -664,7 +659,7 @@ Property *QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, String
++it->arrayIndex;
if (attributes)
*attributes = QV4::Attr_Data;
- it->tmpDynamicProperty.value = that->get(*name);
+ it->tmpDynamicProperty.value = QV4::Value::fromReturnedValue(that->get(*name));
return &it->tmpDynamicProperty;
}
return QV4::Object::advanceIterator(m, it, name, index, attributes);
@@ -701,14 +696,15 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
QV4::ExecutionEngine *v4 = f->internalClass->engine;
QV4::ExecutionContext *ctx = v4->current;
- QV4::ScopedCallData callData(v4, argCount);
+ Scope scope(v4);
+ QV4::ScopedCallData callData(scope, argCount);
callData->thisObject = This->thisObject.isEmpty() ? Value::fromObject(v4->globalObject) : This->thisObject.value();
for (int ii = 0; ii < argCount; ++ii) {
int type = argsTypes[ii + 1];
if (type == qMetaTypeId<QVariant>()) {
- callData->args[ii] = v4->v8Engine->fromVariant(*((QVariant *)metaArgs[ii + 1]));
+ callData->args[ii] = QV4::Value::fromReturnedValue(v4->v8Engine->fromVariant(*((QVariant *)metaArgs[ii + 1])));
} else {
- callData->args[ii] = v4->v8Engine->fromVariant(QVariant(type, metaArgs[ii + 1]));
+ callData->args[ii] = QV4::Value::fromReturnedValue(v4->v8Engine->fromVariant(QVariant(type, metaArgs[ii + 1])));
}
}
@@ -740,7 +736,7 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
return;
}
- QV4::ValueScope scope(v4);
+ QV4::Scope scope(v4);
QV4::ScopedValue function(scope, *reinterpret_cast<QV4::Value*>(metaArgs[1]));
QV4::ScopedValue thisObject(scope, *reinterpret_cast<QV4::Value*>(metaArgs[2]));
QObject *receiverToDisconnect = reinterpret_cast<QObject*>(metaArgs[3]);
@@ -779,7 +775,7 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
} // namespace QV4
-Value QObjectWrapper::method_connect(SimpleCallContext *ctx)
+ReturnedValue QObjectWrapper::method_connect(SimpleCallContext *ctx)
{
if (ctx->argumentCount == 0)
V4THROW_ERROR("Function.prototype.connect: no arguments given");
@@ -815,10 +811,10 @@ Value QObjectWrapper::method_connect(SimpleCallContext *ctx)
QObjectPrivate::connect(signalObject, signalIndex, slot, Qt::AutoConnection);
- return QV4::Value::undefinedValue();
+ return Encode::undefined();
}
-Value QObjectWrapper::method_disconnect(SimpleCallContext *ctx)
+ReturnedValue QObjectWrapper::method_disconnect(SimpleCallContext *ctx)
{
if (ctx->argumentCount == 0)
V4THROW_ERROR("Function.prototype.disconnect: no arguments given");
@@ -864,7 +860,7 @@ Value QObjectWrapper::method_disconnect(SimpleCallContext *ctx)
QObjectPrivate::disconnect(signalObject, signalIndex, reinterpret_cast<void**>(&a));
- return QV4::Value::undefinedValue();
+ return Encode::undefined();
}
static void markChildQObjectsRecursively(QObject *parent)
@@ -967,7 +963,7 @@ struct CallArgument {
inline void initAsType(int type);
inline void fromValue(int type, QV8Engine *, const QV4::Value&);
- inline QV4::Value toValue(QV8Engine *);
+ inline ReturnedValue toValue(QV8Engine *);
private:
CallArgument(const CallArgument &);
@@ -1021,7 +1017,7 @@ private:
};
}
-static QV4::Value CallMethod(QObject *object, int index, int returnType, int argCount,
+static QV4::ReturnedValue CallMethod(QObject *object, int index, int returnType, int argCount,
int *argTypes, QV8Engine *engine, CallArgs &callArgs)
{
if (argCount > 0) {
@@ -1068,7 +1064,7 @@ static QV4::Value CallMethod(QObject *object, int index, int returnType, int arg
void *args[] = { 0 };
QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, args);
- return QV4::Value::undefinedValue();
+ return Encode::undefined();
}
}
@@ -1264,7 +1260,7 @@ static const QQmlPropertyData * RelatedMethod(QObject *object,
}
}
-static QV4::Value CallPrecise(QObject *object, const QQmlPropertyData &data,
+static QV4::ReturnedValue CallPrecise(QObject *object, const QQmlPropertyData &data,
QV8Engine *engine, CallArgs &callArgs)
{
QByteArray unknownTypeError;
@@ -1318,7 +1314,7 @@ Resolve the overloaded method to call. The algorithm works conceptually like th
If two or more overloads have the same match score, call the last one. The match
score is constructed by adding the matchScore() result for each of the parameters.
*/
-static QV4::Value CallOverloaded(QObject *object, const QQmlPropertyData &data,
+static QV4::ReturnedValue CallOverloaded(QObject *object, const QQmlPropertyData &data,
QV8Engine *engine, CallArgs &callArgs)
{
int argumentCount = callArgs.Length();
@@ -1503,7 +1499,7 @@ void CallArgument::fromValue(int callType, QV8Engine *engine, const QV4::Value &
if (value.isNull() || value.isUndefined())
qstringPtr = new (&allocData) QString();
else
- qstringPtr = new (&allocData) QString(value.toQString());
+ qstringPtr = new (&allocData) QString(value.toQStringNoThrow());
type = callType;
} else if (callType == QMetaType::QObjectStar) {
qobjectPtr = 0;
@@ -1516,10 +1512,14 @@ void CallArgument::fromValue(int callType, QV8Engine *engine, const QV4::Value &
} else if (callType == qMetaTypeId<QList<QObject*> >()) {
qlistPtr = new (&allocData) QList<QObject *>();
if (QV4::ArrayObject *array = value.asArrayObject()) {
+ QV4::Scope scope(array->engine());
+ Scoped<QV4::QObjectWrapper> qobjectWrapper(scope);
+
uint32_t length = array->arrayLength();
for (uint32_t ii = 0; ii < length; ++ii) {
QObject *o = 0;
- if (QV4::QObjectWrapper *qobjectWrapper = array->getIndexed(ii).as<QV4::QObjectWrapper>())
+ qobjectWrapper = array->getIndexed(ii);
+ if (!!qobjectWrapper)
o = qobjectWrapper->object();
qlistPtr->append(o);
}
@@ -1576,23 +1576,25 @@ void CallArgument::fromValue(int callType, QV8Engine *engine, const QV4::Value &
}
}
-QV4::Value CallArgument::toValue(QV8Engine *engine)
+QV4::ReturnedValue CallArgument::toValue(QV8Engine *engine)
{
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
+ QV4::Scope scope(v4);
+
if (type == qMetaTypeId<QJSValue>()) {
return QJSValuePrivate::get(*qjsValuePtr)->getValue(v4);
} else if (type == QMetaType::Int) {
- return QV4::Value::fromInt32(int(intValue));
+ return QV4::Encode(int(intValue));
} else if (type == QMetaType::UInt) {
- return QV4::Value::fromUInt32(intValue);
+ return QV4::Encode((uint)intValue);
} else if (type == QMetaType::Bool) {
- return QV4::Value::fromBoolean(boolValue);
+ return QV4::Encode(boolValue);
} else if (type == QMetaType::Double) {
- return QV4::Value::fromDouble(doubleValue);
+ return QV4::Encode(doubleValue);
} else if (type == QMetaType::Float) {
- return QV4::Value::fromDouble(floatValue);
+ return QV4::Encode(floatValue);
} else if (type == QMetaType::QString) {
- return engine->toString(*qstringPtr);
+ return engine->toString(*qstringPtr).asReturnedValue();
} else if (type == QMetaType::QObjectStar) {
QObject *object = qobjectPtr;
if (object)
@@ -1602,15 +1604,15 @@ QV4::Value CallArgument::toValue(QV8Engine *engine)
// XXX Can this be made more by using Array as a prototype and implementing
// directly against QList<QObject*>?
QList<QObject *> &list = *qlistPtr;
- QV4::ArrayObject *array = v4->newArrayObject();
+ QV4::Scoped<ArrayObject> array(scope, v4->newArrayObject());
array->arrayReserve(list.count());
array->arrayDataLen = list.count();
for (int ii = 0; ii < list.count(); ++ii)
- array->arrayData[ii].value = QV4::QObjectWrapper::wrap(v4, list.at(ii));
+ array->arrayData[ii].value = Value::fromReturnedValue(QV4::QObjectWrapper::wrap(v4, list.at(ii)));
array->setArrayLengthUnchecked(list.count());
- return QV4::Value::fromObject(array);
+ return array.asReturnedValue();
} else if (type == qMetaTypeId<QQmlV4Handle>()) {
- return handlePtr->toValue();
+ return handlePtr->toValue().asReturnedValue();
} else if (type == QMetaType::QJsonArray) {
return QV4::JsonObject::fromJsonArray(v4, *jsonArrayPtr);
} else if (type == QMetaType::QJsonObject) {
@@ -1619,14 +1621,14 @@ QV4::Value CallArgument::toValue(QV8Engine *engine)
return QV4::JsonObject::fromJsonValue(v4, *jsonValuePtr);
} else if (type == -1 || type == qMetaTypeId<QVariant>()) {
QVariant value = *qvariantPtr;
- QV4::Value rv = engine->fromVariant(value);
- if (QV4::QObjectWrapper *qobjectWrapper = rv.as<QV4::QObjectWrapper>()) {
+ QV4::ScopedValue rv(scope, engine->fromVariant(value));
+ if (QV4::QObjectWrapper *qobjectWrapper = rv->as<QV4::QObjectWrapper>()) {
if (QObject *object = qobjectWrapper->object())
QQmlData::get(object, true)->setImplicitDestructible();
}
- return rv;
+ return rv.asReturnedValue();
} else {
- return QV4::Value::undefinedValue();
+ return QV4::Encode::undefined();
}
}
@@ -1645,7 +1647,7 @@ QObjectMethod::QObjectMethod(ExecutionContext *scope, QObject *object, int index
subtype = WrappedQtMethod;
}
-QV4::Value QObjectMethod::method_toString(QV4::ExecutionContext *ctx)
+QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx)
{
QString result;
if (m_object) {
@@ -1666,13 +1668,13 @@ QV4::Value QObjectMethod::method_toString(QV4::ExecutionContext *ctx)
result = QLatin1String("null");
}
- return QV4::Value::fromString(ctx, result);
+ return QV4::Value::fromString(ctx, result).asReturnedValue();
}
-QV4::Value QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc)
+QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc)
{
if (!m_object)
- return QV4::Value::undefinedValue();
+ return Encode::undefined();
if (QQmlData::keepAliveDuringGarbageCollection(m_object))
ctx->throwError(QStringLiteral("Invalid attempt to destroy() an indestructible object"));
@@ -1685,16 +1687,16 @@ QV4::Value QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, const Value
else
m_object->deleteLater();
- return QV4::Value::undefinedValue();
+ return Encode::undefined();
}
-Value QObjectMethod::call(Managed *m, CallData *callData)
+ReturnedValue QObjectMethod::call(Managed *m, CallData *callData)
{
QObjectMethod *This = static_cast<QObjectMethod*>(m);
return This->callInternal(callData);
}
-Value QObjectMethod::callInternal(CallData *callData)
+ReturnedValue QObjectMethod::callInternal(CallData *callData)
{
ExecutionContext *context = engine()->current;
if (m_index == DestroyMethod)
@@ -1704,11 +1706,11 @@ Value QObjectMethod::callInternal(CallData *callData)
QObject *object = m_object.data();
if (!object)
- return QV4::Value::undefinedValue();
+ return Encode::undefined();
QQmlData *ddata = QQmlData::get(object);
if (!ddata)
- return QV4::Value::undefinedValue();
+ return Encode::undefined();
QV8Engine *v8Engine = context->engine->v8Engine;
@@ -1718,7 +1720,7 @@ Value QObjectMethod::callInternal(CallData *callData)
if (ddata->propertyCache) {
QQmlPropertyData *d = ddata->propertyCache->method(m_index);
if (!d)
- return QV4::Value::undefinedValue();
+ return QV4::Encode::undefined();
method = *d;
}
}
@@ -1727,7 +1729,7 @@ Value QObjectMethod::callInternal(CallData *callData)
method.load(object->metaObject()->method(m_index));
if (method.coreIndex == -1)
- return QV4::Value::undefinedValue();
+ return QV4::Encode::undefined();
}
if (method.isV4Function()) {
@@ -1741,7 +1743,7 @@ Value QObjectMethod::callInternal(CallData *callData)
void *args[] = { 0, &funcptr };
QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, method.coreIndex, args);
- return rv;
+ return rv.asReturnedValue();
}
CallArgs callArgs(callData->argc, callData->args);
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 3a48fee1ec..95986a4b0d 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -85,17 +85,17 @@ struct Q_QML_EXPORT QObjectWrapper : public QV4::Object
QObject *object() const { return m_object.data(); }
- Value getQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, bool *hasProperty = 0, bool includeImports = false);
- static Value getQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, bool *hasProperty = 0);
+ ReturnedValue getQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, bool *hasProperty = 0, bool includeImports = false);
+ static ReturnedValue getQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, bool *hasProperty = 0);
static bool setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, const Value &value);
- static Value wrap(ExecutionEngine *engine, QObject *object);
+ static ReturnedValue wrap(ExecutionEngine *engine, QObject *object);
using Object::get;
private:
- static Value create(ExecutionEngine *engine, QQmlData *ddata, QObject *object);
+ static ReturnedValue create(ExecutionEngine *engine, QQmlData *ddata, QObject *object);
QObjectWrapper(ExecutionEngine *engine, QObject *object);
@@ -105,7 +105,7 @@ private:
String *m_destroy;
String *m_toString;
- static Value get(Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
static PropertyAttributes query(const Managed *, String *name);
static Property *advanceIterator(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attributes);
@@ -116,8 +116,8 @@ private:
static_cast<QObjectWrapper *>(that)->~QObjectWrapper();
}
- static Value method_connect(SimpleCallContext *ctx);
- static Value method_disconnect(SimpleCallContext *ctx);
+ static ReturnedValue method_connect(SimpleCallContext *ctx);
+ static ReturnedValue method_disconnect(SimpleCallContext *ctx);
};
struct QObjectMethod : public QV4::FunctionObject
@@ -134,16 +134,16 @@ struct QObjectMethod : public QV4::FunctionObject
private:
QObjectMethod(QV4::ExecutionContext *scope, QObject *object, int index, const QV4::Value &qmlGlobal);
- QV4::Value method_toString(QV4::ExecutionContext *ctx);
- QV4::Value method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc);
+ QV4::ReturnedValue method_toString(QV4::ExecutionContext *ctx);
+ QV4::ReturnedValue method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc);
QPointer<QObject> m_object;
int m_index;
QV4::PersistentValue m_qmlGlobal;
- static Value call(Managed *, CallData *callData);
+ static ReturnedValue call(Managed *, CallData *callData);
- Value callInternal(CallData *callData);
+ ReturnedValue callInternal(CallData *callData);
static void destroy(Managed *that)
{
@@ -188,7 +188,7 @@ public:
Iterator erase(Iterator it);
void remove(QObject *key);
-private slots:
+private Q_SLOTS:
void removeDestroyedObject(QObject*);
};
diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp
index ab01ce7650..5a9a8d9d1d 100644
--- a/src/qml/jsruntime/qv4regexp.cpp
+++ b/src/qml/jsruntime/qv4regexp.cpp
@@ -136,14 +136,14 @@ void RegExp::markObjects(Managed *that)
{
}
-Value RegExp::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue RegExp::get(Managed *, String *, bool *)
{
- return Value::undefinedValue();
+ return Value::undefinedValue().asReturnedValue();
}
-Value RegExp::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue RegExp::getIndexed(Managed *m, uint index, bool *hasProperty)
{
- return Value::undefinedValue();
+ return Value::undefinedValue().asReturnedValue();
}
void RegExp::put(Managed *m, String *name, const Value &value)
diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h
index 6edbd4b2ad..f91faf5044 100644
--- a/src/qml/jsruntime/qv4regexp_p.h
+++ b/src/qml/jsruntime/qv4regexp_p.h
@@ -111,8 +111,8 @@ public:
protected:
static void destroy(Managed *that);
static void markObjects(Managed *that);
- static Value get(Managed *m, String *name, bool *hasProperty);
- static Value getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue get(Managed *, String *, bool *);
+ static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
static void putIndexed(Managed *m, uint index, const Value &value);
static PropertyAttributes query(const Managed *m, String *name);
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index 448d10180c..60a5026772 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -206,7 +206,8 @@ QString RegExpObject::toString() const
QString RegExpObject::source() const
{
- return const_cast<RegExpObject *>(this)->get(internalClass->engine->newIdentifier(QStringLiteral("source"))).stringValue()->toQString();
+ Value s = Value::fromReturnedValue(const_cast<RegExpObject *>(this)->get(internalClass->engine->newIdentifier(QStringLiteral("source"))));
+ return s.stringValue()->toQString();
}
uint RegExpObject::flags() const
@@ -229,10 +230,10 @@ RegExpCtor::RegExpCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value RegExpCtor::construct(Managed *m, CallData *callData)
+ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData)
{
ExecutionContext *ctx = m->engine()->current;
- ValueScope scope(ctx);
+ Scope scope(ctx);
ScopedValue r(scope, callData->argc > 0 ? callData->args[0] : Value::undefinedValue());
ScopedValue f(scope, callData->argc > 1 ? callData->args[1] : Value::undefinedValue());
@@ -240,8 +241,7 @@ Value RegExpCtor::construct(Managed *m, CallData *callData)
if (!f->isUndefined())
ctx->throwTypeError();
- RegExpObject *o = ctx->engine->newRegExpObject(re->value, re->global);
- return Value::fromObject(o);
+ return Encode(ctx->engine->newRegExpObject(re->value, re->global));
}
QString pattern;
@@ -271,15 +271,14 @@ Value RegExpCtor::construct(Managed *m, CallData *callData)
if (!re->isValid())
ctx->throwSyntaxError(0);
- RegExpObject *o = ctx->engine->newRegExpObject(re, global);
- return Value::fromObject(o);
+ return Encode(ctx->engine->newRegExpObject(re, global));
}
-Value RegExpCtor::call(Managed *that, CallData *callData)
+ReturnedValue RegExpCtor::call(Managed *that, CallData *callData)
{
if (callData->argc > 0 && callData->args[0].as<RegExpObject>()) {
if (callData->argc == 1 || callData->args[1].isUndefined())
- return callData->args[0];
+ return callData->args[0].asReturnedValue();
}
return construct(that, callData);
@@ -296,9 +295,9 @@ void RegExpPrototype::init(ExecutionContext *ctx, const Value &ctor)
defineDefaultProperty(ctx, QStringLiteral("compile"), method_compile, 2);
}
-Value RegExpPrototype::method_exec(SimpleCallContext *ctx)
+ReturnedValue RegExpPrototype::method_exec(SimpleCallContext *ctx)
{
- ValueScope scope(ctx);
+ Scope scope(ctx);
RegExpObject *r = ctx->thisObject.as<RegExpObject>();
if (!r)
@@ -311,18 +310,18 @@ Value RegExpPrototype::method_exec(SimpleCallContext *ctx)
int offset = r->global ? r->lastIndexProperty(ctx)->value.toInt32() : 0;
if (offset < 0 || offset > s.length()) {
r->lastIndexProperty(ctx)->value = Value::fromInt32(0);
- return Value::nullValue();
+ return Encode::null();
}
uint* matchOffsets = (uint*)alloca(r->value->captureCount() * 2 * sizeof(uint));
int result = r->value->match(s, offset, matchOffsets);
if (result == -1) {
r->lastIndexProperty(ctx)->value = Value::fromInt32(0);
- return Value::nullValue();
+ return Encode::null();
}
// fill in result data
- ArrayObject *array = ctx->engine->newArrayObject(ctx->engine->regExpExecArrayClass);
+ Scoped<ArrayObject> array(scope, ctx->engine->newArrayObject(ctx->engine->regExpExecArrayClass));
int len = r->value->captureCount();
array->arrayReserve(len);
for (int i = 0; i < len; ++i) {
@@ -339,37 +338,39 @@ Value RegExpPrototype::method_exec(SimpleCallContext *ctx)
if (r->global)
r->lastIndexProperty(ctx)->value = Value::fromInt32(matchOffsets[1]);
- return Value::fromObject(array);
+ return array.asReturnedValue();
}
-Value RegExpPrototype::method_test(SimpleCallContext *ctx)
+ReturnedValue RegExpPrototype::method_test(SimpleCallContext *ctx)
{
- Value r = method_exec(ctx);
- return Value::fromBoolean(!r.isNull());
+ Scope scope(ctx);
+ ScopedValue r(scope, method_exec(ctx));
+ return Encode(!r->isNull());
}
-Value RegExpPrototype::method_toString(SimpleCallContext *ctx)
+ReturnedValue RegExpPrototype::method_toString(SimpleCallContext *ctx)
{
RegExpObject *r = ctx->thisObject.as<RegExpObject>();
if (!r)
ctx->throwTypeError();
- return Value::fromString(ctx, r->toString());
+ return Value::fromString(ctx, r->toString()).asReturnedValue();
}
-Value RegExpPrototype::method_compile(SimpleCallContext *ctx)
+ReturnedValue RegExpPrototype::method_compile(SimpleCallContext *ctx)
{
+ Scope scope(ctx);
RegExpObject *r = ctx->thisObject.as<RegExpObject>();
if (!r)
ctx->throwTypeError();
- ScopedCallData callData(ctx->engine, ctx->argumentCount);
+ ScopedCallData callData(scope, ctx->argumentCount);
memcpy(callData->args, ctx->arguments, ctx->argumentCount*sizeof(Value));
- RegExpObject *re = ctx->engine->regExpCtor.asFunctionObject()->construct(callData).as<RegExpObject>();
+ RegExpObject *re = Value::fromReturnedValue(ctx->engine->regExpCtor.asFunctionObject()->construct(callData)).as<RegExpObject>();
r->value = re->value;
r->global = re->global;
- return Value::undefinedValue();
+ return Encode::undefined();
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index a17802e2ff..765e98176c 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -103,13 +103,11 @@ protected:
struct RegExpCtor: FunctionObject
{
+ Q_MANAGED
RegExpCtor(ExecutionContext *scope);
- static Value construct(Managed *m, CallData *callData);
- static Value call(Managed *that, CallData *callData);
-
-protected:
- static const ManagedVTable static_vtbl;
+ static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue call(Managed *that, CallData *callData);
};
struct RegExpPrototype: RegExpObject
@@ -117,10 +115,10 @@ struct RegExpPrototype: RegExpObject
RegExpPrototype(InternalClass *ic): RegExpObject(ic) {}
void init(ExecutionContext *ctx, const Value &ctor);
- static Value method_exec(SimpleCallContext *ctx);
- static Value method_test(SimpleCallContext *ctx);
- static Value method_toString(SimpleCallContext *ctx);
- static Value method_compile(SimpleCallContext *ctx);
+ static ReturnedValue method_exec(SimpleCallContext *ctx);
+ static ReturnedValue method_test(SimpleCallContext *ctx);
+ static ReturnedValue method_toString(SimpleCallContext *ctx);
+ static ReturnedValue method_compile(SimpleCallContext *ctx);
};
}
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 733f353330..2bd201e2a1 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -67,6 +67,126 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
+#ifdef QV4_COUNT_RUNTIME_FUNCTIONS
+struct RuntimeCounters::Data {
+ enum Type {
+ None = 0,
+ Undefined = 1,
+ Null = 2,
+ Boolean = 3,
+ Integer = 4,
+ Managed = 5,
+ Double = 7
+ };
+
+ static const char *pretty(Type t) {
+ switch (t) {
+ case None: return "";
+ case Undefined: return "Undefined";
+ case Null: return "Null";
+ case Boolean: return "Boolean";
+ case Integer: return "Integer";
+ case Managed: return "Managed";
+ case Double: return "Double";
+ default: return "Unknown";
+ }
+ }
+
+ static unsigned mangle(unsigned tag) {
+ switch (tag) {
+ case Value::Undefined_Type: return Undefined;
+ case Value::Null_Type: return Null;
+ case Value::Boolean_Type: return Boolean;
+ case Value::Integer_Type: return Integer;
+ case Value::Managed_Type: return Managed;
+ default: return Double;
+ }
+ }
+
+ static unsigned mangle(unsigned tag1, unsigned tag2) {
+ return (mangle(tag1) << 3) | mangle(tag2);
+ }
+
+ static void unmangle(unsigned signature, Type &tag1, Type &tag2) {
+ tag1 = Type((signature >> 3) & 7);
+ tag2 = Type(signature & 7);
+ }
+
+ typedef QVector<quint64> Counters;
+ QHash<const char *, Counters> counters;
+
+ inline void count(const char *func, unsigned tag) {
+ QVector<quint64> &cnt = counters[func];
+ if (cnt.isEmpty())
+ cnt.resize(64);
+ cnt[mangle(tag)] += 1;
+ }
+
+ inline void count(const char *func, unsigned tag1, unsigned tag2) {
+ QVector<quint64> &cnt = counters[func];
+ if (cnt.isEmpty())
+ cnt.resize(64);
+ cnt[mangle(tag1, tag2)] += 1;
+ }
+
+ struct Line {
+ const char *func;
+ Type tag1, tag2;
+ quint64 count;
+
+ static bool less(const Line &line1, const Line &line2) {
+ return line1.count > line2.count;
+ }
+ };
+
+ void dump() const {
+ QList<Line> lines;
+ foreach (const char *func, counters.keys()) {
+ const Counters &fCount = counters[func];
+ for (int i = 0, ei = fCount.size(); i != ei; ++i) {
+ quint64 count = fCount[i];
+ if (!count)
+ continue;
+ Line line;
+ line.func = func;
+ unmangle(i, line.tag1, line.tag2);
+ line.count = count;
+ lines.append(line);
+ }
+ }
+ qSort(lines.begin(), lines.end(), Line::less);
+ qDebug() << "Counters:";
+ foreach (const Line &line, lines)
+ qDebug("%10ld | %s | %s | %s", line.count, line.func, pretty(line.tag1), pretty(line.tag2));
+ }
+};
+
+RuntimeCounters *RuntimeCounters::instance = 0;
+static RuntimeCounters runtimeCountersInstance;
+RuntimeCounters::RuntimeCounters()
+ : d(new Data)
+{
+ if (!instance)
+ instance = this;
+}
+
+RuntimeCounters::~RuntimeCounters()
+{
+ d->dump();
+}
+
+void RuntimeCounters::count(const char *func, uint tag)
+{
+ d->count(func, tag);
+}
+
+void RuntimeCounters::count(const char *func, uint tag1, uint tag2)
+{
+ d->count(func, tag1, tag2);
+}
+
+#endif // QV4_COUNT_RUNTIME_FUNCTIONS
+
void __qmljs_numberToString(QString *result, double num, int radix)
{
Q_ASSERT(result);
@@ -120,47 +240,41 @@ void __qmljs_numberToString(QString *result, double num, int radix)
result->prepend(QLatin1Char('-'));
}
-void __qmljs_init_closure(ExecutionContext *ctx, ValueRef result, int functionId)
+ReturnedValue __qmljs_init_closure(ExecutionContext *ctx, int functionId)
{
QV4::Function *clos = ctx->compilationUnit->runtimeFunctions[functionId];
- assert(clos);
- *result = Value::fromObject(FunctionObject::creatScriptFunction(ctx, clos));
+ Q_ASSERT(clos);
+ FunctionObject *f = FunctionObject::creatScriptFunction(ctx, clos);
+ return f->asReturnedValue();
}
-void __qmljs_delete_subscript(ExecutionContext *ctx, ValueRef result, const ValueRef base, const ValueRef index)
+ReturnedValue __qmljs_delete_subscript(ExecutionContext *ctx, const ValueRef base, const ValueRef index)
{
if (Object *o = base->asObject()) {
uint n = index->asArrayIndex();
if (n < UINT_MAX) {
- Value res = Value::fromBoolean(o->deleteIndexedProperty(n));
- if (result)
- *result = res;
- return;
+ return Value::fromBoolean(o->deleteIndexedProperty(n)).asReturnedValue();
}
}
String *name = index->toString(ctx);
- __qmljs_delete_member(ctx, result, base, name);
+ return __qmljs_delete_member(ctx, base, name);
}
-void __qmljs_delete_member(ExecutionContext *ctx, ValueRef result, const ValueRef base, String *name)
+ReturnedValue __qmljs_delete_member(ExecutionContext *ctx, const ValueRef base, String *name)
{
Object *obj = base->toObject(ctx);
- Value res = Value::fromBoolean(obj->deleteProperty(name));
- if (result)
- *result = res;
+ return Value::fromBoolean(obj->deleteProperty(name)).asReturnedValue();
}
-void __qmljs_delete_name(ExecutionContext *ctx, ValueRef result, String *name)
+ReturnedValue __qmljs_delete_name(ExecutionContext *ctx, String *name)
{
- Value res = Value::fromBoolean(ctx->deleteProperty(name));
- if (result)
- *result = res;
+ return Value::fromBoolean(ctx->deleteProperty(name)).asReturnedValue();
}
-void __qmljs_add_helper(ExecutionContext *ctx, ValueRef result, const ValueRef left, const ValueRef right)
+QV4::ReturnedValue __qmljs_add_helper(ExecutionContext *ctx, const ValueRef left, const ValueRef right)
{
- ValueScope scope(ctx);
+ Scope scope(ctx);
ScopedValue pleft(scope, __qmljs_to_primitive(left, PREFERREDTYPE_HINT));
ScopedValue pright(scope, __qmljs_to_primitive(right, PREFERREDTYPE_HINT));
@@ -169,40 +283,37 @@ void __qmljs_add_helper(ExecutionContext *ctx, ValueRef result, const ValueRef l
pleft = __qmljs_to_string(pleft, ctx);
if (!pright->isString())
pright = __qmljs_to_string(pright, ctx);
- String *string = __qmljs_string_concat(ctx, pleft->stringValue(), pright->stringValue());
- *result = Value::fromString(string);
- return;
+ return __qmljs_string_concat(ctx, pleft->stringValue(), pright->stringValue())->asReturnedValue();
}
double x = __qmljs_to_number(pleft);
double y = __qmljs_to_number(pright);
- *result = Value::fromDouble(x + y);
+ return Value::fromDouble(x + y).asReturnedValue();
}
-void __qmljs_instanceof(ExecutionContext *ctx, ValueRef result, const ValueRef left, const ValueRef right)
+QV4::ReturnedValue __qmljs_instanceof(ExecutionContext *ctx, const ValueRef left, const ValueRef right)
{
Object *o = right->asObject();
if (!o)
ctx->throwTypeError();
bool r = o->hasInstance(*left);
- *result = Value::fromBoolean(r);
+ return Value::fromBoolean(r).asReturnedValue();
}
-void __qmljs_in(ExecutionContext *ctx, ValueRef result, const ValueRef left, const ValueRef right)
+QV4::ReturnedValue __qmljs_in(ExecutionContext *ctx, const ValueRef left, const ValueRef right)
{
if (!right->isObject())
ctx->throwTypeError();
String *s = left->toString(ctx);
bool r = right->objectValue()->__hasProperty__(s);
- *result = Value::fromBoolean(r);
+ return Value::fromBoolean(r).asReturnedValue();
}
static void inplaceBitOp(ExecutionContext *ctx, String *name, const ValueRef value, BinOp op)
{
- ValueScope scope(ctx);
+ Scope scope(ctx);
ScopedValue lhs(scope, ctx->getProperty(name));
- ScopedValue result(scope);
- op(result, lhs, value);
+ ScopedValue result(scope, op(lhs, value));
ctx->setProperty(name, result);
}
@@ -224,10 +335,9 @@ void __qmljs_inplace_bit_xor_name(ExecutionContext *ctx, String *name, const Val
void __qmljs_inplace_add_name(ExecutionContext *ctx, String *name, const ValueRef value)
{
- ValueScope scope(ctx);
+ Scope scope(ctx);
ScopedValue lhs(scope, ctx->getProperty(name));
- ScopedValue result(scope);
- __qmljs_add(ctx, result, lhs, value);
+ ScopedValue result(scope, __qmljs_add(ctx, lhs, value));
ctx->setProperty(name, result);
}
@@ -419,15 +529,15 @@ double __qmljs_string_to_number(const QString &string)
return d;
}
-Value __qmljs_string_from_number(ExecutionContext *ctx, double number)
+Returned<String> *__qmljs_string_from_number(ExecutionContext *ctx, double number)
{
QString qstr;
__qmljs_numberToString(&qstr, number, 10);
String *string = ctx->engine->newString(qstr);
- return Value::fromString(string);
+ return string->asReturned<String>();
}
-String *__qmljs_string_concat(ExecutionContext *ctx, String *first, String *second)
+Returned<String> *__qmljs_string_concat(ExecutionContext *ctx, String *first, String *second)
{
const QString &a = first->toQString();
const QString &b = second->toQString();
@@ -437,10 +547,10 @@ String *__qmljs_string_concat(ExecutionContext *ctx, String *first, String *seco
data += a.length();
memcpy(data, b.constData(), b.length()*sizeof(QChar));
- return ctx->engine->newString(newStr);
+ return ctx->engine->newString(newStr)->asReturned<String>();
}
-Value __qmljs_object_default_value(Object *object, int typeHint)
+ReturnedValue __qmljs_object_default_value(Object *object, int typeHint)
{
if (typeHint == PREFERREDTYPE_HINT) {
if (object->asDateObject())
@@ -457,27 +567,26 @@ Value __qmljs_object_default_value(Object *object, int typeHint)
qSwap(meth1, meth2);
ExecutionContext *ctx = engine->current;
+ Scope scope(ctx);
+ ScopedCallData callData(scope, 0);
+ callData->thisObject = Value::fromObject(object);
- Value conv = object->get(meth1);
- if (FunctionObject *o = conv.asFunctionObject()) {
- ScopedCallData callData(engine, 0);
- callData->thisObject = Value::fromObject(object);
- Value r = o->call(callData);
+ ScopedValue conv(scope, object->get(meth1));
+ if (FunctionObject *o = conv->asFunctionObject()) {
+ Value r = Value::fromReturnedValue(o->call(callData));
if (r.isPrimitive())
- return r;
+ return r.asReturnedValue();
}
conv = object->get(meth2);
- if (FunctionObject *o = conv.asFunctionObject()) {
- ScopedCallData callData(engine, 0);
- callData->thisObject = Value::fromObject(object);
- Value r = o->call(callData);
+ if (FunctionObject *o = conv->asFunctionObject()) {
+ Value r = Value::fromReturnedValue(o->call(callData));
if (r.isPrimitive())
- return r;
+ return r.asReturnedValue();
}
ctx->throwTypeError();
- return Value::undefinedValue();
+ return Value::undefinedValue().asReturnedValue();
}
Bool __qmljs_to_boolean(const ValueRef value)
@@ -486,7 +595,7 @@ Bool __qmljs_to_boolean(const ValueRef value)
}
-Object *__qmljs_convert_to_object(ExecutionContext *ctx, const ValueRef value)
+Returned<Object> *__qmljs_convert_to_object(ExecutionContext *ctx, const ValueRef value)
{
assert(!value->isObject());
switch (value->type()) {
@@ -495,42 +604,40 @@ Object *__qmljs_convert_to_object(ExecutionContext *ctx, const ValueRef value)
ctx->throwTypeError();
case Value::Boolean_Type:
return ctx->engine->newBooleanObject(*value);
- case Value::String_Type:
+ case Value::Managed_Type:
+ Q_ASSERT(value->isString());
return ctx->engine->newStringObject(*value);
- break;
- case Value::Object_Type:
- Q_UNREACHABLE();
case Value::Integer_Type:
default: // double
return ctx->engine->newNumberObject(*value);
}
}
-String *__qmljs_convert_to_string(ExecutionContext *ctx, const ValueRef value)
+Returned<String> *__qmljs_convert_to_string(ExecutionContext *ctx, const ValueRef value)
{
switch (value->type()) {
case Value::Undefined_Type:
- return ctx->engine->id_undefined;
+ case Value::Empty_Type:
+ return ctx->engine->id_undefined->asReturned<String>();
case Value::Null_Type:
- return ctx->engine->id_null;
+ return ctx->engine->id_null->asReturned<String>();
case Value::Boolean_Type:
if (value->booleanValue())
- return ctx->engine->id_true;
- else
- return ctx->engine->id_false;
- case Value::String_Type:
- return value->stringValue();
- case Value::Object_Type: {
- Value prim = __qmljs_to_primitive(value, STRING_HINT);
- if (prim.isPrimitive())
- return __qmljs_convert_to_string(ctx, ValueRef(&prim));
+ return ctx->engine->id_true->asReturned<String>();
else
- ctx->throwTypeError();
- }
+ return ctx->engine->id_false->asReturned<String>();
+ case Value::Managed_Type:
+ if (value->isString())
+ return value->stringValue()->asReturned<String>();
+ {
+ Scope scope(ctx);
+ ScopedValue prim(scope, __qmljs_to_primitive(value, STRING_HINT));
+ return __qmljs_convert_to_string(ctx, prim);
+ }
case Value::Integer_Type:
- return __qmljs_string_from_number(ctx, value->int_32).stringValue();
+ return __qmljs_string_from_number(ctx, value->int_32);
default: // double
- return __qmljs_string_from_number(ctx, value->doubleValue()).stringValue();
+ return __qmljs_string_from_number(ctx, value->doubleValue());
} // switch
}
@@ -540,28 +647,25 @@ void __qmljs_set_property(ExecutionContext *ctx, const ValueRef object, String *
o->put(name, *value);
}
-void __qmljs_get_element(ExecutionContext *ctx, ValueRef result, const ValueRef object, const ValueRef index)
+ReturnedValue __qmljs_get_element(ExecutionContext *ctx, const ValueRef object, const ValueRef index)
{
+ Scope scope(ctx);
uint idx = index->asArrayIndex();
- Object *o = object->asObject();
+ Scoped<Object> o(scope, object);
if (!o) {
if (idx < UINT_MAX) {
if (String *str = object->asString()) {
if (idx >= (uint)str->toQString().length()) {
- if (result)
- *result = Value::undefinedValue();
- return;
+ return Value::undefinedValue().asReturnedValue();
}
const QString s = str->toQString().mid(idx, 1);
- if (result)
- *result = Value::fromString(ctx, s);
- return;
+ return Value::fromString(ctx, s).asReturnedValue();
}
}
if (object->isNullOrUndefined()) {
- QString message = QStringLiteral("Cannot read property '%1' of %2").arg(index->toQString()).arg(object->toQString());
+ QString message = QStringLiteral("Cannot read property '%1' of %2").arg(index->toQStringNoThrow()).arg(object->toQStringNoThrow());
ctx->throwTypeError(message);
}
@@ -572,26 +676,20 @@ void __qmljs_get_element(ExecutionContext *ctx, ValueRef result, const ValueRef
uint pidx = o->propertyIndexFromArrayIndex(idx);
if (pidx < UINT_MAX) {
if (!o->arrayAttributes || o->arrayAttributes[pidx].isData()) {
- if (result)
- *result = o->arrayData[pidx].value;
- return;
+ return o->arrayData[pidx].value.asReturnedValue();
}
}
- Value res = o->getIndexed(idx);
- if (result)
- *result = res;
- return;
+ return o->getIndexed(idx);
}
String *name = index->toString(ctx);
- Value res = o->get(name);
- if (result)
- *result = res;
+ return o->get(name);
}
void __qmljs_set_element(ExecutionContext *ctx, const ValueRef object, const ValueRef index, const ValueRef value)
{
+ Scope scope(ctx);
Object *o = object->toObject(ctx);
uint idx = index->asArrayIndex();
@@ -618,7 +716,7 @@ void __qmljs_set_element(ExecutionContext *ctx, const ValueRef object, const Val
return;
}
- ScopedCallData callData(ctx->engine, 1);
+ ScopedCallData callData(scope, 1);
callData->thisObject = Value::fromObject(o);
callData->args[0] = *value;
setter->call(callData);
@@ -633,23 +731,24 @@ void __qmljs_set_element(ExecutionContext *ctx, const ValueRef object, const Val
o->put(name, *value);
}
-void __qmljs_foreach_iterator_object(ExecutionContext *ctx, ValueRef result, const ValueRef in)
+ReturnedValue __qmljs_foreach_iterator_object(ExecutionContext *ctx, const ValueRef in)
{
- Object *o = 0;
+ Scope scope(ctx);
+ Scoped<Object> o(scope, (Object *)0);
if (!in->isNullOrUndefined())
- o = in->toObject(ctx);
- Object *it = ctx->engine->newForEachIteratorObject(ctx, o);
- *result = Value::fromObject(it);
+ o = in;
+ Scoped<Object> it(scope, ctx->engine->newForEachIteratorObject(ctx, o.getPointer()));
+ return it.asReturnedValue();
}
-void __qmljs_foreach_next_property_name(ValueRef result, const ValueRef foreach_iterator)
+ReturnedValue __qmljs_foreach_next_property_name(const ValueRef foreach_iterator)
{
- assert(foreach_iterator->isObject());
+ Q_ASSERT(foreach_iterator->isObject());
ForEachIteratorObject *it = static_cast<ForEachIteratorObject *>(foreach_iterator->objectValue());
- assert(it->as<ForEachIteratorObject>());
+ Q_ASSERT(it->as<ForEachIteratorObject>());
- *result = it->nextPropertyName();
+ return it->nextPropertyName();
}
@@ -658,33 +757,31 @@ void __qmljs_set_activation_property(ExecutionContext *ctx, String *name, const
ctx->setProperty(name, *value);
}
-void __qmljs_get_property(ExecutionContext *ctx, ValueRef result, const ValueRef object, String *name)
+ReturnedValue __qmljs_get_property(ExecutionContext *ctx, const ValueRef object, String *name)
{
- Value res;
- Managed *m = object->asManaged();
- if (m) {
- res = m->get(name);
- } else {
- if (object->isNullOrUndefined()) {
- QString message = QStringLiteral("Cannot read property '%1' of %2").arg(name->toQString()).arg(object->toQString());
- ctx->throwTypeError(message);
- }
+ Scope scope(ctx);
+
+ Scoped<Object> o(scope, object);
+ if (o)
+ return o->get(name);
- m = __qmljs_convert_to_object(ctx, object);
- res = m->get(name);
+ if (object->isNullOrUndefined()) {
+ QString message = QStringLiteral("Cannot read property '%1' of %2").arg(name->toQString()).arg(object->toQStringNoThrow());
+ ctx->throwTypeError(message);
}
- if (result)
- *result = res;
+
+ o = __qmljs_convert_to_object(ctx, object);
+ return o->get(name);
}
-void __qmljs_get_activation_property(ExecutionContext *ctx, ValueRef result, String *name)
+ReturnedValue __qmljs_get_activation_property(ExecutionContext *ctx, String *name)
{
- *result = ctx->getProperty(name);
+ return ctx->getProperty(name);
}
uint __qmljs_equal_helper(const ValueRef x, const ValueRef y)
{
- Q_ASSERT(x->type() != y->type());
+ Q_ASSERT(x->type() != y->type() || (x->isManaged() && (x->isString() != y->isString())));
if (x->isNumber() && y->isNumber())
return x->asDouble() == y->asDouble();
@@ -705,11 +802,13 @@ uint __qmljs_equal_helper(const ValueRef x, const ValueRef y)
Value ny = Value::fromDouble((double) y->booleanValue());
return __qmljs_cmp_eq(x, ValueRef(&ny));
} else if ((x->isNumber() || x->isString()) && y->isObject()) {
- Value py = __qmljs_to_primitive(y, PREFERREDTYPE_HINT);
- return __qmljs_cmp_eq(x, ValueRef(&py));
+ Scope scope(y->objectValue()->engine());
+ ScopedValue py(scope, __qmljs_to_primitive(y, PREFERREDTYPE_HINT));
+ return __qmljs_cmp_eq(x, py);
} else if (x->isObject() && (y->isNumber() || y->isString())) {
- Value px = __qmljs_to_primitive(x, PREFERREDTYPE_HINT);
- return __qmljs_cmp_eq(ValueRef(&px), y);
+ Scope scope(x->objectValue()->engine());
+ ScopedValue px(scope, __qmljs_to_primitive(x, PREFERREDTYPE_HINT));
+ return __qmljs_cmp_eq(px, y);
}
return false;
@@ -721,7 +820,7 @@ Bool __qmljs_strict_equal(const ValueRef x, const ValueRef y)
if (x->rawValue() == y->rawValue())
// NaN != NaN
- return (x->tag & QV4::Value::NotDouble_Mask) != QV4::Value::NaN_Mask;
+ return !x->isNaN();
if (x->isNumber())
return y->isNumber() && x->asDouble() == y->asDouble();
@@ -730,181 +829,244 @@ Bool __qmljs_strict_equal(const ValueRef x, const ValueRef y)
return false;
}
+QV4::Bool __qmljs_cmp_gt(const QV4::ValueRef l, const QV4::ValueRef r)
+{
+ TRACE2(l, r);
+ if (QV4::Value::integerCompatible(*l, *r))
+ return l->integerValue() > r->integerValue();
+ if (QV4::Value::bothDouble(*l, *r))
+ return l->doubleValue() > r->doubleValue();
+ if (l->isString() && r->isString())
+ return r->stringValue()->compare(l->stringValue());
+
+ if (l->isObject() || r->isObject()) {
+ QV4::ExecutionEngine *e = (l->isObject() ? l->objectValue() : r->objectValue())->engine();
+ QV4::Scope scope(e);
+ QV4::ScopedValue pl(scope, __qmljs_to_primitive(l, QV4::NUMBER_HINT));
+ QV4::ScopedValue pr(scope, __qmljs_to_primitive(r, QV4::NUMBER_HINT));
+ return __qmljs_cmp_gt(pl, pr);
+ }
+
+ double dl = __qmljs_to_number(l);
+ double dr = __qmljs_to_number(r);
+ return dl > dr;
+}
+
+QV4::Bool __qmljs_cmp_lt(const QV4::ValueRef l, const QV4::ValueRef r)
+{
+ TRACE2(l, r);
+ if (QV4::Value::integerCompatible(*l, *r))
+ return l->integerValue() < r->integerValue();
+ if (QV4::Value::bothDouble(*l, *r))
+ return l->doubleValue() < r->doubleValue();
+ if (l->isString() && r->isString())
+ return l->stringValue()->compare(r->stringValue());
+
+ if (l->isObject() || r->isObject()) {
+ QV4::ExecutionEngine *e = (l->isObject() ? l->objectValue() : r->objectValue())->engine();
+ QV4::Scope scope(e);
+ QV4::ScopedValue pl(scope, __qmljs_to_primitive(l, QV4::NUMBER_HINT));
+ QV4::ScopedValue pr(scope, __qmljs_to_primitive(r, QV4::NUMBER_HINT));
+ return __qmljs_cmp_lt(pl, pr);
+ }
+
+ double dl = __qmljs_to_number(l);
+ double dr = __qmljs_to_number(r);
+ return dl < dr;
+}
+
+QV4::Bool __qmljs_cmp_ge(const QV4::ValueRef l, const QV4::ValueRef r)
+{
+ TRACE2(l, r);
+ if (QV4::Value::integerCompatible(*l, *r))
+ return l->integerValue() >= r->integerValue();
+ if (QV4::Value::bothDouble(*l, *r))
+ return l->doubleValue() >= r->doubleValue();
+ if (l->isString() && r->isString())
+ return !l->stringValue()->compare(r->stringValue());
+
+ if (l->isObject() || r->isObject()) {
+ QV4::ExecutionEngine *e = (l->isObject() ? l->objectValue() : r->objectValue())->engine();
+ QV4::Scope scope(e);
+ QV4::ScopedValue pl(scope, __qmljs_to_primitive(l, QV4::NUMBER_HINT));
+ QV4::ScopedValue pr(scope, __qmljs_to_primitive(r, QV4::NUMBER_HINT));
+ return __qmljs_cmp_ge(pl, pr);
+ }
+
+ double dl = __qmljs_to_number(l);
+ double dr = __qmljs_to_number(r);
+ return dl >= dr;
+}
+
+QV4::Bool __qmljs_cmp_le(const QV4::ValueRef l, const QV4::ValueRef r)
+{
+ TRACE2(l, r);
+ if (QV4::Value::integerCompatible(*l, *r))
+ return l->integerValue() <= r->integerValue();
+ if (QV4::Value::bothDouble(*l, *r))
+ return l->doubleValue() <= r->doubleValue();
+ if (l->isString() && r->isString())
+ return !r->stringValue()->compare(l->stringValue());
+
+ if (l->isObject() || r->isObject()) {
+ QV4::ExecutionEngine *e = (l->isObject() ? l->objectValue() : r->objectValue())->engine();
+ QV4::Scope scope(e);
+ QV4::ScopedValue pl(scope, __qmljs_to_primitive(l, QV4::NUMBER_HINT));
+ QV4::ScopedValue pr(scope, __qmljs_to_primitive(r, QV4::NUMBER_HINT));
+ return __qmljs_cmp_le(pl, pr);
+ }
+
+ double dl = __qmljs_to_number(l);
+ double dr = __qmljs_to_number(r);
+ return dl <= dr;
+}
+
-void __qmljs_call_global_lookup(ExecutionContext *context, ValueRef result, uint index, CallDataRef callData)
+ReturnedValue __qmljs_call_global_lookup(ExecutionContext *context, uint index, CallDataRef callData)
{
+ Scope scope(context);
Q_ASSERT(callData->thisObject.isUndefined());
Lookup *l = context->lookups + index;
- Value v;
- l->globalGetter(l, context, &v);
- FunctionObject *o = v.asFunctionObject();
+ Scoped<FunctionObject> o(scope, l->globalGetter(l, context));
if (!o)
context->throwTypeError();
- if (o == context->engine->evalFunction && l->name->isEqualTo(context->engine->id_eval)) {
- Value res = static_cast<EvalFunction *>(o)->evalCall(callData->thisObject, callData->args, callData->argc, true);
- if (result)
- *result = res;
- return;
- }
+ if (o.getPointer() == context->engine->evalFunction && l->name->isEqualTo(context->engine->id_eval))
+ return static_cast<EvalFunction *>(o.getPointer())->evalCall(callData->thisObject, callData->args, callData->argc, true);
- Value res = o->call(callData);
- if (result)
- *result = res;
+ return o->call(callData);
}
-void __qmljs_call_activation_property(ExecutionContext *context, ValueRef result, String *name, CallDataRef callData)
+ReturnedValue __qmljs_call_activation_property(ExecutionContext *context, String *name, CallDataRef callData)
{
Q_ASSERT(callData->thisObject.isUndefined());
+ Scope scope(context);
Object *base;
- Value func = context->getPropertyAndBase(name, &base);
+ ScopedValue func(scope, context->getPropertyAndBase(name, &base));
if (base)
callData->thisObject = Value::fromObject(base);
- FunctionObject *o = func.asFunctionObject();
+ FunctionObject *o = func->asFunctionObject();
if (!o) {
QString objectAsString = QStringLiteral("[null]");
if (base)
- objectAsString = Value::fromObject(base).toQString();
+ objectAsString = Value::fromObject(base).toQStringNoThrow();
QString msg = QStringLiteral("Property '%1' of object %2 is not a function").arg(name->toQString()).arg(objectAsString);
context->throwTypeError(msg);
}
if (o == context->engine->evalFunction && name->isEqualTo(context->engine->id_eval)) {
- Value res = static_cast<EvalFunction *>(o)->evalCall(callData->thisObject, callData->args, callData->argc, true);
- if (result)
- *result = res;
- return;
+ return static_cast<EvalFunction *>(o)->evalCall(callData->thisObject, callData->args, callData->argc, true);
}
- Value res = o->call(callData);
- if (result)
- *result = res;
+ return o->call(callData);
}
-void __qmljs_call_property(ExecutionContext *context, ValueRef result, String *name, CallDataRef callData)
+ReturnedValue __qmljs_call_property(ExecutionContext *context, String *name, CallDataRef callData)
{
- Managed *baseObject = callData->thisObject.asManaged();
+ Scope scope(context);
+ Scoped<Object> baseObject(scope, callData->thisObject);
if (!baseObject) {
- if (callData->thisObject.isNullOrUndefined()) {
- QString message = QStringLiteral("Cannot call method '%1' of %2").arg(name->toQString()).arg(callData->thisObject.toQString());
+ if (callData->thisObject.isNullOrUndefined() || callData->thisObject.isEmpty()) {
+ QString message = QStringLiteral("Cannot call method '%1' of %2").arg(name->toQString()).arg(callData->thisObject.toQStringNoThrow());
context->throwTypeError(message);
}
baseObject = __qmljs_convert_to_object(context, ValueRef(&callData->thisObject));
- callData->thisObject = Value::fromObject(static_cast<Object *>(baseObject));
+ callData->thisObject = baseObject.asValue();
}
- FunctionObject *o = baseObject->get(name).asFunctionObject();
+ Scoped<FunctionObject> o(scope, baseObject->get(name));
if (!o) {
- QString error = QString("Property '%1' of object %2 is not a function").arg(name->toQString(), callData->thisObject.toQString());
+ QString error = QString("Property '%1' of object %2 is not a function").arg(name->toQString(), callData->thisObject.toQStringNoThrow());
context->throwTypeError(error);
}
- Value res = o->call(callData);
- if (result)
- *result = res;
+ return o->call(callData);
}
-void __qmljs_call_property_lookup(ExecutionContext *context, ValueRef result, uint index, CallDataRef callData)
+ReturnedValue __qmljs_call_property_lookup(ExecutionContext *context, uint index, CallDataRef callData)
{
- Value func;
+ Scope scope(context);
Lookup *l = context->lookups + index;
- l->getter(l, &func, callData->thisObject);
-
- Object *o = func.asObject();
+ Scoped<Object> o(scope, l->getter(l, callData->thisObject));
if (!o)
context->throwTypeError();
- Value res = o->call(callData);
- if (result)
- *result = res;
+ return o->call(callData);
}
-void __qmljs_call_element(ExecutionContext *context, ValueRef result, const ValueRef index, CallDataRef callData)
+ReturnedValue __qmljs_call_element(ExecutionContext *context, const ValueRef index, CallDataRef callData)
{
+ Scope scope(context);
Object *baseObject = callData->thisObject.toObject(context);
callData->thisObject = Value::fromObject(baseObject);
- Object *o = baseObject->get(index->toString(context)).asObject();
+ Scoped<Object> o(scope, baseObject->get(index->toString(context)));
if (!o)
context->throwTypeError();
- Value res = o->call(callData);
- if (result)
- *result = res;
+ return o->call(callData);
}
-void __qmljs_call_value(ExecutionContext *context, ValueRef result, const ValueRef func, CallDataRef callData)
+ReturnedValue __qmljs_call_value(ExecutionContext *context, const ValueRef func, CallDataRef callData)
{
Object *o = func->asObject();
if (!o)
context->throwTypeError();
- Value res = o->call(callData);
- if (result)
- *result = res;
+ return o->call(callData);
}
-void __qmljs_construct_global_lookup(ExecutionContext *context, ValueRef result, uint index, CallDataRef callData)
+ReturnedValue __qmljs_construct_global_lookup(ExecutionContext *context, uint index, CallDataRef callData)
{
+ Scope scope(context);
Q_ASSERT(callData->thisObject.isUndefined());
- Value func;
-
Lookup *l = context->lookups + index;
- l->globalGetter(l, context, &func);
-
- Object *f = func.asObject();
+ Scoped<Object> f(scope, l->globalGetter(l, context));
if (!f)
context->throwTypeError();
- Value res = f->construct(callData);
- if (result)
- *result = res;
+ return f->construct(callData);
}
-void __qmljs_construct_activation_property(ExecutionContext *context, ValueRef result, String *name, CallDataRef callData)
+ReturnedValue __qmljs_construct_activation_property(ExecutionContext *context, String *name, CallDataRef callData)
{
- Value func = context->getProperty(name);
- Object *f = func.asObject();
+ Scope scope(context);
+ ScopedValue func(scope, context->getProperty(name));
+ Object *f = func->asObject();
if (!f)
context->throwTypeError();
- Value res = f->construct(callData);
- if (result)
- *result = res;
+ return f->construct(callData);
}
-void __qmljs_construct_value(ExecutionContext *context, ValueRef result, const ValueRef func, CallDataRef callData)
+ReturnedValue __qmljs_construct_value(ExecutionContext *context, const ValueRef func, CallDataRef callData)
{
Object *f = func->asObject();
if (!f)
context->throwTypeError();
- Value res = f->construct(callData);
- if (result)
- *result = res;
+ return f->construct(callData);
}
-void __qmljs_construct_property(ExecutionContext *context, ValueRef result, const ValueRef base, String *name, CallDataRef callData)
+ReturnedValue __qmljs_construct_property(ExecutionContext *context, const ValueRef base, String *name, CallDataRef callData)
{
+ Scope scope(context);
Object *thisObject = base->toObject(context);
- Value func = thisObject->get(name);
- Object *f = func.asObject();
+ Scoped<Object> f(scope, thisObject->get(name));
if (!f)
context->throwTypeError();
- Value res = f->construct(callData);
- if (result)
- *result = res;
+ return f->construct(callData);
}
void __qmljs_throw(ExecutionContext *context, const ValueRef value)
@@ -912,10 +1074,8 @@ void __qmljs_throw(ExecutionContext *context, const ValueRef value)
Exception::throwException(context, *value);
}
-void __qmljs_builtin_typeof(ExecutionContext *ctx, ValueRef result, const ValueRef value)
+ReturnedValue __qmljs_builtin_typeof(ExecutionContext *ctx, const ValueRef value)
{
- if (!result)
- return;
String *res = 0;
switch (value->type()) {
case Value::Undefined_Type:
@@ -927,11 +1087,10 @@ void __qmljs_builtin_typeof(ExecutionContext *ctx, ValueRef result, const ValueR
case Value::Boolean_Type:
res = ctx->engine->id_boolean;
break;
- case Value::String_Type:
- res = ctx->engine->id_string;
- break;
- case Value::Object_Type:
- if (value->objectValue()->asFunctionObject())
+ case Value::Managed_Type:
+ if (value->isString())
+ res = ctx->engine->id_string;
+ else if (value->objectValue()->asFunctionObject())
res = ctx->engine->id_function;
else
res = ctx->engine->id_object; // ### implementation-defined
@@ -940,201 +1099,31 @@ void __qmljs_builtin_typeof(ExecutionContext *ctx, ValueRef result, const ValueR
res = ctx->engine->id_number;
break;
}
- *result = Value::fromString(res);
+ return Value::fromString(res).asReturnedValue();
}
-void __qmljs_builtin_typeof_name(ExecutionContext *context, ValueRef result, String *name)
+QV4::ReturnedValue __qmljs_builtin_typeof_name(ExecutionContext *context, String *name)
{
- ValueScope scope(context);
- ScopedValue res(scope);
+ Scope scope(context);
ScopedValue prop(scope, context->getPropertyNoThrow(name));
- __qmljs_builtin_typeof(context, res, prop);
- if (result)
- *result = res;
+ return __qmljs_builtin_typeof(context, prop);
}
-void __qmljs_builtin_typeof_member(ExecutionContext *context, ValueRef result, const ValueRef base,
- String *name)
+QV4::ReturnedValue __qmljs_builtin_typeof_member(ExecutionContext *context, const ValueRef base, String *name)
{
- ValueScope scope(context);
+ Scope scope(context);
Object *obj = base->toObject(context);
- ScopedValue res(scope);
ScopedValue prop(scope, obj->get(name));
- __qmljs_builtin_typeof(context, res, prop);
- if (result)
- *result = res;
+ return __qmljs_builtin_typeof(context, prop);
}
-void __qmljs_builtin_typeof_element(ExecutionContext *context, ValueRef result, const ValueRef base, const ValueRef index)
+QV4::ReturnedValue __qmljs_builtin_typeof_element(ExecutionContext *context, const ValueRef base, const ValueRef index)
{
- ValueScope scope(context);
+ Scope scope(context);
String *name = index->toString(context);
Object *obj = base->toObject(context);
- ScopedValue res(scope);
ScopedValue prop(scope, obj->get(name));
- __qmljs_builtin_typeof(context, res, prop);
- if (result)
- *result = res;
-}
-
-void __qmljs_builtin_post_increment(ValueRef result, ValueRef val)
-{
- if (val->isInteger() && val->integerValue() < INT_MAX) {
- if (result)
- *result = *val;
- val->int_32 += 1;
- return;
- }
-
- double d = val->toNumber();
- *val = Value::fromDouble(d + 1);
- if (result)
- *result = Value::fromDouble(d);
-}
-
-void __qmljs_builtin_post_increment_name(ExecutionContext *context, ValueRef result, String *name)
-{
- Value v = context->getProperty(name);
-
- if (v.isInteger() && v.integerValue() < INT_MAX) {
- if (result)
- *result = v;
- v.int_32 += 1;
- } else {
- double d = v.toNumber();
- if (result)
- *result = Value::fromDouble(d);
- v = Value::fromDouble(d + 1);
- }
-
- context->setProperty(name, v);
-}
-
-void __qmljs_builtin_post_increment_member(ExecutionContext *context, ValueRef result, const ValueRef base, String *name)
-{
- Object *o = base->toObject(context);
-
- Value v = o->get(name);
-
- if (v.isInteger() && v.integerValue() < INT_MAX) {
- if (result)
- *result = v;
- v.int_32 += 1;
- } else {
- double d = v.toNumber();
- if (result)
- *result = Value::fromDouble(d);
- v = Value::fromDouble(d + 1);
- }
-
- o->put(name, v);
-}
-
-void __qmljs_builtin_post_increment_element(ExecutionContext *context, ValueRef result, const ValueRef base, const ValueRef index)
-{
- Object *o = base->toObject(context);
-
- uint idx = index->asArrayIndex();
-
- if (idx == UINT_MAX) {
- String *s = index->toString(context);
- return __qmljs_builtin_post_increment_member(context, result, base, s);
- }
-
- Value v = o->getIndexed(idx);
-
- if (v.isInteger() && v.integerValue() < INT_MAX) {
- if (result)
- *result = v;
- v.int_32 += 1;
- } else {
- double d = v.toNumber();
- if (result)
- *result = Value::fromDouble(d);
- v = Value::fromDouble(d + 1);
- }
-
- o->putIndexed(idx, v);
-}
-
-void __qmljs_builtin_post_decrement(ValueRef result, ValueRef val)
-{
- if (val->isInteger() && val->integerValue() > INT_MIN) {
- if (result)
- *result = *val;
- val->int_32 -= 1;
- return;
- }
-
- double d = val->toNumber();
- *val = Value::fromDouble(d - 1);
- if (result)
- *result = Value::fromDouble(d);
-}
-
-void __qmljs_builtin_post_decrement_name(ExecutionContext *context, ValueRef result, String *name)
-{
- Value v = context->getProperty(name);
-
- if (v.isInteger() && v.integerValue() > INT_MIN) {
- if (result)
- *result = v;
- v.int_32 -= 1;
- } else {
- double d = v.toNumber();
- if (result)
- *result = Value::fromDouble(d);
- v = Value::fromDouble(d - 1);
- }
-
- context->setProperty(name, v);
-}
-
-void __qmljs_builtin_post_decrement_member(ExecutionContext *context, ValueRef result, const ValueRef base, String *name)
-{
- Object *o = base->toObject(context);
-
- Value v = o->get(name);
-
- if (v.isInteger() && v.integerValue() > INT_MIN) {
- if (result)
- *result = v;
- v.int_32 -= 1;
- } else {
- double d = v.toNumber();
- if (result)
- *result = Value::fromDouble(d);
- v = Value::fromDouble(d - 1);
- }
-
- o->put(name, v);
-}
-
-void __qmljs_builtin_post_decrement_element(ExecutionContext *context, ValueRef result, const ValueRef base, const ValueRef index)
-{
- Object *o = base->toObject(context);
-
- uint idx = index->asArrayIndex();
-
- if (idx == UINT_MAX) {
- String *s = index->toString(context);
- return __qmljs_builtin_post_decrement_member(context, result, base, s);
- }
-
- Value v = o->getIndexed(idx);
-
- if (v.isInteger() && v.integerValue() > INT_MIN) {
- if (result)
- *result = v;
- v.int_32 -= 1;
- } else {
- double d = v.toNumber();
- if (result)
- *result = Value::fromDouble(d);
- v = Value::fromDouble(d - 1);
- }
-
- o->putIndexed(idx, v);
+ return __qmljs_builtin_typeof(context, prop);
}
ExecutionContext *__qmljs_builtin_push_with_scope(const ValueRef o, ExecutionContext *ctx)
@@ -1168,9 +1157,10 @@ void __qmljs_builtin_define_property(ExecutionContext *ctx, const ValueRef objec
pd->value = val ? *val : Value::undefinedValue();
}
-void __qmljs_builtin_define_array(ExecutionContext *ctx, ValueRef array, Value *values, uint length)
+ReturnedValue __qmljs_builtin_define_array(ExecutionContext *ctx, Value *values, uint length)
{
- ArrayObject *a = ctx->engine->newArrayObject();
+ Scope scope(ctx);
+ Scoped<ArrayObject> a(scope, ctx->engine->newArrayObject());
// ### FIXME: We need to allocate the array data to avoid crashes other places
// This should rather be done when required
@@ -1190,7 +1180,7 @@ void __qmljs_builtin_define_array(ExecutionContext *ctx, ValueRef array, Value *
}
a->setArrayLengthUnchecked(length);
}
- *array = Value::fromObject(a);
+ return a.asReturnedValue();
}
void __qmljs_builtin_define_getter_setter(ExecutionContext *ctx, const ValueRef object, String *name, const ValueRef getter, const ValueRef setter)
@@ -1204,7 +1194,7 @@ void __qmljs_builtin_define_getter_setter(ExecutionContext *ctx, const ValueRef
pd->setSetter(setter ? setter->asFunctionObject() : 0);
}
-void __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, ValueRef result, const QV4::Value *args, int classId)
+ReturnedValue __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, const QV4::Value *args, int classId)
{
QV4::InternalClass *klass = ctx->compilationUnit->runtimeClasses[classId];
Object *o = ctx->engine->newObject(klass);
@@ -1220,44 +1210,58 @@ void __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, ValueRef
}
}
- *result = Value::fromObject(o);
+ return Value::fromObject(o).asReturnedValue();
}
-void __qmljs_builtin_setup_arguments_object(ExecutionContext *ctx, ValueRef result)
+QV4::ReturnedValue __qmljs_builtin_setup_arguments_object(ExecutionContext *ctx)
{
assert(ctx->type >= ExecutionContext::Type_CallContext);
CallContext *c = static_cast<CallContext *>(ctx);
ArgumentsObject *args = new (c->engine->memoryManager) ArgumentsObject(c);
- *result = Value::fromObject(args);
+ return Value::fromObject(args).asReturnedValue();
}
-void __qmljs_increment(QV4::ValueRef result, const QV4::ValueRef value)
+QV4::ReturnedValue __qmljs_increment(const QV4::ValueRef value)
{
TRACE1(value);
if (value->isInteger())
- *result = Value::fromInt32(value->integerValue() + 1);
+ return Value::fromInt32(value->integerValue() + 1).asReturnedValue();
else {
double d = value->toNumber();
- *result = Value::fromDouble(d + 1);
+ return Value::fromDouble(d + 1).asReturnedValue();
}
}
-void __qmljs_decrement(QV4::ValueRef result, const QV4::ValueRef value)
+QV4::ReturnedValue __qmljs_decrement(const QV4::ValueRef value)
{
TRACE1(value);
if (value->isInteger())
- *result = Value::fromInt32(value->integerValue() - 1);
+ return Value::fromInt32(value->integerValue() - 1).asReturnedValue();
else {
double d = value->toNumber();
- *result = Value::fromDouble(d - 1);
+ return Value::fromDouble(d - 1).asReturnedValue();
}
}
-void __qmljs_value_to_double(double *result, const ValueRef value)
+QV4::ReturnedValue __qmljs_to_string(const QV4::ValueRef value, QV4::ExecutionContext *ctx)
+{
+ if (value->isString())
+ return value.asReturnedValue();
+ return __qmljs_convert_to_string(ctx, value)->asReturnedValue();
+}
+
+QV4::ReturnedValue __qmljs_to_object(QV4::ExecutionContext *ctx, const QV4::ValueRef value)
+{
+ if (value->isObject())
+ return value.asReturnedValue();
+ return Encode(__qmljs_convert_to_object(ctx, value));
+}
+
+ReturnedValue __qmljs_value_to_double(const ValueRef value)
{
- *result = value->toNumber();
+ return Encode(value->toNumber());
}
int __qmljs_value_to_int32(const ValueRef value)
@@ -1280,14 +1284,14 @@ unsigned __qmljs_double_to_uint32(const double &d)
return Value::toUInt32(d);
}
-void __qmljs_value_from_string(ValueRef result, String *string)
+ReturnedValue __qmljs_value_from_string(String *string)
{
- *result = Value::fromString(string);
+ return Value::fromString(string).asReturnedValue();
}
-void __qmljs_lookup_runtime_regexp(ExecutionContext *ctx, ValueRef result, int id)
+ReturnedValue __qmljs_lookup_runtime_regexp(ExecutionContext *ctx, int id)
{
- *result = ctx->compilationUnit->runtimeRegularExpressions[id];
+ return ctx->compilationUnit->runtimeRegularExpressions[id].asReturnedValue();
}
} // namespace QV4
diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h
index d1ca86fddd..8fbf7a6cb8 100644
--- a/src/qml/jsruntime/qv4runtime_p.h
+++ b/src/qml/jsruntime/qv4runtime_p.h
@@ -57,18 +57,36 @@
//#include <wtf/MathExtras.h>
-#ifdef DO_TRACE_INSTR
-# define TRACE1(x) fprintf(stderr, " %s\n", __FUNCTION__);
-# define TRACE2(x, y) fprintf(stderr, " %s\n", __FUNCTION__);
-#else
-# define TRACE1(x)
-# define TRACE2(x, y)
-#endif // TRACE1
-
QT_BEGIN_NAMESPACE
+#undef QV4_COUNT_RUNTIME_FUNCTIONS
+
namespace QV4 {
+#ifdef QV4_COUNT_RUNTIME_FUNCTIONS
+class RuntimeCounters
+{
+public:
+ RuntimeCounters();
+ ~RuntimeCounters();
+
+ static RuntimeCounters *instance;
+
+ void count(const char *func, uint tag);
+ void count(const char *func, uint tag1, uint tag2);
+
+private:
+ struct Data;
+ Data *d;
+};
+
+# define TRACE1(x) RuntimeCounters::instance->count(Q_FUNC_INFO, x.type());
+# define TRACE2(x, y) RuntimeCounters::instance->count(Q_FUNC_INFO, x.type(), y.type());
+#else
+# define TRACE1(x)
+# define TRACE2(x, y)
+#endif // QV4_COUNT_RUNTIME_FUNCTIONS
+
enum TypeHint {
PREFERREDTYPE_HINT,
NUMBER_HINT,
@@ -91,30 +109,20 @@ struct ExecutionEngine;
struct InternalClass;
// context
-void __qmljs_call_activation_property(QV4::ExecutionContext *, QV4::ValueRef result, QV4::String *name, CallDataRef callData);
-void __qmljs_call_property(QV4::ExecutionContext *context, QV4::ValueRef result, QV4::String *name, CallDataRef callData);
-void __qmljs_call_property_lookup(ExecutionContext *context, ValueRef result, uint index, CallDataRef callData);
-void __qmljs_call_element(ExecutionContext *context, ValueRef result, const ValueRef index, CallDataRef callData);
-void __qmljs_call_value(QV4::ExecutionContext *context, QV4::ValueRef result, const QV4::ValueRef func, CallDataRef callData);
-
-void __qmljs_construct_activation_property(QV4::ExecutionContext *, QV4::ValueRef result, QV4::String *name, CallDataRef callData);
-void __qmljs_construct_property(QV4::ExecutionContext *context, QV4::ValueRef result, const QV4::ValueRef base, QV4::String *name, CallDataRef callData);
-void __qmljs_construct_value(QV4::ExecutionContext *context, QV4::ValueRef result, const QV4::ValueRef func, CallDataRef callData);
-
-void __qmljs_builtin_typeof(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef val);
-void __qmljs_builtin_typeof_name(QV4::ExecutionContext *context, QV4::ValueRef result, QV4::String *name);
-void __qmljs_builtin_typeof_member(QV4::ExecutionContext* context, QV4::ValueRef result, const QV4::ValueRef base, QV4::String *name);
-void __qmljs_builtin_typeof_element(QV4::ExecutionContext* context, QV4::ValueRef result, const QV4::ValueRef base, const QV4::ValueRef index);
-
-void __qmljs_builtin_post_increment(QV4::ValueRef result, QV4::ValueRef val);
-void __qmljs_builtin_post_increment_name(QV4::ExecutionContext *context, QV4::ValueRef result, QV4::String *name);
-void __qmljs_builtin_post_increment_member(QV4::ExecutionContext *context, QV4::ValueRef result, const QV4::ValueRef base, QV4::String *name);
-void __qmljs_builtin_post_increment_element(QV4::ExecutionContext *context, QV4::ValueRef result, const QV4::ValueRef base, const QV4::ValueRef index);
-
-void __qmljs_builtin_post_decrement(QV4::ValueRef result, QV4::ValueRef val);
-void __qmljs_builtin_post_decrement_name(QV4::ExecutionContext *context, QV4::ValueRef result, QV4::String *name);
-void __qmljs_builtin_post_decrement_member(QV4::ExecutionContext *context, QV4::ValueRef result, const QV4::ValueRef base, QV4::String *name);
-void __qmljs_builtin_post_decrement_element(QV4::ExecutionContext *context, QV4::ValueRef result, const QV4::ValueRef base, const QV4::ValueRef index);
+QV4::ReturnedValue __qmljs_call_activation_property(QV4::ExecutionContext *, QV4::String *name, CallDataRef callData);
+QV4::ReturnedValue __qmljs_call_property(QV4::ExecutionContext *context, QV4::String *name, CallDataRef callData);
+QV4::ReturnedValue __qmljs_call_property_lookup(ExecutionContext *context, uint index, CallDataRef callData);
+QV4::ReturnedValue __qmljs_call_element(ExecutionContext *context, const ValueRef index, CallDataRef callData);
+QV4::ReturnedValue __qmljs_call_value(QV4::ExecutionContext *context, const QV4::ValueRef func, CallDataRef callData);
+
+QV4::ReturnedValue __qmljs_construct_activation_property(QV4::ExecutionContext *, QV4::String *name, CallDataRef callData);
+QV4::ReturnedValue __qmljs_construct_property(QV4::ExecutionContext *context, const QV4::ValueRef base, QV4::String *name, CallDataRef callData);
+QV4::ReturnedValue __qmljs_construct_value(QV4::ExecutionContext *context, const QV4::ValueRef func, CallDataRef callData);
+
+QV4::ReturnedValue __qmljs_builtin_typeof(QV4::ExecutionContext *ctx, const QV4::ValueRef val);
+QV4::ReturnedValue __qmljs_builtin_typeof_name(QV4::ExecutionContext *context, QV4::String *name);
+QV4::ReturnedValue __qmljs_builtin_typeof_member(QV4::ExecutionContext* context, const QV4::ValueRef base, QV4::String *name);
+QV4::ReturnedValue __qmljs_builtin_typeof_element(QV4::ExecutionContext* context, const QV4::ValueRef base, const QV4::ValueRef index);
void Q_NORETURN __qmljs_builtin_rethrow(QV4::ExecutionContext *context);
QV4::ExecutionContext *__qmljs_builtin_push_with_scope(const QV4::ValueRef o, QV4::ExecutionContext *ctx);
@@ -122,101 +130,101 @@ QV4::ExecutionContext *__qmljs_builtin_push_catch_scope(QV4::String *exceptionVa
QV4::ExecutionContext *__qmljs_builtin_pop_scope(QV4::ExecutionContext *ctx);
void __qmljs_builtin_declare_var(QV4::ExecutionContext *ctx, bool deletable, QV4::String *name);
void __qmljs_builtin_define_property(QV4::ExecutionContext *ctx, const QV4::ValueRef object, QV4::String *name, QV4::ValueRef val);
-void __qmljs_builtin_define_array(QV4::ExecutionContext *ctx, QV4::ValueRef array, QV4::Value *values, uint length);
+QV4::ReturnedValue __qmljs_builtin_define_array(QV4::ExecutionContext *ctx, QV4::Value *values, uint length);
void __qmljs_builtin_define_getter_setter(QV4::ExecutionContext *ctx, const QV4::ValueRef object, QV4::String *name, const QV4::ValueRef getter, const QV4::ValueRef setter);
-void __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::Value *args, int classId);
-void __qmljs_builtin_setup_arguments_object(ExecutionContext *ctx, QV4::ValueRef result);
+QV4::ReturnedValue __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, const QV4::Value *args, int classId);
+QV4::ReturnedValue __qmljs_builtin_setup_arguments_object(ExecutionContext *ctx);
-void __qmljs_value_from_string(QV4::ValueRef result, QV4::String *string);
-void __qmljs_lookup_runtime_regexp(QV4::ExecutionContext *ctx, QV4::ValueRef result, int id);
+QV4::ReturnedValue __qmljs_value_from_string(QV4::String *string);
+QV4::ReturnedValue __qmljs_lookup_runtime_regexp(QV4::ExecutionContext *ctx, int id);
// constructors
-void __qmljs_init_closure(QV4::ExecutionContext *ctx, QV4::ValueRef result, int functionId);
+QV4::ReturnedValue __qmljs_init_closure(QV4::ExecutionContext *ctx, int functionId);
// strings
Q_QML_EXPORT double __qmljs_string_to_number(const QString &s);
-QV4::Value __qmljs_string_from_number(QV4::ExecutionContext *ctx, double number);
-QV4::String *__qmljs_string_concat(QV4::ExecutionContext *ctx, QV4::String *first, QV4::String *second);
+Returned<String> *__qmljs_string_from_number(QV4::ExecutionContext *ctx, double number);
+Returned<String> *__qmljs_string_concat(QV4::ExecutionContext *ctx, QV4::String *first, QV4::String *second);
// objects
-Q_QML_EXPORT QV4::Value __qmljs_object_default_value(QV4::Object *object, int typeHint);
+Q_QML_EXPORT ReturnedValue __qmljs_object_default_value(QV4::Object *object, int typeHint);
void __qmljs_set_activation_property(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::ValueRef value);
void __qmljs_set_property(QV4::ExecutionContext *ctx, const QV4::ValueRef object, QV4::String *name, const QV4::ValueRef value);
-void __qmljs_get_property(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef object, QV4::String *name);
-void __qmljs_get_activation_property(QV4::ExecutionContext *ctx, QV4::ValueRef result, QV4::String *name);
+QV4::ReturnedValue __qmljs_get_property(QV4::ExecutionContext *ctx, const QV4::ValueRef object, QV4::String *name);
+QV4::ReturnedValue __qmljs_get_activation_property(QV4::ExecutionContext *ctx, QV4::String *name);
-void __qmljs_call_global_lookup(QV4::ExecutionContext *context, QV4::ValueRef result, uint index, CallDataRef callData);
-void __qmljs_construct_global_lookup(QV4::ExecutionContext *context, QV4::ValueRef result, uint index, CallDataRef callData);
+ReturnedValue __qmljs_call_global_lookup(QV4::ExecutionContext *context, uint index, CallDataRef callData);
+QV4::ReturnedValue __qmljs_construct_global_lookup(QV4::ExecutionContext *context, uint index, CallDataRef callData);
-void __qmljs_get_element(QV4::ExecutionContext *ctx, QV4::ValueRef retval, const QV4::ValueRef object, const QV4::ValueRef index);
+QV4::ReturnedValue __qmljs_get_element(QV4::ExecutionContext *ctx, const QV4::ValueRef object, const QV4::ValueRef index);
void __qmljs_set_element(QV4::ExecutionContext *ctx, const QV4::ValueRef object, const QV4::ValueRef index, const QV4::ValueRef value);
// For each
-void __qmljs_foreach_iterator_object(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef in);
-void __qmljs_foreach_next_property_name(QV4::ValueRef result, const ValueRef foreach_iterator);
+QV4::ReturnedValue __qmljs_foreach_iterator_object(QV4::ExecutionContext *ctx, const QV4::ValueRef in);
+QV4::ReturnedValue __qmljs_foreach_next_property_name(const ValueRef foreach_iterator);
// type conversion and testing
-QV4::Value __qmljs_to_primitive(const ValueRef value, int typeHint);
+QV4::ReturnedValue __qmljs_to_primitive(const ValueRef value, int typeHint);
Q_QML_EXPORT QV4::Bool __qmljs_to_boolean(const QV4::ValueRef value);
double __qmljs_to_number(const QV4::ValueRef value);
-QV4::Value __qmljs_to_string(const ValueRef value, QV4::ExecutionContext *ctx);
-Q_QML_EXPORT QV4::String *__qmljs_convert_to_string(QV4::ExecutionContext *ctx, const ValueRef value);
+QV4::ReturnedValue __qmljs_to_string(const ValueRef value, QV4::ExecutionContext *ctx);
+Q_QML_EXPORT Returned<String> *__qmljs_convert_to_string(QV4::ExecutionContext *ctx, const ValueRef value);
void __qmljs_numberToString(QString *result, double num, int radix = 10);
-QV4::Value __qmljs_to_object(QV4::ExecutionContext *ctx, const ValueRef value);
-QV4::Object *__qmljs_convert_to_object(QV4::ExecutionContext *ctx, const ValueRef value);
+ReturnedValue __qmljs_to_object(QV4::ExecutionContext *ctx, const ValueRef value);
+Returned<Object> *__qmljs_convert_to_object(QV4::ExecutionContext *ctx, const ValueRef value);
QV4::Bool __qmljs_equal_helper(const ValueRef x, const ValueRef y);
Q_QML_EXPORT QV4::Bool __qmljs_strict_equal(const ValueRef x, const ValueRef y);
// unary operators
-typedef void (*UnaryOpName)(QV4::ValueRef, const QV4::ValueRef);
-void __qmljs_uplus(QV4::ValueRef result, const QV4::ValueRef value);
-void __qmljs_uminus(QV4::ValueRef result, const QV4::ValueRef value);
-void __qmljs_compl(QV4::ValueRef result, const QV4::ValueRef value);
-void __qmljs_not(QV4::ValueRef result, const QV4::ValueRef value);
-void __qmljs_increment(QV4::ValueRef result, const QV4::ValueRef value);
-void __qmljs_decrement(QV4::ValueRef result, const QV4::ValueRef value);
-
-Q_QML_EXPORT void __qmljs_value_to_double(double *result, const ValueRef value);
+typedef QV4::ReturnedValue (*UnaryOpName)(const QV4::ValueRef);
+QV4::ReturnedValue __qmljs_uplus(const QV4::ValueRef value);
+QV4::ReturnedValue __qmljs_uminus(const QV4::ValueRef value);
+QV4::ReturnedValue __qmljs_compl(const QV4::ValueRef value);
+QV4::ReturnedValue __qmljs_not(const QV4::ValueRef value);
+QV4::ReturnedValue __qmljs_increment(const QV4::ValueRef value);
+QV4::ReturnedValue __qmljs_decrement(const QV4::ValueRef value);
+
+Q_QML_EXPORT ReturnedValue __qmljs_value_to_double(const ValueRef value);
Q_QML_EXPORT int __qmljs_value_to_int32(const ValueRef value);
Q_QML_EXPORT int __qmljs_double_to_int32(const double &d);
Q_QML_EXPORT unsigned __qmljs_value_to_uint32(const ValueRef value);
Q_QML_EXPORT unsigned __qmljs_double_to_uint32(const double &d);
-void __qmljs_delete_subscript(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef base, const QV4::ValueRef index);
-void __qmljs_delete_member(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef base, QV4::String *name);
-void __qmljs_delete_name(QV4::ExecutionContext *ctx, QV4::ValueRef result, QV4::String *name);
+QV4::ReturnedValue __qmljs_delete_subscript(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index);
+ReturnedValue __qmljs_delete_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name);
+ReturnedValue __qmljs_delete_name(QV4::ExecutionContext *ctx, QV4::String *name);
void Q_NORETURN __qmljs_throw(QV4::ExecutionContext*, const QV4::ValueRef value);
// binary operators
-typedef void (*BinOp)(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
-typedef void (*BinOpContext)(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
-
-void __qmljs_instanceof(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
-void __qmljs_in(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
-void __qmljs_add(ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
-void __qmljs_bit_or(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
-void __qmljs_bit_xor(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
-void __qmljs_bit_and(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
-void __qmljs_sub(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
-void __qmljs_mul(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
-void __qmljs_div(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
-void __qmljs_mod(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
-void __qmljs_shl(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
-void __qmljs_shr(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
-void __qmljs_ushr(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
-void __qmljs_gt(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
-void __qmljs_lt(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
-void __qmljs_ge(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
-void __qmljs_le(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
-void __qmljs_eq(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
-void __qmljs_ne(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
-void __qmljs_se(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
-void __qmljs_sne(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
-
-void __qmljs_add_helper(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+typedef QV4::ReturnedValue (*BinOp)(const QV4::ValueRef left, const QV4::ValueRef right);
+typedef QV4::ReturnedValue (*BinOpContext)(QV4::ExecutionContext *ctx, const QV4::ValueRef left, const QV4::ValueRef right);
+
+QV4::ReturnedValue __qmljs_instanceof(QV4::ExecutionContext *ctx, const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::ReturnedValue __qmljs_in(QV4::ExecutionContext *ctx, const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::ReturnedValue __qmljs_add(ExecutionContext *ctx, const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::ReturnedValue __qmljs_bit_or(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::ReturnedValue __qmljs_bit_xor(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::ReturnedValue __qmljs_bit_and(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::ReturnedValue __qmljs_sub(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::ReturnedValue __qmljs_mul(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::ReturnedValue __qmljs_div(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::ReturnedValue __qmljs_mod(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::ReturnedValue __qmljs_shl(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::ReturnedValue __qmljs_shr(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::ReturnedValue __qmljs_ushr(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::ReturnedValue __qmljs_gt(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::ReturnedValue __qmljs_lt(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::ReturnedValue __qmljs_ge(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::ReturnedValue __qmljs_le(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::ReturnedValue __qmljs_eq(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::ReturnedValue __qmljs_ne(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::ReturnedValue __qmljs_se(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::ReturnedValue __qmljs_sne(const QV4::ValueRef left, const QV4::ValueRef right);
+
+QV4::ReturnedValue __qmljs_add_helper(QV4::ExecutionContext *ctx, const QV4::ValueRef left, const QV4::ValueRef right);
typedef void (*InplaceBinOpName)(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::ValueRef value);
@@ -259,10 +267,10 @@ void __qmljs_inplace_shr_member(QV4::ExecutionContext *ctx, const QV4::ValueRef
void __qmljs_inplace_ushr_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
typedef QV4::Bool (*CmpOp)(const QV4::ValueRef left, const QV4::ValueRef right);
-QV4::Bool __qmljs_cmp_gt(const QV4::ValueRef left, const QV4::ValueRef right);
-QV4::Bool __qmljs_cmp_lt(const QV4::ValueRef left, const QV4::ValueRef right);
-QV4::Bool __qmljs_cmp_ge(const QV4::ValueRef left, const QV4::ValueRef right);
-QV4::Bool __qmljs_cmp_le(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::Bool __qmljs_cmp_gt(const QV4::ValueRef l, const QV4::ValueRef r);
+QV4::Bool __qmljs_cmp_lt(const QV4::ValueRef l, const QV4::ValueRef r);
+QV4::Bool __qmljs_cmp_ge(const QV4::ValueRef l, const QV4::ValueRef r);
+QV4::Bool __qmljs_cmp_le(const QV4::ValueRef l, const QV4::ValueRef r);
QV4::Bool __qmljs_cmp_eq(const QV4::ValueRef left, const QV4::ValueRef right);
QV4::Bool __qmljs_cmp_ne(const QV4::ValueRef left, const QV4::ValueRef right);
QV4::Bool __qmljs_cmp_se(const QV4::ValueRef left, const QV4::ValueRef right);
@@ -273,11 +281,11 @@ QV4::Bool __qmljs_cmp_instanceof(QV4::ExecutionContext *ctx, const QV4::ValueRef
QV4::Bool __qmljs_cmp_in(QV4::ExecutionContext *ctx, const QV4::ValueRef left, const QV4::ValueRef right);
// type conversion and testing
-inline QV4::Value __qmljs_to_primitive(const QV4::ValueRef value, int typeHint)
+inline ReturnedValue __qmljs_to_primitive(const QV4::ValueRef value, int typeHint)
{
QV4::Object *o = value->asObject();
if (!o)
- return *value;
+ return value.asReturnedValue();
return __qmljs_object_default_value(o, typeHint);
}
@@ -286,210 +294,174 @@ inline double __qmljs_to_number(const ValueRef value)
return value->toNumber();
}
-inline QV4::Value __qmljs_to_string(const QV4::ValueRef value, QV4::ExecutionContext *ctx)
-{
- if (value->isString())
- return *value;
- return QV4::Value::fromString(__qmljs_convert_to_string(ctx, value));
-}
-
-inline QV4::Value __qmljs_to_object(QV4::ExecutionContext *ctx, const QV4::ValueRef value)
-{
- if (value->isObject())
- return *value;
- return QV4::Value::fromObject(__qmljs_convert_to_object(ctx, value));
-}
-
-
-inline void __qmljs_uplus(QV4::ValueRef result, const QV4::ValueRef value)
+inline QV4::ReturnedValue __qmljs_uplus(const QV4::ValueRef value)
{
TRACE1(value);
- result = value;
- if (result->tryIntegerConversion())
- return;
+ if (value->integerCompatible())
+ return Encode(value->int_32);
- double n = __qmljs_to_number(value);
- *result = QV4::Value::fromDouble(n);
+ double n = value->toNumber();
+ return Encode(n);
}
-inline void __qmljs_uminus(QV4::ValueRef result, const QV4::ValueRef value)
+inline QV4::ReturnedValue __qmljs_uminus(const QV4::ValueRef value)
{
TRACE1(value);
// +0 != -0, so we need to convert to double when negating 0
if (value->isInteger() && value->integerValue())
- *result = QV4::Value::fromInt32(-value->integerValue());
+ return QV4::Value::fromInt32(-value->integerValue()).asReturnedValue();
else {
double n = __qmljs_to_number(value);
- *result = QV4::Value::fromDouble(-n);
+ return QV4::Value::fromDouble(-n).asReturnedValue();
}
}
-inline void __qmljs_compl(QV4::ValueRef result, const QV4::ValueRef value)
+inline QV4::ReturnedValue __qmljs_compl(const QV4::ValueRef value)
{
TRACE1(value);
int n;
- if (value->isConvertibleToInt())
+ if (value->integerCompatible())
n = value->int_32;
else
- n = QV4::Value::toInt32(__qmljs_to_number(value));
+ n = value->toInt32();
- *result = QV4::Value::fromInt32(~n);
+ return Encode((int)~n);
}
-inline void __qmljs_not(QV4::ValueRef result, const QV4::ValueRef value)
+inline QV4::ReturnedValue __qmljs_not(const QV4::ValueRef value)
{
TRACE1(value);
bool b = value->toBoolean();
- *result = QV4::Value::fromBoolean(!b);
+ return Encode(!b);
}
// binary operators
-inline void __qmljs_bit_or(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
+inline ReturnedValue __qmljs_bit_or(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(*left, *right)) {
- *result = QV4::Value::fromInt32(left->integerValue() | right->integerValue());
- return;
- }
+ if (QV4::Value::integerCompatible(*left, *right))
+ return QV4::Value::fromInt32(left->integerValue() | right->integerValue()).asReturnedValue();
- int lval = QV4::Value::toInt32(__qmljs_to_number(left));
- int rval = QV4::Value::toInt32(__qmljs_to_number(right));
- *result = QV4::Value::fromInt32(lval | rval);
+ int lval = left->toInt32();
+ int rval = right->toInt32();
+ return QV4::Value::fromInt32(lval | rval).asReturnedValue();
}
-inline void __qmljs_bit_xor(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
+inline ReturnedValue __qmljs_bit_xor(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(*left, *right)) {
- *result = QV4::Value::fromInt32(left->integerValue() ^ right->integerValue());
- return;
- }
+ if (QV4::Value::integerCompatible(*left, *right))
+ return QV4::Value::fromInt32(left->integerValue() ^ right->integerValue()).asReturnedValue();
- int lval = QV4::Value::toInt32(__qmljs_to_number(left));
- int rval = QV4::Value::toInt32(__qmljs_to_number(right));
- *result = QV4::Value::fromInt32(lval ^ rval);
+ int lval = left->toInt32();
+ int rval = right->toInt32();
+ return QV4::Value::fromInt32(lval ^ rval).asReturnedValue();
}
-inline void __qmljs_bit_and(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
+inline ReturnedValue __qmljs_bit_and(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(*left, *right)) {
- *result = QV4::Value::fromInt32(left->integerValue() & right->integerValue());
- return;
- }
+ if (QV4::Value::integerCompatible(*left, *right))
+ return QV4::Value::fromInt32(left->integerValue() & right->integerValue()).asReturnedValue();
- int lval = QV4::Value::toInt32(__qmljs_to_number(left));
- int rval = QV4::Value::toInt32(__qmljs_to_number(right));
- *result = QV4::Value::fromInt32(lval & rval);
+ int lval = left->toInt32();
+ int rval = right->toInt32();
+ return QV4::Value::fromInt32(lval & rval).asReturnedValue();
}
-inline void __qmljs_add(QV4::ExecutionContext *ctx, ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
+inline QV4::ReturnedValue __qmljs_add(QV4::ExecutionContext *ctx, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(*left, *right)) {
- *result = add_int32(left->integerValue(), right->integerValue());
- return;
- }
+ if (QV4::Value::integerCompatible(*left, *right))
+ return add_int32(left->integerValue(), right->integerValue()).asReturnedValue();
- if (QV4::Value::bothDouble(*left, *right)) {
- *result = QV4::Value::fromDouble(left->doubleValue() + right->doubleValue());
- return;
- }
+ if (QV4::Value::bothDouble(*left, *right))
+ return QV4::Value::fromDouble(left->doubleValue() + right->doubleValue()).asReturnedValue();
- __qmljs_add_helper(ctx, result, left, right);
+ return __qmljs_add_helper(ctx, left, right);
}
-inline void __qmljs_sub(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
+inline QV4::ReturnedValue __qmljs_sub(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(*left, *right)) {
- *result = sub_int32(left->integerValue(), right->integerValue());
- return;
- }
+ if (QV4::Value::integerCompatible(*left, *right))
+ return sub_int32(left->integerValue(), right->integerValue()).asReturnedValue();
double lval = __qmljs_to_number(left);
double rval = __qmljs_to_number(right);
- *result = QV4::Value::fromDouble(lval - rval);
+ return QV4::Value::fromDouble(lval - rval).asReturnedValue();
}
-inline void __qmljs_mul(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
+inline QV4::ReturnedValue __qmljs_mul(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(*left, *right)) {
- *result = mul_int32(left->integerValue(), right->integerValue());
- return;
- }
+ if (QV4::Value::integerCompatible(*left, *right))
+ return mul_int32(left->integerValue(), right->integerValue()).asReturnedValue();
double lval = __qmljs_to_number(left);
double rval = __qmljs_to_number(right);
- *result = QV4::Value::fromDouble(lval * rval);
+ return QV4::Value::fromDouble(lval * rval).asReturnedValue();
}
-inline void __qmljs_div(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
+inline QV4::ReturnedValue __qmljs_div(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
double lval = __qmljs_to_number(left);
double rval = __qmljs_to_number(right);
- *result = QV4::Value::fromDouble(lval / rval);
+ return QV4::Value::fromDouble(lval / rval).asReturnedValue();
}
-inline void __qmljs_mod(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
+inline QV4::ReturnedValue __qmljs_mod(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
if (QV4::Value::integerCompatible(*left, *right) && right->integerValue() != 0) {
int intRes = left->integerValue() % right->integerValue();
- if (intRes != 0 || left->integerValue() >= 0) {
- *result = QV4::Value::fromInt32(intRes);
- return;
- }
+ if (intRes != 0 || left->integerValue() >= 0)
+ return QV4::Value::fromInt32(intRes).asReturnedValue();
}
double lval = __qmljs_to_number(left);
double rval = __qmljs_to_number(right);
- *result = QV4::Value::fromDouble(std::fmod(lval, rval));
+ return QV4::Value::fromDouble(std::fmod(lval, rval)).asReturnedValue();
}
-inline void __qmljs_shl(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
+inline QV4::ReturnedValue __qmljs_shl(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(*left, *right)) {
- *result = QV4::Value::fromInt32(left->integerValue() << ((uint(right->integerValue()) & 0x1f)));
- return;
- }
+ if (QV4::Value::integerCompatible(*left, *right))
+ return QV4::Value::fromInt32(left->integerValue() << ((uint(right->integerValue()) & 0x1f))).asReturnedValue();
- int lval = QV4::Value::toInt32(__qmljs_to_number(left));
- unsigned rval = QV4::Value::toUInt32(__qmljs_to_number(right)) & 0x1f;
- *result = QV4::Value::fromInt32(lval << rval);
+ int lval = left->toInt32();
+ unsigned rval = right->toUInt32() & 0x1f;
+ return QV4::Value::fromInt32(lval << rval).asReturnedValue();
}
-inline void __qmljs_shr(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
+inline QV4::ReturnedValue __qmljs_shr(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(*left, *right)) {
- *result = QV4::Value::fromInt32(left->integerValue() >> ((uint(right->integerValue()) & 0x1f)));
- return;
- }
+ if (QV4::Value::integerCompatible(*left, *right))
+ return QV4::Value::fromInt32(left->integerValue() >> ((uint(right->integerValue()) & 0x1f))).asReturnedValue();
- int lval = QV4::Value::toInt32(__qmljs_to_number(left));
- unsigned rval = QV4::Value::toUInt32(__qmljs_to_number(right)) & 0x1f;
- *result = QV4::Value::fromInt32(lval >> rval);
+ int lval = left->toInt32();
+ unsigned rval = right->toUInt32() & 0x1f;
+ return QV4::Value::fromInt32(lval >> rval).asReturnedValue();
}
-inline void __qmljs_ushr(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
+inline QV4::ReturnedValue __qmljs_ushr(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
@@ -497,168 +469,88 @@ inline void __qmljs_ushr(QV4::ValueRef result, const QV4::ValueRef left, const Q
if (QV4::Value::integerCompatible(*left, *right)) {
res = uint(left->integerValue()) >> (uint(right->integerValue()) & 0x1f);
} else {
- unsigned lval = QV4::Value::toUInt32(__qmljs_to_number(left));
- unsigned rval = QV4::Value::toUInt32(__qmljs_to_number(right)) & 0x1f;
+ unsigned lval = left->toUInt32();
+ unsigned rval = right->toUInt32() & 0x1f;
res = lval >> rval;
}
if (res > INT_MAX)
- *result = QV4::Value::fromDouble(res);
+ return QV4::Value::fromDouble(res).asReturnedValue();
else
- *result = QV4::Value::fromInt32(res);
+ return QV4::Value::fromInt32(res).asReturnedValue();
}
-inline void __qmljs_gt(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
+inline QV4::ReturnedValue __qmljs_gt(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- *result = QV4::Value::fromBoolean(__qmljs_cmp_gt(left, right));
+ return QV4::Value::fromBoolean(__qmljs_cmp_gt(left, right)).asReturnedValue();
}
-inline void __qmljs_lt(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
+inline QV4::ReturnedValue __qmljs_lt(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- *result = QV4::Value::fromBoolean(__qmljs_cmp_lt(left, right));
+ return QV4::Value::fromBoolean(__qmljs_cmp_lt(left, right)).asReturnedValue();
}
-inline void __qmljs_ge(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
+inline QV4::ReturnedValue __qmljs_ge(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- *result = QV4::Value::fromBoolean(__qmljs_cmp_ge(left, right));
+ return QV4::Value::fromBoolean(__qmljs_cmp_ge(left, right)).asReturnedValue();
}
-inline void __qmljs_le(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
+inline QV4::ReturnedValue __qmljs_le(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- *result = QV4::Value::fromBoolean(__qmljs_cmp_le(left, right));
+ return QV4::Value::fromBoolean(__qmljs_cmp_le(left, right)).asReturnedValue();
}
-inline void __qmljs_eq(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
+inline QV4::ReturnedValue __qmljs_eq(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- *result = QV4::Value::fromBoolean(__qmljs_cmp_eq(left, right));
+ return QV4::Value::fromBoolean(__qmljs_cmp_eq(left, right)).asReturnedValue();
}
-inline void __qmljs_ne(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
+inline QV4::ReturnedValue __qmljs_ne(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- *result = QV4::Value::fromBoolean(!__qmljs_cmp_eq(left, right));
+ return QV4::Value::fromBoolean(!__qmljs_cmp_eq(left, right)).asReturnedValue();
}
-inline void __qmljs_se(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
+inline QV4::ReturnedValue __qmljs_se(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
bool r = __qmljs_strict_equal(left, right);
- *result = QV4::Value::fromBoolean(r);
+ return QV4::Value::fromBoolean(r).asReturnedValue();
}
-inline void __qmljs_sne(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
+inline QV4::ReturnedValue __qmljs_sne(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
bool r = ! __qmljs_strict_equal(left, right);
- *result = QV4::Value::fromBoolean(r);
-}
-
-inline QV4::Bool __qmljs_cmp_gt(const QV4::ValueRef left, const QV4::ValueRef right)
-{
- TRACE2(left, right);
- if (QV4::Value::integerCompatible(*left, *right))
- return left->integerValue() > right->integerValue();
-
- // Safe, as l & r are primitive values
- QV4::Value l = __qmljs_to_primitive(left, QV4::NUMBER_HINT);
- QV4::Value r = __qmljs_to_primitive(right, QV4::NUMBER_HINT);
-
- if (QV4::Value::bothDouble(l, r)) {
- return l.doubleValue() > r.doubleValue();
- } else if (l.isString() && r.isString()) {
- return r.stringValue()->compare(l.stringValue());
- } else {
- double dl = __qmljs_to_number(ValueRef(&l));
- double dr = __qmljs_to_number(ValueRef(&r));
- return dl > dr;
- }
-}
-
-inline QV4::Bool __qmljs_cmp_lt(const QV4::ValueRef left, const QV4::ValueRef right)
-{
- TRACE2(left, right);
- if (QV4::Value::integerCompatible(*left, *right))
- return left->integerValue() < right->integerValue();
-
- QV4::Value l = __qmljs_to_primitive(left, QV4::NUMBER_HINT);
- QV4::Value r = __qmljs_to_primitive(right, QV4::NUMBER_HINT);
-
- if (QV4::Value::bothDouble(l, r)) {
- return l.doubleValue() < r.doubleValue();
- } else if (l.isString() && r.isString()) {
- return l.stringValue()->compare(r.stringValue());
- } else {
- double dl = __qmljs_to_number(ValueRef(&l));
- double dr = __qmljs_to_number(ValueRef(&r));
- return dl < dr;
- }
-}
-
-inline QV4::Bool __qmljs_cmp_ge(const QV4::ValueRef left, const QV4::ValueRef right)
-{
- TRACE2(left, right);
- if (QV4::Value::integerCompatible(*left, *right))
- return left->integerValue() >= right->integerValue();
-
- QV4::Value l = __qmljs_to_primitive(left, QV4::NUMBER_HINT);
- QV4::Value r = __qmljs_to_primitive(right, QV4::NUMBER_HINT);
-
- if (QV4::Value::bothDouble(l, r)) {
- return l.doubleValue() >= r.doubleValue();
- } else if (l.isString() && r.isString()) {
- return !l.stringValue()->compare(r.stringValue());
- } else {
- double dl = __qmljs_to_number(ValueRef(&l));
- double dr = __qmljs_to_number(ValueRef(&r));
- return dl >= dr;
- }
-}
-
-inline QV4::Bool __qmljs_cmp_le(const QV4::ValueRef left, const QV4::ValueRef right)
-{
- TRACE2(left, right);
- if (QV4::Value::integerCompatible(*left, *right))
- return left->integerValue() <= right->integerValue();
-
- QV4::Value l = __qmljs_to_primitive(left, QV4::NUMBER_HINT);
- QV4::Value r = __qmljs_to_primitive(right, QV4::NUMBER_HINT);
-
- if (QV4::Value::bothDouble(l, r)) {
- return l.doubleValue() <= r.doubleValue();
- } else if (l.isString() && r.isString()) {
- return !r.stringValue()->compare(l.stringValue());
- } else {
- double dl = __qmljs_to_number(ValueRef(&l));
- double dr = __qmljs_to_number(ValueRef(&r));
- return dl <= dr;
- }
+ return QV4::Value::fromBoolean(r).asReturnedValue();
}
inline QV4::Bool __qmljs_cmp_eq(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (left->val == right->val)
+ if (left->rawValue() == right->rawValue())
// NaN != NaN
- return (left->tag & QV4::Value::NotDouble_Mask) != QV4::Value::NaN_Mask;
+ return !left->isNaN();
if (left->type() == right->type()) {
- if (left->isManaged())
+ if (!left->isManaged())
+ return false;
+ if (left->isString() == right->isString())
return left->managed()->isEqualTo(right->managed());
- return false;
}
return __qmljs_equal_helper(left, right);
@@ -689,18 +581,18 @@ inline QV4::Bool __qmljs_cmp_instanceof(QV4::ExecutionContext *ctx, const QV4::V
{
TRACE2(left, right);
- QV4::Value v;
- __qmljs_instanceof(ctx, &v, left, right);
- return v.booleanValue();
+ Scope scope(ctx);
+ QV4::ScopedValue v(scope, __qmljs_instanceof(ctx, left, right));
+ return v->booleanValue();
}
inline uint __qmljs_cmp_in(QV4::ExecutionContext *ctx, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- QV4::Value v;
- __qmljs_in(ctx, &v, left, right);
- return v.booleanValue();
+ Scope scope(ctx);
+ QV4::ScopedValue v(scope, __qmljs_in(ctx, left, right));
+ return v->booleanValue();
}
} // namespace QV4
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index a0e0d784a7..a800283cee 100644
--- a/src/qml/jsruntime/qv4scopedvalue_p.h
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -79,61 +79,73 @@ struct ScopedValueArray {
struct ScopedValue;
-struct ValueScope {
- ValueScope(ExecutionContext *ctx)
+struct Scope {
+ Scope(ExecutionContext *ctx)
: engine(ctx->engine)
+#ifndef QT_NO_DEBUG
+ , size(0)
+#endif
{
mark = ctx->engine->jsStackTop;
}
- ValueScope(ExecutionEngine *e)
+ Scope(ExecutionEngine *e)
: engine(e)
{
mark = e->jsStackTop;
}
- ~ValueScope() {
+ ~Scope() {
Q_ASSERT(engine->jsStackTop >= mark);
engine->jsStackTop = mark;
}
ExecutionEngine *engine;
Value *mark;
+#ifndef QT_NO_DEBUG
+ mutable int size;
+#endif
};
struct ScopedValue;
struct ValueRef;
-struct ReturnedValue
-{
- ReturnedValue(const Value &v)
- : v(v) {}
- // no destructor
-
-
-private:
- friend struct ValueRef;
- friend struct ScopedValue;
- QV4::Value v;
-};
-
struct ScopedValue
{
- ScopedValue(const ValueScope &scope)
+ ScopedValue(const Scope &scope)
{
ptr = scope.engine->jsStackTop++;
+#ifndef QT_NO_DEBUG
+ ++scope.size;
+#endif
}
- ScopedValue(const ValueScope &scope, const Value &v)
+ ScopedValue(const Scope &scope, const Value &v)
{
ptr = scope.engine->jsStackTop++;
*ptr = v;
+#ifndef QT_NO_DEBUG
+ ++scope.size;
+#endif
+ }
+
+ ScopedValue(const Scope &scope, const ReturnedValue &v)
+ {
+ ptr = scope.engine->jsStackTop++;
+ ptr->val = v;
+#ifndef QT_NO_DEBUG
+ ++scope.size;
+#endif
}
- ScopedValue(const ValueScope &scope, const ReturnedValue &v)
+ template<typename T>
+ ScopedValue(const Scope &scope, Returned<T> *t)
{
ptr = scope.engine->jsStackTop++;
- *ptr = v.v;
+ *ptr = t->getPointer() ? Value::fromManaged(t->getPointer()) : Value::undefinedValue();
+#ifndef QT_NO_DEBUG
+ ++scope.size;
+#endif
}
ScopedValue &operator=(const Value &v) {
@@ -142,7 +154,13 @@ struct ScopedValue
}
ScopedValue &operator=(const ReturnedValue &v) {
- *ptr = v.v;
+ ptr->val = v;
+ return *this;
+ }
+
+ template<typename T>
+ ScopedValue &operator=(Returned<T> *t) {
+ *ptr = t->getPointer() ? Value::fromManaged(t->getPointer()) : Value::undefinedValue();
return *this;
}
@@ -155,32 +173,149 @@ struct ScopedValue
return ptr;
}
+ const Value *operator->() const {
+ return ptr;
+ }
+
operator const Value &() const {
return *ptr;
}
+ ReturnedValue asReturnedValue() const { return ptr->val; }
+
Value *ptr;
};
-struct ScopedCallData {
- ScopedCallData(ExecutionEngine *e, int argc)
- : engine(e)
- // ### this check currently won't work because of exceptions
+template<typename T>
+struct Scoped
+{
+ inline void setPointer(Managed *p) {
+#if QT_POINTER_SIZE == 8
+ ptr->val = (quint64)p;
+#else
+ *ptr = p ? QV4::Value::fromManaged(p) : QV4::Value::undefinedValue();
+#endif
+ }
+
+ Scoped(const Scope &scope)
+ {
+ ptr = scope.engine->jsStackTop++;
#ifndef QT_NO_DEBUG
- , size(qMax(argc, (int)QV4::Global::ReservedArgumentCount) + offsetof(QV4::CallData, args)/sizeof(QV4::Value))
+ ++scope.size;
#endif
+ }
+
+ // ### GC FIX casting below to be safe
+ Scoped(const Scope &scope, const Value &v)
{
- ptr = reinterpret_cast<CallData *>(e->stackPush(qMax(argc, (int)QV4::Global::ReservedArgumentCount) + offsetof(QV4::CallData, args)/sizeof(QV4::Value)));
- ptr->tag = 0;
- ptr->argc = argc;
+ ptr = scope.engine->jsStackTop++;
+ setPointer(T::cast(v));
+#ifndef QT_NO_DEBUG
+ ++scope.size;
+#endif
}
- ~ScopedCallData() {
+ Scoped(const Scope &scope, const ValueRef &v);
+
+ Scoped(const Scope &scope, T *t)
+ {
+ ptr = scope.engine->jsStackTop++;
+ setPointer(t);
#ifndef QT_NO_DEBUG
- engine->stackPop(size);
- Q_ASSERT((void *)engine->jsStackTop == (void *)ptr);
+ ++scope.size;
+#endif
+ }
+ template<typename X>
+ Scoped(const Scope &scope, Returned<X> *x)
+ {
+ ptr = scope.engine->jsStackTop++;
+ setPointer(Returned<T>::getPointer(x));
+#ifndef QT_NO_DEBUG
+ ++scope.size;
+#endif
+ }
+
+ Scoped(const Scope &scope, const ReturnedValue &v)
+ {
+ ptr = scope.engine->jsStackTop++;
+ setPointer(T::cast(QV4::Value::fromReturnedValue(v)));
+#ifndef QT_NO_DEBUG
+ ++scope.size;
+#endif
+ }
+
+ Scoped<T> &operator=(const Value &v) {
+ setPointer(T::cast(v));
+ return *this;
+ }
+
+ Scoped<T> &operator=(const ValueRef &v);
+
+ Scoped<T> &operator=(const ReturnedValue &v) {
+ setPointer(T::cast(QV4::Value::fromReturnedValue(v)));
+ return *this;
+ }
+
+ Scoped<T> &operator=(const Scoped<T> &other) {
+ *ptr = *other.ptr;
+ return *this;
+ }
+
+ Scoped<T> &operator=(T *t) {
+ setPointer(t);
+ return *this;
+ }
+
+ template<typename X>
+ Scoped<T> &operator=(Returned<X> *x) {
+ setPointer(Returned<T>::getPointer(x));
+ return *this;
+ }
+
+
+ T *operator->() {
+ return static_cast<T *>(ptr->managed());
+ }
+
+ bool operator!() const {
+ return !ptr->managed();
+ }
+ operator bool() const {
+ return ptr->managed();
+ }
+
+ T *getPointer() {
+ return static_cast<T *>(ptr->managed());
+ }
+
+ Value asValue() const {
+#if QT_POINTER_SIZE == 8
+ return ptr->val ? *ptr : QV4::Value::undefinedValue();
+#else
+ return *ptr;
+#endif
+ }
+
+ ReturnedValue asReturnedValue() const {
+#if QT_POINTER_SIZE == 8
+ return ptr->val ? ptr->val : Value::undefinedValue().asReturnedValue();
#else
- engine->jsStackTop = reinterpret_cast<Value *>(ptr);
+ return ptr->val;
+#endif
+ }
+
+ Value *ptr;
+};
+
+struct ScopedCallData {
+ ScopedCallData(Scope &scope, int argc)
+ {
+ int size = qMax(argc, (int)QV4::Global::ReservedArgumentCount) + offsetof(QV4::CallData, args)/sizeof(QV4::Value);
+ ptr = reinterpret_cast<CallData *>(scope.engine->stackPush(size));
+ ptr->tag = QV4::Value::Integer_Type;
+ ptr->argc = argc;
+#ifndef QT_NO_DEBUG
+ scope.size += size;
#endif
}
@@ -192,17 +327,15 @@ struct ScopedCallData {
return ptr;
}
-
- ExecutionEngine *engine;
-#ifndef QT_NO_DEBUG
- int size;
-#endif
CallData *ptr;
};
struct ValueRef {
ValueRef(const ScopedValue &v)
: ptr(v.ptr) {}
+ template <typename T>
+ ValueRef(const Scoped<T> &v)
+ : ptr(v.ptr) {}
ValueRef(const PersistentValue &v)
: ptr(&v.d->value) {}
ValueRef(PersistentValuePrivate *p)
@@ -218,7 +351,7 @@ struct ValueRef {
ValueRef &operator=(const Value &v)
{ *ptr = v; return *this; }
ValueRef &operator=(const ReturnedValue &v) {
- *ptr = v.v;
+ ptr->val = v;
return *this;
}
@@ -242,12 +375,32 @@ struct ValueRef {
static const ValueRef fromRawValue(const Value *v) {
return ValueRef(const_cast<Value *>(v));
}
+
+ ReturnedValue asReturnedValue() const { return ptr->val; }
+
// ### get rid of this one!
ValueRef(Value *v) { ptr = v; }
private:
Value *ptr;
};
+template<typename T>
+inline Scoped<T>::Scoped(const Scope &scope, const ValueRef &v)
+{
+ ptr = scope.engine->jsStackTop++;
+ setPointer(T::cast(*v.operator ->()));
+#ifndef QT_NO_DEBUG
+ ++scope.size;
+#endif
+}
+
+template<typename T>
+inline Scoped<T> &Scoped<T>::operator=(const ValueRef &v)
+{
+ setPointer(T::cast(*v.operator ->()));
+ return *this;
+}
+
struct CallDataRef {
CallDataRef(const ScopedCallData &c)
@@ -280,6 +433,47 @@ private:
CallData *ptr;
};
+struct Encode : private Value {
+ static ReturnedValue undefined() {
+ return quint64(Undefined_Type) << Tag_Shift;
+ }
+ static ReturnedValue null() {
+ return quint64(_Null_Type) << Tag_Shift;
+ }
+
+ Encode(bool b) {
+ tag = _Boolean_Type;
+ int_32 = b;
+ }
+ Encode(double d) {
+ setDouble(d);
+ }
+ Encode(int i) {
+ tag = _Integer_Type;
+ int_32 = i;
+ }
+ Encode(uint i) {
+ if (i <= INT_MAX) {
+ tag = _Integer_Type;
+ int_32 = i;
+ } else {
+ setDouble(i);
+ }
+ }
+ Encode(ReturnedValue v) {
+ val = v;
+ }
+
+ template<typename T>
+ Encode(Returned<T> *t) {
+ val = t->getPointer()->asReturnedValue();
+ }
+
+ operator ReturnedValue() const {
+ return val;
+ }
+};
+
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 16bab966e9..ad83a52d8f 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -75,19 +75,19 @@ QmlBindingWrapper::QmlBindingWrapper(ExecutionContext *scope, Function *f, Objec
scope->engine->popContext();
}
-Value QmlBindingWrapper::call(Managed *that, CallData *)
+ReturnedValue QmlBindingWrapper::call(Managed *that, CallData *)
{
ExecutionEngine *engine = that->engine();
+ Scope scope(engine);
QmlBindingWrapper *This = static_cast<QmlBindingWrapper *>(that);
CallContext *ctx = This->qmlContext;
std::fill(ctx->locals, ctx->locals + ctx->function->varCount, Value::undefinedValue());
engine->pushContext(ctx);
- Value result = This->function->code(ctx, This->function->codeData);
+ ScopedValue result(scope, This->function->code(ctx, This->function->codeData));
engine->popContext();
- return result;
-
+ return result.asReturnedValue();
}
void QmlBindingWrapper::markObjects(Managed *m)
@@ -141,6 +141,7 @@ void Script::parse()
parsed = true;
ExecutionEngine *v4 = scope->engine;
+ Scope valueScope(v4);
MemoryManager::GCBlocker gcBlocker(v4->memoryManager);
@@ -188,19 +189,22 @@ void Script::parse()
compilationUnitHolder = Value::fromObject(new (v4->memoryManager) CompilationUnitHolder(v4, compilationUnit));
}
- if (!vmFunction)
+ if (!vmFunction) {
// ### FIX file/line number
- v4->current->throwError(QV4::Value::fromObject(v4->newSyntaxErrorObject("Syntax error")));
+ Scoped<Object> error(valueScope, v4->newSyntaxErrorObject("Syntax error"));
+ v4->current->throwError(error);
+ }
}
-Value Script::run()
+ReturnedValue Script::run()
{
if (!parsed)
parse();
if (!vmFunction)
- return Value::undefinedValue();
+ return Encode::undefined();
QV4::ExecutionEngine *engine = scope->engine;
+ QV4::Scope valueScope(engine);
if (qml.isEmpty()) {
TemporaryAssignment<Function*> savedGlobalCode(engine->globalCode, vmFunction);
@@ -217,7 +221,7 @@ Value Script::run()
scope->compiledFunction = vmFunction->compiledFunction;
scope->runtimeStrings = vmFunction->compilationUnit->runtimeStrings;
- QV4::Value result;
+ QV4::ScopedValue result(valueScope);
try {
result = vmFunction->code(scope, vmFunction->codeData);
} catch (Exception &e) {
@@ -234,11 +238,11 @@ Value Script::run()
scope->compiledFunction = oldCompiledFunction;
scope->runtimeStrings = oldRuntimeStrings;
- return result;
+ return result.asReturnedValue();
} else {
FunctionObject *f = new (engine->memoryManager) QmlBindingWrapper(scope, vmFunction, qml.value().asObject());
- ScopedCallData callData(scope->engine, 0);
+ ScopedCallData callData(valueScope, 0);
callData->thisObject = Value::undefinedValue();
return f->call(callData);
}
@@ -251,25 +255,25 @@ Function *Script::function()
return vmFunction;
}
-Value Script::qmlBinding()
+ReturnedValue Script::qmlBinding()
{
if (!parsed)
parse();
QV4::ExecutionEngine *v4 = scope->engine;
- return Value::fromObject(new (v4->memoryManager) QmlBindingWrapper(scope, vmFunction, qml.value().asObject()));
+ return Value::fromObject(new (v4->memoryManager) QmlBindingWrapper(scope, vmFunction, qml.value().asObject())).asReturnedValue();
}
-QV4::Value Script::evaluate(ExecutionEngine *engine, const QString &script, Object *scopeObject)
+QV4::ReturnedValue Script::evaluate(ExecutionEngine *engine, const QString &script, Object *scopeObject)
{
+ QV4::Scope scope(engine);
QV4::Script qmlScript(engine, scopeObject, script, QString());
QV4::ExecutionContext *ctx = engine->current;
- QV4::Value result = QV4::Value::undefinedValue();
try {
qmlScript.parse();
- result = qmlScript.run();
+ return qmlScript.run();
} catch (QV4::Exception &e) {
e.accept(ctx);
}
- return result;
+ return Encode::undefined();
}
diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h
index b00e076a2b..5a880fee88 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -56,7 +56,7 @@ struct QmlBindingWrapper : FunctionObject {
QmlBindingWrapper(ExecutionContext *scope, Function *f, Object *qml);
- static Value call(Managed *that, CallData *);
+ static ReturnedValue call(Managed *that, CallData *);
static void markObjects(Managed *m);
private:
@@ -88,13 +88,13 @@ struct Q_QML_EXPORT Script {
bool parseAsBinding;
void parse();
- Value run();
- Value qmlBinding();
+ ReturnedValue run();
+ ReturnedValue qmlBinding();
Function *function();
- static Value evaluate(ExecutionEngine *engine, const QString &script, Object *scopeObject);
+ static ReturnedValue evaluate(ExecutionEngine *engine, const QString &script, Object *scopeObject);
};
}
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index 29ca34910c..72356204b5 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -48,6 +48,8 @@
#include <private/qqmlengine_p.h>
#include <private/qv4scopedvalue_p.h>
+#include <algorithm>
+
QT_BEGIN_NAMESPACE
using namespace QV4;
@@ -136,7 +138,7 @@ template <typename ElementType> ElementType convertValueToElement(const QV4::Val
template <> QString convertValueToElement(const QV4::Value &value)
{
- return value.toQString();
+ return value.toQStringNoThrow();
}
template <> int convertValueToElement(const QV4::Value &value)
@@ -146,7 +148,7 @@ template <> int convertValueToElement(const QV4::Value &value)
template <> QUrl convertValueToElement(const QV4::Value &value)
{
- return QUrl(value.toQString());
+ return QUrl(value.toQStringNoThrow());
}
template <> qreal convertValueToElement(const QV4::Value &value)
@@ -352,12 +354,13 @@ public:
bool operator()(typename Container::value_type lhs, typename Container::value_type rhs)
{
QV4::Managed *fun = this->m_compareFn.asManaged();
- ScopedCallData callData(fun->engine(), 2);
+ Scope scope(fun->engine());
+ ScopedCallData callData(scope, 2);
callData->args[0] = convertElementToValue(this->m_ctx->engine, lhs);
callData->args[1] = convertElementToValue(this->m_ctx->engine, rhs);
callData->thisObject = QV4::Value::fromObject(this->m_ctx->engine->globalObject);
- QV4::Value result = fun->call(callData);
- return result.toNumber() < 0;
+ QV4::ScopedValue result(scope, fun->call(callData));
+ return result->toNumber() < 0;
}
private:
@@ -376,17 +379,17 @@ public:
if (ctx->argumentCount == 1 && ctx->arguments[0].asFunctionObject()) {
QV4::Value compareFn = ctx->arguments[0];
CompareFunctor cf(ctx, compareFn);
- qSort(m_container.begin(), m_container.end(), cf);
+ std::sort(m_container.begin(), m_container.end(), cf);
} else {
DefaultCompareFunctor cf;
- qSort(m_container.begin(), m_container.end(), cf);
+ std::sort(m_container.begin(), m_container.end(), cf);
}
if (m_isReference)
storeReference();
}
- static QV4::Value method_get_length(QV4::SimpleCallContext *ctx)
+ static QV4::ReturnedValue method_get_length(QV4::SimpleCallContext *ctx)
{
QQmlSequence<Container> *This = ctx->thisObject.as<QQmlSequence<Container> >();
if (!This)
@@ -394,13 +397,13 @@ public:
if (This->m_isReference) {
if (!This->m_object)
- return QV4::Value::fromInt32(0);
+ return QV4::Encode(0);
This->loadReference();
}
- return QV4::Value::fromInt32(This->m_container.count());
+ return QV4::Encode(This->m_container.count());
}
- static QV4::Value method_set_length(QV4::SimpleCallContext* ctx)
+ static QV4::ReturnedValue method_set_length(QV4::SimpleCallContext* ctx)
{
QQmlSequence<Container> *This = ctx->thisObject.as<QQmlSequence<Container> >();
if (!This)
@@ -410,19 +413,19 @@ public:
/* Qt containers have int (rather than uint) allowable indexes. */
if (newLength > INT_MAX) {
generateWarning(ctx, QLatin1String("Index out of range during length set"));
- return QV4::Value::undefinedValue();
+ return QV4::Encode::undefined();
}
/* Read the sequence from the QObject property if we're a reference */
if (This->m_isReference) {
if (!This->m_object)
- return QV4::Value::undefinedValue();
+ return QV4::Encode::undefined();
This->loadReference();
}
/* Determine whether we need to modify the sequence */
qint32 newCount = static_cast<qint32>(newLength);
qint32 count = This->m_container.count();
if (newCount == count) {
- return QV4::Value::undefinedValue();
+ return QV4::Encode::undefined();
} else if (newCount > count) {
/* according to ECMA262r3 we need to insert */
/* undefined values increasing length to newLength. */
@@ -444,7 +447,7 @@ public:
/* write back. already checked that object is non-null, so skip that check here. */
This->storeReference();
}
- return QV4::Value::undefinedValue();
+ return QV4::Encode::undefined();
}
QVariant toVariant() const
@@ -455,7 +458,7 @@ public:
Container result;
quint32 length = array->arrayLength();
for (quint32 i = 0; i < length; ++i)
- result << convertValueToElement<typename Container::value_type>(array->getIndexed(i));
+ result << convertValueToElement<typename Container::value_type>(QV4::Value::fromReturnedValue(array->getIndexed(i)));
return QVariant::fromValue(result);
}
@@ -483,8 +486,8 @@ private:
int m_propertyIndex;
bool m_isReference;
- static QV4::Value getIndexed(QV4::Managed *that, uint index, bool *hasProperty)
- { return static_cast<QQmlSequence<Container> *>(that)->containerGetIndexed(index, hasProperty); }
+ static QV4::ReturnedValue getIndexed(QV4::Managed *that, uint index, bool *hasProperty)
+ { return static_cast<QQmlSequence<Container> *>(that)->containerGetIndexed(index, hasProperty).asReturnedValue(); }
static void putIndexed(Managed *that, uint index, const QV4::Value &value)
{ static_cast<QQmlSequence<Container> *>(that)->containerPutIndexed(index, value); }
static QV4::PropertyAttributes queryIndexed(const QV4::Managed *that, uint index)
@@ -535,14 +538,14 @@ void SequencePrototype::init(QV4::ExecutionEngine *engine)
defineDefaultProperty(engine, QStringLiteral("valueOf"), method_valueOf, 0);
}
-QV4::Value SequencePrototype::method_sort(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue SequencePrototype::method_sort(QV4::SimpleCallContext *ctx)
{
QV4::Object *o = ctx->thisObject.asObject();
if (!o || !o->isListType())
ctx->throwTypeError();
if (ctx->argumentCount >= 2)
- return ctx->thisObject;
+ return ctx->thisObject.asReturnedValue();
#define CALL_SORT(SequenceElementType, SequenceElementTypeName, SequenceType, DefaultValue) \
if (QQml##SequenceElementTypeName##List *s = o->as<QQml##SequenceElementTypeName##List>()) { \
@@ -552,7 +555,7 @@ QV4::Value SequencePrototype::method_sort(QV4::SimpleCallContext *ctx)
FOREACH_QML_SEQUENCE_TYPE(CALL_SORT)
#undef CALL_SORT
- return ctx->thisObject;
+ return ctx->thisObject.asReturnedValue();
}
#define IS_SEQUENCE(unused1, unused2, SequenceType, unused3) \
@@ -568,36 +571,38 @@ bool SequencePrototype::isSequenceType(int sequenceTypeId)
#define NEW_REFERENCE_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \
if (sequenceType == qMetaTypeId<SequenceType>()) { \
- QV4::Object *obj = new (engine->memoryManager) QQml##ElementTypeName##List(engine, object, propertyIndex); \
- return QV4::Value::fromObject(obj); \
+ QV4::Scoped<QV4::Object> obj(scope, QV4::Value::fromObject(new (engine->memoryManager) QQml##ElementTypeName##List(engine, object, propertyIndex))); \
+ return obj.asReturnedValue(); \
} else
-QV4::Value SequencePrototype::newSequence(QV4::ExecutionEngine *engine, int sequenceType, QObject *object, int propertyIndex, bool *succeeded)
+ReturnedValue SequencePrototype::newSequence(QV4::ExecutionEngine *engine, int sequenceType, QObject *object, int propertyIndex, bool *succeeded)
{
+ QV4::Scope scope(engine);
// This function is called when the property is a QObject Q_PROPERTY of
// the given sequence type. Internally we store a typed-sequence
// (as well as object ptr + property index for updated-read and write-back)
// and so access/mutate avoids variant conversion.
*succeeded = true;
- FOREACH_QML_SEQUENCE_TYPE(NEW_REFERENCE_SEQUENCE) { /* else */ *succeeded = false; return QV4::Value::undefinedValue(); }
+ FOREACH_QML_SEQUENCE_TYPE(NEW_REFERENCE_SEQUENCE) { /* else */ *succeeded = false; return QV4::Encode::undefined(); }
}
#undef NEW_REFERENCE_SEQUENCE
#define NEW_COPY_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \
if (sequenceType == qMetaTypeId<SequenceType>()) { \
- QV4::Object *obj = new (engine->memoryManager) QQml##ElementTypeName##List(engine, v.value<SequenceType >()); \
- return QV4::Value::fromObject(obj); \
+ QV4::Scoped<QV4::Object> obj(scope, QV4::Value::fromObject(new (engine->memoryManager) QQml##ElementTypeName##List(engine, v.value<SequenceType >()))); \
+ return obj.asReturnedValue(); \
} else
-QV4::Value SequencePrototype::fromVariant(QV4::ExecutionEngine *engine, const QVariant& v, bool *succeeded)
+ReturnedValue SequencePrototype::fromVariant(QV4::ExecutionEngine *engine, const QVariant& v, bool *succeeded)
{
+ QV4::Scope scope(engine);
// This function is called when assigning a sequence value to a normal JS var
// in a JS block. Internally, we store a sequence of the specified type.
// Access and mutation is extremely fast since it will not need to modify any
// QObject property.
int sequenceType = v.userType();
*succeeded = true;
- FOREACH_QML_SEQUENCE_TYPE(NEW_COPY_SEQUENCE) { /* else */ *succeeded = false; return QV4::Value::undefinedValue(); }
+ FOREACH_QML_SEQUENCE_TYPE(NEW_COPY_SEQUENCE) { /* else */ *succeeded = false; return QV4::Encode::undefined(); }
}
#undef NEW_COPY_SEQUENCE
diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h
index ceae4e6f97..f2d06d8918 100644
--- a/src/qml/jsruntime/qv4sequenceobject_p.h
+++ b/src/qml/jsruntime/qv4sequenceobject_p.h
@@ -69,16 +69,16 @@ struct SequencePrototype : public QV4::Object
void init(QV4::ExecutionEngine *engine);
- static QV4::Value method_valueOf(QV4::SimpleCallContext *ctx)
+ static ReturnedValue method_valueOf(QV4::SimpleCallContext *ctx)
{
- return QV4::Value::fromString(ctx->thisObject.toString(ctx));
+ return QV4::Value::fromString(ctx->thisObject.toString(ctx)).asReturnedValue();
}
- static QV4::Value method_sort(QV4::SimpleCallContext *ctx);
+ static ReturnedValue method_sort(QV4::SimpleCallContext *ctx);
static bool isSequenceType(int sequenceTypeId);
- static QV4::Value newSequence(QV4::ExecutionEngine *engine, int sequenceTypeId, QObject *object, int propertyIndex, bool *succeeded);
- static QV4::Value fromVariant(QV4::ExecutionEngine *engine, const QVariant& v, bool *succeeded);
+ static ReturnedValue newSequence(QV4::ExecutionEngine *engine, int sequenceTypeId, QObject *object, int propertyIndex, bool *succeeded);
+ static ReturnedValue fromVariant(QV4::ExecutionEngine *engine, const QVariant& v, bool *succeeded);
static int metaTypeForSequence(QV4::Object *object);
static QVariant toVariant(QV4::Object *object);
static QVariant toVariant(const QV4::Value &array, int typeHint, bool *succeeded);
diff --git a/src/qml/jsruntime/qv4serialize.cpp b/src/qml/jsruntime/qv4serialize.cpp
index f7389dc6d7..41481ac1b8 100644
--- a/src/qml/jsruntime/qv4serialize.cpp
+++ b/src/qml/jsruntime/qv4serialize.cpp
@@ -150,6 +150,8 @@ static inline void *popPtr(const char *&data)
void Serialize::serialize(QByteArray &data, const QV4::Value &v, QV8Engine *engine)
{
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
+ QV4::Scope scope(v4);
+
if (v.isEmpty()) {
} else if (v.isUndefined()) {
push(data, valueheader(WorkerUndefined));
@@ -187,7 +189,7 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, QV8Engine *engi
reserve(data, sizeof(quint32) + length * sizeof(quint32));
push(data, valueheader(WorkerArray, length));
for (uint32_t ii = 0; ii < length; ++ii)
- serialize(data, array->getIndexed(ii), engine);
+ serialize(data, QV4::Value::fromReturnedValue(array->getIndexed(ii)), engine);
} else if (v.isInteger()) {
reserve(data, 2 * sizeof(quint32));
push(data, valueheader(WorkerInt32));
@@ -240,7 +242,7 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, QV8Engine *engi
if (o->isListType()) {
// valid sequence. we generate a length (sequence length + 1 for the sequence type)
- uint32_t seqLength = o->get(v4->id_length).toUInt32();
+ uint32_t seqLength = ScopedValue(scope, o->get(v4->id_length))->toUInt32();
uint32_t length = seqLength + 1;
if (length > 0xFFFFFF) {
push(data, valueheader(WorkerUndefined));
@@ -250,7 +252,7 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, QV8Engine *engi
push(data, valueheader(WorkerSequence, length));
serialize(data, QV4::Value::fromInt32(QV4::SequencePrototype::metaTypeForSequence(o)), engine); // sequence type
for (uint32_t ii = 0; ii < seqLength; ++ii)
- serialize(data, o->getIndexed(ii), engine); // sequence elements
+ serialize(data, QV4::Value::fromReturnedValue(o->getIndexed(ii)), engine); // sequence elements
return;
}
@@ -264,16 +266,15 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, QV8Engine *engi
}
push(data, valueheader(WorkerObject, length));
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
+ QV4::ScopedValue val(scope);
+ QV4::ScopedValue s(scope);
for (quint32 ii = 0; ii < length; ++ii) {
- QV4::String *s = properties->getIndexed(ii).asString();
- serialize(data, QV4::Value::fromString(s), engine);
+ s = properties->getIndexed(ii);
+ serialize(data, s, engine);
- bool hasCaught = false;
QV4::ExecutionContext *ctx = v4->current;
- QV4::Value val = QV4::Value::undefinedValue();
try {
- val = o->get(s);
+ val = o->get(s->asString());
} catch (QV4::Exception &e) {
e.accept(ctx);
}
@@ -286,28 +287,29 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, QV8Engine *engi
}
}
-QV4::Value Serialize::deserialize(const char *&data, QV8Engine *engine)
+ReturnedValue Serialize::deserialize(const char *&data, QV8Engine *engine)
{
quint32 header = popUint32(data);
Type type = headertype(header);
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
+ Scope scope(v4);
switch (type) {
case WorkerUndefined:
- return QV4::Value::undefinedValue();
+ return QV4::Encode::undefined();
case WorkerNull:
- return QV4::Value::nullValue();
+ return QV4::Encode::null();
case WorkerTrue:
- return QV4::Value::fromBoolean(true);
+ return QV4::Encode(true);
case WorkerFalse:
- return QV4::Value::fromBoolean(false);
+ return QV4::Encode(false);
case WorkerString:
{
quint32 size = headersize(header);
QString qstr((QChar *)data, size);
data += ALIGN(size * sizeof(uint16_t));
- return QV4::Value::fromString(v4->newString(qstr));
+ return QV4::Value::fromString(v4->newString(qstr)).asReturnedValue();
}
case WorkerFunction:
Q_ASSERT(!"Unreachable");
@@ -315,71 +317,80 @@ QV4::Value Serialize::deserialize(const char *&data, QV8Engine *engine)
case WorkerArray:
{
quint32 size = headersize(header);
- QV4::ArrayObject *a = v4->newArrayObject();
+ Scoped<ArrayObject> a(scope, v4->newArrayObject());
+ ScopedValue v(scope);
for (quint32 ii = 0; ii < size; ++ii) {
- a->putIndexed(ii, deserialize(data, engine));
+ v = deserialize(data, engine);
+ a->putIndexed(ii, v);
}
- return QV4::Value::fromObject(a);
+ return a.asReturnedValue();
}
case WorkerObject:
{
quint32 size = headersize(header);
QV4::Object *o = v4->newObject();
+ ScopedValue name(scope);
+ ScopedValue value(scope);
for (quint32 ii = 0; ii < size; ++ii) {
- QV4::Value name = deserialize(data, engine);
- QV4::Value value = deserialize(data, engine);
- o->put(name.asString(), value);
+ name = deserialize(data, engine);
+ value = deserialize(data, engine);
+ o->put(name->asString(), value);
}
- return QV4::Value::fromObject(o);
+ return QV4::Value::fromObject(o).asReturnedValue();
}
case WorkerInt32:
- return QV4::Value::fromInt32((qint32)popUint32(data));
+ return QV4::Encode((qint32)popUint32(data));
case WorkerUint32:
- return QV4::Value::fromUInt32(popUint32(data));
+ return QV4::Encode(popUint32(data));
case WorkerNumber:
- return QV4::Value::fromDouble(popDouble(data));
+ return QV4::Encode(popDouble(data));
case WorkerDate:
- return QV4::Value::fromObject(v4->newDateObject(QV4::Value::fromDouble(popDouble(data))));
+ return QV4::Encode(v4->newDateObject(QV4::Value::fromDouble(popDouble(data))));
case WorkerRegexp:
{
quint32 flags = headersize(header);
quint32 length = popUint32(data);
QString pattern = QString((QChar *)data, length - 1);
data += ALIGN(length * sizeof(uint16_t));
- return QV4::Value::fromObject(v4->newRegExpObject(pattern, flags));
+ return Encode(v4->newRegExpObject(pattern, flags));
}
case WorkerListModel:
{
void *ptr = popPtr(data);
QQmlListModelWorkerAgent *agent = (QQmlListModelWorkerAgent *)ptr;
- QV4::Value rv = QV4::QObjectWrapper::wrap(v4, agent);
+ QV4::ScopedValue rv(scope, QV4::QObjectWrapper::wrap(v4, agent));
// ### Find a better solution then the ugly property
QQmlListModelWorkerAgent::VariantRef ref(agent);
QVariant var = qVariantFromValue(ref);
- rv.asObject()->defineReadonlyProperty(v4->newString("__qml:hidden:ref"), engine->fromVariant(var));
+ QV4::ScopedValue v(scope, engine->fromVariant((var)));
+ rv->asObject()->defineReadonlyProperty(v4->newString("__qml:hidden:ref"), v);
agent->release();
agent->setV8Engine(engine);
- return rv;
+ return rv.asReturnedValue();
}
case WorkerSequence:
{
+ ScopedValue value(scope);
bool succeeded = false;
quint32 length = headersize(header);
quint32 seqLength = length - 1;
- int sequenceType = deserialize(data, engine).integerValue();
- QV4::ArrayObject *array = v4->newArrayObject();
+ value = deserialize(data, engine);
+ int sequenceType = value->integerValue();
+ Scoped<ArrayObject> array(scope, v4->newArrayObject());
array->arrayReserve(seqLength);
array->arrayDataLen = seqLength;
- for (quint32 ii = 0; ii < seqLength; ++ii)
- array->arrayData[ii].value = deserialize(data, engine);
+ for (quint32 ii = 0; ii < seqLength; ++ii) {
+ value = deserialize(data, engine);
+ array->arrayData[ii].value = value;
+ }
array->setArrayLengthUnchecked(seqLength);
- QVariant seqVariant = QV4::SequencePrototype::toVariant(QV4::Value::fromObject(array), sequenceType, &succeeded);
+ QVariant seqVariant = QV4::SequencePrototype::toVariant(array.asValue(), sequenceType, &succeeded);
return QV4::SequencePrototype::fromVariant(v4, seqVariant, &succeeded);
}
}
Q_ASSERT(!"Unreachable");
- return QV4::Value::undefinedValue();
+ return QV4::Encode::undefined();
}
QByteArray Serialize::serialize(const QV4::Value &value, QV8Engine *engine)
@@ -389,7 +400,7 @@ QByteArray Serialize::serialize(const QV4::Value &value, QV8Engine *engine)
return rv;
}
-QV4::Value Serialize::deserialize(const QByteArray &data, QV8Engine *engine)
+ReturnedValue Serialize::deserialize(const QByteArray &data, QV8Engine *engine)
{
const char *stream = data.constData();
return deserialize(stream, engine);
diff --git a/src/qml/jsruntime/qv4serialize_p.h b/src/qml/jsruntime/qv4serialize_p.h
index 5a04c9d25f..caedb962b1 100644
--- a/src/qml/jsruntime/qv4serialize_p.h
+++ b/src/qml/jsruntime/qv4serialize_p.h
@@ -66,11 +66,11 @@ class Serialize {
public:
static QByteArray serialize(const Value &, QV8Engine *);
- static Value deserialize(const QByteArray &, QV8Engine *);
+ static ReturnedValue deserialize(const QByteArray &, QV8Engine *);
private:
static void serialize(QByteArray &, const Value &, QV8Engine *);
- static Value deserialize(const char *&, QV8Engine *);
+ static ReturnedValue deserialize(const char *&, QV8Engine *);
};
}
diff --git a/src/qml/jsruntime/qv4sparsearray.cpp b/src/qml/jsruntime/qv4sparsearray.cpp
index f21855ebc9..faa2f310ed 100644
--- a/src/qml/jsruntime/qv4sparsearray.cpp
+++ b/src/qml/jsruntime/qv4sparsearray.cpp
@@ -61,13 +61,15 @@ bool ArrayElementLessThan::operator()(const Property &p1, const Property &p2) co
if (p2.value.isUndefined())
return true;
if (Object *o = m_comparefn.asObject()) {
- ScopedCallData callData(o->engine(), 2);
+ Scope scope(o->engine());
+ ScopedValue result(scope);
+ ScopedCallData callData(scope, 2);
callData->thisObject = Value::undefinedValue();
callData->args[0] = p1.value;
callData->args[1] = p2.value;
- Value result = Value::undefinedValue();
- __qmljs_call_value(m_context, &result, QV4::ValueRef::fromRawValue(&m_comparefn), callData);
- return result.toNumber() <= 0;
+ result = __qmljs_call_value(m_context, QV4::ValueRef::fromRawValue(&m_comparefn), callData);
+
+ return result->toNumber() <= 0;
}
return p1.value.toString(m_context)->toQString() < p2.value.toString(m_context)->toQString();
}
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index 11d3100180..bd1f14b680 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -129,42 +129,42 @@ void String::destroy(Managed *that)
static_cast<String*>(that)->~String();
}
-Value String::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue String::get(Managed *m, String *name, bool *hasProperty)
{
String *that = static_cast<String *>(m);
ExecutionEngine *v4 = m->engine();
if (name == v4->id_length) {
if (hasProperty)
*hasProperty = true;
- return Value::fromInt32(that->_text.length());
+ return Value::fromInt32(that->_text.length()).asReturnedValue();
}
PropertyAttributes attrs;
Property *pd = v4->stringClass->prototype->__getPropertyDescriptor__(name, &attrs);
if (!pd || attrs.isGeneric()) {
if (hasProperty)
*hasProperty = false;
- return Value::undefinedValue();
+ return Value::undefinedValue().asReturnedValue();
}
if (hasProperty)
*hasProperty = true;
return v4->stringClass->prototype->getValue(Value::fromString(that), pd, attrs);
}
-Value String::getIndexed(Managed *m, uint index, bool *hasProperty)
+ReturnedValue String::getIndexed(Managed *m, uint index, bool *hasProperty)
{
String *that = static_cast<String *>(m);
ExecutionEngine *engine = that->engine();
if (index < that->_text.length()) {
if (hasProperty)
*hasProperty = true;
- return Value::fromString(engine->newString(that->toQString().mid(index, 1)));
+ return Value::fromString(engine->newString(that->toQString().mid(index, 1))).asReturnedValue();
}
PropertyAttributes attrs;
Property *pd = engine->stringClass->prototype->__getPropertyDescriptor__(index, &attrs);
if (!pd || attrs.isGeneric()) {
if (hasProperty)
*hasProperty = false;
- return Value::undefinedValue();
+ return Value::undefinedValue().asReturnedValue();
}
if (hasProperty)
*hasProperty = true;
@@ -173,15 +173,17 @@ Value String::getIndexed(Managed *m, uint index, bool *hasProperty)
void String::put(Managed *m, String *name, const Value &value)
{
+ Scope scope(m->engine());
String *that = static_cast<String *>(m);
- Object *o = that->engine()->newStringObject(Value::fromString(that));
+ Scoped<Object> o(scope, that->engine()->newStringObject(Value::fromString(that)));
o->put(name, value);
}
void String::putIndexed(Managed *m, uint index, const Value &value)
{
+ Scope scope(m->engine());
String *that = static_cast<String *>(m);
- Object *o = m->engine()->newStringObject(Value::fromString(that));
+ Scoped<Object> o(scope, that->engine()->newStringObject(Value::fromString(that)));
o->putIndexed(index, value);
}
@@ -213,6 +215,8 @@ bool String::isEqualTo(Managed *t, Managed *o)
{
if (t == o)
return true;
+
+ Q_ASSERT(t->type == Type_String && o->type == Type_String);
String *that = static_cast<String *>(t);
String *other = static_cast<String *>(o);
if (that->hashValue() != other->hashValue())
diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h
index 31e5c2a5f7..7dd912a41f 100644
--- a/src/qml/jsruntime/qv4string_p.h
+++ b/src/qml/jsruntime/qv4string_p.h
@@ -52,6 +52,7 @@ struct ExecutionEngine;
struct Identifier;
struct Q_QML_EXPORT String : public Managed {
+ Q_MANAGED
enum StringType {
StringType_Unknown,
StringType_Regular,
@@ -119,6 +120,10 @@ 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;
@@ -126,8 +131,8 @@ struct Q_QML_EXPORT String : public Managed {
protected:
static void destroy(Managed *);
- static Value get(Managed *m, String *name, bool *hasProperty);
- static Value getIndexed(Managed *m, uint index, bool *hasProperty);
+ static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
static void put(Managed *m, String *name, const Value &value);
static void putIndexed(Managed *m, uint index, const Value &value);
static PropertyAttributes query(const Managed *m, String *name);
@@ -135,8 +140,6 @@ protected:
static bool deleteProperty(Managed *, String *);
static bool deleteIndexedProperty(Managed *m, uint index);
static bool isEqualTo(Managed *that, Managed *o);
-
- static const ManagedVTable static_vtbl;
};
}
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index 0a9cb32e6f..811c5b26b9 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -160,24 +160,24 @@ StringCtor::StringCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value StringCtor::construct(Managed *m, CallData *callData)
+ReturnedValue StringCtor::construct(Managed *m, CallData *callData)
{
Value value;
if (callData->argc)
value = Value::fromString(callData->args[0].toString(m->engine()->current));
else
value = Value::fromString(m->engine()->current, QString());
- return Value::fromObject(m->engine()->newStringObject(value));
+ return Encode(m->engine()->newStringObject(value));
}
-Value StringCtor::call(Managed *m, CallData *callData)
+ReturnedValue StringCtor::call(Managed *m, CallData *callData)
{
Value value;
if (callData->argc)
value = Value::fromString(callData->args[0].toString(m->engine()->current));
else
value = Value::fromString(m->engine()->current, QString());
- return value;
+ return value.asReturnedValue();
}
void StringPrototype::init(ExecutionEngine *engine, const Value &ctor)
@@ -237,18 +237,18 @@ static QString getThisString(ExecutionContext *context, Value thisObject)
return str->toQString();
}
-Value StringPrototype::method_toString(SimpleCallContext *context)
+ReturnedValue StringPrototype::method_toString(SimpleCallContext *context)
{
if (context->thisObject.isString())
- return context->thisObject;
+ return context->thisObject.asReturnedValue();
StringObject *o = context->thisObject.asStringObject();
if (!o)
context->throwTypeError();
- return o->value;
+ return o->value.asReturnedValue();
}
-Value StringPrototype::method_charAt(SimpleCallContext *context)
+ReturnedValue StringPrototype::method_charAt(SimpleCallContext *context)
{
const QString str = getThisString(context, context->thisObject);
@@ -260,10 +260,10 @@ Value StringPrototype::method_charAt(SimpleCallContext *context)
if (pos >= 0 && pos < str.length())
result += str.at(pos);
- return Value::fromString(context, result);
+ return Value::fromString(context, result).asReturnedValue();
}
-Value StringPrototype::method_charCodeAt(SimpleCallContext *context)
+ReturnedValue StringPrototype::method_charCodeAt(SimpleCallContext *context)
{
const QString str = getThisString(context, context->thisObject);
@@ -273,14 +273,14 @@ Value StringPrototype::method_charCodeAt(SimpleCallContext *context)
if (pos >= 0 && pos < str.length())
- return Value::fromInt32(str.at(pos).unicode());
+ return Encode(str.at(pos).unicode());
- return Value::fromDouble(qSNaN());
+ return Encode(qSNaN());
}
-Value StringPrototype::method_concat(SimpleCallContext *context)
+ReturnedValue StringPrototype::method_concat(SimpleCallContext *context)
{
- ValueScope scope(context);
+ Scope scope(context);
QString value = getThisString(context, context->thisObject);
@@ -291,10 +291,10 @@ Value StringPrototype::method_concat(SimpleCallContext *context)
value += v->stringValue()->toQString();
}
- return Value::fromString(context, value);
+ return Value::fromString(context, value).asReturnedValue();
}
-Value StringPrototype::method_indexOf(SimpleCallContext *context)
+ReturnedValue StringPrototype::method_indexOf(SimpleCallContext *context)
{
QString value = getThisString(context, context->thisObject);
@@ -310,20 +310,18 @@ Value StringPrototype::method_indexOf(SimpleCallContext *context)
if (! value.isEmpty())
index = value.indexOf(searchString, qMin(qMax(pos, 0), value.length()));
- return Value::fromDouble(index);
+ return Encode(index);
}
-Value StringPrototype::method_lastIndexOf(SimpleCallContext *context)
+ReturnedValue StringPrototype::method_lastIndexOf(SimpleCallContext *context)
{
- ValueScope scope(context);
+ Scope scope(context);
const QString value = getThisString(context, context->thisObject);
QString searchString;
- if (context->argumentCount) {
- Value v = __qmljs_to_string(ValueRef(&context->arguments[0]), context);
- searchString = v.stringValue()->toQString();
- }
+ if (context->argumentCount)
+ searchString = context->arguments[0].toQString();
ScopedValue posArg(scope, context->argumentCount > 1 ? context->arguments[1] : Value::undefinedValue());
double position = __qmljs_to_number(posArg);
@@ -336,31 +334,32 @@ Value StringPrototype::method_lastIndexOf(SimpleCallContext *context)
if (!searchString.isEmpty() && pos == value.length())
--pos;
if (searchString.isNull() && pos == 0)
- return Value::fromDouble(-1);
+ return Encode(-1);
int index = value.lastIndexOf(searchString, pos);
- return Value::fromDouble(index);
+ return Encode(index);
}
-Value StringPrototype::method_localeCompare(SimpleCallContext *context)
+ReturnedValue StringPrototype::method_localeCompare(SimpleCallContext *context)
{
const QString value = getThisString(context, context->thisObject);
const QString that = (context->argumentCount ? context->arguments[0] : Value::undefinedValue()).toString(context)->toQString();
- return Value::fromDouble(QString::localeAwareCompare(value, that));
+ return Encode(QString::localeAwareCompare(value, that));
}
-Value StringPrototype::method_match(SimpleCallContext *context)
+ReturnedValue StringPrototype::method_match(SimpleCallContext *context)
{
if (context->thisObject.isUndefined() || context->thisObject.isNull())
context->throwTypeError();
+ Scope scope(context);
String *s = context->thisObject.toString(context);
Value regexp = context->argumentCount ? context->arguments[0] : Value::undefinedValue();
RegExpObject *rx = regexp.as<RegExpObject>();
if (!rx) {
- ScopedCallData callData(context->engine, 1);
+ ScopedCallData callData(scope, 1);
callData->args[0] = regexp;
- rx = context->engine->regExpCtor.asFunctionObject()->construct(callData).as<RegExpObject>();
+ rx = Value::fromReturnedValue(context->engine->regExpCtor.asFunctionObject()->construct(callData)).as<RegExpObject>();
}
if (!rx)
@@ -370,9 +369,9 @@ Value StringPrototype::method_match(SimpleCallContext *context)
bool global = rx->global;
// ### use the standard builtin function, not the one that might be redefined in the proto
- FunctionObject *exec = context->engine->regExpClass->prototype->get(context->engine->newString(QStringLiteral("exec")), 0).asFunctionObject();
+ Scoped<FunctionObject> exec(scope, context->engine->regExpClass->prototype->get(context->engine->newString(QStringLiteral("exec")), 0));
- ScopedCallData callData(context->engine, 1);
+ ScopedCallData callData(scope, 1);
callData->thisObject = Value::fromObject(rx);
callData->args[0] = Value::fromString(s);
if (!global)
@@ -380,30 +379,34 @@ Value StringPrototype::method_match(SimpleCallContext *context)
String *lastIndex = context->engine->newString(QStringLiteral("lastIndex"));
rx->put(lastIndex, Value::fromInt32(0));
- ArrayObject *a = context->engine->newArrayObject();
+ Scoped<ArrayObject> a(scope, context->engine->newArrayObject());
double previousLastIndex = 0;
uint n = 0;
+ ScopedValue result(scope);
+ ScopedValue matchStr(scope);
+ ScopedValue index(scope);
while (1) {
- Value result = exec->call(callData);
- if (result.isNull())
+ result = exec->call(callData);
+ if (result->isNull())
break;
- assert(result.isObject());
- double thisIndex = rx->get(lastIndex, 0).toInteger();
+ assert(result->isObject());
+ index = rx->get(lastIndex, 0);
+ double thisIndex = index->toInteger();
if (previousLastIndex == thisIndex) {
previousLastIndex = thisIndex + 1;
rx->put(lastIndex, Value::fromDouble(previousLastIndex));
} else {
previousLastIndex = thisIndex;
}
- Value matchStr = result.objectValue()->getIndexed(0);
+ matchStr = result->objectValue()->getIndexed(0);
a->arraySet(n, matchStr);
++n;
}
if (!n)
- return Value::nullValue();
+ return Encode::null();
- return Value::fromObject(a);
+ return a.asReturnedValue();
}
@@ -452,8 +455,9 @@ static void appendReplacementString(QString *result, const QString &input, const
}
}
-Value StringPrototype::method_replace(SimpleCallContext *ctx)
+ReturnedValue StringPrototype::method_replace(SimpleCallContext *ctx)
{
+ Scope scope(ctx);
QString string;
if (StringObject *thisString = ctx->thisObject.asStringObject())
string = thisString->value.stringValue()->toQString();
@@ -509,9 +513,10 @@ Value StringPrototype::method_replace(SimpleCallContext *ctx)
QString result;
Value replaceValue = ctx->argument(1);
+ ScopedValue replacement(scope);
if (FunctionObject* searchCallback = replaceValue.asFunctionObject()) {
result.reserve(string.length() + 10*numStringMatches);
- ScopedCallData callData(ctx->engine, numCaptures + 2);
+ ScopedCallData callData(scope, numCaptures + 2);
callData->thisObject = Value::undefinedValue();
int lastEnd = 0;
for (int i = 0; i < numStringMatches; ++i) {
@@ -530,9 +535,9 @@ Value StringPrototype::method_replace(SimpleCallContext *ctx)
callData->args[numCaptures] = Value::fromUInt32(matchStart);
callData->args[numCaptures + 1] = Value::fromString(ctx, string);
- Value replacement = searchCallback->call(callData);
+ replacement = searchCallback->call(callData);
result += string.midRef(lastEnd, matchStart - lastEnd);
- result += replacement.toString(ctx)->toQString();
+ result += replacement->toString(ctx)->toQString();
lastEnd = matchEnd;
}
result += string.midRef(lastEnd);
@@ -558,33 +563,34 @@ Value StringPrototype::method_replace(SimpleCallContext *ctx)
if (matchOffsets != _matchOffsets)
free(matchOffsets);
- return Value::fromString(ctx, result);
+ return Value::fromString(ctx, result).asReturnedValue();
}
-Value StringPrototype::method_search(SimpleCallContext *ctx)
+ReturnedValue StringPrototype::method_search(SimpleCallContext *ctx)
{
+ Scope scope(ctx);
QString string;
if (StringObject *thisString = ctx->thisObject.asStringObject())
string = thisString->value.stringValue()->toQString();
else
string = ctx->thisObject.toString(ctx)->toQString();
- Value regExpValue = ctx->argument(0);
- RegExpObject *regExp = regExpValue.as<RegExpObject>();
+ ScopedValue regExpValue(scope, ctx->argument(0));
+ RegExpObject *regExp = regExpValue->as<RegExpObject>();
if (!regExp) {
- ScopedCallData callData(ctx->engine, 1);
+ ScopedCallData callData(scope, 1);
callData->args[0] = regExpValue;
regExpValue = ctx->engine->regExpCtor.asFunctionObject()->construct(callData);
- regExp = regExpValue.as<RegExpObject>();
+ regExp = regExpValue->as<RegExpObject>();
}
uint* matchOffsets = (uint*)alloca(regExp->value->captureCount() * 2 * sizeof(uint));
uint result = regExp->value->match(string, /*offset*/0, matchOffsets);
if (result == JSC::Yarr::offsetNoMatch)
- return Value::fromInt32(-1);
- return Value::fromUInt32(result);
+ return Encode(-1);
+ return Encode(result);
}
-Value StringPrototype::method_slice(SimpleCallContext *ctx)
+ReturnedValue StringPrototype::method_slice(SimpleCallContext *ctx)
{
const QString text = getThisString(ctx);
const double length = text.length();
@@ -607,11 +613,12 @@ Value StringPrototype::method_slice(SimpleCallContext *ctx)
const int intEnd = int(end);
int count = qMax(0, intEnd - intStart);
- return Value::fromString(ctx, text.mid(intStart, count));
+ return Value::fromString(ctx, text.mid(intStart, count)).asReturnedValue();
}
-Value StringPrototype::method_split(SimpleCallContext *ctx)
+ReturnedValue StringPrototype::method_split(SimpleCallContext *ctx)
{
+ Scope scope(ctx);
QString text;
if (StringObject *thisObject = ctx->thisObject.asStringObject())
text = thisObject->value.stringValue()->toQString();
@@ -621,21 +628,20 @@ Value StringPrototype::method_split(SimpleCallContext *ctx)
Value separatorValue = ctx->argumentCount > 0 ? ctx->argument(0) : Value::undefinedValue();
Value limitValue = ctx->argumentCount > 1 ? ctx->argument(1) : Value::undefinedValue();
- ArrayObject* array = ctx->engine->newArrayObject();
- Value result = Value::fromObject(array);
+ Scoped<ArrayObject> array(scope, ctx->engine->newArrayObject());
if (separatorValue.isUndefined()) {
if (limitValue.isUndefined()) {
array->push_back(Value::fromString(ctx, text));
- return result;
+ return array.asReturnedValue();
}
- return Value::fromString(ctx, text.left(limitValue.toInteger()));
+ return Value::fromString(ctx, text.left(limitValue.toInteger())).asReturnedValue();
}
uint limit = limitValue.isUndefined() ? UINT_MAX : limitValue.toUInt32();
if (limit == 0)
- return result;
+ return array.asReturnedValue();
if (RegExpObject* re = separatorValue.as<RegExpObject>()) {
if (re->value->pattern().isEmpty()) {
@@ -673,7 +679,7 @@ Value StringPrototype::method_split(SimpleCallContext *ctx)
if (separator.isEmpty()) {
for (uint i = 0; i < qMin(limit, uint(text.length())); ++i)
array->push_back(Value::fromString(ctx, text.mid(i, 1)));
- return result;
+ return array.asReturnedValue();
}
int start = 0;
@@ -687,10 +693,10 @@ Value StringPrototype::method_split(SimpleCallContext *ctx)
if (array->arrayLength() < limit && start != -1)
array->push_back(Value::fromString(ctx, text.mid(start)));
}
- return result;
+ return array.asReturnedValue();
}
-Value StringPrototype::method_substr(SimpleCallContext *context)
+ReturnedValue StringPrototype::method_substr(SimpleCallContext *context)
{
const QString value = getThisString(context, context->thisObject);
@@ -710,10 +716,10 @@ Value StringPrototype::method_substr(SimpleCallContext *context)
qint32 x = Value::toInt32(start);
qint32 y = Value::toInt32(length);
- return Value::fromString(context, value.mid(x, y));
+ return Value::fromString(context, value.mid(x, y)).asReturnedValue();
}
-Value StringPrototype::method_substring(SimpleCallContext *context)
+ReturnedValue StringPrototype::method_substring(SimpleCallContext *context)
{
QString value = getThisString(context, context->thisObject);
int length = value.length();
@@ -748,32 +754,32 @@ Value StringPrototype::method_substring(SimpleCallContext *context)
qint32 x = (int)start;
qint32 y = (int)(end - start);
- return Value::fromString(context, value.mid(x, y));
+ return Value::fromString(context, value.mid(x, y)).asReturnedValue();
}
-Value StringPrototype::method_toLowerCase(SimpleCallContext *ctx)
+ReturnedValue StringPrototype::method_toLowerCase(SimpleCallContext *ctx)
{
QString value = getThisString(ctx);
- return Value::fromString(ctx, value.toLower());
+ return Value::fromString(ctx, value.toLower()).asReturnedValue();
}
-Value StringPrototype::method_toLocaleLowerCase(SimpleCallContext *ctx)
+ReturnedValue StringPrototype::method_toLocaleLowerCase(SimpleCallContext *ctx)
{
return method_toLowerCase(ctx);
}
-Value StringPrototype::method_toUpperCase(SimpleCallContext *ctx)
+ReturnedValue StringPrototype::method_toUpperCase(SimpleCallContext *ctx)
{
QString value = getThisString(ctx);
- return Value::fromString(ctx, value.toUpper());
+ return Value::fromString(ctx, value.toUpper()).asReturnedValue();
}
-Value StringPrototype::method_toLocaleUpperCase(SimpleCallContext *ctx)
+ReturnedValue StringPrototype::method_toLocaleUpperCase(SimpleCallContext *ctx)
{
return method_toUpperCase(ctx);
}
-Value StringPrototype::method_fromCharCode(SimpleCallContext *context)
+ReturnedValue StringPrototype::method_fromCharCode(SimpleCallContext *context)
{
QString str(context->argumentCount, Qt::Uninitialized);
QChar *ch = str.data();
@@ -781,15 +787,15 @@ Value StringPrototype::method_fromCharCode(SimpleCallContext *context)
*ch = QChar(context->arguments[i].toUInt16());
++ch;
}
- return Value::fromString(context, str);
+ return Value::fromString(context, str).asReturnedValue();
}
-Value StringPrototype::method_trim(SimpleCallContext *ctx)
+ReturnedValue StringPrototype::method_trim(SimpleCallContext *ctx)
{
if (ctx->thisObject.isNull() || ctx->thisObject.isUndefined())
ctx->throwTypeError();
- QString s = __qmljs_to_string(ValueRef(&ctx->thisObject), ctx).stringValue()->toQString();
+ QString s = ctx->thisObject.toQString();
const QChar *chars = s.constData();
int start, end;
for (start = 0; start < s.length(); ++start) {
@@ -801,5 +807,5 @@ Value StringPrototype::method_trim(SimpleCallContext *ctx)
break;
}
- return Value::fromString(ctx, QString(chars + start, end - start + 1));
+ return Value::fromString(ctx, QString(chars + start, end - start + 1)).asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h
index f9cf89e9d9..0932379843 100644
--- a/src/qml/jsruntime/qv4stringobject_p.h
+++ b/src/qml/jsruntime/qv4stringobject_p.h
@@ -68,13 +68,11 @@ protected:
struct StringCtor: FunctionObject
{
+ Q_MANAGED
StringCtor(ExecutionContext *scope);
- static Value construct(Managed *m, CallData *callData);
- static Value call(Managed *that, CallData *callData);
-
-protected:
- static const ManagedVTable static_vtbl;
+ static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue call(Managed *that, CallData *callData);
};
struct StringPrototype: StringObject
@@ -82,26 +80,26 @@ struct StringPrototype: StringObject
StringPrototype(InternalClass *ic): StringObject(ic) {}
void init(ExecutionEngine *engine, const Value &ctor);
- static Value method_toString(SimpleCallContext *context);
- static Value method_charAt(SimpleCallContext *context);
- static Value method_charCodeAt(SimpleCallContext *context);
- static Value method_concat(SimpleCallContext *context);
- static Value method_indexOf(SimpleCallContext *context);
- static Value method_lastIndexOf(SimpleCallContext *context);
- static Value method_localeCompare(SimpleCallContext *context);
- static Value method_match(SimpleCallContext *context);
- static Value method_replace(SimpleCallContext *ctx);
- static Value method_search(SimpleCallContext *ctx);
- static Value method_slice(SimpleCallContext *ctx);
- static Value method_split(SimpleCallContext *ctx);
- static Value method_substr(SimpleCallContext *context);
- static Value method_substring(SimpleCallContext *context);
- static Value method_toLowerCase(SimpleCallContext *ctx);
- static Value method_toLocaleLowerCase(SimpleCallContext *ctx);
- static Value method_toUpperCase(SimpleCallContext *ctx);
- static Value method_toLocaleUpperCase(SimpleCallContext *ctx);
- static Value method_fromCharCode(SimpleCallContext *context);
- static Value method_trim(SimpleCallContext *ctx);
+ static ReturnedValue method_toString(SimpleCallContext *context);
+ static ReturnedValue method_charAt(SimpleCallContext *context);
+ static ReturnedValue method_charCodeAt(SimpleCallContext *context);
+ static ReturnedValue method_concat(SimpleCallContext *context);
+ static ReturnedValue method_indexOf(SimpleCallContext *context);
+ static ReturnedValue method_lastIndexOf(SimpleCallContext *context);
+ static ReturnedValue method_localeCompare(SimpleCallContext *context);
+ static ReturnedValue method_match(SimpleCallContext *context);
+ static ReturnedValue method_replace(SimpleCallContext *ctx);
+ static ReturnedValue method_search(SimpleCallContext *ctx);
+ static ReturnedValue method_slice(SimpleCallContext *ctx);
+ static ReturnedValue method_split(SimpleCallContext *ctx);
+ static ReturnedValue method_substr(SimpleCallContext *context);
+ static ReturnedValue method_substring(SimpleCallContext *context);
+ static ReturnedValue method_toLowerCase(SimpleCallContext *ctx);
+ static ReturnedValue method_toLocaleLowerCase(SimpleCallContext *ctx);
+ static ReturnedValue method_toUpperCase(SimpleCallContext *ctx);
+ static ReturnedValue method_toLocaleUpperCase(SimpleCallContext *ctx);
+ static ReturnedValue method_fromCharCode(SimpleCallContext *context);
+ static ReturnedValue method_trim(SimpleCallContext *ctx);
};
}
diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp
index 718b87d2c9..f97aa66669 100644
--- a/src/qml/jsruntime/qv4value.cpp
+++ b/src/qml/jsruntime/qv4value.cpp
@@ -48,44 +48,9 @@
using namespace QV4;
-int Value::toInt32() const
-{
- if (isConvertibleToInt())
- return int_32;
- double d;
- if (isDouble())
- d = dbl;
- else
- d = toNumber();
-
- const double D32 = 4294967296.0;
- const double D31 = D32 / 2.0;
-
- if ((d >= -D31 && d < D31))
- return static_cast<int>(d);
-
- return Value::toInt32(d);
-}
-
-unsigned int Value::toUInt32() const
-{
- if (isConvertibleToInt())
- return (unsigned) int_32;
- double d;
- if (isDouble())
- d = dbl;
- else
- d = toNumber();
-
- const double D32 = 4294967296.0;
- if (d >= 0 && d < D32)
- return static_cast<uint>(d);
- return toUInt32(d);
-}
-
int Value::toUInt16() const
{
- if (isConvertibleToInt())
+ if (integerCompatible())
return (ushort)(uint)integerValue();
double number = toNumber();
@@ -111,41 +76,39 @@ int Value::toUInt16() const
double Value::toInteger() const
{
- if (isConvertibleToInt())
+ if (integerCompatible())
return int_32;
return Value::toInteger(toNumber());
}
-double Value::toNumber() const
+double Value::toNumberImpl() const
{
- QV4::Value v = *this;
-
- redo:
- switch (v.type()) {
+ switch (type()) {
case QV4::Value::Undefined_Type:
return std::numeric_limits<double>::quiet_NaN();
+ case QV4::Value::Managed_Type:
+ if (isString())
+ return __qmljs_string_to_number(stringValue()->toQString());
+ {
+ ExecutionContext *ctx = objectValue()->internalClass->engine->current;
+ Scope scope(ctx);
+ ScopedValue prim(scope, __qmljs_to_primitive(ValueRef::fromRawValue(this), NUMBER_HINT));
+ return prim->toNumber();
+ }
case QV4::Value::Null_Type:
- return 0;
case QV4::Value::Boolean_Type:
- return (v.booleanValue() ? 1. : 0.);
case QV4::Value::Integer_Type:
- return v.int_32;
- case QV4::Value::String_Type:
- return __qmljs_string_to_number(v.toQString());
- case QV4::Value::Object_Type: {
- v = __qmljs_to_primitive(ValueRef::fromRawValue(this), QV4::NUMBER_HINT);
- goto redo;
- }
default: // double
- return v.doubleValue();
+ Q_UNREACHABLE();
}
}
-QString Value::toQString() const
+QString Value::toQStringNoThrow() const
{
switch (type()) {
case Value::Undefined_Type:
+ case Value::Empty_Type:
return QStringLiteral("undefined");
case Value::Null_Type:
return QStringLiteral("null");
@@ -154,28 +117,64 @@ QString Value::toQString() const
return QStringLiteral("true");
else
return QStringLiteral("false");
- case Value::String_Type:
- return stringValue()->toQString();
- case Value::Object_Type: {
- ExecutionContext *ctx = objectValue()->internalClass->engine->current;
- ValueScope scope(ctx);
- try {
- ScopedValue prim(scope, __qmljs_to_primitive(ValueRef::fromRawValue(this), STRING_HINT));
- if (prim->isPrimitive())
- return prim->toQString();
- } catch (Exception &e) {
- e.accept(ctx);
+ case Value::Managed_Type:
+ if (isString())
+ return stringValue()->toQString();
+ {
+ ExecutionContext *ctx = objectValue()->internalClass->engine->current;
+ Scope scope(ctx);
try {
- ScopedValue ex(scope, e.value());
- ScopedValue prim(scope, __qmljs_to_primitive(ex, STRING_HINT));
+ ScopedValue prim(scope, __qmljs_to_primitive(ValueRef::fromRawValue(this), STRING_HINT));
if (prim->isPrimitive())
- return prim->toQString();
- } catch(Exception &e) {
+ return prim->toQStringNoThrow();
+ } catch (Exception &e) {
e.accept(ctx);
+ try {
+ ScopedValue ex(scope, e.value());
+ ScopedValue prim(scope, __qmljs_to_primitive(ex, STRING_HINT));
+ if (prim->isPrimitive())
+ return prim->toQStringNoThrow();
+ } catch(Exception &e) {
+ e.accept(ctx);
+ }
}
+ return QString();
}
- return QString();
+ case Value::Integer_Type: {
+ QString str;
+ __qmljs_numberToString(&str, (double)int_32, 10);
+ return str;
+ }
+ default: { // double
+ QString str;
+ __qmljs_numberToString(&str, doubleValue(), 10);
+ return str;
}
+ } // switch
+}
+
+QString Value::toQString() const
+{
+ switch (type()) {
+ case Value::Undefined_Type:
+ case Value::Empty_Type:
+ return QStringLiteral("undefined");
+ case Value::Null_Type:
+ return QStringLiteral("null");
+ case Value::Boolean_Type:
+ if (booleanValue())
+ return QStringLiteral("true");
+ else
+ return QStringLiteral("false");
+ case Value::Managed_Type:
+ if (isString())
+ return stringValue()->toQString();
+ {
+ ExecutionContext *ctx = objectValue()->internalClass->engine->current;
+ Scope scope(ctx);
+ ScopedValue prim(scope, __qmljs_to_primitive(ValueRef::fromRawValue(this), STRING_HINT));
+ return prim->toQString();
+ }
case Value::Integer_Type: {
QString str;
__qmljs_numberToString(&str, (double)int_32, 10);
@@ -194,10 +193,10 @@ bool Value::sameValue(Value other) const {
return true;
if (isString() && other.isString())
return stringValue()->isEqualTo(other.stringValue());
- if (isInteger())
- return int_32 ? (double(int_32) == other.dbl) : (other.val == 0);
- if (other.isInteger())
- return other.int_32 ? (dbl == double(other.int_32)) : (val == 0);
+ if (isInteger() && other.isDouble())
+ return int_32 ? (double(int_32) == other.doubleValue()) : (other.val == 0);
+ if (isDouble() && other.isInteger())
+ return other.int_32 ? (doubleValue() == double(other.int_32)) : (val == 0);
return false;
}
@@ -273,25 +272,24 @@ String *Value::toString(ExecutionContext *ctx) const
{
if (isString())
return stringValue();
- return __qmljs_convert_to_string(ctx, ValueRef::fromRawValue(this));
+ return __qmljs_convert_to_string(ctx, ValueRef::fromRawValue(this))->getPointer();
}
Object *Value::toObject(ExecutionContext *ctx) const
{
if (isObject())
return objectValue();
- return __qmljs_convert_to_object(ctx, ValueRef::fromRawValue(this));
+ return __qmljs_convert_to_object(ctx, ValueRef::fromRawValue(this))->getPointer();
}
-Value Value::property(ExecutionContext *ctx, String *name) const
+PersistentValue::PersistentValue(const Value &val)
+ : d(new PersistentValuePrivate(val))
{
- return isObject() ? objectValue()->get(name) : undefinedValue();
}
-
-PersistentValue::PersistentValue(const Value &val)
- : d(new PersistentValuePrivate(val))
+PersistentValue::PersistentValue(ReturnedValue val)
+ : d(new PersistentValuePrivate(Value::fromReturnedValue(val)))
{
}
@@ -328,6 +326,16 @@ PersistentValue &PersistentValue::operator =(const Value &other)
return *this;
}
+PersistentValue &PersistentValue::operator =(const ReturnedValue &other)
+{
+ if (!d) {
+ d = new PersistentValuePrivate(Value::fromReturnedValue(other));
+ return *this;
+ }
+ d = d->detach(Value::fromReturnedValue(other));
+ return *this;
+}
+
PersistentValue::~PersistentValue()
{
if (d)
diff --git a/src/qml/jsruntime/qv4value_def_p.h b/src/qml/jsruntime/qv4value_def_p.h
index 7d037f3d49..76f694c0e9 100644
--- a/src/qml/jsruntime/qv4value_def_p.h
+++ b/src/qml/jsruntime/qv4value_def_p.h
@@ -52,9 +52,38 @@ typedef uint Bool;
struct Q_QML_EXPORT Value
{
+ /*
+ We use two different ways of encoding JS values. One for 32bit and one for 64bit systems.
+
+ In both cases, we 8 bytes for a value and different variant of NaN boxing. A Double NaN (actually -qNaN)
+ is indicated by a number that has the top 13 bits set. THe other values are usually set to 0 by the
+ processor, and are thus free for us to store other data. We keep pointers in there for managed objects,
+ and encode the other types using the free space given to use by the unused bits for NaN values. This also
+ works for pointers on 64 bit systems, as they all currently only have 48 bits of addressable memory.
+
+ On 32bit, we store doubles as doubles. All other values, have the high 32bits set to a value that
+ will make the number a NaN. The Masks below are used for encoding the other types.
+
+ On 64 bit, we xor Doubles with (0xffff8000 << 32). Thas has the effect that no doubles will get encoded
+ with the 13 highest bits all 0. We are now using special values for bits 14-17 to encode our values. These
+ can be used, as the highest valid pointer on a 64 bit system is 2^48-1.
+
+ If they are all 0, we have a pointer to a Managed object. If bit 14 is set we have an integer.
+ This makes testing for pointers and numbers very fast (we have a number if any of the highest 14 bits is set).
+
+ Bit 15-17 is then used to encode other immediates.
+ */
+
+
union {
quint64 val;
+#if QT_POINTER_SIZE == 8
+ Managed *m;
+ Object *o;
+ String *s;
+#else
double dbl;
+#endif
struct {
#if Q_BYTE_ORDER != Q_LITTLE_ENDIAN
uint tag;
@@ -74,12 +103,12 @@ struct Q_QML_EXPORT Value
};
};
+#if QT_POINTER_SIZE == 4
enum Masks {
NaN_Mask = 0x7ff80000,
NotDouble_Mask = 0x7ffc0000,
Type_Mask = 0xffff8000,
Immediate_Mask = NotDouble_Mask | 0x00008000,
- IsManaged_Mask = Type_Mask & ~0x10000,
IsNullOrUndefined_Mask = Immediate_Mask | 0x20000,
Tag_Shift = 32
};
@@ -88,9 +117,8 @@ struct Q_QML_EXPORT Value
Null_Type = Immediate_Mask | 0x10000,
Boolean_Type = Immediate_Mask | 0x20000,
Integer_Type = Immediate_Mask | 0x30000,
- Object_Type = NotDouble_Mask | 0x00000,
- String_Type = NotDouble_Mask | 0x10000,
- Deleted_Type = NotDouble_Mask | 0x30000
+ Managed_Type = NotDouble_Mask | 0x00000,
+ Empty_Type = NotDouble_Mask | 0x30000
};
enum ImmediateFlags {
@@ -98,45 +126,119 @@ struct Q_QML_EXPORT Value
};
enum ValueTypeInternal {
- _Undefined_Type = Undefined_Type,
- _Empty_Type = Deleted_Type,
_Null_Type = Null_Type | ConvertibleToInt,
_Boolean_Type = Boolean_Type | ConvertibleToInt,
_Integer_Type = Integer_Type | ConvertibleToInt,
- _Object_Type = Object_Type,
- _String_Type = String_Type
};
+#else
+ static const quint64 NaNEncodeMask = 0xffff800000000000ll;
+ static const quint64 IsInt32Mask = 0x0002000000000000ll;
+ static const quint64 IsDoubleMask = 0xfffc000000000000ll;
+ static const quint64 IsNumberMask = IsInt32Mask|IsDoubleMask;
+ static const quint64 IsNullOrUndefinedMask = 0x0000800000000000ll;
+ static const quint64 IsNullOrBooleanMask = 0x0001000000000000ll;
+ static const quint64 IsConvertibleToIntMask = IsInt32Mask|IsNullOrBooleanMask;
+
+ enum Masks {
+ NaN_Mask = 0x7ff80000,
+ Type_Mask = 0xffff8000,
+ IsDouble_Mask = 0xfffc0000,
+ Immediate_Mask = 0x00018000,
+ IsNullOrUndefined_Mask = 0x00008000,
+ IsNullOrBoolean_Mask = 0x00010000,
+ Tag_Shift = 32
+ };
+ enum ValueType {
+ Undefined_Type = IsNullOrUndefined_Mask,
+ Null_Type = IsNullOrUndefined_Mask|IsNullOrBoolean_Mask,
+ Boolean_Type = IsNullOrBoolean_Mask,
+ Integer_Type = 0x20000|IsNullOrBoolean_Mask,
+ Managed_Type = 0,
+ Empty_Type = Undefined_Type | 0x4000
+ };
+ enum {
+ IsDouble_Shift = 64-14,
+ IsNumber_Shift = 64-15,
+ IsConvertibleToInt_Shift = 64-16,
+ IsManaged_Shift = 64-17
+ };
+
+
+ enum ValueTypeInternal {
+ _Null_Type = Null_Type,
+ _Boolean_Type = Boolean_Type,
+ _Integer_Type = Integer_Type
+ };
+#endif
inline unsigned type() const {
return tag & Type_Mask;
}
// used internally in property
- inline bool isEmpty() const { return tag == _Empty_Type; }
+ inline bool isEmpty() const { return tag == Empty_Type; }
- inline bool isUndefined() const { return tag == _Undefined_Type; }
+ inline bool isUndefined() const { return tag == Undefined_Type; }
inline bool isNull() const { return tag == _Null_Type; }
inline bool isBoolean() const { return tag == _Boolean_Type; }
inline bool isInteger() const { return tag == _Integer_Type; }
- inline bool isDouble() const { return (tag & NotDouble_Mask) != NotDouble_Mask; }
- inline bool isNumber() const { return tag == _Integer_Type || (tag & NotDouble_Mask) != NotDouble_Mask; }
#if QT_POINTER_SIZE == 8
- inline bool isString() const { return (tag & Type_Mask) == String_Type; }
- inline bool isObject() const { return (tag & Type_Mask) == Object_Type; }
+ inline bool isDouble() const { return (val >> IsDouble_Shift); }
+ inline bool isNumber() const { return (val >> IsNumber_Shift); }
+ inline bool isManaged() const { return !(val >> IsManaged_Shift); }
+ inline bool isNullOrUndefined() const { return ((val >> IsManaged_Shift) & ~2) == 1; }
+ inline bool integerCompatible() const { return ((val >> IsConvertibleToInt_Shift) & ~2) == 1; }
+ static inline bool integerCompatible(Value a, Value b) {
+ return a.integerCompatible() && b.integerCompatible();
+ }
+ static inline bool bothDouble(Value a, Value b) {
+ return a.isDouble() && b.isDouble();
+ }
+ double doubleValue() const {
+ Q_ASSERT(isDouble());
+ union {
+ quint64 i;
+ double d;
+ } v;
+ v.i = val ^ NaNEncodeMask;
+ return v.d;
+ }
+ void setDouble(double d) {
+ union {
+ quint64 i;
+ double d;
+ } v;
+ v.d = d;
+ val = v.i ^ NaNEncodeMask;
+ Q_ASSERT(isDouble());
+ }
+ bool isNaN() const { return (tag & 0x7fff8000) == 0x00078000; }
#else
- inline bool isString() const { return tag == String_Type; }
- inline bool isObject() const { return tag == Object_Type; }
-#endif
- inline bool isManaged() const { return (tag & IsManaged_Mask) == Object_Type; }
+ inline bool isDouble() const { return (tag & NotDouble_Mask) != NotDouble_Mask; }
+ inline bool isNumber() const { return tag == _Integer_Type || (tag & NotDouble_Mask) != NotDouble_Mask; }
+ inline bool isManaged() const { return tag == Managed_Type; }
inline bool isNullOrUndefined() const { return (tag & IsNullOrUndefined_Mask) == Undefined_Type; }
- inline bool isConvertibleToInt() const { return (tag & ConvertibleToInt) == ConvertibleToInt; }
+ inline bool integerCompatible() const { return (tag & ConvertibleToInt) == ConvertibleToInt; }
+ static inline bool integerCompatible(Value a, Value b) {
+ return ((a.tag & b.tag) & ConvertibleToInt) == ConvertibleToInt;
+ }
+ static inline bool bothDouble(Value a, Value b) {
+ return ((a.tag | b.tag) & NotDouble_Mask) != NotDouble_Mask;
+ }
+ double doubleValue() const { return dbl; }
+ void setDouble(double d) { dbl = d; }
+ bool isNaN() const { return (tag & QV4::Value::NotDouble_Mask) == QV4::Value::NaN_Mask; }
+#endif
+ inline bool isString() const;
+ inline bool isObject() const;
inline bool isInt32() {
if (tag == _Integer_Type)
return true;
if (isDouble()) {
- int i = (int)dbl;
- if (i == dbl) {
+ double d = doubleValue();
+ int i = (int)d;
+ if (i == d) {
int_32 = i;
tag = _Integer_Type;
return true;
@@ -144,36 +246,19 @@ struct Q_QML_EXPORT Value
}
return false;
}
-
- bool booleanValue() const {
- return int_32;
- }
- double doubleValue() const {
- return dbl;
- }
- void setDouble(double d) {
- dbl = d;
- }
double asDouble() const {
if (tag == _Integer_Type)
return int_32;
- return dbl;
+ return doubleValue();
+ }
+
+ bool booleanValue() const {
+ return int_32;
}
int integerValue() const {
return int_32;
}
-#if QT_POINTER_SIZE == 8
- String *stringValue() const {
- return (String *)(val & ~(quint64(Type_Mask) << Tag_Shift));
- }
- Object *objectValue() const {
- return (Object *)(val & ~(quint64(Type_Mask) << Tag_Shift));
- }
- Managed *managed() const {
- return (Managed *)(val & ~(quint64(Type_Mask) << Tag_Shift));
- }
-#else
String *stringValue() const {
return s;
}
@@ -183,7 +268,6 @@ struct Q_QML_EXPORT Value
Managed *managed() const {
return m;
}
-#endif
quint64 rawValue() const {
return val;
@@ -198,6 +282,7 @@ struct Q_QML_EXPORT Value
static Value fromUInt32(uint i);
static Value fromString(String *s);
static Value fromObject(Object *o);
+ static Value fromManaged(Managed *o);
#ifndef QMLJS_LLVM_RUNTIME
static Value fromString(ExecutionContext *ctx, const QString &fromString);
@@ -215,37 +300,15 @@ struct Q_QML_EXPORT Value
bool toBoolean() const;
double toInteger() const;
double toNumber() const;
+ double toNumberImpl() const;
+ QString toQStringNoThrow() const;
QString toQString() const;
String *toString(ExecutionContext *ctx) const;
Object *toObject(ExecutionContext *ctx) const;
- inline bool isPrimitive() const { return !isObject(); }
-#if QT_POINTER_SIZE == 8
- inline bool integerCompatible() const {
- const quint64 mask = quint64(ConvertibleToInt) << 32;
- return (val & mask) == mask;
- }
- static inline bool integerCompatible(Value a, Value b) {
- const quint64 mask = quint64(ConvertibleToInt) << 32;
- return ((a.val & b.val) & mask) == mask;
- }
- static inline bool bothDouble(Value a, Value b) {
- const quint64 mask = quint64(NotDouble_Mask) << 32;
- return ((a.val | b.val) & mask) != mask;
- }
-#else
- inline bool integerCompatible() const {
- return (tag & ConvertibleToInt) == ConvertibleToInt;
- }
- static inline bool integerCompatible(Value a, Value b) {
- return ((a.tag & b.tag) & ConvertibleToInt) == ConvertibleToInt;
- }
- static inline bool bothDouble(Value a, Value b) {
- return ((a.tag | b.tag) & NotDouble_Mask) != NotDouble_Mask;
- }
-#endif
+ inline bool isPrimitive() const;
inline bool tryIntegerConversion() {
- bool b = isConvertibleToInt();
+ bool b = integerCompatible();
if (b)
tag = _Integer_Type;
return b;
@@ -267,10 +330,11 @@ struct Q_QML_EXPORT Value
uint asArrayIndex() const;
uint asArrayLength(bool *ok) const;
- Value property(ExecutionContext *ctx, String *name) const;
-
inline ExecutionEngine *engine() const;
+ ReturnedValue asReturnedValue() const { return val; }
+ static Value fromReturnedValue(ReturnedValue val) { Value v; v.val = val; return v; }
+
// Section 9.12
bool sameValue(Value other) const;
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 8d6f26ea57..de00a2264c 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -59,7 +59,23 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-QV4::Object *__qmljs_convert_to_object(QV4::ExecutionContext *ctx, const QV4::Value &value);
+inline bool Value::isString() const
+{
+ if (!isManaged())
+ return false;
+ return managed() && managed()->type == Managed::Type_String;
+}
+inline bool Value::isObject() const
+{
+ if (!isManaged())
+ return false;
+ return managed() && managed()->type != Managed::Type_String;
+}
+
+inline bool Value::isPrimitive() const
+{
+ return !isObject();
+}
inline Managed *Value::asManaged() const
{
@@ -83,9 +99,9 @@ inline Value Value::undefinedValue()
{
Value v;
#if QT_POINTER_SIZE == 8
- v.val = quint64(_Undefined_Type) << Tag_Shift;
+ v.val = quint64(Undefined_Type) << Tag_Shift;
#else
- v.tag = _Undefined_Type;
+ v.tag = Undefined_Type;
v.int_32 = 0;
#endif
return v;
@@ -106,7 +122,7 @@ inline Value Value::nullValue()
inline Value Value::emptyValue()
{
Value v;
- v.tag = Value::_Empty_Type;
+ v.tag = Value::Empty_Type;
v.uint_32 = 0;
return v;
}
@@ -123,7 +139,7 @@ inline Value Value::fromBoolean(Bool b)
inline Value Value::fromDouble(double d)
{
Value v;
- v.dbl = d;
+ v.setDouble(d);
return v;
}
@@ -142,7 +158,7 @@ inline Value Value::fromUInt32(uint i)
v.tag = _Integer_Type;
v.int_32 = (int)i;
} else {
- v.dbl = i;
+ v.setDouble(i);
}
return v;
}
@@ -151,10 +167,9 @@ inline Value Value::fromString(String *s)
{
Value v;
#if QT_POINTER_SIZE == 8
- v.val = (quint64)s;
- v.val |= quint64(_String_Type) << Tag_Shift;
+ v.s = s;
#else
- v.tag = _String_Type;
+ v.tag = Managed_Type;
v.s = s;
#endif
return v;
@@ -164,15 +179,62 @@ inline Value Value::fromObject(Object *o)
{
Value v;
#if QT_POINTER_SIZE == 8
- v.val = (quint64)o;
- v.val |= quint64(_Object_Type) << Tag_Shift;
+ v.o = o;
#else
- v.tag = _Object_Type;
+ v.tag = Managed_Type;
v.o = o;
#endif
return v;
}
+inline Value Value::fromManaged(Managed *m)
+{
+ if (!m)
+ return QV4::Value::undefinedValue();
+ Value v;
+#if QT_POINTER_SIZE == 8
+ v.m = m;
+#else
+ v.tag = Managed_Type;
+ v.m = m;
+#endif
+ return v;
+}
+
+inline double Value::toNumber() const
+{
+ if (integerCompatible())
+ return int_32;
+ if (isDouble())
+ return doubleValue();
+ return toNumberImpl();
+}
+
+inline int Value::toInt32() const
+{
+ if (integerCompatible())
+ return int_32;
+ double d;
+ if (isDouble())
+ d = doubleValue();
+ else
+ d = toNumberImpl();
+
+ const double D32 = 4294967296.0;
+ const double D31 = D32 / 2.0;
+
+ if ((d >= -D31 && d < D31))
+ return static_cast<int>(d);
+
+ return Value::toInt32(d);
+}
+
+inline unsigned int Value::toUInt32() const
+{
+ return (unsigned int)toInt32();
+}
+
+
inline bool Value::toBoolean() const
{
switch (type()) {
@@ -182,9 +244,9 @@ inline bool Value::toBoolean() const
case Value::Boolean_Type:
case Value::Integer_Type:
return (bool)int_32;
- case Value::String_Type:
- return stringValue()->toQString().length() > 0;
- case Value::Object_Type:
+ case Value::Managed_Type:
+ if (isString())
+ return stringValue()->toQString().length() > 0;
return true;
default: // double
return doubleValue() && !std::isnan(doubleValue());
@@ -197,8 +259,9 @@ inline uint Value::asArrayIndex() const
return (uint)int_32;
if (!isDouble())
return UINT_MAX;
- uint idx = (uint)dbl;
- if (idx != dbl)
+ double d = doubleValue();
+ uint idx = (uint)d;
+ if (idx != d)
return UINT_MAX;
return idx;
}
@@ -206,11 +269,12 @@ inline uint Value::asArrayIndex() const
inline uint Value::asArrayLength(bool *ok) const
{
*ok = true;
- if (isConvertibleToInt() && int_32 >= 0)
+ if (integerCompatible() && int_32 >= 0)
return (uint)int_32;
if (isDouble()) {
- uint idx = (uint)dbl;
- if ((double)idx != dbl) {
+ double d = doubleValue();
+ uint idx = (uint)d;
+ if (idx != d) {
*ok = false;
return UINT_MAX;
}
@@ -275,13 +339,8 @@ inline ErrorObject *Value::asErrorObject() const
return isObject() ? managed()->asErrorObject() : 0;
}
-// ###
-inline Value Managed::construct(CallData *d) {
- return vtbl->construct(this, d);
-}
-inline Value Managed::call(CallData *d) {
- return vtbl->call(this, d);
-}
+template<typename T>
+inline T *Value::as() const { Managed *m = isObject() ? managed() : 0; return m ? m->as<T>() : 0; }
struct Q_QML_PRIVATE_EXPORT PersistentValuePrivate
{
@@ -311,10 +370,13 @@ class Q_QML_EXPORT PersistentValue
{
public:
PersistentValue() : d(0) {}
+
PersistentValue(const Value &val);
+ PersistentValue(ReturnedValue val);
PersistentValue(const PersistentValue &other);
PersistentValue &operator=(const PersistentValue &other);
PersistentValue &operator=(const Value &other);
+ PersistentValue &operator =(const ReturnedValue &other);
~PersistentValue();
Value value() const {
diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp
index 574f612f74..ed3342aa58 100644
--- a/src/qml/jsruntime/qv4variantobject.cpp
+++ b/src/qml/jsruntime/qv4variantobject.cpp
@@ -152,15 +152,15 @@ void VariantPrototype::init(ExecutionEngine *engine)
defineDefaultProperty(engine, QStringLiteral("toString"), method_toString, 0);
}
-QV4::Value VariantPrototype::method_preserve(SimpleCallContext *ctx)
+QV4::ReturnedValue VariantPrototype::method_preserve(SimpleCallContext *ctx)
{
VariantObject *o = ctx->thisObject.as<QV4::VariantObject>();
if (o && o->isScarce())
o->node.remove();
- return Value::undefinedValue();
+ return Encode::undefined();
}
-QV4::Value VariantPrototype::method_destroy(SimpleCallContext *ctx)
+QV4::ReturnedValue VariantPrototype::method_destroy(SimpleCallContext *ctx)
{
VariantObject *o = ctx->thisObject.as<QV4::VariantObject>();
if (o) {
@@ -168,42 +168,42 @@ QV4::Value VariantPrototype::method_destroy(SimpleCallContext *ctx)
o->node.remove();
o->data = QVariant();
}
- return QV4::Value::undefinedValue();
+ return Encode::undefined();
}
-QV4::Value VariantPrototype::method_toString(SimpleCallContext *ctx)
+QV4::ReturnedValue VariantPrototype::method_toString(SimpleCallContext *ctx)
{
VariantObject *o = ctx->thisObject.as<QV4::VariantObject>();
if (!o)
- return Value::undefinedValue();
+ return Encode::undefined();
QString result = o->data.toString();
if (result.isEmpty() && !o->data.canConvert(QVariant::String))
result = QString::fromLatin1("QVariant(%0)").arg(QString::fromLatin1(o->data.typeName()));
- return Value::fromString(ctx->engine->newString(result));
+ return Value::fromString(ctx->engine->newString(result)).asReturnedValue();
}
-QV4::Value VariantPrototype::method_valueOf(SimpleCallContext *ctx)
+QV4::ReturnedValue VariantPrototype::method_valueOf(SimpleCallContext *ctx)
{
VariantObject *o = ctx->thisObject.as<QV4::VariantObject>();
if (o) {
QVariant v = o->data;
switch (v.type()) {
case QVariant::Invalid:
- return Value::undefinedValue();
+ return Encode::undefined();
case QVariant::String:
- return Value::fromString(ctx->engine->newString(v.toString()));
+ return Value::fromString(ctx->engine->newString(v.toString())).asReturnedValue();
case QVariant::Int:
- return Value::fromInt32(v.toInt());
+ return Encode(v.toInt());
case QVariant::Double:
case QVariant::UInt:
- return Value::fromDouble(v.toDouble());
+ return Encode(v.toDouble());
case QVariant::Bool:
- return Value::fromBoolean(v.toBool());
+ return Encode(v.toBool());
default:
break;
}
}
- return ctx->thisObject;
+ return ctx->thisObject.asReturnedValue();
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h
index eadf0ac4cf..60a48374b0 100644
--- a/src/qml/jsruntime/qv4variantobject_p.h
+++ b/src/qml/jsruntime/qv4variantobject_p.h
@@ -89,10 +89,10 @@ public:
void init(ExecutionEngine *engine);
- static Value method_preserve(SimpleCallContext *ctx);
- static Value method_destroy(SimpleCallContext *ctx);
- static Value method_toString(SimpleCallContext *ctx);
- static Value method_valueOf(SimpleCallContext *ctx);
+ static ReturnedValue method_preserve(SimpleCallContext *ctx);
+ static ReturnedValue method_destroy(SimpleCallContext *ctx);
+ static ReturnedValue method_toString(SimpleCallContext *ctx);
+ static ReturnedValue method_valueOf(SimpleCallContext *ctx);
};
}
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 92b0c75e8c..c342470015 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -217,9 +217,10 @@ static inline QV4::Value *getValueRef(QV4::ExecutionContext *context,
# define VALUE(param) *getValueRef(context, stack, param, stackSize)
# define VALUEPTR(param) getValueRef(context, stack, param, stackSize)
#endif
+#define STOREVALUE(param, value) VALUE(param) = QV4::Value::fromReturnedValue((value))
-QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
- QV4::Value *stack, unsigned stackSize
+QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *&code,
+ QV4::Value *stack, unsigned stackSize
#ifdef MOTH_THREADED_INTERPRETER
, void ***storeJumpTable
#endif
@@ -237,7 +238,7 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
};
#undef MOTH_INSTR_ADDR
*storeJumpTable = jumpTable;
- return QV4::Value::undefinedValue();
+ return QV4::Value::undefinedValue().asReturnedValue();
}
#endif
@@ -257,6 +258,10 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
VALUE(instr.result) = VALUE(instr.source);
MOTH_END_INSTR(MoveTemp)
+ MOTH_BEGIN_INSTR(SwapTemps)
+ qSwap(VALUE(instr.left), VALUE(instr.right));
+ MOTH_END_INSTR(MoveTemp)
+
MOTH_BEGIN_INSTR(LoadValue)
// TRACE(value, "%s", instr.value.toString(context)->toQString().toUtf8().constData());
VALUE(instr.result) = VALUE(instr.value);
@@ -273,21 +278,21 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(LoadRegExp)
MOTH_BEGIN_INSTR(LoadClosure)
- __qmljs_init_closure(context, VALUEPTR(instr.result), instr.value);
+ STOREVALUE(instr.result, __qmljs_init_closure(context, instr.value));
MOTH_END_INSTR(LoadClosure)
MOTH_BEGIN_INSTR(LoadName)
- TRACE(inline, "property name = %s", instr.name->toQString().toUtf8().constData());
- __qmljs_get_activation_property(context, VALUEPTR(instr.result), runtimeStrings[instr.name]);
+ TRACE(inline, "property name = %s", runtimeStrings[instr.name]->toQString().toUtf8().constData());
+ STOREVALUE(instr.result, __qmljs_get_activation_property(context, runtimeStrings[instr.name]));
MOTH_END_INSTR(LoadName)
MOTH_BEGIN_INSTR(StoreName)
- TRACE(inline, "property name = %s", instr.name->toQString().toUtf8().constData());
+ TRACE(inline, "property name = %s", runtimeStrings[instr.name]->toQString().toUtf8().constData());
__qmljs_set_activation_property(context, runtimeStrings[instr.name], VALUEPTR(instr.source));
MOTH_END_INSTR(StoreName)
MOTH_BEGIN_INSTR(LoadElement)
- __qmljs_get_element(context, VALUEPTR(instr.result), VALUEPTR(instr.base), VALUEPTR(instr.index));
+ STOREVALUE(instr.result, __qmljs_get_element(context, VALUEPTR(instr.base), VALUEPTR(instr.index)));
MOTH_END_INSTR(LoadElement)
MOTH_BEGIN_INSTR(StoreElement)
@@ -295,7 +300,7 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(StoreElement)
MOTH_BEGIN_INSTR(LoadProperty)
- __qmljs_get_property(context, VALUEPTR(instr.result), VALUEPTR(instr.base), runtimeStrings[instr.name]);
+ STOREVALUE(instr.result, __qmljs_get_property(context, VALUEPTR(instr.base), runtimeStrings[instr.name]));
MOTH_END_INSTR(LoadProperty)
MOTH_BEGIN_INSTR(StoreProperty)
@@ -310,7 +315,7 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(Push)
MOTH_BEGIN_INSTR(CallValue)
-#ifdef DO_TRACE_INSTR
+#if 0 //def DO_TRACE_INSTR
if (Debugging::Debugger *debugger = context->engine->debugger) {
if (QV4::FunctionObject *o = (VALUE(instr.dest)).asFunctionObject()) {
if (Debugging::FunctionDebugInfo *info = debugger->debugInfo(o)) {
@@ -322,39 +327,39 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
#endif // DO_TRACE_INSTR
Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = 0;
+ callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = QV4::Value::undefinedValue();
- __qmljs_call_value(context, VALUEPTR(instr.result), VALUEPTR(instr.dest), callData);
+ STOREVALUE(instr.result, __qmljs_call_value(context, VALUEPTR(instr.dest), callData));
MOTH_END_INSTR(CallValue)
MOTH_BEGIN_INSTR(CallProperty)
- TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(instr.name->toQString()), instr.args, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
+ TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = 0;
+ callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = VALUE(instr.base);
- __qmljs_call_property(context, QV4::ValueRef::fromRawValue(VALUEPTR(instr.result)), runtimeStrings[instr.name], callData);
+ STOREVALUE(instr.result, __qmljs_call_property(context, runtimeStrings[instr.name], callData));
MOTH_END_INSTR(CallProperty)
MOTH_BEGIN_INSTR(CallElement)
Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = 0;
+ callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = VALUE(instr.base);
- __qmljs_call_element(context, VALUEPTR(instr.result), VALUEPTR(instr.index), callData);
+ STOREVALUE(instr.result, __qmljs_call_element(context, VALUEPTR(instr.index), callData));
MOTH_END_INSTR(CallElement)
MOTH_BEGIN_INSTR(CallActivationProperty)
TRACE(args, "starting at %d, length %d", instr.args, instr.argc);
Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = 0;
+ callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = QV4::Value::undefinedValue();
- __qmljs_call_activation_property(context, VALUEPTR(instr.result), runtimeStrings[instr.name], callData);
+ STOREVALUE(instr.result, __qmljs_call_activation_property(context, runtimeStrings[instr.name], callData));
MOTH_END_INSTR(CallActivationProperty)
MOTH_BEGIN_INSTR(CallBuiltinThrow)
@@ -370,7 +375,7 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
context->interpreterInstructionPointer = &code;
} catch (QV4::Exception &ex) {
ex.accept(context);
- VALUE(instr.exceptionVar) = ex.value();
+ STOREVALUE(instr.exceptionVar, ex.value());
try {
QV4::ExecutionContext *catchContext = __qmljs_builtin_push_catch_scope(runtimeStrings[instr.exceptionVarName], VALUEPTR(instr.exceptionVar), context);
const uchar *catchCode = ((uchar *)&instr.catchOffset) + instr.catchOffset;
@@ -380,7 +385,7 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
context = __qmljs_builtin_pop_scope(catchContext);
} catch (QV4::Exception &ex) {
ex.accept(context);
- VALUE(instr.exceptionVar) = ex.value();
+ STOREVALUE(instr.exceptionVar, ex.value());
const uchar *catchCode = ((uchar *)&instr.catchOffset) + instr.catchOffset;
run(context, catchCode, stack, stackSize);
code = catchCode;
@@ -390,7 +395,7 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(EnterTry)
MOTH_BEGIN_INSTR(CallBuiltinFinishTry)
- return QV4::Value();
+ return QV4::ReturnedValue(0);
MOTH_END_INSTR(CallBuiltinFinishTry)
MOTH_BEGIN_INSTR(CallBuiltinPushScope)
@@ -402,71 +407,39 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(CallBuiltinPopScope)
MOTH_BEGIN_INSTR(CallBuiltinForeachIteratorObject)
- __qmljs_foreach_iterator_object(context, VALUEPTR(instr.result), VALUEPTR(instr.arg));
+ STOREVALUE(instr.result, __qmljs_foreach_iterator_object(context, VALUEPTR(instr.arg)));
MOTH_END_INSTR(CallBuiltinForeachIteratorObject)
MOTH_BEGIN_INSTR(CallBuiltinForeachNextPropertyName)
- __qmljs_foreach_next_property_name(VALUEPTR(instr.result), VALUEPTR(instr.arg));
+ STOREVALUE(instr.result, __qmljs_foreach_next_property_name(VALUEPTR(instr.arg)));
MOTH_END_INSTR(CallBuiltinForeachNextPropertyName)
MOTH_BEGIN_INSTR(CallBuiltinDeleteMember)
- __qmljs_delete_member(context, VALUEPTR(instr.result), VALUEPTR(instr.base), runtimeStrings[instr.member]);
+ STOREVALUE(instr.result, __qmljs_delete_member(context, VALUEPTR(instr.base), runtimeStrings[instr.member]));
MOTH_END_INSTR(CallBuiltinDeleteMember)
MOTH_BEGIN_INSTR(CallBuiltinDeleteSubscript)
- __qmljs_delete_subscript(context, VALUEPTR(instr.result), VALUEPTR(instr.base), VALUEPTR(instr.index));
+ STOREVALUE(instr.result, __qmljs_delete_subscript(context, VALUEPTR(instr.base), VALUEPTR(instr.index)));
MOTH_END_INSTR(CallBuiltinDeleteSubscript)
MOTH_BEGIN_INSTR(CallBuiltinDeleteName)
- __qmljs_delete_name(context, VALUEPTR(instr.result), runtimeStrings[instr.name]);
+ STOREVALUE(instr.result, __qmljs_delete_name(context, runtimeStrings[instr.name]));
MOTH_END_INSTR(CallBuiltinDeleteName)
MOTH_BEGIN_INSTR(CallBuiltinTypeofMember)
- __qmljs_builtin_typeof_member(context, VALUEPTR(instr.result), VALUEPTR(instr.base), runtimeStrings[instr.member]);
+ STOREVALUE(instr.result, __qmljs_builtin_typeof_member(context, VALUEPTR(instr.base), runtimeStrings[instr.member]));
MOTH_END_INSTR(CallBuiltinTypeofMember)
MOTH_BEGIN_INSTR(CallBuiltinTypeofSubscript)
- __qmljs_builtin_typeof_element(context, VALUEPTR(instr.result), VALUEPTR(instr.base), VALUEPTR(instr.index));
+ STOREVALUE(instr.result, __qmljs_builtin_typeof_element(context, VALUEPTR(instr.base), VALUEPTR(instr.index)));
MOTH_END_INSTR(CallBuiltinTypeofSubscript)
MOTH_BEGIN_INSTR(CallBuiltinTypeofName)
- __qmljs_builtin_typeof_name(context, VALUEPTR(instr.result), runtimeStrings[instr.name]);
+ STOREVALUE(instr.result, __qmljs_builtin_typeof_name(context, runtimeStrings[instr.name]));
MOTH_END_INSTR(CallBuiltinTypeofName)
MOTH_BEGIN_INSTR(CallBuiltinTypeofValue)
- __qmljs_builtin_typeof(context, VALUEPTR(instr.result), VALUEPTR(instr.value));
- MOTH_END_INSTR(CallBuiltinTypeofValue)
-
- MOTH_BEGIN_INSTR(CallBuiltinPostIncMember)
- __qmljs_builtin_post_increment_member(context, VALUEPTR(instr.result), VALUEPTR(instr.base), runtimeStrings[instr.member]);
- MOTH_END_INSTR(CallBuiltinTypeofMember)
-
- MOTH_BEGIN_INSTR(CallBuiltinPostIncSubscript)
- __qmljs_builtin_post_increment_element(context, VALUEPTR(instr.result), VALUEPTR(instr.base), VALUEPTR(instr.index));
- MOTH_END_INSTR(CallBuiltinTypeofSubscript)
-
- MOTH_BEGIN_INSTR(CallBuiltinPostIncName)
- __qmljs_builtin_post_increment_name(context, VALUEPTR(instr.result), runtimeStrings[instr.name]);
- MOTH_END_INSTR(CallBuiltinTypeofName)
-
- MOTH_BEGIN_INSTR(CallBuiltinPostIncValue)
- __qmljs_builtin_post_increment(VALUEPTR(instr.result), VALUEPTR(instr.value));
- MOTH_END_INSTR(CallBuiltinTypeofValue)
-
- MOTH_BEGIN_INSTR(CallBuiltinPostDecMember)
- __qmljs_builtin_post_decrement_member(context, VALUEPTR(instr.result), VALUEPTR(instr.base), runtimeStrings[instr.member]);
- MOTH_END_INSTR(CallBuiltinTypeofMember)
-
- MOTH_BEGIN_INSTR(CallBuiltinPostDecSubscript)
- __qmljs_builtin_post_decrement_element(context, VALUEPTR(instr.result), VALUEPTR(instr.base), VALUEPTR(instr.index));
- MOTH_END_INSTR(CallBuiltinTypeofSubscript)
-
- MOTH_BEGIN_INSTR(CallBuiltinPostDecName)
- __qmljs_builtin_post_decrement_name(context, VALUEPTR(instr.result), runtimeStrings[instr.name]);
- MOTH_END_INSTR(CallBuiltinTypeofName)
-
- MOTH_BEGIN_INSTR(CallBuiltinPostDecValue)
- __qmljs_builtin_post_decrement(VALUEPTR(instr.result), VALUEPTR(instr.value));
+ STOREVALUE(instr.result, __qmljs_builtin_typeof(context, VALUEPTR(instr.value)));
MOTH_END_INSTR(CallBuiltinTypeofValue)
MOTH_BEGIN_INSTR(CallBuiltinDeclareVar)
@@ -484,44 +457,44 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_BEGIN_INSTR(CallBuiltinDefineArray)
Q_ASSERT(instr.args + instr.argc <= stackSize);
QV4::Value *args = stack + instr.args;
- __qmljs_builtin_define_array(context, VALUEPTR(instr.result), args, instr.argc);
+ STOREVALUE(instr.result, __qmljs_builtin_define_array(context, args, instr.argc));
MOTH_END_INSTR(CallBuiltinDefineArray)
MOTH_BEGIN_INSTR(CallBuiltinDefineObjectLiteral)
QV4::Value *args = stack + instr.args;
- __qmljs_builtin_define_object_literal(context, VALUEPTR(instr.result), args, instr.internalClassId);
+ STOREVALUE(instr.result, __qmljs_builtin_define_object_literal(context, args, instr.internalClassId));
MOTH_END_INSTR(CallBuiltinDefineObjectLiteral)
MOTH_BEGIN_INSTR(CallBuiltinSetupArgumentsObject)
- __qmljs_builtin_setup_arguments_object(context, VALUEPTR(instr.result));
+ STOREVALUE(instr.result, __qmljs_builtin_setup_arguments_object(context));
MOTH_END_INSTR(CallBuiltinSetupArgumentsObject)
MOTH_BEGIN_INSTR(CreateValue)
Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = 0;
+ callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = QV4::Value::undefinedValue();
- __qmljs_construct_value(context, VALUEPTR(instr.result), VALUEPTR(instr.func), callData);
+ STOREVALUE(instr.result, __qmljs_construct_value(context, VALUEPTR(instr.func), callData));
MOTH_END_INSTR(CreateValue)
MOTH_BEGIN_INSTR(CreateProperty)
Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = 0;
+ callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = QV4::Value::undefinedValue();
- __qmljs_construct_property(context, VALUEPTR(instr.result), VALUEPTR(instr.base), runtimeStrings[instr.name], callData);
+ STOREVALUE(instr.result, __qmljs_construct_property(context, VALUEPTR(instr.base), runtimeStrings[instr.name], callData));
MOTH_END_INSTR(CreateProperty)
MOTH_BEGIN_INSTR(CreateActivationProperty)
- TRACE(inline, "property name = %s, args = %d, argc = %d", instr.name->toQString().toUtf8().constData(), instr.args, instr.argc);
+ TRACE(inline, "property name = %s, args = %d, argc = %d", runtimeStrings[instr.name]->toQString().toUtf8().constData(), instr.args, instr.argc);
Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
- callData->tag = 0;
+ callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = QV4::Value::undefinedValue();
- __qmljs_construct_activation_property(context, VALUEPTR(instr.result), runtimeStrings[instr.name], callData);
+ STOREVALUE(instr.result, __qmljs_construct_activation_property(context, runtimeStrings[instr.name], callData));
MOTH_END_INSTR(CreateActivationProperty)
MOTH_BEGIN_INSTR(Jump)
@@ -536,15 +509,15 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(CJump)
MOTH_BEGIN_INSTR(Unop)
- instr.alu(QV4::ValueRef::fromRawValue(VALUEPTR(instr.result)), QV4::ValueRef::fromRawValue(VALUEPTR(instr.source)));
+ STOREVALUE(instr.result, instr.alu(VALUEPTR(instr.source)));
MOTH_END_INSTR(Unop)
MOTH_BEGIN_INSTR(Binop)
- instr.alu(VALUEPTR(instr.result), VALUEPTR(instr.lhs), VALUEPTR(instr.rhs));
+ STOREVALUE(instr.result, instr.alu(VALUEPTR(instr.lhs), VALUEPTR(instr.rhs)));
MOTH_END_INSTR(Binop)
MOTH_BEGIN_INSTR(BinopContext)
- instr.alu(context, VALUEPTR(instr.result), VALUEPTR(instr.lhs), VALUEPTR(instr.rhs));
+ STOREVALUE(instr.result, instr.alu(context, VALUEPTR(instr.lhs), VALUEPTR(instr.rhs)));
MOTH_END_INSTR(BinopContext)
MOTH_BEGIN_INSTR(AddNumberParams)
@@ -578,7 +551,7 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
context->engine->stackPop(stackSize);
QV4::Value &result = VALUE(instr.result);
// TRACE(Ret, "returning value %s", result.toString(context)->toQString().toUtf8().constData());
- return result;
+ return result.asReturnedValue();
MOTH_END_INSTR(Ret)
MOTH_BEGIN_INSTR(LoadThis)
@@ -600,7 +573,7 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(InplaceMemberOp)
MOTH_BEGIN_INSTR(InplaceNameOp)
- TRACE(name, "%s", instr.name->toQString().toUtf8().constData());
+ TRACE(name, "%s", runtimeStrings[instr.name]->toQString().toUtf8().constData());
instr.alu(context, runtimeStrings[instr.name], VALUEPTR(instr.source));
MOTH_END_INSTR(InplaceNameOp)
@@ -628,7 +601,7 @@ void **VME::instructionJumpTable()
}
#endif
-QV4::Value VME::exec(QV4::ExecutionContext *ctxt, const uchar *code)
+QV4::ReturnedValue VME::exec(QV4::ExecutionContext *ctxt, const uchar *code)
{
VME vme;
return vme.run(ctxt, code);
diff --git a/src/qml/jsruntime/qv4vme_moth_p.h b/src/qml/jsruntime/qv4vme_moth_p.h
index aedf865033..04c7f933ab 100644
--- a/src/qml/jsruntime/qv4vme_moth_p.h
+++ b/src/qml/jsruntime/qv4vme_moth_p.h
@@ -53,14 +53,14 @@ namespace Moth {
class VME
{
public:
- static QV4::Value exec(QV4::ExecutionContext *, const uchar *);
+ static QV4::ReturnedValue exec(QV4::ExecutionContext *, const uchar *);
#ifdef MOTH_THREADED_INTERPRETER
static void **instructionJumpTable();
#endif
private:
- QV4::Value run(QV4::ExecutionContext *, const uchar *&code,
+ QV4::ReturnedValue run(QV4::ExecutionContext *, const uchar *&code,
QV4::Value *stack = 0, unsigned stackSize = 0
#ifdef MOTH_THREADED_INTERPRETER
, void ***storeJumpTable = 0