Commit a27fd584 authored by Kent Hansen's avatar Kent Hansen Committed by Qt by Nokia

Let V8 throw the exception when QML property lookup fails

Only V8 knows whether a failed property lookup should actually cause
a ReferenceError to be thrown. When evaluating a "typeof" expression,
for example, a ReferenceError should not be thrown even if the
expression involves global variables that don't exist, according to
the ECMA-262 specification.

QML should try to match the standard JavaScript behavior. This is
achieved by simply returning an empty value handle (to signify the
absence of the property), and leaving it to V8 to throw an exception
as appropriate.

Task-number: QTBUG-21864
Task-number: QTBUG-24448
Change-Id: I9945adcab98fc3b801371163367473d6af0ab31a
Reviewed-by: default avatarAaron Kennedy <aaron.kennedy@nokia.com>
parent 8f077f28
......@@ -238,16 +238,11 @@ QQmlContextData *QV8ContextWrapper::context(v8::Handle<v8::Value> value)
return r?r->getContext():0;
}
v8::Handle<v8::Value> QV8ContextWrapper::NullGetter(v8::Local<v8::String> property,
const v8::AccessorInfo &info)
v8::Handle<v8::Value> QV8ContextWrapper::NullGetter(v8::Local<v8::String>,
const v8::AccessorInfo &)
{
QV8ContextResource *resource = v8_resource_check<QV8ContextResource>(info.This());
QV8Engine *engine = resource->engine;
QString error = engine->toString(property) + QLatin1String(" is not defined");
v8::ThrowException(v8::Exception::ReferenceError(engine->toString(error)));
return v8::Undefined();
// V8 will throw a ReferenceError if appropriate ("typeof" should not throw)
return v8::Handle<v8::Value>();
}
v8::Handle<v8::Value> QV8ContextWrapper::Getter(v8::Local<v8::String> property,
......@@ -365,9 +360,8 @@ v8::Handle<v8::Value> QV8ContextWrapper::Getter(v8::Local<v8::String> property,
expressionContext->unresolvedNames = true;
QString error = engine->toString(property) + QLatin1String(" is not defined");
v8::ThrowException(v8::Exception::ReferenceError(engine->toString(error)));
return v8::Undefined();
// V8 will throw a ReferenceError if appropriate ("typeof" should not throw)
return v8::Handle<v8::Value>();
}
v8::Handle<v8::Value> QV8ContextWrapper::NullSetter(v8::Local<v8::String> property,
......
var test = false;
try {
eval(foo);
} catch (e) {
test = (typeof foo) === "undefined";
}
import "qtbug_24448.js" as Test
import QtQuick 2.0
QtObject {
property bool test: Test.test
}
......@@ -207,6 +207,7 @@ private slots:
void deleteLater();
void in();
void typeOf();
void qtbug_24448();
void sharedAttachedObject();
void objectName();
void writeRemovesBinding();
......@@ -5376,17 +5377,9 @@ void tst_qqmlecmascript::typeOf()
{
QQmlComponent component(&engine, testFileUrl("typeOf.qml"));
// These warnings should not happen once QTBUG-21864 is fixed
QString warning1 = component.url().toString() + QLatin1String(":16: Error: Cannot assign [undefined] to QString");
QString warning2 = component.url().resolved(QUrl("typeOf.js")).toString() + QLatin1String(":1: ReferenceError: a is not defined");
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
QObject *o = component.create();
QVERIFY(o != 0);
QEXPECT_FAIL("", "QTBUG-21864", Abort);
QCOMPARE(o->property("test1").toString(), QLatin1String("undefined"));
QCOMPARE(o->property("test2").toString(), QLatin1String("object"));
QCOMPARE(o->property("test3").toString(), QLatin1String("number"));
......@@ -5400,6 +5393,14 @@ void tst_qqmlecmascript::typeOf()
delete o;
}
void tst_qqmlecmascript::qtbug_24448()
{
QQmlComponent component(&engine, testFileUrl("qtbug_24448.qml"));
QScopedPointer<QObject> o(component.create());
QVERIFY(o != 0);
QVERIFY(o->property("test").toBool());
}
void tst_qqmlecmascript::sharedAttachedObject()
{
QQmlComponent component(&engine, testFileUrl("sharedAttachedObject.qml"));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment