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
|
QJSValue QJSManagedValue::property(const QString &name) const
|
||||||
{
|
{
|
||||||
if (!d || d->isNullOrUndefined())
|
if (!d)
|
||||||
return QJSValue();
|
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 (QV4::String *string = d->as<QV4::String>()) {
|
||||||
if (name == QStringLiteral("length"))
|
if (name == QStringLiteral("length"))
|
||||||
return QJSValue(string->d()->length());
|
return QJSValue(string->d()->length());
|
||||||
|
|
@ -801,6 +807,11 @@ void QJSManagedValue::setProperty(const QString &name, const QJSValue &value)
|
||||||
if (!d)
|
if (!d)
|
||||||
return;
|
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>()) {
|
if (QV4::Object *obj = d->as<QV4::Object>()) {
|
||||||
QV4::ExecutionEngine *v4 = QJSValuePrivate::engine(&value);
|
QV4::ExecutionEngine *v4 = QJSValuePrivate::engine(&value);
|
||||||
if (Q_UNLIKELY(v4 && v4 != obj->engine())) {
|
if (Q_UNLIKELY(v4 && v4 != obj->engine())) {
|
||||||
|
|
|
||||||
|
|
@ -1624,13 +1624,12 @@ void tst_QJSManagedValue::engineDeleted()
|
||||||
|
|
||||||
delete eng;
|
delete eng;
|
||||||
|
|
||||||
|
// You can still check the type, but anything involving the engine is obviously prohibited.
|
||||||
QCOMPARE(v1.type(), QJSManagedValue::Undefined);
|
QCOMPARE(v1.type(), QJSManagedValue::Undefined);
|
||||||
QCOMPARE(v2.type(), QJSManagedValue::Undefined);
|
QCOMPARE(v2.type(), QJSManagedValue::Undefined);
|
||||||
QCOMPARE(v3.type(), QJSManagedValue::Undefined);
|
QCOMPARE(v3.type(), QJSManagedValue::Undefined);
|
||||||
QCOMPARE(v4.type(), QJSManagedValue::Undefined);
|
QCOMPARE(v4.type(), QJSManagedValue::Undefined);
|
||||||
QCOMPARE(v5.type(), QJSManagedValue::Undefined);
|
QCOMPARE(v5.type(), QJSManagedValue::Undefined);
|
||||||
|
|
||||||
QVERIFY(v3.property(QStringLiteral("foo")).isUndefined());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QJSManagedValue::valueOfWithClosure()
|
void tst_QJSManagedValue::valueOfWithClosure()
|
||||||
|
|
@ -1822,4 +1821,36 @@ void tst_QJSManagedValue::jsMetaTypes()
|
||||||
QVERIFY(halfPopulated.property("ccc").isUndefined());
|
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)
|
QTEST_MAIN(tst_QJSManagedValue)
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,8 @@ private Q_SLOTS:
|
||||||
void stringByIndex();
|
void stringByIndex();
|
||||||
void jsMetaTypes();
|
void jsMetaTypes();
|
||||||
|
|
||||||
|
void exceptionsOnNullAccess();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void newEngine() { engine.reset(new QJSEngine()); }
|
void newEngine() { engine.reset(new QJSEngine()); }
|
||||||
QScopedPointer<QJSEngine> engine;
|
QScopedPointer<QJSEngine> engine;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue