/*!
    \title Moving from QSA to Qt Script
    \page porting-qsa.html
    \ingroup porting

    The purpose of this document is to map the differences between Qt
    Script for Applications (QSA) and Qt Script, the ECMAScript compatible
    engine supplied with Qt 4.3. This document is not supposed to be a
    complete function by function porting guide, but will cover the most
    obvious aspects.

    First of all it is important to realize that Qt Script is only an
    interpreter, it does not provide an editor, completion or script project
    management, like QSA does. Qt Script however does provides almost full
    compliance with the ECMAScript standard and performs significantly
    better than the script engine provided by QSA. 

    \tableofcontents

    \section1 The Scripting Language

    The scripting language used in QSA, from here on referred to as QSA,
    was derived from ECMAScript 3.0 and 4.0 and is a hybrid of these
    standards. Most of the run-time logic, such as classes and scoping
    rules, is based on the ECMAScript 4.0 proposal, while the library
    implementation is based on the ECMAScript 3.0 standard.
    Qt Script on the other hand is solely based on the ECMAScript 3.0
    standard. Though the languages look identical at first glance,
    there are a few differences that we'll cover in the sections below.


    \section2 Classes vs. Objects and Properties

    QSA implements classes and inheritance much in a familiar way to users
    of other object oriented languages, like C++ and Java. However, the
    ECMAScript 3.0 standard defines that everything is an object, and objects
    can have named properties. For instance to create an point object with
    the properties x and y one would write the following Qt Script code:

    \code
    point = new Object();
    point.x = 12;
    point.y = 35;
    \endcode

    The object \c point in this case is constructed as a plain object and
    we assign two properties, \c x and \c y, to it with the values 12 and
    35. The \c point object is assigned to the "Global Object" as the
    named property \c{point}. The global object can be considered the
    global namespace of the script engine. Similarly, global functions are
    named properties of the global object; for example:

    \code
    function manhattanLength(point) {  
        return point.x + point.y;
    }
    \endcode

    An equivalent construction that illustrates that the function is a
    property of the global object is the following assignment:

    \code
    manhattanLength = function(point) {
       return point.x + point.y;
    }
    \endcode

    Since functions are objects, they can be assigned to objects as
    properties, becoming member functions:

    \code
    point.manhattanLength = function() {
        return this.x + this.y;
    }
    print(point.manhattanLength()); // prints 47
    \endcode

    In the code above, we see the first subtle difference between
    QSA and Qt Script. In QSA one would write the point class like this:

    \code
    class Point() {
        var x;
        var y;
        function manhattanLength() { return x + y; }
    }
    \endcode

    where in the \c manhattanLength() function we access \c x and \c y
    directly because, when the function is called, the \c this object is
    implicitly part of the current scope, as in C++. In Qt Script,
    however, this is not the case, and we need to explicitly access
    the \c x and \c y values via \c{this}.

    All the code above runs with QSA except the assignment of a function
    to \c{point.manhattanLength}, which we repeat here for clarity:
    
    \code
    point.manhattanLength = function() {
        return this.x + this.y;
    }
    print(point.manhattanLength()); // prints 47
    \endcode

    This is because, in QSA, the value of \c this is decided based on
    the location of the declaration of the function it is used in. In the
    code above, the function is assigned to an object, but it is declared
    in the global scope, hence there will be no valid \c this value.
    In Qt Script, the value of \c this is decided at run-time,
    hence you could have assigned the \c manhattanLength() function to any
    object that had \c x and \c y values.


    \section2 Constructors

    In the code above, we use a rather awkward method for constructing
    the objects, by first instantiating them, then manually
    assigning properties to them. In QSA, the proper way to solve this
    is to implement a constructor in the class:

    \code
    class Car {
        var regNumber;
        function Car(regnr) {
            regNumber = regnr;
        }
    }
    var car = new Car("ABC 123");
    \endcode

    The equivalent in Qt Script is to create a constructor function:

    \code
    function Car(regnr) {
        this.regNumber = regnr;
    }
    var car = new Car("ABC 123");
    \endcode

    As we can see, the constructor is just a normal function. What is
    special with is how we call it, namely prefixed with the \c new
    keyword. This will create a new object and call the \c Car()
    function with the newly created object as the \c this pointer.
    So, in a sense, it is equivalent to:

    \code
    var car = new Object();
    car.constructor = function(regnr) { ... }
    car.constructor();
    \endcode

    This is similar to the manhattenLength() example above. Again, the
    main difference between QSA and Qt Script is that one has to
    explicitly use the keyword \c this to access the members and that
    instead of declaring the variable, \c regNumber, we just extend the
    \c this object with the property.


    \section2 Member Functions and Prototypes

    As we saw above, one way of creating member functions of a Qt Script
    object is to assign the member function to the object as a property
    and use the \c this object inside the functions. So, if we add a
    \c toString function to the \c Car class

    \code
    class Car {
        var regNumber;
        function Car(regnr) {
            regNumber = regnr;
        }
        function toString() {
            return regNumber;
        }
    }
    \endcode

    one could write this in Qt Script as:

    \code
    function Car(regnr) {
        this.regNumber = regnr;
        this.toString = function() { return this.regNumber; }
    }
    \endcode

    In QSA, the member functions were part of the class declaration,
    and were therefore shared between all instances of a given class.
    In Qt Script, each instance has a instance member for each function.
    This means that more memory is used when multiple instances are used.
    Qt Script uses prototypes to remedy this. 

    The basic prototype-based inheritance mechanism works as follows.
    Each Qt Script object has an internal link to another object, its
    prototype. When a property is looked up in an object, and the object
    itself does not have the property, the interpreter searches for the
    property in the prototype object instead; if the prototype has the
    property then that property is returned. If the prototype object does
    not have the property, the interpreter searches for the property in
    the prototype of the prototype object, and so on.

    This chain of objects constitutes a prototype chain. The chain of
    prototype objects is followed until the property is found or the end
    of the chain is reached.

    To make the \c toString() function part of the prototype, we write
    code like this:

    \code
    function Car(regnr) {
        this.regNumber = regnr;
    }
    Car.prototype.toString = function() { return this.regNumber; }
    \endcode

    Here, we made the \c toString() function part of the prototype so
    that, when we call \c{car.toString()} it will be resolved via the
    internal prototype object of the car object. Note, however, that the
    \c this object is still the original object that the function was
    called on, namely \c{car}.


    \section2 Inheritance

    Now that we've seen how to use prototypes to create a "class" members
    in Qt Script, let's see how we can use prototypes to create
    polymorphism. In QSA you would write

    \code
    class GasolineCar extends Car {
        function GasolineCar(regnr) {
            Car(regnr);
        }
        function toString() {
            return "GasolineCar(" + regNumber + ")";
        }
    }
    \endcode

    With Qt Script, we acheive the same effect by creating a prototype
    chain. The default prototype of an object is a plain \c Object
    without any special members, but it is possible to replace this
    object with another prototype object.

    \code
    function GasolineCar(regnr) {
        Car(regnr); 
    }
    GasolineCar.prototype = new Car();
    GasolineCar.prototype.toString = function() { 
        return "GasolineCar(" + this.regNumber + ")"; 
    }
    \endcode

    In the code above, we have a constructor, \c{GasolineCar}, which
    calls the "base class" implementation of the constructor to
    initialize the \c this object with the property \c{regNumber},
    based on the values passed in the constructor. The interesting line
    in this case is the line after the constructor where we change the
    default prototype for \c GasolineCar to be an instance of type
    \c{Car}. This means that all members available in a \c Car object
    are now available in all \c GasolineCar objects. In the last line,
    we replace the \c toString() function in the prototype with our own,
    thus overriding the \c toString() for all instances of
    \c{GasolineCar}.


    \section2 Static Members

    QSA allowed users to declare static members in classes, and these
    could be accessed both through instances of the class and through
    the class itself. For example, the following variable is accessed
    through the \c Car class:

    \code
    class Car {
        static var globalCount = 0;
    }     
    print(Car.globalCount);
    \endcode

    The equivalent in Qt Script is to assign variables that should appear
    as static members as properties of the constructor function. For
    example:

    \code
    Car.globalCount = 0;
    print(Car.globalCount);
    \endcode

    Note that in QSA, static member variables were also accessible in
    instances of the given class. In Qt Script, with the approach
    illustrated above, the variable is a member of the constructor
    object only, and thus only accessible through \c{Car.globalCount}.


    \section1 The Built-in Functions and Library

    The built-in functions in QSA are based on those defined in the
    ECMAScript 3.0 standard, the same standard used for Qt Script, but
    QSA adds some extensions to this, specifically for the \c String
    and \c RegExp types. QSA also lacked some functions from the
    standard, most notably the \c Date type. Below we list all the
    differences. All changes made to Qt Script are to increase
    compliance with ECMAScript 3.0.

    \table
    \header \o QSA Function \o Notes about Equivalent Qt Script Functions
    \row \o eval()
    \o The eval function in QSA opened a new scope for code being
    executed in the eval function, so locally declared variables were not
    accessible outside. In Qt Script, the eval() function shares the
    current scope, making locally declared variables accessible outside
    the eval() call.

    \row \o debug()
    \o This function is not available in Qt Script. Use print() instead.

    \row \o connect()
    \o QSA had closures, meaning that a member function
    reference implicitly contained its \c this object. Qt Script does not
    support this. See the Qt Script documentation for details on using the
    connect function.

    \row \o String.arg()
    \o This function is not available in Qt Script. Use replace() or concat() instead.

    \row \o String.argDec()
    \o This function is not available in Qt Script. Use replace() or concat() instead.

    \row \o String.argInt()
    \o This function is not available in Qt Script. Use replace() or concat() instead.

    \row \o String.argStr()
    \o This function is not available in Qt Script. Use replace() or concat() instead.

    \row \o String.endsWith()
    \o This function is not available in Qt Script. Use lastIndexOf() instead.

    \row \o String.find()
    \o This function is not available in Qt Script. Use indexOf() instead.

    \row \o String.findRev()
    \o This function is not available in Qt Script. Use lastIndexOf() and length instead.

    \row \o String.isEmpty()
    \o This function is not available in Qt Script. Use length == 0 instead.

    \row \o String.left()
    \o This function is not available in Qt Script. Use substring() instead.

    \row \o String.lower()
    \o This function is not available in Qt Script. Use toLowerCase() instead.

    \row \o String.mid()
    \o This function is not available in Qt Script. Use substring() instead.

    \row \o String.right()
    \o This function is not available in Qt Script. Use substring() instead.

    \row \o String.searchRev()
    \o This function is not available in Qt Script. Use search() / match() instead.

    \row \o String.startsWith()
    \o This function is not available in Qt Script. Use indexOf() instead.

    \row \o String.upper()
    \o This function is not available in Qt Script. Use toUpperCase() instead.

    \row \o RegExp.valid
    \o This property is not available in Qt Script because it is not
       required; a \c SyntaxError exception is thrown for bad \c RegExp objects.

    \row \o RegExp.empty
    \o This property is not available in Qt Script. Use \c{toString().length == 0} instead.

    \row \o RegExp.matchedLength
    \o This property is not available in Qt Script. RegExp.exec() returns an
       array whose size is the matched length.

    \row \o RegExp.capturedTexts
    \o This property is not available in Qt Script. RegExp.exec() returns an
       array of captured texts.

    \row \o RegExp.search()
    \o This function is not available in Qt Script. Use RegExp.exec() instead.

    \row \o RegExp.searchRev()
    \o This function is not available in Qt Script. Use RegExp.exec() or
       String.search()/match() instead.

    \row \o RegExp.exactMatch()
    \o This function is not available in Qt Script. Use RegExp.exec() instead.

    \row \o RegExp.pos()
    \o This function is not available in Qt Script. Use String.match() instead.

    \row \o RegExp.cap()
    \o This function is not available in Qt Script. RegExp.exec() returns an
       array of captured texts.
    \endtable

    QSA also defined some internal Qt API which is not present in Qt
    Script. The types provided by QSA which are not provided by Qt Script are:

    \list
    \o Rect
    \o Point
    \o Size
    \o Color
    \o Palette
    \o ColorGroup
    \o Font
    \o Pixmap
    \o ByteArray
    \endlist


    \section1 The C++ API of QSA vs Qt Script

    QSA is more than just a scripting engine. It provides project
    management, an editor with completion and a minimalistic IDE to edit
    scriptable projects. Qt Script on the other hand is just a scripting
    engine. This means that equivalents to the classes \c QSEditor,
    \c QSScript, \c QSProject and \c QSWorkbench do not exist in Qt Script.
    QSA also provides some extension APIs through the \c QSUtilFactory and
    \c QSInputDialogFactory. There is also no equivalent to these classes
    in the Qt Script API.


    \section2 Making QObjects Accessible from Scripts

    There are two different ways of making \l{QObject}s accessible from
    scripts in QSA. The first method is via the
    \c QSInterpreter::addTransientObject() and \c QSProject::addObject()
    functions. In this case objects are added to the global namespace of
    the interpreter using their object names as the names of the
    variables.

    \code
    QPushButton *button = new QPushButton();
    button->setObjectName("button");
    interpreter->addTransientObject(button);
    \endcode

    The code above adds the button to the global namespace under the name
    "button". One obvious limitation here is that there is potential for
    either unnamed \l{QObject}s or objects whose names conflict. Qt Script
    provides a more flexible way of adding QObjects to the scripting
    environment.

    \code
    QPushButton *button = new QPushButton();
    QScriptValue scriptButton = engine.newQObject(button);
    engine.globalObject().setProperty("button", scriptButton);
    \endcode

    In the code above we create a QPushButton and wrap it in a script
    value using the function, QScriptEngine::newQObject(). This gives us
    a script value that we put into the global object using the name
    "button". The concept of objects and properties discussed above is
    quite visible here in the public C++ API as well. We have no
    dependency on the object's name and we can also resolve name conflicts
    more gracefully. Here, we operate directly on QScriptValue objects.
    This is the actual object that is being passed around inside
    the script engine, so we actually have low-level access to the
    internal script data structures, far beyond that which is possible
    in QSA. Properties, signals and slots of the QObject are accessible
    to the scripter in Qt Script, just like in QSA.

    The other way to expose \l{QObject}s in QSA was to create a
    \c QSObjectFactory that made it possible to instantiate QObjects from
    scripts.

    Below is listed some code from the filter example in the QSA
    package.

    \code
    ModuleFactory::ModuleFactory()
    {
        registerClass( "ImageSource", &ImgSource::staticMetaObject);
        ...
    }

    QObject *ModuleFactory::create( const QString &type,
        			    const QVariantList &,
        			    QObject * )
    {
        if ( type == "ImageSource" )
            return new ImgSource();
        ...
    }

    ...

    interpreter.addObjectFactory(new ModuleFactory());
    \endcode

    The equivalent in Qt Script is written in much the same way as
    constructors are written in scripts. We register a callback C++
    function under the name "ImageSource" in the global namespace and
    return the QObject from this function:

    \code
    QScriptValue construct_QPushButton(QScriptContext *, QScriptEngine *engine) {
        return engine->newQObject(new QPushButton());
    }

    ...

    QScriptValue constructor = engine.newFunction(construct_QPushButton);
    QScriptValue value =
        engine.newQMetaObject(&QPushButton::staticMetaObject,
                              constructor);
    engine.globalObject().setProperty("QPushButton", value);
    \endcode

    In the Qt Script case we use the same approach that we use to expose
    a QObject, namely via QScriptEngine::newQObject(). This function also
    has the benefit that it is possible to specify if the QObject should
    expose properties and slots of its base class. It is also possible to
    specify custom ownership rules.

    The reader might question why we don't add the constructor function
    directly into the namespace, but create a meta-object script value for
    it in addition. The plain function would certainly be good enough,
    but by creating a QMetaObject based constructor we get the enums on
    QPushButton for free in the QPushButton function object. Exposing
    enums in QSA is rather painful in comparison.

    If we want to add more "static" data to the QPushButton type in Qt
    Script, we're free to add properties, similar to how we did for
    the script. It is also possible to add custom functions to a Qt Script
    QPushButton instance by setting more properties on it, such as making
    the \l{QPushButton::}{setText()} C++ function available. It is also
    possible to acheive this by installing a custom prototype, and be
    memory efficient, as discussed in the script example above.


    \section2 Accessing Non-QObjects

    In QSA, it was possible to expose non-QObjects to QSA by wrapping them
    in a QObject and using either \c QSWrapperFactory or \c QSObjectFactory
    to expose them. Deciding when to use each of these classes could be
    confusing, as one was used for script based construction and the other
    for wrapping function parameters and return values, but in essence they
    did exactly the same thing.

    In Qt Script, providing access to QObjects and non-QObjects is done in
    the same way as shown above, by creating a constructor function, and
    by adding properties or a custom prototype to the constructed object.


    \section2 Data Mapping

    QSA supported a hardcoded set of type mappings which covered most
    of the QVariant types, QObjects and primitives. For more complex type
    signatures, such as the template-based tool classes, it had rather
    limited support. Qt Script is significantly better at type mapping
    and will convert lists of template types into arrays of the
    appropriate types, given that all the types are declared to the
    meta-type system.
*/
