// -*- c-basic-offset: 2 -*- /* * This file is part of the KDE libraries * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) * Copyright (C) 2004 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "kjs_binding.h" #include "kjs_dom.h" #include "kjs_window.h" #include // for InterpreterImp #include #include "dom/dom_exception.h" #include "dom/dom2_range.h" #include "xml/dom2_eventsimpl.h" #include using DOM::DOMString; 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()); err.put(exec, "code", Number(e.code)); 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()); err.put(exec, "code", Number(e.code)); exec->setException(err); } catch (...) { kdError(6070) << "Unknown exception in DOMObject::put()" << endl; } } UString DOMObject::toString(ExecState *) const { return "[object " + className() + "]"; } Value DOMFunction::get(ExecState *exec, const Identifier &propertyName) const { Value result; try { result = tryGet(exec, propertyName); } catch (DOM::DOMException e) { result = Undefined(); Object err = Error::create(exec, GeneralError, QString("DOM exception %1").arg(e.code).local8Bit()); err.put(exec, "code", Number(e.code)); exec->setException(err); } catch (...) { kdError(6070) << "Unknown exception in DOMFunction::get()" << endl; result = String("Unknown exception"); } return result; } Value DOMFunction::call(ExecState *exec, Object &thisObj, const List &args) { Value val; try { val = tryCall(exec, thisObj, args); } // pity there's no way to distinguish between these in JS code 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); } 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); } 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); } 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); } catch (...) { kdError(6070) << "Unknown exception in DOMFunction::call()" << endl; Object err = Error::create(exec, GeneralError, "Unknown exception"); exec->setException(err); } return val; } static QPtrDict * staticDomObjects = 0; QPtrDict< QPtrDict > * staticDOMNodesPerDocument = 0; QPtrDict & ScriptInterpreter::domObjects() { if (!staticDomObjects) { staticDomObjects = new QPtrDict(1021); } return *staticDomObjects; } QPtrDict< QPtrDict > & ScriptInterpreter::domNodesPerDocument() { if (!staticDOMNodesPerDocument) { staticDOMNodesPerDocument = new QPtrDict >(); staticDOMNodesPerDocument->setAutoDelete(true); } return *staticDOMNodesPerDocument; } ScriptInterpreter::ScriptInterpreter( const Object &global, KHTMLPart* part ) : Interpreter( global ), m_part( part ), m_evt( 0L ), m_inlineCode(false), m_timerCallback(false) { #ifdef KJS_VERBOSE kdDebug(6070) << "ScriptInterpreter::ScriptInterpreter " << this << " for part=" << m_part << endl; #endif } ScriptInterpreter::~ScriptInterpreter() { #ifdef KJS_VERBOSE kdDebug(6070) << "ScriptInterpreter::~ScriptInterpreter " << this << " for part=" << m_part << endl; #endif } void ScriptInterpreter::forgetDOMObject( void* objectHandle ) { deleteDOMObject( objectHandle ); } DOMNode *ScriptInterpreter::getDOMNodeForDocument(DOM::DocumentImpl *document, DOM::NodeImpl *node) { QPtrDict *documentDict = (QPtrDict *)domNodesPerDocument()[document]; if (documentDict) return (*documentDict)[node]; return NULL; } void ScriptInterpreter::forgetDOMNodeForDocument(DOM::DocumentImpl *document, DOM::NodeImpl *node) { QPtrDict *documentDict = domNodesPerDocument()[document]; if (documentDict) documentDict->remove(node); } void ScriptInterpreter::putDOMNodeForDocument(DOM::DocumentImpl *document, DOM::NodeImpl *nodeHandle, DOMNode *nodeWrapper) { QPtrDict *documentDict = domNodesPerDocument()[document]; if (!documentDict) { documentDict = new QPtrDict(); domNodesPerDocument().insert(document, documentDict); } documentDict->insert(nodeHandle, nodeWrapper); } void ScriptInterpreter::forgetAllDOMNodesForDocument(DOM::DocumentImpl *document) { domNodesPerDocument().remove(document); } void ScriptInterpreter::mark() { QPtrDictIterator > dictIterator(domNodesPerDocument()); QPtrDict *nodeDict; while ((nodeDict = dictIterator.current())) { QPtrDictIterator nodeIterator(*nodeDict); DOMNode *node; while ((node = nodeIterator.current())) { // don't mark wrappers for nodes that are no longer in the // document - they should not be saved if the node is not // otherwise reachable from JS. DOM::NodeImpl *n = node->toNode().handle(); if (n && n->inDocument() && !node->marked()) node->mark(); ++nodeIterator; } ++dictIterator; } } void ScriptInterpreter::updateDOMNodeDocument(DOM::NodeImpl *node, DOM::DocumentImpl *oldDoc, DOM::DocumentImpl *newDoc) { DOMNode *cachedObject = getDOMNodeForDocument(oldDoc, node); if (cachedObject) { putDOMNodeForDocument(newDoc, node, cachedObject); forgetDOMNodeForDocument(oldDoc, node); } } bool ScriptInterpreter::wasRunByUserGesture() const { if ( m_evt ) { int id = m_evt->handle()->id(); bool eventOk = ( // mouse events id == DOM::EventImpl::CLICK_EVENT || id == DOM::EventImpl::MOUSEDOWN_EVENT || id == DOM::EventImpl::MOUSEUP_EVENT || id == DOM::EventImpl::KHTML_DBLCLICK_EVENT || id == DOM::EventImpl::KHTML_CLICK_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::FOCUS_EVENT || id == DOM::EventImpl::BLUR_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,