1

I'm trying to get the result of a script simple operation on the C++ side.

I create a QScriptValue (myvar) and call engine.globalObject().setProperty("result", myvar); Then I evaluate "result = anothervar + 7;" The evaluate method return value is OK but the variable result is not OK. If the script is "result = anothervar + 7; a=1" then the result value is OK.

It looks too stupid to be a Qt bug so what did I miss ?

Thanks

Jeff

Marc Mutz - mmutz
  • 24,485
  • 12
  • 80
  • 90
JFM
  • 11
  • 2
  • Works for me: `QScriptEngine e; e.globalObject().setProperty( "result", QScriptValue( 1.0 ) ); e.globalObject().setProperty( "anotherVar", QScriptValue( 14 ) ); const QScriptValue s = e.evaluate( "result = anotherVar + 7;" ); qDebug() << s.toVariant(); qDebug() << e.globalObject().property("result").toVariant();` both print "QVariant(double,21)". – Marc Mutz - mmutz Apr 20 '11 at 14:08
  • Could you try to create a variable QScriptValue( 1.0 ) and display the value of this variable instead of reading the value in the engine ? (e.globalObject().property("result").toVariant()). Thanks. – JFM Apr 20 '11 at 14:13

1 Answers1

0

From your answer to my comment, I'm assuming you're keeping the QScriptValue myvar instance around, and look at it after calling evaluate():

QScriptEngine e;
QScriptValue myvar( 1.0 );
e.globalObject().setProperty( "result", myvar );
e.globalObject().setProperty( "anotherVar", QScriptValue( 14 ) );
const QScriptValue s = e.evaluate( "result = anotherVar + 7;" );
qDebug() << s.toVariant();
qDebug() << e.globalObject().property("result").toVariant();
qDebug() << myvar.toVariant();

This will print 2x "QVariant(double,21)" and once "QVariant(double,1)". That is expected behaviour, here's why:

In JavaScript, everything is an object, and you are only dealing with references to objects, not the objects themselves (if you know Java, this is similar to int vs. Integer). So, what the assignment result = anotherVar + 7; does is replace the object represented by myvar as the global object's "result" property with the object that results from the expression anotherVar + 7. Meanwhile, the QScriptValue myvar still references the (old) object, which otherwise would be up for grabs by the garbage-collecter at this point.

About the addition of a=1 to fix the problem: I can't reproduce that here. The first debug statement prints the value of a, of course, but the second and third are unchanged.

The solution to your problem, therefore, is to always re-get the "result" property from the engine whenever you need it (using engine.globalObject().property("result")), or—in other words—QScriptValue doesn't track assigments.

If you do want to track assignment, you need to turn it into a method call: Implement result as a custom class with an assign() method, and replace assignment (=) with result.assign( anotherVal + 7 );.

Marc Mutz - mmutz
  • 24,485
  • 12
  • 80
  • 90
  • You are right, a=1 does not fix anything, I should have dream this result !! I'm not sure to understand your explanation concerning "If you didn't hold on to the object represented by myvar through the QScriptValue myvar, then it would be garbage-collected at this point". What would be your advice to solve that problem ? – JFM Apr 20 '11 at 14:48
  • @JFM: I edited my answer to be (hopefully) more clear on both points. – Marc Mutz - mmutz Apr 20 '11 at 15:01
  • OK, I was afraid of this answer... I have a lot of variables accessibles in many scripts but not all variables are modified in, all scripts. I wanted to avoid to get values for all variables. If I create a custom class replace QScriptValues will I get the same behaviour or can I expect to code a better feedback ? thru qScriptRegisterMetaType(&engine, toScriptValue, fromScriptValue); ? – JFM Apr 20 '11 at 15:14
  • @JFM: assignment always breaks the binding of the object to the name, so to say. Even if you implement the `result` object as you mention, this will still be the case. However, you can give that object an `assign()` (e.g.) method, and rewrite the JavaScript to say `result.assign( anotherVar + 7 );`. Then `result` will not be assigned-to and the QScriptValue will still reference the correct object, yes. – Marc Mutz - mmutz Apr 20 '11 at 15:24