/*! Evaluates \a program, using \a lineNumber as the base line number, and returns the result of the evaluation. The script code will be evaluated in the context of the global object. The evaluation of \a program can cause an \l{Script Exceptions}{exception} in the engine; in this case the return value will be the exception that was thrown (typically an \c{Error} object; see QJSValue::isError()). \a lineNumber is used to specify a starting line number for \a program; line number information reported by the engine that pertains to this evaluation will be based on this argument. For example, if \a program consists of two lines of code, and the statement on the second line causes a script exception, the exception line number would be \a lineNumber plus one. When no starting line number is specified, line numbers will be 1-based. \a fileName is used for error reporting. For example, in error objects the file name is accessible through the "fileName" property if it is provided with this function. \note If an exception was thrown and the exception value is not an Error instance (i.e., QJSValue::isError() returns \c false), the exception value will still be returned, but there is currently no API for detecting that an exception did occur in this case. */ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, int lineNumber) { QV4::ExecutionEngine *v4 = d->m_v4Engine; QV4::Scope scope(v4); QV4::ExecutionContextSaver saver(scope); QV4::ExecutionContext *ctx = v4->currentContext; if (ctx->d() != v4->rootContext()->d()) ctx = v4->pushGlobalContext(); QV4::ScopedValue result(scope); QV4::Script script(ctx, program, fileName, lineNumber); script.strictMode = ctx->d()->strictMode; script.inheritContext = true; script.parse(); if (!scope.engine->hasException) result = script.run(); if (scope.engine->hasException) result = v4->catchException(); return QJSValue(v4, result->asReturnedValue()); }
QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context, const QV4::ValueRef function, QV4::CallData *callData, bool *isUndefined) { Q_ASSERT(context && context->engine); if (function->isUndefined()) { if (isUndefined) *isUndefined = true; return QV4::Encode::undefined(); } QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine); // All code that follows must check with watcher before it accesses data members // incase we have been deleted. DeleteWatcher watcher(this); Q_ASSERT(notifyOnValueChanged() || activeGuards.isEmpty()); GuardCapture capture(context->engine, this, &watcher); QQmlEnginePrivate::PropertyCapture *lastPropertyCapture = ep->propertyCapture; ep->propertyCapture = notifyOnValueChanged()?&capture:0; if (notifyOnValueChanged()) capture.guards.copyAndClearPrepend(activeGuards); QV4::ExecutionEngine *v4 = QV8Engine::getV4(ep->v8engine()); QV4::Scope scope(v4); QV4::ScopedValue result(scope, QV4::Primitive::undefinedValue()); QV4::ExecutionContext *ctx = v4->currentContext(); callData->thisObject = v4->globalObject; if (scopeObject()) { QV4::ScopedValue value(scope, QV4::QObjectWrapper::wrap(ctx->d()->engine, scopeObject())); if (value->isObject()) callData->thisObject = value; } result = function->asFunctionObject()->call(callData); if (scope.hasException()) { if (watcher.wasDeleted()) ctx->catchException(); // ignore exception else delayedError()->catchJavaScriptException(ctx); if (isUndefined) *isUndefined = true; } else { if (isUndefined) *isUndefined = result->isUndefined(); if (!watcher.wasDeleted() && hasDelayedError()) delayedError()->clearError(); } if (capture.errorString) { for (int ii = 0; ii < capture.errorString->count(); ++ii) qWarning("%s", qPrintable(capture.errorString->at(ii))); delete capture.errorString; capture.errorString = 0; } while (Guard *g = capture.guards.takeFirst()) g->Delete(); ep->propertyCapture = lastPropertyCapture; return result.asReturnedValue(); }