void tst_QScriptClass::enumerate() { QScriptEngine eng; TestClass cls(&eng); QScriptValue obj = eng.newObject(&cls); QScriptString foo = eng.toStringHandle("foo"); obj.setProperty(foo, QScriptValue(&eng, 123)); cls.setIterationEnabled(false); { QScriptValueIterator it(obj); QVERIFY(it.hasNext()); it.next(); QVERIFY(it.scriptName() == foo); QVERIFY(!it.hasNext()); } // add a custom property QScriptString foo2 = eng.toStringHandle("foo2"); const uint foo2Id = 123; const QScriptValue::PropertyFlags foo2Pflags = QScriptValue::Undeletable; QScriptValue foo2Value(&eng, 456); cls.addCustomProperty(foo2, QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess, foo2Id, foo2Pflags, QScriptValue()); cls.setIterationEnabled(true); QScriptValueIterator it(obj); for (int x = 0; x < 2; ++x) { QVERIFY(it.hasNext()); it.next(); QEXPECT_FAIL("", "", Abort); QVERIFY(it.scriptName() == foo); QVERIFY(it.hasNext()); it.next(); QVERIFY(it.scriptName() == foo2); QCOMPARE(it.flags(), foo2Pflags); QVERIFY(!it.hasNext()); QVERIFY(it.hasPrevious()); it.previous(); QVERIFY(it.scriptName() == foo2); QCOMPARE(it.flags(), foo2Pflags); QVERIFY(it.hasPrevious()); it.previous(); QVERIFY(it.scriptName() == foo); QVERIFY(!it.hasPrevious()); } }
void tst_QScriptString::hash() { QScriptEngine engine; QHash<QScriptString, int> stringToInt; QScriptString foo = engine.toStringHandle("foo"); QScriptString bar = engine.toStringHandle("bar"); QVERIFY(!stringToInt.contains(foo)); for (int i = 0; i < 1000000; ++i) stringToInt.insert(foo, 123); QCOMPARE(stringToInt.value(foo), 123); QVERIFY(!stringToInt.contains(bar)); stringToInt.insert(bar, 456); QCOMPARE(stringToInt.value(bar), 456); QCOMPARE(stringToInt.value(foo), 123); }
// Test the time taken to get the propeties flags accross the engine void tst_QScriptClass::propertyFlags() { QScriptEngine eng; FooScriptClass cls(&eng); QScriptValue obj = eng.newObject(&cls); QScriptString foo = eng.toStringHandle("foo"); QBENCHMARK { for (int i = 0; i < iterationNumber; ++i) (void)obj.propertyFlags(foo); } }
ScriptDataItemPropertyIterator::ScriptDataItemPropertyIterator(const QScriptValue &object) : QScriptClassPropertyIterator(object), m_id(-1) { DataItem *item = get_data_item(object); QScriptEngine *engine = object.engine(); const char *names[] = { "name", "title", "data", "maxCount", "defaultSubitem", "onDataChangedReceiver", "onDataChangedMethod" }; for (uint i = 0; i < sizeof(names)/sizeof(names[0]); ++i) m_names << engine->toStringHandle(QLatin1String(names[i])); const QList<QByteArray> dynamicNames = item->dynamicPropertyNames(); for (int i = 0; i < dynamicNames.size(); ++i) m_names << engine->toStringHandle(QLatin1String(dynamicNames[i])); }
// Test the overhead of setting a value on QScriptClass accross the Javascript engine void tst_QScriptClass::setProperty() { QScriptEngine eng; FooScriptClass cls(&eng); QScriptValue obj = eng.newObject(&cls); QScriptValue value(456); QScriptString foo = eng.toStringHandle("foo"); QBENCHMARK { for (int i = 0; i < iterationNumber; ++i) obj.setProperty(foo, value); } }
void tst_QScriptValueIterator::iterateForward() { QFETCH(QStringList, propertyNames); QFETCH(QStringList, propertyValues); QMap<QString, QString> pmap; QVERIFY(propertyNames.size() == propertyValues.size()); QScriptEngine engine; QScriptValue object = engine.newObject(); for (int i = 0; i < propertyNames.size(); ++i) { QString name = propertyNames.at(i); QString value = propertyValues.at(i); pmap.insert(name, value); object.setProperty(name, QScriptValue(&engine, value)); } QScriptValue otherObject = engine.newObject(); otherObject.setProperty("foo", QScriptValue(&engine, 123456)); otherObject.setProperty("protoProperty", QScriptValue(&engine, 654321)); object.setPrototype(otherObject); // should not affect iterator QStringList lst; QScriptValueIterator it(object); while (!pmap.isEmpty()) { QCOMPARE(it.hasNext(), true); QCOMPARE(it.hasNext(), true); it.next(); QString name = it.name(); QCOMPARE(pmap.contains(name), true); QCOMPARE(it.name(), name); QCOMPARE(it.flags(), object.propertyFlags(name)); QCOMPARE(it.value().strictlyEquals(QScriptValue(&engine, pmap.value(name))), true); QCOMPARE(it.scriptName(), engine.toStringHandle(name)); pmap.remove(name); lst.append(name); } QCOMPARE(it.hasNext(), false); QCOMPARE(it.hasNext(), false); it.toFront(); for (int i = 0; i < lst.count(); ++i) { QCOMPARE(it.hasNext(), true); it.next(); QCOMPARE(it.name(), lst.at(i)); } for (int i = 0; i < lst.count(); ++i) { QCOMPARE(it.hasPrevious(), true); it.previous(); QCOMPARE(it.name(), lst.at(lst.count()-1-i)); } QCOMPARE(it.hasPrevious(), false); }
void tst_QScriptString::toArrayIndex() { QFETCH(QString, input); QFETCH(bool, expectSuccess); QFETCH(quint32, expectedIndex); QScriptEngine engine; for (int x = 0; x < 2; ++x) { bool isArrayIndex; bool* ptr = (!x) ? &isArrayIndex : (bool*)0; quint32 result = engine.toStringHandle(input).toArrayIndex(ptr); if (!x) QCOMPARE(isArrayIndex, expectSuccess); QCOMPARE(result, expectedIndex); } }
const QList<ParameterInfo>& RootNetworkValue::getParameterInfo() { if (isLoaded() && _parameterInfo.isEmpty()) { ScriptCache* cache = _program->getCache(); QScriptEngine* engine = cache->getEngine(); QScriptValue parameters = _value.property(cache->getParametersString()); if (parameters.isArray()) { int length = parameters.property(cache->getLengthString()).toInt32(); for (int i = 0; i < length; i++) { QScriptValue parameter = parameters.property(i); ParameterInfo info = { engine->toStringHandle(parameter.property(cache->getNameString()).toString()), QMetaType::type(parameter.property(cache->getTypeString()).toString().toUtf8().constData()) }; _parameterInfo.append(info); } } } return _parameterInfo; }
void tst_QScriptClass::getProperty_invalidValue() { QScriptEngine eng; TestClass cls(&eng); cls.addCustomProperty(eng.toStringHandle("foo"), QScriptClass::HandlesReadAccess, /*id=*/0, QScriptValue::ReadOnly, QScriptValue()); QScriptValue obj = eng.newObject(&cls); QVERIFY(obj.property("foo").isUndefined()); eng.globalObject().setProperty("obj", obj); QVERIFY(eng.evaluate("obj.hasOwnProperty('foo'))").toBool()); // The JS environment expects that a valid value is returned, // otherwise we could crash. QVERIFY(eng.evaluate("obj.foo").isUndefined()); QVERIFY(eng.evaluate("obj.foo + ''").isString()); QVERIFY(eng.evaluate("Object.getOwnPropertyDescriptor(obj, 'foo').value").isUndefined()); QVERIFY(eng.evaluate("Object.getOwnPropertyDescriptor(obj, 'foo').value +''").isString()); }
void tst_QScriptClass::getAndSetProperty() { QScriptEngine eng; TestClass cls(&eng); QScriptValue obj1 = eng.newObject(&cls); QScriptValue obj2 = eng.newObject(&cls); QScriptString foo = eng.toStringHandle("foo"); QScriptString bar = eng.toStringHandle("bar"); // should behave just like normal for (int x = 0; x < 2; ++x) { QScriptValue &o = (x == 0) ? obj1 : obj2; for (int y = 0; y < 2; ++y) { QScriptString &s = (y == 0) ? foo : bar; // read property cls.clearReceivedArgs(); QScriptValue ret = o.property(s); QVERIFY(!ret.isValid()); QVERIFY(cls.lastQueryPropertyObject().strictlyEquals(o)); QVERIFY(cls.lastQueryPropertyName() == s); QVERIFY(!cls.lastPropertyObject().isValid()); QVERIFY(!cls.lastSetPropertyObject().isValid()); QVERIFY(cls.lastQueryPropertyFlags() == QScriptClass::HandlesReadAccess); // write property cls.clearReceivedArgs(); QScriptValue num(&eng, 123); o.setProperty(s, num); QVERIFY(cls.lastQueryPropertyObject().strictlyEquals(o)); QVERIFY(cls.lastQueryPropertyName() == s); QVERIFY(!cls.lastPropertyObject().isValid()); QVERIFY(!cls.lastSetPropertyObject().isValid()); // ### ideally, we should only test for HandlesWriteAccess in this case QVERIFY(cls.lastQueryPropertyFlags() == (QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess)); // re-read property cls.clearReceivedArgs(); QVERIFY(o.property(s).strictlyEquals(num)); QVERIFY(!cls.lastQueryPropertyObject().isValid()); } } // add a custom property QScriptString foo2 = eng.toStringHandle("foo2"); const uint foo2Id = 123; const QScriptValue::PropertyFlags foo2Pflags = QScriptValue::Undeletable; QScriptValue foo2Value(&eng, 456); cls.addCustomProperty(foo2, QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess, foo2Id, foo2Pflags, foo2Value); { // read property cls.clearReceivedArgs(); { QScriptValue ret = obj1.property(foo2); QVERIFY(ret.strictlyEquals(foo2Value)); } QVERIFY(cls.lastQueryPropertyObject().strictlyEquals(obj1)); QVERIFY(cls.lastQueryPropertyName() == foo2); QVERIFY(cls.lastPropertyObject().strictlyEquals(obj1)); QVERIFY(cls.lastPropertyName() == foo2); QCOMPARE(cls.lastPropertyId(), foo2Id); // read flags cls.clearReceivedArgs(); QCOMPARE(obj1.propertyFlags(foo2), foo2Pflags); QVERIFY(cls.lastQueryPropertyObject().strictlyEquals(obj1)); QVERIFY(cls.lastQueryPropertyName() == foo2); QVERIFY(!cls.lastPropertyObject().isValid()); QVERIFY(cls.lastPropertyFlagsObject().strictlyEquals(obj1)); QVERIFY(cls.lastPropertyFlagsName() == foo2); QCOMPARE(cls.lastPropertyFlagsId(), foo2Id); // write property cls.clearReceivedArgs(); QScriptValue newFoo2Value(&eng, 789); obj1.setProperty(foo2, newFoo2Value); QVERIFY(cls.lastQueryPropertyObject().strictlyEquals(obj1)); QVERIFY(cls.lastQueryPropertyName() == foo2); // read property again cls.clearReceivedArgs(); { QScriptValue ret = obj1.property(foo2); QVERIFY(ret.strictlyEquals(newFoo2Value)); } QVERIFY(cls.lastQueryPropertyObject().strictlyEquals(obj1)); QVERIFY(cls.lastQueryPropertyName() == foo2); QVERIFY(cls.lastPropertyObject().strictlyEquals(obj1)); QVERIFY(cls.lastPropertyName() == foo2); QCOMPARE(cls.lastPropertyId(), foo2Id); } }
void tst_QScriptString::test() { QScriptEngine eng; { QScriptString str; QVERIFY(!str.isValid()); QVERIFY(str == str); QVERIFY(!(str != str)); QVERIFY(str.toString().isNull()); QScriptString str1(str); QVERIFY(!str1.isValid()); QScriptString str2 = str; QVERIFY(!str2.isValid()); QCOMPARE(str.toArrayIndex(), quint32(0xffffffff)); } for (int x = 0; x < 2; ++x) { QString ciao = QString::fromLatin1("ciao"); QScriptString str = eng.toStringHandle(ciao); QVERIFY(str.isValid()); QVERIFY(str == str); QVERIFY(!(str != str)); QCOMPARE(str.toString(), ciao); QScriptString str1(str); QCOMPARE(str, str1); QScriptString str2 = str; QCOMPARE(str, str2); QScriptString str3 = eng.toStringHandle(ciao); QVERIFY(str3.isValid()); QCOMPARE(str, str3); eng.collectGarbage(); QVERIFY(str.isValid()); QCOMPARE(str.toString(), ciao); QVERIFY(str1.isValid()); QCOMPARE(str1.toString(), ciao); QVERIFY(str2.isValid()); QCOMPARE(str2.toString(), ciao); QVERIFY(str3.isValid()); QCOMPARE(str3.toString(), ciao); } { QScriptEngine* eng2 = new QScriptEngine; QString one = QString::fromLatin1("one"); QString two = QString::fromLatin1("two"); QScriptString oneInterned = eng2->toStringHandle(one); QCOMPARE(oneInterned.toString(), one); QScriptString twoInterned = eng2->toStringHandle(two); QCOMPARE(twoInterned.toString(), two); QVERIFY(oneInterned != twoInterned); QVERIFY(!(oneInterned == twoInterned)); delete eng2; } }
void tst_QScriptClass::getAndSetProperty() { QScriptEngine eng; TestClass cls(&eng); QScriptValue obj1 = eng.newObject(&cls); QScriptValue obj2 = eng.newObject(&cls); QScriptString foo = eng.toStringHandle("foo"); QScriptString bar = eng.toStringHandle("bar"); QScriptValue num(&eng, 123); // should behave just like normal for (int x = 0; x < 2; ++x) { QScriptValue &o = (x == 0) ? obj1 : obj2; for (int y = 0; y < 2; ++y) { QScriptString &s = (y == 0) ? foo : bar; // read property cls.clearReceivedArgs(); QScriptValue ret = o.property(s); QVERIFY(!ret.isValid()); QVERIFY(cls.lastQueryPropertyObject().strictlyEquals(o)); QVERIFY(cls.lastQueryPropertyName() == s); QVERIFY(!cls.lastPropertyObject().isValid()); QVERIFY(!cls.lastSetPropertyObject().isValid()); QVERIFY(cls.lastQueryPropertyFlags() == QScriptClass::HandlesReadAccess); // write property cls.clearReceivedArgs(); o.setProperty(s, num); QVERIFY(cls.lastQueryPropertyObject().strictlyEquals(o)); QVERIFY(cls.lastQueryPropertyName() == s); QVERIFY(!cls.lastPropertyObject().isValid()); QVERIFY(!cls.lastSetPropertyObject().isValid()); QVERIFY(cls.lastQueryPropertyFlags() == QScriptClass::HandlesWriteAccess); // re-read property // When a QScriptClass doesn't want to handle a property write, // that property becomes a normal property and the QScriptClass // shall not be queried about it again. cls.clearReceivedArgs(); QVERIFY(o.property(s).strictlyEquals(num)); QVERIFY(!cls.lastQueryPropertyObject().isValid()); } } // add a custom property QScriptString foo2 = eng.toStringHandle("foo2"); const uint foo2Id = 123; const QScriptValue::PropertyFlags foo2Pflags = QScriptValue::Undeletable; QScriptValue foo2Value(&eng, 456); cls.addCustomProperty(foo2, QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess, foo2Id, foo2Pflags, foo2Value); { // read property cls.clearReceivedArgs(); { QScriptValue ret = obj1.property(foo2); QVERIFY(ret.strictlyEquals(foo2Value)); } QVERIFY(cls.lastQueryPropertyObject().strictlyEquals(obj1)); QVERIFY(cls.lastQueryPropertyName() == foo2); QVERIFY(cls.lastPropertyObject().strictlyEquals(obj1)); QVERIFY(cls.lastPropertyName() == foo2); QCOMPARE(cls.lastPropertyId(), foo2Id); // read flags cls.clearReceivedArgs(); QCOMPARE(obj1.propertyFlags(foo2), foo2Pflags); QVERIFY(cls.lastQueryPropertyObject().strictlyEquals(obj1)); QVERIFY(cls.lastQueryPropertyName() == foo2); QEXPECT_FAIL("", "classObject.getOwnPropertyDescriptor() reads the property value", Continue); QVERIFY(!cls.lastPropertyObject().isValid()); QVERIFY(cls.lastPropertyFlagsObject().strictlyEquals(obj1)); QVERIFY(cls.lastPropertyFlagsName() == foo2); QCOMPARE(cls.lastPropertyFlagsId(), foo2Id); // write property cls.clearReceivedArgs(); QScriptValue newFoo2Value(&eng, 789); obj1.setProperty(foo2, newFoo2Value); QVERIFY(cls.lastQueryPropertyObject().strictlyEquals(obj1)); QVERIFY(cls.lastQueryPropertyName() == foo2); // read property again cls.clearReceivedArgs(); { QScriptValue ret = obj1.property(foo2); QVERIFY(ret.strictlyEquals(newFoo2Value)); } QVERIFY(cls.lastQueryPropertyObject().strictlyEquals(obj1)); QVERIFY(cls.lastQueryPropertyName() == foo2); QVERIFY(cls.lastPropertyObject().strictlyEquals(obj1)); QVERIFY(cls.lastPropertyName() == foo2); QCOMPARE(cls.lastPropertyId(), foo2Id); } // remove script class; normal properties should remain obj1.setScriptClass(0); QCOMPARE(obj1.scriptClass(), (QScriptClass*)0); QVERIFY(obj1.property(foo).equals(num)); QVERIFY(obj1.property(bar).equals(num)); obj1.setProperty(foo, QScriptValue()); QVERIFY(!obj1.property(foo).isValid()); obj1.setProperty(bar, QScriptValue()); QVERIFY(!obj1.property(bar).isValid()); }