/* * 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 "tdehtmlpart_p.h" #include #include #include 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, TQString(TQString("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, TQString(TQString("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(exec->dynamicInterpreter())->customizedDOMObject(this); ObjectImp::put(exec,propertyName,value,attr); } UString DOMObject::toString(ExecState *) const { return "[object " + className() + "]"; } Boolean DOMObject::hasInstance(ExecState *exec, const Value &value) { if (value.type() != ObjectType) return Boolean(false); Value prot = get(exec,prototypePropertyName); if (prot.type() != ObjectType && prot.type() != NullType) { Object err = Error::create(exec, TypeError, "Invalid prototype encountered " "in instanceof operation."); exec->setException(err); return Boolean(false); } Object v = Object(static_cast(value.imp())); while ((v = Object::dynamicCast(v.prototype())).imp()) { if (v.imp() == prot.imp()) return Boolean(true); } return Boolean(false); } Value DOMFunction::get(ExecState *exec, const Identifier &propertyName) const { try { return tryGet(exec, propertyName); } catch (DOM::DOMException e) { Object err = Error::create(exec, GeneralError, TQString(TQString("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, TQString(TQString("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, TQString(TQString("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, TQString(TQString("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, TQString(TQString("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 TQPtrList InterpreterList; static InterpreterList *interpreterList; ScriptInterpreter::ScriptInterpreter( const Object &global, tdehtml::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; TQPtrListIterator 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 TQPtrDictIterator it( m_customizedDomObjects ); for( ; it.current(); ++it ) static_cast(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::TDEHTML_ECMA_CLICK_EVENT || id == DOM::EventImpl::TDEHTML_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 ok" << endl; } else // This is the case or a timer callback -> block it kdDebug(6070) << "Window.open, smart policy, no event,