summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Barron <jbarron@trolltech.com>2009-08-24 10:33:34 +0200
committerJason Barron <jbarron@trolltech.com>2009-08-24 10:33:34 +0200
commit27e6cf45f652f3f80a40abb08cabbd7bc285b4e3 (patch)
treedb8dbfbaea2f5c45b96f664d9ce8afb02485d94e
parentc987e036538a53564345aa6bc4f84a33b0b02fca (diff)
parent84081ce91c56168edd686a404b405dcad5f74106 (diff)
Merge branch '4.6' of git@scm.dev.nokia.troll.no:qt/qt into 4.6
-rw-r--r--src/corelib/tools/qlist.cpp53
-rw-r--r--src/corelib/tools/qlist.h11
-rw-r--r--src/corelib/tools/qscopedpointer.h9
-rw-r--r--src/gui/painting/qbrush.cpp14
-rw-r--r--src/gui/painting/qbrush.h6
-rw-r--r--src/script/api/qscriptcontext.cpp9
-rw-r--r--src/script/api/qscriptvalue.cpp4
-rw-r--r--tests/auto/qscriptcontext/tst_qscriptcontext.cpp35
-rw-r--r--tests/auto/qscriptengine/tst_qscriptengine.cpp32
9 files changed, 144 insertions, 29 deletions
diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp
index 58406b9b6..868bed1d2 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 5fa0f6cfa..331f448d5 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 7a3ee14e5..f801366cb 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 b005842a1..a52a270ac 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 51b108e29..9f9819c50 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 0b1ca33f4..6a85edeff 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 73c8d1bba..93d6be8b4 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 a0c56edd0..ef609e022 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 85cee280a..0c679875d 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()