/* * Copyright (C) 2001-2003, Richard J. Moore * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #ifndef QT_ONLY #include #endif // QT_ONLY #include #include #include #include #include #include "global.h" #include "jsfactory.h" #include "jsbinding.h" #include "jsobjectproxy.h" #include "jsconsolewidget.h" #include "jsbuiltin.h" #ifndef QT_ONLY #include "bindings/image_imp.h" #endif // QT_ONLY #include "kjsembedpart_imp.h" #include "kjsembedpart.h" #ifndef QT_ONLY #include "kjsembedpart.moc" namespace KJSEmbed { class KJSEmbedActionRunner : public XMLActionRunner { public: KJSEmbedActionRunner( KJSEmbedPart *jspart ) : XMLActionRunner(), part(jspart) {} virtual ~KJSEmbedActionRunner() {} virtual bool run( XMLActionClient *client, const XMLActionClient::XMLActionScript &script ) { if ( script.type == "js" ) return part->runFile( script.src ); else return XMLActionRunner::run( client, script ); } private: KJSEmbedPart *part; }; } // namespace KJSEmbed #else // QT_ONLY #include "qtstubs.h" #endif // QT_ONLY namespace KJSEmbed { // // KPart // KJSEmbedPart::KJSEmbedPart( TQObject *parent, const char *name ) : KParts::ReadOnlyPart( parent, name ? name : "kjsembed_part" ), jsConsole(0), jsfactory(0), widgetparent(0), widgetname(name ? name : "kjsembed_part"), deletejs(false) { createInterpreter(); createBuiltIn( js->globalExec(), js->globalObject() ); createActionClient(); } KJSEmbedPart::KJSEmbedPart( TQWidget *wparent, const char *wname, TQObject *parent, const char *name ) : KParts::ReadOnlyPart( parent, name ? name : (wname?wname:"jsembed_part") ), jsConsole(0), jsfactory(0), widgetparent(wparent), widgetname(wname), deletejs(false) { createInterpreter(); createBuiltIn( js->globalExec(), js->globalObject() ); createActionClient(); } KJSEmbedPart::KJSEmbedPart( KJS::Interpreter *jsi, TQWidget *wparent, const char *wname, TQObject *parent, const char *name ) : KParts::ReadOnlyPart( parent, name ? name : (wname?wname:"jsembed_part") ), jsConsole(0), jsfactory(0), builtins(0), widgetparent(wparent), widgetname(wname), js(jsi), deletejs(false) { if ( !js ) { createInterpreter(); createBuiltIn( js->globalExec(), js->globalObject() ); } createActionClient(); } KJSEmbedPart::~KJSEmbedPart() { if ( deletejs ) delete js; delete jsfactory; delete builtins; } void KJSEmbedPart::createInterpreter() { deletejs = true; js = new KJS::Interpreter(); jsfactory = new JSFactory( this ); jsfactory->addType( className() ); jsfactory->addTypes( js->globalExec(), js->globalObject() ); } void KJSEmbedPart::createBuiltIn( KJS::ExecState *exec, KJS::Object &parent ) { partobj = addObject( this, parent, "part" ); builtins = new JSBuiltIn( this ); builtins->add( exec, parent ); } void KJSEmbedPart::createActionClient() { #ifndef QT_ONLY xmlclient = new KJSEmbed::XMLActionClient( this ); xmlclient->setActionCollection( actionCollection() ); xmlclient->setRunner( new KJSEmbedActionRunner(this) ); #endif // QT_ONLY } JSConsoleWidget *KJSEmbedPart::view() { #ifndef QT_ONLY if ( !jsConsole ) { TQCString name = widgetname ? widgetname : TQCString("jsembed_console"); jsConsole = new JSConsoleWidget( this, widgetparent, name ); setWidget( jsConsole ); jsfactory->addType( jsConsole->className() ); } return jsConsole; #endif // QT_ONLY return 0L; } TQStringList KJSEmbedPart::constructorNames() const { TQStringList classes; KJS::List cons = constructorList(); KJS::ListIterator it = cons.begin(); while ( it != cons.end() ) { KJS::Value v = *it; classes += v.toString( js->globalExec() ).qstring(); it++; } return classes; } KJS::Value KJSEmbedPart::constructors() const { KJS::List items = constructorList(); kdDebug(80001) << "KJSEmbedPart::constructors() returning " << items.size() << " items" << endl; return KJS::Object( js->builtinArray().construct( js->globalExec(), items ) ); } KJS::List KJSEmbedPart::constructorList() const { KJS::List items; KJS::Object obj = js->globalObject(); KJS::ExecState *exec = js->globalExec(); KJS::ReferenceList l = obj.propList( exec ); KJS::ReferenceListIterator propIt = l.begin(); while ( propIt != l.end() ) { KJS::Identifier name = propIt->getPropertyName( exec ); if ( obj.hasProperty( exec, name ) ) { KJS::Value v = obj.get( exec, name ); KJS::Object vobj = v.toObject( exec ); if ( vobj.implementsConstruct() ) items.append( KJS::String( name.ustring() ) ); } propIt++; } return items; } // // Version information // TQCString KJSEmbedPart::versionString() const { return TQCString(KJSEMBED_VERSION_STRING); } int KJSEmbedPart::versionMajor() const { return KJSEMBED_VERSION_MAJOR; } int KJSEmbedPart::versionMinor() const { return KJSEMBED_VERSION_MINOR; } // // Execute a JS script. // KJS::Value KJSEmbedPart::evaluate( const TQString &script, const KJS::Value &self ) { if ( execute( res, script, self ) ) return res.value(); return KJS::Null(); } bool KJSEmbedPart::execute( const TQString &script, const KJS::Value &self ) { return execute( res, script, self ); } bool KJSEmbedPart::execute( KJS::Completion &result, const TQString &script, const KJS::Value &self ) { KJS::Value val( self ); result = js->evaluate( script, self.isNull() ? partobj : val ); return (result.complType() == KJS::Normal) || (result.complType() == KJS::ReturnValue); } bool KJSEmbedPart::openURL( const KURL &url ) { if ( url.protocol() == "javascript" ) { // kdDebug(80001) << "KJSEmbedPart: openURL '" << url.url() << "' is javascript" << endl; #ifndef QT_ONLY TQString cmd = url.url(); #else TQString cmd = url.toString(); #endif TQString js( "javascript:" ); cmd = cmd.replace( 0, js.length(), TQString("") ); // kdDebug(80001) << "KJSEmbedPart: JS command is '" << cmd << "'" << endl; return execute( cmd ); } return false; } // // Invoke a script file. // bool KJSEmbedPart::runFile( const TQString &name, const KJS::Value &self ) { kdDebug(80001) << "KJSEmbedPart::runFile(): file is '" << name << "'" << endl; TQString script = loadFile( name ); return execute( script, self ); } bool KJSEmbedPart::loadActionSet( const TQString &file ) { #ifndef QT_ONLY return xmlclient->load( file ); #else // QT_ONLY Q_UNUSED( file ); return false; #endif // QT_ONLY } TQString KJSEmbedPart::loadFile( const TQString &src ) { TQString script; if ( src == "-" ) { TQTextStream ts( stdin, IO_ReadOnly ); script = ts.read(); } else { TQFile file( src ); if ( file.open( IO_ReadOnly ) ) { script = TQString( file.readAll() ); } else { kdWarning() << "Could not open file '" << src << "', " << strerror( errno ) << endl; return TQString::null; } } if ( script.startsWith( "#!" ) ) { int pos = script.find( "\n" ); if ( pos > 0 ) script = script.mid( pos ); } return script; } // // Publishing objects. // KJS::Object KJSEmbedPart::bind( TQObject *obj ) { KJS::Object jsobj = jsfactory->createProxy( js->globalExec(), obj ); JSProxy::toObjectProxy(jsobj.imp() )->setOwner(JSProxy::Native); return jsobj; } KJS::Object KJSEmbedPart::addObject( TQObject *obj, KJS::Object &parent, const char *name ) { KJS::Object jsobj = bind( obj ); parent.put( js->globalExec(), name ? name : obj->name(), jsobj ); return jsobj; } KJS::Object KJSEmbedPart::addObject( TQObject *obj, const char *name ) { return addObject( obj, js->globalObject(), name ); } void KJSEmbedPart::virtual_hook( int /*id*/, void * /*data*/ ) { } static KJS::Object scopeWalker( KJS::ExecState *exec, const KJS::Object &root, const TQString &objectString ) { KJS::Object returnObject = root; TQStringList objects = TQStringList::split(".", objectString); for( uint idx = 0; idx < objects.count(); ++idx) { KJS::Identifier id = KJS::Identifier( KJS::UString( objects[idx] )); KJS::Value newObject = returnObject.get(exec, id ); if( newObject.isValid() ) returnObject = newObject.toObject(exec); } return returnObject; } KJS::Value KJSEmbedPart::callMethod( const TQString & methodName, const KJS::List & args ) const { KJS::ExecState *exec = js->globalExec(); KJS::Identifier id = KJS::Identifier( KJS::UString(methodName.latin1() )); KJS::Object obj = js->globalObject(); KJS::Object fun = obj.get(exec, id ).toObject( exec ); KJS::Value retValue; if ( !fun.implementsCall() ) { // We need to create an exception here... } else retValue = fun.call(exec, obj, args); kdDebug( 80001 ) << "Returned type is: " << retValue.type() << endl; if( exec->hadException() ) { kdWarning( 80001 ) << "Got error: " << exec->exception().toString(exec).qstring() << endl; return exec->exception(); } else { if( retValue.type() == 1 && retValue.type() == 0) { kdDebug( 80001 ) << "Got void return type. " << endl; return KJS::Null(); } } return retValue; } KJS::Value KJSEmbedPart::getValue( const TQString & valueName ) const { KJS::ExecState *exec = js->globalExec(); KJS::Identifier id = KJS::Identifier( KJS::UString(valueName.latin1() )); KJS::Object obj = js->globalObject(); return obj.get(exec, id ); } void KJSEmbedPart::putValue( const TQString & valueName, const KJS::Value & value ) { KJS::ExecState *exec = js->globalExec(); KJS::Identifier id = KJS::Identifier( KJS::UString(valueName.latin1() )); KJS::Object obj = js->globalObject(); obj.put(exec, id, value); } void KJSEmbedPart::putVariant( const TQString & valueName, const TQVariant & value ) { KJS::Value val = convertToValue( js->globalExec(), value); putValue( valueName, val ); } TQVariant KJSEmbedPart::getVariant( const TQString & valueName ) const { return convertToVariant( js->globalExec(), getValue( valueName ) ); } bool KJSEmbedPart::hasMethod( const TQString & methodName ) { KJS::ExecState *exec = js->globalExec(); KJS::Identifier id = KJS::Identifier( KJS::UString(methodName.latin1() )); KJS::Object obj = js->globalObject(); KJS::Object fun = obj.get(exec, id ).toObject( exec ); return fun.implementsCall(); } }// namespace KJSEmbed