예제 #1
0
QScriptValue QScriptContext::activationObject() const
{
    JSC::CallFrame *frame = const_cast<JSC::ExecState*>(QScriptEnginePrivate::frameForContext(this));
    QScript::APIShim shim(QScript::scriptEngineFromExec(frame));
    JSC::JSObject *result = 0;

    uint flags = QScriptEnginePrivate::contextFlags(frame);
    if ((flags & QScriptEnginePrivate::NativeContext) && !(flags & QScriptEnginePrivate::HasScopeContext)) {
        //For native functions, lazily create it if needed
        QScript::QScriptActivationObject *scope = new (frame) QScript::QScriptActivationObject(frame);
        frame->setScopeChain(frame->scopeChain()->copy()->push(scope));
        result = scope;
        QScriptEnginePrivate::setContextFlags(frame, flags | QScriptEnginePrivate::HasScopeContext);
    } else {
        // look in scope chain
        JSC::ScopeChainNode *node = frame->scopeChain();
        JSC::ScopeChainIterator it(node);
        for (it = node->begin(); it != node->end(); ++it) {
            if ((*it) && (*it)->isVariableObject()) {
                result = *it;
                break;
            }
        }
    }
    if (!result) {
        if (!parentContext())
            return engine()->globalObject();

        qWarning("QScriptContext::activationObject:  could not get activation object for frame");
        return QScriptValue();
        /*JSC::CodeBlock *codeBlock = frame->codeBlock();
        if (!codeBlock) {
            // non-Qt native function 
            Q_ASSERT(true); //### this should in theorry not happen
            result = new (frame)QScript::QScriptActivationObject(frame);
        } else {
            // ### this is wrong
            JSC::FunctionBodyNode *body = static_cast<JSC::FunctionBodyNode*>(codeBlock->ownerNode());
            result = new (frame)JSC::JSActivation(frame, body);
        }*/
    }

    if (result && result->inherits(&QScript::QScriptActivationObject::info)
        && (static_cast<QScript::QScriptActivationObject*>(result)->delegate() != 0)) {
        // Return the object that property access is being delegated to
        result = static_cast<QScript::QScriptActivationObject*>(result)->delegate();
    }

    return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(result);
}
예제 #2
0
/*
Returns the scope chain entry at \a index.  If index is less than 0, returns
entries starting at the end.  For example, scopeChainValue(context, -1) will return
the value last in the scope chain.
*/
QScriptValue QScriptDeclarativeClass::scopeChainValue(QScriptContext *context, int index)
{
    context->activationObject(); //ensure the creation of the normal scope for native context
    const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(context);
    QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame);
    QScript::APIShim shim(engine);

    JSC::ScopeChainNode *node = frame->scopeChain();
    JSC::ScopeChainIterator it(node);

    if (index < 0) {
        int count = 0;
        for (it = node->begin(); it != node->end(); ++it) 
            ++count;

        index = qAbs(index);
        if (index > count)
            return QScriptValue();
        else
            index = count - index;
    }

    for (it = node->begin(); it != node->end(); ++it) {

        if (index == 0) {

            JSC::JSObject *object = *it;
            if (!object) return QScriptValue();

            if (object->inherits(&QScript::QScriptActivationObject::info)
                    && (static_cast<QScript::QScriptActivationObject*>(object)->delegate() != 0)) {
                // Return the object that property access is being delegated to
                object = static_cast<QScript::QScriptActivationObject*>(object)->delegate();
            }
            return engine->scriptValueFromJSCValue(object);

        } else {
            --index;
        }

    }

    return QScriptValue();
}
예제 #3
0
/*!
  \internal
  \since 4.5

  Returns the scope chain of this QScriptContext.
*/
QScriptValueList QScriptContext::scopeChain() const
{
    activationObject(); //ensure the creation of the normal scope for native context
    const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
    QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame);
    QScript::APIShim shim(engine);
    QScriptValueList result;
    JSC::ScopeChainNode *node = frame->scopeChain();
    JSC::ScopeChainIterator it(node);
    for (it = node->begin(); it != node->end(); ++it) {
        JSC::JSObject *object = *it;
        if (!object)
            continue;
        if (object->inherits(&QScript::QScriptActivationObject::info)
            && (static_cast<QScript::QScriptActivationObject*>(object)->delegate() != 0)) {
            // Return the object that property access is being delegated to
            object = static_cast<QScript::QScriptActivationObject*>(object)->delegate();
        }
        result.append(engine->scriptValueFromJSCValue(object));
    }
    return result;
}
예제 #4
0
/*!
  \internal
*/
QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *context)
{
    Q_ASSERT(context);
    functionType = QScriptContextInfo::NativeFunction;
    functionMetaIndex = -1;
    functionStartLineNumber = -1;
    functionEndLineNumber = -1;
    scriptId = -1;
    lineNumber = -1;
    columnNumber = -1;

    JSC::CallFrame *frame = const_cast<JSC::CallFrame *>(QScriptEnginePrivate::frameForContext(context));

    // Get the line number:

    //We need to know the context directly up in the backtrace, in order to get the line number, and adjust the global context
    JSC::CallFrame *rewindContext = QScriptEnginePrivate::get(context->engine())->currentFrame;
    if (QScriptEnginePrivate::contextForFrame(rewindContext) == context) {  //top context
        frame = rewindContext; //for retreiving the global context's "fake" frame
        // An agent might have provided the line number.
        lineNumber = QScript::scriptEngineFromExec(frame)->agentLineNumber;
        if (lineNumber == -1)
            lineNumber = QScript::scriptEngineFromExec(frame)->uncaughtExceptionLineNumber;
    } else {
        // rewind the stack from the top in order to find the frame from the caller where the returnPC is stored
        while (rewindContext && QScriptEnginePrivate::contextForFrame(rewindContext->callerFrame()->removeHostCallFrameFlag()) != context)
            rewindContext = rewindContext->callerFrame()->removeHostCallFrameFlag();
        if (rewindContext) {
            frame = rewindContext->callerFrame()->removeHostCallFrameFlag(); //for retreiving the global context's "fake" frame

            JSC::Instruction *returnPC = rewindContext->returnPC();
            JSC::CodeBlock *codeBlock = frame->codeBlock();
            if (returnPC && codeBlock && QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) {
#if ENABLE(JIT)
                JSC::JITCode code = codeBlock->getJITCode();
                uintptr_t jitOffset = reinterpret_cast<uintptr_t>(JSC::ReturnAddressPtr(returnPC).value()) - reinterpret_cast<uintptr_t>(code.addressForCall().executableAddress());
                // We can only use the JIT code offset if it's smaller than the JIT size;
                // otherwise calling getBytecodeIndex() is meaningless.
                if (jitOffset < code.size()) {
                    unsigned bytecodeOffset = codeBlock->getBytecodeIndex(frame, JSC::ReturnAddressPtr(returnPC));
#else
                unsigned bytecodeOffset = returnPC - codeBlock->instructions().begin();
#endif
                bytecodeOffset--; //because returnPC is on the next instruction. We want the current one
                lineNumber = codeBlock->lineNumberForBytecodeOffset(const_cast<JSC::ExecState *>(frame), bytecodeOffset);
#if ENABLE(JIT)
                }
#endif
            }
        }
    }

    // Get the filename and the scriptId:
    JSC::CodeBlock *codeBlock = frame->codeBlock();
    if (codeBlock && QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) {
           JSC::SourceProvider *source = codeBlock->source();
           scriptId = source->asID();
           fileName = source->url();
    }

    // Get the others information:
    JSC::JSObject *callee = frame->callee();
    if (callee && callee->inherits(&JSC::InternalFunction::info))
        functionName = JSC::asInternalFunction(callee)->name(frame);
    if (callee && callee->inherits(&JSC::JSFunction::info)
        && !JSC::asFunction(callee)->isHostFunction()) {
        functionType = QScriptContextInfo::ScriptFunction;
        JSC::FunctionExecutable *body = JSC::asFunction(callee)->jsExecutable();
        functionStartLineNumber = body->lineNo();
        functionEndLineNumber = body->lastLine();
        for (size_t i = 0; i < body->parameterCount(); ++i)
            parameterNames.append(body->parameterName(i));
        // ### get the function name from the AST
    } else if (callee && callee->inherits(&QScript::QtFunction::info)) {
        functionType = QScriptContextInfo::QtFunction;
        functionMetaIndex = static_cast<QScript::QtFunction*>(callee)->specificIndex(context);
        const QMetaObject *meta = static_cast<QScript::QtFunction*>(callee)->metaObject();
        if (meta != 0) {
            QMetaMethod method = meta->method(functionMetaIndex);
            QList<QByteArray> formals = method.parameterNames();
            for (int i = 0; i < formals.count(); ++i)
                parameterNames.append(QLatin1String(formals.at(i)));
        }
    }
    else if (callee && callee->inherits(&QScript::QtPropertyFunction::info)) {
        functionType = QScriptContextInfo::QtPropertyFunction;
        functionMetaIndex = static_cast<QScript::QtPropertyFunction*>(callee)->propertyIndex();
    }
}