QList<JSAgentWatchData> QJSDebuggerAgent::localsAtFrame(int frameId) { SetupExecEnv execEnv(d); int deep = 0; QScriptContext *ctx = engine()->currentContext(); while (ctx && deep < frameId) { ctx = ctx->parentContext(); deep++; } return d->getLocals(ctx); }
/*! Returns the context for the frame with the given \a index. */ QScriptContext *QScriptDebuggerBackend::context(int index) const { if (index < 0) return 0; QScriptContext *ctx = engine()->currentContext(); while (ctx) { if (index == 0) return ctx; ctx = ctx->parentContext(); --index; } return 0; }
void Cluster::setup () { QScriptEngine* engine = scene->scriptEngine(); QScriptContext* ctx = engine->pushContext(); QScriptValue ao = ctx->activationObject(); prepGlobalObject(ao); ao.setProperty("emit", engine->newFunction(emitFun)); /// @todo is this the best way to get access to the cluster? QVariant var = qVariantFromValue(this); ao.setProperty("self", engine->newVariant(var)); engine->evaluate(d->shellProgram); engine->popContext(); }
/*! Constructs a new agent for the given \a engine. The agent will report debugging-related events (e.g. step completion) to the given \a backend. */ QScriptDebuggerAgent::QScriptDebuggerAgent( QScriptDebuggerBackendPrivate *backend, QScriptEngine *engine) : QScriptEngineAgent(engine), d_ptr(new QScriptDebuggerAgentPrivate()) { Q_D(QScriptDebuggerAgent); d->backend = backend; QScriptContext *ctx = engine->currentContext(); while (ctx) { d->scriptIdStack.append(QList<qint64>()); d->contextIdStack.append(d->nextContextId); ++d->nextContextId; ctx = ctx->parentContext(); } }
QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContextData *context, QObject *object, const QString &program, QScriptValue *contextObject) { QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine); QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(&ep->scriptEngine); if (contextObject) { *contextObject = ep->contextClass->newContext(context, object); scriptContext->pushScope(*contextObject); } else { scriptContext->pushScope(ep->contextClass->newContext(context, object)); } scriptContext->pushScope(ep->globalClass->globalObject()); QScriptValue rv = ep->scriptEngine.evaluate(program); ep->scriptEngine.popContext(); return rv; }
static PyObject *meth_QScriptContext_parentContext(PyObject *sipSelf, PyObject *sipArgs) { PyObject *sipParseErr = NULL; { QScriptContext *sipCpp; if (sipParseArgs(&sipParseErr, sipArgs, "B", &sipSelf, sipType_QScriptContext, &sipCpp)) { QScriptContext *sipRes; Py_BEGIN_ALLOW_THREADS sipRes = sipCpp->parentContext(); Py_END_ALLOW_THREADS return sipConvertFromType(sipRes,sipType_QScriptContext,NULL); } }
bool XTreeView::throwScriptException(const QString &message) { QObject *ancestor = this; QScriptEngine *engine = 0; for ( ; ancestor; ancestor = ancestor->parent()) { engine = ancestor->findChild<QScriptEngine*>(); if (engine) break; } if (engine) { QScriptContext *ctx = engine->currentContext(); ctx->throwError(message); return true; } return false; }
/*! Executes the pending evaluate, if any. */ void QScriptDebuggerBackend::doPendingEvaluate(bool postEvent) { Q_D(QScriptDebuggerBackend); QString program = d->pendingEvaluateProgram; if (program.isEmpty()) return; int contextIndex = d->pendingEvaluateContextIndex; QScriptContext *ctx = context(contextIndex); Q_ASSERT(ctx != 0); QString fileName = d->pendingEvaluateFileName; int lineNumber = d->pendingEvaluateLineNumber; d->pendingEvaluateProgram = QString(); d->pendingEvaluateFileName = QString(); d->pendingEvaluateLineNumber = -1; d->pendingEvaluateContextIndex = -1; // push a new context and initialize its scope chain etc. { QScriptContext *evalContext = engine()->pushContext(); QScriptValueList scopeChain = ctx->scopeChain(); if (scopeChain.isEmpty()) scopeChain.append(engine()->globalObject()); while (!scopeChain.isEmpty()) evalContext->pushScope(scopeChain.takeLast()); evalContext->setActivationObject(ctx->activationObject()); evalContext->setThisObject(ctx->thisObject()); } d->agent->enterContinueMode(); // set a flag so that any exception that happens in // the evaluate() is not sent to the debugger d->ignoreExceptions = true; bool hadException = engine()->hasUncaughtException(); QScriptValue ret = engine()->evaluate(program, fileName, lineNumber); d->ignoreExceptions = false; if (!hadException && engine()->hasUncaughtException()) engine()->clearExceptions(); engine()->popContext(); QScriptDebuggerValue retret(ret); QScriptDebuggerEvent e(QScriptDebuggerEvent::InlineEvalFinished); e.setScriptValue(retret); if (!ret.isUndefined()) e.setMessage(ret.toString()); // for convenience -- we always need it e.setNestedEvaluate(engine()->isEvaluating()); if (postEvent) { QScriptDebuggerEventEvent *de = new QScriptDebuggerEventEvent(e); d->postEvent(de); } else { event(e); } }
JSC::JSObject* ClassObjectDelegate::construct(JSC::ExecState *exec, JSC::JSObject *callee, const JSC::ArgList &args) { Q_ASSERT(callee->inherits(&QScriptObject::info)); QScriptObject *obj = static_cast<QScriptObject*>(callee); QScriptObjectDelegate *delegate = obj->delegate(); QScriptClass *scriptClass = static_cast<ClassObjectDelegate*>(delegate)->scriptClass(); QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec); //JSC::ExecState *oldFrame = eng_p->currentFrame; eng_p->pushContext(exec, JSC::JSValue(), args, callee, true); QScriptContext *ctx = eng_p->contextForFrame(eng_p->currentFrame); QScriptValue defaultObject = ctx->thisObject(); QScriptValue result = qvariant_cast<QScriptValue>(scriptClass->extension(QScriptClass::Callable, qVariantFromValue(ctx))); if (!result.isObject()) result = defaultObject; return JSC::asObject(eng_p->scriptValueToJSCValue(result)); }
JSC::JSObject* FunctionWithArgWrapper::proxyConstruct(JSC::ExecState *exec, JSC::JSObject *callee, const JSC::ArgList &args) { FunctionWithArgWrapper *self = static_cast<FunctionWithArgWrapper*>(callee); QScriptEnginePrivate *eng_p = QScript::scriptEngineFromExec(exec); JSC::ExecState *oldFrame = eng_p->currentFrame; eng_p->pushContext(exec, JSC::JSValue(), args, callee, true); QScriptContext *ctx = eng_p->contextForFrame(eng_p->currentFrame); QScriptValue result = self->data->function(ctx, QScriptEnginePrivate::get(eng_p) , self->data->arg); if (!result.isObject()) result = ctx->thisObject(); eng_p->popContext(); eng_p->currentFrame = oldFrame; return JSC::asObject(eng_p->scriptValueToJSCValue(result)); }
static QScriptValue loadScripts(QScriptContext *context, QScriptEngine *engine) { for (int i = 0; i < context->argumentCount(); ++i) { QString fileName = context->argument(0).toString(); QFile file(fileName); if (!file.open(QIODevice::ReadOnly)) return context->throwError(QString::fromLatin1("could not open %0 for reading").arg(fileName)); QTextStream ts(&file); QString contents = ts.readAll(); file.close(); QScriptContext *pc = context->parentContext(); context->setActivationObject(pc->activationObject()); context->setThisObject(pc->thisObject()); QScriptValue ret = engine->evaluate(contents); if (engine->hasUncaughtException()) return ret; } return engine->undefinedValue(); }
bool HttpHandlerQtScriptFile::handleRequest(Pillow::HttpConnection *request) { if (!_lastModified.isValid() || (_autoReload && QFileInfo(_fileName).lastModified() > _lastModified)) { // Time to (re)load the script. qDebug() << "HttpHandlerQtScriptFile::handleRequest: (re)loading" << _fileName; QFile file(_fileName); if (!file.open(QIODevice::ReadOnly)) { request->writeResponseString(500, HttpHeaderCollection(), QString("HttpHandlerQtScriptFile::handleRequest: Could not read file %1").arg(_fileName)); return true; } QScriptEngine* engine = _scriptObject.engine(); _scriptObject = engine->newObject(); QScriptContext* context = engine->pushContext(); context->setActivationObject(_scriptObject); context->setThisObject(_scriptObject); QScriptValue result = engine->evaluate(file.readAll(), _fileName); engine->popContext(); if (result.isError()) { request->writeResponseString(500, HttpHeaderCollection(), QString("HttpHandlerQtScriptFile::handleRequest: Error while evaluating script %1: %2").arg(_fileName).arg(objectToString(result))); return true; } QScriptValue scriptFunction = _scriptObject.property(_functionName); if (!scriptFunction.isFunction()) { request->writeResponseString(500, HttpHeaderCollection(), QString("HttpHandlerQtScriptFile::handleRequest: Error while evaluating script %1: '%2' is not a function defined in the script").arg(_fileName).arg(_functionName)); return true; } _lastModified = QFileInfo(_fileName).lastModified(); setScriptFunction(scriptFunction); } return HttpHandlerQtScript::handleRequest(request); }
QList<JSAgentStackData> QJSDebuggerAgent::backtrace() { SetupExecEnv execEnv(d); QList<JSAgentStackData> backtrace; for (QScriptContext *ctx = engine()->currentContext(); ctx; ctx = ctx->parentContext()) { QScriptContextInfo info(ctx); JSAgentStackData frame; frame.functionName = info.functionName().toUtf8(); if (frame.functionName.isEmpty()) { if (ctx->parentContext()) { switch (info.functionType()) { case QScriptContextInfo::ScriptFunction: frame.functionName = "<anonymous>"; break; case QScriptContextInfo::NativeFunction: frame.functionName = "<native>"; break; case QScriptContextInfo::QtFunction: case QScriptContextInfo::QtPropertyFunction: frame.functionName = "<native slot>"; break; } } else { frame.functionName = "<global>"; } } frame.lineNumber = info.lineNumber(); // if the line number is unknown, fallback to the function line number if (frame.lineNumber == -1) frame.lineNumber = info.functionStartLineNumber(); frame.fileUrl = info.fileName().toUtf8(); backtrace.append(frame); } return backtrace; }
static QScriptValue includeFunction(QScriptContext *context, QScriptEngine *engine) { QString filename = prefixFilenameWithCurrentPath(context->argument(0).toString(), engine); QFile file(filename); if(!file.open(QIODevice::ReadOnly)) { Code::CodeClass::throwError(context, engine, QStringLiteral("IncludeFileError"), QObject::tr("Unable to include file %1").arg(filename)); return context->thisObject(); } QString fileContent = QString::fromUtf8(file.readAll()); file.close(); QScriptContext *parent = context->parentContext(); if(parent) { context->setActivationObject(parent->activationObject()); context->setThisObject(parent->thisObject()); } return engine->evaluate(fileContent, filename); }
QVariant TestClass::extension(Extension extension, const QVariant &argument) { m_lastExtensionType = extension; m_lastExtensionArgument = argument; if (extension == Callable) { Q_ASSERT(m_callableMode != NotCallable); QScriptContext *ctx = qvariant_cast<QScriptContext*>(argument); if (m_callableMode == CallableReturnsSum) { qsreal sum = 0; for (int i = 0; i < ctx->argumentCount(); ++i) sum += ctx->argument(i).toNumber(); QScriptValueIterator it(ctx->callee()); while (it.hasNext()) { it.next(); sum += it.value().toNumber(); } return sum; } else if (m_callableMode == CallableReturnsArgument) { return qVariantFromValue(ctx->argument(0)); } else if (m_callableMode == CallableReturnsInvalidVariant) { return QVariant(); } else if (m_callableMode == CallableReturnsGlobalObject) { return qVariantFromValue(engine()->globalObject()); } else if (m_callableMode == CallableReturnsThisObject) { return qVariantFromValue(ctx->thisObject()); } else if (m_callableMode == CallableReturnsCallee) { return qVariantFromValue(ctx->callee()); } else if (m_callableMode == CallableReturnsArgumentsObject) { return qVariantFromValue(ctx->argumentsObject()); } else if (m_callableMode == CallableInitializesThisObject) { engine()->newQObject(ctx->thisObject(), engine()); return QVariant(); } } else if (extension == HasInstance) { Q_ASSERT(m_hasInstance); QScriptValueList args = qvariant_cast<QScriptValueList>(argument); QScriptValue obj = args.at(0); QScriptValue value = args.at(1); return value.property("foo").equals(obj.property("foo")); } return QVariant(); }
void JavascriptInstance::IncludeFile(const QString &path) { for(uint i = 0; i < includedFiles.size(); ++i) if (includedFiles[i].toLower() == path.toLower()) { LogDebug("JavascriptInstance::IncludeFile: Not including already included file " + path); return; } QString script = LoadScript(path); QScriptContext *context = engine_->currentContext(); assert(context); if (!context) { LogError("JavascriptInstance::IncludeFile: QScriptEngine::currentContext() returned null!"); return; } QScriptContext *parent = context->parentContext(); if (!parent) { LogError("JavascriptInstance::IncludeFile: QScriptEngine::parentContext() returned null!"); return; } context->setActivationObject(context->parentContext()->activationObject()); context->setThisObject(context->parentContext()->thisObject()); QScriptSyntaxCheckResult syntaxResult = engine_->checkSyntax(script); if(syntaxResult.state() != QScriptSyntaxCheckResult::Valid) { LogError("JavascriptInstance::IncludeFile: Syntax error in " + path + ". " + syntaxResult.errorMessage() + " In line:" + QString::number(syntaxResult.errorLineNumber())); return; } QScriptValue result = engine_->evaluate(script, path); includedFiles.push_back(path); if (engine_->hasUncaughtException()) LogError(result.toString()); }
QVariant JSEmitClass::extension( Extension extension, const QVariant& argument ) { Q_UNUSED(argument); if (extension == Callable) { // QScriptContext *context = qvariant_cast<QScriptContext*>(argument); QScriptContext *context = engine()->currentContext(); if ( context->argumentCount() != 2) { context->throwError("emit() accepts exactly two parameters"); return QVariant(); } if ( !context->argument(0).isArray() ) { context->throwError("The first argument to emit() must be an array"); return QVariant(); } qDebug("emit(%s,%s)", qPrintable(context->argument(0).toString()), qPrintable(context->argument(1).toString())); return QVariant(true); } return QVariant(); }
/*! Applies the given \a command to the given \a backend. */ QScriptDebuggerResponse QScriptDebuggerCommandExecutor::execute( QScriptDebuggerBackend *backend, const QScriptDebuggerCommand &command) { QScriptDebuggerResponse response; switch (command.type()) { case QScriptDebuggerCommand::None: break; case QScriptDebuggerCommand::Interrupt: backend->interruptEvaluation(); break; case QScriptDebuggerCommand::Continue: if (backend->engine()->isEvaluating()) { backend->continueEvalution(); response.setAsync(true); } break; case QScriptDebuggerCommand::StepInto: { QVariant attr = command.attribute(QScriptDebuggerCommand::StepCount); int count = attr.isValid() ? attr.toInt() : 1; backend->stepInto(count); response.setAsync(true); } break; case QScriptDebuggerCommand::StepOver: { QVariant attr = command.attribute(QScriptDebuggerCommand::StepCount); int count = attr.isValid() ? attr.toInt() : 1; backend->stepOver(count); response.setAsync(true); } break; case QScriptDebuggerCommand::StepOut: backend->stepOut(); response.setAsync(true); break; case QScriptDebuggerCommand::RunToLocation: backend->runToLocation(command.fileName(), command.lineNumber()); response.setAsync(true); break; case QScriptDebuggerCommand::RunToLocationByID: backend->runToLocation(command.scriptId(), command.lineNumber()); response.setAsync(true); break; case QScriptDebuggerCommand::ForceReturn: { int contextIndex = command.contextIndex(); QScriptDebuggerValue value = command.scriptValue(); QScriptEngine *engine = backend->engine(); QScriptValue realValue = value.toScriptValue(engine); backend->returnToCaller(contextIndex, realValue); response.setAsync(true); } break; case QScriptDebuggerCommand::Resume: backend->resume(); response.setAsync(true); break; case QScriptDebuggerCommand::SetBreakpoint: { QScriptBreakpointData data = command.breakpointData(); if (!data.isValid()) data = QScriptBreakpointData(command.fileName(), command.lineNumber()); int id = backend->setBreakpoint(data); response.setResult(id); } break; case QScriptDebuggerCommand::DeleteBreakpoint: { int id = command.breakpointId(); if (!backend->deleteBreakpoint(id)) response.setError(QScriptDebuggerResponse::InvalidBreakpointID); } break; case QScriptDebuggerCommand::DeleteAllBreakpoints: backend->deleteAllBreakpoints(); break; case QScriptDebuggerCommand::GetBreakpoints: { QScriptBreakpointMap bps = backend->breakpoints(); if (!bps.isEmpty()) response.setResult(bps); } break; case QScriptDebuggerCommand::GetBreakpointData: { int id = command.breakpointId(); QScriptBreakpointData data = backend->breakpointData(id); if (data.isValid()) response.setResult(data); else response.setError(QScriptDebuggerResponse::InvalidBreakpointID); } break; case QScriptDebuggerCommand::SetBreakpointData: { int id = command.breakpointId(); QScriptBreakpointData data = command.breakpointData(); if (!backend->setBreakpointData(id, data)) response.setError(QScriptDebuggerResponse::InvalidBreakpointID); } break; case QScriptDebuggerCommand::GetScripts: { QScriptScriptMap scripts = backend->scripts(); if (!scripts.isEmpty()) response.setResult(scripts); } break; case QScriptDebuggerCommand::GetScriptData: { qint64 id = command.scriptId(); QScriptScriptData data = backend->scriptData(id); if (data.isValid()) response.setResult(data); else response.setError(QScriptDebuggerResponse::InvalidScriptID); } break; case QScriptDebuggerCommand::ScriptsCheckpoint: backend->scriptsCheckpoint(); response.setResult(QVariant::fromValue(backend->scriptsDelta())); break; case QScriptDebuggerCommand::GetScriptsDelta: response.setResult(QVariant::fromValue(backend->scriptsDelta())); break; case QScriptDebuggerCommand::ResolveScript: response.setResult(backend->resolveScript(command.fileName())); break; case QScriptDebuggerCommand::GetBacktrace: response.setResult(backend->backtrace()); break; case QScriptDebuggerCommand::GetContextCount: response.setResult(backend->contextCount()); break; case QScriptDebuggerCommand::GetContextState: { QScriptContext *ctx = backend->context(command.contextIndex()); if (ctx) response.setResult(static_cast<int>(ctx->state())); else response.setError(QScriptDebuggerResponse::InvalidContextIndex); } break; case QScriptDebuggerCommand::GetContextID: { int idx = command.contextIndex(); if ((idx >= 0) && (idx < backend->contextCount())) response.setResult(backend->contextIds()[idx]); else response.setError(QScriptDebuggerResponse::InvalidContextIndex); } break; case QScriptDebuggerCommand::GetContextInfo: { QScriptContext *ctx = backend->context(command.contextIndex()); if (ctx) response.setResult(QScriptContextInfo(ctx)); else response.setError(QScriptDebuggerResponse::InvalidContextIndex); } break; case QScriptDebuggerCommand::GetThisObject: { QScriptContext *ctx = backend->context(command.contextIndex()); if (ctx) response.setResult(ctx->thisObject()); else response.setError(QScriptDebuggerResponse::InvalidContextIndex); } break; case QScriptDebuggerCommand::GetActivationObject: { QScriptContext *ctx = backend->context(command.contextIndex()); if (ctx) response.setResult(ctx->activationObject()); else response.setError(QScriptDebuggerResponse::InvalidContextIndex); } break; case QScriptDebuggerCommand::GetScopeChain: { QScriptContext *ctx = backend->context(command.contextIndex()); if (ctx) { QScriptDebuggerValueList dest; QScriptValueList src = ctx->scopeChain(); for (int i = 0; i < src.size(); ++i) dest.append(src.at(i)); response.setResult(dest); } else { response.setError(QScriptDebuggerResponse::InvalidContextIndex); } } break; case QScriptDebuggerCommand::ContextsCheckpoint: { response.setResult(QVariant::fromValue(backend->contextsCheckpoint())); } break; case QScriptDebuggerCommand::GetPropertyExpressionValue: { QScriptContext *ctx = backend->context(command.contextIndex()); int lineNumber = command.lineNumber(); QVariant attr = command.attribute(QScriptDebuggerCommand::UserAttribute); QStringList path = attr.toStringList(); if (!ctx || path.isEmpty()) break; QScriptContextInfo ctxInfo(ctx); if (ctx->callee().isValid() && ((lineNumber < ctxInfo.functionStartLineNumber()) || (lineNumber > ctxInfo.functionEndLineNumber()))) { break; } QScriptValueList objects; int pathIndex = 0; if (path.at(0) == QLatin1String("this")) { objects.append(ctx->thisObject()); ++pathIndex; } else { objects << ctx->scopeChain(); } for (int i = 0; i < objects.size(); ++i) { QScriptValue val = objects.at(i); for (int j = pathIndex; val.isValid() && (j < path.size()); ++j) { val = val.property(path.at(j)); } if (val.isValid()) { bool hadException = (ctx->state() == QScriptContext::ExceptionState); QString str = val.toString(); if (!hadException && backend->engine()->hasUncaughtException()) backend->engine()->clearExceptions(); response.setResult(str); break; } } } break; case QScriptDebuggerCommand::GetCompletions: { QScriptContext *ctx = backend->context(command.contextIndex()); QVariant attr = command.attribute(QScriptDebuggerCommand::UserAttribute); QStringList path = attr.toStringList(); if (!ctx || path.isEmpty()) break; QScriptValueList objects; QString prefix = path.last(); QSet<QString> matches; if (path.size() > 1) { const QString &topLevelIdent = path.at(0); QScriptValue obj; if (topLevelIdent == QLatin1String("this")) { obj = ctx->thisObject(); } else { QScriptValueList scopeChain; scopeChain = ctx->scopeChain(); for (int i = 0; i < scopeChain.size(); ++i) { QScriptValue oo = scopeChain.at(i).property(topLevelIdent); if (oo.isObject()) { obj = oo; break; } } } for (int i = 1; obj.isObject() && (i < path.size()-1); ++i) obj = obj.property(path.at(i)); if (obj.isValid()) objects.append(obj); } else { objects << ctx->scopeChain(); QStringList keywords; keywords.append(QString::fromLatin1("this")); keywords.append(QString::fromLatin1("true")); keywords.append(QString::fromLatin1("false")); keywords.append(QString::fromLatin1("null")); for (int i = 0; i < keywords.size(); ++i) { const QString &kwd = keywords.at(i); if (isPrefixOf(prefix, kwd)) matches.insert(kwd); } } for (int i = 0; i < objects.size(); ++i) { QScriptValue obj = objects.at(i); while (obj.isObject()) { QScriptValueIterator it(obj); while (it.hasNext()) { it.next(); QString propertyName = it.name(); if (isPrefixOf(prefix, propertyName)) matches.insert(propertyName); } obj = obj.prototype(); } } QStringList matchesList = matches.toList(); qStableSort(matchesList); response.setResult(matchesList); } break; case QScriptDebuggerCommand::NewScriptObjectSnapshot: { int id = backend->newScriptObjectSnapshot(); response.setResult(id); } break; case QScriptDebuggerCommand::ScriptObjectSnapshotCapture: { int id = command.snapshotId(); QScriptObjectSnapshot *snap = backend->scriptObjectSnapshot(id); Q_ASSERT(snap != 0); QScriptDebuggerValue object = command.scriptValue(); Q_ASSERT(object.type() == QScriptDebuggerValue::ObjectValue); QScriptEngine *engine = backend->engine(); QScriptValue realObject = object.toScriptValue(engine); Q_ASSERT(realObject.isObject()); QScriptObjectSnapshot::Delta delta = snap->capture(realObject); QScriptDebuggerObjectSnapshotDelta result; result.removedProperties = delta.removedProperties; bool didIgnoreExceptions = backend->ignoreExceptions(); backend->setIgnoreExceptions(true); for (int i = 0; i < delta.changedProperties.size(); ++i) { const QScriptValueProperty &src = delta.changedProperties.at(i); bool hadException = engine->hasUncaughtException(); QString str = src.value().toString(); if (!hadException && engine->hasUncaughtException()) engine->clearExceptions(); QScriptDebuggerValueProperty dest(src.name(), src.value(), str, src.flags()); result.changedProperties.append(dest); } for (int j = 0; j < delta.addedProperties.size(); ++j) { const QScriptValueProperty &src = delta.addedProperties.at(j); bool hadException = engine->hasUncaughtException(); QString str = src.value().toString(); if (!hadException && engine->hasUncaughtException()) engine->clearExceptions(); QScriptDebuggerValueProperty dest(src.name(), src.value(), str, src.flags()); result.addedProperties.append(dest); } backend->setIgnoreExceptions(didIgnoreExceptions); response.setResult(QVariant::fromValue(result)); } break; case QScriptDebuggerCommand::DeleteScriptObjectSnapshot: { int id = command.snapshotId(); backend->deleteScriptObjectSnapshot(id); } break; case QScriptDebuggerCommand::NewScriptValueIterator: { QScriptDebuggerValue object = command.scriptValue(); Q_ASSERT(object.type() == QScriptDebuggerValue::ObjectValue); QScriptEngine *engine = backend->engine(); QScriptValue realObject = object.toScriptValue(engine); Q_ASSERT(realObject.isObject()); int id = backend->newScriptValueIterator(realObject); response.setResult(id); } break; case QScriptDebuggerCommand::GetPropertiesByIterator: { int id = command.iteratorId(); int count = 1000; QScriptValueIterator *it = backend->scriptValueIterator(id); Q_ASSERT(it != 0); QScriptDebuggerValuePropertyList props; for (int i = 0; (i < count) && it->hasNext(); ++i) { it->next(); QString name = it->name(); QScriptValue value = it->value(); QString valueAsString = value.toString(); QScriptValue::PropertyFlags flags = it->flags(); QScriptDebuggerValueProperty prp(name, value, valueAsString, flags); props.append(prp); } response.setResult(props); } break; case QScriptDebuggerCommand::DeleteScriptValueIterator: { int id = command.iteratorId(); backend->deleteScriptValueIterator(id); } break; case QScriptDebuggerCommand::Evaluate: { int contextIndex = command.contextIndex(); QString program = command.program(); QString fileName = command.fileName(); int lineNumber = command.lineNumber(); backend->evaluate(contextIndex, program, fileName, lineNumber); response.setAsync(true); } break; case QScriptDebuggerCommand::ScriptValueToString: { QScriptDebuggerValue value = command.scriptValue(); QScriptEngine *engine = backend->engine(); QScriptValue realValue = value.toScriptValue(engine); response.setResult(realValue.toString()); } break; case QScriptDebuggerCommand::SetScriptValueProperty: { QScriptDebuggerValue object = command.scriptValue(); QScriptEngine *engine = backend->engine(); QScriptValue realObject = object.toScriptValue(engine); QScriptDebuggerValue value = command.subordinateScriptValue(); QScriptValue realValue = value.toScriptValue(engine); QString name = command.name(); realObject.setProperty(name, realValue); } break; case QScriptDebuggerCommand::ClearExceptions: backend->engine()->clearExceptions(); break; case QScriptDebuggerCommand::UserCommand: case QScriptDebuggerCommand::MaxUserCommand: break; } return response; }
QStringList JSPluginsLoader::names() const { QScriptContext *ctx = eng.currentContext(); QScriptValue jsLdr = ctx->activationObject().property("PluginsLoader").call(); //var jsLdr = PluginsLoader(); QStringList plgNames= qscriptvalue_cast<QStringList>(jsLdr.property("names").call(jsLdr)); //plgNames = jsLdr.names(); return plgNames; }
/* Documented in qdeclarativeengine.cpp */ QScriptValue QDeclarativeInclude::include(QScriptContext *ctxt, QScriptEngine *engine) { if (ctxt->argumentCount() == 0) return engine->undefinedValue(); QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); QUrl contextUrl = ep->contextClass->urlFromValue(QScriptDeclarativeClass::scopeChainValue(ctxt, -3)); if (contextUrl.isEmpty()) return ctxt->throwError(QLatin1String("Qt.include(): Can only be called from JavaScript files")); QString urlString = ctxt->argument(0).toString(); QUrl url(urlString); if (url.isRelative()) { url = QUrl(contextUrl).resolved(url); urlString = url.toString(); } QString localFile = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url); QScriptValue func = ctxt->argument(1); if (!func.isFunction()) func = QScriptValue(); QScriptValue result; if (localFile.isEmpty()) { QDeclarativeInclude *i = new QDeclarativeInclude(url, QDeclarativeEnginePrivate::getEngine(engine), ctxt); if (func.isValid()) i->setCallback(func); result = i->result(); } else { QFile f(localFile); if (f.open(QIODevice::ReadOnly)) { QByteArray data = f.readAll(); QString code = QString::fromUtf8(data); QDeclarativeContextData *context = ep->contextClass->contextFromValue(QScriptDeclarativeClass::scopeChainValue(ctxt, -3)); QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(engine); scriptContext->pushScope(ep->contextClass->newUrlContext(context, 0, urlString)); scriptContext->pushScope(ep->globalClass->staticGlobalObject()); QScriptValue scope = QScriptDeclarativeClass::scopeChainValue(ctxt, -5); scriptContext->pushScope(scope); scriptContext->setActivationObject(scope); QDeclarativeScriptParser::extractPragmas(code); engine->evaluate(code, urlString, 1); engine->popContext(); if (engine->hasUncaughtException()) { result = resultValue(engine, Exception); result.setProperty(QLatin1String("exception"), engine->uncaughtException()); engine->clearExceptions(); } else { result = resultValue(engine, Ok); } callback(engine, func, result); } else { result = resultValue(engine, NetworkError); callback(engine, func, result); } } return result; }
QVariant QDeclarativeExpressionPrivate::evalQtScript(QObject *secondaryScope, bool *isUndefined) { QDeclarativeExpressionData *data = this->data; QDeclarativeEngine *engine = data->context()->engine; QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); if (!data->expressionFunctionValid) { QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine); data->expressionContext = ep->contextClass->newContext(data->context(), data->me); scriptContext->pushScope(data->expressionContext); scriptContext->pushScope(ep->globalClass->globalObject()); if (data->expressionRewritten) { data->expressionFunction = scriptEngine->evaluate(data->expression, data->url, data->line); } else { QDeclarativeRewrite::RewriteBinding rewriteBinding; bool ok = true; const QString code = rewriteBinding(data->expression, &ok); if (!ok) { scriptEngine->popContext(); return QVariant(); } data->expressionFunction = scriptEngine->evaluate(code, data->url, data->line); } scriptEngine->popContext(); data->expressionFunctionValid = true; } QDeclarativeContextData *oldSharedContext = 0; QObject *oldSharedScope = 0; QObject *oldOverride = 0; if (data->isShared) { oldSharedContext = ep->sharedContext; oldSharedScope = ep->sharedScope; ep->sharedContext = data->context(); ep->sharedScope = data->me; } else { oldOverride = ep->contextClass->setOverrideObject(data->expressionContext, secondaryScope); } QScriptValue svalue = data->expressionFunction.call(); if (data->isShared) { ep->sharedContext = oldSharedContext; ep->sharedScope = oldSharedScope; } else { ep->contextClass->setOverrideObject(data->expressionContext, oldOverride); } if (isUndefined) *isUndefined = svalue.isUndefined() || scriptEngine->hasUncaughtException(); // Handle exception if (scriptEngine->hasUncaughtException()) { exceptionToError(scriptEngine, data->error); scriptEngine->clearExceptions(); return QVariant(); } else { data->error = QDeclarativeError(); } QVariant rv; if (svalue.isArray()) { int length = svalue.property(QLatin1String("length")).toInt32(); if (length && svalue.property(0).isObject()) { QList<QObject *> list; for (int ii = 0; ii < length; ++ii) { QScriptValue arrayItem = svalue.property(ii); QObject *d = arrayItem.toQObject(); list << d; } rv = QVariant::fromValue(list); } } else if (svalue.isObject() && ep->objectClass->scriptClass(svalue) == ep->objectClass) { QObject *o = svalue.toQObject(); int type = QMetaType::QObjectStar; // If the object is null, we extract the predicted type. While this isn't // 100% reliable, in many cases it gives us better error messages if we // assign this null-object to an incompatible property if (!o) type = ep->objectClass->objectType(svalue); return QVariant(type, &o); } if (rv.isNull()) rv = svalue.toVariant(); return rv; }
void tst_QScriptContext::getSetActivationObject() { QScriptEngine eng; QScriptContext *ctx = eng.currentContext(); QVERIFY(ctx->activationObject().equals(eng.globalObject())); ctx->setActivationObject(QScriptValue()); QVERIFY(ctx->activationObject().equals(eng.globalObject())); QCOMPARE(ctx->engine(), &eng); QScriptValue obj = eng.newObject(); ctx->setActivationObject(obj); QVERIFY(ctx->activationObject().equals(obj)); QCOMPARE(ctx->scopeChain().size(), 1); QVERIFY(ctx->scopeChain().at(0).equals(obj)); { QScriptEngine eng2; QScriptValue obj2 = eng2.newObject(); QTest::ignoreMessage(QtWarningMsg, "QScriptContext::setActivationObject() failed: cannot set an object created in a different engine"); QScriptValue was = ctx->activationObject(); ctx->setActivationObject(obj2); QVERIFY(ctx->activationObject().equals(was)); } ctx->setActivationObject(eng.globalObject()); QVERIFY(ctx->activationObject().equals(eng.globalObject())); QScriptValue fun = eng.newFunction(get_activationObject); eng.globalObject().setProperty("get_activationObject", fun); { QScriptValue ret = eng.evaluate("get_activationObject(1, 2, 3)"); QVERIFY(ret.isObject()); QScriptValue arguments = ret.property("arguments"); QEXPECT_FAIL("", "Getting arguments property of activation object doesn't work", Abort); QVERIFY(arguments.isObject()); QCOMPARE(arguments.property("length").toInt32(), 3); QCOMPARE(arguments.property("0").toInt32(), 1); QCOMPARE(arguments.property("1").toInt32(), 1); QCOMPARE(arguments.property("2").toInt32(), 1); } }
void tst_QScriptContext::pushAndPopContext() { QScriptEngine eng; QScriptContext *topLevel = eng.currentContext(); QCOMPARE(topLevel->engine(), &eng); QScriptContext *ctx = eng.pushContext(); QVERIFY(ctx != 0); QCOMPARE(ctx->parentContext(), topLevel); QCOMPARE(eng.currentContext(), ctx); QCOMPARE(ctx->engine(), &eng); QCOMPARE(ctx->state(), QScriptContext::NormalState); QCOMPARE(ctx->isCalledAsConstructor(), false); QCOMPARE(ctx->argumentCount(), 0); QCOMPARE(ctx->argument(0).isUndefined(), true); QVERIFY(!ctx->argument(-1).isValid()); QCOMPARE(ctx->argumentsObject().isObject(), true); QCOMPARE(ctx->activationObject().isObject(), true); QCOMPARE(ctx->callee().isValid(), false); QCOMPARE(ctx->thisObject().strictlyEquals(eng.globalObject()), true); QCOMPARE(ctx->scopeChain().size(), 2); QVERIFY(ctx->scopeChain().at(0).equals(ctx->activationObject())); QVERIFY(ctx->scopeChain().at(1).equals(eng.globalObject())); QScriptContext *ctx2 = eng.pushContext(); QCOMPARE(ctx2->parentContext(), ctx); QCOMPARE(eng.currentContext(), ctx2); eng.popContext(); QCOMPARE(eng.currentContext(), ctx); eng.popContext(); QCOMPARE(eng.currentContext(), topLevel); // popping the top-level context is not allowed QTest::ignoreMessage(QtWarningMsg, "QScriptEngine::popContext() doesn't match with pushContext()"); eng.popContext(); QCOMPARE(eng.currentContext(), topLevel); { QScriptContext *ctx3 = eng.pushContext(); ctx3->activationObject().setProperty("foo", QScriptValue(&eng, 123)); QVERIFY(eng.evaluate("foo").strictlyEquals(QScriptValue(&eng, 123))); eng.evaluate("var bar = 'ciao'"); QVERIFY(ctx3->activationObject().property("bar", QScriptValue::ResolveLocal).strictlyEquals(QScriptValue(&eng, "ciao"))); eng.popContext(); } { QScriptContext *ctx4 = eng.pushContext(); QScriptValue obj = eng.newObject(); obj.setProperty("prop", QScriptValue(&eng, 456)); ctx4->setThisObject(obj); QScriptValue ret = eng.evaluate("var tmp = this.prop; tmp + 1"); QCOMPARE(eng.currentContext(), ctx4); QVERIFY(ret.strictlyEquals(QScriptValue(&eng, 457))); eng.popContext(); } // throwing an exception { QScriptContext *ctx5 = eng.pushContext(); QScriptValue ret = eng.evaluate("throw new Error('oops')"); QVERIFY(ret.isError()); QVERIFY(eng.hasUncaughtException()); QCOMPARE(eng.currentContext(), ctx5); eng.popContext(); } }
void tst_QScriptContext::popNativeContextScope() { QScriptEngine eng; QScriptContext *ctx = eng.pushContext(); QVERIFY(ctx->popScope().isObject()); // the activation object QCOMPARE(ctx->scopeChain().size(), 1); QVERIFY(ctx->scopeChain().at(0).strictlyEquals(eng.globalObject())); // This was different in 4.5: scope and activation were decoupled QVERIFY(ctx->activationObject().strictlyEquals(eng.globalObject())); QVERIFY(!eng.evaluate("var foo = 123; function bar() {}").isError()); QVERIFY(eng.globalObject().property("foo").isNumber()); QVERIFY(eng.globalObject().property("bar").isFunction()); QScriptValue customScope = eng.newObject(); ctx->pushScope(customScope); QCOMPARE(ctx->scopeChain().size(), 2); QVERIFY(ctx->scopeChain().at(0).strictlyEquals(customScope)); QVERIFY(ctx->scopeChain().at(1).strictlyEquals(eng.globalObject())); QVERIFY(ctx->activationObject().strictlyEquals(eng.globalObject())); ctx->setActivationObject(customScope); QVERIFY(ctx->activationObject().strictlyEquals(customScope)); QCOMPARE(ctx->scopeChain().size(), 2); QVERIFY(ctx->scopeChain().at(0).strictlyEquals(customScope)); QEXPECT_FAIL("", "QTBUG-11012", Continue); QVERIFY(ctx->scopeChain().at(1).strictlyEquals(eng.globalObject())); QVERIFY(!eng.evaluate("baz = 456; var foo = 789; function barbar() {}").isError()); QEXPECT_FAIL("", "QTBUG-11012", Continue); QVERIFY(eng.globalObject().property("baz").isNumber()); QVERIFY(customScope.property("foo").isNumber()); QVERIFY(customScope.property("barbar").isFunction()); QVERIFY(ctx->popScope().strictlyEquals(customScope)); QCOMPARE(ctx->scopeChain().size(), 1); QEXPECT_FAIL("", "QTBUG-11012", Continue); QVERIFY(ctx->scopeChain().at(0).strictlyEquals(eng.globalObject())); // Need to push another object, otherwise we crash in popContext() (QTBUG-11012) ctx->pushScope(customScope); eng.popContext(); }
void ScriptDebuggerPrivate::positionChange(qint64 scriptId, int lineNumber, int /*columnNumber*/) { ScriptInfo *info = 0; bool enterInteractiveMode = false; if (m_bpManager->hasBreakpoints()) { // check if we hit a breakpoint info = m_scripts.value(scriptId); QScriptContext *ctx = engine()->currentContext(); QScriptContextInfo ctxInfo(ctx); QScriptValue callee = ctx->callee(); // try fileName:lineNumber int bpid = m_bpManager->findBreakpoint(info->fileName(), lineNumber); if ((bpid != -1) && m_bpManager->isBreakpointEnabled(bpid)) { message(QString::fromLatin1("Breakpoint %0 at %1:%2") .arg(bpid + 1).arg(info->fileName()).arg(lineNumber)); if (m_bpManager->isBreakpointSingleShot(bpid)) m_bpManager->removeBreakpoint(bpid); } if (bpid == -1) { // try function bpid = m_bpManager->findBreakpoint(callee); if ((bpid != -1) && m_bpManager->isBreakpointEnabled(bpid)) { message(QString::fromLatin1("Breakpoint %0, %1()") .arg(bpid + 1).arg(ctxInfo.functionName())); if (m_bpManager->isBreakpointSingleShot(bpid)) m_bpManager->removeBreakpoint(bpid); } } if ((bpid == -1) && !ctxInfo.functionName().isEmpty()) { // try functionName:fileName bpid = m_bpManager->findBreakpoint(ctxInfo.functionName(), ctxInfo.fileName()); if ((bpid != -1) && m_bpManager->isBreakpointEnabled(bpid)) { message(QString::fromLatin1("Breakpoint %0, %1():%2").arg(bpid + 1) .arg(ctxInfo.functionName()).arg(ctxInfo.fileName())); if (m_bpManager->isBreakpointSingleShot(bpid)) m_bpManager->removeBreakpoint(bpid); } } enterInteractiveMode = (bpid != -1); } switch (mode()) { case Run: break; case StepInto: enterInteractiveMode = true; break; case StepOver: enterInteractiveMode = enterInteractiveMode || (m_stepDepth <= 0); break; } if (enterInteractiveMode) { if (!info) info = m_scripts.value(scriptId); Q_ASSERT(info); message(QString::fromLatin1("%0\t%1").arg(lineNumber).arg(info->lineText(lineNumber))); interactive(); } }
bool ScriptDebuggerPrivate::executeCommand(const QString &command, const QStringList &args) { if (command == QLatin1String("c") || command == QLatin1String("continue")) { setMode(Run); return true; } else if (command == QLatin1String("s") || command == QLatin1String("step")) { setMode(StepInto); return true; } else if (command == QLatin1String("n") || command == QLatin1String("next")) { setMode(StepOver); m_stepDepth = 0; return true; } else if (command == QLatin1String("f") || command == QLatin1String("frame")) { bool ok = false; int index = args.value(0).toInt(&ok); if (ok) { if (index < 0 || index >= frameCount()) { errorMessage("No such frame."); } else { setCurrentFrameIndex(index); QScriptContext *ctx = currentFrameContext(); message(QString::fromLatin1("#%0 %1").arg(index).arg(ctx->toString())); } } } else if (command == QLatin1String("bt") || command == QLatin1String("backtrace")) { QScriptContext *ctx = engine()->currentContext(); int index = -1; while (ctx) { ++index; QString line = ctx->toString(); message(QString::fromLatin1("#%0 %1").arg(index).arg(line)); ctx = ctx->parentContext(); } } else if (command == QLatin1String("up")) { int index = currentFrameIndex() + 1; if (index == frameCount()) { errorMessage(QString::fromLatin1("Initial frame selected; you cannot go up.")); } else { setCurrentFrameIndex(index); QScriptContext *ctx = currentFrameContext(); message(QString::fromLatin1("#%0 %1").arg(index).arg(ctx->toString())); } } else if (command == QLatin1String("down")) { int index = currentFrameIndex() - 1; if (index < 0) { errorMessage(QString::fromLatin1("Bottom (innermost) frame selected; you cannot go down.")); } else { setCurrentFrameIndex(index); QScriptContext *ctx = currentFrameContext(); message(QString::fromLatin1("#%0 %1").arg(index).arg(ctx->toString())); } } else if (command == QLatin1String("b") || command == QLatin1String("break")) { QString str = args.value(0); int colonIndex = str.indexOf(QLatin1Char(':')); if (colonIndex != -1) { // filename:line form QString fileName = str.left(colonIndex); int lineNumber = str.mid(colonIndex+1).toInt(); int id = m_bpManager->setBreakpoint(fileName, lineNumber); message(QString::fromLatin1("Breakpoint %0 at %1, line %2.").arg(id+1).arg(fileName).arg(lineNumber)); } else { // function QScriptValue fun = engine()->globalObject().property(str); if (fun.isFunction()) { int id = m_bpManager->setBreakpoint(fun); message(QString::fromLatin1("Breakpoint %0 at %1().").arg(id+1).arg(str)); } } } else if (command == QLatin1String("d") || command == QLatin1String("delete")) { int id = args.value(0).toInt() - 1; m_bpManager->removeBreakpoint(id); } else if (command == QLatin1String("disable")) { int id = args.value(0).toInt() - 1; m_bpManager->setBreakpointEnabled(id, false); } else if (command == QLatin1String("enable")) { int id = args.value(0).toInt() - 1; m_bpManager->setBreakpointEnabled(id, true); } else if (command == QLatin1String("list")) { QScriptContext *ctx = currentFrameContext(); ScriptInfo *progInfo = scriptInfo(ctx); if (!progInfo) { errorMessage("No source text available for this frame."); } else { QScriptContextInfo ctxInfo(ctx); bool ok; int line = args.value(0).toInt(&ok); if (ok) { line = qMax(1, line - 5); } else { line = listLineNumber(); if (line == -1) line = qMax(progInfo->lineNumber(), ctxInfo.lineNumber() - 5); } for (int i = line; i < line + 10; ++i) { message(QString::fromLatin1("%0\t%1").arg(i).arg(progInfo->lineText(i))); } setListLineNumber(line + 10); } } else if (command == QLatin1String("info")) { if (args.size() < 1) { } else { QString what = args.value(0); if (what == QLatin1String("locals")) { QScriptValueIterator it(currentFrameContext()->activationObject()); while (it.hasNext()) { it.next(); QString line; line.append(it.name()); line.append(QLatin1String(" = ")); line.append(safeValueToString(it.value())); message(line); } } } } else if (command == QLatin1String("help")) { message("continue - continue execution\n" "step - step into statement\n" "next - step over statement\n" "list - show where you are\n" "\n" "break - set breakpoint\n" "delete - remove breakpoint\n" "disable - disable breakpoint\n" "enable - enable breakpoint\n" "\n" "backtrace - show backtrace\n" "up - one frame up\n" "down - one frame down\n" "frame - set frame\n" "\n" "info locals - show local variables"); } else { errorMessage(QString::fromLatin1("Undefined command \"%0\". Try \"help\".") .arg(command)); } return false; }
void tst_QScriptContext::pushAndPopScope() { QScriptEngine eng; QScriptContext *ctx = eng.currentContext(); QCOMPARE(ctx->scopeChain().size(), 1); QVERIFY(ctx->scopeChain().at(0).strictlyEquals(eng.globalObject())); QVERIFY(ctx->popScope().strictlyEquals(eng.globalObject())); ctx->pushScope(eng.globalObject()); QCOMPARE(ctx->scopeChain().size(), 1); QVERIFY(ctx->scopeChain().at(0).strictlyEquals(eng.globalObject())); QScriptValue obj = eng.newObject(); ctx->pushScope(obj); QCOMPARE(ctx->scopeChain().size(), 2); QVERIFY(ctx->scopeChain().at(0).strictlyEquals(obj)); QVERIFY(ctx->scopeChain().at(1).strictlyEquals(eng.globalObject())); QVERIFY(ctx->popScope().strictlyEquals(obj)); QCOMPARE(ctx->scopeChain().size(), 1); QVERIFY(ctx->scopeChain().at(0).strictlyEquals(eng.globalObject())); { QScriptValue ret = eng.evaluate("x"); QVERIFY(ret.isError()); eng.clearExceptions(); } QCOMPARE(ctx->scopeChain().size(), 1); QVERIFY(ctx->scopeChain().at(0).strictlyEquals(eng.globalObject())); // task 236685 QScriptValue qobj = eng.newQObject(this, QScriptEngine::QtOwnership, QScriptEngine::AutoCreateDynamicProperties); ctx->pushScope(qobj); QCOMPARE(ctx->scopeChain().size(), 2); QVERIFY(ctx->scopeChain().at(0).strictlyEquals(qobj)); QVERIFY(ctx->scopeChain().at(1).strictlyEquals(eng.globalObject())); { QScriptValue ret = eng.evaluate("print"); QVERIFY(ret.isFunction()); } ctx->popScope(); ctx->pushScope(obj); QCOMPARE(ctx->scopeChain().size(), 2); QVERIFY(ctx->scopeChain().at(0).strictlyEquals(obj)); obj.setProperty("x", 123); { QScriptValue ret = eng.evaluate("x"); QVERIFY(ret.isNumber()); QCOMPARE(ret.toInt32(), 123); } QVERIFY(ctx->popScope().strictlyEquals(obj)); QCOMPARE(ctx->scopeChain().size(), 1); QVERIFY(ctx->scopeChain().at(0).strictlyEquals(eng.globalObject())); ctx->pushScope(QScriptValue()); QCOMPARE(ctx->scopeChain().size(), 1); QVERIFY(ctx->popScope().strictlyEquals(eng.globalObject())); QVERIFY(ctx->scopeChain().isEmpty()); // Used to work with old back-end, doesn't with new one because JSC requires that the last object in // a scope chain is the Global Object. QTest::ignoreMessage(QtWarningMsg, "QScriptContext::pushScope() failed: initial object in scope chain has to be the Global Object"); ctx->pushScope(obj); QCOMPARE(ctx->scopeChain().size(), 0); QScriptEngine eng2; QScriptValue obj2 = eng2.newObject(); QTest::ignoreMessage(QtWarningMsg, "QScriptContext::pushScope() failed: cannot push an object created in a different engine"); ctx->pushScope(obj2); QVERIFY(ctx->scopeChain().isEmpty()); QVERIFY(!ctx->popScope().isValid()); }
QScriptValue include( QScriptContext *context, QScriptEngine *engine ) { // Check argument count, include() call in global context? const QScriptContextInfo contextInfo( context->parentContext() ); if ( context->argumentCount() < 1 ) { context->throwError( i18nc("@info/plain", "One argument expected for <icode>include()</icode>") ); return engine->undefinedValue(); } else if ( context->parentContext() && context->parentContext()->parentContext() ) { QScriptContext *parentContext = context->parentContext()->parentContext(); bool error = false; while ( parentContext ) { const QScriptContextInfo parentContextInfo( parentContext ); if ( !parentContextInfo.fileName().isEmpty() && parentContextInfo.fileName() == contextInfo.fileName() ) { // Parent context is in the same file, error error = true; break; } parentContext = parentContext->parentContext(); } if ( error ) { context->throwError( i18nc("@info/plain", "<icode>include()</icode> calls must be in global context") ); return engine->undefinedValue(); } } // Check if this include() call is before all other statements QVariantHash includeData = context->callee().data().toVariant().toHash(); if ( includeData.contains(contextInfo.fileName()) ) { const quint16 maxIncludeLine = includeData[ contextInfo.fileName() ].toInt(); if ( contextInfo.lineNumber() > maxIncludeLine ) { context->throwError( i18nc("@info/plain", "<icode>include()</icode> calls must be the first statements") ); return engine->undefinedValue(); } } // Get argument and check that it's not pointing to another directory const QString fileName = context->argument(0).toString(); if ( fileName.contains('/') ) { context->throwError( i18nc("@info/plain", "Cannot include files from other directories") ); return engine->undefinedValue(); } // Get path of the main script QString path; QScriptContext *fileInfoContext = context; do { path = QFileInfo( QScriptContextInfo(fileInfoContext).fileName() ).path(); fileInfoContext = fileInfoContext->parentContext(); } while ( path.isEmpty() || path == QLatin1String(".") ); // Construct file path to the file to be included and check if the file is already included const QString filePath = path + '/' + fileName; QStringList includedFiles = engine->globalObject().property( "includedFiles" ).toVariant().toStringList(); if ( includedFiles.contains(filePath) ) { kWarning() << "File already included" << filePath; return engine->undefinedValue(); } // Try to open the file to be included QFile scriptFile( filePath ); if ( !scriptFile.open(QIODevice::ReadOnly) ) { context->throwError( i18nc("@info/plain", "Cannot find file to be included: " "<filename>%1</filename>", filePath) ); return engine->undefinedValue(); } // Read the file QTextStream stream( &scriptFile ); const QString program = stream.readAll(); scriptFile.close(); if ( !includeData.contains(scriptFile.fileName()) ) { includeData[ scriptFile.fileName() ] = maxIncludeLine( program ); QScriptValue includeFunction = engine->globalObject().property("include"); Q_ASSERT( includeFunction.isValid() ); includeFunction.setData( qScriptValueFromValue(engine, includeData) ); engine->globalObject().setProperty( "include", includeFunction, QScriptValue::KeepExistingFlags ); } // Set script context QScriptContext *parent = context->parentContext(); if ( parent ) { context->setActivationObject( parent->activationObject() ); context->setThisObject( parent->thisObject() ); } // Store included files in global property "includedFiles" includedFiles << filePath; includedFiles.removeDuplicates(); QScriptValue::PropertyFlags flags = QScriptValue::ReadOnly | QScriptValue::Undeletable; engine->globalObject().setProperty( "includedFiles", engine->newVariant(includedFiles), flags ); // Evaluate script return engine->evaluate( program, filePath ); }
void QDeclarativeContextData::addImportedScript(const QDeclarativeParser::Object::ScriptBlock &script) { if (!engine) return; QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine); QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); const QString &code = script.code; const QString &url = script.file; const QDeclarativeParser::Object::ScriptBlock::Pragmas &pragmas = script.pragmas; Q_ASSERT(!url.isEmpty()); if (pragmas & QDeclarativeParser::Object::ScriptBlock::Shared) { QHash<QString, QScriptValue>::Iterator iter = enginePriv->m_sharedScriptImports.find(url); if (iter == enginePriv->m_sharedScriptImports.end()) { QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine); scriptContext->pushScope(enginePriv->contextClass->newUrlContext(url)); scriptContext->pushScope(enginePriv->globalClass->staticGlobalObject()); QScriptValue scope = QScriptDeclarativeClass::newStaticScopeObject(scriptEngine); scriptContext->pushScope(scope); scriptEngine->evaluate(code, url, 1); if (scriptEngine->hasUncaughtException()) { QDeclarativeError error; QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error); enginePriv->warning(error); } scriptEngine->popContext(); iter = enginePriv->m_sharedScriptImports.insert(url, scope); } importedScripts.append(*iter); } else { QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine); scriptContext->pushScope(enginePriv->contextClass->newUrlContext(this, 0, url)); scriptContext->pushScope(enginePriv->globalClass->staticGlobalObject()); QScriptValue scope = QScriptDeclarativeClass::newStaticScopeObject(scriptEngine); scriptContext->pushScope(scope); scriptEngine->evaluate(code, url, 1); if (scriptEngine->hasUncaughtException()) { QDeclarativeError error; QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error); enginePriv->warning(error); } scriptEngine->popContext(); importedScripts.append(scope); } }
QScriptValue DirClass::createInstance(const QScriptContext &context) { return context.argumentCount() > 0 ? newInstance(context.argument(0).toString()) : newInstance(); }