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