📄 kjs_binding.cpp
字号:
// -*- c-basic-offset: 2 -*-/* * This file is part of the KDE libraries * Copyright (C) 1999-2003 Harri Porten (porten@kde.org) * Copyright (C) 2001-2003 David Faure (faure@kde.org) * Copyright (C) 2003 Apple Computer, Inc. * * 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; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */#include "kjs_binding.h"#include "kjs_dom.h"#include "dom/dom_exception.h"#include "dom/dom2_range.h"#include "xml/dom2_eventsimpl.h"#include "khtmlpart_p.h"#include <kdebug.h>#include <kparts/browserextension.h>#include <assert.h>using namespace KJS;/* TODO: * The catch all (...) clauses below shouldn't be necessary. * But they helped to view for example www.faz.net in an stable manner. * Those unknown exceptions should be treated as severe bugs and be fixed. * * these may be CSS exceptions - need to check - pmk */Value DOMObject::get(ExecState *exec, const Identifier &p) const{ Value result; try { result = tryGet(exec,p); } catch (DOM::DOMException e) { // ### translate code into readable string ? // ### oh, and s/QString/i18n or I18N_NOOP (the code in kjs uses I18N_NOOP... but where is it translated ?) // and where does it appear to the user ? Object err = Error::create(exec, GeneralError, QString("DOM exception %1").arg(e.code).local8Bit()); exec->setException( err ); result = Undefined(); } catch (...) { kdError(6070) << "Unknown exception in DOMObject::get()" << endl; result = String("Unknown exception"); } return result;}void DOMObject::put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr){ try { tryPut(exec, propertyName, value, attr); } catch (DOM::DOMException e) { Object err = Error::create(exec, GeneralError, QString("DOM exception %1").arg(e.code).local8Bit()); exec->setException(err); } catch (...) { kdError(6070) << "Unknown exception in DOMObject::put()" << endl; }}void DOMObject::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr){ static_cast<ScriptInterpreter*>(exec->dynamicInterpreter())->customizedDOMObject(this); ObjectImp::put(exec,propertyName,value,attr);}UString DOMObject::toString(ExecState *) const{ return "[object " + className() + "]";}Value DOMFunction::get(ExecState *exec, const Identifier &propertyName) const{ try { return tryGet(exec, propertyName); } catch (DOM::DOMException e) { Object err = Error::create(exec, GeneralError, QString("DOM exception %1").arg(e.code).local8Bit()); exec->setException(err); return Undefined(); } catch (...) { kdError(6070) << "Unknown exception in DOMFunction::get()" << endl; return String("Unknown exception"); }}Value DOMFunction::call(ExecState *exec, Object &thisObj, const List &args){ try { return tryCall(exec, thisObj, args); } // pity there's no way to distinguish between these in JS code // ### Look into setting prototypes of these & the use of instanceof so the exception // type can be determined. See what other browsers do. catch (DOM::DOMException e) { Object err = Error::create(exec, GeneralError, QString("DOM Exception %1").arg(e.code).local8Bit()); err.put(exec, "code", Number(e.code)); exec->setException(err); return Undefined(); } catch (DOM::RangeException e) { Object err = Error::create(exec, GeneralError, QString("DOM Range Exception %1").arg(e.code).local8Bit()); err.put(exec, "code", Number(e.code)); exec->setException(err); return Undefined(); } catch (DOM::CSSException e) { Object err = Error::create(exec, GeneralError, QString("CSS Exception %1").arg(e.code).local8Bit()); err.put(exec, "code", Number(e.code)); exec->setException(err); return Undefined(); } catch (DOM::EventException e) { Object err = Error::create(exec, GeneralError, QString("DOM Event Exception %1").arg(e.code).local8Bit()); err.put(exec, "code", Number(e.code)); exec->setException(err); return Undefined(); } catch (...) { kdError(6070) << "Unknown exception in DOMFunction::call()" << endl; Object err = Error::create(exec, GeneralError, "Unknown exception"); exec->setException(err); return Undefined(); }}typedef QPtrList<ScriptInterpreter> InterpreterList;static InterpreterList *interpreterList;ScriptInterpreter::ScriptInterpreter( const Object &global, khtml::ChildFrame* frame ) : Interpreter( global ), m_frame( frame ), m_domObjects(1021), m_evt( 0L ), m_inlineCode(false), m_timerCallback(false){#ifdef KJS_VERBOSE kdDebug(6070) << "ScriptInterpreter::ScriptInterpreter " << this << " for part=" << m_frame << endl;#endif if ( !interpreterList ) interpreterList = new InterpreterList; interpreterList->append( this );}ScriptInterpreter::~ScriptInterpreter(){#ifdef KJS_VERBOSE kdDebug(6070) << "ScriptInterpreter::~ScriptInterpreter " << this << " for part=" << m_frame << endl;#endif assert( interpreterList && interpreterList->contains( this ) ); interpreterList->remove( this ); if ( interpreterList->isEmpty() ) { delete interpreterList; interpreterList = 0; }}void ScriptInterpreter::forgetDOMObject( void* objectHandle ){ if( !interpreterList ) return; QPtrListIterator<ScriptInterpreter> it( *interpreterList ); while ( it.current() ) { (*it)->deleteDOMObject( objectHandle ); ++it; }}void ScriptInterpreter::mark(){ Interpreter::mark();#ifdef KJS_VERBOSE kdDebug(6070) << "ScriptInterpreter::mark " << this << " marking " << m_customizedDomObjects.count() << " DOM objects" << endl;#endif QPtrDictIterator<void> it( m_customizedDomObjects ); for( ; it.current(); ++it ) static_cast<DOMObject*>(it.currentKey())->mark();}KParts::ReadOnlyPart* ScriptInterpreter::part() const { return m_frame->m_part;}bool ScriptInterpreter::isWindowOpenAllowed() const{ if ( m_evt ) { int id = m_evt->handle()->id(); bool eventOk = ( // mouse events id == DOM::EventImpl::CLICK_EVENT || id == DOM::EventImpl::MOUSEUP_EVENT || id == DOM::EventImpl::MOUSEDOWN_EVENT || id == DOM::EventImpl::KHTML_ECMA_CLICK_EVENT || id == DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT || // keyboard events id == DOM::EventImpl::KEYDOWN_EVENT || id == DOM::EventImpl::KEYPRESS_EVENT || id == DOM::EventImpl::KEYUP_EVENT || // other accepted events id == DOM::EventImpl::SELECT_EVENT || id == DOM::EventImpl::CHANGE_EVENT || id == DOM::EventImpl::SUBMIT_EVENT ); kdDebug(6070) << "Window.open, smart policy: id=" << id << " eventOk=" << eventOk << endl; if (eventOk) return true; } else // no event { if ( m_inlineCode && !m_timerCallback ) { // This is the <a href="javascript:window.open('...')> case -> we let it through return true; kdDebug(6070) << "Window.open, smart policy, no event, inline code -> ok" << endl; } else // This is the <script>window.open(...)</script> case or a timer callback -> block it kdDebug(6070) << "Window.open, smart policy, no event, <script> tag -> refused" << endl; } return false;}UString::UString(const QString &d){ unsigned int len = d.length(); UChar *dat = new UChar[len]; memcpy(dat, d.unicode(), len * sizeof(UChar)); rep = UString::Rep::create(dat, len);}UString::UString(const DOM::DOMString &d){ if (d.isNull()) { // we do a conversion here as null DOMStrings shouldn't cross // the boundary to kjs. They should either be empty strings // or explicitly converted to KJS::Null via getString(). attach(&Rep::empty); return; } unsigned int len = d.length(); UChar *dat = new UChar[len]; memcpy(dat, d.unicode(), len * sizeof(UChar)); rep = UString::Rep::create(dat, len);}DOM::DOMString UString::string() const{ return DOM::DOMString((QChar*) data(), size());}QString UString::qstring() const{ return QString((QChar*) data(), size());}QConstString UString::qconststring() const{ return QConstString((QChar*) data(), size());}DOM::DOMString Identifier::string() const{ return DOM::DOMString((QChar*) data(), size());}QString Identifier::qstring() const{ return QString((QChar*) data(), size());}DOM::Node KJS::toNode(const Value& val){ Object obj = Object::dynamicCast(val); if (!obj.isValid() || !obj.inherits(&DOMNode::info)) return DOM::Node(); const DOMNode *dobj = static_cast<const DOMNode*>(obj.imp()); return dobj->toNode();}Value KJS::getString(DOM::DOMString s){ if (s.isNull()) return Null(); else return String(s);}QVariant KJS::ValueToVariant(ExecState* exec, const Value &val) { QVariant res; switch (val.type()) { case BooleanType: res = QVariant(val.toBoolean(exec), 0); break; case NumberType: res = QVariant(val.toNumber(exec)); break; case StringType: res = QVariant(val.toString(exec).qstring()); break; default: // everything else will be 'invalid' break; } return res;}class EmbedLiveConnect : public ObjectImp{ friend Value KJS::getLiveConnectValue(KParts::LiveConnectExtension *lc, const QString & name, const int type, const QString & value, int id); EmbedLiveConnect(KParts::LiveConnectExtension *lc, UString n, KParts::LiveConnectExtension::Type t, int id);public: ~EmbedLiveConnect(); virtual Value get(ExecState *, const Identifier & prop) const; virtual void put(ExecState * exec, const Identifier &prop, const Value & value, int=None); virtual Value call(ExecState * exec, Object &, const List &args); virtual bool implementsCall() const; virtual bool toBoolean(ExecState *) const; virtual Value toPrimitive(ExecState *exec, Type) const; virtual UString toString(ExecState *) const;private: EmbedLiveConnect(const EmbedLiveConnect &); QGuardedPtr<KParts::LiveConnectExtension> m_liveconnect; UString name; KParts::LiveConnectExtension::Type objtype; unsigned long objid;};Value KJS::getLiveConnectValue(KParts::LiveConnectExtension *lc, const QString & name, const int type, const QString & value, int id){ KParts::LiveConnectExtension::Type t=(KParts::LiveConnectExtension::Type)type; switch(t) { case KParts::LiveConnectExtension::TypeBool: { bool ok; int i = value.toInt(&ok); if (ok) return Boolean(i); return Boolean(!strcasecmp(value.latin1(), "true")); } case KParts::LiveConnectExtension::TypeObject: case KParts::LiveConnectExtension::TypeFunction: return Value(new EmbedLiveConnect(lc, name, t, id)); case KParts::LiveConnectExtension::TypeNumber: { bool ok; int i = value.toInt(&ok); if (ok) return Number(i); else return Number(value.toDouble(&ok)); } case KParts::LiveConnectExtension::TypeString: return String(value); case KParts::LiveConnectExtension::TypeVoid: default: return Undefined(); }}/* only with gcc > 3.4 KDE_NO_EXPORT */EmbedLiveConnect::EmbedLiveConnect(KParts::LiveConnectExtension *lc, UString n, KParts::LiveConnectExtension::Type t, int id) : m_liveconnect (lc), name(n), objtype(t), objid(id){}/* only with gcc > 3.4 KDE_NO_EXPORT */EmbedLiveConnect::~EmbedLiveConnect() { if (m_liveconnect) m_liveconnect->unregister(objid);}KDE_NO_EXPORTValue EmbedLiveConnect::get(ExecState *, const Identifier & prop) const{ if (m_liveconnect) { KParts::LiveConnectExtension::Type rettype; QString retval; unsigned long retobjid; if (m_liveconnect->get(objid, prop.qstring(), rettype, retobjid, retval)) return getLiveConnectValue(m_liveconnect, prop.qstring(), rettype, retval, retobjid); } return Undefined();}KDE_NO_EXPORTvoid EmbedLiveConnect::put(ExecState * exec, const Identifier &prop, const Value & value, int){ if (m_liveconnect) m_liveconnect->put(objid, prop.qstring(), value.toString(exec).qstring());}KDE_NO_EXPORTbool EmbedLiveConnect::implementsCall() const { return objtype == KParts::LiveConnectExtension::TypeFunction;}KDE_NO_EXPORTValue EmbedLiveConnect::call(ExecState *exec, Object&, const List &args){ if (m_liveconnect) { QStringList qargs; for (ListIterator i = args.begin(); i != args.end(); ++i) qargs.append((*i).toString(exec).qstring()); KParts::LiveConnectExtension::Type rtype; QString rval; unsigned long robjid; if (m_liveconnect->call(objid, name.qstring(), qargs, rtype, robjid, rval)) return getLiveConnectValue(m_liveconnect, name.qstring(), rtype, rval, robjid); } return Undefined();}KDE_NO_EXPORTbool EmbedLiveConnect::toBoolean(ExecState *) const { return true;}KDE_NO_EXPORTValue EmbedLiveConnect::toPrimitive(ExecState *exec, Type) const { return String(toString(exec));}KDE_NO_EXPORTUString EmbedLiveConnect::toString(ExecState *) const { QString str; const char *type = objtype == KParts::LiveConnectExtension::TypeFunction ? "Function" : "Object"; str.sprintf("[object %s ref=%d]", type, (int) objid); return UString(str);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -