#include "kjs_proxy.h"
#include "kjs_window.h"
#include "kjs_events.h"
#include <khtml_part.h>
#include <kprotocolmanager.h>
#include <kdebug.h>
#include <kjs/collector.h>
using namespace KJS;
extern "C" {
KJSProxy *kjs_html_init(KHTMLPart *khtmlpart);
}
class KJSProxyImpl : public KJSProxy {
public:
KJSProxyImpl(KHTMLPart *part);
virtual ~KJSProxyImpl();
virtual QVariant evaluate(QString filename, int baseLine, const QString&str, const DOM::Node &n);
virtual void clear();
virtual DOM::EventListener *createHTMLEventHandler(QString sourceUrl, QString code, DOM::NodeImpl *node);
virtual void finishedWithEvent(const DOM::Event &event);
virtual KJS::ScriptInterpreter *interpreter();
virtual void setDebugEnabled(bool enabled);
virtual bool paused() const;
virtual void setSourceFile(QString url, QString code);
virtual void appendSourceFile(QString url, QString code);
void initScript();
private:
KJS::ScriptInterpreter* m_script;
bool m_debugEnabled;
#ifndef NDEBUG
static int s_count;
#endif
};
#ifndef NDEBUG
int KJSProxyImpl::s_count = 0;
#endif
KJSProxyImpl::KJSProxyImpl(KHTMLPart *part)
{
m_script = 0;
m_part = part;
m_debugEnabled = false;
#ifndef NDEBUG
s_count++;
#endif
}
KJSProxyImpl::~KJSProxyImpl()
{
delete m_script;
#ifndef NDEBUG
s_count--;
#ifdef KJS_DEBUG_MEM
if ( s_count == 0 )
Interpreter::finalCheck();
#endif
#endif
}
QVariant KJSProxyImpl::evaluate(QString filename, int baseLine,
const QString&str, const DOM::Node &n) {
initScript();
bool inlineCode = filename.isNull();
#ifdef KJS_DEBUGGER
if (inlineCode)
filename = "(unknown file)";
if (KJSDebugWin::instance())
KJSDebugWin::instance()->setNextSourceInfo(filename,baseLine);
#else
Q_UNUSED(baseLine);
#endif
m_script->setInlineCode(inlineCode);
KJS::Value thisNode = n.isNull() ? Window::retrieve( m_part ) : getDOMNode(m_script->globalExec(),n);
UString code( str );
Completion comp = m_script->evaluate(filename, baseLine, code, thisNode);
bool success = ( comp.complType() == Normal ) || ( comp.complType() == ReturnValue );
#ifdef KJS_DEBUGGER
#endif
if (success && !comp.value().isNull())
return ValueToVariant( m_script->globalExec(), comp.value());
else
{
if ( comp.complType() == Throw )
{
KJS::Interpreter::lock();
UString errorMessage = comp.value().toString(m_script->globalExec());
int lineNumber = comp.value().toObject(m_script->globalExec()).get(m_script->globalExec(), "line").toInt32(m_script->globalExec());
UString sourceURL = comp.value().toObject(m_script->globalExec()).get(m_script->globalExec(), "sourceURL").toString(m_script->globalExec());
KJS::Interpreter::unlock();
#if APPLE_CHANGES
KWQ(m_part)->addMessageToConsole(errorMessage.qstring(), lineNumber, sourceURL.qstring());
#else
kdWarning(6070) << "Script threw exception: " << errorMessage.qstring() << endl;
#endif
}
return QVariant();
}
}
void KJSProxyImpl::clear() {
if (m_script) {
#ifdef KJS_DEBUGGER
KJSDebugWin *debugWin = KJSDebugWin::instance();
if (debugWin && debugWin->currentScript() == m_script) {
debugWin->setMode(KJSDebugWin::Stop);
}
#endif
Window *win = Window::retrieveWindow(m_part);
if (win)
win->clear( m_script->globalExec() );
}
}
DOM::EventListener *KJSProxyImpl::createHTMLEventHandler(QString sourceUrl, QString code, DOM::NodeImpl *node)
{
#ifdef KJS_DEBUGGER
if (KJSDebugWin::instance())
KJSDebugWin::instance()->setNextSourceInfo(sourceUrl,m_handlerLineno);
#else
Q_UNUSED(sourceUrl);
#endif
initScript();
return KJS::Window::retrieveWindow(m_part)->getJSLazyEventListener(code,node,m_handlerLineno);
}
void KJSProxyImpl::finishedWithEvent(const DOM::Event &event)
{
m_script->forgetDOMObject(event.handle());
}
KJS::ScriptInterpreter *KJSProxyImpl::interpreter()
{
if (!m_script)
initScript();
m_part->keepAlive();
return m_script;
}
void KJSProxyImpl::setDebugEnabled(bool enabled)
{
#ifdef KJS_DEBUGGER
m_debugEnabled = enabled;
if (m_script)
m_script->setDebuggingEnabled(enabled);
if (!enabled && KJSDebugWin::instance()) {
KJSDebugWin::destroyInstance();
}
else if (enabled && !KJSDebugWin::instance()) {
KJSDebugWin::createInstance();
initScript();
KJSDebugWin::instance()->attach(m_script);
}
#else
Q_UNUSED(enabled);
#endif
}
bool KJSProxyImpl::paused() const
{
#ifdef KJS_DEBUGGER
if (KJSDebugWin::instance())
return KJSDebugWin::instance()->inSession();
#endif
return false;
}
void KJSProxyImpl::setSourceFile(QString url, QString code)
{
#ifdef KJS_DEBUGGER
if (KJSDebugWin::instance())
KJSDebugWin::instance()->setSourceFile(url,code);
#else
Q_UNUSED(url);
Q_UNUSED(code);
#endif
}
void KJSProxyImpl::appendSourceFile(QString url, QString code)
{
#ifdef KJS_DEBUGGER
if (KJSDebugWin::instance())
KJSDebugWin::instance()->appendSourceFile(url,code);
#else
Q_UNUSED(url);
Q_UNUSED(code);
#endif
}
class TestFunctionImp : public ObjectImp {
public:
TestFunctionImp() : ObjectImp() {}
virtual bool implementsCall() const { return true; }
virtual Value call(ExecState *exec, Object &thisObj, const List &args);
};
Value TestFunctionImp::call(ExecState *exec, Object &, const List &args)
{
fprintf(stderr,"--> %s\n",args[0].toString(exec).ascii());
return Undefined();
}
void KJSProxyImpl::initScript()
{
if (m_script)
return;
KJS::Interpreter::lock();
Object globalObject( new Window(m_part) );
KJS::Interpreter::unlock();
m_script = new KJS::ScriptInterpreter(globalObject, m_part);
#ifdef KJS_DEBUGGER
m_script->setDebuggingEnabled(m_debugEnabled);
#endif
KJS::Interpreter::lock();
globalObject.put(m_script->globalExec(),
"debug", Value(new TestFunctionImp()), Internal);
KJS::Interpreter::unlock();
#if APPLE_CHANGES
QString userAgent = KWQ(m_part)->userAgent();
#else
QString userAgent = KProtocolManager::userAgentForHost(m_part->url().host());
#endif
if (userAgent.find(QString::fromLatin1("Microsoft")) >= 0 ||
userAgent.find(QString::fromLatin1("MSIE")) >= 0)
m_script->setCompatMode(Interpreter::IECompat);
else
if (userAgent.find(QString::fromLatin1("Mozilla")) >= 0 &&
userAgent.find(QString::fromLatin1("compatible")) == -1)
m_script->setCompatMode(Interpreter::NetscapeCompat);
}
KJSProxy * KJSProxy::proxy( KHTMLPart *part )
{
return part->jScript();
}
KJSProxy *kjs_html_init(KHTMLPart *khtmlpart)
{
return new KJSProxyImpl(khtmlpart);
}