/*! \internal \since 4.5 Adds the given \a object to the front of this context's scope chain. If \a object is not an object, this function does nothing. */ void QScriptContext::pushScope(const QScriptValue &object) { activationObject(); //ensure the creation of the normal scope for native context if (!object.isObject()) return; else if (object.engine() != engine()) { qWarning("QScriptContext::pushScope() failed: " "cannot push an object created in " "a different engine"); return; } JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame); QScript::APIShim shim(engine); JSC::JSObject *jscObject = JSC::asObject(engine->scriptValueToJSCValue(object)); if (jscObject == engine->originalGlobalObjectProxy) jscObject = engine->originalGlobalObject(); JSC::ScopeChainNode *scope = frame->scopeChain(); Q_ASSERT(scope != 0); if (!scope->object) { // pushing to an "empty" chain if (!jscObject->isGlobalObject()) { qWarning("QScriptContext::pushScope() failed: initial object in scope chain has to be the Global Object"); return; } scope->object = jscObject; } else frame->setScopeChain(scope->push(jscObject)); }
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 Removes the front object from this context's scope chain, and returns the removed object. If the scope chain is already empty, this function returns an invalid QScriptValue. */ QScriptValue QScriptContext::popScope() { activationObject(); //ensure the creation of the normal scope for native context JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this); JSC::ScopeChainNode *scope = frame->scopeChain(); Q_ASSERT(scope != 0); QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame); QScript::APIShim shim(engine); QScriptValue result = engine->scriptValueFromJSCValue(scope->object); if (!scope->next) { // We cannot have a null scope chain, so just zap the object pointer. scope->object = 0; } else { frame->setScopeChain(scope->pop()); } return result; }
/* 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(); }
/*! \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; }