diff options
Diffstat (limited to 'WebCore/bindings/js/JSDOMBinding.h')
-rw-r--r-- | WebCore/bindings/js/JSDOMBinding.h | 95 |
1 files changed, 66 insertions, 29 deletions
diff --git a/WebCore/bindings/js/JSDOMBinding.h b/WebCore/bindings/js/JSDOMBinding.h index 3982dad..5456c75 100644 --- a/WebCore/bindings/js/JSDOMBinding.h +++ b/WebCore/bindings/js/JSDOMBinding.h @@ -23,9 +23,11 @@ #define JSDOMBinding_h #include "JSDOMGlobalObject.h" -#include "Document.h" // For DOMConstructorWithDocument +#include "JSSVGContextCache.h" +#include "Document.h" #include <runtime/Completion.h> #include <runtime/Lookup.h> +#include <runtime/WeakGCMap.h> #include <wtf/Noncopyable.h> namespace JSC { @@ -69,41 +71,33 @@ namespace WebCore { // updated to store a globalObject pointer. class DOMObjectWithGlobalPointer : public DOMObject { public: - JSDOMGlobalObject* globalObject() const { return m_globalObject; } + JSDOMGlobalObject* globalObject() const { return static_cast<JSDOMGlobalObject*>(getAnonymousValue(GlobalObjectSlot).asCell()); } ScriptExecutionContext* scriptExecutionContext() const { // FIXME: Should never be 0, but can be due to bug 27640. - return m_globalObject->scriptExecutionContext(); + return globalObject()->scriptExecutionContext(); } static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags)); + return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount); } protected: - static const unsigned StructureFlags = JSC::OverridesMarkChildren | DOMObject::StructureFlags; + static const unsigned AnonymousSlotCount = 1 + DOMObject::AnonymousSlotCount; + static const unsigned GlobalObjectSlot = AnonymousSlotCount - 1; DOMObjectWithGlobalPointer(NonNullPassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject) : DOMObject(structure) - , m_globalObject(globalObject) { // FIXME: This ASSERT is valid, but fires in fast/dom/gc-6.html when trying to create // new JavaScript objects on detached windows due to DOMWindow::document() // needing to reach through the frame to get to the Document*. See bug 27640. // ASSERT(globalObject->scriptExecutionContext()); + putAnonymousValue(GlobalObjectSlot, globalObject); } virtual ~DOMObjectWithGlobalPointer() { } - - void markChildren(JSC::MarkStack& markStack) - { - DOMObject::markChildren(markStack); - markStack.append(m_globalObject); - } - - private: - JSDOMGlobalObject* m_globalObject; }; // Base class for all constructor objects in the JSC bindings. @@ -111,7 +105,7 @@ namespace WebCore { public: static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags)); + return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount); } protected: @@ -139,11 +133,12 @@ namespace WebCore { } }; - typedef HashMap<void*, DOMObject*> DOMObjectWrapperMap; + typedef JSC::WeakGCMap<void*, DOMObject*> DOMObjectWrapperMap; + typedef JSC::WeakGCMap<StringImpl*, JSC::JSString*> JSStringCache; class DOMWrapperWorld : public RefCounted<DOMWrapperWorld> { public: - DOMWrapperWorld(JSC::JSGlobalData*); + DOMWrapperWorld(JSC::JSGlobalData*, bool isNormal); ~DOMWrapperWorld(); void rememberDocument(Document* document) { documentsWithWrappers.add(document); } @@ -151,10 +146,14 @@ namespace WebCore { // FIXME: can we make this private? DOMObjectWrapperMap m_wrappers; + JSStringCache m_stringCache; + + bool isNormal() const { return m_isNormal; } private: JSC::JSGlobalData* m_globalData; HashSet<Document*> documentsWithWrappers; + bool m_isNormal; }; // Map from static HashTable instances to per-GlobalData ones. @@ -181,12 +180,12 @@ namespace WebCore { HashMap<const JSC::HashTable*, JSC::HashTable> m_map; }; - class WebCoreJSClientData : public JSC::JSGlobalData::ClientData { + class WebCoreJSClientData : public JSC::JSGlobalData::ClientData, public Noncopyable { friend class JSGlobalDataWorldIterator; public: WebCoreJSClientData(JSC::JSGlobalData* globalData) - : m_normalWorld(globalData) + : m_normalWorld(globalData, true) { m_worldSet.add(&m_normalWorld); } @@ -216,22 +215,24 @@ namespace WebCore { DOMWrapperWorld m_normalWorld; }; - bool hasCachedDOMObjectWrapper(JSC::JSGlobalData*, void* objectHandle); DOMObject* getCachedDOMObjectWrapper(JSC::ExecState*, void* objectHandle); + bool hasCachedDOMObjectWrapper(JSC::JSGlobalData*, void* objectHandle); void cacheDOMObjectWrapper(JSC::ExecState*, void* objectHandle, DOMObject* wrapper); - void forgetDOMNode(DOMObject* wrapper, Node* node, Document* document); + void forgetDOMNode(JSNode* 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); + bool hasCachedDOMObjectWrapperUnchecked(JSC::JSGlobalData*, void* objectHandle); + bool hasCachedDOMNodeWrapperUnchecked(Document*, Node*); JSC::Structure* getCachedDOMStructure(JSDOMGlobalObject*, const JSC::ClassInfo*); JSC::Structure* cacheDOMStructure(JSDOMGlobalObject*, NonNullPassRefPtr<JSC::Structure>, const JSC::ClassInfo*); @@ -293,19 +294,21 @@ namespace WebCore { #define CREATE_SVG_OBJECT_WRAPPER(exec, globalObject, className, object, context) createDOMObjectWrapper<JS##className>(exec, globalObject, static_cast<className*>(object), context) template<class WrapperClass, class DOMClass> inline DOMObject* createDOMObjectWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* object, SVGElement* context) { - ASSERT(object); - ASSERT(!getCachedDOMObjectWrapper(exec, object)); - WrapperClass* wrapper = new (exec) WrapperClass(getDOMStructure<WrapperClass>(exec, globalObject), globalObject, object, context); - cacheDOMObjectWrapper(exec, object, wrapper); + DOMObject* wrapper = createDOMObjectWrapper<WrapperClass, DOMClass>(exec, globalObject, object); + ASSERT(wrapper); + if (context) + JSSVGContextCache::addWrapper(wrapper, context); 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, object)) + if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec, object)) { + ASSERT(JSSVGContextCache::svgContextForDOMObject(wrapper) == context); return wrapper; - return createDOMObjectWrapper<WrapperClass>(exec, globalObject, object, context); + } + return createDOMObjectWrapper<WrapperClass, DOMClass>(exec, globalObject, object, context); } #endif @@ -337,6 +340,14 @@ namespace WebCore { // Convert a DOM implementation exception code into a JavaScript exception in the execution state. void setDOMException(JSC::ExecState*, ExceptionCode); + JSC::JSValue jsString(JSC::ExecState*, const String&); // empty if the string is null + JSC::JSValue jsStringSlowCase(JSC::ExecState*, JSStringCache&, StringImpl*); + JSC::JSValue jsString(JSC::ExecState*, const KURL&); // empty if the URL is null + inline JSC::JSValue jsString(JSC::ExecState* exec, const AtomicString& s) + { + return jsString(exec, s.string()); + } + JSC::JSValue jsStringOrNull(JSC::ExecState*, const String&); // null if the string is null JSC::JSValue jsStringOrNull(JSC::ExecState*, const KURL&); // null if the URL is null @@ -353,6 +364,11 @@ namespace WebCore { JSC::UString valueToStringWithNullCheck(JSC::ExecState*, JSC::JSValue); // null if the value is null JSC::UString valueToStringWithUndefinedOrNullCheck(JSC::ExecState*, JSC::JSValue); // null if the value is null or undefined + // Returns a Date instance for the specified value, or null if the value is NaN or infinity. + JSC::JSValue jsDateOrNull(JSC::ExecState*, double); + // NaN if the value can't be converted to a date. + double valueToDate(JSC::ExecState*, JSC::JSValue); + // FIXME: These are a stop-gap until all toJS calls can be converted to pass a globalObject template <typename T> inline JSC::JSValue toJS(JSC::ExecState* exec, T* ptr) @@ -395,6 +411,27 @@ namespace WebCore { bool processingUserGesture(JSC::ExecState*); KURL completeURL(JSC::ExecState*, const String& relativeURL); + inline DOMWrapperWorld* currentWorld(JSC::ExecState* exec) + { + return static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->world(); + } + + inline JSC::JSValue jsString(JSC::ExecState* exec, const String& s) + { + StringImpl* stringImpl = s.impl(); + if (!stringImpl || !stringImpl->length()) + return jsEmptyString(exec); + + if (stringImpl->length() == 1 && stringImpl->characters()[0] <= 0xFF) + return jsString(exec, stringImpl->ustring()); + + JSStringCache& stringCache = currentWorld(exec)->m_stringCache; + if (JSC::JSString* wrapper = stringCache.get(stringImpl)) + return wrapper; + + return jsStringSlowCase(exec, stringCache, stringImpl); + } + } // namespace WebCore #endif // JSDOMBinding_h |