/*! \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)); }
bool ClassObjectDelegate::getOwnPropertySlot(QScriptObject* object, JSC::ExecState *exec, const JSC::Identifier &propertyName, JSC::PropertySlot &slot) { QScriptEnginePrivate *engine = scriptEngineFromExec(exec); QScript::SaveFrameHelper saveFrame(engine, exec); // for compatibility with the old back-end, normal JS properties // are queried first. if (QScriptObjectDelegate::getOwnPropertySlot(object, exec, propertyName, slot)) return true; QScriptValue scriptObject = engine->scriptValueFromJSCValue(object); QScriptString scriptName; QScriptStringPrivate scriptName_d(engine, propertyName, QScriptStringPrivate::StackAllocated); QScriptStringPrivate::init(scriptName, &scriptName_d); uint id = 0; QScriptClass::QueryFlags flags = m_scriptClass->queryProperty( scriptObject, scriptName, QScriptClass::HandlesReadAccess, &id); if (flags & QScriptClass::HandlesReadAccess) { QScriptValue value = m_scriptClass->property(scriptObject, scriptName, id); if (!value.isValid()) { // The class claims to have the property, but returned an invalid // value. Silently convert to undefined to avoid the invalid value // "escaping" into JS. value = QScriptValue(QScriptValue::UndefinedValue); } slot.setValue(engine->scriptValueToJSCValue(value)); return true; } return false; }
bool ClassObjectDelegate::getOwnPropertySlot(QScriptObject* object, JSC::ExecState *exec, const JSC::Identifier &propertyName, JSC::PropertySlot &slot) { QScriptEnginePrivate *engine = scriptEngineFromExec(exec); QScript::SaveFrameHelper saveFrame(engine, exec); // for compatibility with the old back-end, normal JS properties // are queried first. if (QScriptObjectDelegate::getOwnPropertySlot(object, exec, propertyName, slot)) return true; QScriptValue scriptObject = engine->scriptValueFromJSCValue(object); QScriptString scriptName; QScriptStringPrivate scriptName_d(engine, propertyName, QScriptStringPrivate::StackAllocated); QScriptStringPrivate::init(scriptName, &scriptName_d); uint id = 0; QScriptClass::QueryFlags flags = m_scriptClass->queryProperty( scriptObject, scriptName, QScriptClass::HandlesReadAccess, &id); if (flags & QScriptClass::HandlesReadAccess) { QScriptValue value = m_scriptClass->property(scriptObject, scriptName, id); slot.setValue(engine->scriptValueToJSCValue(value)); return true; } return false; }
bool GlobalObject::getOwnPropertySlot(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertySlot& slot) { QScriptEnginePrivate *engine = scriptEngineFromExec(exec); if (propertyName == exec->propertyNames().arguments && engine->currentFrame->argumentCount() > 0) { JSC::JSValue args = engine->scriptValueToJSCValue(engine->contextForFrame(engine->currentFrame)->argumentsObject()); slot.setValue(args); return true; } if (customGlobalObject) return customGlobalObject->getOwnPropertySlot(exec, propertyName, slot); return JSC::JSGlobalObject::getOwnPropertySlot(exec, propertyName, slot); }
/*! Sets the activation object of this QScriptContext to be the given \a activation. If \a activation is not an object, this function does nothing. \note For a context corresponding to a JavaScript function, this is only guaranteed to work if there was an QScriptEngineAgent active on the engine while the function was evaluated. */ void QScriptContext::setActivationObject(const QScriptValue &activation) { if (!activation.isObject()) return; else if (activation.engine() != engine()) { qWarning("QScriptContext::setActivationObject() failed: " "cannot set 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 *object = JSC::asObject(engine->scriptValueToJSCValue(activation)); if (object == engine->originalGlobalObjectProxy) object = engine->originalGlobalObject(); uint flags = QScriptEnginePrivate::contextFlags(frame); if ((flags & QScriptEnginePrivate::NativeContext) && !(flags & QScriptEnginePrivate::HasScopeContext)) { //For native functions, we create a scope node JSC::JSObject *scope = object; if (!scope->isVariableObject()) { // Create a QScriptActivationObject that acts as a proxy scope = new (frame) QScript::QScriptActivationObject(frame, scope); } frame->setScopeChain(frame->scopeChain()->copy()->push(scope)); QScriptEnginePrivate::setContextFlags(frame, flags | QScriptEnginePrivate::HasScopeContext); return; } // else replace the first activation object in the scope chain JSC::ScopeChainNode *node = frame->scopeChain(); while (node != 0) { if (node->object && node->object->isVariableObject()) { if (!object->isVariableObject()) { if (node->object->inherits(&QScript::QScriptActivationObject::info)) { static_cast<QScript::QScriptActivationObject*>(node->object)->setDelegate(object); } else { // Create a QScriptActivationObject that acts as a proxy node->object = new (frame) QScript::QScriptActivationObject(frame, object); } } else { node->object = object; } break; } node = node->next; } }
bool GlobalObject::getOwnPropertyDescriptor(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertyDescriptor& descriptor) { // Must match the logic of getOwnPropertySlot(). QScriptEnginePrivate *engine = scriptEngineFromExec(exec); if (propertyName == exec->propertyNames().arguments && engine->currentFrame->argumentCount() > 0) { // ### Can we get rid of this special handling of the arguments property? JSC::JSValue args = engine->scriptValueToJSCValue(engine->contextForFrame(engine->currentFrame)->argumentsObject()); descriptor.setValue(args); return true; } if (customGlobalObject) return customGlobalObject->getOwnPropertyDescriptor(exec, propertyName, descriptor); return JSC::JSGlobalObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); }
bool ClassObjectDelegate::getOwnPropertyDescriptor(QScriptObject *object, JSC::ExecState *exec, const JSC::Identifier &propertyName, JSC::PropertyDescriptor &descriptor) { QScriptEnginePrivate *engine = scriptEngineFromExec(exec); QScript::SaveFrameHelper saveFrame(engine, exec); // for compatibility with the old back-end, normal JS properties // are queried first. if (QScriptObjectDelegate::getOwnPropertyDescriptor(object, exec, propertyName, descriptor)) return true; QScriptValue scriptObject = engine->scriptValueFromJSCValue(object); QScriptString scriptName; QScriptStringPrivate scriptName_d(engine, propertyName, QScriptStringPrivate::StackAllocated); QScriptStringPrivate::init(scriptName, &scriptName_d); uint id = 0; QScriptClass::QueryFlags qflags = m_scriptClass->queryProperty( scriptObject, scriptName, QScriptClass::HandlesReadAccess, &id); if (qflags & QScriptClass::HandlesReadAccess) { QScriptValue::PropertyFlags pflags = m_scriptClass->propertyFlags(scriptObject, scriptName, id); unsigned attribs = 0; if (pflags & QScriptValue::ReadOnly) attribs |= JSC::ReadOnly; if (pflags & QScriptValue::SkipInEnumeration) attribs |= JSC::DontEnum; if (pflags & QScriptValue::Undeletable) attribs |= JSC::DontDelete; if (pflags & QScriptValue::PropertyGetter) attribs |= JSC::Getter; if (pflags & QScriptValue::PropertySetter) attribs |= JSC::Setter; attribs |= pflags & QScriptValue::UserRange; // Rather than calling the getter, we could return an access descriptor here. QScriptValue value = m_scriptClass->property(scriptObject, scriptName, id); if (!value.isValid()) { // The class claims to have the property, but returned an invalid // value. Silently convert to undefined to avoid the invalid value // "escaping" into JS. value = QScriptValue(QScriptValue::UndefinedValue); } descriptor.setDescriptor(engine->scriptValueToJSCValue(value), attribs); return true; } return false; }
bool DeclarativeObjectDelegate::getOwnPropertySlot(QScriptObject* object, JSC::ExecState *exec, const JSC::Identifier &propertyName, JSC::PropertySlot &slot) { QScriptEnginePrivate *engine = scriptEngineFromExec(exec); QScriptDeclarativeClass::Identifier identifier = (void *)propertyName.ustring().rep(); QScriptDeclarativeClassPrivate *p = QScriptDeclarativeClassPrivate::get(m_class); p->context = reinterpret_cast<QScriptContext *>(exec); QScriptClass::QueryFlags flags = m_class->queryProperty(m_object, identifier, QScriptClass::HandlesReadAccess); if (flags & QScriptClass::HandlesReadAccess) { QScriptValue value = m_class->property(m_object, identifier); p->context = 0; slot.setValue(engine->scriptValueToJSCValue(value)); return true; } p->context = 0; return QScriptObjectDelegate::getOwnPropertySlot(object, exec, propertyName, slot); }