⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kjs_binding.h

📁 khtml在gtk上的移植版本
💻 H
字号:
// -*- c-basic-offset: 2 -*-/* *  This file is part of the KDE libraries *  Copyright (C) 1999-2001 Harri Porten (porten@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 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 */#ifndef _KJS_BINDING_H_#define _KJS_BINDING_H_#include <kjs/interpreter.h>#include <dom/dom_node.h>#include <dom/dom_doc.h>#include <qvariant.h>#include <qptrdict.h>#include <kurl.h>#include <kjs/lookup.h>#include <kjs/protect.h>class KHTMLPart;namespace KJS {  /**   * Base class for all objects in this binding - get() and put() run   * tryGet() and tryPut() respectively, and catch exceptions if they   * occur.   */  class DOMObject : public ObjectImp {  public:    DOMObject(const Object &proto) : ObjectImp(proto) {}    DOMObject() : ObjectImp() {}    virtual Value get(ExecState *exec, const Identifier &propertyName) const;    virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const      { return ObjectImp::get(exec, propertyName); }    virtual void put(ExecState *exec, const Identifier &propertyName,                     const Value &value, int attr = None);    virtual void tryPut(ExecState *exec, const Identifier &propertyName,                        const Value& value, int attr = None)      { ObjectImp::put(exec,propertyName,value,attr); }    virtual UString toString(ExecState *exec) const;  };  /**   * Base class for all functions in this binding - get() and call() run   * tryGet() and tryCall() respectively, and catch exceptions if they   * occur.   */  class DOMFunction : public ObjectImp {  public:    DOMFunction() : ObjectImp( /* proto? */ ) {}    virtual Value get(ExecState *exec, const Identifier &propertyName) const;    virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const      { return ObjectImp::get(exec, propertyName); }    virtual bool implementsCall() const { return true; }    virtual Value call(ExecState *exec, Object &thisObj, const List &args);    virtual Value tryCall(ExecState *exec, Object &thisObj, const List&args)      { return ObjectImp::call(exec, thisObj, args); }    virtual bool toBoolean(ExecState *) const { return true; }    virtual Value toPrimitive(ExecState *exec, Type) const { return String(toString(exec)); }    virtual UString toString(ExecState *) const { return UString("[function]"); }  };  /**   * We inherit from Interpreter, to save a pointer to the HTML part   * that the interpreter runs for.   * The interpreter also stores the DOM object - >KJS::DOMObject cache.   */  class ScriptInterpreter : public Interpreter  {  public:    ScriptInterpreter( const Object &global, KHTMLPart* part );    virtual ~ScriptInterpreter();    static DOMObject* getDOMObject( void* objectHandle ) {      return domObjects()[objectHandle];    }    static void putDOMObject( void* objectHandle, DOMObject* obj ) {      domObjects().insert( objectHandle, obj );    }    static bool deleteDOMObject( void* objectHandle ) {      return domObjects().remove( objectHandle );    }    static DOMObject* getDOMObjectForDocument( DOM::DocumentImpl* documentHandle, void *objectHandle );    static void putDOMObjectForDocument( DOM::DocumentImpl* documentHandle, void *objectHandle, DOMObject *obj );    static bool deleteDOMObjectsForDocument( DOM::DocumentImpl* documentHandle );    /**     * Static method. Makes all interpreters forget about the object     */    static void forgetDOMObject( void* objectHandle );    static void forgetDOMObjectsForDocument( DOM::DocumentImpl* documentHandle );    static void updateDOMObjectDocument(void *objectHandle, DOM::DocumentImpl *oldDoc, DOM::DocumentImpl *newDoc);    KHTMLPart* part() const { return m_part; }    virtual int rtti() { return 1; }    /**     * Set the event that is triggering the execution of a script, if any     */    void setCurrentEvent( DOM::Event *evt ) { m_evt = evt; }    void setInlineCode( bool inlineCode ) { m_inlineCode = inlineCode; }    void setProcessingTimerCallback( bool timerCallback ) { m_timerCallback = timerCallback; }    /**     * "Smart" window.open policy     */    bool wasRunByUserGesture() const;    virtual void mark();        DOM::Event *getCurrentEvent() const { return m_evt; }      private:    KHTMLPart* m_part;    static QPtrDict<DOMObject> &domObjects();    static QPtrDict<QPtrDict<DOMObject> > &domObjectsPerDocument();    DOM::Event *m_evt;    bool m_inlineCode;    bool m_timerCallback;  };  /**   * Retrieve from cache, or create, a KJS object around a DOM object   */  template<class DOMObj, class KJSDOMObj>  inline Value cacheDOMObject(ExecState *exec, DOMObj domObj)  {    DOMObject *ret;    if (domObj.isNull())      return Null();    ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());    if ((ret = interp->getDOMObject(domObj.handle())))      return Value(ret);    else {      ret = new KJSDOMObj(exec, domObj);      interp->putDOMObject(domObj.handle(),ret);      return Value(ret);    }  }  /**   * Convert an object to a Node. Returns a null Node if not possible.   */  DOM::Node toNode(const Value&);  /**   *  Get a String object, or Null() if s is null   */  Value getStringOrNull(DOM::DOMString s);  /**   * Convery a KJS value into a QVariant   */  QVariant ValueToVariant(ExecState* exec, const Value& val);  /**   * We need a modified version of lookupGet because   * we call tryGet instead of get, in DOMObjects.   */  template <class FuncImp, class ThisImp, class ParentImp>  inline Value DOMObjectLookupGet(ExecState *exec, const Identifier &propertyName,                                  const HashTable* table, const ThisImp* thisObj)  {    const HashEntry* entry = Lookup::findEntry(table, propertyName);    if (!entry) // not found, forward to parent      return thisObj->ParentImp::tryGet(exec, propertyName);    if (entry->attr & Function)      return lookupOrCreateFunction<FuncImp>(exec, propertyName, thisObj, entry->value, entry->params, entry->attr);    return thisObj->getValueProperty(exec, entry->value);  }  /**   * Simplified version of DOMObjectLookupGet in case there are no   * functions, only "values".   */  template <class ThisImp, class ParentImp>  inline Value DOMObjectLookupGetValue(ExecState *exec, const Identifier &propertyName,                                       const HashTable* table, const ThisImp* thisObj)  {    const HashEntry* entry = Lookup::findEntry(table, propertyName);    if (!entry) // not found, forward to parent      return thisObj->ParentImp::tryGet(exec, propertyName);    if (entry->attr & Function)      fprintf(stderr, "Function bit set! Shouldn't happen in lookupValue!\n" );    return thisObj->getValueProperty(exec, entry->value);  }  /**   * We need a modified version of lookupPut because   * we call tryPut instead of put, in DOMObjects.   */  template <class ThisImp, class ParentImp>  inline void DOMObjectLookupPut(ExecState *exec, const Identifier &propertyName,                                 const Value& value, int attr,                                 const HashTable* table, ThisImp* thisObj)  {    const HashEntry* entry = Lookup::findEntry(table, propertyName);    if (!entry) // not found: forward to parent      thisObj->ParentImp::tryPut(exec, propertyName, value, attr);    else if (entry->attr & Function) // function: put as override property      thisObj->ObjectImp::put(exec, propertyName, value, attr);    else if (entry->attr & ReadOnly) // readonly! Can't put!#ifdef KJS_VERBOSE      fprintf(stderr,"Attempt to change value of readonly property '%s'\n",propertyName.ascii());#else    ; // do nothing#endif    else      thisObj->putValue(exec, entry->value, value, attr);  }  /**   * This template method retrieves or create an object that is unique   * (for a given interpreter) The first time this is called (for a given   * property name), the Object will be constructed, and set as a property   * of the interpreter's global object. Later calls will simply retrieve   * that cached object. Note that the object constructor must take 1 argument, exec.   */  template <class ClassCtor>  inline Object cacheGlobalObject(ExecState *exec, const Identifier &propertyName)  {    ValueImp *obj = static_cast<ObjectImp*>(exec->lexicalInterpreter()->globalObject().imp())->getDirect(propertyName);    if (obj)      return Object::dynamicCast(Value(obj));    else    {      Object newObject(new ClassCtor(exec));      exec->lexicalInterpreter()->globalObject().put(exec, propertyName, newObject, Internal);      return newObject;    }  }  /**   * Helpers to define prototype objects (each of which simply implements   * the functions for a type of objects).   * Sorry for this not being very readable, but it actually saves much copy-n-paste.   * ParentProto is not our base class, it's the object we use as fallback.   * The reason for this is that there should only be ONE DOMNode.hasAttributes (e.g.),   * not one in each derived class. So we link the (unique) prototypes between them.   *   * Using those macros is very simple: define the hashtable (e.g. "DOMNodeProtoTable"), then   * DEFINE_PROTOTYPE("DOMNode",DOMNodeProto)   * IMPLEMENT_PROTOFUNC(DOMNodeProtoFunc)   * IMPLEMENT_PROTOTYPE(DOMNodeProto,DOMNodeProtoFunc)   * and use DOMNodeProto::self(exec) as prototype in the DOMNode constructor.   * If the prototype has a "parent prototype", e.g. DOMElementProto falls back on DOMNodeProto,   * then the last line will use IMPLEMENT_PROTOTYPE_WITH_PARENT, with DOMNodeProto as last argument.   */#define DEFINE_PROTOTYPE(ClassName,ClassProto) \  namespace KJS { \  class ClassProto : public ObjectImp { \    friend Object cacheGlobalObject<ClassProto>(ExecState *exec, const Identifier &propertyName); \  public: \    static Object self(ExecState *exec) \    { \      return cacheGlobalObject<ClassProto>( exec, "[[" ClassName ".prototype]]" ); \    } \  protected: \    ClassProto( ExecState *exec ) \      : ObjectImp( exec->lexicalInterpreter()->builtinObjectPrototype() ) {} \    \  public: \    virtual const ClassInfo *classInfo() const { return &info; } \    static const ClassInfo info; \    Value get(ExecState *exec, const Identifier &propertyName) const; \    bool hasProperty(ExecState *exec, const Identifier &propertyName) const; \  }; \  const ClassInfo ClassProto::info = { ClassName, 0, &ClassProto##Table, 0 }; \  };#define IMPLEMENT_PROTOTYPE(ClassProto,ClassFunc) \    Value KJS::ClassProto::get(ExecState *exec, const Identifier &propertyName) const \    { \      /*fprintf( stderr, "%sProto::get(%s) [in macro, no parent]\n", info.className, propertyName.ascii());*/ \      return lookupGetFunction<ClassFunc,ObjectImp>(exec, propertyName, &ClassProto##Table, this ); \    } \    bool KJS::ClassProto::hasProperty(ExecState *exec, const Identifier &propertyName) const \    { /*stupid but we need this to have a common macro for the declaration*/ \      return ObjectImp::hasProperty(exec, propertyName); \    }#define IMPLEMENT_PROTOTYPE_WITH_PARENT(ClassProto,ClassFunc,ParentProto)  \    Value KJS::ClassProto::get(ExecState *exec, const Identifier &propertyName) const \    { \      /*fprintf( stderr, "%sProto::get(%s) [in macro]\n", info.className, propertyName.ascii());*/ \      Value val = lookupGetFunction<ClassFunc,ObjectImp>(exec, propertyName, &ClassProto##Table, this ); \      if ( val.type() != UndefinedType ) return val; \      /* Not found -> forward request to "parent" prototype */ \      return ParentProto::self(exec).get( exec, propertyName ); \    } \    bool KJS::ClassProto::hasProperty(ExecState *exec, const Identifier &propertyName) const \    { \      if (ObjectImp::hasProperty(exec, propertyName)) \        return true; \      return ParentProto::self(exec).hasProperty(exec, propertyName); \    }#define IMPLEMENT_PROTOFUNC(ClassFunc) \  namespace KJS { \  class ClassFunc : public DOMFunction { \  public: \    ClassFunc(ExecState *exec, int i, int len) \       : DOMFunction( /*proto? */ ), id(i) { \       Value protect(this); \       put(exec,lengthPropertyName,Number(len),DontDelete|ReadOnly|DontEnum); \    } \    /** You need to implement that one */ \    virtual Value tryCall(ExecState *exec, Object &thisObj, const List &args); \  private: \    int id; \  }; \  };}; // namespace#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -