void QSRegExpClass::write(QSObject *objPtr, const QSMember &mem, const QSObject &val ) const { if (mem.type() != QSMember::Custom) { QSWritableClass::write(objPtr, mem, val); return; } Q_ASSERT(objPtr->objectType() == objPtr->objectType()->env()->regexpClass()); switch (mem.index()) { case Source: ((QSRegExpShared*)objPtr->shVal())->source = val.toString(); break; case Global: ((QSRegExpShared*)objPtr->shVal())->global = val.toBoolean(); break; case IgnoreCase: { bool ic = val.toBoolean(); ((QSRegExpShared*)objPtr->shVal())->ignoreCase = ic; ((QSRegExpShared*)objPtr->shVal())->reg.setCaseSensitive(!ic); } break; default: QSWritableClass::write(objPtr, mem, val); } }
QSObject QSRegExpClass::fetchValue( const QSObject *objPtr, const QSMember &mem ) const { if ( mem.type() != QSMember::Custom ) return QSWritableClass::fetchValue( objPtr, mem ); QRegExp *re = regExp( objPtr ); switch ( mem.index() ) { case Valid: return createBoolean( re->isValid() ); case Empty: return createBoolean( re->isEmpty() ); case MLength: return createNumber( re->matchedLength() ); case Source: return createString( source(objPtr) ); case Global: return createBoolean( isGlobal(objPtr) ); case IgnoreCase: return createBoolean( isIgnoreCase(objPtr) ); case CTexts: { QSArray array( env() ); QStringList ct = re->capturedTexts(); QStringList::ConstIterator it = ct.begin(); int i = 0; for ( ; it != ct.end(); ++it, ++i ) array.put( QString::number( i ), createString( *it ) ); array.put( QString::fromLatin1("length"), createNumber( i ) ); return array; } default: return createUndefined(); } }
/*! Adds the Qt Script function \a qtscriptFunction (fully qualified) as a transient signal handler for the C++ signal \a signal of the object \a sender. Example: \code interpreter->addTransientSignalHandler( myButton, SIGNAL( clicked() ), "classA.obj.calculate" ); \endcode \sa removeTransientSignalHandler() */ void QSInterpreter::addTransientSignalHandler(QObject *sender, const char *signal, const char *qtscriptFunction) { QuickInterpreter *ip = interpreter(); QString func = QString::fromLatin1(qtscriptFunction); func.left(func.find('(')); QSObject senderObj = ip->wrap(sender); QSObject obj = ip->object(func); if (!obj.isFunction()) { qDebug("QSInterpreter::addTransientSignalHandler(): '%s' not a function", qtscriptFunction); return; } QSObject base = QSFuncRefClass::refBase(obj); QSMember member = QSFuncRefClass::refMember(obj); QSWrapperShared *sh = ip->wrapperClass()->shared(&senderObj); if (!sh->setEventHandler(ip, QString::fromLatin1(signal + 1), 0, member.name(), base)) { #if defined( QT_CHECK_STATE ) qWarning("QSInterpreter::addTransientSignalHandler(), " "failed to add signal handler: '%s' to '%s'", signal + 1, qtscriptFunction); #endif } }
// ECMA 8.6.2.5 bool QSObject::deleteProperty(const QString &p) { QSMember mem; if (!objectType()->member(this, p, &mem) || mem.type() == QSMember::Identifier) return TRUE; return objectType()->deleteProperty(this, mem); }
void QSRectClass::write(QSObject *o, const QSMember &mem, const QSObject &val) const { if (mem.type() == QSMember::Custom) { int i = val.toInteger(); switch (mem.idx) { case 0: case 1: rect(o)->setX(i); break; case 2: case 3: rect(o)->setY(i); break; case 4: rect(o)->setWidth(i); break; case 5: rect(o)->setHeight(i); break; case 6: rect(o)->setRight(i); break; case 7: rect(o)->setBottom(i); break; case 8: break; default: qFatal("QSRectClass::write: unhandled case"); } } else { QSClass::write(o, mem, val); } }
QSObject QSRectClass::fetchValue(const QSObject *o, const QSMember &mem) const { if (mem.type() == QSMember::Custom) { switch (mem.idx) { case 0: case 1: return createNumber(rect(o)->x()); case 2: case 3: return createNumber(rect(o)->y()); case 4: return createNumber(rect(o)->width()); case 5: return createNumber(rect(o)->height()); case 6: return createNumber(rect(o)->right()); case 7: return createNumber(rect(o)->bottom()); case 8: return pointClass()->construct(rect(o)->center()); default: qFatal("QSRectClass::fetchValue: unhandled case"); return createUndefined(); } } return QSClass::fetchValue(o, mem); }
/*! Tries to resolve a member named \a name. If it is found \a mem is initialized with the result and the class defining this member is returned. In case of a failed search, 0 is returned and the content of \a mem is undefined. */ const QSClass *QSObject::resolveMember(const QString &name, QSMember *mem, const QSClass *owner, int *offset) const { Q_ASSERT(offset); Q_ASSERT(mem); Q_ASSERT(!name.isEmpty()); if (!owner) owner = objectType(); QPtrList<QSClass> enclosing; QSMember stackedMember; while (owner) { if (owner->member(*offset == 0 ? this : 0, name, mem)) { return owner; } else if (mem->type() == QSMember::Identifier && !stackedMember.isDefined()) { stackedMember = *mem; } if (owner->enclosingClass()) enclosing.append(owner->enclosingClass()); owner = owner->base(); } const QSClass *eClass = enclosing.first(); while (eClass) { const QSClass *enc = resolveMember(name, mem, eClass, &(++(*offset))); if (enc) { if (mem->type() == QSMember::Identifier) if (!stackedMember.isDefined()) stackedMember = *mem; else return enc; } else { --(*offset); } eClass = enclosing.next(); } if (stackedMember.isDefined()) { *mem = stackedMember; return stackedMember.owner(); } return 0; }
QSObject QSEnv::resolveValue(const QString &ident) const { Q_ASSERT(!ident.isEmpty()); ScopeChain::const_iterator it = scopeChain->begin(); QSMember mem; int offset; while (it != scopeChain->end() && (*it).isValid()) { offset = 0; const QSClass *cl = (*it).resolveMember(ident, &mem, (*it).objectType(), &offset); if (cl && mem.type() != QSMember::Identifier) { while (offset--) it++; return cl->fetchValue(&(*it), mem); } it++; } return QSObject(); }
void QSVarBindingNode::check( QSCheckData *c ) { var->check( c ); if ( assign ) assign->check( c ); if (!c->directLookupEnabled()) { c->addError( this, QString::fromLatin1( "QSA does not support declaring variables inside " "a 'with' block" )); return; } int attrs = c->lastAttributes(); QSClass * cl = c->currentScope(); QSMember m; if ( cl->member( 0, var->identifier(), &m ) ) { if( cl->asClass() ) { c->addError( this, QString::fromLatin1( "Variable '%1' has already been " "declared in class '%2'" ) .arg( var->identifier() ) .arg( cl->identifier() ) ); return; } m = QSMember( QSMember::Variable, 0, attrs ); cl->replaceMember( var->identifier(), &m ); idx = m.index(); } else { idx = cl->addVariableMember( var->identifier(), attrs ); } // store pointer to init node if this is a class member QSClassClass *clcl = cl->asClass(); if ( clcl ) { if( attrs & AttributeStatic ) clcl->addStaticInitializer( assign ); else clcl->addMemberInitializer( assign ); idx = -1; // Disable the variable binding node. } }
static bool hasMember(QSEnv *env, const QString &function, QSMember::Type type) { QSObject o = env->globalObject(); QSMember member; QStringList names = function.split(QString::fromLatin1(".")); int nameCount = names.count(); for (QStringList::ConstIterator it = names.begin(); it != names.end(); ++it, --nameCount) { if (nameCount==1) { if (o.objectType() == env->typeClass()) return QSTypeClass::classValue(&o)->member(0, *it, &member) && member.type() == type; else if (o.objectType()->member(&o, *it, &member)) return o.objectType()->member(0, *it, &member) && member.type() == type; } else { o = o.get(*it); if (!o.isValid()) return false; } } return false; }
QSObject QSStringClass::fetchValue( const QSObject *objPtr, const QSMember &mem ) const { if ( mem.type() == QSMember::Custom ) if ( mem.idx == 0 ) { return createNumber( objPtr->sVal().length() ); } else { qFatal( "QSStringClass::fetchValue: unhandled member" ); return createUndefined(); } else return QSClass::fetchValue( objPtr, mem ); }
void QSResolveNode::check( QSCheckData *c ) { if ( !c->directLookupEnabled() ) return; QSClass * cl = c->currentScope(); QSClass *cont = cl; int uplvl = 0; int blocks = 0; QSMember member; while ( cont ) { QSMember mem; if ( cont->member( 0, ident, &mem ) ) { if ( mem.type()==QSMember::Variable && !mem.isStatic() ) { member = mem; break; } } uplvl++; cont = cont->enclosingClass(); } if( member.isDefined() ) { /* If the containing class has an undefined base, the indexes will be moved when the we call QSAbstractBaseClass::replace() and the lookup info will be crap. Therefore, we don't create it. */ QSClass *tmp = cont->base(); while (tmp) { if (tmp->name() == QString::fromLatin1("AbstractBase")) return; tmp = tmp->base(); } // Due to special handling of block scopes in the global object... if( cont==c->env()->globalClass() ) uplvl+=blocks; info = new QSLookupInfo( uplvl, member ); } }
QSObject QSPixmapClass::fetchValue( const QSObject *obj, const QSMember &mem ) const { if ( mem.type() == QSMember::Custom ) { switch ( mem.index() ) { case Width: return createNumber( pixmap( obj )->width() ); case Height: return createNumber( pixmap( obj )->height() ); case Rect: return rectClass()->construct( pixmap( obj )->rect() ); case Size: return sizeClass()->construct( pixmap( obj )->size() ); case Depth: return createNumber( pixmap( obj )->depth() ); default: qWarning( "QSPixmapClass::fetchValue: unhandled case" ); return createUndefined(); } } else { return QSClass::fetchValue( obj, mem ); } }
static QSObject qsDisconnect( QSEnv *env ) { QS_CONNECT_INIT( disconnect ); // find receiver and slot QObject *receiver = 0; int member_index = -1; const char *slotName = sl.ascii(); if ( recIfaces ) { for ( int i = (int)recIfaces->count()-1; i >= 0; --i ) { receiver = recIfaces->at( i ); member_index = receiver->metaObject()->findSlot( slotName, TRUE ); if ( member_index > 0 && signal_index > 0 ) { // regular signal/slot connection QObject::disconnectInternal( sender, signal_index, receiver, QSLOT_CODE, member_index ); return env->createUndefined(); } } } if ( signal_index == -1 ) { QString msg = QString::fromLatin1("Can't find signal named ") + sig; return env->throwError( SyntaxError, msg ); } if ( recIfaces ) { sendObj->removeEventHandler( sig, recIfaces->at( 0 ), sl.left( sl.find( '(' ) ) ); } else { QSObject base = QSFuncRefClass::refBase( arg2 ); QSMember member = QSFuncRefClass::refMember( arg2 ); sendObj->removeEventHandler( sig, 0, member.name(), base ); } return env->createUndefined(); }
QSObject QSPointClass::fetchValue(const QSObject *obj, const QSMember &mem) const { if (mem.type() == QSMember::Custom) { switch (mem.idx) { case 0: return createNumber(point(obj)->x()); case 1: return createNumber(point(obj)->y()); default: qFatal("QSPointClass::fetchValue: unhandled case"); return createUndefined(); } } return QSClass::fetchValue(obj, mem); }
QSObject QSSizeClass::fetchValue(const QSObject *objPtr, const QSMember &mem) const { if (mem.type() == QSMember::Custom) { switch (mem.idx) { case 0: return createNumber(size(objPtr)->width()); case 1: return createNumber(size(objPtr)->height()); default: qFatal("QSSizeClass::fetchValue, unhandled case"); return createUndefined(); } } return QSClass::fetchValue(objPtr, mem); }
void QSPointClass::write(QSObject *objPtr, const QSMember &mem, const QSObject &val) const { if (mem.type() == QSMember::Custom) { switch (mem.idx) { case 0: point(objPtr)->setX(val.toInteger()); break; case 1: point(objPtr)->setY(val.toInteger()); break; default: qDebug("QSPointClass::write() Unhandled case"); } } else { QSClass::write(objPtr, mem, val); } }
void QSSizeClass::write(QSObject *objPtr, const QSMember &mem, const QSObject &val) const { if (mem.type() == QSMember::Custom) { switch (mem.idx) { case 0: size(objPtr)->setWidth(val.toInteger()); break; case 1: size(objPtr)->setHeight(val.toInteger()); break; default: qFatal("QSSizeClass::write, unhandled case"); break; } } else { QSClass::write(objPtr, mem, val); } }
void QSFuncDeclNode::check( QSCheckData *c ) { // qDebug( "Function noticed: " + c->globalName(ident) ); if ( attrs ) attrs->check( c ); else c->setLastAttributes( AttributeNone ); int as = c->lastAttributes(); QSClass * cl = c->currentScope(); Q_ASSERT( cl ); if ( (as&AttributeStatic) && cl->name() != QString::fromLatin1("Class") ) { c->addError( this, QSErrAttrStaticContext, QString::fromLatin1( "Function '%1' cannot be declared static " "outside a class" ).arg( ident ) ); return; } // A bit of magic fail early when trying to overwrite a context. if (c->inGlobal()) { QSObject object = c->env()->globalObject().get(ident); if (object.isValid()) { if (object.objectType()->name() == QString::fromLatin1("QObject")) { c->addError(this, QString("Cannot declare function '%1', already a global object " "present with same name").arg(ident)); return; } } } QSMember m; m.setPrivate( as&AttributePrivate ); if ( cl->member( 0, ident, &m ) ) { QSMember mem( body, as ); cl->replaceMember( ident, &mem ); } else { cl->addFunctionMember( ident, body, as ); } int tmpVarBlockCount = c->varBlockCount(); c->setVarBlockCount( 0 ); QSFunctionScopeClass * fscope = new QSFunctionScopeClass( c->env()->objectClass(), this ); fscope->setEnclosingClass( cl ); body->setScopeDefinition( fscope ); fscope->setFunctionBodyNode(body); c->enterFunction( fscope ); if( param ) param->check( c ); body->check( c ); c->leaveFunction(); if( c->varBlockCount()>fscope->numVariables() ) fscope->setNumVariables( c->varBlockCount() ); c->setVarBlockCount( tmpVarBlockCount ); // Calculate the number of arguments int count = 0; QSParameterNode * node = param; while( node ) { count++; node = node->nextParam(); } fscope->setNumArguments( count ); // unset attributes c->setLastAttributes( AttributeNone ); }
void QSClassDefNode::check( QSCheckData *c ) { // qDebug( "Class noticed: " + c->globalName( ident ) ); // forward declaration ? if ( !body ) { c->addWarning( this, QString::fromLatin1("Forward declarations not supported, yet") ); return; } if ( attrs ) attrs->check( c ); else c->setLastAttributes( AttributeNone ); int as = c->lastAttributes(); // base class QSClass *b = c->env()->objectClass(); if ( type ) { type->check( c ); if ( c->hasError() ) return; Q_ASSERT( c->lastType() ); b = c->lastType(); // try to cast if ( b->isFinal() ) { c->addError( this, QSErrClassBaseFinal, QString::fromLatin1("Base class has been declared final") ); return; } } // create new class description QSClass *scope = c->currentScope(); if ( scope->name()==QString::fromLatin1("Class") ) { if ( !(as&AttributeStatic) ) { c->addError( this, QSErrNestedClass, QString::fromLatin1( "Nested class '%1' in class '%2' must be " "declared static" ) .arg( ident ).arg( scope->identifier() ) ); return; } } else if ( as&AttributeStatic ) { c->addError( this, QSErrAttributeConflict, QString::fromLatin1( "Static class '%1' cannot be declared outside " "a class" ).arg( ident ) ); return; } else if ( scope->name()==QString::fromLatin1("FunctionScope") ) { c->addError( this, QSErrNestedClass, QString::fromLatin1( "Class '%1' cannot be declared inside function '%2'" ) .arg( ident ).arg( scope->identifier() ) ); return; } QSClass *absBase = c->env()->classByIdentifier(ident); bool usesAbstractBase = absBase && absBase->name() == QString::fromLatin1("AbstractBase"); QSClassClass *cl = new QSClassClass( b, as, ident ); ref(); // Compensate for setClassDefNode below. Dereffed in QSClassClass destructor. cl->setClassDefNode( this ); cl->setEnclosingClass( scope ); QSMember member; QSObject tobj = c->env()->typeClass()->createType(cl); if( scope->member( 0, cl->identifier(), &member ) ) { scope->replaceMember( cl->identifier(), &member, tobj ); } else { scope->addStaticVariableMember( cl->identifier(), tobj, AttributeExecutable ); } c->enterClass( cl ); body->check( c ); c->leaveClass(); // if there is a function with the same name it becomes the constructor QSMember ctor; if ( cl->member( 0, ident, &ctor ) ) { if ( ctor.isExecutable() ) { cl->setHasDefaultConstructor( true ); } else { qWarning( "Constructor is no function" ); // pedantic } } cl->setClassBodyNode( body ); QSFunctionScopeClass *fs = new QSFunctionScopeClass( c->env()->objectClass() ); fs->setEnclosingClass( cl ); body->setScopeDefinition( fs ); fs->setFunctionBodyNode(body); // will be used in execute() this->cldef = cl; // If the classname exists in env and is a previously undefined type, we have to // replace it with this one. if (usesAbstractBase) { ((QSAbstractBaseClass*)absBase)->replace(cl); } }