QJSManagedValue: Throw TypeErrors when accessing null or undefined
Accessing properties of null or undefined is supposed to throw TypeErrors in ECMAScript. Change-Id: I4f05d56fa2f4d6767e582795bf39769a12df8019 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
ae22e8d479
commit
2e4561d4e7
|
|
@ -774,9 +774,15 @@ bool QJSManagedValue::hasOwnProperty(const QString &name) const
|
|||
*/
|
||||
QJSValue QJSManagedValue::property(const QString &name) const
|
||||
{
|
||||
if (!d || d->isNullOrUndefined())
|
||||
if (!d)
|
||||
return QJSValue();
|
||||
|
||||
if (d->isNullOrUndefined()) {
|
||||
QV4::ExecutionEngine *e = v4Engine(d);
|
||||
e->throwTypeError(QStringLiteral("Cannot read property '%1' of null").arg(name));
|
||||
return QJSValue();
|
||||
}
|
||||
|
||||
if (QV4::String *string = d->as<QV4::String>()) {
|
||||
if (name == QStringLiteral("length"))
|
||||
return QJSValue(string->d()->length());
|
||||
|
|
@ -801,6 +807,11 @@ void QJSManagedValue::setProperty(const QString &name, const QJSValue &value)
|
|||
if (!d)
|
||||
return;
|
||||
|
||||
if (d->isNullOrUndefined()) {
|
||||
v4Engine(d)->throwTypeError(
|
||||
QStringLiteral("Value is null and could not be converted to an object"));
|
||||
}
|
||||
|
||||
if (QV4::Object *obj = d->as<QV4::Object>()) {
|
||||
QV4::ExecutionEngine *v4 = QJSValuePrivate::engine(&value);
|
||||
if (Q_UNLIKELY(v4 && v4 != obj->engine())) {
|
||||
|
|
|
|||
|
|
@ -1624,13 +1624,12 @@ void tst_QJSManagedValue::engineDeleted()
|
|||
|
||||
delete eng;
|
||||
|
||||
// You can still check the type, but anything involving the engine is obviously prohibited.
|
||||
QCOMPARE(v1.type(), QJSManagedValue::Undefined);
|
||||
QCOMPARE(v2.type(), QJSManagedValue::Undefined);
|
||||
QCOMPARE(v3.type(), QJSManagedValue::Undefined);
|
||||
QCOMPARE(v4.type(), QJSManagedValue::Undefined);
|
||||
QCOMPARE(v5.type(), QJSManagedValue::Undefined);
|
||||
|
||||
QVERIFY(v3.property(QStringLiteral("foo")).isUndefined());
|
||||
}
|
||||
|
||||
void tst_QJSManagedValue::valueOfWithClosure()
|
||||
|
|
@ -1822,4 +1821,36 @@ void tst_QJSManagedValue::jsMetaTypes()
|
|||
QVERIFY(halfPopulated.property("ccc").isUndefined());
|
||||
}
|
||||
|
||||
void tst_QJSManagedValue::exceptionsOnNullAccess()
|
||||
{
|
||||
QJSEngine engine;
|
||||
QJSManagedValue null(QJSValue(QJSValue::NullValue), &engine);
|
||||
QJSManagedValue undef(QJSValue(QJSValue::UndefinedValue), &engine);
|
||||
|
||||
const QString nullReadError = engine.evaluate(
|
||||
QStringLiteral("var n = null; n.prop")).toString();
|
||||
const QString nullWriteError = engine.evaluate(
|
||||
QStringLiteral("var n = null; n.prop = 5")).toString();
|
||||
const QString undefReadError = engine.evaluate(
|
||||
QStringLiteral("var n; n.prop")).toString();
|
||||
const QString undefWriteError = engine.evaluate(
|
||||
QStringLiteral("var n; n.prop = 5")).toString();
|
||||
|
||||
QVERIFY(null.property(QStringLiteral("prop")).isUndefined());
|
||||
QVERIFY(engine.hasError());
|
||||
QCOMPARE(engine.catchError().toString(), nullReadError);
|
||||
|
||||
null.setProperty(QStringLiteral("prop"), 5);
|
||||
QVERIFY(engine.hasError());
|
||||
QCOMPARE(engine.catchError().toString(), nullWriteError);
|
||||
|
||||
QVERIFY(undef.property(QStringLiteral("prop")).isUndefined());
|
||||
QVERIFY(engine.hasError());
|
||||
QCOMPARE(engine.catchError().toString(), undefReadError);
|
||||
|
||||
undef.setProperty(QStringLiteral("prop"), 5);
|
||||
QVERIFY(engine.hasError());
|
||||
QCOMPARE(engine.catchError().toString(), undefWriteError);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QJSManagedValue)
|
||||
|
|
|
|||
|
|
@ -110,6 +110,8 @@ private Q_SLOTS:
|
|||
void stringByIndex();
|
||||
void jsMetaTypes();
|
||||
|
||||
void exceptionsOnNullAccess();
|
||||
|
||||
private:
|
||||
void newEngine() { engine.reset(new QJSEngine()); }
|
||||
QScopedPointer<QJSEngine> engine;
|
||||
|
|
|
|||
Loading…
Reference in New Issue