<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (<EMAIL>)
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at <EMAIL>.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

// #define COMPILEDBINDINGS_DEBUG

#include "private/qdeclarativecompiledbindings_p.h"

#include <QtDeclarative/qdeclarativeinfo.h>
#include <private/qdeclarativecontext_p.h>
#include <private/qdeclarativejsast_p.h>
#include <private/qdeclarativejsengine_p.h>
#include <private/qdeclarativeexpression_p.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qdebug.h>
#include <QtCore/qnumeric.h>
#include <private/qdeclarativeanchors_p_p.h>
#include <private/qdeclarativeglobal_p.h>
#include <private/qdeclarativefastproperties_p.h>

QT_BEGIN_NAMESPACE

DEFINE_BOOL_CONFIG_OPTION(qmlExperimental, QML_EXPERIMENTAL);
DEFINE_BOOL_CONFIG_OPTION(qmlDisableOptimizer, QML_DISABLE_OPTIMIZER);
DEFINE_BOOL_CONFIG_OPTION(qmlDisableFastProperties, QML_DISABLE_FAST_PROPERTIES);
DEFINE_BOOL_CONFIG_OPTION(bindingsDump, QML_BINDINGS_DUMP);

Q_GLOBAL_STATIC(QDeclarativeFastProperties, fastProperties);

using namespace QDeclarativeJS;

namespace {
// Supported types: int, qreal, QString (needs constr/destr), QObject*, bool
struct Register {
    void setUndefined() { type = 0; }
    void setUnknownButDefined() { type = -1; }
    void setNaN() { setqreal(qSNaN()); }
    bool isUndefined() const { return type == 0; }

    void setQObject(QObject *o) { *((QObject **)data) = o; type = QMetaType::QObjectStar; }
    QObject *getQObject() const { return *((QObject **)data); }

    void setqreal(qreal v) { *((qreal *)data) = v; type = QMetaType::QReal; }
    qreal getqreal() const { return *((qreal *)data); }

    void setint(int v) { *((int *)data) = v; type = QMetaType::Int; }
    int getint() const { return *((int *)data); }

    void setbool(bool v) { *((bool *)data) = v; type = QMetaType::Bool; }
    bool getbool() const { return *((bool *)data); }

    QVariant *getvariantptr() { return (QVariant *)typeDataPtr(); }
    QString *getstringptr() { return (QString *)typeDataPtr(); }
    QUrl *geturlptr() { return (QUrl *)typeDataPtr(); }
    const QVariant *getvariantptr() const { return (QVariant *)typeDataPtr(); }
    const QString *getstringptr() const { return (QString *)typeDataPtr(); }
    const QUrl *geturlptr() const { return (QUrl *)typeDataPtr(); }

    void *typeDataPtr() { return (void *)&data; }
    void *typeMemory() { return (void *)data; }
    const void *typeDataPtr() const { return (void *)&data; }
    const void *typeMemory() const { return (void *)data; }

    int gettype() const { return type; }
    void settype(int t) { type = t; }

    int type;          // Optional type
    void *data[2];     // Object stored here
};
}

class QDeclarativeCompiledBindingsPrivate : public QObjectPrivate
{
    Q_DECLARE_PUBLIC(QDeclarativeCompiledBindings)

public:
    QDeclarativeCompiledBindingsPrivate();
    virtual ~QDeclarativeCompiledBindingsPrivate();

    struct Binding : public QDeclarativeAbstractBinding, public QDeclarativeDelayedError {
        Binding() : enabled(false), updating(0), property(0),
                    scope(0), target(0), parent(0) {}

        // Inherited from QDeclarativeAbstractBinding
        virtual void setEnabled(bool, QDeclarativePropertyPrivate::WriteFlags flags);
        virtual int propertyIndex();
        virtual void update(QDeclarativePropertyPrivate::WriteFlags flags);
        virtual void destroy();

        int index:30;
        bool enabled:1;
        bool updating:1;
        int property;
        QObject *scope;
        QObject *target;

        QDeclarativeCompiledBindingsPrivate *parent;
    };

    typedef QDeclarativeNotifierEndpoint Subscription;
    Subscription *subscriptions;
    QScriptDeclarativeClass::PersistentIdentifier *identifiers;

    void run(Binding *, QDeclarativePropertyPrivate::WriteFlags flags);

    const char *programData;
    Binding *m_bindings;
    quint32 *m_signalTable;

    static int methodCount;

    void init();
    void run(int instr, QDeclarativeContextData *context, 
             QDeclarativeDelayedError *error, QObject *scope, QObject *output, QDeclarativePropertyPrivate::WriteFlags storeFlags);


    inline void unsubscribe(int subIndex);
    inline void subscribeId(QDeclarativeContextData *p, int idIndex, int subIndex);
    inline void subscribe(QObject *o, int notifyIndex, int subIndex);

    QDeclarativePropertyCache::Data *findproperty(QObject *obj, 
                                                  const QScriptDeclarativeClass::Identifier &name,
                                                  QDeclarativeEnginePrivate *enginePriv, 
                                                  QDeclarativePropertyCache::Data &local);
    bool findproperty(QObject *obj, 
                      Register *output, 
                      QDeclarativeEnginePrivate *enginePriv,
                      int subIdx, 
                      const QScriptDeclarativeClass::Identifier &name,
                      bool isTerminal);
    void findgeneric(Register *output,                                 // value output
                     int subIdx,                                       // Subscription index in config
                     QDeclarativeContextData *context,                 // Context to search in
                     const QScriptDeclarativeClass::Identifier &name, 
                     bool isTerminal);
};

QDeclarativeCompiledBindingsPrivate::QDeclarativeCompiledBindingsPrivate()
: subscriptions(0), identifiers(0)
{
}

QDeclarativeCompiledBindingsPrivate::~QDeclarativeCompiledBindingsPrivate()
{
    delete [] subscriptions; subscriptions = 0;
    delete [] identifiers; identifiers = 0;
}

int QDeclarativeCompiledBindingsPrivate::methodCount = -1;

QDeclarativeCompiledBindings::QDeclarativeCompiledBindings(const char *program, QDeclarativeContextData *context)
: QObject(*(new QDeclarativeCompiledBindingsPrivate))
{
    Q_D(QDeclarativeCompiledBindings);

    if (d->methodCount == -1)
        d->methodCount = QDeclarativeCompiledBindings::staticMetaObject.methodCount();

    d->programData = program;

    d->init();

    QDeclarativeAbstractExpression::setContext(context);
}

QDeclarativeCompiledBindings::~QDeclarativeCompiledBindings()
{
    Q_D(QDeclarativeCompiledBindings);

    delete [] d->m_bindings;
}

QDeclarativeAbstractBinding *QDeclarativeCompiledBindings::configBinding(int index, QObject *target, 
                                                        QObject *scope, int property)
{
    Q_D(QDeclarativeCompiledBindings);

    QDeclarativeCompiledBindingsPrivate::Binding *rv = d->m_bindings + index;

    rv->index = index;
    rv->property = property;
    rv->target = target;
    rv->scope = scope;
    rv->parent = d;

    addref(); // This is decremented in Binding::destroy()

    return rv;
}

void QDeclarativeCompiledBindingsPrivate::Binding::setEnabled(bool e, QDeclarativePropertyPrivate::WriteFlags flags)
{
    if (e) {
        addToObject(target);
    } else {
        removeFromObject();
    }

    QDeclarativeAbstractBinding::setEnabled(e, flags);

    if (enabled != e) {
        enabled = e;

        if (e) update(flags);
    }
}

int QDeclarativeCompiledBindingsPrivate::Binding::propertyIndex()
{
    return property & 0xFFFF;
}

void QDeclarativeCompiledBindingsPrivate::Binding::update(QDeclarativePropertyPrivate::WriteFlags flags)
{
    parent->run(this, flags);
}

void QDeclarativeCompiledBindingsPrivate::Binding::destroy()
{
    enabled = false;
    removeFromObject();
    clear();
    parent->q_func()->release();
}

int QDeclarativeCompiledBindings::qt_metacall(QMetaObject::Call c, int id, void **)
{
    Q_D(QDeclarativeCompiledBindings);

    if (c == QMetaObject::InvokeMetaMethod && id >= d->methodCount) {
        id -= d->methodCount;

        quint32 *reeval = d->m_signalTable + d->m_signalTable[id];
        quint32 count = *reeval;
        ++reeval;
        for (quint32 ii = 0; ii < count; ++ii) {
            d->run(d->m_bindings + reeval[ii], QDeclarativePropertyPrivate::DontRemoveBinding);
        }
    }
    return -1;
}

void QDeclarativeCompiledBindingsPrivate::run(Binding *binding, QDeclarativePropertyPrivate::WriteFlags flags)
{
    Q_Q(QDeclarativeCompiledBindings);

    if (!binding->enabled)
        return;

    QDeclarativeContextData *context = q->QDeclarativeAbstractExpression::context();
    if (!context) {
        qWarning("QDeclarativeCompiledBindings: Attempted to evaluate an expression in an invalid context");
        return;
    }

    if (!context->engine)
        return;

    if (binding->updating) {
        QString name;
        if (binding->property & 0xFFFF0000) {
            QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine);

            QDeclarativeValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF];
            Q_ASSERT(vt);

            name = QLatin1String(binding->target->metaObject()->property(binding->property & 0xFFFF).name());
            name.append(QLatin1String("."));
            name.append(QLatin1String(vt->metaObject()->property(binding->property >> 24).name()));
        } else {
            name = QLatin1String(binding->target->metaObject()->property(binding->property).name());
        }
        qmlInfo(binding->target) << QCoreApplication::translate("QDeclarativeCompiledBindings", "Binding loop detected for property \"%1\"").arg(name);<commit_msg>Compiled bindings should not print warnings where normal bindings don't<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (<EMAIL>)
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at <EMAIL>.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

// #define COMPILEDBINDINGS_DEBUG

#include "private/qdeclarativecompiledbindings_p.h"

#include <QtDeclarative/qdeclarativeinfo.h>
#include <private/qdeclarativecontext_p.h>
#include <private/qdeclarativejsast_p.h>
#include <private/qdeclarativejsengine_p.h>
#include <private/qdeclarativeexpression_p.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qdebug.h>
#include <QtCore/qnumeric.h>
#include <private/qdeclarativeanchors_p_p.h>
#include <private/qdeclarativeglobal_p.h>
#include <private/qdeclarativefastproperties_p.h>

QT_BEGIN_NAMESPACE

DEFINE_BOOL_CONFIG_OPTION(qmlExperimental, QML_EXPERIMENTAL);
DEFINE_BOOL_CONFIG_OPTION(qmlDisableOptimizer, QML_DISABLE_OPTIMIZER);
DEFINE_BOOL_CONFIG_OPTION(qmlDisableFastProperties, QML_DISABLE_FAST_PROPERTIES);
DEFINE_BOOL_CONFIG_OPTION(bindingsDump, QML_BINDINGS_DUMP);

Q_GLOBAL_STATIC(QDeclarativeFastProperties, fastProperties);

using namespace QDeclarativeJS;

namespace {
// Supported types: int, qreal, QString (needs constr/destr), QObject*, bool
struct Register {
    void setUndefined() { type = 0; }
    void setUnknownButDefined() { type = -1; }
    void setNaN() { setqreal(qSNaN()); }
    bool isUndefined() const { return type == 0; }

    void setQObject(QObject *o) { *((QObject **)data) = o; type = QMetaType::QObjectStar; }
    QObject *getQObject() const { return *((QObject **)data); }

    void setqreal(qreal v) { *((qreal *)data) = v; type = QMetaType::QReal; }
    qreal getqreal() const { return *((qreal *)data); }

    void setint(int v) { *((int *)data) = v; type = QMetaType::Int; }
    int getint() const { return *((int *)data); }

    void setbool(bool v) { *((bool *)data) = v; type = QMetaType::Bool; }
    bool getbool() const { return *((bool *)data); }

    QVariant *getvariantptr() { return (QVariant *)typeDataPtr(); }
    QString *getstringptr() { return (QString *)typeDataPtr(); }
    QUrl *geturlptr() { return (QUrl *)typeDataPtr(); }
    const QVariant *getvariantptr() const { return (QVariant *)typeDataPtr(); }
    const QString *getstringptr() const { return (QString *)typeDataPtr(); }
    const QUrl *geturlptr() const { return (QUrl *)typeDataPtr(); }

    void *typeDataPtr() { return (void *)&data; }
    void *typeMemory() { return (void *)data; }
    const void *typeDataPtr() const { return (void *)&data; }
    const void *typeMemory() const { return (void *)data; }

    int gettype() const { return type; }
    void settype(int t) { type = t; }

    int type;          // Optional type
    void *data[2];     // Object stored here
};
}

class QDeclarativeCompiledBindingsPrivate : public QObjectPrivate
{
    Q_DECLARE_PUBLIC(QDeclarativeCompiledBindings)

public:
    QDeclarativeCompiledBindingsPrivate();
    virtual ~QDeclarativeCompiledBindingsPrivate();

    struct Binding : public QDeclarativeAbstractBinding, public QDeclarativeDelayedError {
        Binding() : enabled(false), updating(0), property(0),
                    scope(0), target(0), parent(0) {}

        // Inherited from QDeclarativeAbstractBinding
        virtual void setEnabled(bool, QDeclarativePropertyPrivate::WriteFlags flags);
        virtual int propertyIndex();
        virtual void update(QDeclarativePropertyPrivate::WriteFlags flags);
        virtual void destroy();

        int index:30;
        bool enabled:1;
        bool updating:1;
        int property;
        QObject *scope;
        QObject *target;

        QDeclarativeCompiledBindingsPrivate *parent;
    };

    typedef QDeclarativeNotifierEndpoint Subscription;
    Subscription *subscriptions;
    QScriptDeclarativeClass::PersistentIdentifier *identifiers;

    void run(Binding *, QDeclarativePropertyPrivate::WriteFlags flags);

    const char *programData;
    Binding *m_bindings;
    quint32 *m_signalTable;

    static int methodCount;

    void init();
    void run(int instr, QDeclarativeContextData *context, 
             QDeclarativeDelayedError *error, QObject *scope, QObject *output, QDeclarativePropertyPrivate::WriteFlags storeFlags);


    inline void unsubscribe(int subIndex);
    inline void subscribeId(QDeclarativeContextData *p, int idIndex, int subIndex);
    inline void subscribe(QObject *o, int notifyIndex, int subIndex);

    QDeclarativePropertyCache::Data *findproperty(QObject *obj, 
                                                  const QScriptDeclarativeClass::Identifier &name,
                                                  QDeclarativeEnginePrivate *enginePriv, 
                                                  QDeclarativePropertyCache::Data &local);
    bool findproperty(QObject *obj, 
                      Register *output, 
                      QDeclarativeEnginePrivate *enginePriv,
                      int subIdx, 
                      const QScriptDeclarativeClass::Identifier &name,
                      bool isTerminal);
    void findgeneric(Register *output,                                 // value output
                     int subIdx,                                       // Subscription index in config
                     QDeclarativeContextData *context,                 // Context to search in
                     const QScriptDeclarativeClass::Identifier &name, 
                     bool isTerminal);
};

QDeclarativeCompiledBindingsPrivate::QDeclarativeCompiledBindingsPrivate()
: subscriptions(0), identifiers(0)
{
}

QDeclarativeCompiledBindingsPrivate::~QDeclarativeCompiledBindingsPrivate()
{
    delete [] subscriptions; subscriptions = 0;
    delete [] identifiers; identifiers = 0;
}

int QDeclarativeCompiledBindingsPrivate::methodCount = -1;

QDeclarativeCompiledBindings::QDeclarativeCompiledBindings(const char *program, QDeclarativeContextData *context)
: QObject(*(new QDeclarativeCompiledBindingsPrivate))
{
    Q_D(QDeclarativeCompiledBindings);

    if (d->methodCount == -1)
        d->methodCount = QDeclarativeCompiledBindings::staticMetaObject.methodCount();

    d->programData = program;

    d->init();

    QDeclarativeAbstractExpression::setContext(context);
}

QDeclarativeCompiledBindings::~QDeclarativeCompiledBindings()
{
    Q_D(QDeclarativeCompiledBindings);

    delete [] d->m_bindings;
}

QDeclarativeAbstractBinding *QDeclarativeCompiledBindings::configBinding(int index, QObject *target, 
                                                        QObject *scope, int property)
{
    Q_D(QDeclarativeCompiledBindings);

    QDeclarativeCompiledBindingsPrivate::Binding *rv = d->m_bindings + index;

    rv->index = index;
    rv->property = property;
    rv->target = target;
    rv->scope = scope;
    rv->parent = d;

    addref(); // This is decremented in Binding::destroy()

    return rv;
}

void QDeclarativeCompiledBindingsPrivate::Binding::setEnabled(bool e, QDeclarativePropertyPrivate::WriteFlags flags)
{
    if (e) {
        addToObject(target);
    } else {
        removeFromObject();
    }

    QDeclarativeAbstractBinding::setEnabled(e, flags);

    if (enabled != e) {
        enabled = e;

        if (e) update(flags);
    }
}

int QDeclarativeCompiledBindingsPrivate::Binding::propertyIndex()
{
    return property & 0xFFFF;
}

void QDeclarativeCompiledBindingsPrivate::Binding::update(QDeclarativePropertyPrivate::WriteFlags flags)
{
    parent->run(this, flags);
}

void QDeclarativeCompiledBindingsPrivate::Binding::destroy()
{
    enabled = false;
    removeFromObject();
    clear();
    parent->q_func()->release();
}

int QDeclarativeCompiledBindings::qt_metacall(QMetaObject::Call c, int id, void **)
{
    Q_D(QDeclarativeCompiledBindings);

    if (c == QMetaObject::InvokeMetaMethod && id >= d->methodCount) {
        id -= d->methodCount;

        quint32 *reeval = d->m_signalTable + d->m_signalTable[id];
        quint32 count = *reeval;
        ++reeval;
        for (quint32 ii = 0; ii < count; ++ii) {
            d->run(d->m_bindings + reeval[ii], QDeclarativePropertyPrivate::DontRemoveBinding);
        }
    }
    return -1;
}

void QDeclarativeCompiledBindingsPrivate::run(Binding *binding, QDeclarativePropertyPrivate::WriteFlags flags)
{
    Q_Q(QDeclarativeCompiledBindings);

    if (!binding->enabled)
        return;

    QDeclarativeContextData *context = q->QDeclarativeAbstractExpression::context();
    if (!context) 
        return;

    if (!context->engine)
        return;

    if (binding->updating) {
        QString name;
        if (binding->property & 0xFFFF0000) {
            QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine);

            QDeclarativeValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF];
            Q_ASSERT(vt);

            name = QLatin1String(binding->target->metaObject()->property(binding->property & 0xFFFF).name());
            name.append(QLatin1String("."));
            name.append(QLatin1String(vt->metaObject()->property(binding->property >> 24).name()));
        } else {
            name = QLatin1String(binding->target->metaObject()->property(binding->property).name());
        }
        qmlInfo(binding->target) << QCoreApplication::translate("QDeclarativeCompiledBindings", "Binding loop detected for property \"%1\"").arg(name);
{'fraction_non_alphanumeric': 0.12259414225941423, 'fraction_numerical': 0.005392840539284054, 'mean_word_length': 3.5257731958762886, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 119, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 22, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2270098', 'n_tokens_mistral': 6360, 'n_tokens_neox': 6102, 'n_words': 1470}