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; }
/*! 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); }
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); } }
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); }
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); } }
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); }
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))); }
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); }
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; }
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(); }
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); }
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; } }