diff options
author | Jason Barron <jbarron@trolltech.com> | 2009-08-24 08:33:34 (GMT) |
---|---|---|
committer | Jason Barron <jbarron@trolltech.com> | 2009-08-24 08:33:34 (GMT) |
commit | 27e6cf45f652f3f80a40abb08cabbd7bc285b4e3 (patch) | |
tree | db8dbfbaea2f5c45b96f664d9ce8afb02485d94e | |
parent | c987e036538a53564345aa6bc4f84a33b0b02fca (diff) | |
parent | 84081ce91c56168edd686a404b405dcad5f74106 (diff) | |
download | Qt-27e6cf45f652f3f80a40abb08cabbd7bc285b4e3.zip Qt-27e6cf45f652f3f80a40abb08cabbd7bc285b4e3.tar.gz Qt-27e6cf45f652f3f80a40abb08cabbd7bc285b4e3.tar.bz2 |
Merge branch '4.6' of git@scm.dev.nokia.troll.no:qt/qt into 4.6
-rw-r--r-- | src/corelib/tools/qlist.cpp | 53 | ||||
-rw-r--r-- | src/corelib/tools/qlist.h | 11 | ||||
-rw-r--r-- | src/corelib/tools/qscopedpointer.h | 9 | ||||
-rw-r--r-- | src/gui/painting/qbrush.cpp | 14 | ||||
-rw-r--r-- | src/gui/painting/qbrush.h | 6 | ||||
-rw-r--r-- | src/script/api/qscriptcontext.cpp | 9 | ||||
-rw-r--r-- | src/script/api/qscriptvalue.cpp | 4 | ||||
-rw-r--r-- | tests/auto/qscriptcontext/tst_qscriptcontext.cpp | 35 | ||||
-rw-r--r-- | tests/auto/qscriptengine/tst_qscriptengine.cpp | 32 |
9 files changed, 144 insertions, 29 deletions
diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index 58406b9..868bed1 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -94,16 +94,49 @@ QListData::Data *QListData::detach() /*! * Detaches the QListData by reallocating new memory. * Returns the old (shared) data, it is up to the caller to deref() and free() + * For the new data node_copy needs to be called. * * \internal */ +#if QT_VERSION >= 0x050000 +# error "Remove QListData::detach2(), it is only required for binary compatibility for 4.3.x to 4.5.x" +#endif QListData::Data *QListData::detach2() { Data *x = d; Data* t = static_cast<Data *>(qMalloc(DataHeaderSize + x->alloc * sizeof(void *))); Q_CHECK_PTR(t); - ::memcpy(t, x, DataHeaderSize + x->alloc * sizeof(void *)); + ::memcpy(x, d, DataHeaderSize + d->alloc * sizeof(void *)); + + t->ref = 1; + t->sharable = true; + t->alloc = x->alloc; + if (!t->alloc) { + t->begin = 0; + t->end = 0; + } else { + t->begin = x->begin; + t->end = x->end; + } + d = t; + + return x; +} + +/*! + * Detaches the QListData by reallocating new memory. + * Returns the old (shared) data, it is up to the caller to deref() and free() + * For the new data node_copy needs to be called. + * + * \internal + */ +QListData::Data *QListData::detach3() +{ + Data *x = d; + Data* t = static_cast<Data *>(qMalloc(DataHeaderSize + x->alloc * sizeof(void *))); + Q_CHECK_PTR(t); + t->ref = 1; t->sharable = true; t->alloc = x->alloc; @@ -150,6 +183,9 @@ void **QListData::append() } // ensures that enough space is available to append the list +#if QT_VERSION >= 0x050000 +# error "Remove QListData::append(), it is only required for binary compatibility up to 4.5.x" +#endif void **QListData::append(const QListData& l) { Q_ASSERT(d->ref == 1); @@ -158,6 +194,21 @@ void **QListData::append(const QListData& l) if (n) { if (e + n > d->alloc) realloc(grow(e + l.d->end - l.d->begin)); + ::memcpy(d->array + d->end, l.d->array + l.d->begin, n*sizeof(void*)); + d->end += n; + } + return d->array + e; +} + +// ensures that enough space is available to append the list +void **QListData::append2(const QListData& l) +{ + Q_ASSERT(d->ref == 1); + int e = d->end; + int n = l.d->end - l.d->begin; + if (n) { + if (e + n > d->alloc) + realloc(grow(e + l.d->end - l.d->begin)); d->end += n; } return d->array + e; diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 5fa0f6c..331f448 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -72,13 +72,15 @@ struct Q_CORE_EXPORT QListData { enum { DataHeaderSize = sizeof(Data) - sizeof(void *) }; Data *detach(); // remove in 5.0 - Data *detach2(); + Data *detach2(); // remove in 5.0 + Data *detach3(); void realloc(int alloc); static Data shared_null; Data *d; void **erase(void **xi); void **append(); void **append(const QListData &l); + void **append2(const QListData &l); // remove in 5.0 void **prepend(); void **insert(int i); void remove(int i); @@ -381,6 +383,9 @@ Q_INLINE_TEMPLATE void QList<T>::node_copy(Node *from, Node *to, Node *src) (reinterpret_cast<T*>(current--))->~T(); QT_RETHROW; } + } else { + if (src != from && to - from > 0) + memcpy(from, src, (to - from) * sizeof(Node *)); } } @@ -590,7 +595,7 @@ template <typename T> Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper() { Node *n = reinterpret_cast<Node *>(p.begin()); - QListData::Data *x = p.detach2(); + QListData::Data *x = p.detach3(); QT_TRY { node_copy(reinterpret_cast<Node *>(p.begin()), reinterpret_cast<Node *>(p.end()), n); } QT_CATCH(...) { @@ -690,7 +695,7 @@ template <typename T> Q_OUTOFLINE_TEMPLATE QList<T> &QList<T>::operator+=(const QList<T> &l) { detach(); - Node *n = reinterpret_cast<Node *>(p.append(l.p)); + Node *n = reinterpret_cast<Node *>(p.append2(l.p)); QT_TRY{ node_copy(n, reinterpret_cast<Node *>(p.end()), reinterpret_cast<Node *>(l.p.begin())); } QT_CATCH(...) { diff --git a/src/corelib/tools/qscopedpointer.h b/src/corelib/tools/qscopedpointer.h index 7a3ee14..f801366 100644 --- a/src/corelib/tools/qscopedpointer.h +++ b/src/corelib/tools/qscopedpointer.h @@ -166,6 +166,11 @@ public: return oldD; } + inline void swap(QScopedPointer<T, Cleanup> &other) + { + qSwap(d, other.d); + } + typedef T *pointer; protected: @@ -175,6 +180,10 @@ private: Q_DISABLE_COPY(QScopedPointer) }; +template <class T, class Cleanup> +Q_INLINE_TEMPLATE void qSwap(QScopedPointer<T, Cleanup> &p1, QScopedPointer<T, Cleanup> &p2) +{ p1.swap(p2); } + template <typename T, typename Cleanup = QScopedPointerArrayDeleter<T> > class QScopedArrayPointer : public QScopedPointer<T, Cleanup> { diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp index b005842..a52a270 100644 --- a/src/gui/painting/qbrush.cpp +++ b/src/gui/painting/qbrush.cpp @@ -389,20 +389,20 @@ void QBrush::init(const QColor &color, Qt::BrushStyle style) { switch(style) { case Qt::NoBrush: - d.data_ptr() = nullBrushInstance(); + d.reset(nullBrushInstance()); d->ref.ref(); if (d->color != color) setColor(color); return; case Qt::TexturePattern: - d.data_ptr() = new QTexturedBrushData; + d.reset(new QTexturedBrushData); break; case Qt::LinearGradientPattern: case Qt::RadialGradientPattern: case Qt::ConicalGradientPattern: - d.data_ptr() = new QGradientBrushData; + d.reset(new QGradientBrushData); break; default: - d.data_ptr() = new QBrushData; + d.reset(new QBrushData); break; } d->ref = 1; @@ -460,7 +460,7 @@ QBrush::QBrush(Qt::BrushStyle style) if (qbrush_check_type(style)) init(Qt::black, style); else { - d.data_ptr() = nullBrushInstance(); + d.reset(nullBrushInstance()); d->ref.ref(); } } @@ -476,7 +476,7 @@ QBrush::QBrush(const QColor &color, Qt::BrushStyle style) if (qbrush_check_type(style)) init(color, style); else { - d.data_ptr() = nullBrushInstance(); + d.reset(nullBrushInstance()); d->ref.ref(); } } @@ -493,7 +493,7 @@ QBrush::QBrush(Qt::GlobalColor color, Qt::BrushStyle style) if (qbrush_check_type(style)) init(color, style); else { - d.data_ptr() = nullBrushInstance(); + d.reset(nullBrushInstance()); d->ref.ref(); } } diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h index 51b108e..9f9819c 100644 --- a/src/gui/painting/qbrush.h +++ b/src/gui/painting/qbrush.h @@ -137,13 +137,13 @@ private: friend bool Q_GUI_EXPORT qHasPixmapTexture(const QBrush& brush); void detach(Qt::BrushStyle newStyle); void init(const QColor &color, Qt::BrushStyle bs); - QCustomScopedPointer<QBrushData, QBrushDataPointerDeleter> d; + QScopedPointer<QBrushData, QBrushDataPointerDeleter> d; void cleanUp(QBrushData *x); public: inline bool isDetached() const; - typedef QBrushData * DataPtr; - inline DataPtr &data_ptr() { return d.data_ptr(); } + typedef QScopedPointer<QBrushData, QBrushDataPointerDeleter> DataPtr; + inline DataPtr &data_ptr() { return d; } }; inline void QBrush::setColor(Qt::GlobalColor acolor) diff --git a/src/script/api/qscriptcontext.cpp b/src/script/api/qscriptcontext.cpp index 0b1ca33..6a85ede 100644 --- a/src/script/api/qscriptcontext.cpp +++ b/src/script/api/qscriptcontext.cpp @@ -305,8 +305,8 @@ QScriptValue QScriptContext::argumentsObject() const { JSC::CallFrame *frame = const_cast<JSC::ExecState*>(QScriptEnginePrivate::frameForContext(this)); - if (frame == frame->lexicalGlobalObject()->globalExec() || frame->callerFrame()->hasHostCallFrameFlag()) { - // <global> or <eval> context doesn't have arguments. return an empty object + if (frame == frame->lexicalGlobalObject()->globalExec()) { + // <global> context doesn't have arguments. return an empty object return QScriptEnginePrivate::get(QScript::scriptEngineFromExec(frame))->newObject(); } @@ -316,6 +316,11 @@ QScriptValue QScriptContext::argumentsObject() const return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(result); } + if (frame->callerFrame()->hasHostCallFrameFlag()) { + // <eval> context doesn't have arguments. return an empty object + return QScriptEnginePrivate::get(QScript::scriptEngineFromExec(frame))->newObject(); + } + //for a native function if (!frame->optionalCalleeArguments()) { Q_ASSERT(frame->argumentCount() > 0); //we need at least 'this' otherwise we'll crash later diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp index 73c8d1b..93d6be8 100644 --- a/src/script/api/qscriptvalue.cpp +++ b/src/script/api/qscriptvalue.cpp @@ -1936,7 +1936,6 @@ QScriptValue QScriptValue::call(const QScriptValue &thisObject, "a different engine"); return QScriptValue(); } - engine()->currentContext()->activationObject(); //force the creation of a context for native function; JSC::ExecState *exec = d->engine->currentFrame; @@ -2011,7 +2010,6 @@ QScriptValue QScriptValue::call(const QScriptValue &thisObject, "a different engine"); return QScriptValue(); } - engine()->currentContext()->activationObject(); //force the creation of a context for native function; JSC::ExecState *exec = d->engine->currentFrame; @@ -2077,7 +2075,6 @@ QScriptValue QScriptValue::construct(const QScriptValueList &args) Q_D(const QScriptValue); if (!isFunction()) return QScriptValue(); - engine()->currentContext()->activationObject(); //force the creation of a context for native function; JSC::ExecState *exec = d->engine->currentFrame; QVector<JSC::JSValue> argsVector; @@ -2125,7 +2122,6 @@ QScriptValue QScriptValue::construct(const QScriptValue &arguments) Q_D(QScriptValue); if (!isFunction()) return QScriptValue(); - engine()->currentContext()->activationObject(); //force the creation of a context for native function; JSC::ExecState *exec = d->engine->currentFrame; JSC::JSValue array = d->engine->scriptValueToJSCValue(arguments); diff --git a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp index a0c56ed..ef609e0 100644 --- a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp +++ b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp @@ -559,6 +559,11 @@ static QScriptValue custom_eval(QScriptContext *ctx, QScriptEngine *eng) return eng->evaluate(ctx->argumentsObject().property(0).toString(), ctx->argumentsObject().property(1).toString()); } +static QScriptValue custom_call(QScriptContext *ctx, QScriptEngine *) +{ + return ctx->argumentsObject().property(0).call(QScriptValue(), QScriptValueList() << ctx->argumentsObject().property(1)); +} + void tst_QScriptContext::backtrace_data() { QTest::addColumn<QString>("code"); @@ -681,7 +686,36 @@ void tst_QScriptContext::backtrace_data() QTest::newRow("two function") << source << expected; } + { + QString func("function foo(a, b) {\n" + " return bt(a);\n" + "}"); + + QString source = func + QString::fromLatin1("\n" + "custom_call(foo, 'hello');\n" + "var a = 1\n"); + + QStringList expected; + expected << "<native>('hello') at -1" + << "foo(a = 'hello') at testfile:2" + << QString("<native>(%1, 'hello') at -1").arg(func) + << "<global>() at testfile:4"; + QTest::newRow("call") << source << expected; + } + + { + QString source = QString::fromLatin1("\n" + "custom_call(bt, 'hello_world');\n" + "var a = 1\n"); + + QStringList expected; + expected << "<native>('hello_world') at -1" + << "<native>(function () {\n [native code]\n}, 'hello_world') at -1" + << "<global>() at testfile:2"; + + QTest::newRow("call native") << source << expected; + } } @@ -693,6 +727,7 @@ void tst_QScriptContext::backtrace() QScriptEngine eng; eng.globalObject().setProperty("bt", eng.newFunction(getBacktrace)); eng.globalObject().setProperty("custom_eval", eng.newFunction(custom_eval)); + eng.globalObject().setProperty("custom_call", eng.newFunction(custom_call)); QString fileName = "testfile"; QScriptValue ret = eng.evaluate(code, fileName); diff --git a/tests/auto/qscriptengine/tst_qscriptengine.cpp b/tests/auto/qscriptengine/tst_qscriptengine.cpp index 85cee28..0c67987 100644 --- a/tests/auto/qscriptengine/tst_qscriptengine.cpp +++ b/tests/auto/qscriptengine/tst_qscriptengine.cpp @@ -1518,15 +1518,29 @@ static QScriptValue eval_nested(QScriptContext *ctx, QScriptEngine *eng) void tst_QScriptEngine::nestedEvaluate() { QScriptEngine eng; - eng.globalObject().setProperty("fun", eng.newFunction(eval_nested)); - QScriptValue result = eng.evaluate("o = { id:'foo'}; o.fun = fun; o.fun()"); - QCOMPARE(result.property("local_bar").toString(), QString("local")); - QCOMPARE(result.property("thisObjectIdBefore").toString(), QString("foo")); - QCOMPARE(result.property("thisObjectIdAfter").toString(), QString("foo")); - QCOMPARE(result.property("evaluatedThisObjectId").toString(), QString("foo")); - QScriptValue bar = eng.evaluate("bar"); - QVERIFY(bar.isError()); - QCOMPARE(bar.toString(), QString::fromLatin1("ReferenceError: Can't find variable: bar")); + QScriptValue fun = eng.newFunction(eval_nested); + eng.globalObject().setProperty("fun", fun); + { + QScriptValue result = eng.evaluate("o = { id:'foo'}; o.fun = fun; o.fun()"); + QCOMPARE(result.property("local_bar").toString(), QString("local")); + QCOMPARE(result.property("thisObjectIdBefore").toString(), QString("foo")); + QCOMPARE(result.property("thisObjectIdAfter").toString(), QString("foo")); + QCOMPARE(result.property("evaluatedThisObjectId").toString(), QString("foo")); + QScriptValue bar = eng.evaluate("bar"); + QVERIFY(bar.isError()); + QCOMPARE(bar.toString(), QString::fromLatin1("ReferenceError: Can't find variable: bar")); + } + + { + QScriptValue result = fun.call(eng.evaluate("p = { id:'foo' }") , QScriptValueList() ); + QCOMPARE(result.property("local_bar").toString(), QString("local")); + QCOMPARE(result.property("thisObjectIdBefore").toString(), QString("foo")); + QCOMPARE(result.property("thisObjectIdAfter").toString(), QString("foo")); + QCOMPARE(result.property("evaluatedThisObjectId").toString(), QString("foo")); + QScriptValue bar = eng.evaluate("bar"); + QVERIFY(bar.isError()); + QCOMPARE(bar.toString(), QString::fromLatin1("ReferenceError: Can't find variable: bar")); + } } void tst_QScriptEngine::uncaughtException() |