diff options
Diffstat (limited to 'WebCore/bindings/js/JSDOMBinding.cpp')
| -rw-r--r-- | WebCore/bindings/js/JSDOMBinding.cpp | 416 |
1 files changed, 319 insertions, 97 deletions
diff --git a/WebCore/bindings/js/JSDOMBinding.cpp b/WebCore/bindings/js/JSDOMBinding.cpp index 566b986..f12c779 100644 --- a/WebCore/bindings/js/JSDOMBinding.cpp +++ b/WebCore/bindings/js/JSDOMBinding.cpp @@ -21,27 +21,36 @@ #include "config.h" #include "JSDOMBinding.h" +#include "debugger/DebuggerCallFrame.h" + #include "ActiveDOMObject.h" #include "DOMCoreException.h" #include "Document.h" #include "EventException.h" +#include "ExceptionBase.h" #include "ExceptionCode.h" #include "Frame.h" #include "HTMLAudioElement.h" +#include "HTMLCanvasElement.h" #include "HTMLImageElement.h" #include "HTMLScriptElement.h" #include "HTMLNames.h" #include "JSDOMCoreException.h" #include "JSDOMWindowCustom.h" #include "JSEventException.h" +#include "JSExceptionBase.h" #include "JSNode.h" #include "JSRangeException.h" #include "JSXMLHttpRequestException.h" #include "KURL.h" #include "MessagePort.h" #include "RangeException.h" +#include "ScriptCachedFrameData.h" #include "ScriptController.h" +#include "Settings.h" #include "XMLHttpRequestException.h" +#include <runtime/Error.h> +#include <runtime/JSFunction.h> #include <runtime/PrototypeFunction.h> #include <wtf/StdLibExtras.h> @@ -67,6 +76,7 @@ namespace WebCore { using namespace HTMLNames; typedef Document::JSWrapperCache JSWrapperCache; +typedef Document::JSWrapperCacheMap JSWrapperCacheMap; // For debugging, keep a set of wrappers currently registered, and check that // all are unregistered before they are destroyed. This has helped us fix at @@ -75,6 +85,7 @@ typedef Document::JSWrapperCache JSWrapperCache; static void addWrapper(DOMObject* wrapper); static void removeWrapper(DOMObject* wrapper); static void removeWrappers(const JSWrapperCache& wrappers); +static void removeWrappers(const DOMObjectWrapperMap& wrappers); #ifdef NDEBUG @@ -90,6 +101,10 @@ static inline void removeWrappers(const JSWrapperCache&) { } +static inline void removeWrappers(const DOMObjectWrapperMap&) +{ +} + #else static HashSet<DOMObject*>& wrapperSet() @@ -119,7 +134,15 @@ static void removeWrapper(DOMObject* wrapper) static void removeWrappers(const JSWrapperCache& wrappers) { - for (JSWrapperCache::const_iterator it = wrappers.begin(); it != wrappers.end(); ++it) + JSWrapperCache::const_iterator wrappersEnd = wrappers.end(); + for (JSWrapperCache::const_iterator it = wrappers.begin(); it != wrappersEnd; ++it) + removeWrapper(it->second); +} + +static inline void removeWrappers(const DOMObjectWrapperMap& wrappers) +{ + DOMObjectWrapperMap::const_iterator wrappersEnd = wrappers.end(); + for (DOMObjectWrapperMap::const_iterator it = wrappers.begin(); it != wrappersEnd; ++it) removeWrapper(it->second); } @@ -130,67 +153,82 @@ DOMObject::~DOMObject() #endif -class DOMObjectWrapperMap { -public: - static DOMObjectWrapperMap& mapFor(JSGlobalData&); +DOMWrapperWorld::DOMWrapperWorld(JSC::JSGlobalData* globalData) + : m_globalData(globalData) +{ +} - DOMObject* get(void* objectHandle) +DOMWrapperWorld::~DOMWrapperWorld() +{ + JSGlobalData::ClientData* clientData = m_globalData->clientData; + ASSERT(clientData); + static_cast<WebCoreJSClientData*>(clientData)->forgetWorld(this); + + removeWrappers(m_wrappers); + + for (HashSet<Document*>::iterator iter = documentsWithWrappers.begin(); iter != documentsWithWrappers.end(); ++iter) + forgetWorldOfDOMNodesForDocument(*iter, this); +} + +class JSGlobalDataWorldIterator { +public: + JSGlobalDataWorldIterator(JSGlobalData* globalData) + : m_pos(static_cast<WebCoreJSClientData*>(globalData->clientData)->m_worldSet.begin()) + , m_end(static_cast<WebCoreJSClientData*>(globalData->clientData)->m_worldSet.end()) { - return m_map.get(objectHandle); } - void set(void* objectHandle, DOMObject* wrapper) + operator bool() { - addWrapper(wrapper); - m_map.set(objectHandle, wrapper); + return m_pos != m_end; } - void remove(void* objectHandle) + DOMWrapperWorld* operator*() { - removeWrapper(m_map.take(objectHandle)); + ASSERT(m_pos != m_end); + return *m_pos; } -private: - HashMap<void*, DOMObject*> m_map; -}; - -// Map from static HashTable instances to per-GlobalData ones. -class DOMObjectHashTableMap { -public: - static DOMObjectHashTableMap& mapFor(JSGlobalData&); - - ~DOMObjectHashTableMap() + DOMWrapperWorld* operator->() { - 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(); + ASSERT(m_pos != m_end); + return *m_pos; } - const JSC::HashTable* get(const JSC::HashTable* staticTable) + JSGlobalDataWorldIterator& operator++() { - 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; + ++m_pos; + return *this; } private: - HashMap<const JSC::HashTable*, JSC::HashTable> m_map; + HashSet<DOMWrapperWorld*>::iterator m_pos; + HashSet<DOMWrapperWorld*>::iterator m_end; }; -class WebCoreJSClientData : public JSGlobalData::ClientData { -public: - DOMObjectHashTableMap hashTableMap; - DOMObjectWrapperMap wrapperMap; -}; +DOMWrapperWorld* currentWorld(JSC::ExecState* exec) +{ + return static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->world(); +} + +DOMWrapperWorld* normalWorld(JSC::JSGlobalData& globalData) +{ + JSGlobalData::ClientData* clientData = globalData.clientData; + ASSERT(clientData); + return static_cast<WebCoreJSClientData*>(clientData)->normalWorld(); +} + +DOMWrapperWorld* mainThreadNormalWorld() +{ + ASSERT(isMainThread()); + static DOMWrapperWorld* cachedNormalWorld = normalWorld(*JSDOMWindow::commonJSGlobalData()); + return cachedNormalWorld; +} DOMObjectHashTableMap& DOMObjectHashTableMap::mapFor(JSGlobalData& globalData) { JSGlobalData::ClientData* clientData = globalData.clientData; - if (!clientData) { - clientData = new WebCoreJSClientData; - globalData.clientData = clientData; - } + ASSERT(clientData); return static_cast<WebCoreJSClientData*>(clientData)->hashTableMap; } @@ -199,64 +237,123 @@ const JSC::HashTable* getHashTableForGlobalData(JSGlobalData& globalData, const return DOMObjectHashTableMap::mapFor(globalData).get(staticTable); } -inline DOMObjectWrapperMap& DOMObjectWrapperMap::mapFor(JSGlobalData& globalData) +static inline DOMObjectWrapperMap& DOMObjectWrapperMapFor(JSC::ExecState* exec) { - JSGlobalData::ClientData* clientData = globalData.clientData; - if (!clientData) { - clientData = new WebCoreJSClientData; - globalData.clientData = clientData; - } - return static_cast<WebCoreJSClientData*>(clientData)->wrapperMap; + return currentWorld(exec)->m_wrappers; } -DOMObject* getCachedDOMObjectWrapper(JSGlobalData& globalData, void* objectHandle) +bool hasCachedDOMObjectWrapper(JSGlobalData* globalData, void* objectHandle) { - return DOMObjectWrapperMap::mapFor(globalData).get(objectHandle); + for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) { + if (worldIter->m_wrappers.contains(objectHandle)) + return true; + } + return false; } -void cacheDOMObjectWrapper(JSGlobalData& globalData, void* objectHandle, DOMObject* wrapper) +DOMObject* getCachedDOMObjectWrapper(JSC::ExecState* exec, void* objectHandle) { - DOMObjectWrapperMap::mapFor(globalData).set(objectHandle, wrapper); + return DOMObjectWrapperMapFor(exec).get(objectHandle); } -void forgetDOMObject(JSGlobalData& globalData, void* objectHandle) +void cacheDOMObjectWrapper(JSC::ExecState* exec, void* objectHandle, DOMObject* wrapper) { - DOMObjectWrapperMap::mapFor(globalData).remove(objectHandle); + addWrapper(wrapper); + DOMObjectWrapperMapFor(exec).set(objectHandle, wrapper); } -JSNode* getCachedDOMNodeWrapper(Document* document, Node* node) +bool hasCachedDOMNodeWrapper(Document* document, Node* node) { if (!document) - return static_cast<JSNode*>(DOMObjectWrapperMap::mapFor(*JSDOMWindow::commonJSGlobalData()).get(node)); - return document->wrapperCache().get(node); + return hasCachedDOMObjectWrapper(JSDOMWindow::commonJSGlobalData(), node); + + JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap(); + for (JSWrapperCacheMap::iterator iter = wrapperCacheMap.begin(); iter != wrapperCacheMap.end(); ++iter) { + if (iter->second->contains(node)) + return true; + } + return false; +} + +JSNode* getCachedDOMNodeWrapper(JSC::ExecState* exec, Document* document, Node* node) +{ + if (document) + return document->getWrapperCache(currentWorld(exec))->get(node); + return static_cast<JSNode*>(DOMObjectWrapperMapFor(exec).get(node)); +} + +void forgetDOMObject(DOMObject* wrapper, void* objectHandle) +{ + JSC::JSGlobalData* globalData = Heap::heap(wrapper)->globalData(); + for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) { + DOMObjectWrapperMap& wrappers = worldIter->m_wrappers; + DOMObjectWrapperMap::iterator iter = wrappers.find(objectHandle); + if ((iter != wrappers.end()) && (iter->second == wrapper)) { + removeWrapper(wrapper); + wrappers.remove(iter); + return; + } + } + + // If the world went away, it should have removed this wrapper from the set. + ASSERT(!wrapperSet().contains(wrapper)); } -void forgetDOMNode(Document* document, Node* node) +void forgetDOMNode(DOMObject* wrapper, Node* node, Document* document) { if (!document) { - DOMObjectWrapperMap::mapFor(*JSDOMWindow::commonJSGlobalData()).remove(node); + forgetDOMObject(wrapper, node); return; } - removeWrapper(document->wrapperCache().take(node)); + + JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap(); + for (JSWrapperCacheMap::iterator wrappersIter = wrapperCacheMap.begin(); wrappersIter != wrapperCacheMap.end(); ++wrappersIter) { + JSWrapperCache* wrappers = wrappersIter->second; + JSWrapperCache::iterator iter = wrappers->find(node); + if ((iter != wrappers->end()) && (iter->second == wrapper)) { + wrappers->remove(iter); + removeWrapper(wrapper); + return; + } + } + + // If the world went away, it should have removed this wrapper from the set. + ASSERT(!wrapperSet().contains(wrapper)); } -void cacheDOMNodeWrapper(Document* document, Node* node, JSNode* wrapper) +void cacheDOMNodeWrapper(JSC::ExecState* exec, Document* document, Node* node, JSNode* wrapper) { if (!document) { - DOMObjectWrapperMap::mapFor(*JSDOMWindow::commonJSGlobalData()).set(node, wrapper); + addWrapper(wrapper); + DOMObjectWrapperMapFor(exec).set(node, wrapper); return; } addWrapper(wrapper); - document->wrapperCache().set(node, wrapper); + document->getWrapperCache(currentWorld(exec))->set(node, wrapper); } void forgetAllDOMNodesForDocument(Document* document) { ASSERT(document); - removeWrappers(document->wrapperCache()); + JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap(); + JSWrapperCacheMap::const_iterator wrappersMapEnd = wrapperCacheMap.end(); + for (JSWrapperCacheMap::const_iterator wrappersMapIter = wrapperCacheMap.begin(); wrappersMapIter != wrappersMapEnd; ++wrappersMapIter) { + JSWrapperCache* wrappers = wrappersMapIter->second; + removeWrappers(*wrappers); + delete wrappers; + wrappersMapIter->first->forgetDocument(document); + } } -static inline bool isObservableThroughDOM(JSNode* jsNode) +void forgetWorldOfDOMNodesForDocument(Document* document, DOMWrapperWorld* world) +{ + JSWrapperCache* wrappers = document->wrapperCacheMap().take(world); + ASSERT(wrappers); // 'world' should only know about 'document' if 'document' knows about 'world'! + removeWrappers(*wrappers); + delete wrappers; +} + +static inline bool isObservableThroughDOM(JSNode* jsNode, DOMWrapperWorld* world) { // Certain conditions implicitly make a JS DOM node wrapper observable // through the DOM, even if no explicit reference to it remains. @@ -264,18 +361,48 @@ static inline bool isObservableThroughDOM(JSNode* jsNode) Node* node = jsNode->impl(); if (node->inDocument()) { - // 1. If a node is in the document, and its wrapper has custom properties, + // If a node is in the document, and its wrapper has custom properties, // the wrapper is observable because future access to the node through the // DOM must reflect those properties. if (jsNode->hasCustomProperties()) return true; - // 2. If a node is in the document, and has event listeners, its wrapper is + // If a node is in the document, and has event listeners, its wrapper is // observable because its wrapper is responsible for marking those event listeners. - if (node->eventListeners().size()) + if (node->hasEventListeners()) return true; // Technically, we may overzealously mark a wrapper for a node that has only non-JS event listeners. Oh well. + + // If a node owns another object with a wrapper with custom properties, + // the wrapper must be treated as observable, because future access to + // those objects through the DOM must reflect those properties. + // FIXME: It would be better if this logic could be in the node next to + // the custom markChildren functions rather than here. + if (node->isElementNode()) { + if (NamedNodeMap* attributes = static_cast<Element*>(node)->attributeMap()) { + if (DOMObject* wrapper = world->m_wrappers.get(attributes)) { + if (wrapper->hasCustomProperties()) + return true; + } + } + if (node->isStyledElement()) { + if (CSSMutableStyleDeclaration* style = static_cast<StyledElement*>(node)->inlineStyleDecl()) { + if (DOMObject* wrapper = world->m_wrappers.get(style)) { + if (wrapper->hasCustomProperties()) + return true; + } + } + } + if (static_cast<Element*>(node)->hasTagName(canvasTag)) { + if (CanvasRenderingContext* context = static_cast<HTMLCanvasElement*>(node)->renderingContext()) { + if (DOMObject* wrapper = world->m_wrappers.get(context)) { + if (wrapper->hasCustomProperties()) + return true; + } + } + } + } } else { - // 3. If a wrapper is the last reference to an image or script element + // If a wrapper is the last reference to an image or script element // that is loading but not in the document, the wrapper is observable // because it is the only thing keeping the image element alive, and if // the image element is destroyed, its load event will not fire. @@ -290,17 +417,27 @@ static inline bool isObservableThroughDOM(JSNode* jsNode) #endif } + // If a node is firing event listeners, its wrapper is observable because + // its wrapper is responsible for marking those event listeners. + if (node->isFiringEventListeners()) + return true; + return false; } -void markDOMNodesForDocument(MarkStack& markStack, Document* doc) +void markDOMNodesForDocument(MarkStack& markStack, Document* document) { - JSWrapperCache& nodeDict = doc->wrapperCache(); - JSWrapperCache::iterator nodeEnd = nodeDict.end(); - for (JSWrapperCache::iterator nodeIt = nodeDict.begin(); nodeIt != nodeEnd; ++nodeIt) { - JSNode* jsNode = nodeIt->second; - if (isObservableThroughDOM(jsNode)) - markStack.append(jsNode); + JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap(); + for (JSWrapperCacheMap::iterator wrappersIter = wrapperCacheMap.begin(); wrappersIter != wrapperCacheMap.end(); ++wrappersIter) { + DOMWrapperWorld* world = wrappersIter->first; + JSWrapperCache* nodeDict = wrappersIter->second; + + JSWrapperCache::iterator nodeEnd = nodeDict->end(); + for (JSWrapperCache::iterator nodeIt = nodeDict->begin(); nodeIt != nodeEnd; ++nodeIt) { + JSNode* jsNode = nodeIt->second; + if (isObservableThroughDOM(jsNode, world)) + markStack.append(jsNode); + } } } @@ -313,12 +450,10 @@ void markActiveObjectsForContext(MarkStack& markStack, JSGlobalData& globalData, HashMap<ActiveDOMObject*, void*>::const_iterator activeObjectsEnd = activeObjects.end(); for (HashMap<ActiveDOMObject*, void*>::const_iterator iter = activeObjects.begin(); iter != activeObjectsEnd; ++iter) { if (iter->first->hasPendingActivity()) { - DOMObject* wrapper = getCachedDOMObjectWrapper(globalData, iter->second); // Generally, an active object with pending activity must have a wrapper to mark its listeners. // However, some ActiveDOMObjects don't have JS wrappers (timers created by setTimeout is one example). // FIXME: perhaps need to make sure even timers have a markable 'wrapper'. - if (wrapper) - markStack.append(wrapper); + markDOMObjectWrapper(markStack, globalData, iter->second); } } @@ -326,10 +461,31 @@ void markActiveObjectsForContext(MarkStack& markStack, JSGlobalData& globalData, HashSet<MessagePort*>::const_iterator portsEnd = messagePorts.end(); for (HashSet<MessagePort*>::const_iterator iter = messagePorts.begin(); iter != portsEnd; ++iter) { // If the message port is remotely entangled, then always mark it as in-use because we can't determine reachability across threads. - if (!(*iter)->locallyEntangledPort() || (*iter)->hasPendingActivity()) { - DOMObject* wrapper = getCachedDOMObjectWrapper(globalData, *iter); - if (wrapper) - markStack.append(wrapper); + if (!(*iter)->locallyEntangledPort() || (*iter)->hasPendingActivity()) + markDOMObjectWrapper(markStack, globalData, *iter); + } +} + +typedef std::pair<JSNode*, DOMWrapperWorld*> WrapperAndWorld; +typedef WTF::Vector<WrapperAndWorld, 8> WrapperSet; + +static inline void takeWrappers(Node* node, Document* document, WrapperSet& wrapperSet) +{ + if (document) { + JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap(); + for (JSWrapperCacheMap::iterator iter = wrapperCacheMap.begin(); iter != wrapperCacheMap.end(); ++iter) { + if (JSNode* wrapper = iter->second->take(node)) { + removeWrapper(wrapper); + wrapperSet.append(WrapperAndWorld(wrapper, iter->first)); + } + } + } else { + for (JSGlobalDataWorldIterator worldIter(JSDOMWindow::commonJSGlobalData()); worldIter; ++worldIter) { + DOMWrapperWorld* world = *worldIter; + if (JSNode* wrapper = static_cast<JSNode*>(world->m_wrappers.take(node))) { + removeWrapper(wrapper); + wrapperSet.append(WrapperAndWorld(wrapper, world)); + } } } } @@ -337,23 +493,49 @@ void markActiveObjectsForContext(MarkStack& markStack, JSGlobalData& globalData, void updateDOMNodeDocument(Node* node, Document* oldDocument, Document* newDocument) { ASSERT(oldDocument != newDocument); - JSNode* wrapper = getCachedDOMNodeWrapper(oldDocument, node); - if (!wrapper) - return; - removeWrapper(wrapper); - cacheDOMNodeWrapper(newDocument, node, wrapper); - forgetDOMNode(oldDocument, node); - addWrapper(wrapper); + + WrapperSet wrapperSet; + takeWrappers(node, oldDocument, wrapperSet); + + for (unsigned i = 0; i < wrapperSet.size(); ++i) { + JSNode* wrapper = wrapperSet[i].first; + if (newDocument) + newDocument->getWrapperCache(wrapperSet[i].second)->set(node, wrapper); + else + wrapperSet[i].second->m_wrappers.set(node, wrapper); + addWrapper(wrapper); + } } void markDOMObjectWrapper(MarkStack& markStack, JSGlobalData& globalData, void* object) { + // FIXME: This could be changed to only mark wrappers that are "observable" + // as markDOMNodesForDocument does, allowing us to collect more wrappers, + // but doing this correctly would be challenging. if (!object) return; - DOMObject* wrapper = getCachedDOMObjectWrapper(globalData, object); - if (!wrapper) + + for (JSGlobalDataWorldIterator worldIter(&globalData); worldIter; ++worldIter) { + if (DOMObject* wrapper = worldIter->m_wrappers.get(object)) + markStack.append(wrapper); + } +} + +void markDOMNodeWrapper(MarkStack& markStack, Document* document, Node* node) +{ + if (document) { + JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap(); + for (JSWrapperCacheMap::iterator iter = wrapperCacheMap.begin(); iter != wrapperCacheMap.end(); ++iter) { + if (JSNode* wrapper = iter->second->get(node)) + markStack.append(wrapper); + } return; - markStack.append(wrapper); + } + + for (JSGlobalDataWorldIterator worldIter(JSDOMWindow::commonJSGlobalData()); worldIter; ++worldIter) { + if (DOMObject* wrapper = worldIter->m_wrappers.get(node)) + markStack.append(wrapper); + } } JSValue jsStringOrNull(ExecState* exec, const String& s) @@ -427,6 +609,9 @@ void reportException(ExecState* exec, JSValue exception) UString exceptionSourceURL = exceptionObject->get(exec, Identifier(exec, "sourceURL")).toString(exec); exec->clearException(); + if (ExceptionBase* exceptionBase = toExceptionBase(exception)) + errorMessage = exceptionBase->message() + ": " + exceptionBase->description(); + ScriptExecutionContext* scriptExecutionContext = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext(); ASSERT(scriptExecutionContext); @@ -497,7 +682,7 @@ bool allowsAccessFromFrame(ExecState* exec, Frame* frame) { if (!frame) return false; - JSDOMWindow* window = toJSDOMWindow(frame); + JSDOMWindow* window = toJSDOMWindow(frame, currentWorld(exec)); return window && window->allowsAccessFrom(exec); } @@ -505,7 +690,7 @@ bool allowsAccessFromFrame(ExecState* exec, Frame* frame, String& message) { if (!frame) return false; - JSDOMWindow* window = toJSDOMWindow(frame); + JSDOMWindow* window = toJSDOMWindow(frame, currentWorld(exec)); return window && window->allowsAccessFrom(exec, message); } @@ -519,8 +704,16 @@ void printErrorMessageForFrame(Frame* frame, const String& message) { if (!frame) return; - if (JSDOMWindow* window = toJSDOMWindow(frame)) - window->printErrorMessage(message); + if (message.isEmpty()) + return; + + Settings* settings = frame->settings(); + if (!settings) + return; + if (settings->privateBrowsingEnabled()) + return; + + frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, message, 1, String()); // FIXME: provide a real line number and source URL. } Frame* toLexicalFrame(ExecState* exec) @@ -559,7 +752,7 @@ Structure* getCachedDOMStructure(JSDOMGlobalObject* globalObject, const ClassInf return structures.get(classInfo).get(); } -Structure* cacheDOMStructure(JSDOMGlobalObject* globalObject, PassRefPtr<Structure> structure, const ClassInfo* classInfo) +Structure* cacheDOMStructure(JSDOMGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, const ClassInfo* classInfo) { JSDOMStructureMap& structures = globalObject->structures(); ASSERT(!structures.contains(classInfo)); @@ -571,7 +764,7 @@ Structure* getCachedDOMStructure(ExecState* exec, const ClassInfo* classInfo) return getCachedDOMStructure(static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), classInfo); } -Structure* cacheDOMStructure(ExecState* exec, PassRefPtr<Structure> structure, const ClassInfo* classInfo) +Structure* cacheDOMStructure(ExecState* exec, NonNullPassRefPtr<Structure> structure, const ClassInfo* classInfo) { return cacheDOMStructure(static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), structure, classInfo); } @@ -589,4 +782,33 @@ void cacheDOMConstructor(ExecState* exec, const ClassInfo* classInfo, JSObject* constructors.set(classInfo, constructor); } +JSC::JSObject* toJSSequence(ExecState* exec, JSValue value, unsigned& length) +{ + JSObject* object = value.getObject(); + if (!object) { + throwError(exec, TypeError); + return 0; + } + JSValue lengthValue = object->get(exec, exec->propertyNames().length); + if (exec->hadException()) + return 0; + + if (lengthValue.isUndefinedOrNull()) { + throwError(exec, TypeError); + return 0; + } + + length = lengthValue.toUInt32(exec); + if (exec->hadException()) + return 0; + + return object; +} + +bool DOMObject::defineOwnProperty(ExecState* exec, const Identifier&, PropertyDescriptor&, bool) +{ + throwError(exec, TypeError, "defineProperty is not supported on DOM Objects"); + return false; +} + } // namespace WebCore |
