diff options
Diffstat (limited to 'WebCore/bindings/js/JSDOMBinding.h')
| -rw-r--r-- | WebCore/bindings/js/JSDOMBinding.h | 154 |
1 files changed, 128 insertions, 26 deletions
diff --git a/WebCore/bindings/js/JSDOMBinding.h b/WebCore/bindings/js/JSDOMBinding.h index 64cfc3a..3982dad 100644 --- a/WebCore/bindings/js/JSDOMBinding.h +++ b/WebCore/bindings/js/JSDOMBinding.h @@ -26,21 +26,23 @@ #include "Document.h" // For DOMConstructorWithDocument #include <runtime/Completion.h> #include <runtime/Lookup.h> -#include <runtime/JSFunction.h> #include <wtf/Noncopyable.h> namespace JSC { class JSGlobalData; + class DebuggerCallFrame; } namespace WebCore { class Document; class Frame; + class JSNode; class KURL; class Node; class String; - class JSNode; + class ScriptController; + class ScriptCachedFrameData; typedef int ExceptionCode; @@ -51,17 +53,19 @@ namespace WebCore { // Base class for all objects in this binding except Window. class DOMObject : public JSC::JSObject { protected: - explicit DOMObject(PassRefPtr<JSC::Structure> structure) + explicit DOMObject(NonNullPassRefPtr<JSC::Structure> structure) : JSObject(structure) { } + virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&, bool); + #ifndef NDEBUG virtual ~DOMObject(); #endif }; - // FIXME: This class should colapse into DOMObject once all DOMObjects are + // FIXME: This class should collapse into DOMObject once all DOMObjects are // updated to store a globalObject pointer. class DOMObjectWithGlobalPointer : public DOMObject { public: @@ -73,8 +77,15 @@ namespace WebCore { return m_globalObject->scriptExecutionContext(); } + static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) + { + return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags)); + } + protected: - DOMObjectWithGlobalPointer(PassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject) + static const unsigned StructureFlags = JSC::OverridesMarkChildren | DOMObject::StructureFlags; + + DOMObjectWithGlobalPointer(NonNullPassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject) : DOMObject(structure) , m_globalObject(globalObject) { @@ -83,7 +94,7 @@ namespace WebCore { // needing to reach through the frame to get to the Document*. See bug 27640. // ASSERT(globalObject->scriptExecutionContext()); } - virtual ~DOMObjectWithGlobalPointer() {} + virtual ~DOMObjectWithGlobalPointer() { } void markChildren(JSC::MarkStack& markStack) { @@ -100,11 +111,12 @@ namespace WebCore { public: static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, JSC::HasStandardGetOwnPropertySlot | JSC::ImplementsHasInstance)); + return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags)); } protected: - DOMConstructorObject(PassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject) + static const unsigned StructureFlags = JSC::ImplementsHasInstance | JSC::OverridesMarkChildren | DOMObjectWithGlobalPointer::StructureFlags; + DOMConstructorObject(NonNullPassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject) : DOMObjectWithGlobalPointer(structure, globalObject) { } @@ -120,30 +132,117 @@ namespace WebCore { } protected: - DOMConstructorWithDocument(PassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject) + DOMConstructorWithDocument(NonNullPassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject) : DOMConstructorObject(structure, globalObject) { ASSERT(globalObject->scriptExecutionContext()->isDocument()); } }; - DOMObject* getCachedDOMObjectWrapper(JSC::JSGlobalData&, void* objectHandle); - void cacheDOMObjectWrapper(JSC::JSGlobalData&, void* objectHandle, DOMObject* wrapper); - void forgetDOMObject(JSC::JSGlobalData&, void* objectHandle); + typedef HashMap<void*, DOMObject*> DOMObjectWrapperMap; + + class DOMWrapperWorld : public RefCounted<DOMWrapperWorld> { + public: + DOMWrapperWorld(JSC::JSGlobalData*); + ~DOMWrapperWorld(); + + void rememberDocument(Document* document) { documentsWithWrappers.add(document); } + void forgetDocument(Document* document) { documentsWithWrappers.remove(document); } + + // FIXME: can we make this private? + DOMObjectWrapperMap m_wrappers; + + private: + JSC::JSGlobalData* m_globalData; + HashSet<Document*> documentsWithWrappers; + }; + + // Map from static HashTable instances to per-GlobalData ones. + class DOMObjectHashTableMap { + public: + static DOMObjectHashTableMap& mapFor(JSC::JSGlobalData&); + + ~DOMObjectHashTableMap() + { + HashMap<const JSC::HashTable*, JSC::HashTable>::iterator mapEnd = m_map.end(); + for (HashMap<const JSC::HashTable*, JSC::HashTable>::iterator iter = m_map.begin(); iter != m_map.end(); ++iter) + iter->second.deleteTable(); + } + + const JSC::HashTable* get(const JSC::HashTable* staticTable) + { + HashMap<const JSC::HashTable*, JSC::HashTable>::iterator iter = m_map.find(staticTable); + if (iter != m_map.end()) + return &iter->second; + return &m_map.set(staticTable, JSC::HashTable(*staticTable)).first->second; + } + + private: + HashMap<const JSC::HashTable*, JSC::HashTable> m_map; + }; + + class WebCoreJSClientData : public JSC::JSGlobalData::ClientData { + friend class JSGlobalDataWorldIterator; + + public: + WebCoreJSClientData(JSC::JSGlobalData* globalData) + : m_normalWorld(globalData) + { + m_worldSet.add(&m_normalWorld); + } + // FIXME: add a destructor to assert m_worldSet only contains m_normalWorld? + + DOMWrapperWorld* normalWorld() { return &m_normalWorld; } + + void getAllWorlds(Vector<DOMWrapperWorld*>& worlds) + { + copyToVector(m_worldSet, worlds); + } - JSNode* getCachedDOMNodeWrapper(Document*, Node*); - void cacheDOMNodeWrapper(Document*, Node*, JSNode* wrapper); - void forgetDOMNode(Document*, Node*); + void rememberWorld(DOMWrapperWorld* world) + { + ASSERT(!m_worldSet.contains(world)); + m_worldSet.add(world); + } + void forgetWorld(DOMWrapperWorld* world) + { + ASSERT(m_worldSet.contains(world)); + m_worldSet.remove(world); + } + + DOMObjectHashTableMap hashTableMap; + private: + HashSet<DOMWrapperWorld*> m_worldSet; + DOMWrapperWorld m_normalWorld; + }; + + bool hasCachedDOMObjectWrapper(JSC::JSGlobalData*, void* objectHandle); + DOMObject* getCachedDOMObjectWrapper(JSC::ExecState*, void* objectHandle); + void cacheDOMObjectWrapper(JSC::ExecState*, void* objectHandle, DOMObject* wrapper); + void forgetDOMNode(DOMObject* wrapper, Node* node, Document* document); + void forgetDOMObject(DOMObject* wrapper, void* objectHandle); + + bool hasCachedDOMNodeWrapper(Document*, Node*); + JSNode* getCachedDOMNodeWrapper(JSC::ExecState*, Document*, Node*); + void cacheDOMNodeWrapper(JSC::ExecState*, Document*, Node*, JSNode* wrapper); void forgetAllDOMNodesForDocument(Document*); + void forgetWorldOfDOMNodesForDocument(Document*, DOMWrapperWorld*); void updateDOMNodeDocument(Node*, Document* oldDocument, Document* newDocument); void markDOMNodesForDocument(JSC::MarkStack&, Document*); void markActiveObjectsForContext(JSC::MarkStack&, JSC::JSGlobalData&, ScriptExecutionContext*); void markDOMObjectWrapper(JSC::MarkStack&, JSC::JSGlobalData& globalData, void* object); + void markDOMNodeWrapper(JSC::MarkStack& markStack, Document* document, Node* node); JSC::Structure* getCachedDOMStructure(JSDOMGlobalObject*, const JSC::ClassInfo*); - JSC::Structure* cacheDOMStructure(JSDOMGlobalObject*, PassRefPtr<JSC::Structure>, const JSC::ClassInfo*); + JSC::Structure* cacheDOMStructure(JSDOMGlobalObject*, NonNullPassRefPtr<JSC::Structure>, const JSC::ClassInfo*); JSC::Structure* getCachedDOMStructure(JSC::ExecState*, const JSC::ClassInfo*); - JSC::Structure* cacheDOMStructure(JSC::ExecState*, PassRefPtr<JSC::Structure>, const JSC::ClassInfo*); + JSC::Structure* cacheDOMStructure(JSC::ExecState*, NonNullPassRefPtr<JSC::Structure>, const JSC::ClassInfo*); + + DOMWrapperWorld* currentWorld(JSC::ExecState*); + DOMWrapperWorld* normalWorld(JSC::JSGlobalData&); + DOMWrapperWorld* mainThreadNormalWorld(); + inline DOMWrapperWorld* debuggerWorld() { return mainThreadNormalWorld(); } + inline DOMWrapperWorld* pluginWorld() { return mainThreadNormalWorld(); } JSC::JSObject* getCachedDOMConstructor(JSC::ExecState*, const JSC::ClassInfo*); void cacheDOMConstructor(JSC::ExecState*, const JSC::ClassInfo*, JSC::JSObject* constructor); @@ -175,17 +274,17 @@ namespace WebCore { template<class WrapperClass, class DOMClass> inline DOMObject* createDOMObjectWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* object) { ASSERT(object); - ASSERT(!getCachedDOMObjectWrapper(exec->globalData(), object)); + ASSERT(!getCachedDOMObjectWrapper(exec, object)); // FIXME: new (exec) could use a different globalData than the globalData this wrapper is cached on. WrapperClass* wrapper = new (exec) WrapperClass(getDOMStructure<WrapperClass>(exec, globalObject), globalObject, object); - cacheDOMObjectWrapper(exec->globalData(), object, wrapper); + cacheDOMObjectWrapper(exec, object, wrapper); return wrapper; } template<class WrapperClass, class DOMClass> inline JSC::JSValue getDOMObjectWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* object) { if (!object) return JSC::jsNull(); - if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec->globalData(), object)) + if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec, object)) return wrapper; return createDOMObjectWrapper<WrapperClass>(exec, globalObject, object); } @@ -195,16 +294,16 @@ namespace WebCore { template<class WrapperClass, class DOMClass> inline DOMObject* createDOMObjectWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* object, SVGElement* context) { ASSERT(object); - ASSERT(!getCachedDOMObjectWrapper(exec->globalData(), object)); + ASSERT(!getCachedDOMObjectWrapper(exec, object)); WrapperClass* wrapper = new (exec) WrapperClass(getDOMStructure<WrapperClass>(exec, globalObject), globalObject, object, context); - cacheDOMObjectWrapper(exec->globalData(), object, wrapper); + cacheDOMObjectWrapper(exec, object, wrapper); return wrapper; } template<class WrapperClass, class DOMClass> inline JSC::JSValue getDOMObjectWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* object, SVGElement* context) { if (!object) return JSC::jsNull(); - if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec->globalData(), object)) + if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec, object)) return wrapper; return createDOMObjectWrapper<WrapperClass>(exec, globalObject, object, context); } @@ -214,18 +313,18 @@ namespace WebCore { template<class WrapperClass, class DOMClass> inline JSNode* createDOMNodeWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* node) { ASSERT(node); - ASSERT(!getCachedDOMNodeWrapper(node->document(), node)); + ASSERT(!getCachedDOMNodeWrapper(exec, node->document(), node)); WrapperClass* wrapper = new (exec) WrapperClass(getDOMStructure<WrapperClass>(exec, globalObject), globalObject, node); // FIXME: The entire function can be removed, once we fix caching. // This function is a one-off hack to make Nodes cache in the right global object. - cacheDOMNodeWrapper(node->document(), node, wrapper); + cacheDOMNodeWrapper(exec, node->document(), node, wrapper); return wrapper; } template<class WrapperClass, class DOMClass> inline JSC::JSValue getDOMNodeWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* node) { if (!node) return JSC::jsNull(); - if (JSNode* wrapper = getCachedDOMNodeWrapper(node->document(), node)) + if (JSNode* wrapper = getCachedDOMNodeWrapper(exec, node->document(), node)) return wrapper; return createDOMNodeWrapper<WrapperClass>(exec, globalObject, node); } @@ -277,6 +376,9 @@ namespace WebCore { return toJS(exec, globalObject, ptr.get()); } + // Validates that the passed object is a sequence type per section 4.1.13 of the WebIDL spec. + JSC::JSObject* toJSSequence(JSC::ExecState*, JSC::JSValue, unsigned&); + bool checkNodeSecurity(JSC::ExecState*, Node*); // Helpers for Window, History, and Location classes to implement cross-domain policy. |
