void QEnginioCollectionObjectPrivate::QmlCallbackFunctor::operator ()(QEnginioOperationObject *aOperation)
{
    using namespace QV4;

    if (!aOperation)
        return;

    if (iCallback.isCallable()) {
        QJSValuePrivate *prv=QJSValuePrivate::get(iCallback);
        FunctionObject *f =prv->value.asFunctionObject();

        if (f) {
            ExecutionEngine *engine = prv->engine;
            Q_ASSERT(engine);

            Scope scope(engine);
            ScopedCallData callData(scope, 1); // args.length());
            callData->thisObject = engine->globalObject->asReturnedValue();

            ScopedValue result(scope);
            QV4::ExecutionContext *ctx = engine->currentContext();

            callData->args[0] = QObjectWrapper::wrap(engine,aOperation);

            result = f->call(callData);
            if (scope.hasException()) {
                result = ctx->catchException();
            }
            QJSValue tmp(new QJSValuePrivate(engine, result));
        }
    }

    delete aOperation;
}
Beispiel #2
0
/*!
  Creates a new \c{Object} and calls this QJSValue as a
  constructor, using the created object as the `this' object and
  passing \a args as arguments. If the return value from the
  constructor call is an object, then that object is returned;
  otherwise the default constructed object is returned.

  If this QJSValue is not a function, callAsConstructor() does
  nothing and returns an undefined QJSValue.

  Calling this function can cause an exception to occur in the
  script engine; in that case, the value that was thrown
  (typically an \c{Error} object) is returned. You can call
  isError() on the return value to determine whether an
  exception occurred.

  \sa call(), QJSEngine::newObject()
*/
QJSValue QJSValue::callAsConstructor(const QJSValueList &args)
{
    FunctionObject *f = d->value.asFunctionObject();
    if (!f)
        return QJSValue();

    ExecutionEngine *engine = d->engine;
    assert(engine);

    Scope scope(engine);
    ScopedCallData callData(scope, args.size());
    for (int i = 0; i < args.size(); ++i) {
        if (!args.at(i).d->checkEngine(engine)) {
            qWarning("QJSValue::callAsConstructor() failed: cannot construct function with argument created in a different engine");
            return QJSValue();
        }
        callData->args[i] = args.at(i).d->getValue(engine);
    }

    ScopedValue result(scope);
    QV4::ExecutionContext *ctx = engine->currentContext();
    result = f->construct(callData);
    if (scope.hasException())
        result = ctx->catchException();

    return new QJSValuePrivate(engine, result);
}
Beispiel #3
0
void VariantDB::CallFunctionIfExists( const string &keyName, VariantList *pVList )
{
	FunctionObject *pFunc = GetFunctionIfExists(keyName);
	if (pFunc)
	{
		pFunc->sig_function(pVList);
	}
}
int main()
{
	int x = 3, xSquared, xSquaredAgain;
	FunctionObject square;

	xSquared = square(x); // Call the function-call operator
	xSquaredAgain = square.doSquare(x); // Call the normal method

	return 0;
}
void EntityComponent::OnRemove()
{
	FunctionObject *pFunc = GetShared()->GetFunctionIfExists("OnDelete");
	if (pFunc)
	{
		//looks like someone wanted notification
		VariantList vList(this);
        pFunc->m_sig_function(&vList);
	}
}
Beispiel #6
0
FunctionObject*
Curry::evaluate(Thread& t,
                FunctionObject* inObj,
                const Function::ArgumentVector& args,
                const vector<bool>& mask,
                bool dynamicDispatch)
{
    //
    //  Never do partial application on the result of a lambda
    //  expression (its too difficult to archive). Instead do partial
    //  evaluation. The good side is that there will never be more
    //  than one level of indirection in multiple-curried lambda
    //  expressions. the bad side is that there will be more overhead
    //  upfront.
    //

    Process*        p     = t.process();
    const Function* F     = inObj->function();
    const bool      apply = !F->isLambda();

    try
    {
        if (apply)
        {
            PartialApplicator evaluator(F, p, &t, args, mask, dynamicDispatch);

            const FunctionType* rt = evaluator.result()->type();
            FunctionObject* outObj = new FunctionObject(rt);
            outObj->setDependent(inObj);
            outObj->setFunction(evaluator.result());
            return outObj;
        }
        else
        {
            FunctionSpecializer evaluator(F, p, &t);
            evaluator.partiallyEvaluate(args, mask);

            const FunctionType* rt = evaluator.result()->type();
            FunctionObject* outObj = new FunctionObject(rt);
            outObj->setFunction(evaluator.result());
            return outObj;
        }
    }
    catch (Exception& e)
    {
        ProgramException exc(t);
        exc.message() = e.message();
        exc.message() += " during partial ";
        exc.message() += (apply ? "application" : "evaluation");
        exc.message() += " of ";
        exc.message() += F->name().c_str();
        throw exc;
    }
}
ReturnedValue Object::getValue(const ValueRef thisObject, const Property *p, PropertyAttributes attrs)
{
    if (!attrs.isAccessor())
        return p->value.asReturnedValue();
    FunctionObject *getter = p->getter();
    if (!getter)
        return Encode::undefined();

    Scope scope(getter->engine());
    ScopedCallData callData(scope, 0);
    callData->thisObject = *thisObject;
    return getter->call(callData);
}
Beispiel #8
0
ReturnedValue Script::run()
{
    struct ContextStateSaver {
        ExecutionContext *savedContext;
        bool strictMode;
        Lookup *lookups;
        CompiledData::CompilationUnit *compilationUnit;

        ContextStateSaver(ExecutionContext *context)
            : savedContext(context)
            , strictMode(context->strictMode)
            , lookups(context->lookups)
            , compilationUnit(context->compilationUnit)
        {}

        ~ContextStateSaver()
        {
            savedContext->strictMode = strictMode;
            savedContext->lookups = lookups;
            savedContext->compilationUnit = compilationUnit;
        }
    };

    if (!parsed)
        parse();
    if (!vmFunction)
        return Encode::undefined();

    QV4::ExecutionEngine *engine = scope->engine;
    QV4::Scope valueScope(engine);

    if (qml.isUndefined()) {
        TemporaryAssignment<Function*> savedGlobalCode(engine->globalCode, vmFunction);

        ExecutionContextSaver ctxSaver(scope);
        ContextStateSaver stateSaver(scope);
        scope->strictMode = vmFunction->isStrict();
        scope->lookups = vmFunction->compilationUnit->runtimeLookups;
        scope->compilationUnit = vmFunction->compilationUnit;

        return vmFunction->code(scope, vmFunction->codeData);
    } else {
        ScopedObject qmlObj(valueScope, qml.value());
        FunctionObject *f = new (engine->memoryManager) QmlBindingWrapper(scope, vmFunction, qmlObj);
        ScopedCallData callData(valueScope, 0);
        callData->thisObject = Primitive::undefinedValue();
        return f->call(callData);
    }
}
Beispiel #9
0
ReturnedValue FunctionPrototype::method_call(CallContext *ctx)
{
    Scope scope(ctx);

    FunctionObject *o = ctx->callData->thisObject.asFunctionObject();
    if (!o)
        return ctx->throwTypeError();

    ScopedCallData callData(scope, ctx->callData->argc ? ctx->callData->argc - 1 : 0);
    if (ctx->callData->argc) {
        std::copy(ctx->callData->args + 1,
                  ctx->callData->args + ctx->callData->argc, callData->args);
    }
    callData->thisObject = ctx->argument(0);
    return o->call(callData);
}
ReturnedValue DatePrototype::method_toJSON(CallContext *ctx)
{
    Scope scope(ctx);
    ScopedValue O(scope, RuntimeHelpers::toObject(ctx, ValueRef(&ctx->d()->callData->thisObject)));
    ScopedValue tv(scope, RuntimeHelpers::toPrimitive(O, NUMBER_HINT));

    if (tv->isNumber() && !std::isfinite(tv->toNumber()))
        return Encode::null();

    ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("toISOString")));
    ScopedValue v(scope, O->objectValue()->get(s.getPointer()));
    FunctionObject *toIso = v->asFunctionObject();

    if (!toIso)
        return ctx->throwTypeError();

    ScopedCallData callData(scope, 0);
    callData->thisObject = ctx->d()->callData->thisObject;
    return toIso->call(callData);
}
Beispiel #11
0
NODE_IMPLEMENTATION(Curry::node, Pointer)
{
    Process*                 p = NODE_THREAD.process();
    Context*                 c = p->context();
    FunctionObject*          o = NODE_ARG_OBJECT(1, FunctionObject);
    bool                     d = NODE_ARG(2, bool);
    const Function*          F = o->function();
    Function::ArgumentVector args(F->numArgs() + F->numFreeVariables());
    vector<bool>             mask(args.size());

    for (int i=0, s=args.size(); i < s; i++)
    {
        mask[i] = NODE_THIS.argNode(i+3)->symbol() != c->noop();

        if (mask[i])
        {
            args[i] = NODE_ANY_TYPE_ARG(i+3);
        }
    }

    NODE_RETURN(Pointer(evaluate(NODE_THREAD, o, args, mask, d)));
}
Beispiel #12
0
ReturnedValue FunctionPrototype::method_apply(CallContext *ctx)
{
    Scope scope(ctx);
    FunctionObject *o = ctx->callData->thisObject.asFunctionObject();
    if (!o)
        return ctx->throwTypeError();

    ScopedValue arg(scope, ctx->argument(1));

    ScopedObject arr(scope, arg);

    quint32 len;
    if (!arr) {
        len = 0;
        if (!arg->isNullOrUndefined())
            return ctx->throwTypeError();
    } else {
        len = ArrayPrototype::getLength(ctx, arr);
    }

    ScopedCallData callData(scope, len);

    if (len) {
        if (!(arr->flags & SimpleArray) || arr->protoHasArray() || arr->hasAccessorProperty) {
            for (quint32 i = 0; i < len; ++i)
                callData->args[i] = arr->getIndexed(i);
        } else {
            int alen = qMin(len, arr->arrayDataLen);
            for (int i = 0; i < alen; ++i)
                callData->args[i] = arr->arrayData[i].value;
            for (quint32 i = alen; i < len; ++i)
                callData->args[i] = Primitive::undefinedValue();
        }
    }

    callData->thisObject = ctx->argument(0);
    return o->call(callData);
}
Beispiel #13
0
bool ExecutionContext::deleteProperty(String *name)
{
    Scope scope(this);
    bool hasWith = false;
    for (ExecutionContext *ctx = this; ctx; ctx = ctx->d()->outer) {
        if (ctx->d()->type == Type_WithContext) {
            hasWith = true;
            WithContext *w = static_cast<WithContext *>(ctx);
            if (w->d()->withObject->hasProperty(name))
                return w->d()->withObject->deleteProperty(name);
        } else if (ctx->d()->type == Type_CatchContext) {
            CatchContext *c = static_cast<CatchContext *>(ctx);
            if (c->d()->exceptionVarName->isEqualTo(name))
                return false;
        } else if (ctx->d()->type >= Type_CallContext) {
            CallContext *c = static_cast<CallContext *>(ctx);
            FunctionObject *f = c->d()->function;
            if (f->needsActivation() || hasWith) {
                uint index = f->function()->internalClass->find(name);
                if (index < UINT_MAX)
                    // ### throw in strict mode?
                    return false;
            }
            if (c->d()->activation && c->d()->activation->hasProperty(name))
                return c->d()->activation->deleteProperty(name);
        } else if (ctx->d()->type == Type_GlobalContext) {
            GlobalContext *g = static_cast<GlobalContext *>(ctx);
            if (g->d()->global->hasProperty(name))
                return g->d()->global->deleteProperty(name);
        }
    }

    if (d()->strictMode)
        throwSyntaxError(QStringLiteral("Can't delete property %1").arg(name->toQString()));
    return true;
}
Beispiel #14
0
NODE_IMPLEMENTATION(DynamicPartialEvaluate::node, Pointer)
{
    typedef FunctionSpecializer Generator;

    FunctionObject* f = NODE_ARG_OBJECT(1, FunctionObject);
    Generator::ArgumentVector args(f->function()->numArgs() +
                                   f->function()->numFreeVariables());
    Generator::ArgumentMask   mask(args.size());
    Process* p = NODE_THREAD.process();
    Context* c = p->context();

    for (int i=0; i < args.size(); i++)
    {
        mask[i] = NODE_THIS.argNode(i+2)->symbol() != c->noop();

        if (mask[i])
        {
            args[i] = NODE_ANY_TYPE_ARG(i+2);
        }
    }

    try
    {
        Generator evaluator(f->function(), p, &NODE_THREAD);
        evaluator.partiallyEvaluate(args, mask);

        const FunctionType* rt = evaluator.result()->type();
        assert(rt == NODE_THIS.argNode(0)->type());
        FunctionObject* o = new FunctionObject(rt);
        o->setFunction(evaluator.result());
        NODE_RETURN(Pointer(o));
    }
    catch (Exception& e)
    {
        ProgramException exc(NODE_THREAD);
        exc.message() = e.message();
        exc.message() += " during partial evaluation of ";
        exc.message() += f->function()->name().c_str();
        throw exc;
    }
}
QString Stringify::Str(const QString &key, ValueRef v)
{
    Scope scope(ctx);

    ScopedValue value(scope, *v);
    ScopedObject o(scope, value);
    if (o) {
        ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("toJSON")));
        Scoped<FunctionObject> toJSON(scope, o->get(s.getPointer()));
        if (!!toJSON) {
            ScopedCallData callData(scope, 1);
            callData->thisObject = value;
            callData->args[0] = ctx->d()->engine->newString(key);
            value = toJSON->call(callData);
        }
    }

    if (replacerFunction) {
        ScopedObject holder(scope, ctx->d()->engine->newObject());
        holder->put(ctx, QString(), value);
        ScopedCallData callData(scope, 2);
        callData->args[0] = ctx->d()->engine->newString(key);
        callData->args[1] = value;
        callData->thisObject = holder;
        value = replacerFunction->call(callData);
    }

    o = value.asReturnedValue();
    if (o) {
        if (NumberObject *n = o->asNumberObject())
            value = n->value();
        else if (StringObject *so = o->asStringObject())
            value = so->d()->value;
        else if (BooleanObject *b =o->asBooleanObject())
            value = b->value();
    }

    if (value->isNull())
        return QStringLiteral("null");
    if (value->isBoolean())
        return value->booleanValue() ? QStringLiteral("true") : QStringLiteral("false");
    if (value->isString())
        return quote(value->stringValue()->toQString());

    if (value->isNumber()) {
        double d = value->toNumber();
        return std::isfinite(d) ? value->toString(ctx)->toQString() : QStringLiteral("null");
    }

    o = value.asReturnedValue();
    if (o) {
        if (!o->asFunctionObject()) {
            if (o->asArrayObject()) {
                ScopedArrayObject a(scope, o);
                return JA(a);
            } else {
                return JO(o);
            }
        }
    }

    return QString();
}
Beispiel #16
0
ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Object *&base)
{
    Scope scope(this);
    ScopedValue v(scope);
    base = (Object *)0;
    name->makeIdentifier();

    if (name->equals(d()->engine->id_this.getPointer()))
        return d()->callData->thisObject.asReturnedValue();

    bool hasWith = false;
    bool hasCatchScope = false;
    for (ExecutionContext *ctx = this; ctx; ctx = ctx->d()->outer) {
        if (ctx->d()->type == Type_WithContext) {
            Object *w = static_cast<WithContext *>(ctx)->d()->withObject;
            hasWith = true;
            bool hasProperty = false;
            v = w->get(name, &hasProperty);
            if (hasProperty) {
                base = w;
                return v.asReturnedValue();
            }
            continue;
        }

        else if (ctx->d()->type == Type_CatchContext) {
            hasCatchScope = true;
            CatchContext *c = static_cast<CatchContext *>(ctx);
            if (c->d()->exceptionVarName->isEqualTo(name))
                return c->d()->exceptionValue.asReturnedValue();
        }

        else if (ctx->d()->type >= Type_CallContext) {
            QV4::CallContext *c = static_cast<CallContext *>(ctx);
            FunctionObject *f = c->d()->function;
            if (f->function() && (f->needsActivation() || hasWith || hasCatchScope)) {
                uint index = f->function()->internalClass->find(name);
                if (index < UINT_MAX) {
                    if (index < c->d()->function->formalParameterCount())
                        return c->d()->callData->args[c->d()->function->formalParameterCount() - index - 1].asReturnedValue();
                    return c->d()->locals[index - c->d()->function->formalParameterCount()].asReturnedValue();
                }
            }
            if (c->d()->activation) {
                bool hasProperty = false;
                v = c->d()->activation->get(name, &hasProperty);
                if (hasProperty) {
                    if (ctx->d()->type == Type_QmlContext)
                        base = c->d()->activation;
                    return v.asReturnedValue();
                }
            }
            if (f->function() && f->function()->isNamedExpression()
                && name->equals(f->function()->name()))
                return c->d()->function->asReturnedValue();
        }

        else if (ctx->d()->type == Type_GlobalContext) {
            GlobalContext *g = static_cast<GlobalContext *>(ctx);
            bool hasProperty = false;
            v = g->d()->global->get(name, &hasProperty);
            if (hasProperty)
                return v.asReturnedValue();
        }
    }
    ScopedValue n(scope, name);
    return throwReferenceError(n);
}
Beispiel #17
0
NODE_IMPLEMENTATION(DynamicPartialApplication::node, Pointer)
{
    //
    //  Never do partial application on the result of a lambda
    //  expression (its too difficult to archive). Instead do
    //  partial evaluation. The good side is that there will never
    //  be more than one level of indirection in multiple-curried
    //  lambda expressions. the bad side is that there will be
    //  more overhead upfront.
    //

    Process* p = NODE_THREAD.process();
    Context* c = p->context();
    FunctionObject* f = NODE_ARG_OBJECT(1, FunctionObject);
    bool apply = f->function()->isLambda();

    try
    {
        if (apply)
        {
            typedef PartialApplicator Generator;
            Generator::ArgumentVector args(f->function()->numArgs() +
                                           f->function()->numFreeVariables());
            Generator::ArgumentMask   mask(args.size());

            for (int i=0; i < args.size(); i++)
            {
                mask[i] = NODE_THIS.argNode(i+2)->symbol() != c->noop();
                if (mask[i])
                {
                    args[i] = NODE_ANY_TYPE_ARG(i+2);
                }
            }

            Generator evaluator(f->function(), p, &NODE_THREAD, args, mask);

            const FunctionType* rt = evaluator.result()->type();
            assert(rt == NODE_THIS.argNode(0)->type());
            FunctionObject* o = new FunctionObject(rt);
            o->setDependent(f);
            o->setFunction(evaluator.result());
            NODE_RETURN(Pointer(o));
        }
        else
        {
            typedef FunctionSpecializer Generator;
            Generator::ArgumentVector args(f->function()->numArgs() +
                                           f->function()->numFreeVariables());
            Generator::ArgumentMask   mask(args.size());

            for (int i=0; i < args.size(); i++)
            {
                mask[i] = NODE_THIS.argNode(i+2)->symbol() != c->noop();

                if (mask[i])
                {
                    args[i] = NODE_ANY_TYPE_ARG(i+2);
                }
            }

            Generator evaluator(f->function(), p, &NODE_THREAD);
            evaluator.partiallyEvaluate(args, mask);

            const FunctionType* rt = evaluator.result()->type();
            assert(rt == NODE_THIS.argNode(0)->type());
            FunctionObject* o = new FunctionObject(rt);
            o->setFunction(evaluator.result());
            NODE_RETURN(Pointer(o));
        }
    }
    catch (Exception& e)
    {
        ProgramException exc(NODE_THREAD);
        exc.message() = e.message();
        exc.message() += " during partial ";
        exc.message() += (apply ? "application" : "evaluation");
        exc.message() += " of ";
        exc.message() += f->function()->name().c_str();
        throw exc;
    }
}