V4: Fix multiplication
Ensure that negative number times positive zero yields negative zero,
not positive zero.
Do the same adjustment in QJSPrimitiveValue
Fixes: QTBUG-104582
Change-Id: I8231bfb051b7d902e5e50bbd282410a572b1628a
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
(cherry picked from commit f59af767ae
)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
3951642331
commit
2a39659aee
|
@ -93,7 +93,11 @@ class QJSPrimitiveValue
|
|||
static constexpr double op(double lhs, double rhs) { return lhs * rhs; }
|
||||
static bool opOverflow(int lhs, int rhs, int *result)
|
||||
{
|
||||
return qMulOverflow(lhs, rhs, result);
|
||||
// compare mul_int32 in qv4math_p.h
|
||||
auto hadOverflow = qMulOverflow(lhs, rhs, result);
|
||||
if (((lhs < 0) xor (rhs < 0)) && (*result == 0))
|
||||
return true; // result must be negative 0, does not fit into int
|
||||
return hadOverflow;
|
||||
}
|
||||
|
||||
using StringNaNOperators::op;
|
||||
|
|
|
@ -52,6 +52,9 @@ static inline QMLJS_READONLY ReturnedValue mul_int32(int a, int b)
|
|||
int result;
|
||||
if (Q_UNLIKELY(mul_overflow(a, b, &result)))
|
||||
return StaticValue::fromDouble(static_cast<double>(a) * b).asReturnedValue();
|
||||
// need to handle the case where one number is negative and the other 0 ==> -0
|
||||
if (((a < 0) xor (b < 0)) && (result == 0))
|
||||
return StaticValue::fromDouble(-0.0).asReturnedValue();
|
||||
return StaticValue::fromInt32(result).asReturnedValue();
|
||||
}
|
||||
|
||||
|
|
|
@ -225,6 +225,7 @@ private slots:
|
|||
void returnError();
|
||||
void catchError();
|
||||
void mathMinMax();
|
||||
void mathNegativeZero();
|
||||
|
||||
void importModule();
|
||||
void importModuleRelative();
|
||||
|
@ -4931,6 +4932,18 @@ void tst_QJSEngine::mathMinMax()
|
|||
QVERIFY(QV4::Value(QJSValuePrivate::asReturnedValue(&result)).isInteger());
|
||||
}
|
||||
|
||||
void tst_QJSEngine::mathNegativeZero()
|
||||
{
|
||||
QJSEngine engine;
|
||||
QJSValue result = engine.evaluate("var a = 0; Object.is(-1*a, -0)");
|
||||
QVERIFY(result.isBool());
|
||||
QVERIFY(result.toBool());
|
||||
|
||||
result = engine.evaluate("var a = 0; Object.is(1*a, 0)");
|
||||
QVERIFY(result.isBool());
|
||||
QVERIFY(result.toBool());
|
||||
}
|
||||
|
||||
void tst_QJSEngine::importModule()
|
||||
{
|
||||
// This is just a basic test for the API. Primary test coverage is via the ES test suite.
|
||||
|
|
|
@ -34,6 +34,8 @@ private slots:
|
|||
void strictlyEquals();
|
||||
void stringAndUrl();
|
||||
|
||||
void negativeNullMult();
|
||||
|
||||
private:
|
||||
QJSEngine engine;
|
||||
|
||||
|
@ -929,6 +931,19 @@ void tst_QJSPrimitiveValue::stringAndUrl()
|
|||
QCOMPARE(engine.fromPrimitiveValue<QUrl>(immediateStringValue), url);
|
||||
}
|
||||
|
||||
void tst_QJSPrimitiveValue::negativeNullMult()
|
||||
{
|
||||
QJSPrimitiveValue zero(0);
|
||||
QJSPrimitiveValue negative(-1);
|
||||
QJSPrimitiveValue positive(1);
|
||||
|
||||
QCOMPARE((zero * negative).type(), QJSPrimitiveValue::Double);
|
||||
QCOMPARE((negative * zero).type(), QJSPrimitiveValue::Double);
|
||||
|
||||
QCOMPARE((zero * positive).type(), QJSPrimitiveValue::Integer);
|
||||
QCOMPARE((positive * zero).type(), QJSPrimitiveValue::Integer);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QJSPrimitiveValue)
|
||||
|
||||
#include "tst_qjsprimitivevalue.moc"
|
||||
|
|
Loading…
Reference in New Issue