diff options
Diffstat (limited to 'src/qml/jsruntime/qv4runtime.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 575 |
1 files changed, 442 insertions, 133 deletions
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 60136a9bd9..0a71f0000a 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -252,14 +252,14 @@ void RuntimeHelpers::numberToString(QString *result, double num, int radix) result->append(QLatin1Char('+')); result->append(QString::number(decpt - 1)); } else if (decpt <= 0) { - result->prepend(QString::fromLatin1("0.%1").arg(QString().fill(zero, -decpt))); + result->prepend(QLatin1String("0.") + QString(-decpt, zero)); } else if (decpt < result->length()) { result->insert(decpt, dot); } else { - result->append(QString().fill(zero, decpt - result->length())); + result->append(QString(decpt - result->length(), zero)); } - if (sign) + if (sign && num) result->prepend(QLatin1Char('-')); return; @@ -298,14 +298,14 @@ void RuntimeHelpers::numberToString(QString *result, double num, int radix) result->prepend(QLatin1Char('-')); } -ReturnedValue Runtime::closure(ExecutionEngine *engine, int functionId) +ReturnedValue Runtime::method_closure(ExecutionEngine *engine, int functionId) { QV4::Function *clos = engine->current->compilationUnit->runtimeFunctions[functionId]; Q_ASSERT(clos); return FunctionObject::createScriptFunction(engine->currentContext, clos)->asReturnedValue(); } -ReturnedValue Runtime::deleteElement(ExecutionEngine *engine, const Value &base, const Value &index) +ReturnedValue Runtime::method_deleteElement(ExecutionEngine *engine, const Value &base, const Value &index) { Scope scope(engine); ScopedObject o(scope, base); @@ -317,17 +317,17 @@ ReturnedValue Runtime::deleteElement(ExecutionEngine *engine, const Value &base, } ScopedString name(scope, index.toString(engine)); - return Runtime::deleteMemberString(engine, base, name); + return method_deleteMemberString(engine, base, name); } -ReturnedValue Runtime::deleteMember(ExecutionEngine *engine, const Value &base, int nameIndex) +ReturnedValue Runtime::method_deleteMember(ExecutionEngine *engine, const Value &base, int nameIndex) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); - return deleteMemberString(engine, base, name); + return method_deleteMemberString(engine, base, name); } -ReturnedValue Runtime::deleteMemberString(ExecutionEngine *engine, const Value &base, String *name) +ReturnedValue Runtime::method_deleteMemberString(ExecutionEngine *engine, const Value &base, String *name) { Scope scope(engine); ScopedObject obj(scope, base.toObject(engine)); @@ -336,14 +336,14 @@ ReturnedValue Runtime::deleteMemberString(ExecutionEngine *engine, const Value & return Encode(obj->deleteProperty(name)); } -ReturnedValue Runtime::deleteName(ExecutionEngine *engine, int nameIndex) +ReturnedValue Runtime::method_deleteName(ExecutionEngine *engine, int nameIndex) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); return Encode(engine->currentContext->deleteProperty(name)); } -QV4::ReturnedValue Runtime::instanceof(ExecutionEngine *engine, const Value &left, const Value &right) +QV4::ReturnedValue Runtime::method_instanceof(ExecutionEngine *engine, const Value &left, const Value &right) { Scope scope(engine); ScopedFunctionObject f(scope, right.as<FunctionObject>()); @@ -373,7 +373,7 @@ QV4::ReturnedValue Runtime::instanceof(ExecutionEngine *engine, const Value &lef return Encode(false); } -QV4::ReturnedValue Runtime::in(ExecutionEngine *engine, const Value &left, const Value &right) +QV4::ReturnedValue Runtime::method_in(ExecutionEngine *engine, const Value &left, const Value &right) { if (!right.isObject()) return engine->throwTypeError(); @@ -387,7 +387,7 @@ QV4::ReturnedValue Runtime::in(ExecutionEngine *engine, const Value &left, const double RuntimeHelpers::stringToNumber(const QString &string) { - QString s = string.trimmed(); + const QStringRef s = QStringRef(&string).trimmed(); if (s.startsWith(QLatin1String("0x")) || s.startsWith(QLatin1String("0X"))) return s.toLong(0, 16); bool ok; @@ -438,9 +438,9 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(const Object *object, int typeH ScopedValue conv(scope, object->get(meth1)); if (FunctionObject *o = conv->as<FunctionObject>()) { - ScopedValue r(scope, o->call(callData)); - if (r->isPrimitive()) - return r->asReturnedValue(); + o->call(scope, callData); + if (scope.result.isPrimitive()) + return scope.result.asReturnedValue(); } if (engine->hasException) @@ -448,9 +448,9 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(const Object *object, int typeH conv = object->get(meth2); if (FunctionObject *o = conv->as<FunctionObject>()) { - ScopedValue r(scope, o->call(callData)); - if (r->isPrimitive()) - return r->asReturnedValue(); + o->call(scope, callData); + if (scope.result.isPrimitive()) + return scope.result.asReturnedValue(); } return engine->throwTypeError(); @@ -562,7 +562,7 @@ QV4::ReturnedValue RuntimeHelpers::addHelper(ExecutionEngine *engine, const Valu return Encode(x + y); } -QV4::ReturnedValue Runtime::addString(ExecutionEngine *engine, const Value &left, const Value &right) +QV4::ReturnedValue Runtime::method_addString(ExecutionEngine *engine, const Value &left, const Value &right) { Q_ASSERT(left.isString() || right.isString()); @@ -593,7 +593,7 @@ QV4::ReturnedValue Runtime::addString(ExecutionEngine *engine, const Value &left return (mm->alloc<String>(mm, pleft->stringValue()->d(), pright->stringValue()->d()))->asReturnedValue(); } -void Runtime::setProperty(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value) +void Runtime::method_setProperty(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); @@ -603,7 +603,7 @@ void Runtime::setProperty(ExecutionEngine *engine, const Value &object, int name o->put(name, value); } -ReturnedValue Runtime::getElement(ExecutionEngine *engine, const Value &object, const Value &index) +ReturnedValue Runtime::method_getElement(ExecutionEngine *engine, const Value &object, const Value &index) { Scope scope(engine); uint idx = index.asArrayIndex(); @@ -646,7 +646,7 @@ ReturnedValue Runtime::getElement(ExecutionEngine *engine, const Value &object, return o->get(name); } -void Runtime::setElement(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value) +void Runtime::method_setElement(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value) { Scope scope(engine); ScopedObject o(scope, object.toObject(engine)); @@ -670,7 +670,7 @@ void Runtime::setElement(ExecutionEngine *engine, const Value &object, const Val o->put(name, value); } -ReturnedValue Runtime::foreachIterator(ExecutionEngine *engine, const Value &in) +ReturnedValue Runtime::method_foreachIterator(ExecutionEngine *engine, const Value &in) { Scope scope(engine); ScopedObject o(scope, (Object *)0); @@ -679,7 +679,7 @@ ReturnedValue Runtime::foreachIterator(ExecutionEngine *engine, const Value &in) return engine->newForEachIteratorObject(o)->asReturnedValue(); } -ReturnedValue Runtime::foreachNextPropertyName(const Value &foreach_iterator) +ReturnedValue Runtime::method_foreachNextPropertyName(const Value &foreach_iterator) { Q_ASSERT(foreach_iterator.isObject()); @@ -690,14 +690,14 @@ ReturnedValue Runtime::foreachNextPropertyName(const Value &foreach_iterator) } -void Runtime::setActivationProperty(ExecutionEngine *engine, int nameIndex, const Value &value) +void Runtime::method_setActivationProperty(ExecutionEngine *engine, int nameIndex, const Value &value) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); engine->currentContext->setProperty(name, value); } -ReturnedValue Runtime::getProperty(ExecutionEngine *engine, const Value &object, int nameIndex) +ReturnedValue Runtime::method_getProperty(ExecutionEngine *engine, const Value &object, int nameIndex) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); @@ -717,7 +717,7 @@ ReturnedValue Runtime::getProperty(ExecutionEngine *engine, const Value &object, return o->get(name); } -ReturnedValue Runtime::getActivationProperty(ExecutionEngine *engine, int nameIndex) +ReturnedValue Runtime::method_getActivationProperty(ExecutionEngine *engine, int nameIndex) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); @@ -743,9 +743,9 @@ uint RuntimeHelpers::equalHelper(const Value &x, const Value &y) double dx = RuntimeHelpers::toNumber(x); return dx == y.asDouble(); } else if (x.isBoolean()) { - return Runtime::compareEqual(Primitive::fromDouble((double) x.booleanValue()), y); + return Runtime::method_compareEqual(Primitive::fromDouble((double) x.booleanValue()), y); } else if (y.isBoolean()) { - return Runtime::compareEqual(x, Primitive::fromDouble((double) y.booleanValue())); + return Runtime::method_compareEqual(x, Primitive::fromDouble((double) y.booleanValue())); } else { #ifdef V4_BOOTSTRAP Q_UNIMPLEMENTED(); @@ -753,11 +753,11 @@ uint RuntimeHelpers::equalHelper(const Value &x, const Value &y) if ((x.isNumber() || x.isString()) && y.isObject()) { Scope scope(y.objectValue()->engine()); ScopedValue py(scope, RuntimeHelpers::toPrimitive(y, PREFERREDTYPE_HINT)); - return Runtime::compareEqual(x, py); + return Runtime::method_compareEqual(x, py); } else if (x.isObject() && (y.isNumber() || y.isString())) { Scope scope(x.objectValue()->engine()); ScopedValue px(scope, RuntimeHelpers::toPrimitive(x, PREFERREDTYPE_HINT)); - return Runtime::compareEqual(px, y); + return Runtime::method_compareEqual(px, y); } #endif } @@ -780,7 +780,7 @@ Bool RuntimeHelpers::strictEqual(const Value &x, const Value &y) return false; } -QV4::Bool Runtime::compareGreaterThan(const Value &l, const Value &r) +QV4::Bool Runtime::method_compareGreaterThan(const Value &l, const Value &r) { TRACE2(l, r); if (l.isInteger() && r.isInteger()) @@ -804,7 +804,7 @@ QV4::Bool Runtime::compareGreaterThan(const Value &l, const Value &r) QV4::Scope scope(e); QV4::ScopedValue pl(scope, RuntimeHelpers::toPrimitive(l, QV4::NUMBER_HINT)); QV4::ScopedValue pr(scope, RuntimeHelpers::toPrimitive(r, QV4::NUMBER_HINT)); - return Runtime::compareGreaterThan(pl, pr); + return Runtime::method_compareGreaterThan(pl, pr); #endif } @@ -813,7 +813,7 @@ QV4::Bool Runtime::compareGreaterThan(const Value &l, const Value &r) return dl > dr; } -QV4::Bool Runtime::compareLessThan(const Value &l, const Value &r) +QV4::Bool Runtime::method_compareLessThan(const Value &l, const Value &r) { TRACE2(l, r); if (l.isInteger() && r.isInteger()) @@ -837,7 +837,7 @@ QV4::Bool Runtime::compareLessThan(const Value &l, const Value &r) QV4::Scope scope(e); QV4::ScopedValue pl(scope, RuntimeHelpers::toPrimitive(l, QV4::NUMBER_HINT)); QV4::ScopedValue pr(scope, RuntimeHelpers::toPrimitive(r, QV4::NUMBER_HINT)); - return Runtime::compareLessThan(pl, pr); + return Runtime::method_compareLessThan(pl, pr); #endif } @@ -846,7 +846,7 @@ QV4::Bool Runtime::compareLessThan(const Value &l, const Value &r) return dl < dr; } -QV4::Bool Runtime::compareGreaterEqual(const Value &l, const Value &r) +QV4::Bool Runtime::method_compareGreaterEqual(const Value &l, const Value &r) { TRACE2(l, r); if (l.isInteger() && r.isInteger()) @@ -870,7 +870,7 @@ QV4::Bool Runtime::compareGreaterEqual(const Value &l, const Value &r) QV4::Scope scope(e); QV4::ScopedValue pl(scope, RuntimeHelpers::toPrimitive(l, QV4::NUMBER_HINT)); QV4::ScopedValue pr(scope, RuntimeHelpers::toPrimitive(r, QV4::NUMBER_HINT)); - return Runtime::compareGreaterEqual(pl, pr); + return Runtime::method_compareGreaterEqual(pl, pr); #endif } @@ -879,7 +879,7 @@ QV4::Bool Runtime::compareGreaterEqual(const Value &l, const Value &r) return dl >= dr; } -QV4::Bool Runtime::compareLessEqual(const Value &l, const Value &r) +QV4::Bool Runtime::method_compareLessEqual(const Value &l, const Value &r) { TRACE2(l, r); if (l.isInteger() && r.isInteger()) @@ -903,7 +903,7 @@ QV4::Bool Runtime::compareLessEqual(const Value &l, const Value &r) QV4::Scope scope(e); QV4::ScopedValue pl(scope, RuntimeHelpers::toPrimitive(l, QV4::NUMBER_HINT)); QV4::ScopedValue pr(scope, RuntimeHelpers::toPrimitive(r, QV4::NUMBER_HINT)); - return Runtime::compareLessEqual(pl, pr); + return Runtime::method_compareLessEqual(pl, pr); #endif } @@ -913,26 +913,26 @@ QV4::Bool Runtime::compareLessEqual(const Value &l, const Value &r) } #ifndef V4_BOOTSTRAP -Bool Runtime::compareInstanceof(ExecutionEngine *engine, const Value &left, const Value &right) +Bool Runtime::method_compareInstanceof(ExecutionEngine *engine, const Value &left, const Value &right) { TRACE2(left, right); Scope scope(engine); - ScopedValue v(scope, Runtime::instanceof(engine, left, right)); + ScopedValue v(scope, method_instanceof(engine, left, right)); return v->booleanValue(); } -uint Runtime::compareIn(ExecutionEngine *engine, const Value &left, const Value &right) +uint Runtime::method_compareIn(ExecutionEngine *engine, const Value &left, const Value &right) { TRACE2(left, right); Scope scope(engine); - ScopedValue v(scope, Runtime::in(engine, left, right)); + ScopedValue v(scope, method_in(engine, left, right)); return v->booleanValue(); } -ReturnedValue Runtime::callGlobalLookup(ExecutionEngine *engine, uint index, CallData *callData) +ReturnedValue Runtime::method_callGlobalLookup(ExecutionEngine *engine, uint index, CallData *callData) { Scope scope(engine); Q_ASSERT(callData->thisObject.isUndefined()); @@ -943,14 +943,17 @@ ReturnedValue Runtime::callGlobalLookup(ExecutionEngine *engine, uint index, Cal return engine->throwTypeError(); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[l->nameIndex]); - if (o->d() == scope.engine->evalFunction()->d() && name->equals(scope.engine->id_eval())) - return static_cast<EvalFunction *>(o.getPointer())->evalCall(callData, true); + if (o->d() == scope.engine->evalFunction()->d() && name->equals(scope.engine->id_eval())) { + static_cast<EvalFunction *>(o.getPointer())->evalCall(scope, callData, true); + } else { + o->call(scope, callData); + } - return o->call(callData); + return scope.result.asReturnedValue(); } -ReturnedValue Runtime::callActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData) +ReturnedValue Runtime::method_callActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData) { Q_ASSERT(callData->thisObject.isUndefined()); Scope scope(engine); @@ -974,36 +977,41 @@ ReturnedValue Runtime::callActivationProperty(ExecutionEngine *engine, int nameI } if (o->d() == scope.engine->evalFunction()->d() && name->equals(scope.engine->id_eval())) { - return static_cast<EvalFunction *>(o)->evalCall(callData, true); + static_cast<EvalFunction *>(o)->evalCall(scope, callData, true); + } else { + o->call(scope, callData); } - return o->call(callData); + return scope.result.asReturnedValue(); } -ReturnedValue Runtime::callQmlScopeObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData) +ReturnedValue Runtime::method_callQmlScopeObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData) { Scope scope(engine); - ScopedFunctionObject o(scope, getQmlScopeObjectProperty(engine, callData->thisObject, propertyIndex)); + ScopedFunctionObject o(scope, method_getQmlScopeObjectProperty(engine, callData->thisObject, propertyIndex, /*captureRequired*/true)); if (!o) { QString error = QStringLiteral("Property '%1' of scope object is not a function").arg(propertyIndex); return engine->throwTypeError(error); } - return o->call(callData); + + o->call(scope, callData); + return scope.result.asReturnedValue(); } -ReturnedValue Runtime::callQmlContextObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData) +ReturnedValue Runtime::method_callQmlContextObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData) { Scope scope(engine); - ScopedFunctionObject o(scope, getQmlContextObjectProperty(engine, callData->thisObject, propertyIndex)); + ScopedFunctionObject o(scope, method_getQmlContextObjectProperty(engine, callData->thisObject, propertyIndex, /*captureRequired*/true)); if (!o) { QString error = QStringLiteral("Property '%1' of context object is not a function").arg(propertyIndex); return engine->throwTypeError(error); } - return o->call(callData); + o->call(scope, callData); + return scope.result.asReturnedValue(); } -ReturnedValue Runtime::callProperty(ExecutionEngine *engine, int nameIndex, CallData *callData) +ReturnedValue Runtime::method_callProperty(ExecutionEngine *engine, int nameIndex, CallData *callData) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); @@ -1022,26 +1030,31 @@ ReturnedValue Runtime::callProperty(ExecutionEngine *engine, int nameIndex, Call } ScopedFunctionObject o(scope, baseObject->get(name)); - if (!o) { + if (o) { + o->call(scope, callData); + return scope.result.asReturnedValue(); + } else { QString error = QStringLiteral("Property '%1' of object %2 is not a function").arg(name->toQString(), callData->thisObject.toQStringNoThrow()); return engine->throwTypeError(error); } - return o->call(callData); } -ReturnedValue Runtime::callPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData) +ReturnedValue Runtime::method_callPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData) { Lookup *l = engine->current->lookups + index; Value v; v = l->getter(l, engine, callData->thisObject); - if (!v.isObject()) + if (v.isObject()) { + Scope scope(engine); + v.objectValue()->call(scope, callData); + return scope.result.asReturnedValue(); + } else { return engine->throwTypeError(); - - return v.objectValue()->call(callData); + } } -ReturnedValue Runtime::callElement(ExecutionEngine *engine, const Value &index, CallData *callData) +ReturnedValue Runtime::method_callElement(ExecutionEngine *engine, const Value &index, CallData *callData) { Scope scope(engine); ScopedObject baseObject(scope, callData->thisObject.toObject(engine)); @@ -1055,33 +1068,38 @@ ReturnedValue Runtime::callElement(ExecutionEngine *engine, const Value &index, if (!o) return engine->throwTypeError(); - return o->call(callData); + o->call(scope, callData); + return scope.result.asReturnedValue(); } -ReturnedValue Runtime::callValue(ExecutionEngine *engine, const Value &func, CallData *callData) +ReturnedValue Runtime::method_callValue(ExecutionEngine *engine, const Value &func, CallData *callData) { if (!func.isObject()) return engine->throwTypeError(QStringLiteral("%1 is not a function").arg(func.toQStringNoThrow())); - return func.objectValue()->call(callData); + Scope scope(engine); + func.objectValue()->call(scope, callData); + return scope.result.asReturnedValue(); } -ReturnedValue Runtime::constructGlobalLookup(ExecutionEngine *engine, uint index, CallData *callData) +ReturnedValue Runtime::method_constructGlobalLookup(ExecutionEngine *engine, uint index, CallData *callData) { Scope scope(engine); Q_ASSERT(callData->thisObject.isUndefined()); Lookup *l = engine->current->lookups + index; ScopedObject f(scope, l->globalGetter(l, engine)); - if (!f) + if (f) { + f->construct(scope, callData); + return scope.result.asReturnedValue(); + } else { return engine->throwTypeError(); - - return f->construct(callData); + } } -ReturnedValue Runtime::constructActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData) +ReturnedValue Runtime::method_constructActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); @@ -1093,19 +1111,22 @@ ReturnedValue Runtime::constructActivationProperty(ExecutionEngine *engine, int if (!f) return engine->throwTypeError(); - return f->construct(callData); + f->construct(scope, callData); + return scope.result.asReturnedValue(); } -ReturnedValue Runtime::constructValue(ExecutionEngine *engine, const Value &func, CallData *callData) +ReturnedValue Runtime::method_constructValue(ExecutionEngine *engine, const Value &func, CallData *callData) { const Object *f = func.as<Object>(); if (!f) return engine->throwTypeError(); - return f->construct(callData); + Scope scope(engine); + f->construct(scope, callData); + return scope.result.asReturnedValue(); } -ReturnedValue Runtime::constructProperty(ExecutionEngine *engine, int nameIndex, CallData *callData) +ReturnedValue Runtime::method_constructProperty(ExecutionEngine *engine, int nameIndex, CallData *callData) { Scope scope(engine); ScopedObject thisObject(scope, callData->thisObject.toObject(engine)); @@ -1114,31 +1135,38 @@ ReturnedValue Runtime::constructProperty(ExecutionEngine *engine, int nameIndex, return Encode::undefined(); ScopedObject f(scope, thisObject->get(name)); - if (!f) + if (f) { + Scope scope(engine); + f->construct(scope, callData); + return scope.result.asReturnedValue(); + } else { return engine->throwTypeError(); - - return f->construct(callData); + } } -ReturnedValue Runtime::constructPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData) +ReturnedValue Runtime::method_constructPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData) { Lookup *l = engine->current->lookups + index; Value v; v = l->getter(l, engine, callData->thisObject); - if (!v.isObject()) + if (v.isObject()) { + Scope scope(engine); + ScopedValue result(scope); + v.objectValue()->construct(scope, callData); + return scope.result.asReturnedValue(); + } else { return engine->throwTypeError(); - - return v.objectValue()->construct(callData); + } } -void Runtime::throwException(ExecutionEngine *engine, const Value &value) +void Runtime::method_throwException(ExecutionEngine *engine, const Value &value) { if (!value.isEmpty()) engine->throwError(value); } -ReturnedValue Runtime::typeofValue(ExecutionEngine *engine, const Value &value) +ReturnedValue Runtime::method_typeofValue(ExecutionEngine *engine, const Value &value) { Scope scope(engine); ScopedString res(scope); @@ -1167,39 +1195,37 @@ ReturnedValue Runtime::typeofValue(ExecutionEngine *engine, const Value &value) return res.asReturnedValue(); } -QV4::ReturnedValue Runtime::typeofName(ExecutionEngine *engine, int nameIndex) +QV4::ReturnedValue Runtime::method_typeofName(ExecutionEngine *engine, int nameIndex) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); ScopedValue prop(scope, engine->currentContext->getProperty(name)); // typeof doesn't throw. clear any possible exception scope.engine->hasException = false; - return Runtime::typeofValue(engine, prop); + return method_typeofValue(engine, prop); } #ifndef V4_BOOTSTRAP -ReturnedValue Runtime::typeofScopeObjectProperty(ExecutionEngine *engine, const Value &context, - int propertyIndex) +ReturnedValue Runtime::method_typeofScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex) { Scope scope(engine); - ScopedValue prop(scope, getQmlScopeObjectProperty(engine, context, propertyIndex)); + ScopedValue prop(scope, method_getQmlScopeObjectProperty(engine, context, propertyIndex, /*captureRequired*/true)); if (scope.engine->hasException) return Encode::undefined(); - return Runtime::typeofValue(engine, prop); + return method_typeofValue(engine, prop); } -ReturnedValue Runtime::typeofContextObjectProperty(ExecutionEngine *engine, const Value &context, - int propertyIndex) +ReturnedValue Runtime::method_typeofContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex) { Scope scope(engine); - ScopedValue prop(scope, getQmlContextObjectProperty(engine, context, propertyIndex)); + ScopedValue prop(scope, method_getQmlContextObjectProperty(engine, context, propertyIndex, /*captureRequired*/true)); if (scope.engine->hasException) return Encode::undefined(); - return Runtime::typeofValue(engine, prop); + return method_typeofValue(engine, prop); } #endif // V4_BOOTSTRAP -QV4::ReturnedValue Runtime::typeofMember(ExecutionEngine *engine, const Value &base, int nameIndex) +QV4::ReturnedValue Runtime::method_typeofMember(ExecutionEngine *engine, const Value &base, int nameIndex) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); @@ -1207,10 +1233,10 @@ QV4::ReturnedValue Runtime::typeofMember(ExecutionEngine *engine, const Value &b if (scope.engine->hasException) return Encode::undefined(); ScopedValue prop(scope, obj->get(name)); - return Runtime::typeofValue(engine, prop); + return method_typeofValue(engine, prop); } -QV4::ReturnedValue Runtime::typeofElement(ExecutionEngine *engine, const Value &base, const Value &index) +QV4::ReturnedValue Runtime::method_typeofElement(ExecutionEngine *engine, const Value &base, const Value &index) { Scope scope(engine); ScopedString name(scope, index.toString(engine)); @@ -1218,10 +1244,10 @@ QV4::ReturnedValue Runtime::typeofElement(ExecutionEngine *engine, const Value & if (scope.engine->hasException) return Encode::undefined(); ScopedValue prop(scope, obj->get(name)); - return Runtime::typeofValue(engine, prop); + return method_typeofValue(engine, prop); } -ReturnedValue Runtime::unwindException(ExecutionEngine *engine) +ReturnedValue Runtime::method_unwindException(ExecutionEngine *engine) { if (!engine->hasException) return Primitive::emptyValue().asReturnedValue(); @@ -1233,39 +1259,39 @@ ReturnedValue Runtime::unwindException(ExecutionEngine *engine) * * Instead the push/pop pair acts as a non local scope. */ -void Runtime::pushWithScope(const Value &o, ExecutionEngine *engine) +void Runtime::method_pushWithScope(const Value &o, ExecutionEngine *engine) { engine->pushContext(engine->currentContext->newWithContext(o.toObject(engine))); Q_ASSERT(engine->jsStackTop == engine->currentContext + 2); } -void Runtime::pushCatchScope(NoThrowEngine *engine, int exceptionVarNameIndex) +void Runtime::method_pushCatchScope(NoThrowEngine *engine, int exceptionVarNameIndex) { ExecutionContext *c = engine->currentContext; engine->pushContext(c->newCatchContext(c->d()->compilationUnit->runtimeStrings[exceptionVarNameIndex], engine->catchException(0))); Q_ASSERT(engine->jsStackTop == engine->currentContext + 2); } -void Runtime::popScope(ExecutionEngine *engine) +void Runtime::method_popScope(ExecutionEngine *engine) { Q_ASSERT(engine->jsStackTop == engine->currentContext + 2); engine->popContext(); engine->jsStackTop -= 2; } -void Runtime::declareVar(ExecutionEngine *engine, bool deletable, int nameIndex) +void Runtime::method_declareVar(ExecutionEngine *engine, bool deletable, int nameIndex) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); engine->currentContext->createMutableBinding(name, deletable); } -ReturnedValue Runtime::arrayLiteral(ExecutionEngine *engine, Value *values, uint length) +ReturnedValue Runtime::method_arrayLiteral(ExecutionEngine *engine, Value *values, uint length) { return engine->newArrayObject(values, length)->asReturnedValue(); } -ReturnedValue Runtime::objectLiteral(ExecutionEngine *engine, const QV4::Value *args, int classId, int arrayValueCount, int arrayGetterSetterCountAndFlags) +ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, const QV4::Value *args, int classId, int arrayValueCount, int arrayGetterSetterCountAndFlags) { Scope scope(engine); QV4::InternalClass *klass = engine->current->compilationUnit->runtimeClasses[classId]; @@ -1307,7 +1333,7 @@ ReturnedValue Runtime::objectLiteral(ExecutionEngine *engine, const QV4::Value * return o.asReturnedValue(); } -QV4::ReturnedValue Runtime::setupArgumentsObject(ExecutionEngine *engine) +QV4::ReturnedValue Runtime::method_setupArgumentsObject(ExecutionEngine *engine) { Q_ASSERT(engine->current->type == Heap::ExecutionContext::Type_CallContext); QV4::CallContext *c = static_cast<QV4::CallContext *>(engine->currentContext); @@ -1317,7 +1343,7 @@ QV4::ReturnedValue Runtime::setupArgumentsObject(ExecutionEngine *engine) #endif // V4_BOOTSTRAP -QV4::ReturnedValue Runtime::increment(const Value &value) +QV4::ReturnedValue Runtime::method_increment(const Value &value) { TRACE1(value); @@ -1329,7 +1355,7 @@ QV4::ReturnedValue Runtime::increment(const Value &value) } } -QV4::ReturnedValue Runtime::decrement(const Value &value) +QV4::ReturnedValue Runtime::method_decrement(const Value &value) { TRACE1(value); @@ -1364,31 +1390,31 @@ QV4::ReturnedValue RuntimeHelpers::toObject(ExecutionEngine *engine, const Value #endif // V4_BOOTSTRAP -ReturnedValue Runtime::toDouble(const Value &value) +ReturnedValue Runtime::method_toDouble(const Value &value) { TRACE1(value); return Encode(value.toNumber()); } -int Runtime::toInt(const Value &value) +int Runtime::method_toInt(const Value &value) { TRACE1(value); return value.toInt32(); } -int Runtime::doubleToInt(const double &d) +int Runtime::method_doubleToInt(const double &d) { TRACE0(); return Primitive::toInt32(d); } -unsigned Runtime::toUInt(const Value &value) +unsigned Runtime::method_toUInt(const Value &value) { TRACE1(value); return value.toUInt32(); } -unsigned Runtime::doubleToUInt(const double &d) +unsigned Runtime::method_doubleToUInt(const double &d) { TRACE0(); return Primitive::toUInt32(d); @@ -1396,17 +1422,17 @@ unsigned Runtime::doubleToUInt(const double &d) #ifndef V4_BOOTSTRAP -ReturnedValue Runtime::getQmlContext(NoThrowEngine *engine) +ReturnedValue Runtime::method_getQmlContext(NoThrowEngine *engine) { return engine->qmlContext()->asReturnedValue(); } -ReturnedValue Runtime::regexpLiteral(ExecutionEngine *engine, int id) +ReturnedValue Runtime::method_regexpLiteral(ExecutionEngine *engine, int id) { return engine->current->compilationUnit->runtimeRegularExpressions[id].asReturnedValue(); } -ReturnedValue Runtime::getQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired) +ReturnedValue Runtime::method_getQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired) { Scope scope(engine); QV4::Scoped<QObjectWrapper> wrapper(scope, object); @@ -1417,7 +1443,7 @@ ReturnedValue Runtime::getQmlQObjectProperty(ExecutionEngine *engine, const Valu return QV4::QObjectWrapper::getProperty(scope.engine, wrapper->object(), propertyIndex, captureRequired); } -QV4::ReturnedValue Runtime::getQmlAttachedProperty(ExecutionEngine *engine, int attachedPropertiesId, int propertyIndex) +QV4::ReturnedValue Runtime::method_getQmlAttachedProperty(ExecutionEngine *engine, int attachedPropertiesId, int propertyIndex) { QObject *scopeObject = engine->qmlScopeObject(); QObject *attachedObject = qmlAttachedPropertiesObjectById(attachedPropertiesId, scopeObject); @@ -1427,19 +1453,19 @@ QV4::ReturnedValue Runtime::getQmlAttachedProperty(ExecutionEngine *engine, int return QV4::QObjectWrapper::getProperty(engine, attachedObject, propertyIndex, /*captureRequired*/true); } -ReturnedValue Runtime::getQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex) +ReturnedValue Runtime::method_getQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, bool captureRequired) { const QmlContext &c = static_cast<const QmlContext &>(context); - return QV4::QObjectWrapper::getProperty(engine, c.d()->qml->scopeObject, propertyIndex, false); + return QV4::QObjectWrapper::getProperty(engine, c.d()->qml->scopeObject, propertyIndex, captureRequired); } -ReturnedValue Runtime::getQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex) +ReturnedValue Runtime::method_getQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, bool captureRequired) { const QmlContext &c = static_cast<const QmlContext &>(context); - return QV4::QObjectWrapper::getProperty(engine, c.d()->qml->context->contextObject, propertyIndex, false); + return QV4::QObjectWrapper::getProperty(engine, (*c.d()->qml->context)->contextObject, propertyIndex, captureRequired); } -ReturnedValue Runtime::getQmlSingletonQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired) +ReturnedValue Runtime::method_getQmlSingletonQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired) { Scope scope(engine); QV4::Scoped<QmlTypeWrapper> wrapper(scope, object); @@ -1450,11 +1476,11 @@ ReturnedValue Runtime::getQmlSingletonQObjectProperty(ExecutionEngine *engine, c return QV4::QObjectWrapper::getProperty(scope.engine, wrapper->singletonObject(), propertyIndex, captureRequired); } -ReturnedValue Runtime::getQmlIdObject(ExecutionEngine *engine, const Value &c, uint index) +ReturnedValue Runtime::method_getQmlIdObject(ExecutionEngine *engine, const Value &c, uint index) { Scope scope(engine); const QmlContext &qmlContext = static_cast<const QmlContext &>(c); - QQmlContextData *context = qmlContext.d()->qml->context; + QQmlContextData *context = *qmlContext.d()->qml->context; if (!context || index >= (uint)context->idValueCount) return Encode::undefined(); @@ -1465,19 +1491,19 @@ ReturnedValue Runtime::getQmlIdObject(ExecutionEngine *engine, const Value &c, u return QObjectWrapper::wrap(engine, context->idValues[index].data()); } -void Runtime::setQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value) +void Runtime::method_setQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value) { const QmlContext &c = static_cast<const QmlContext &>(context); return QV4::QObjectWrapper::setProperty(engine, c.d()->qml->scopeObject, propertyIndex, value); } -void Runtime::setQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value) +void Runtime::method_setQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value) { const QmlContext &c = static_cast<const QmlContext &>(context); - return QV4::QObjectWrapper::setProperty(engine, c.d()->qml->context->contextObject, propertyIndex, value); + return QV4::QObjectWrapper::setProperty(engine, (*c.d()->qml->context)->contextObject, propertyIndex, value); } -void Runtime::setQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, const Value &value) +void Runtime::method_setQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, const Value &value) { Scope scope(engine); QV4::Scoped<QObjectWrapper> wrapper(scope, object); @@ -1488,7 +1514,7 @@ void Runtime::setQmlQObjectProperty(ExecutionEngine *engine, const Value &object wrapper->setProperty(engine, propertyIndex, value); } -ReturnedValue Runtime::getQmlImportedScripts(NoThrowEngine *engine) +ReturnedValue Runtime::method_getQmlImportedScripts(NoThrowEngine *engine) { QQmlContextData *context = engine->callingQmlContext(); if (!context) @@ -1496,14 +1522,14 @@ ReturnedValue Runtime::getQmlImportedScripts(NoThrowEngine *engine) return context->importedScripts.value(); } -QV4::ReturnedValue Runtime::getQmlSingleton(QV4::NoThrowEngine *engine, int nameIndex) +QV4::ReturnedValue Runtime::method_getQmlSingleton(QV4::NoThrowEngine *engine, int nameIndex) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); return engine->qmlSingletonWrapper(name); } -void Runtime::convertThisToObject(ExecutionEngine *engine) +void Runtime::method_convertThisToObject(ExecutionEngine *engine) { Value *t = &engine->current->callData->thisObject; if (t->isObject()) @@ -1515,8 +1541,291 @@ void Runtime::convertThisToObject(ExecutionEngine *engine) } } +ReturnedValue Runtime::method_uPlus(const Value &value) +{ + TRACE1(value); + + if (value.isNumber()) + return value.asReturnedValue(); + if (value.integerCompatible()) + return Encode(value.int_32()); + + double n = value.toNumberImpl(); + return Encode(n); +} + +ReturnedValue Runtime::method_uMinus(const Value &value) +{ + TRACE1(value); + + // +0 != -0, so we need to convert to double when negating 0 + if (value.isInteger() && value.integerValue()) + return Encode(-value.integerValue()); + else { + double n = RuntimeHelpers::toNumber(value); + return Encode(-n); + } +} + +ReturnedValue Runtime::method_complement(const Value &value) +{ + TRACE1(value); + + int n = value.toInt32(); + return Encode((int)~n); +} + +ReturnedValue Runtime::method_uNot(const Value &value) +{ + TRACE1(value); + + bool b = value.toBoolean(); + return Encode(!b); +} + +// binary operators +ReturnedValue Runtime::method_bitOr(const Value &left, const Value &right) +{ + TRACE2(left, right); + + int lval = left.toInt32(); + int rval = right.toInt32(); + return Encode(lval | rval); +} + +ReturnedValue Runtime::method_bitXor(const Value &left, const Value &right) +{ + TRACE2(left, right); + + int lval = left.toInt32(); + int rval = right.toInt32(); + return Encode(lval ^ rval); +} + +ReturnedValue Runtime::method_bitAnd(const Value &left, const Value &right) +{ + TRACE2(left, right); + + int lval = left.toInt32(); + int rval = right.toInt32(); + return Encode(lval & rval); +} + +#ifndef V4_BOOTSTRAP +ReturnedValue Runtime::method_add(ExecutionEngine *engine, const Value &left, const Value &right) +{ + TRACE2(left, right); + + if (Q_LIKELY(left.isInteger() && right.isInteger())) + return add_int32(left.integerValue(), right.integerValue()); + if (left.isNumber() && right.isNumber()) + return Primitive::fromDouble(left.asDouble() + right.asDouble()).asReturnedValue(); + + return RuntimeHelpers::addHelper(engine, left, right); +} +#endif // V4_BOOTSTRAP + +ReturnedValue Runtime::method_sub(const Value &left, const Value &right) +{ + TRACE2(left, right); + + if (Q_LIKELY(left.isInteger() && right.isInteger())) + return sub_int32(left.integerValue(), right.integerValue()); + + double lval = left.isNumber() ? left.asDouble() : left.toNumberImpl(); + double rval = right.isNumber() ? right.asDouble() : right.toNumberImpl(); + + return Primitive::fromDouble(lval - rval).asReturnedValue(); +} + +ReturnedValue Runtime::method_mul(const Value &left, const Value &right) +{ + TRACE2(left, right); + + if (Q_LIKELY(left.isInteger() && right.isInteger())) + return mul_int32(left.integerValue(), right.integerValue()); + + double lval = left.isNumber() ? left.asDouble() : left.toNumberImpl(); + double rval = right.isNumber() ? right.asDouble() : right.toNumberImpl(); + + return Primitive::fromDouble(lval * rval).asReturnedValue(); +} + +ReturnedValue Runtime::method_div(const Value &left, const Value &right) +{ + TRACE2(left, right); + + if (Value::integerCompatible(left, right)) { + int lval = left.integerValue(); + int rval = right.integerValue(); + if (rval != 0 && (lval % rval == 0)) + return Encode(int(lval / rval)); + else + return Encode(double(lval) / rval); + } + + double lval = left.toNumber(); + double rval = right.toNumber(); + return Primitive::fromDouble(lval / rval).asReturnedValue(); +} + +ReturnedValue Runtime::method_mod(const Value &left, const Value &right) +{ + TRACE2(left, right); + + if (Value::integerCompatible(left, right) && right.integerValue() != 0) { + int intRes = left.integerValue() % right.integerValue(); + if (intRes != 0 || left.integerValue() >= 0) + return Encode(intRes); + } + + double lval = RuntimeHelpers::toNumber(left); + double rval = RuntimeHelpers::toNumber(right); +#ifdef fmod +# undef fmod +#endif + return Primitive::fromDouble(std::fmod(lval, rval)).asReturnedValue(); +} + +ReturnedValue Runtime::method_shl(const Value &left, const Value &right) +{ + TRACE2(left, right); + + int lval = left.toInt32(); + int rval = right.toInt32() & 0x1f; + return Encode((int)(lval << rval)); +} + +ReturnedValue Runtime::method_shr(const Value &left, const Value &right) +{ + TRACE2(left, right); + + int lval = left.toInt32(); + unsigned rval = right.toUInt32() & 0x1f; + return Encode((int)(lval >> rval)); +} + +ReturnedValue Runtime::method_ushr(const Value &left, const Value &right) +{ + TRACE2(left, right); + + unsigned lval = left.toUInt32(); + unsigned rval = right.toUInt32() & 0x1f; + uint res = lval >> rval; + + return Encode(res); +} + #endif // V4_BOOTSTRAP +ReturnedValue Runtime::method_greaterThan(const Value &left, const Value &right) +{ + TRACE2(left, right); + + bool r = method_compareGreaterThan(left, right); + return Encode(r); +} + +ReturnedValue Runtime::method_lessThan(const Value &left, const Value &right) +{ + TRACE2(left, right); + + bool r = method_compareLessThan(left, right); + return Encode(r); +} + +ReturnedValue Runtime::method_greaterEqual(const Value &left, const Value &right) +{ + TRACE2(left, right); + + bool r = method_compareGreaterEqual(left, right); + return Encode(r); +} + +ReturnedValue Runtime::method_lessEqual(const Value &left, const Value &right) +{ + TRACE2(left, right); + + bool r = method_compareLessEqual(left, right); + return Encode(r); +} + +Bool Runtime::method_compareEqual(const Value &left, const Value &right) +{ + TRACE2(left, right); + + if (left.rawValue() == right.rawValue()) + // NaN != NaN + return !left.isNaN(); + + if (left.type() == right.type()) { + if (!left.isManaged()) + return false; + if (left.isString() == right.isString()) + return left.cast<Managed>()->isEqualTo(right.cast<Managed>()); + } + + return RuntimeHelpers::equalHelper(left, right); +} + +ReturnedValue Runtime::method_equal(const Value &left, const Value &right) +{ + TRACE2(left, right); + + bool r = method_compareEqual(left, right); + return Encode(r); +} + +ReturnedValue Runtime::method_notEqual(const Value &left, const Value &right) +{ + TRACE2(left, right); + + bool r = !method_compareEqual(left, right); + return Encode(r); +} + +ReturnedValue Runtime::method_strictEqual(const Value &left, const Value &right) +{ + TRACE2(left, right); + + bool r = RuntimeHelpers::strictEqual(left, right); + return Encode(r); +} + +ReturnedValue Runtime::method_strictNotEqual(const Value &left, const Value &right) +{ + TRACE2(left, right); + + bool r = ! RuntimeHelpers::strictEqual(left, right); + return Encode(r); +} + +Bool Runtime::method_compareNotEqual(const Value &left, const Value &right) +{ + TRACE2(left, right); + + return !Runtime::method_compareEqual(left, right); +} + +Bool Runtime::method_compareStrictEqual(const Value &left, const Value &right) +{ + TRACE2(left, right); + + return RuntimeHelpers::strictEqual(left, right); +} + +Bool Runtime::method_compareStrictNotEqual(const Value &left, const Value &right) +{ + TRACE2(left, right); + + return ! RuntimeHelpers::strictEqual(left, right); +} + +Bool Runtime::method_toBoolean(const Value &value) +{ + return value.toBoolean(); +} + } // namespace QV4 QT_END_NAMESPACE |