summaryrefslogtreecommitdiffstats
path: root/WebCore/bindings/js/JSDOMBinding.h
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/bindings/js/JSDOMBinding.h')
-rw-r--r--WebCore/bindings/js/JSDOMBinding.h95
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