diff options
Diffstat (limited to 'WebCore/bindings/js')
73 files changed, 1290 insertions, 1812 deletions
diff --git a/WebCore/bindings/js/DOMObjectWithSVGContext.h b/WebCore/bindings/js/DOMObjectWithSVGContext.h deleted file mode 100644 index 3d435cb..0000000 --- a/WebCore/bindings/js/DOMObjectWithSVGContext.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2009 Google, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef DOMObjectWithSVGContext_h -#define DOMObjectWithSVGContext_h - -#if ENABLE(SVG) - -#include "JSDOMBinding.h" -#include "SVGElement.h" - -namespace WebCore { - - // FIXME: This class (and file) should be removed once all SVG bindings - // have moved context() onto the various impl() pointers. - class DOMObjectWithSVGContext : public DOMObject { - public: - SVGElement* context() const { return m_context.get(); } - - protected: - DOMObjectWithSVGContext(NonNullPassRefPtr<JSC::Structure> structure, JSDOMGlobalObject*, SVGElement* context) - : DOMObject(structure) - , m_context(context) - { - // No space to store the JSDOMGlobalObject w/o hitting the CELL_SIZE limit. - } - - protected: // FIXME: Many custom bindings use m_context directly. Making this protected to temporariliy reduce code churn. - RefPtr<SVGElement> m_context; - }; - -} // namespace WebCore - -#endif // ENABLE(SVG) -#endif // DOMObjectWithSVGContext_h diff --git a/WebCore/bindings/js/GCController.cpp b/WebCore/bindings/js/GCController.cpp index 59bcfa3..3e5645f 100644 --- a/WebCore/bindings/js/GCController.cpp +++ b/WebCore/bindings/js/GCController.cpp @@ -40,17 +40,13 @@ using namespace JSC; namespace WebCore { -#if USE(PTHREADS) - static void* collect(void*) { JSLock lock(SilenceAssertionsOnly); - JSDOMWindow::commonJSGlobalData()->heap.collect(); + JSDOMWindow::commonJSGlobalData()->heap.collectAllGarbage(); return 0; } -#endif - GCController& gcController() { DEFINE_STATIC_LOCAL(GCController, staticGCController, ()); @@ -70,14 +66,12 @@ void GCController::garbageCollectSoon() void GCController::gcTimerFired(Timer<GCController>*) { - JSLock lock(SilenceAssertionsOnly); - JSDOMWindow::commonJSGlobalData()->heap.collect(); + collect(0); } void GCController::garbageCollectNow() { - JSLock lock(SilenceAssertionsOnly); - JSDOMWindow::commonJSGlobalData()->heap.collect(); + collect(0); } void GCController::garbageCollectOnAlternateThreadForDebugging(bool waitUntilDone) diff --git a/WebCore/bindings/js/JSBindingsAllInOne.cpp b/WebCore/bindings/js/JSBindingsAllInOne.cpp index cf1049a..e539042 100644 --- a/WebCore/bindings/js/JSBindingsAllInOne.cpp +++ b/WebCore/bindings/js/JSBindingsAllInOne.cpp @@ -86,7 +86,6 @@ #include "JSImageConstructor.cpp" #include "JSImageDataCustom.cpp" #include "JSInjectedScriptHostCustom.cpp" -#include "JSInspectedObjectWrapper.cpp" #include "JSInspectorFrontendHostCustom.cpp" #include "JSJavaScriptCallFrameCustom.cpp" #include "JSLazyEventListener.cpp" @@ -107,7 +106,6 @@ #include "JSPluginArrayCustom.cpp" #include "JSPluginCustom.cpp" #include "JSPluginElementFunctions.cpp" -#include "JSQuarantinedObjectWrapper.cpp" #include "JSSQLResultSetRowListCustom.cpp" #include "JSSQLTransactionCustom.cpp" #include "JSSVGElementInstanceCustom.cpp" @@ -115,7 +113,6 @@ #include "JSSVGMatrixCustom.cpp" #include "JSSVGPathSegCustom.cpp" #include "JSSVGPathSegListCustom.cpp" -#include "JSSVGPointListCustom.cpp" #include "JSSharedWorkerConstructor.cpp" #include "JSSharedWorkerCustom.cpp" #include "JSStorageCustom.cpp" diff --git a/WebCore/bindings/js/JSDOMBinding.cpp b/WebCore/bindings/js/JSDOMBinding.cpp index f12c779..04b6dc9 100644 --- a/WebCore/bindings/js/JSDOMBinding.cpp +++ b/WebCore/bindings/js/JSDOMBinding.cpp @@ -49,9 +49,11 @@ #include "ScriptController.h" #include "Settings.h" #include "XMLHttpRequestException.h" +#include <runtime/DateInstance.h> #include <runtime/Error.h> #include <runtime/JSFunction.h> #include <runtime/PrototypeFunction.h> +#include <wtf/MathExtras.h> #include <wtf/StdLibExtras.h> #if ENABLE(SVG) @@ -78,30 +80,32 @@ 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 -// least one bug. - -static void addWrapper(DOMObject* wrapper); -static void removeWrapper(DOMObject* wrapper); -static void removeWrappers(const JSWrapperCache& wrappers); -static void removeWrappers(const DOMObjectWrapperMap& wrappers); - -#ifdef NDEBUG - -static inline void addWrapper(DOMObject*) +inline JSWrapperCache* Document::getWrapperCache(DOMWrapperWorld* world) { + if (world->isNormal()) { + if (JSWrapperCache* wrapperCache = m_normalWorldWrapperCache) + return wrapperCache; + ASSERT(!m_wrapperCacheMap.contains(world)); + } else if (JSWrapperCache* wrapperCache = m_wrapperCacheMap.get(world)) + return wrapperCache; + return createWrapperCache(world); } -static inline void removeWrapper(DOMObject*) -{ -} +// For debugging, keep a set of wrappers currently cached, and check that +// all are uncached before they are destroyed. This helps us catch bugs like: +// - wrappers being deleted without being removed from the cache +// - wrappers being cached twice + +static void willCacheWrapper(DOMObject* wrapper); +static void didUncacheWrapper(DOMObject* wrapper); + +#ifdef NDEBUG -static inline void removeWrappers(const JSWrapperCache&) +static inline void willCacheWrapper(DOMObject*) { } -static inline void removeWrappers(const DOMObjectWrapperMap&) +static inline void didUncacheWrapper(DOMObject*) { } @@ -118,13 +122,13 @@ static HashSet<DOMObject*>& wrapperSet() #endif } -static void addWrapper(DOMObject* wrapper) +static void willCacheWrapper(DOMObject* wrapper) { ASSERT(!wrapperSet().contains(wrapper)); wrapperSet().add(wrapper); } -static void removeWrapper(DOMObject* wrapper) +static void didUncacheWrapper(DOMObject* wrapper) { if (!wrapper) return; @@ -132,20 +136,6 @@ static void removeWrapper(DOMObject* wrapper) wrapperSet().remove(wrapper); } -static void removeWrappers(const JSWrapperCache& wrappers) -{ - 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); -} - DOMObject::~DOMObject() { ASSERT(!wrapperSet().contains(this)); @@ -153,8 +143,9 @@ DOMObject::~DOMObject() #endif -DOMWrapperWorld::DOMWrapperWorld(JSC::JSGlobalData* globalData) +DOMWrapperWorld::DOMWrapperWorld(JSC::JSGlobalData* globalData, bool isNormal) : m_globalData(globalData) + , m_isNormal(isNormal) { } @@ -164,8 +155,6 @@ DOMWrapperWorld::~DOMWrapperWorld() 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); } @@ -206,11 +195,6 @@ private: HashSet<DOMWrapperWorld*>::iterator m_end; }; -DOMWrapperWorld* currentWorld(JSC::ExecState* exec) -{ - return static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->world(); -} - DOMWrapperWorld* normalWorld(JSC::JSGlobalData& globalData) { JSGlobalData::ClientData* clientData = globalData.clientData; @@ -242,10 +226,19 @@ static inline DOMObjectWrapperMap& DOMObjectWrapperMapFor(JSC::ExecState* exec) return currentWorld(exec)->m_wrappers; } +bool hasCachedDOMObjectWrapperUnchecked(JSGlobalData* globalData, void* objectHandle) +{ + for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) { + if (worldIter->m_wrappers.uncheckedGet(objectHandle)) + return true; + } + return false; +} + bool hasCachedDOMObjectWrapper(JSGlobalData* globalData, void* objectHandle) { for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) { - if (worldIter->m_wrappers.contains(objectHandle)) + if (worldIter->m_wrappers.get(objectHandle)) return true; } return false; @@ -258,18 +251,18 @@ DOMObject* getCachedDOMObjectWrapper(JSC::ExecState* exec, void* objectHandle) void cacheDOMObjectWrapper(JSC::ExecState* exec, void* objectHandle, DOMObject* wrapper) { - addWrapper(wrapper); + willCacheWrapper(wrapper); DOMObjectWrapperMapFor(exec).set(objectHandle, wrapper); } -bool hasCachedDOMNodeWrapper(Document* document, Node* node) +bool hasCachedDOMNodeWrapperUnchecked(Document* document, Node* node) { if (!document) - return hasCachedDOMObjectWrapper(JSDOMWindow::commonJSGlobalData(), node); + return hasCachedDOMObjectWrapperUnchecked(JSDOMWindow::commonJSGlobalData(), node); JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap(); for (JSWrapperCacheMap::iterator iter = wrapperCacheMap.begin(); iter != wrapperCacheMap.end(); ++iter) { - if (iter->second->contains(node)) + if (iter->second->uncheckedGet(node)) return true; } return false; @@ -285,50 +278,50 @@ JSNode* getCachedDOMNodeWrapper(JSC::ExecState* exec, Document* document, 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; - } + + // Check the normal world first! + JSGlobalData::ClientData* clientData = globalData->clientData; + ASSERT(clientData); + DOMObjectWrapperMap& wrappers = static_cast<WebCoreJSClientData*>(clientData)->normalWorld()->m_wrappers; + if (wrappers.uncheckedRemove(objectHandle, wrapper)) { + didUncacheWrapper(wrapper); + return; } - // If the world went away, it should have removed this wrapper from the set. - ASSERT(!wrapperSet().contains(wrapper)); + // We can't guarantee that a wrapper is in the cache when it uncaches itself, + // since a new wrapper may be cached before the old wrapper's destructor runs. + for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) { + if (worldIter->m_wrappers.uncheckedRemove(objectHandle, wrapper)) + break; + } + didUncacheWrapper(wrapper); } -void forgetDOMNode(DOMObject* wrapper, Node* node, Document* document) +void forgetDOMNode(JSNode* wrapper, Node* node, Document* document) { if (!document) { forgetDOMObject(wrapper, node); return; } + // We can't guarantee that a wrapper is in the cache when it uncaches itself, + // since a new wrapper may be cached before the old wrapper's destructor runs. 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 (wrappersIter->second->uncheckedRemove(node, wrapper)) + break; } - - // If the world went away, it should have removed this wrapper from the set. - ASSERT(!wrapperSet().contains(wrapper)); + didUncacheWrapper(wrapper); } void cacheDOMNodeWrapper(JSC::ExecState* exec, Document* document, Node* node, JSNode* wrapper) { if (!document) { - addWrapper(wrapper); + willCacheWrapper(wrapper); DOMObjectWrapperMapFor(exec).set(node, wrapper); return; } - addWrapper(wrapper); + willCacheWrapper(wrapper); document->getWrapperCache(currentWorld(exec))->set(node, wrapper); } @@ -338,9 +331,7 @@ void forgetAllDOMNodesForDocument(Document* document) 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; + delete wrappersMapIter->second; wrappersMapIter->first->forgetDocument(document); } } @@ -349,7 +340,6 @@ 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; } @@ -379,14 +369,14 @@ static inline bool isObservableThroughDOM(JSNode* jsNode, DOMWrapperWorld* world // 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 (DOMObject* wrapper = world->m_wrappers.uncheckedGet(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 (DOMObject* wrapper = world->m_wrappers.uncheckedGet(style)) { if (wrapper->hasCustomProperties()) return true; } @@ -394,7 +384,7 @@ static inline bool isObservableThroughDOM(JSNode* jsNode, DOMWrapperWorld* world } if (static_cast<Element*>(node)->hasTagName(canvasTag)) { if (CanvasRenderingContext* context = static_cast<HTMLCanvasElement*>(node)->renderingContext()) { - if (DOMObject* wrapper = world->m_wrappers.get(context)) { + if (DOMObject* wrapper = world->m_wrappers.uncheckedGet(context)) { if (wrapper->hasCustomProperties()) return true; } @@ -432,8 +422,8 @@ void markDOMNodesForDocument(MarkStack& markStack, Document* document) DOMWrapperWorld* world = wrappersIter->first; JSWrapperCache* nodeDict = wrappersIter->second; - JSWrapperCache::iterator nodeEnd = nodeDict->end(); - for (JSWrapperCache::iterator nodeIt = nodeDict->begin(); nodeIt != nodeEnd; ++nodeIt) { + JSWrapperCache::iterator nodeEnd = nodeDict->uncheckedEnd(); + for (JSWrapperCache::iterator nodeIt = nodeDict->uncheckedBegin(); nodeIt != nodeEnd; ++nodeIt) { JSNode* jsNode = nodeIt->second; if (isObservableThroughDOM(jsNode, world)) markStack.append(jsNode); @@ -451,8 +441,7 @@ void markActiveObjectsForContext(MarkStack& markStack, JSGlobalData& globalData, for (HashMap<ActiveDOMObject*, void*>::const_iterator iter = activeObjects.begin(); iter != activeObjectsEnd; ++iter) { if (iter->first->hasPendingActivity()) { // 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'. + // However, some ActiveDOMObjects don't have JS wrappers. markDOMObjectWrapper(markStack, globalData, iter->second); } } @@ -475,7 +464,7 @@ static inline void takeWrappers(Node* node, Document* document, WrapperSet& wrap JSWrapperCacheMap& wrapperCacheMap = document->wrapperCacheMap(); for (JSWrapperCacheMap::iterator iter = wrapperCacheMap.begin(); iter != wrapperCacheMap.end(); ++iter) { if (JSNode* wrapper = iter->second->take(node)) { - removeWrapper(wrapper); + didUncacheWrapper(wrapper); wrapperSet.append(WrapperAndWorld(wrapper, iter->first)); } } @@ -483,7 +472,7 @@ static inline void takeWrappers(Node* node, Document* document, WrapperSet& wrap for (JSGlobalDataWorldIterator worldIter(JSDOMWindow::commonJSGlobalData()); worldIter; ++worldIter) { DOMWrapperWorld* world = *worldIter; if (JSNode* wrapper = static_cast<JSNode*>(world->m_wrappers.take(node))) { - removeWrapper(wrapper); + didUncacheWrapper(wrapper); wrapperSet.append(WrapperAndWorld(wrapper, world)); } } @@ -499,11 +488,11 @@ void updateDOMNodeDocument(Node* node, Document* oldDocument, Document* newDocum for (unsigned i = 0; i < wrapperSet.size(); ++i) { JSNode* wrapper = wrapperSet[i].first; + willCacheWrapper(wrapper); if (newDocument) newDocument->getWrapperCache(wrapperSet[i].second)->set(node, wrapper); else wrapperSet[i].second->m_wrappers.set(node, wrapper); - addWrapper(wrapper); } } @@ -516,7 +505,7 @@ void markDOMObjectWrapper(MarkStack& markStack, JSGlobalData& globalData, void* return; for (JSGlobalDataWorldIterator worldIter(&globalData); worldIter; ++worldIter) { - if (DOMObject* wrapper = worldIter->m_wrappers.get(object)) + if (DOMObject* wrapper = worldIter->m_wrappers.uncheckedGet(object)) markStack.append(wrapper); } } @@ -526,18 +515,55 @@ 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)) + if (JSNode* wrapper = iter->second->uncheckedGet(node)) markStack.append(wrapper); } return; } for (JSGlobalDataWorldIterator worldIter(JSDOMWindow::commonJSGlobalData()); worldIter; ++worldIter) { - if (DOMObject* wrapper = worldIter->m_wrappers.get(node)) + if (DOMObject* wrapper = worldIter->m_wrappers.uncheckedGet(node)) markStack.append(wrapper); } } +static void stringWrapperDestroyed(JSString* str, void* context) +{ + StringImpl* cacheKey = static_cast<StringImpl*>(context); + JSC::JSGlobalData* globalData = Heap::heap(str)->globalData(); + + // Check the normal world first! + JSGlobalData::ClientData* clientData = globalData->clientData; + ASSERT(clientData); + JSStringCache& cache = static_cast<WebCoreJSClientData*>(clientData)->normalWorld()->m_stringCache; + if (cache.uncheckedRemove(cacheKey, str)) { + cacheKey->deref(); + return; + } + + for (JSGlobalDataWorldIterator worldIter(globalData); worldIter; ++worldIter) { + if (worldIter->m_stringCache.uncheckedRemove(cacheKey, str)) + break; + } + + cacheKey->deref(); +} + +JSValue jsStringSlowCase(ExecState* exec, JSStringCache& stringCache, StringImpl* stringImpl) +{ + // If there is a stale entry, we have to explicitly remove it to avoid + // problems down the line. + if (JSString* wrapper = stringCache.uncheckedGet(stringImpl)) + stringCache.uncheckedRemove(stringImpl, wrapper); + + JSString* wrapper = jsStringWithFinalizer(exec, stringImpl->ustring(), stringWrapperDestroyed, stringImpl); + stringCache.set(stringImpl, wrapper); + // ref explicitly instead of using a RefPtr-keyed hashtable because the wrapper can + // outlive the cache, so the stringImpl has to match the wrapper's lifetime. + stringImpl->ref(); + return wrapper; +} + JSValue jsStringOrNull(ExecState* exec, const String& s) { if (s.isNull()) @@ -566,6 +592,11 @@ JSValue jsStringOrFalse(ExecState* exec, const String& s) return jsString(exec, s); } +JSValue jsString(ExecState* exec, const KURL& url) +{ + return jsString(exec, url.string()); +} + JSValue jsStringOrNull(ExecState* exec, const KURL& url) { if (url.isNull()) @@ -601,6 +632,22 @@ UString valueToStringWithUndefinedOrNullCheck(ExecState* exec, JSValue value) return value.toString(exec); } +JSValue jsDateOrNull(ExecState* exec, double value) +{ + if (!isfinite(value)) + return jsNull(); + return new (exec) DateInstance(exec, value); +} + +double valueToDate(ExecState* exec, JSValue value) +{ + if (value.isNumber()) + return value.uncheckedGetNumber(); + if (!value.inherits(&DateInstance::info)) + return std::numeric_limits<double>::quiet_NaN(); + return static_cast<DateInstance*>(value.toObject(exec))->internalNumber(); +} + void reportException(ExecState* exec, JSValue exception) { UString errorMessage = exception.toString(exec); @@ -659,7 +706,7 @@ void setDOMException(ExecState* exec, ExceptionCode ec) break; #if ENABLE(SVG) case SVGExceptionType: - errorObject = toJS(exec, globalObject, SVGException::create(description).get(), 0); + errorObject = toJS(exec, globalObject, SVGException::create(description).get(), 0 /* no context on purpose */); break; #endif #if ENABLE(XPATH) @@ -734,7 +781,7 @@ bool processingUserGesture(ExecState* exec) KURL completeURL(ExecState* exec, const String& relativeURL) { - // For histoical reasons, we need to complete the URL using the dynamic frame. + // For historical reasons, we need to complete the URL using the dynamic frame. Frame* frame = toDynamicFrame(exec); if (!frame) return KURL(); 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 diff --git a/WebCore/bindings/js/JSDOMGlobalObject.cpp b/WebCore/bindings/js/JSDOMGlobalObject.cpp index 011a4e4..e0b5b89 100644 --- a/WebCore/bindings/js/JSDOMGlobalObject.cpp +++ b/WebCore/bindings/js/JSDOMGlobalObject.cpp @@ -40,6 +40,8 @@ using namespace JSC; namespace WebCore { +const ClassInfo JSDOMGlobalObject::s_info = { "DOMGlobalObject", 0, 0, 0 }; + JSDOMGlobalObject::JSDOMGlobalObject(NonNullPassRefPtr<Structure> structure, JSDOMGlobalObject::JSDOMGlobalObjectData* data, JSObject* thisValue) : JSGlobalObject(structure, data, thisValue) { @@ -56,14 +58,9 @@ void JSDOMGlobalObject::markChildren(MarkStack& markStack) JSDOMConstructorMap::iterator end2 = constructors().end(); for (JSDOMConstructorMap::iterator it2 = constructors().begin(); it2 != end2; ++it2) markStack.append(it2->second); -} -PassRefPtr<JSEventListener> JSDOMGlobalObject::createJSAttributeEventListener(JSValue val) -{ - if (!val.isObject()) - return 0; - - return JSEventListener::create(asObject(val), true, currentWorld(globalExec())).get(); + if (d()->m_injectedScript) + markStack.append(d()->m_injectedScript); } void JSDOMGlobalObject::setCurrentEvent(Event* evt) @@ -76,6 +73,16 @@ Event* JSDOMGlobalObject::currentEvent() const return d()->evt; } +void JSDOMGlobalObject::setInjectedScript(JSObject* injectedScript) +{ + d()->m_injectedScript = injectedScript; +} + +JSObject* JSDOMGlobalObject::injectedScript() const +{ + return d()->m_injectedScript; +} + void JSDOMGlobalObject::destroyJSDOMGlobalObjectData(void* jsDOMGlobalObjectData) { delete static_cast<JSDOMGlobalObjectData*>(jsDOMGlobalObjectData); diff --git a/WebCore/bindings/js/JSDOMGlobalObject.h b/WebCore/bindings/js/JSDOMGlobalObject.h index 647730c..8eb55c1 100644 --- a/WebCore/bindings/js/JSDOMGlobalObject.h +++ b/WebCore/bindings/js/JSDOMGlobalObject.h @@ -54,26 +54,29 @@ namespace WebCore { virtual ScriptExecutionContext* scriptExecutionContext() const = 0; - // Creates a JS EventListener for an "onXXX" event attribute. These - // listeners cannot be removed through the removeEventListener API. - PassRefPtr<JSEventListener> createJSAttributeEventListener(JSC::JSValue); - // Make binding code generation easier. JSDOMGlobalObject* globalObject() { return this; } void setCurrentEvent(Event*); Event* currentEvent() const; + void setInjectedScript(JSObject*); + JSObject* injectedScript() const; + virtual void markChildren(JSC::MarkStack&); DOMWrapperWorld* world() { return d()->m_world.get(); } + virtual const JSC::ClassInfo* classInfo() const { return &s_info; } + static const JSC::ClassInfo s_info; + protected: struct JSDOMGlobalObjectData : public JSC::JSGlobalObject::JSGlobalObjectData { JSDOMGlobalObjectData(DOMWrapperWorld* world, Destructor destructor = destroyJSDOMGlobalObjectData) : JSGlobalObjectData(destructor) , evt(0) , m_world(world) + , m_injectedScript(0) { } @@ -82,6 +85,7 @@ namespace WebCore { Event* evt; RefPtr<DOMWrapperWorld> m_world; + JSObject* m_injectedScript; }; private: diff --git a/WebCore/bindings/js/JSDOMWindowBase.cpp b/WebCore/bindings/js/JSDOMWindowBase.cpp index e3af13f..4338cdd 100644 --- a/WebCore/bindings/js/JSDOMWindowBase.cpp +++ b/WebCore/bindings/js/JSDOMWindowBase.cpp @@ -24,6 +24,7 @@ #include "JSDOMWindowBase.h" #include "CString.h" +#include "Chrome.h" #include "Console.h" #include "DOMWindow.h" #include "Frame.h" @@ -40,7 +41,7 @@ using namespace JSC; namespace WebCore { -const ClassInfo JSDOMWindowBase::s_info = { "Window", 0, 0, 0 }; +const ClassInfo JSDOMWindowBase::s_info = { "Window", &JSDOMGlobalObject::s_info, 0, 0 }; JSDOMWindowBase::JSDOMWindowBaseData::JSDOMWindowBaseData(PassRefPtr<DOMWindow> window, JSDOMWindowShell* shell) : JSDOMGlobalObjectData(shell->world(), destroyJSDOMWindowBaseData) @@ -75,7 +76,7 @@ ScriptExecutionContext* JSDOMWindowBase::scriptExecutionContext() const String JSDOMWindowBase::crossDomainAccessErrorMessage(const JSGlobalObject* other) const { KURL originURL = asJSDOMWindow(other)->impl()->url(); - KURL targetURL = impl()->frame()->document()->url(); + KURL targetURL = d()->shell->window()->impl()->url(); if (originURL.isNull() || targetURL.isNull()) return String(); @@ -170,7 +171,7 @@ void JSDOMWindowBase::destroyJSDOMWindowBaseData(void* jsDOMWindowBaseData) delete static_cast<JSDOMWindowBaseData*>(jsDOMWindowBaseData); } -// JSDOMGlobalObject* is ignored, accesing a window in any context will +// JSDOMGlobalObject* is ignored, accessing a window in any context will // use that DOMWindow's prototype chain. JSValue toJS(ExecState* exec, JSDOMGlobalObject*, DOMWindow* domWindow) { diff --git a/WebCore/bindings/js/JSDOMWindowBase.h b/WebCore/bindings/js/JSDOMWindowBase.h index 66af344..2726996 100644 --- a/WebCore/bindings/js/JSDOMWindowBase.h +++ b/WebCore/bindings/js/JSDOMWindowBase.h @@ -92,7 +92,7 @@ namespace WebCore { }; // Returns a JSDOMWindow or jsNull() - // JSDOMGlobalObject* is ignored, accesing a window in any context will + // JSDOMGlobalObject* is ignored, accessing a window in any context will // use that DOMWindow's prototype chain. JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, DOMWindow*); JSC::JSValue toJS(JSC::ExecState*, DOMWindow*); diff --git a/WebCore/bindings/js/JSDOMWindowCustom.cpp b/WebCore/bindings/js/JSDOMWindowCustom.cpp index 66fe926..1da5af2 100644 --- a/WebCore/bindings/js/JSDOMWindowCustom.cpp +++ b/WebCore/bindings/js/JSDOMWindowCustom.cpp @@ -22,6 +22,7 @@ #include "AtomicString.h" #include "Base64.h" +#include "Chrome.h" #include "DOMWindow.h" #include "Document.h" #include "ExceptionCode.h" @@ -112,6 +113,7 @@ void JSDOMWindow::markChildren(MarkStack& markStack) markDOMObjectWrapper(markStack, globalData, impl()->optionalStatusbar()); markDOMObjectWrapper(markStack, globalData, impl()->optionalToolbar()); markDOMObjectWrapper(markStack, globalData, impl()->optionalLocation()); + markDOMObjectWrapper(markStack, globalData, impl()->optionalMedia()); #if ENABLE(DOM_STORAGE) markDOMObjectWrapper(markStack, globalData, impl()->optionalSessionStorage()); markDOMObjectWrapper(markStack, globalData, impl()->optionalLocalStorage()); @@ -265,7 +267,7 @@ bool JSDOMWindow::getOwnPropertySlot(ExecState* exec, const Identifier& property } } - // FIXME: Search the whole frame hierachy somewhere around here. + // FIXME: Search the whole frame hierarchy somewhere around here. // We need to test the correct priority order. // allow window[1] or parent[1] etc. (#56983) @@ -323,22 +325,6 @@ bool JSDOMWindow::getOwnPropertyDescriptor(ExecState* exec, const Identifier& pr return true; } - // We need this code here because otherwise JSDOMWindowBase will stop the search before we even get to the - // prototype due to the blanket same origin (allowsAccessFrom) check at the end of getOwnPropertySlot. - // Also, it's important to get the implementation straight out of the DOMWindow prototype regardless of - // what prototype is actually set on this object. - entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName); - if (entry) { - if (entry->attributes() & Function) { - if (entry->function() == jsDOMWindowPrototypeFunctionShowModalDialog) { - if (!DOMWindow::canShowModalDialog(impl()->frame())) { - descriptor.setUndefined(); - return true; - } - } - } - } - entry = JSDOMWindow::s_info.propHashTable(exec)->entry(exec, propertyName); if (entry) { PropertySlot slot; @@ -359,14 +345,6 @@ bool JSDOMWindow::getOwnPropertyDescriptor(ExecState* exec, const Identifier& pr return true; } - // Do prototype lookup early so that functions and attributes in the prototype can have - // precedence over the index and name getters. - JSValue proto = prototype(); - if (proto.isObject()) { - if (asObject(proto)->getPropertyDescriptor(exec, propertyName, descriptor)) - return true; - } - bool ok; unsigned i = propertyName.toArrayIndex(&ok); if (ok && i < impl()->frame()->tree()->childCount()) { @@ -418,20 +396,20 @@ bool JSDOMWindow::deleteProperty(ExecState* exec, const Identifier& propertyName return Base::deleteProperty(exec, propertyName); } -void JSDOMWindow::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSDOMWindow::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { // Only allow the window to enumerated by frames in the same origin. if (!allowsAccessFrom(exec)) return; - Base::getPropertyNames(exec, propertyNames); + Base::getPropertyNames(exec, propertyNames, mode); } -void JSDOMWindow::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSDOMWindow::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { // Only allow the window to enumerated by frames in the same origin. if (!allowsAccessFrom(exec)) return; - Base::getOwnPropertyNames(exec, propertyNames); + Base::getOwnPropertyNames(exec, propertyNames, mode); } void JSDOMWindow::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes) @@ -928,7 +906,12 @@ JSValue JSDOMWindow::setTimeout(ExecState* exec, const ArgList& args) if (exec->hadException()) return jsUndefined(); int delay = args.at(1).toInt32(exec); - return jsNumber(exec, impl()->setTimeout(action, delay)); + + ExceptionCode ec = 0; + int result = impl()->setTimeout(action, delay, ec); + setDOMException(exec, ec); + + return jsNumber(exec, result); } JSValue JSDOMWindow::setInterval(ExecState* exec, const ArgList& args) @@ -937,7 +920,12 @@ JSValue JSDOMWindow::setInterval(ExecState* exec, const ArgList& args) if (exec->hadException()) return jsUndefined(); int delay = args.at(1).toInt32(exec); - return jsNumber(exec, impl()->setInterval(action, delay)); + + ExceptionCode ec = 0; + int result = impl()->setInterval(action, delay, ec); + setDOMException(exec, ec); + + return jsNumber(exec, result); } JSValue JSDOMWindow::atob(ExecState* exec, const ArgList& args) diff --git a/WebCore/bindings/js/JSDOMWindowShell.cpp b/WebCore/bindings/js/JSDOMWindowShell.cpp index 09141ee..1e82a49 100644 --- a/WebCore/bindings/js/JSDOMWindowShell.cpp +++ b/WebCore/bindings/js/JSDOMWindowShell.cpp @@ -114,14 +114,14 @@ bool JSDOMWindowShell::deleteProperty(ExecState* exec, const Identifier& propert return m_window->deleteProperty(exec, propertyName); } -void JSDOMWindowShell::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSDOMWindowShell::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { - m_window->getPropertyNames(exec, propertyNames); + m_window->getPropertyNames(exec, propertyNames, mode); } -void JSDOMWindowShell::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSDOMWindowShell::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { - m_window->getOwnPropertyNames(exec, propertyNames); + m_window->getOwnPropertyNames(exec, propertyNames, mode); } void JSDOMWindowShell::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes) diff --git a/WebCore/bindings/js/JSDOMWindowShell.h b/WebCore/bindings/js/JSDOMWindowShell.h index 27036d4..1b986b8 100644 --- a/WebCore/bindings/js/JSDOMWindowShell.h +++ b/WebCore/bindings/js/JSDOMWindowShell.h @@ -60,7 +60,7 @@ namespace WebCore { 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); } DOMWrapperWorld* world() { return m_world.get(); } @@ -75,8 +75,8 @@ namespace WebCore { virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); virtual void putWithAttributes(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, unsigned attributes); virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier& propertyName); - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); - virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties); + virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties); virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes); virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction, unsigned attributes); virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&, bool shouldThrow); diff --git a/WebCore/bindings/js/JSDocumentCustom.cpp b/WebCore/bindings/js/JSDocumentCustom.cpp index 4aa6583..9366399 100644 --- a/WebCore/bindings/js/JSDocumentCustom.cpp +++ b/WebCore/bindings/js/JSDocumentCustom.cpp @@ -96,18 +96,18 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Document* documen if (!document) return jsNull(); - DOMObject* wrapper = getCachedDOMObjectWrapper(exec, document); + DOMObject* wrapper = getCachedDOMNodeWrapper(exec, document, document); if (wrapper) return wrapper; if (document->isHTMLDocument()) - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, HTMLDocument, document); + wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, HTMLDocument, document); #if ENABLE(SVG) else if (document->isSVGDocument()) - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, SVGDocument, document); + wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, SVGDocument, document); #endif else - wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, Document, document); + wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, Document, document); // Make sure the document is kept around by the window object, and works right with the // back/forward cache. diff --git a/WebCore/bindings/js/JSEventListener.cpp b/WebCore/bindings/js/JSEventListener.cpp index 73060f1..d3b5fe1 100644 --- a/WebCore/bindings/js/JSEventListener.cpp +++ b/WebCore/bindings/js/JSEventListener.cpp @@ -81,7 +81,7 @@ void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext return; // FIXME: Is this check needed for other contexts? ScriptController* script = frame->script(); - if (!script->isEnabled() || script->isPaused()) + if (!script->canExecuteScripts() || script->isPaused()) return; } diff --git a/WebCore/bindings/js/JSEventListener.h b/WebCore/bindings/js/JSEventListener.h index bf3af48..9ba09c6 100644 --- a/WebCore/bindings/js/JSEventListener.h +++ b/WebCore/bindings/js/JSEventListener.h @@ -66,6 +66,16 @@ namespace WebCore { RefPtr<DOMWrapperWorld> m_isolatedWorld; }; + // Creates a JS EventListener for an "onXXX" event attribute. + inline PassRefPtr<JSEventListener> createJSAttributeEventListener(JSC::ExecState* exec, JSC::JSValue listener) + { + if (!listener.isObject()) + return 0; + + return JSEventListener::create(asObject(listener), true, currentWorld(exec)); + } + + } // namespace WebCore #endif // JSEventListener_h diff --git a/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp b/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp index 751e7de..80634f7 100644 --- a/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp +++ b/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp @@ -26,10 +26,12 @@ #include "config.h" #include "JSHTMLCanvasElement.h" +#include "CanvasContextAttributes.h" #include "HTMLCanvasElement.h" #include "JSCanvasRenderingContext2D.h" #if ENABLE(3D_CANVAS) #include "JSWebGLRenderingContext.h" +#include "WebGLContextAttributes.h" #endif #include <wtf/GetPtr.h> @@ -47,4 +49,36 @@ void JSHTMLCanvasElement::markChildren(MarkStack& markStack) markDOMObjectWrapper(markStack, globalData, canvas->renderingContext()); } +JSValue JSHTMLCanvasElement::getContext(ExecState* exec, const ArgList& args) +{ + HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(impl()); + const UString& contextId = args.at(0).toString(exec); + RefPtr<CanvasContextAttributes> attrs; +#if ENABLE(3D_CANVAS) + if (contextId == "experimental-webgl" || contextId == "webkit-3d") { + attrs = WebGLContextAttributes::create(); + WebGLContextAttributes* webGLAttrs = static_cast<WebGLContextAttributes*>(attrs.get()); + if (args.size() > 1 && args.at(1).isObject()) { + JSObject* jsAttrs = args.at(1).getObject(); + Identifier alpha(exec, "alpha"); + if (jsAttrs->hasProperty(exec, alpha)) + webGLAttrs->setAlpha(jsAttrs->get(exec, alpha).toBoolean(exec)); + Identifier depth(exec, "depth"); + if (jsAttrs->hasProperty(exec, depth)) + webGLAttrs->setDepth(jsAttrs->get(exec, depth).toBoolean(exec)); + Identifier stencil(exec, "stencil"); + if (jsAttrs->hasProperty(exec, stencil)) + webGLAttrs->setStencil(jsAttrs->get(exec, stencil).toBoolean(exec)); + Identifier antialias(exec, "antialias"); + if (jsAttrs->hasProperty(exec, antialias)) + webGLAttrs->setAntialias(jsAttrs->get(exec, antialias).toBoolean(exec)); + Identifier premultipliedAlpha(exec, "premultipliedAlpha"); + if (jsAttrs->hasProperty(exec, premultipliedAlpha)) + webGLAttrs->setPremultipliedAlpha(jsAttrs->get(exec, premultipliedAlpha).toBoolean(exec)); + } + } +#endif + return toJS(exec, globalObject(), WTF::getPtr(canvas->getContext(contextId, attrs.get()))); +} + } // namespace WebCore diff --git a/WebCore/bindings/js/JSHTMLFormElementCustom.cpp b/WebCore/bindings/js/JSHTMLFormElementCustom.cpp index de9ec4a..c364c14 100644 --- a/WebCore/bindings/js/JSHTMLFormElementCustom.cpp +++ b/WebCore/bindings/js/JSHTMLFormElementCustom.cpp @@ -66,7 +66,7 @@ JSValue JSHTMLFormElement::submit(ExecState* exec, const ArgList&) Frame* activeFrame = asJSDOMWindow(exec->dynamicGlobalObject())->impl()->frame(); if (!activeFrame) return jsUndefined(); - static_cast<HTMLFormElement*>(impl())->submit(0, false, !activeFrame->script()->anyPageIsProcessingUserGesture()); + static_cast<HTMLFormElement*>(impl())->submit(activeFrame); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSHistoryCustom.cpp b/WebCore/bindings/js/JSHistoryCustom.cpp index 3076503..fff747f 100644 --- a/WebCore/bindings/js/JSHistoryCustom.cpp +++ b/WebCore/bindings/js/JSHistoryCustom.cpp @@ -154,12 +154,12 @@ bool JSHistory::deleteProperty(ExecState* exec, const Identifier& propertyName) return Base::deleteProperty(exec, propertyName); } -void JSHistory::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSHistory::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { // Only allow the history object to enumerated by frames in the same origin. if (!allowsAccessFromFrame(exec, impl()->frame())) return; - Base::getOwnPropertyNames(exec, propertyNames); + Base::getOwnPropertyNames(exec, propertyNames, mode); } JSValue JSHistory::pushState(ExecState* exec, const ArgList& args) diff --git a/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp b/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp index fcc9e5e..d38d8ee 100644 --- a/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp +++ b/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp @@ -47,8 +47,6 @@ #include "InspectorController.h" #include "InspectorResource.h" #include "JSDOMWindow.h" -#include "JSInspectedObjectWrapper.h" -#include "JSInspectorCallbackWrapper.h" #include "JSNode.h" #include "JSRange.h" #include "Node.h" @@ -59,6 +57,7 @@ #endif #include "TextIterator.h" #include "VisiblePosition.h" +#include <parser/SourceCode.h> #include <runtime/JSArray.h> #include <runtime/JSLock.h> #include <wtf/Vector.h> @@ -73,6 +72,31 @@ using namespace JSC; namespace WebCore { +static ScriptObject createInjectedScript(const String& source, InjectedScriptHost* injectedScriptHost, ScriptState* scriptState, long id) +{ + SourceCode sourceCode = makeSource(source); + JSLock lock(SilenceAssertionsOnly); + JSDOMGlobalObject* globalObject = static_cast<JSDOMGlobalObject*>(scriptState->lexicalGlobalObject()); + JSValue globalThisValue = scriptState->globalThisValue(); + Completion comp = JSC::evaluate(scriptState, globalObject->globalScopeChain(), sourceCode, globalThisValue); + if (comp.complType() != JSC::Normal && comp.complType() != JSC::ReturnValue) + return ScriptObject(); + JSValue functionValue = comp.value(); + CallData callData; + CallType callType = functionValue.getCallData(callData); + if (callType == CallTypeNone) + return ScriptObject(); + + MarkedArgumentBuffer args; + args.append(toJS(scriptState, globalObject, injectedScriptHost)); + args.append(globalThisValue); + args.append(jsNumber(scriptState, id)); + JSValue result = JSC::call(scriptState, functionValue, callType, callData, globalThisValue, args); + if (result.isObject()) + return ScriptObject(scriptState, result.getObject()); + return ScriptObject(); +} + #if ENABLE(DATABASE) JSValue JSInjectedScriptHost::databaseForId(ExecState* exec, const ArgList& args) { @@ -86,29 +110,10 @@ JSValue JSInjectedScriptHost::databaseForId(ExecState* exec, const ArgList& args Database* database = impl()->databaseForId(args.at(0).toInt32(exec)); if (!database) return jsUndefined(); - // Could use currentWorld(exec) ... but which exec! The following mixed use of exec & inspectedWindow->globalExec() scares me! - JSDOMWindow* inspectedWindow = toJSDOMWindow(ic->inspectedPage()->mainFrame(), debuggerWorld()); - return JSInspectedObjectWrapper::wrap(inspectedWindow->globalExec(), toJS(exec, database)); + return toJS(exec, database); } #endif -JSValue JSInjectedScriptHost::inspectedWindow(ExecState*, const ArgList&) -{ - InspectorController* ic = impl()->inspectorController(); - if (!ic) - return jsUndefined(); - JSDOMWindow* inspectedWindow = toJSDOMWindow(ic->inspectedPage()->mainFrame(), debuggerWorld()); - return JSInspectedObjectWrapper::wrap(inspectedWindow->globalExec(), inspectedWindow); -} - -JSValue JSInjectedScriptHost::wrapCallback(ExecState* exec, const ArgList& args) -{ - if (args.size() < 1) - return jsUndefined(); - - return JSInspectorCallbackWrapper::wrap(exec, args.at(0)); -} - #if ENABLE(JAVASCRIPT_DEBUGGER) JSValue JSInjectedScriptHost::currentCallFrame(ExecState* exec, const ArgList&) @@ -117,11 +122,14 @@ JSValue JSInjectedScriptHost::currentCallFrame(ExecState* exec, const ArgList&) if (!callFrame || !callFrame->isValid()) return jsUndefined(); - // FIXME: I am not sure if this is actually needed. Can we just use exec? - ExecState* globalExec = callFrame->scopeChain()->globalObject->globalExec(); - JSLock lock(SilenceAssertionsOnly); - return JSInspectedObjectWrapper::wrap(globalExec, toJS(exec, callFrame)); + return toJS(exec, callFrame); +} + +JSValue JSInjectedScriptHost::isActivation(ExecState*, const ArgList& args) +{ + JSObject* object = args.at(0).getObject(); + return jsBoolean(object && object->isActivationObject()); } #endif @@ -140,41 +148,21 @@ JSValue JSInjectedScriptHost::nodeForId(ExecState* exec, const ArgList& args) return jsUndefined(); JSLock lock(SilenceAssertionsOnly); - JSDOMWindow* inspectedWindow = toJSDOMWindow(ic->inspectedPage()->mainFrame(), debuggerWorld()); - return JSInspectedObjectWrapper::wrap(inspectedWindow->globalExec(), toJS(exec, deprecatedGlobalObjectForPrototype(inspectedWindow->globalExec()), node)); -} - -JSValue JSInjectedScriptHost::wrapObject(ExecState* exec, const ArgList& args) -{ - if (args.size() < 2) - return jsUndefined(); - - return impl()->wrapObject(ScriptValue(args.at(0)), args.at(1).toString(exec)).jsValue(); -} - -JSValue JSInjectedScriptHost::unwrapObject(ExecState* exec, const ArgList& args) -{ - if (args.size() < 1) - return jsUndefined(); - - return impl()->unwrapObject(args.at(0).toString(exec)).jsValue(); + return toJS(exec, node); } JSValue JSInjectedScriptHost::pushNodePathToFrontend(ExecState* exec, const ArgList& args) { - if (args.size() < 2) + if (args.size() < 3) return jsUndefined(); - JSQuarantinedObjectWrapper* wrapper = JSQuarantinedObjectWrapper::asWrapper(args.at(0)); - if (!wrapper) - return jsUndefined(); - - Node* node = toNode(wrapper->unwrappedObject()); + Node* node = toNode(args.at(0)); if (!node) return jsUndefined(); - bool selectInUI = args.at(1).toBoolean(exec); - return jsNumber(exec, impl()->pushNodePathToFrontend(node, selectInUI)); + bool withChildren = args.at(1).toBoolean(exec); + bool selectInUI = args.at(2).toBoolean(exec); + return jsNumber(exec, impl()->pushNodePathToFrontend(node, withChildren, selectInUI)); } #if ENABLE(DATABASE) @@ -183,11 +171,7 @@ JSValue JSInjectedScriptHost::selectDatabase(ExecState*, const ArgList& args) if (args.size() < 1) return jsUndefined(); - JSQuarantinedObjectWrapper* wrapper = JSQuarantinedObjectWrapper::asWrapper(args.at(0)); - if (!wrapper) - return jsUndefined(); - - Database* database = toDatabase(wrapper->unwrappedObject()); + Database* database = toDatabase(args.at(0)); if (database) impl()->selectDatabase(database); return jsUndefined(); @@ -203,17 +187,29 @@ JSValue JSInjectedScriptHost::selectDOMStorage(ExecState*, const ArgList& args) if (!ic) return jsUndefined(); - JSQuarantinedObjectWrapper* wrapper = JSQuarantinedObjectWrapper::asWrapper(args.at(0)); - if (!wrapper) - return jsUndefined(); - - Storage* storage = toStorage(wrapper->unwrappedObject()); + Storage* storage = toStorage(args.at(0)); if (storage) impl()->selectDOMStorage(storage); return jsUndefined(); } #endif +ScriptObject InjectedScriptHost::injectedScriptFor(ScriptState* scriptState) +{ + JSLock lock(SilenceAssertionsOnly); + JSDOMGlobalObject* globalObject = static_cast<JSDOMGlobalObject*>(scriptState->lexicalGlobalObject()); + JSObject* injectedScript = globalObject->injectedScript(); + if (injectedScript) + return ScriptObject(scriptState, injectedScript); + + ASSERT(!m_injectedScriptSource.isEmpty()); + ScriptObject injectedScriptObject = createInjectedScript(m_injectedScriptSource, this, scriptState, m_nextInjectedScriptId); + globalObject->setInjectedScript(injectedScriptObject.jsObject()); + m_idToInjectedScript.set(m_nextInjectedScriptId, injectedScriptObject); + m_nextInjectedScriptId++; + return injectedScriptObject; +} + } // namespace WebCore #endif // ENABLE(INSPECTOR) diff --git a/WebCore/bindings/js/JSInspectedObjectWrapper.cpp b/WebCore/bindings/js/JSInspectedObjectWrapper.cpp deleted file mode 100644 index 13f59b7..0000000 --- a/WebCore/bindings/js/JSInspectedObjectWrapper.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "JSInspectedObjectWrapper.h" - -#if ENABLE(INSPECTOR) - -#include "JSInspectorCallbackWrapper.h" -#include <runtime/JSGlobalObject.h> -#include <wtf/StdLibExtras.h> - -using namespace JSC; - -namespace WebCore { - -ASSERT_CLASS_FITS_IN_CELL(JSInspectedObjectWrapper); - -typedef HashMap<JSObject*, JSInspectedObjectWrapper*> WrapperMap; -typedef HashMap<JSGlobalObject*, WrapperMap*> GlobalObjectWrapperMap; - -static GlobalObjectWrapperMap& wrappers() -{ - DEFINE_STATIC_LOCAL(GlobalObjectWrapperMap, map, ()); - return map; -} - -const ClassInfo JSInspectedObjectWrapper::s_info = { "JSInspectedObjectWrapper", &JSQuarantinedObjectWrapper::s_info, 0, 0 }; - -JSValue JSInspectedObjectWrapper::wrap(ExecState* unwrappedExec, JSValue unwrappedValue) -{ - if (!unwrappedValue.isObject()) - return unwrappedValue; - - JSObject* unwrappedObject = asObject(unwrappedValue); - - if (unwrappedObject->inherits(&JSInspectedObjectWrapper::s_info)) - return unwrappedObject; - - if (WrapperMap* wrapperMap = wrappers().get(unwrappedExec->lexicalGlobalObject())) - if (JSInspectedObjectWrapper* wrapper = wrapperMap->get(unwrappedObject)) - return wrapper; - - JSValue prototype = unwrappedObject->prototype(); - ASSERT(prototype.isNull() || prototype.isObject()); - - if (prototype.isNull()) - return new (unwrappedExec) JSInspectedObjectWrapper(unwrappedExec, unwrappedObject, JSQuarantinedObjectWrapper::createStructure(jsNull())); - ProtectedJSValue wrappedProto = wrap(unwrappedExec, prototype); - return new (unwrappedExec) JSInspectedObjectWrapper(unwrappedExec, unwrappedObject, JSQuarantinedObjectWrapper::createStructure(asObject(wrappedProto))); -} - -JSInspectedObjectWrapper::JSInspectedObjectWrapper(ExecState* unwrappedExec, JSObject* unwrappedObject, NonNullPassRefPtr<Structure> structure) - : JSQuarantinedObjectWrapper(unwrappedExec, unwrappedObject, structure) -{ - WrapperMap* wrapperMap = wrappers().get(unwrappedGlobalObject()); - if (!wrapperMap) { - wrapperMap = new WrapperMap; - wrappers().set(unwrappedGlobalObject(), wrapperMap); - } - - ASSERT(!wrapperMap->contains(unwrappedObject)); - wrapperMap->set(unwrappedObject, this); -} - -JSInspectedObjectWrapper::~JSInspectedObjectWrapper() -{ - ASSERT(wrappers().contains(unwrappedGlobalObject())); - WrapperMap* wrapperMap = wrappers().get(unwrappedGlobalObject()); - - ASSERT(wrapperMap->contains(unwrappedObject())); - wrapperMap->remove(unwrappedObject()); - - if (wrapperMap->isEmpty()) { - wrappers().remove(unwrappedGlobalObject()); - delete wrapperMap; - } -} - -JSValue JSInspectedObjectWrapper::prepareIncomingValue(ExecState*, JSValue value) const -{ - // The Inspector is only allowed to pass primitive values and wrapped objects to objects from the inspected page. - - if (!value.isObject()) - return value; - - JSQuarantinedObjectWrapper* wrapper = asWrapper(value); - ASSERT_WITH_MESSAGE(wrapper, "Objects passed to JSInspectedObjectWrapper must be wrapped"); - if (!wrapper) - return jsUndefined(); - - if (wrapper->allowsUnwrappedAccessFrom(unwrappedExecState())) { - ASSERT_WITH_MESSAGE(wrapper->inherits(&s_info), "A wrapper contains an object from the inspected page but is not a JSInspectedObjectWrapper"); - if (!wrapper->inherits(&s_info)) - return jsUndefined(); - - // Return the unwrapped object so the inspected page never sees one of its own objects in wrapped form. - return wrapper->unwrappedObject(); - } - - ASSERT_WITH_MESSAGE(wrapper->inherits(&JSInspectorCallbackWrapper::s_info), "A wrapper that was not from the inspected page and is not an Inspector callback was passed to a JSInspectedObjectWrapper"); - if (!wrapper->inherits(&JSInspectorCallbackWrapper::s_info)) - return jsUndefined(); - - return wrapper; -} - -} // namespace WebCore - -#endif // ENABLE(INSPECTOR) diff --git a/WebCore/bindings/js/JSInspectedObjectWrapper.h b/WebCore/bindings/js/JSInspectedObjectWrapper.h deleted file mode 100644 index ad97035..0000000 --- a/WebCore/bindings/js/JSInspectedObjectWrapper.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef JSInspectedObjectWrapper_h -#define JSInspectedObjectWrapper_h - -#include "JSQuarantinedObjectWrapper.h" - -namespace WebCore { - - class JSInspectedObjectWrapper : public JSQuarantinedObjectWrapper { - public: - static JSC::JSValue wrap(JSC::ExecState* unwrappedExec, JSC::JSValue unwrappedValue); - virtual ~JSInspectedObjectWrapper(); - - static const JSC::ClassInfo s_info; - - private: - JSInspectedObjectWrapper(JSC::ExecState* unwrappedExec, JSC::JSObject* unwrappedObject, NonNullPassRefPtr<JSC::Structure>); - - virtual bool allowsGetProperty() const { return true; } - virtual bool allowsSetProperty() const { return true; } - virtual bool allowsDeleteProperty() const { return true; } - virtual bool allowsConstruct() const { return true; } - virtual bool allowsHasInstance() const { return true; } - virtual bool allowsCallAsFunction() const { return true; } - virtual bool allowsGetPropertyNames() const { return true; } - - virtual JSC::JSValue prepareIncomingValue(JSC::ExecState* unwrappedExec, JSC::JSValue unwrappedValue) const; - virtual JSC::JSValue wrapOutgoingValue(JSC::ExecState* unwrappedExec, JSC::JSValue unwrappedValue) const { return wrap(unwrappedExec, unwrappedValue); } - - virtual const JSC::ClassInfo* classInfo() const { return &s_info; } - }; - -} // namespace WebCore - -#endif // JSInspectedObjectWrapper_h diff --git a/WebCore/bindings/js/JSInspectorCallbackWrapper.cpp b/WebCore/bindings/js/JSInspectorCallbackWrapper.cpp deleted file mode 100644 index ff4fbb9..0000000 --- a/WebCore/bindings/js/JSInspectorCallbackWrapper.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "JSInspectorCallbackWrapper.h" - -#if ENABLE(INSPECTOR) - -#include "JSInspectedObjectWrapper.h" -#include <wtf/StdLibExtras.h> - -using namespace JSC; - -namespace WebCore { - -ASSERT_CLASS_FITS_IN_CELL(JSInspectorCallbackWrapper); - -typedef HashMap<JSObject*, JSInspectorCallbackWrapper*> WrapperMap; - -static WrapperMap& wrappers() -{ - DEFINE_STATIC_LOCAL(WrapperMap, map, ()); - return map; -} - -const ClassInfo JSInspectorCallbackWrapper::s_info = { "JSInspectorCallbackWrapper", &JSQuarantinedObjectWrapper::s_info, 0, 0 }; - -static Structure* leakInspectorCallbackWrapperStructure() -{ - Structure::startIgnoringLeaks(); - Structure* structure = JSInspectorCallbackWrapper::createStructure(jsNull()).releaseRef(); - Structure::stopIgnoringLeaks(); - return structure; -} - -JSValue JSInspectorCallbackWrapper::wrap(ExecState* unwrappedExec, JSValue unwrappedValue) -{ - if (!unwrappedValue.isObject()) - return unwrappedValue; - - JSObject* unwrappedObject = asObject(unwrappedValue); - - if (unwrappedObject->inherits(&JSInspectorCallbackWrapper::s_info)) - return unwrappedObject; - - if (JSInspectorCallbackWrapper* wrapper = wrappers().get(unwrappedObject)) - return wrapper; - - JSValue prototype = unwrappedObject->prototype(); - ASSERT(prototype.isNull() || prototype.isObject()); - - if (prototype.isNull()) { - static Structure* structure = leakInspectorCallbackWrapperStructure(); - return new (unwrappedExec) JSInspectorCallbackWrapper(unwrappedExec, unwrappedObject, structure); - } - ProtectedJSValue wrappedProto = wrap(unwrappedExec, prototype); - return new (unwrappedExec) JSInspectorCallbackWrapper(unwrappedExec, unwrappedObject, createStructure(wrappedProto.get())); -} - -JSInspectorCallbackWrapper::JSInspectorCallbackWrapper(ExecState* unwrappedExec, JSObject* unwrappedObject, NonNullPassRefPtr<Structure> structure) - : JSQuarantinedObjectWrapper(unwrappedExec, unwrappedObject, structure) -{ - ASSERT(!wrappers().contains(unwrappedObject)); - wrappers().set(unwrappedObject, this); -} - -JSInspectorCallbackWrapper::~JSInspectorCallbackWrapper() -{ - wrappers().remove(unwrappedObject()); -} - -JSValue JSInspectorCallbackWrapper::prepareIncomingValue(ExecState* unwrappedExec, JSValue unwrappedValue) const -{ - if (JSQuarantinedObjectWrapper* wrapper = asWrapper(unwrappedValue)) { - // The only time a wrapper should be passed into a JSInspectorCallbackWrapper is when a client-side storage callback - // is called. (The client-side storage API calls the callback with the `this` object set to the callback itself.) - ASSERT_WITH_MESSAGE(wrapper == this, "A different wrapper was passed into a JSInspectorCallbackWrapper"); - if (wrapper != this) - return jsUndefined(); - - return wrapper->unwrappedObject(); - } - - // Any value being passed to the Inspector from the inspected page should be wrapped in a JSInspectedObjectWrapper. - return JSInspectedObjectWrapper::wrap(unwrappedExec, unwrappedValue); -} - -} // namespace WebCore - -#endif // ENABLE(INSPECTOR) diff --git a/WebCore/bindings/js/JSInspectorCallbackWrapper.h b/WebCore/bindings/js/JSInspectorCallbackWrapper.h deleted file mode 100644 index be28063..0000000 --- a/WebCore/bindings/js/JSInspectorCallbackWrapper.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef JSInspectorCallbackWrapper_h -#define JSInspectorCallbackWrapper_h - -#include "JSQuarantinedObjectWrapper.h" - -namespace WebCore { - - class JSInspectorCallbackWrapper : public JSQuarantinedObjectWrapper { - public: - static JSC::JSValue wrap(JSC::ExecState* unwrappedExec, JSC::JSValue unwrappedValue); - - virtual ~JSInspectorCallbackWrapper(); - - virtual const JSC::ClassInfo* classInfo() const { return &s_info; } - static const JSC::ClassInfo s_info; - - protected: - JSInspectorCallbackWrapper(JSC::ExecState* unwrappedExec, JSC::JSObject* unwrappedObject, NonNullPassRefPtr<JSC::Structure>); - - virtual bool allowsCallAsFunction() const { return true; } - - virtual JSC::JSValue prepareIncomingValue(JSC::ExecState* unwrappedExec, JSC::JSValue unwrappedValue) const; - virtual JSC::JSValue wrapOutgoingValue(JSC::ExecState* unwrappedExec, JSC::JSValue unwrappedValue) const { return wrap(unwrappedExec, unwrappedValue); } - }; - -} // namespace WebCore - -#endif // JSInspectorCallbackWrapper_h diff --git a/WebCore/bindings/js/JSInspectorFrontendHostCustom.cpp b/WebCore/bindings/js/JSInspectorFrontendHostCustom.cpp index 1970bf7..7b06bac 100644 --- a/WebCore/bindings/js/JSInspectorFrontendHostCustom.cpp +++ b/WebCore/bindings/js/JSInspectorFrontendHostCustom.cpp @@ -36,18 +36,10 @@ #if ENABLE(INSPECTOR) #include "ContextMenuItem.h" -#include "ExceptionCode.h" -#include "Frame.h" #include "InspectorController.h" #include "InspectorFrontendHost.h" #include "JSEvent.h" -#include "JSNode.h" -#include "JSRange.h" #include "MouseEvent.h" -#include "Node.h" -#include "Page.h" -#include "TextIterator.h" -#include "VisiblePosition.h" #include <runtime/JSArray.h> #include <runtime/JSLock.h> #include <runtime/JSObject.h> @@ -57,42 +49,6 @@ using namespace JSC; namespace WebCore { -JSValue JSInspectorFrontendHost::search(ExecState* exec, const ArgList& args) -{ - if (args.size() < 2) - return jsUndefined(); - - Node* node = toNode(args.at(0)); - if (!node) - return jsUndefined(); - - String target = args.at(1).toString(exec); - if (exec->hadException()) - return jsUndefined(); - - MarkedArgumentBuffer result; - RefPtr<Range> searchRange(rangeOfContents(node)); - - ExceptionCode ec = 0; - do { - RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, false)); - if (resultRange->collapsed(ec)) - break; - - // A non-collapsed result range can in some funky whitespace cases still not - // advance the range's start position (4509328). Break to avoid infinite loop. - VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM); - if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM)) - break; - - result.append(toJS(exec, resultRange.get())); - - setStart(searchRange.get(), newStart); - } while (true); - - return constructArray(exec, result); -} - JSValue JSInspectorFrontendHost::showContextMenu(ExecState* execState, const ArgList& args) { if (args.size() < 2) @@ -101,17 +57,17 @@ JSValue JSInspectorFrontendHost::showContextMenu(ExecState* execState, const Arg Event* event = toEvent(args.at(0)); JSArray* array = asArray(args.at(1)); - Vector<ContextMenuItem> items; + Vector<ContextMenuItem*> items; for (size_t i = 0; i < array->length(); ++i) { JSObject* item = asObject(array->getIndex(i)); JSValue label = item->get(execState, Identifier(execState, "label")); JSValue id = item->get(execState, Identifier(execState, "id")); if (label.isUndefined() || id.isUndefined()) - items.append(ContextMenuItem(SeparatorType, ContextMenuItemTagNoAction, String())); + items.append(new ContextMenuItem(SeparatorType, ContextMenuItemTagNoAction, String())); else { ContextMenuAction typedId = static_cast<ContextMenuAction>(ContextMenuItemBaseCustomTag + id.toInt32(execState)); - items.append(ContextMenuItem(ActionType, typedId, label.toString(execState))); + items.append(new ContextMenuItem(ActionType, typedId, label.toString(execState))); } } diff --git a/WebCore/bindings/js/JSJavaScriptCallFrameCustom.cpp b/WebCore/bindings/js/JSJavaScriptCallFrameCustom.cpp index 08ecf2b..afbdf5d 100644 --- a/WebCore/bindings/js/JSJavaScriptCallFrameCustom.cpp +++ b/WebCore/bindings/js/JSJavaScriptCallFrameCustom.cpp @@ -55,9 +55,9 @@ JSValue JSJavaScriptCallFrame::type(ExecState* exec) const { switch (impl()->type()) { case DebuggerCallFrame::FunctionType: - return jsString(exec, "function"); + return jsString(exec, UString("function")); case DebuggerCallFrame::ProgramType: - return jsString(exec, "program"); + return jsString(exec, UString("program")); } ASSERT_NOT_REACHED(); diff --git a/WebCore/bindings/js/JSLazyEventListener.cpp b/WebCore/bindings/js/JSLazyEventListener.cpp index 6d75f4f..b707991 100644 --- a/WebCore/bindings/js/JSLazyEventListener.cpp +++ b/WebCore/bindings/js/JSLazyEventListener.cpp @@ -89,7 +89,7 @@ void JSLazyEventListener::parseCode(ScriptExecutionContext* executionContext) co return; ScriptController* scriptController = frame->script(); - if (!scriptController->isEnabled()) + if (!scriptController->canExecuteScripts()) return; JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(executionContext, m_isolatedWorld.get()); @@ -110,7 +110,7 @@ void JSLazyEventListener::parseCode(ScriptExecutionContext* executionContext) co return; // FIXME: Is this check needed for non-Document contexts? ScriptController* script = frame->script(); - if (!script->isEnabled() || script->isPaused()) + if (!script->canExecuteScripts() || script->isPaused()) return; } diff --git a/WebCore/bindings/js/JSLocationCustom.cpp b/WebCore/bindings/js/JSLocationCustom.cpp index 6c8e032..8599242 100644 --- a/WebCore/bindings/js/JSLocationCustom.cpp +++ b/WebCore/bindings/js/JSLocationCustom.cpp @@ -24,6 +24,7 @@ #include "JSLocationCustom.h" #include "DOMWindow.h" +#include "ExceptionCode.h" #include "Frame.h" #include "FrameLoader.h" #include "JSDOMBinding.h" @@ -168,12 +169,12 @@ bool JSLocation::deleteProperty(ExecState* exec, const Identifier& propertyName) return Base::deleteProperty(exec, propertyName); } -void JSLocation::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSLocation::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { // Only allow the location object to enumerated by frames in the same origin. if (!allowsAccessFromFrame(exec, impl()->frame())) return; - Base::getOwnPropertyNames(exec, propertyNames); + Base::getOwnPropertyNames(exec, propertyNames, mode); } void JSLocation::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes) @@ -214,7 +215,10 @@ void JSLocation::setProtocol(ExecState* exec, JSValue value) ASSERT(frame); KURL url = frame->loader()->url(); - url.setProtocol(value.toString(exec)); + if (!url.setProtocol(value.toString(exec))) { + setDOMException(exec, SYNTAX_ERR); + return; + } navigateIfAllowed(exec, frame, url, !frame->script()->anyPageIsProcessingUserGesture(), false); } diff --git a/WebCore/bindings/js/JSNodeCustom.cpp b/WebCore/bindings/js/JSNodeCustom.cpp index f375ae5..737430e 100644 --- a/WebCore/bindings/js/JSNodeCustom.cpp +++ b/WebCore/bindings/js/JSNodeCustom.cpp @@ -144,7 +144,7 @@ void JSNode::markChildren(MarkStack& markStack) // mark any other nodes. if (node->inDocument()) { if (Document* doc = node->ownerDocument()) - markDOMObjectWrapper(markStack, *Heap::heap(this)->globalData(), doc); + markDOMNodeWrapper(markStack, doc, doc); return; } @@ -154,7 +154,7 @@ void JSNode::markChildren(MarkStack& markStack) Node* outermostNodeWithWrapper = node; for (Node* current = m_impl.get(); current; current = current->parentNode()) { root = current; - if (hasCachedDOMNodeWrapper(current->document(), current)) + if (hasCachedDOMNodeWrapperUnchecked(current->document(), current)) outermostNodeWithWrapper = current; } diff --git a/WebCore/bindings/js/JSPopStateEventCustom.cpp b/WebCore/bindings/js/JSPopStateEventCustom.cpp index ee86a09..3f5fd7e 100644 --- a/WebCore/bindings/js/JSPopStateEventCustom.cpp +++ b/WebCore/bindings/js/JSPopStateEventCustom.cpp @@ -45,13 +45,4 @@ JSValue JSPopStateEvent::initPopStateEvent(ExecState* exec, const ArgList& args) return jsUndefined(); } -JSC::JSValue JSPopStateEvent::state(JSC::ExecState* exec) const -{ - SerializedScriptValue* object = static_cast<PopStateEvent*>(impl())->state(); - if (!object) - return JSC::jsNull(); - - return object->deserialize(exec); -} - } // namespace WebCore diff --git a/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp b/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp deleted file mode 100644 index ea2f72f..0000000 --- a/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "JSQuarantinedObjectWrapper.h" - -#include "JSDOMBinding.h" - -#include <runtime/JSGlobalObject.h> - -using namespace JSC; - -namespace WebCore { - -ASSERT_CLASS_FITS_IN_CELL(JSQuarantinedObjectWrapper); - -const ClassInfo JSQuarantinedObjectWrapper::s_info = { "JSQuarantinedObjectWrapper", 0, 0, 0 }; - -JSQuarantinedObjectWrapper* JSQuarantinedObjectWrapper::asWrapper(JSValue value) -{ - if (!value.isObject()) - return 0; - - JSObject* object = asObject(value); - - if (!object->inherits(&JSQuarantinedObjectWrapper::s_info)) - return 0; - - return static_cast<JSQuarantinedObjectWrapper*>(object); -} - -JSValue JSQuarantinedObjectWrapper::cachedValueGetter(ExecState*, const Identifier&, const PropertySlot& slot) -{ - JSValue v = slot.slotBase(); - ASSERT(v); - return v; -} - -JSQuarantinedObjectWrapper::JSQuarantinedObjectWrapper(ExecState* unwrappedExec, JSObject* unwrappedObject, NonNullPassRefPtr<Structure> structure) - : JSObject(structure) - , m_unwrappedGlobalObject(unwrappedExec->lexicalGlobalObject()) - , m_unwrappedObject(unwrappedObject) -{ - ASSERT_ARG(unwrappedExec, unwrappedExec); - ASSERT_ARG(unwrappedObject, unwrappedObject); - ASSERT(this->structure()); -} - -JSQuarantinedObjectWrapper::~JSQuarantinedObjectWrapper() -{ -} - -bool JSQuarantinedObjectWrapper::allowsUnwrappedAccessFrom(ExecState* exec) const -{ - return m_unwrappedGlobalObject->profileGroup() == exec->lexicalGlobalObject()->profileGroup(); -} - -ExecState* JSQuarantinedObjectWrapper::unwrappedExecState() const -{ - return m_unwrappedGlobalObject->globalExec(); -} - -void JSQuarantinedObjectWrapper::transferExceptionToExecState(ExecState* exec) const -{ - ASSERT(exec != unwrappedExecState()); - - if (!unwrappedExecState()->hadException()) - return; - - JSValue exception = unwrappedExecState()->exception(); - unwrappedExecState()->clearException(); - exec->setException(wrapOutgoingValue(unwrappedExecState(), exception)); -} - -void JSQuarantinedObjectWrapper::markChildren(MarkStack& markStack) -{ - JSObject::markChildren(markStack); - - markStack.append(m_unwrappedObject); - markStack.append(m_unwrappedGlobalObject); -} - -bool JSQuarantinedObjectWrapper::getOwnPropertySlot(ExecState* exec, const Identifier& identifier, PropertySlot& slot) -{ - if (!allowsGetProperty()) { - slot.setUndefined(); - return true; - } - - PropertySlot unwrappedSlot(m_unwrappedObject); - bool result = m_unwrappedObject->getOwnPropertySlot(unwrappedExecState(), identifier, unwrappedSlot); - if (result) { - JSValue unwrappedValue = unwrappedSlot.getValue(unwrappedExecState(), identifier); - slot.setCustom(wrapOutgoingValue(unwrappedExecState(), unwrappedValue), cachedValueGetter); - } - - transferExceptionToExecState(exec); - - return result; -} - -bool JSQuarantinedObjectWrapper::getOwnPropertySlot(ExecState* exec, unsigned identifier, PropertySlot& slot) -{ - if (!allowsGetProperty()) { - slot.setUndefined(); - return true; - } - - PropertySlot unwrappedSlot(m_unwrappedObject); - bool result = m_unwrappedObject->getOwnPropertySlot(unwrappedExecState(), identifier, unwrappedSlot); - if (result) { - JSValue unwrappedValue = unwrappedSlot.getValue(unwrappedExecState(), identifier); - slot.setCustom(wrapOutgoingValue(unwrappedExecState(), unwrappedValue), cachedValueGetter); - } - - transferExceptionToExecState(exec); - - return result; -} - -bool JSQuarantinedObjectWrapper::getOwnPropertyDescriptor(ExecState* exec, const Identifier& identifier, PropertyDescriptor& descriptor) -{ - if (!allowsGetProperty()) { - descriptor.setUndefined(); - return true; - } - - PropertyDescriptor unwrappedDescriptor; - bool result = m_unwrappedObject->getOwnPropertyDescriptor(unwrappedExecState(), identifier, unwrappedDescriptor); - - if (unwrappedDescriptor.isAccessorDescriptor()) { - descriptor.setAccessorDescriptor(wrapOutgoingValue(unwrappedExecState(), unwrappedDescriptor.getter()), - wrapOutgoingValue(unwrappedExecState(), unwrappedDescriptor.setter()), - unwrappedDescriptor.attributes()); - } else - descriptor.setDescriptor(wrapOutgoingValue(unwrappedExecState(), unwrappedDescriptor.value()), unwrappedDescriptor.attributes()); - transferExceptionToExecState(exec); - return result; -} - -void JSQuarantinedObjectWrapper::put(ExecState* exec, const Identifier& identifier, JSValue value, PutPropertySlot& slot) -{ - if (!allowsSetProperty()) - return; - - m_unwrappedObject->put(unwrappedExecState(), identifier, prepareIncomingValue(exec, value), slot); - - transferExceptionToExecState(exec); -} - -void JSQuarantinedObjectWrapper::put(ExecState* exec, unsigned identifier, JSValue value) -{ - if (!allowsSetProperty()) - return; - - m_unwrappedObject->put(unwrappedExecState(), identifier, prepareIncomingValue(exec, value)); - - transferExceptionToExecState(exec); -} - -bool JSQuarantinedObjectWrapper::defineOwnProperty(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool shouldThrow) -{ - if (!allowsSetProperty()) - return false; - - PropertyDescriptor wrappedDescriptor; - if (descriptor.isDataDescriptor()) { - wrappedDescriptor.setValue(prepareIncomingValue(exec, descriptor.value())); - if (wrappedDescriptor.writablePresent()) - wrappedDescriptor.setWritable(descriptor.writable()); - } else if (descriptor.isAccessorDescriptor()) { - if (descriptor.getter()) - wrappedDescriptor.setGetter(prepareIncomingValue(exec, descriptor.getter())); - if (descriptor.setter()) - wrappedDescriptor.setSetter(prepareIncomingValue(exec, descriptor.setter())); - } - if (wrappedDescriptor.enumerablePresent()) - wrappedDescriptor.setEnumerable(descriptor.enumerable()); - if (wrappedDescriptor.configurablePresent()) - wrappedDescriptor.setConfigurable(descriptor.configurable()); - - bool result = m_unwrappedObject->defineOwnProperty(unwrappedExecState(), propertyName, wrappedDescriptor, shouldThrow); - - transferExceptionToExecState(exec); - return result; -} - -bool JSQuarantinedObjectWrapper::deleteProperty(ExecState* exec, const Identifier& identifier) -{ - if (!allowsDeleteProperty()) - return false; - - bool result = m_unwrappedObject->deleteProperty(unwrappedExecState(), identifier); - - transferExceptionToExecState(exec); - - return result; -} - -bool JSQuarantinedObjectWrapper::deleteProperty(ExecState* exec, unsigned identifier) -{ - if (!allowsDeleteProperty()) - return false; - - bool result = m_unwrappedObject->deleteProperty(unwrappedExecState(), identifier); - - transferExceptionToExecState(exec); - - return result; -} - -JSObject* JSQuarantinedObjectWrapper::construct(ExecState* exec, JSObject* constructor, const ArgList& args) -{ - JSQuarantinedObjectWrapper* wrapper = static_cast<JSQuarantinedObjectWrapper*>(constructor); - - MarkedArgumentBuffer preparedArgs; - for (size_t i = 0; i < args.size(); ++i) - preparedArgs.append(wrapper->prepareIncomingValue(exec, args.at(i))); - - // FIXME: Would be nice to find a way to reuse the result of m_unwrappedObject->getConstructData - // from when we called it in JSQuarantinedObjectWrapper::getConstructData. - ConstructData unwrappedConstructData; - ConstructType unwrappedConstructType = wrapper->m_unwrappedObject->getConstructData(unwrappedConstructData); - ASSERT(unwrappedConstructType != ConstructTypeNone); - - JSValue unwrappedResult = JSC::construct(wrapper->unwrappedExecState(), wrapper->m_unwrappedObject, unwrappedConstructType, unwrappedConstructData, preparedArgs); - JSValue resultValue = wrapper->wrapOutgoingValue(wrapper->unwrappedExecState(), unwrappedResult); - ASSERT(resultValue.isObject()); - JSObject* result = asObject(resultValue); - - wrapper->transferExceptionToExecState(exec); - - return result; -} - -ConstructType JSQuarantinedObjectWrapper::getConstructData(ConstructData& constructData) -{ - if (!allowsConstruct()) - return ConstructTypeNone; - ConstructData unwrappedConstructData; - if (m_unwrappedObject->getConstructData(unwrappedConstructData) == ConstructTypeNone) - return ConstructTypeNone; - constructData.native.function = construct; - return ConstructTypeHost; -} - -bool JSQuarantinedObjectWrapper::hasInstance(ExecState* exec, JSValue value, JSValue proto) -{ - if (!allowsHasInstance()) - return false; - - bool result = m_unwrappedObject->hasInstance(unwrappedExecState(), prepareIncomingValue(exec, value), prepareIncomingValue(exec, proto)); - - transferExceptionToExecState(exec); - - return result; -} - -JSValue JSQuarantinedObjectWrapper::call(ExecState* exec, JSObject* function, JSValue thisValue, const ArgList& args) -{ - JSQuarantinedObjectWrapper* wrapper = static_cast<JSQuarantinedObjectWrapper*>(function); - - JSValue preparedThisValue = wrapper->prepareIncomingValue(exec, thisValue); - - MarkedArgumentBuffer preparedArgs; - for (size_t i = 0; i < args.size(); ++i) - preparedArgs.append(wrapper->prepareIncomingValue(exec, args.at(i))); - - // FIXME: Would be nice to find a way to reuse the result of m_unwrappedObject->getCallData - // from when we called it in JSQuarantinedObjectWrapper::getCallData. - CallData unwrappedCallData; - CallType unwrappedCallType = wrapper->m_unwrappedObject->getCallData(unwrappedCallData); - ASSERT(unwrappedCallType != CallTypeNone); - - JSValue unwrappedResult = JSC::call(wrapper->unwrappedExecState(), wrapper->m_unwrappedObject, unwrappedCallType, unwrappedCallData, preparedThisValue, preparedArgs); - JSValue result = wrapper->wrapOutgoingValue(wrapper->unwrappedExecState(), unwrappedResult); - - wrapper->transferExceptionToExecState(exec); - - return result; -} - -CallType JSQuarantinedObjectWrapper::getCallData(CallData& callData) -{ - if (!allowsCallAsFunction()) - return CallTypeNone; - CallData unwrappedCallData; - if (m_unwrappedObject->getCallData(unwrappedCallData) == CallTypeNone) - return CallTypeNone; - callData.native.function = call; - return CallTypeHost; -} - -void JSQuarantinedObjectWrapper::getPropertyNames(ExecState*, PropertyNameArray& array) -{ - if (!allowsGetPropertyNames()) - return; - - m_unwrappedObject->getPropertyNames(unwrappedExecState(), array); -} - -void JSQuarantinedObjectWrapper::getOwnPropertyNames(ExecState*, PropertyNameArray& array) -{ - if (!allowsGetPropertyNames()) - return; - - m_unwrappedObject->getOwnPropertyNames(unwrappedExecState(), array); -} - -} // namespace WebCore diff --git a/WebCore/bindings/js/JSQuarantinedObjectWrapper.h b/WebCore/bindings/js/JSQuarantinedObjectWrapper.h deleted file mode 100644 index 9f62495..0000000 --- a/WebCore/bindings/js/JSQuarantinedObjectWrapper.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef JSQuarantinedObjectWrapper_h -#define JSQuarantinedObjectWrapper_h - -#include <runtime/JSObject.h> - -namespace WebCore { - - class JSQuarantinedObjectWrapper : public JSC::JSObject { - public: - static JSQuarantinedObjectWrapper* asWrapper(JSC::JSValue); - - virtual ~JSQuarantinedObjectWrapper(); - - virtual JSC::JSObject* unwrappedObject() { return m_unwrappedObject; } - - JSC::JSGlobalObject* unwrappedGlobalObject() const { return m_unwrappedGlobalObject; }; - JSC::ExecState* unwrappedExecState() const; - - bool allowsUnwrappedAccessFrom(JSC::ExecState*) const; - - static const JSC::ClassInfo s_info; - - static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue proto) - { - return JSC::Structure::create(proto, JSC::TypeInfo(JSC::ObjectType, StructureFlags)); - } - - protected: - static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::ImplementsHasInstance | JSC::OverridesHasInstance | JSC::OverridesMarkChildren | JSC::OverridesGetPropertyNames | JSC::JSObject::StructureFlags; - - JSQuarantinedObjectWrapper(JSC::ExecState* unwrappedExec, JSC::JSObject* unwrappedObject, NonNullPassRefPtr<JSC::Structure>); - - virtual void markChildren(JSC::MarkStack&); - - private: - virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&); - virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned, JSC::PropertySlot&); - virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&); - - virtual void put(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, JSC::PutPropertySlot&); - virtual void put(JSC::ExecState*, unsigned, JSC::JSValue); - virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&, bool shouldThrow); - - virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&); - virtual bool deleteProperty(JSC::ExecState*, unsigned); - - virtual JSC::CallType getCallData(JSC::CallData&); - virtual JSC::ConstructType getConstructData(JSC::ConstructData&); - - virtual bool hasInstance(JSC::ExecState*, JSC::JSValue, JSC::JSValue proto); - - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); - virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); - - virtual JSC::UString className() const { return m_unwrappedObject->className(); } - - virtual bool allowsGetProperty() const { return false; } - virtual bool allowsSetProperty() const { return false; } - virtual bool allowsDeleteProperty() const { return false; } - virtual bool allowsConstruct() const { return false; } - virtual bool allowsHasInstance() const { return false; } - virtual bool allowsCallAsFunction() const { return false; } - virtual bool allowsGetPropertyNames() const { return false; } - - virtual JSC::JSValue prepareIncomingValue(JSC::ExecState* unwrappedExec, JSC::JSValue unwrappedValue) const = 0; - virtual JSC::JSValue wrapOutgoingValue(JSC::ExecState* unwrappedExec, JSC::JSValue unwrappedValue) const = 0; - - static JSC::JSValue cachedValueGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&); - - void transferExceptionToExecState(JSC::ExecState*) const; - - static JSC::JSValue JSC_HOST_CALL call(JSC::ExecState*, JSC::JSObject* function, JSC::JSValue thisValue, const JSC::ArgList&); - static JSC::JSObject* construct(JSC::ExecState*, JSC::JSObject*, const JSC::ArgList&); - - JSC::JSGlobalObject* m_unwrappedGlobalObject; - JSC::JSObject* m_unwrappedObject; - }; - -} // namespace WebCore - -#endif // JSQuarantinedObjectWrapper_h diff --git a/WebCore/bindings/js/JSSVGContextCache.h b/WebCore/bindings/js/JSSVGContextCache.h new file mode 100644 index 0000000..75ed324 --- /dev/null +++ b/WebCore/bindings/js/JSSVGContextCache.h @@ -0,0 +1,97 @@ +/* + Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef JSSVGContextCache_h +#define JSSVGContextCache_h + +#if ENABLE(SVG) +#include "SVGElement.h" +#include <wtf/StdLibExtras.h> + +namespace WebCore { + +class DOMObject; + +class JSSVGContextCache : public Noncopyable { +public: + typedef HashMap<DOMObject*, SVGElement*> WrapperMap; + + static WrapperMap& wrapperMap() + { + DEFINE_STATIC_LOCAL(WrapperMap, s_wrapperMap, ()); + return s_wrapperMap; + } + + static void addWrapper(DOMObject* wrapper, SVGElement* context) + { + ASSERT(wrapper); + ASSERT(context); + + pair<WrapperMap::iterator, bool> result = wrapperMap().add(wrapper, context); + if (result.second) { + WrapperMap::iterator& it = result.first; + ASSERT_UNUSED(it, it->second == context); + } + } + + static void forgetWrapper(DOMObject* wrapper) + { + ASSERT(wrapper); + + WrapperMap& map = wrapperMap(); + WrapperMap::iterator it = map.find(wrapper); + if (it == map.end()) + return; + + map.remove(it); + } + + static void propagateSVGDOMChange(DOMObject* wrapper, const QualifiedName& attributeName) + { + WrapperMap& map = wrapperMap(); + WrapperMap::iterator it = map.find(wrapper); + if (it == map.end()) + return; + + SVGElement* context = it->second; + ASSERT(context); + + context->svgAttributeChanged(attributeName); + } + + static SVGElement* svgContextForDOMObject(DOMObject* wrapper) + { + ASSERT(wrapper); + + WrapperMap& map = wrapperMap(); + WrapperMap::iterator it = map.find(wrapper); + if (it == map.end()) + return 0; + + SVGElement* context = it->second; + ASSERT(context); + return context; + } + +}; + +} + +#endif +#endif diff --git a/WebCore/bindings/js/JSSVGLengthCustom.cpp b/WebCore/bindings/js/JSSVGLengthCustom.cpp index bad52ae..33bbf30 100644 --- a/WebCore/bindings/js/JSSVGLengthCustom.cpp +++ b/WebCore/bindings/js/JSSVGLengthCustom.cpp @@ -28,18 +28,22 @@ namespace WebCore { JSValue JSSVGLength::value(ExecState* exec) const { - SVGLength imp(*impl()); - return jsNumber(exec, imp.value(context())); + JSSVGPODTypeWrapper<SVGLength>* imp = impl(); + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(const_cast<JSSVGLength*>(this)); + + SVGLength podImp(*imp); + return jsNumber(exec, podImp.value(context)); } JSValue JSSVGLength::convertToSpecifiedUnits(ExecState* exec, const ArgList& args) { - JSSVGPODTypeWrapper<SVGLength>* wrapper = impl(); + JSSVGPODTypeWrapper<SVGLength>* imp = impl(); + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); - SVGLength imp(*wrapper); - imp.convertToSpecifiedUnits(args.at(0).toInt32(exec), context()); + SVGLength podImp(*imp); + podImp.convertToSpecifiedUnits(args.at(0).toInt32(exec), context); - wrapper->commitChange(imp, context()); + imp->commitChange(podImp, this); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSSVGMatrixCustom.cpp b/WebCore/bindings/js/JSSVGMatrixCustom.cpp index a9d0e54..d2d3d6f 100644 --- a/WebCore/bindings/js/JSSVGMatrixCustom.cpp +++ b/WebCore/bindings/js/JSSVGMatrixCustom.cpp @@ -44,15 +44,16 @@ JSValue JSSVGMatrix::multiply(ExecState* exec, const ArgList& args) TransformationMatrix m1(*impl()); TransformationMatrix m2(*(matrixObj->impl())); - JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGStaticPODTypeWrapper<TransformationMatrix>::create(m1.multLeft(m2)).get(), m_context.get()); - - return result; + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); + return toJS(exec, globalObject(), JSSVGStaticPODTypeWrapper<TransformationMatrix>::create(m1.multLeft(m2)).get(), context); } JSValue JSSVGMatrix::inverse(ExecState* exec, const ArgList&) { TransformationMatrix imp(*impl()); - JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGStaticPODTypeWrapper<TransformationMatrix>::create(imp.inverse()).get(), m_context.get()); + + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); + JSValue result = toJS(exec, globalObject(), JSSVGStaticPODTypeWrapper<TransformationMatrix>::create(imp.inverse()).get(), context); if (!imp.isInvertible()) setDOMException(exec, SVGException::SVG_MATRIX_NOT_INVERTABLE); @@ -67,7 +68,8 @@ JSValue JSSVGMatrix::rotateFromVector(ExecState* exec, const ArgList& args) float x = args.at(0).toFloat(exec); float y = args.at(1).toFloat(exec); - JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGStaticPODTypeWrapper<TransformationMatrix>::create(imp.rotateFromVector(x, y)).get(), m_context.get()); + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); + JSValue result = toJS(exec, globalObject(), JSSVGStaticPODTypeWrapper<TransformationMatrix>::create(imp.rotateFromVector(x, y)).get(), context); if (x == 0.0 || y == 0.0) setDOMException(exec, SVGException::SVG_INVALID_VALUE_ERR); diff --git a/WebCore/bindings/js/JSSVGPODListCustom.h b/WebCore/bindings/js/JSSVGPODListCustom.h new file mode 100644 index 0000000..8a0654c --- /dev/null +++ b/WebCore/bindings/js/JSSVGPODListCustom.h @@ -0,0 +1,199 @@ +/* + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef JSSVGPODListCustom_h +#define JSSVGPODListCustom_h + +#include "JSSVGContextCache.h" +#include "JSSVGPODTypeWrapper.h" +#include "SVGList.h" + +namespace WebCore { + +namespace JSSVGPODListCustom { + +// Helper structure only containing public typedefs, as C++ does not allow templatized typedefs +template<typename PODType> +struct JSSVGPODListTraits { + typedef SVGPODListItem<PODType> PODListItem; + typedef SVGList<RefPtr<PODListItem> > PODList; + typedef PODType (*ConversionCallback)(JSC::JSValue); +}; + +template<typename JSPODListType, typename PODType> +static JSC::JSValue finishGetter(JSC::ExecState* exec, ExceptionCode& ec, JSPODListType* wrapper, + PassRefPtr<typename JSSVGPODListTraits<PODType>::PODListItem> item) +{ + if (ec) { + setDOMException(exec, ec); + return JSC::jsUndefined(); + } + + typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); + + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(wrapper); + return toJS(exec, wrapper->globalObject(), + JSSVGPODTypeWrapperCreatorForList<PODType>::create(item.get(), listImp->associatedAttributeName()).get(), context); +} + +template<typename JSPODListType, typename PODType> +static JSC::JSValue finishSetter(JSC::ExecState* exec, ExceptionCode& ec, JSPODListType* wrapper, + PassRefPtr<typename JSSVGPODListTraits<PODType>::PODListItem> item) +{ + if (ec) { + setDOMException(exec, ec); + return JSC::jsUndefined(); + } + + typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); + + const QualifiedName& attributeName = listImp->associatedAttributeName(); + JSSVGContextCache::propagateSVGDOMChange(wrapper, attributeName); + + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(wrapper); + return toJS(exec, wrapper->globalObject(), + JSSVGPODTypeWrapperCreatorForList<PODType>::create(item.get(), attributeName).get(), context); +} + +template<typename JSPODListType, typename PODType> +static JSC::JSValue finishSetterReadOnlyResult(JSC::ExecState* exec, ExceptionCode& ec, JSPODListType* wrapper, + PassRefPtr<typename JSSVGPODListTraits<PODType>::PODListItem> item) +{ + if (ec) { + setDOMException(exec, ec); + return JSC::jsUndefined(); + } + + typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); + JSSVGContextCache::propagateSVGDOMChange(wrapper, listImp->associatedAttributeName()); + return toJS(exec, wrapper->globalObject(), + JSSVGStaticPODTypeWrapper<PODType>::create(*item).get(), 0 /* no context on purpose */); +} + +template<typename JSPODListType, typename PODType> +static JSC::JSValue clear(JSPODListType* wrapper, JSC::ExecState* exec, const JSC::ArgList&, + typename JSSVGPODListTraits<PODType>::ConversionCallback) +{ + ExceptionCode ec = 0; + typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); + listImp->clear(ec); + + if (ec) + setDOMException(exec, ec); + else + JSSVGContextCache::propagateSVGDOMChange(wrapper, listImp->associatedAttributeName()); + + return JSC::jsUndefined(); +} + +template<typename JSPODListType, typename PODType> +static JSC::JSValue initialize(JSPODListType* wrapper, JSC::ExecState* exec, const JSC::ArgList& args, + typename JSSVGPODListTraits<PODType>::ConversionCallback conversion) +{ + ExceptionCode ec = 0; + typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); + return finishSetter<JSPODListType, PODType>(exec, ec, wrapper, + listImp->initialize(JSSVGPODListTraits<PODType>::PODListItem::copy(conversion(args.at(0))), ec)); +} + +template<typename JSPODListType, typename PODType> +static JSC::JSValue getItem(JSPODListType* wrapper, JSC::ExecState* exec, const JSC::ArgList& args, + typename JSSVGPODListTraits<PODType>::ConversionCallback) +{ + bool indexOk = false; + unsigned index = args.at(0).toUInt32(exec, indexOk); + if (!indexOk) { + setDOMException(exec, TYPE_MISMATCH_ERR); + return JSC::jsUndefined(); + } + + ExceptionCode ec = 0; + typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); + return finishGetter<JSPODListType, PODType>(exec, ec, wrapper, + listImp->getItem(index, ec)); +} + +template<typename JSPODListType, typename PODType> +static JSC::JSValue insertItemBefore(JSPODListType* wrapper, JSC::ExecState* exec, const JSC::ArgList& args, + typename JSSVGPODListTraits<PODType>::ConversionCallback conversion) +{ + bool indexOk = false; + unsigned index = args.at(1).toUInt32(exec, indexOk); + if (!indexOk) { + setDOMException(exec, TYPE_MISMATCH_ERR); + return JSC::jsUndefined(); + } + + ExceptionCode ec = 0; + typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); + return finishSetter<JSPODListType, PODType>(exec, ec, wrapper, + listImp->insertItemBefore(JSSVGPODListTraits<PODType>::PODListItem::copy(conversion(args.at(0))), index, ec)); +} + +template<typename JSPODListType, typename PODType> +static JSC::JSValue replaceItem(JSPODListType* wrapper, JSC::ExecState* exec, const JSC::ArgList& args, + typename JSSVGPODListTraits<PODType>::ConversionCallback conversion) +{ + bool indexOk = false; + unsigned index = args.at(1).toUInt32(exec, indexOk); + if (!indexOk) { + setDOMException(exec, TYPE_MISMATCH_ERR); + return JSC::jsUndefined(); + } + + ExceptionCode ec = 0; + typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); + return finishSetter<JSPODListType, PODType>(exec, ec, wrapper, + listImp->replaceItem(JSSVGPODListTraits<PODType>::PODListItem::copy(conversion(args.at(0))), index, ec)); +} + +template<typename JSPODListType, typename PODType> +static JSC::JSValue removeItem(JSPODListType* wrapper, JSC::ExecState* exec, const JSC::ArgList& args, + typename JSSVGPODListTraits<PODType>::ConversionCallback) +{ + bool indexOk = false; + unsigned index = args.at(0).toUInt32(exec, indexOk); + if (!indexOk) { + setDOMException(exec, TYPE_MISMATCH_ERR); + return JSC::jsUndefined(); + } + + ExceptionCode ec = 0; + typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); + return finishSetterReadOnlyResult<JSPODListType, PODType>(exec, ec, wrapper, + listImp->removeItem(index, ec)); +} + +template<typename JSPODListType, typename PODType> +static JSC::JSValue appendItem(JSPODListType* wrapper, JSC::ExecState* exec, const JSC::ArgList& args, + typename JSSVGPODListTraits<PODType>::ConversionCallback conversion) +{ + ExceptionCode ec = 0; + typename JSSVGPODListTraits<PODType>::PODList* listImp = wrapper->impl(); + return finishSetter<JSPODListType, PODType>(exec, ec, wrapper, + listImp->appendItem(JSSVGPODListTraits<PODType>::PODListItem::copy(conversion(args.at(0))), ec)); +} + +} + +} + +#endif diff --git a/WebCore/bindings/js/JSSVGPODTypeWrapper.h b/WebCore/bindings/js/JSSVGPODTypeWrapper.h index 51e4e9e..7c04f22 100644 --- a/WebCore/bindings/js/JSSVGPODTypeWrapper.h +++ b/WebCore/bindings/js/JSSVGPODTypeWrapper.h @@ -28,25 +28,28 @@ #define JSSVGPODTypeWrapper_h #if ENABLE(SVG) +#include "JSSVGContextCache.h" #include "SVGElement.h" #include <wtf/StdLibExtras.h> namespace WebCore { +class DOMObject; + template<typename PODType> class JSSVGPODTypeWrapper : public RefCounted<JSSVGPODTypeWrapper<PODType> > { public: virtual ~JSSVGPODTypeWrapper() { } virtual operator PODType() = 0; - virtual void commitChange(PODType, SVGElement*) = 0; + virtual void commitChange(PODType, DOMObject*) = 0; }; // This file contains JS wrapper objects for SVG datatypes, that are passed around by value // in WebCore/svg (aka. 'POD types'). For instance SVGMatrix is mapped to TransformationMatrix, and // passed around as const reference. SVG DOM demands these objects to be "live", changes to any // of the writable attributes of SVGMatrix need to be reflected in the object which exposed the -// SVGMatrix object (ie. 'someElement.transform.matrix.a = 50.0', in that case 'SVGTransform'). +// SVGMatrix object (i.e. 'someElement.transform.matrix.a = 50.0', in that case 'SVGTransform'). // The SVGTransform class stores its "TransformationMatrix m_matrix" object on the stack. If it would // be stored as pointer we could just build an auto-generated JSSVG* wrapper object around it // and all changes to that object would automatically affect the TransformationMatrix* object stored @@ -68,13 +71,13 @@ public: // GetterMethod and SetterMethod are each 12 bytes. We have to pack to a size // greater than or equal to that to avoid an alignment warning (C4121). 16 is // the next-largest size allowed for packing, so we use that. -#pragma pack(16) +#pragma pack(push, 16) #endif template<typename PODType, typename PODTypeCreator> class JSSVGDynamicPODTypeWrapper : public JSSVGPODTypeWrapper<PODType> { public: typedef PODType (PODTypeCreator::*GetterMethod)() const; - typedef void (PODTypeCreator::*SetterMethod)(PODType); + typedef void (PODTypeCreator::*SetterMethod)(const PODType&); static PassRefPtr<JSSVGDynamicPODTypeWrapper> create(PassRefPtr<PODTypeCreator> creator, GetterMethod getter, SetterMethod setter) { @@ -86,12 +89,10 @@ public: return (m_creator.get()->*m_getter)(); } - virtual void commitChange(PODType type, SVGElement* context) + virtual void commitChange(PODType type, DOMObject* wrapper) { (m_creator.get()->*m_setter)(type); - - if (context) - context->svgAttributeChanged(m_creator->associatedAttributeName()); + JSSVGContextCache::propagateSVGDOMChange(wrapper, m_creator->associatedAttributeName()); } private: @@ -105,15 +106,20 @@ private: ASSERT(m_setter); } + virtual ~JSSVGDynamicPODTypeWrapper(); + // Update callbacks RefPtr<PODTypeCreator> m_creator; GetterMethod m_getter; SetterMethod m_setter; }; +#if COMPILER(MSVC) +#pragma pack(pop) +#endif -// Represents a JS wrapper object for SVG POD types (not for SVGAnimated* clases). Any modification to the SVG POD +// Represents a JS wrapper object for SVG POD types (not for SVGAnimated* classes). Any modification to the SVG POD // types don't cause any updates unlike JSSVGDynamicPODTypeWrapper. This class is used for return values (ie. getBBox()) -// and for properties where SVG specification explicitely states, that the contents of the POD type are immutable. +// and for properties where SVG specification explicitly states, that the contents of the POD type are immutable. template<typename PODType> class JSSVGStaticPODTypeWrapper : public JSSVGPODTypeWrapper<PODType> { @@ -128,7 +134,7 @@ public: return m_podType; } - virtual void commitChange(PODType type, SVGElement*) + virtual void commitChange(PODType type, DOMObject*) { m_podType = type; } @@ -152,10 +158,10 @@ public: return adoptRef(new JSSVGStaticPODTypeWrapperWithPODTypeParent(type, parent)); } - virtual void commitChange(PODType type, SVGElement* context) + virtual void commitChange(PODType type, DOMObject* wrapper) { - JSSVGStaticPODTypeWrapper<PODType>::commitChange(type, context); - m_parentType->commitChange(ParentTypeArg(type), context); + JSSVGStaticPODTypeWrapper<PODType>::commitChange(type, wrapper); + m_parentType->commitChange(ParentTypeArg(type), wrapper); } private: @@ -172,7 +178,7 @@ private: // GetterMethod and SetterMethod are each 12 bytes. We have to pack to a size // greater than or equal to that to avoid an alignment warning (C4121). 16 is // the next-largest size allowed for packing, so we use that. -#pragma pack(16) +#pragma pack(push, 16) #endif template<typename PODType, typename ParentType> class JSSVGStaticPODTypeWrapperWithParent : public JSSVGPODTypeWrapper<PODType> { @@ -190,7 +196,7 @@ public: return (m_parent.get()->*m_getter)(); } - virtual void commitChange(PODType type, SVGElement*) + virtual void commitChange(PODType type, DOMObject*) { (m_parent.get()->*m_setter)(type); } @@ -223,7 +229,7 @@ public: typedef SVGPODListItem<PODType> PODListItemPtrType; typedef PODType (SVGPODListItem<PODType>::*GetterMethod)() const; - typedef void (SVGPODListItem<PODType>::*SetterMethod)(PODType); + typedef void (SVGPODListItem<PODType>::*SetterMethod)(const PODType&); static PassRefPtr<JSSVGPODTypeWrapperCreatorForList> create(PassRefPtr<PODListItemPtrType> creator, const QualifiedName& attributeName) { @@ -235,15 +241,13 @@ public: return (m_creator.get()->*m_getter)(); } - virtual void commitChange(PODType type, SVGElement* context) + virtual void commitChange(PODType type, DOMObject* wrapper) { if (!m_setter) return; (m_creator.get()->*m_setter)(type); - - if (context) - context->svgAttributeChanged(m_associatedAttributeName); + JSSVGContextCache::propagateSVGDOMChange(wrapper, m_associatedAttributeName); } private: @@ -269,7 +273,7 @@ private: template<typename PODType, typename PODTypeCreator> struct PODTypeWrapperCacheInfo { typedef PODType (PODTypeCreator::*GetterMethod)() const; - typedef void (PODTypeCreator::*SetterMethod)(PODType); + typedef void (PODTypeCreator::*SetterMethod)(const PODType&); // Empty value PODTypeWrapperCacheInfo() @@ -309,6 +313,9 @@ struct PODTypeWrapperCacheInfo { GetterMethod getter; SetterMethod setter; }; +#if COMPILER(MSVC) +#pragma pack(pop) +#endif template<typename PODType, typename PODTypeCreator> struct PODTypeWrapperCacheInfoHash { @@ -351,60 +358,53 @@ struct PODTypeWrapperCacheInfoTraits : WTF::GenericHashTraits<PODTypeWrapperCach } }; +// Used for dynamic read-write attributes template<typename PODType, typename PODTypeCreator> class JSSVGDynamicPODTypeWrapperCache { public: typedef PODType (PODTypeCreator::*GetterMethod)() const; - typedef void (PODTypeCreator::*SetterMethod)(PODType); + typedef void (PODTypeCreator::*SetterMethod)(const PODType&); typedef PODTypeWrapperCacheInfo<PODType, PODTypeCreator> CacheInfo; typedef PODTypeWrapperCacheInfoHash<PODType, PODTypeCreator> CacheInfoHash; typedef PODTypeWrapperCacheInfoTraits<PODType, PODTypeCreator> CacheInfoTraits; typedef JSSVGPODTypeWrapper<PODType> WrapperBase; - typedef JSSVGDynamicPODTypeWrapper<PODType, PODTypeCreator> DynamicWrapper; - typedef HashMap<CacheInfo, DynamicWrapper*, CacheInfoHash, CacheInfoTraits> DynamicWrapperHashMap; - typedef typename DynamicWrapperHashMap::const_iterator DynamicWrapperHashMapIterator; + typedef JSSVGDynamicPODTypeWrapper<PODType, PODTypeCreator> Wrapper; + typedef HashMap<CacheInfo, Wrapper*, CacheInfoHash, CacheInfoTraits> WrapperMap; - static DynamicWrapperHashMap& dynamicWrapperHashMap() + static WrapperMap& wrapperMap() { - DEFINE_STATIC_LOCAL(DynamicWrapperHashMap, s_dynamicWrapperHashMap, ()); - return s_dynamicWrapperHashMap; + DEFINE_STATIC_LOCAL(WrapperMap, s_wrapperMap, ()); + return s_wrapperMap; } - // Used for readwrite attributes only static PassRefPtr<WrapperBase> lookupOrCreateWrapper(PODTypeCreator* creator, GetterMethod getter, SetterMethod setter) { - DynamicWrapperHashMap& map(dynamicWrapperHashMap()); CacheInfo info(creator, getter, setter); + pair<typename WrapperMap::iterator, bool> result = wrapperMap().add(info, 0); + if (!result.second) // pre-existing entry + return result.first->second; - if (map.contains(info)) - return map.get(info); - - RefPtr<DynamicWrapper> wrapper = DynamicWrapper::create(creator, getter, setter); - map.set(info, wrapper.get()); + RefPtr<Wrapper> wrapper = Wrapper::create(creator, getter, setter); + result.first->second = wrapper.get(); return wrapper.release(); } - static void forgetWrapper(WrapperBase* wrapper) + static void forgetWrapper(PODTypeCreator* creator, GetterMethod getter, SetterMethod setter) { - DynamicWrapperHashMap& map(dynamicWrapperHashMap()); - - DynamicWrapperHashMapIterator it = map.begin(); - DynamicWrapperHashMapIterator end = map.end(); - - for (; it != end; ++it) { - if (it->second != wrapper) - continue; - - // It's guaranteed that there's just one object we need to take care of. - map.remove(it->first); - break; - } + CacheInfo info(creator, getter, setter); + wrapperMap().remove(info); } }; -}; +template<typename PODType, typename PODTypeCreator> +JSSVGDynamicPODTypeWrapper<PODType, PODTypeCreator>::~JSSVGDynamicPODTypeWrapper() +{ + JSSVGDynamicPODTypeWrapperCache<PODType, PODTypeCreator>::forgetWrapper(m_creator.get(), m_getter, m_setter); +} + +} // namespace WebCore #endif // ENABLE(SVG) #endif // JSSVGPODTypeWrapper_h diff --git a/WebCore/bindings/js/JSSVGPathSegCustom.cpp b/WebCore/bindings/js/JSSVGPathSegCustom.cpp index d5be3fd..eac2c4b 100644 --- a/WebCore/bindings/js/JSSVGPathSegCustom.cpp +++ b/WebCore/bindings/js/JSSVGPathSegCustom.cpp @@ -21,6 +21,8 @@ #if ENABLE(SVG) #include "JSSVGPathSeg.h" + +#include "JSDOMBinding.h" #include "JSSVGPathSegArcAbs.h" #include "JSSVGPathSegArcRel.h" #include "JSSVGPathSegClosePath.h" @@ -40,9 +42,6 @@ #include "JSSVGPathSegLinetoVerticalRel.h" #include "JSSVGPathSegMovetoAbs.h" #include "JSSVGPathSegMovetoRel.h" - -#include "JSDOMBinding.h" - #include "SVGPathSeg.h" #include "SVGPathSegArc.h" #include "SVGPathSegClosePath.h" @@ -64,8 +63,10 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, SVGPathSeg* objec if (!object) return jsNull(); - if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec, object)) + if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec, object)) { + ASSERT(JSSVGContextCache::svgContextForDOMObject(wrapper) == context); return wrapper; + } switch (object->pathSegType()) { case SVGPathSeg::PATHSEG_CLOSEPATH: @@ -115,5 +116,3 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, SVGPathSeg* objec } #endif // ENABLE(SVG) - -// vim:ts=4:noet diff --git a/WebCore/bindings/js/JSSVGPathSegListCustom.cpp b/WebCore/bindings/js/JSSVGPathSegListCustom.cpp index b71f3a6..4831727 100644 --- a/WebCore/bindings/js/JSSVGPathSegListCustom.cpp +++ b/WebCore/bindings/js/JSSVGPathSegListCustom.cpp @@ -24,6 +24,7 @@ #include "Document.h" #include "Frame.h" +#include "JSSVGContextCache.h" #include "JSSVGPathSeg.h" #include "SVGDocumentExtensions.h" #include "SVGElement.h" @@ -39,12 +40,12 @@ JSValue JSSVGPathSegList::clear(ExecState* exec, const ArgList&) { ExceptionCode ec = 0; - SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl()); - imp->clear(ec); + SVGPathSegList* list = impl(); + list->clear(ec); setDOMException(exec, ec); - m_context->svgAttributeChanged(imp->associatedAttributeName()); + JSSVGContextCache::propagateSVGDOMChange(this, list->associatedAttributeName()); return jsUndefined(); } @@ -53,14 +54,15 @@ JSValue JSSVGPathSegList::initialize(ExecState* exec, const ArgList& args) ExceptionCode ec = 0; SVGPathSeg* newItem = toSVGPathSeg(args.at(0)); - SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl()); + SVGPathSegList* list = impl(); - SVGPathSeg* obj = WTF::getPtr(imp->initialize(newItem, ec)); + SVGPathSeg* obj = WTF::getPtr(list->initialize(newItem, ec)); + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); - JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), obj, m_context.get()); + JSValue result = toJS(exec, globalObject(), obj, context); setDOMException(exec, ec); - m_context->svgAttributeChanged(imp->associatedAttributeName()); + JSSVGContextCache::propagateSVGDOMChange(this, list->associatedAttributeName()); return result; } @@ -75,10 +77,11 @@ JSValue JSSVGPathSegList::getItem(ExecState* exec, const ArgList& args) return jsUndefined(); } - SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl()); - SVGPathSeg* obj = WTF::getPtr(imp->getItem(index, ec)); + SVGPathSegList* list = impl(); + SVGPathSeg* obj = WTF::getPtr(list->getItem(index, ec)); + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); - JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), obj, m_context.get()); + JSValue result = toJS(exec, globalObject(), obj, context); setDOMException(exec, ec); return result; } @@ -95,12 +98,13 @@ JSValue JSSVGPathSegList::insertItemBefore(ExecState* exec, const ArgList& args) return jsUndefined(); } - SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl()); + SVGPathSegList* list = impl(); + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); - JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), WTF::getPtr(imp->insertItemBefore(newItem, index, ec)), m_context.get()); + JSValue result = toJS(exec, globalObject(), WTF::getPtr(list->insertItemBefore(newItem, index, ec)), context); setDOMException(exec, ec); - m_context->svgAttributeChanged(imp->associatedAttributeName()); + JSSVGContextCache::propagateSVGDOMChange(this, list->associatedAttributeName()); return result; } @@ -116,12 +120,13 @@ JSValue JSSVGPathSegList::replaceItem(ExecState* exec, const ArgList& args) return jsUndefined(); } - SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl()); + SVGPathSegList* list = impl(); + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); - JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), WTF::getPtr(imp->replaceItem(newItem, index, ec)), m_context.get()); + JSValue result = toJS(exec, globalObject(), WTF::getPtr(list->replaceItem(newItem, index, ec)), context); setDOMException(exec, ec); - m_context->svgAttributeChanged(imp->associatedAttributeName()); + JSSVGContextCache::propagateSVGDOMChange(this, list->associatedAttributeName()); return result; } @@ -136,14 +141,15 @@ JSValue JSSVGPathSegList::removeItem(ExecState* exec, const ArgList& args) return jsUndefined(); } - SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl()); + SVGPathSegList* list = impl(); - RefPtr<SVGPathSeg> obj(imp->removeItem(index, ec)); + RefPtr<SVGPathSeg> obj(list->removeItem(index, ec)); + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); - JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), obj.get(), m_context.get()); + JSValue result = toJS(exec, globalObject(), obj.get(), context); setDOMException(exec, ec); - m_context->svgAttributeChanged(imp->associatedAttributeName()); + JSSVGContextCache::propagateSVGDOMChange(this, list->associatedAttributeName()); return result; } @@ -152,12 +158,13 @@ JSValue JSSVGPathSegList::appendItem(ExecState* exec, const ArgList& args) ExceptionCode ec = 0; SVGPathSeg* newItem = toSVGPathSeg(args.at(0)); - SVGPathSegList* imp = static_cast<SVGPathSegList*>(impl()); + SVGPathSegList* list = impl(); + SVGElement* context = JSSVGContextCache::svgContextForDOMObject(this); - JSC::JSValue result = toJS(exec, deprecatedGlobalObjectForPrototype(exec), WTF::getPtr(imp->appendItem(newItem, ec)), m_context.get()); + JSValue result = toJS(exec, globalObject(), WTF::getPtr(list->appendItem(newItem, ec)), context); setDOMException(exec, ec); - m_context->svgAttributeChanged(imp->associatedAttributeName()); + JSSVGContextCache::propagateSVGDOMChange(this, list->associatedAttributeName()); return result; } diff --git a/WebCore/bindings/js/JSSVGPointListCustom.cpp b/WebCore/bindings/js/JSSVGPointListCustom.cpp deleted file mode 100644 index 1969fe2..0000000 --- a/WebCore/bindings/js/JSSVGPointListCustom.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#if ENABLE(SVG) -#include "JSSVGPointList.h" - -#include "JSSVGPoint.h" -#include "SVGPointList.h" - -using namespace JSC; - -namespace WebCore { - -typedef SVGPODListItem<FloatPoint> PODListItem; -typedef SVGList<RefPtr<PODListItem> > SVGPointListBase; - -static JSValue finishGetter(ExecState* exec, ExceptionCode& ec, SVGElement* context, SVGPointList* list, PassRefPtr<PODListItem > item) -{ - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } - return toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGPODTypeWrapperCreatorForList<FloatPoint>::create(item.get(), list->associatedAttributeName()).get(), context); -} - -static JSValue finishSetter(ExecState* exec, ExceptionCode& ec, SVGElement* context, SVGPointList* list, PassRefPtr<PODListItem > item) -{ - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } - const QualifiedName& attributeName = list->associatedAttributeName(); - context->svgAttributeChanged(attributeName); - return toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGPODTypeWrapperCreatorForList<FloatPoint>::create(item.get(), attributeName).get(), context); -} - -static JSValue finishSetterReadOnlyResult(ExecState* exec, ExceptionCode& ec, SVGElement* context, SVGPointList* list, PassRefPtr<PODListItem> item) -{ - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } - context->svgAttributeChanged(list->associatedAttributeName()); - return toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGStaticPODTypeWrapper<FloatPoint>::create(*item).get(), context); -} - -JSValue JSSVGPointList::clear(ExecState* exec, const ArgList&) -{ - ExceptionCode ec = 0; - impl()->clear(ec); - setDOMException(exec, ec); - m_context->svgAttributeChanged(impl()->associatedAttributeName()); - return jsUndefined(); -} - -JSValue JSSVGPointList::initialize(ExecState* exec, const ArgList& args) -{ - ExceptionCode ec = 0; - SVGPointListBase* listImp = impl(); - return finishSetter(exec, ec, context(), impl(), - listImp->initialize(PODListItem::copy(toSVGPoint(args.at(0))), ec)); -} - -JSValue JSSVGPointList::getItem(ExecState* exec, const ArgList& args) -{ - bool indexOk; - unsigned index = args.at(0).toUInt32(exec, indexOk); - if (!indexOk) { - setDOMException(exec, TYPE_MISMATCH_ERR); - return jsUndefined(); - } - - ExceptionCode ec = 0; - SVGPointListBase* listImp = impl(); - return finishGetter(exec, ec, context(), impl(), - listImp->getItem(index, ec)); -} - -JSValue JSSVGPointList::insertItemBefore(ExecState* exec, const ArgList& args) -{ - bool indexOk; - unsigned index = args.at(1).toUInt32(exec, indexOk); - if (!indexOk) { - setDOMException(exec, TYPE_MISMATCH_ERR); - return jsUndefined(); - } - - ExceptionCode ec = 0; - SVGPointListBase* listImp = impl(); - return finishSetter(exec, ec, context(), impl(), - listImp->insertItemBefore(PODListItem::copy(toSVGPoint(args.at(0))), index, ec)); -} - -JSValue JSSVGPointList::replaceItem(ExecState* exec, const ArgList& args) -{ - bool indexOk; - unsigned index = args.at(1).toInt32(exec, indexOk); - if (!indexOk) { - setDOMException(exec, TYPE_MISMATCH_ERR); - return jsUndefined(); - } - - ExceptionCode ec = 0; - SVGPointListBase* listImp = impl(); - return finishSetter(exec, ec, context(), impl(), - listImp->replaceItem(PODListItem::copy(toSVGPoint(args.at(0))), index, ec)); -} - -JSValue JSSVGPointList::removeItem(ExecState* exec, const ArgList& args) -{ - bool indexOk; - unsigned index = args.at(0).toInt32(exec, indexOk); - if (!indexOk) { - setDOMException(exec, TYPE_MISMATCH_ERR); - return jsUndefined(); - } - - ExceptionCode ec = 0; - SVGPointListBase* listImp = impl(); - return finishSetterReadOnlyResult(exec, ec, context(), impl(), - listImp->removeItem(index, ec)); -} - -JSValue JSSVGPointList::appendItem(ExecState* exec, const ArgList& args) -{ - ExceptionCode ec = 0; - SVGPointListBase* listImp = impl(); - return finishSetter(exec, ec, context(), impl(), - listImp->appendItem(PODListItem::copy(toSVGPoint(args.at(0))), ec)); -} - -} - -#endif // ENABLE(SVG) diff --git a/WebCore/bindings/js/JSSVGTransformListCustom.cpp b/WebCore/bindings/js/JSSVGTransformListCustom.cpp deleted file mode 100644 index 1a9110a..0000000 --- a/WebCore/bindings/js/JSSVGTransformListCustom.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#if ENABLE(SVG) -#include "JSSVGTransformList.h" - -#include "JSSVGTransform.h" -#include "SVGTransformList.h" - -using namespace JSC; - -namespace WebCore { - -typedef SVGPODListItem<SVGTransform> PODListItem; -typedef SVGList<RefPtr<PODListItem> > SVGTransformListBase; - -static JSValue finishGetter(ExecState* exec, ExceptionCode& ec, SVGElement* context, SVGTransformList* list, PassRefPtr<PODListItem> item) -{ - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } - return toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGPODTypeWrapperCreatorForList<SVGTransform>::create(item.get(), list->associatedAttributeName()).get(), context); -} - -static JSValue finishSetter(ExecState* exec, ExceptionCode& ec, SVGElement* context, SVGTransformList* list, PassRefPtr<PODListItem> item) -{ - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } - const QualifiedName& attributeName = list->associatedAttributeName(); - context->svgAttributeChanged(attributeName); - return toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGPODTypeWrapperCreatorForList<SVGTransform>::create(item.get(), attributeName).get(), context); -} - -static JSValue finishSetterReadOnlyResult(ExecState* exec, ExceptionCode& ec, SVGElement* context, SVGTransformList* list, PassRefPtr<PODListItem> item) -{ - if (ec) { - setDOMException(exec, ec); - return jsUndefined(); - } - context->svgAttributeChanged(list->associatedAttributeName()); - return toJS(exec, deprecatedGlobalObjectForPrototype(exec), JSSVGStaticPODTypeWrapper<SVGTransform>::create(*item).get(), context); -} - -JSValue JSSVGTransformList::clear(ExecState* exec, const ArgList&) -{ - ExceptionCode ec = 0; - impl()->clear(ec); - setDOMException(exec, ec); - m_context->svgAttributeChanged(impl()->associatedAttributeName()); - return jsUndefined(); -} - -JSValue JSSVGTransformList::initialize(ExecState* exec, const ArgList& args) -{ - ExceptionCode ec = 0; - SVGTransformListBase* listImp = impl(); - return finishSetter(exec, ec, context(), impl(), - listImp->initialize(PODListItem::copy(toSVGTransform(args.at(0))), ec)); -} - -JSValue JSSVGTransformList::getItem(ExecState* exec, const ArgList& args) -{ - bool indexOk; - unsigned index = args.at(0).toUInt32(exec, indexOk); - if (!indexOk) { - setDOMException(exec, TYPE_MISMATCH_ERR); - return jsUndefined(); - } - - ExceptionCode ec = 0; - SVGTransformListBase* listImp = impl(); - return finishGetter(exec, ec, context(), impl(), - listImp->getItem(index, ec)); -} - -JSValue JSSVGTransformList::insertItemBefore(ExecState* exec, const ArgList& args) -{ - bool indexOk; - unsigned index = args.at(1).toUInt32(exec, indexOk); - if (!indexOk) { - setDOMException(exec, TYPE_MISMATCH_ERR); - return jsUndefined(); - } - - ExceptionCode ec = 0; - SVGTransformListBase* listImp = impl(); - return finishSetter(exec, ec, context(), impl(), - listImp->insertItemBefore(PODListItem::copy(toSVGTransform(args.at(0))), index, ec)); -} - -JSValue JSSVGTransformList::replaceItem(ExecState* exec, const ArgList& args) -{ - bool indexOk; - unsigned index = args.at(1).toUInt32(exec, indexOk); - if (!indexOk) { - setDOMException(exec, TYPE_MISMATCH_ERR); - return jsUndefined(); - } - - ExceptionCode ec = 0; - SVGTransformListBase* listImp = impl(); - return finishSetter(exec, ec, context(), impl(), - listImp->replaceItem(PODListItem::copy(toSVGTransform(args.at(0))), index, ec)); -} - -JSValue JSSVGTransformList::removeItem(ExecState* exec, const ArgList& args) -{ - bool indexOk; - unsigned index = args.at(0).toUInt32(exec, indexOk); - if (!indexOk) { - setDOMException(exec, TYPE_MISMATCH_ERR); - return jsUndefined(); - } - - ExceptionCode ec = 0; - SVGTransformListBase* listImp = impl(); - return finishSetterReadOnlyResult(exec, ec, context(), impl(), - listImp->removeItem(index, ec)); -} - -JSValue JSSVGTransformList::appendItem(ExecState* exec, const ArgList& args) -{ - ExceptionCode ec = 0; - SVGTransformListBase* listImp = impl(); - return finishSetter(exec, ec, context(), impl(), - listImp->appendItem(PODListItem::copy(toSVGTransform(args.at(0))), ec)); -} - -} - -#endif // ENABLE(SVG) diff --git a/WebCore/bindings/js/JSStorageCustom.cpp b/WebCore/bindings/js/JSStorageCustom.cpp index e416d35..3cfe22e 100644 --- a/WebCore/bindings/js/JSStorageCustom.cpp +++ b/WebCore/bindings/js/JSStorageCustom.cpp @@ -64,13 +64,13 @@ bool JSStorage::deleteProperty(ExecState* exec, const Identifier& propertyName) return true; } -void JSStorage::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSStorage::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { unsigned length = m_impl->length(); for (unsigned i = 0; i < length; ++i) propertyNames.add(Identifier(exec, m_impl->key(i))); - Base::getOwnPropertyNames(exec, propertyNames); + Base::getOwnPropertyNames(exec, propertyNames, mode); } bool JSStorage::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot&) diff --git a/WebCore/bindings/js/JSWebGLArrayHelper.h b/WebCore/bindings/js/JSWebGLArrayHelper.h index f538cce..3326d76 100644 --- a/WebCore/bindings/js/JSWebGLArrayHelper.h +++ b/WebCore/bindings/js/JSWebGLArrayHelper.h @@ -27,6 +27,8 @@ #ifndef JSWebGLArrayHelper_h #define JSWebGLArrayHelper_h +#include "ExceptionCode.h" +#include "JSDOMBinding.h" #include <interpreter/CallFrame.h> #include <runtime/ArgList.h> #include <runtime/Error.h> @@ -45,11 +47,15 @@ JSC::JSValue setWebGLArrayFromArray(JSC::ExecState* exec, T* webGLArray, JSC::Ar if (args.size() == 2) offset = args.at(1).toInt32(exec); int length = array->get(exec, JSC::Identifier(exec, "length")).toInt32(exec); - for (int i = 0; i < length; i++) { - JSC::JSValue v = array->get(exec, i); - if (exec->hadException()) - return JSC::jsUndefined(); - webGLArray->set(i + offset, v.toNumber(exec)); + if (offset + length > webGLArray->length()) + setDOMException(exec, INDEX_SIZE_ERR); + else { + for (int i = 0; i < length; i++) { + JSC::JSValue v = array->get(exec, i); + if (exec->hadException()) + return JSC::jsUndefined(); + webGLArray->set(i + offset, v.toNumber(exec)); + } } return JSC::jsUndefined(); diff --git a/WebCore/bindings/js/JSWebGLFloatArrayCustom.cpp b/WebCore/bindings/js/JSWebGLFloatArrayCustom.cpp index 5f5b24f..f4acbcf 100644 --- a/WebCore/bindings/js/JSWebGLFloatArrayCustom.cpp +++ b/WebCore/bindings/js/JSWebGLFloatArrayCustom.cpp @@ -38,7 +38,7 @@ namespace WebCore { void JSWebGLFloatArray::indexSetter(JSC::ExecState* exec, unsigned index, JSC::JSValue value) { - impl()->set(index, static_cast<float>(value.toInt32(exec))); + impl()->set(index, static_cast<float>(value.toNumber(exec))); } JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, WebGLFloatArray* object) @@ -52,9 +52,9 @@ JSC::JSValue JSWebGLFloatArray::set(JSC::ExecState* exec, JSC::ArgList const& ar return throwError(exec, SyntaxError); if (args.size() == 2 && args.at(0).isInt32()) { - // void set(in unsigned long index, in long value); + // void set(in unsigned long index, in float value); unsigned index = args.at(0).toUInt32(exec); - impl()->set(index, static_cast<signed char>(args.at(1).toInt32(exec))); + impl()->set(index, static_cast<float>(args.at(1).toNumber(exec))); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSWebGLIntArrayCustom.cpp b/WebCore/bindings/js/JSWebGLIntArrayCustom.cpp index 9c384d8..de08256 100644 --- a/WebCore/bindings/js/JSWebGLIntArrayCustom.cpp +++ b/WebCore/bindings/js/JSWebGLIntArrayCustom.cpp @@ -54,7 +54,7 @@ JSC::JSValue JSWebGLIntArray::set(JSC::ExecState* exec, JSC::ArgList const& args if (args.size() == 2 && args.at(0).isInt32()) { // void set(in unsigned long index, in long value); unsigned index = args.at(0).toUInt32(exec); - impl()->set(index, static_cast<signed char>(args.at(1).toInt32(exec))); + impl()->set(index, static_cast<signed int>(args.at(1).toInt32(exec))); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp b/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp index 3de9606..e336027 100644 --- a/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp +++ b/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp @@ -29,12 +29,14 @@ #include "JSWebGLRenderingContext.h" -#include "WebGLRenderingContext.h" #include "ExceptionCode.h" #include "HTMLCanvasElement.h" #include "HTMLImageElement.h" +#include "HTMLVideoElement.h" #include "JSHTMLCanvasElement.h" #include "JSHTMLImageElement.h" +#include "JSHTMLVideoElement.h" +#include "JSImageData.h" #include "JSWebGLBuffer.h" #include "JSWebGLFloatArray.h" #include "JSWebGLFramebuffer.h" @@ -48,11 +50,12 @@ #include "JSWebKitCSSMatrix.h" #include "NotImplemented.h" #include "WebGLBuffer.h" -#include "WebGLGetInfo.h" #include "WebGLFloatArray.h" #include "WebGLFramebuffer.h" +#include "WebGLGetInfo.h" #include "WebGLIntArray.h" #include "WebGLProgram.h" +#include "WebGLRenderingContext.h" #include <runtime/Error.h> #include <wtf/FastMalloc.h> #include <wtf/OwnFastMallocPtr.h> @@ -79,8 +82,7 @@ JSValue JSWebGLRenderingContext::bufferData(JSC::ExecState* exec, JSC::ArgList c static_cast<WebGLRenderingContext*>(impl())->bufferData(target, array, usage, ec); } - if (ec != 0) - setDOMException(exec, ec); + setDOMException(exec, ec); return jsUndefined(); } @@ -97,8 +99,7 @@ JSValue JSWebGLRenderingContext::bufferSubData(JSC::ExecState* exec, JSC::ArgLis static_cast<WebGLRenderingContext*>(impl())->bufferSubData(target, offset, array, ec); - if (ec != 0) - setDOMException(exec, ec); + setDOMException(exec, ec); return jsUndefined(); } @@ -307,27 +308,60 @@ JSValue JSWebGLRenderingContext::getVertexAttrib(ExecState* exec, const ArgList& return getObjectParameter(this, exec, args, kVertexAttrib); } -// void texImage2DHTML(in unsigned long target, in unsigned long level, in HTMLImageElement image); +// void texImage2D(in GLenum target, in GLint level, in GLenum internalformat, in GLsizei width, in GLsizei height, in GLint border, in GLenum format, in GLenum type, in WebGLArray pixels); +// void texImage2D(in GLenum target, in GLint level, in ImageData pixels, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha); +// void texImage2D(in GLenum target, in GLint level, in HTMLImageElement image, [Optional] in GLboolean flipY, [Optional] in premultiplyAlpha); +// void texImage2D(in GLenum target, in GLint level, in HTMLCanvasElement canvas, [Optional] in GLboolean flipY, [Optional] in premultiplyAlpha); +// void texImage2D(in GLenum target, in GLint level, in HTMLVideoElement video, [Optional] in GLboolean flipY, [Optional] in premultiplyAlpha); JSValue JSWebGLRenderingContext::texImage2D(ExecState* exec, const ArgList& args) { - if (args.size() < 3) + if (args.size() < 3 || args.size() > 9) return throwError(exec, SyntaxError); ExceptionCode ec = 0; + WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl()); unsigned target = args.at(0).toInt32(exec); if (exec->hadException()) return jsUndefined(); - + unsigned level = args.at(1).toInt32(exec); if (exec->hadException()) return jsUndefined(); + + JSObject* o = 0; + + if (args.size() <= 5) { + // This is one of the last 4 forms. Param 2 can be ImageData or <img>, <canvas> or <video> element. + JSValue value = args.at(2); - if (args.size() > 5) { - // This must be the bare array case. + if (!value.isObject()) + return throwError(exec, TypeError); + + o = asObject(value); + + bool flipY = args.at(3).toBoolean(exec); + bool premultiplyAlpha = args.at(4).toBoolean(exec); + + if (o->inherits(&JSImageData::s_info)) { + ImageData* data = static_cast<ImageData*>(static_cast<JSImageData*>(o)->impl()); + context->texImage2D(target, level, data, flipY, premultiplyAlpha, ec); + } else if (o->inherits(&JSHTMLImageElement::s_info)) { + HTMLImageElement* element = static_cast<HTMLImageElement*>(static_cast<JSHTMLImageElement*>(o)->impl()); + context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec); + } else if (o->inherits(&JSHTMLCanvasElement::s_info)) { + HTMLCanvasElement* element = static_cast<HTMLCanvasElement*>(static_cast<JSHTMLCanvasElement*>(o)->impl()); + context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec); + } else if (o->inherits(&JSHTMLVideoElement::s_info)) { + HTMLVideoElement* element = static_cast<HTMLVideoElement*>(static_cast<JSHTMLVideoElement*>(o)->impl()); + context->texImage2D(target, level, element, flipY, premultiplyAlpha, ec); + } else + ec = TYPE_MISMATCH_ERR; + } else { if (args.size() != 9) return throwError(exec, SyntaxError); - + + // This must be the WebGLArray case unsigned internalformat = args.at(2).toInt32(exec); if (exec->hadException()) return jsUndefined(); @@ -352,104 +386,143 @@ JSValue JSWebGLRenderingContext::texImage2D(ExecState* exec, const ArgList& args if (exec->hadException()) return jsUndefined(); - WebGLArray* array = toWebGLArray(args.at(8)); - if (exec->hadException()) - return jsUndefined(); + JSValue value = args.at(8); - if (!array) + // For this case passing 0 (for a null array) is allowed + if (value.isNull()) + context->texImage2D(target, level, internalformat, width, height, border, format, type, 0, ec); + else if (value.isObject()) { + o = asObject(value); + + if (o->inherits(&JSWebGLArray::s_info)) { + // FIXME: Need to check to make sure WebGLArray is a WebGLByteArray or WebGLShortArray, + // depending on the passed type parameter. + WebGLArray* obj = static_cast<WebGLArray*>(static_cast<JSWebGLArray*>(o)->impl()); + context->texImage2D(target, level, internalformat, width, height, border, format, type, obj, ec); + } else + return throwError(exec, TypeError); + } else return throwError(exec, TypeError); - - // FIXME: Need to check to make sure WebGLArray is a WebGLByteArray or WebGLShortArray, - // depending on the passed type parameter. - - context->texImage2D(target, level, internalformat, width, height, border, format, type, array, ec); - return jsUndefined(); - } - - // The image parameter can be a <img> or <canvas> element. - JSValue value = args.at(2); - if (!value.isObject()) - return throwError(exec, TypeError); - JSObject* o = asObject(value); - - bool flipY = (args.size() > 3) ? args.at(3).toBoolean(exec) : false; - bool premultiplyAlpha = (args.size() > 4) ? args.at(3).toBoolean(exec) : false; - - if (o->inherits(&JSHTMLImageElement::s_info)) { - HTMLImageElement* imgElt = static_cast<HTMLImageElement*>(static_cast<JSHTMLElement*>(o)->impl()); - context->texImage2D(target, level, imgElt, flipY, premultiplyAlpha, ec); - } else if (o->inherits(&JSHTMLCanvasElement::s_info)) { - HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(static_cast<JSHTMLElement*>(o)->impl()); - context->texImage2D(target, level, canvas, flipY, premultiplyAlpha, ec); - } else { - setDOMException(exec, TYPE_MISMATCH_ERR); } + setDOMException(exec, ec); return jsUndefined(); } -// void texSubImage2DHTML(in unsigned long target, in unsigned long level, in unsigned long xoff, in unsigned long yoff, in unsigned long width, in unsigned long height, in HTMLImageElement image); +// void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in GLsizei width, in GLsizei height, in GLenum format, in GLenum type, in WebGLArray pixels); +// void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in ImageData pixels, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha); +// void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in HTMLImageElement image, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha); +// void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in HTMLCanvasElement canvas, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha); +// void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in HTMLVideoElement video, [Optional] GLboolean flipY, [Optional] in premultiplyAlpha); JSValue JSWebGLRenderingContext::texSubImage2D(ExecState* exec, const ArgList& args) { - if (args.size() < 7 || args.size() > 9) + if (args.size() < 5 || args.size() > 9) return throwError(exec, SyntaxError); + ExceptionCode ec = 0; + WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(impl()); unsigned target = args.at(0).toInt32(exec); + if (exec->hadException()) + return jsUndefined(); + unsigned level = args.at(1).toInt32(exec); - unsigned xoff = args.at(2).toInt32(exec); - unsigned yoff = args.at(3).toInt32(exec); - unsigned width = args.at(4).toInt32(exec); - unsigned height = args.at(5).toInt32(exec); + if (exec->hadException()) + return jsUndefined(); - // The image parameter can be a <img> or <canvas> element. - JSValue value = args.at(6); - if (!value.isObject()) - return throwError(exec, TypeError); - JSObject* o = asObject(value); + unsigned xoff = args.at(2).toInt32(exec); + if (exec->hadException()) + return jsUndefined(); - bool flipY = (args.size() > 3) ? args.at(3).toBoolean(exec) : false; - bool premultiplyAlpha = (args.size() > 4) ? args.at(3).toBoolean(exec) : false; + unsigned yoff = args.at(3).toInt32(exec); + if (exec->hadException()) + return jsUndefined(); - ExceptionCode ec = 0; - if (o->inherits(&JSHTMLImageElement::s_info)) { - HTMLImageElement* imgElt = static_cast<HTMLImageElement*>(static_cast<JSHTMLElement*>(o)->impl()); - context->texSubImage2D(target, level, xoff, yoff, width, height, imgElt, flipY, premultiplyAlpha, ec); - } else if (o->inherits(&JSHTMLCanvasElement::s_info)) { - HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(static_cast<JSHTMLElement*>(o)->impl()); - context->texSubImage2D(target, level, xoff, yoff, width, height, canvas, flipY, premultiplyAlpha, ec); - } else - ec = TYPE_MISMATCH_ERR; + JSObject* o = 0; + + if (args.size() <= 7) { + // This is one of the last 4 forms. Param 4 can be <img>, <canvas> or <video> element, of the format param. + JSValue value = args.at(4); + + if (!value.isObject()) + return throwError(exec, SyntaxError); + + o = asObject(value); + + bool flipY = args.at(5).toBoolean(exec); + bool premultiplyAlpha = args.at(6).toBoolean(exec); + + if (o->inherits(&JSImageData::s_info)) { + ImageData* data = static_cast<ImageData*>(static_cast<JSImageData*>(o)->impl()); + context->texSubImage2D(target, level, xoff, yoff, data, flipY, premultiplyAlpha, ec); + } else if (o->inherits(&JSHTMLImageElement::s_info)) { + HTMLImageElement* element = static_cast<HTMLImageElement*>(static_cast<JSHTMLImageElement*>(o)->impl()); + context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec); + } else if (o->inherits(&JSHTMLCanvasElement::s_info)) { + HTMLCanvasElement* element = static_cast<HTMLCanvasElement*>(static_cast<JSHTMLCanvasElement*>(o)->impl()); + context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec); + } else if (o->inherits(&JSHTMLVideoElement::s_info)) { + HTMLVideoElement* element = static_cast<HTMLVideoElement*>(static_cast<JSHTMLVideoElement*>(o)->impl()); + context->texSubImage2D(target, level, xoff, yoff, element, flipY, premultiplyAlpha, ec); + } else + ec = TYPE_MISMATCH_ERR; + } else { + // This must be the WebGLArray form + if (args.size() != 9) + return throwError(exec, SyntaxError); + + unsigned width = args.at(4).toInt32(exec); + if (exec->hadException()) + return jsUndefined(); + + unsigned height = args.at(5).toInt32(exec); + if (exec->hadException()) + return jsUndefined(); + + unsigned format = args.at(6).toInt32(exec); + if (exec->hadException()) + return jsUndefined(); + + unsigned type = args.at(7).toInt32(exec); + if (exec->hadException()) + return jsUndefined(); + + JSValue value = args.at(8); + if (!value.isObject()) + context->texSubImage2D(target, level, xoff, yoff, width, height, format, type, 0, ec); + else { + o = asObject(value); + + if (o->inherits(&JSWebGLArray::s_info)) { + WebGLArray* obj = static_cast<WebGLArray*>(static_cast<JSWebGLArray*>(o)->impl()); + context->texSubImage2D(target, level, xoff, yoff, width, height, format, type, obj, ec); + } else + return throwError(exec, TypeError); + } + } - if (ec != 0) - setDOMException(exec, ec); - return jsUndefined(); + setDOMException(exec, ec); + return jsUndefined(); } -template<typename T> -void toArray(JSC::ExecState* exec, JSC::JSValue value, T*& array, int& size) +template<typename T, size_t inlineCapacity> +bool toVector(JSC::ExecState* exec, JSC::JSValue value, Vector<T, inlineCapacity>& vector) { - array = 0; - if (!value.isObject()) - return; - + return false; + JSC::JSObject* object = asObject(value); - int length = object->get(exec, JSC::Identifier(exec, "length")).toInt32(exec); - void* tempValues; - if (!tryFastMalloc(length * sizeof(T)).getValue(tempValues)) - return; - - T* values = static_cast<T*>(tempValues); - for (int i = 0; i < length; ++i) { + int32_t length = object->get(exec, JSC::Identifier(exec, "length")).toInt32(exec); + vector.resize(length); + + for (int32_t i = 0; i < length; ++i) { JSC::JSValue v = object->get(exec, i); if (exec->hadException()) - return; - values[i] = static_cast<T>(v.toNumber(exec)); + return false; + vector[i] = static_cast<T>(v.toNumber(exec)); } - array = values; - size = length; + return true; } enum DataFunctionToCall { @@ -497,40 +570,69 @@ static JSC::JSValue dataFunctionf(DataFunctionToCall f, JSC::ExecState* exec, co ExceptionCode ec = 0; if (webGLArray) { - switch(f) { - case f_uniform1v: context->uniform1fv(location, webGLArray.get(), ec); break; - case f_uniform2v: context->uniform2fv(location, webGLArray.get(), ec); break; - case f_uniform3v: context->uniform3fv(location, webGLArray.get(), ec); break; - case f_uniform4v: context->uniform4fv(location, webGLArray.get(), ec); break; - case f_vertexAttrib1v: context->vertexAttrib1fv(index, webGLArray.get()); break; - case f_vertexAttrib2v: context->vertexAttrib2fv(index, webGLArray.get()); break; - case f_vertexAttrib3v: context->vertexAttrib3fv(index, webGLArray.get()); break; - case f_vertexAttrib4v: context->vertexAttrib4fv(index, webGLArray.get()); break; + switch (f) { + case f_uniform1v: + context->uniform1fv(location, webGLArray.get(), ec); + break; + case f_uniform2v: + context->uniform2fv(location, webGLArray.get(), ec); + break; + case f_uniform3v: + context->uniform3fv(location, webGLArray.get(), ec); + break; + case f_uniform4v: + context->uniform4fv(location, webGLArray.get(), ec); + break; + case f_vertexAttrib1v: + context->vertexAttrib1fv(index, webGLArray.get()); + break; + case f_vertexAttrib2v: + context->vertexAttrib2fv(index, webGLArray.get()); + break; + case f_vertexAttrib3v: + context->vertexAttrib3fv(index, webGLArray.get()); + break; + case f_vertexAttrib4v: + context->vertexAttrib4fv(index, webGLArray.get()); + break; } - if (ec != 0) - setDOMException(exec, ec); + + setDOMException(exec, ec); return jsUndefined(); } - - float* array; - int size; - toArray<float>(exec, args.at(1), array, size); - - if (!array) + + Vector<float, 64> array; + if (!toVector(exec, args.at(1), array)) return throwError(exec, TypeError); - switch(f) { - case f_uniform1v: context->uniform1fv(location, array, size, ec); break; - case f_uniform2v: context->uniform2fv(location, array, size, ec); break; - case f_uniform3v: context->uniform3fv(location, array, size, ec); break; - case f_uniform4v: context->uniform4fv(location, array, size, ec); break; - case f_vertexAttrib1v: context->vertexAttrib1fv(index, array, size); break; - case f_vertexAttrib2v: context->vertexAttrib2fv(index, array, size); break; - case f_vertexAttrib3v: context->vertexAttrib3fv(index, array, size); break; - case f_vertexAttrib4v: context->vertexAttrib4fv(index, array, size); break; + switch (f) { + case f_uniform1v: + context->uniform1fv(location, array.data(), array.size(), ec); + break; + case f_uniform2v: + context->uniform2fv(location, array.data(), array.size(), ec); + break; + case f_uniform3v: + context->uniform3fv(location, array.data(), array.size(), ec); + break; + case f_uniform4v: + context->uniform4fv(location, array.data(), array.size(), ec); + break; + case f_vertexAttrib1v: + context->vertexAttrib1fv(index, array.data(), array.size()); + break; + case f_vertexAttrib2v: + context->vertexAttrib2fv(index, array.data(), array.size()); + break; + case f_vertexAttrib3v: + context->vertexAttrib3fv(index, array.data(), array.size()); + break; + case f_vertexAttrib4v: + context->vertexAttrib4fv(index, array.data(), array.size()); + break; } - if (ec != 0) - setDOMException(exec, ec); + + setDOMException(exec, ec); return jsUndefined(); } @@ -550,34 +652,50 @@ static JSC::JSValue dataFunctioni(DataFunctionToCall f, JSC::ExecState* exec, co ExceptionCode ec = 0; if (webGLArray) { - switch(f) { - case f_uniform1v: context->uniform1iv(location, webGLArray.get(), ec); break; - case f_uniform2v: context->uniform2iv(location, webGLArray.get(), ec); break; - case f_uniform3v: context->uniform3iv(location, webGLArray.get(), ec); break; - case f_uniform4v: context->uniform4iv(location, webGLArray.get(), ec); break; - default: break; + switch (f) { + case f_uniform1v: + context->uniform1iv(location, webGLArray.get(), ec); + break; + case f_uniform2v: + context->uniform2iv(location, webGLArray.get(), ec); + break; + case f_uniform3v: + context->uniform3iv(location, webGLArray.get(), ec); + break; + case f_uniform4v: + context->uniform4iv(location, webGLArray.get(), ec); + break; + default: + break; } - if (ec != 0) - setDOMException(exec, ec); + + setDOMException(exec, ec); return jsUndefined(); } - - int* array; - int size; - toArray<int>(exec, args.at(1), array, size); - - if (!array) + + + Vector<int, 64> array; + if (!toVector(exec, args.at(1), array)) return throwError(exec, TypeError); - switch(f) { - case f_uniform1v: context->uniform1iv(location, array, size, ec); break; - case f_uniform2v: context->uniform2iv(location, array, size, ec); break; - case f_uniform3v: context->uniform3iv(location, array, size, ec); break; - case f_uniform4v: context->uniform4iv(location, array, size, ec); break; - default: break; + switch (f) { + case f_uniform1v: + context->uniform1iv(location, array.data(), array.size(), ec); + break; + case f_uniform2v: + context->uniform2iv(location, array.data(), array.size(), ec); + break; + case f_uniform3v: + context->uniform3iv(location, array.data(), array.size(), ec); + break; + case f_uniform4v: + context->uniform4iv(location, array.data(), array.size(), ec); + break; + default: + break; } - if (ec != 0) - setDOMException(exec, ec); + + setDOMException(exec, ec); return jsUndefined(); } @@ -601,30 +719,39 @@ static JSC::JSValue dataFunctionMatrix(DataFunctionMatrixToCall f, JSC::ExecStat ExceptionCode ec = 0; if (webGLArray) { - switch(f) { - case f_uniformMatrix2fv: context->uniformMatrix2fv(location, transpose, webGLArray.get(), ec); break; - case f_uniformMatrix3fv: context->uniformMatrix3fv(location, transpose, webGLArray.get(), ec); break; - case f_uniformMatrix4fv: context->uniformMatrix4fv(location, transpose, webGLArray.get(), ec); break; + switch (f) { + case f_uniformMatrix2fv: + context->uniformMatrix2fv(location, transpose, webGLArray.get(), ec); + break; + case f_uniformMatrix3fv: + context->uniformMatrix3fv(location, transpose, webGLArray.get(), ec); + break; + case f_uniformMatrix4fv: + context->uniformMatrix4fv(location, transpose, webGLArray.get(), ec); + break; } - if (ec != 0) - setDOMException(exec, ec); + + setDOMException(exec, ec); return jsUndefined(); } - - float* array; - int size; - toArray<float>(exec, args.at(2), array, size); - - if (!array) + + Vector<float, 64> array; + if (!toVector(exec, args.at(2), array)) return throwError(exec, TypeError); - switch(f) { - case f_uniformMatrix2fv: context->uniformMatrix2fv(location, transpose, array, size, ec); break; - case f_uniformMatrix3fv: context->uniformMatrix3fv(location, transpose, array, size, ec); break; - case f_uniformMatrix4fv: context->uniformMatrix4fv(location, transpose, array, size, ec); break; + switch (f) { + case f_uniformMatrix2fv: + context->uniformMatrix2fv(location, transpose, array.data(), array.size(), ec); + break; + case f_uniformMatrix3fv: + context->uniformMatrix3fv(location, transpose, array.data(), array.size(), ec); + break; + case f_uniformMatrix4fv: + context->uniformMatrix4fv(location, transpose, array.data(), array.size(), ec); + break; } - if (ec != 0) - setDOMException(exec, ec); + + setDOMException(exec, ec); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSWebGLShortArrayCustom.cpp b/WebCore/bindings/js/JSWebGLShortArrayCustom.cpp index 462b09a..899b0c9 100644 --- a/WebCore/bindings/js/JSWebGLShortArrayCustom.cpp +++ b/WebCore/bindings/js/JSWebGLShortArrayCustom.cpp @@ -54,7 +54,7 @@ JSC::JSValue JSWebGLShortArray::set(JSC::ExecState* exec, JSC::ArgList const& ar if (args.size() == 2 && args.at(0).isInt32()) { // void set(in unsigned long index, in long value); unsigned index = args.at(0).toUInt32(exec); - impl()->set(index, static_cast<signed char>(args.at(1).toInt32(exec))); + impl()->set(index, static_cast<signed short>(args.at(1).toInt32(exec))); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSWebGLUnsignedByteArrayCustom.cpp b/WebCore/bindings/js/JSWebGLUnsignedByteArrayCustom.cpp index 35a545d..b576374 100644 --- a/WebCore/bindings/js/JSWebGLUnsignedByteArrayCustom.cpp +++ b/WebCore/bindings/js/JSWebGLUnsignedByteArrayCustom.cpp @@ -54,7 +54,7 @@ JSC::JSValue JSWebGLUnsignedByteArray::set(JSC::ExecState* exec, JSC::ArgList co if (args.size() == 2 && args.at(0).isInt32()) { // void set(in unsigned long index, in long value); unsigned index = args.at(0).toUInt32(exec); - impl()->set(index, static_cast<signed char>(args.at(1).toInt32(exec))); + impl()->set(index, static_cast<unsigned char>(args.at(1).toInt32(exec))); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSWebGLUnsignedIntArrayCustom.cpp b/WebCore/bindings/js/JSWebGLUnsignedIntArrayCustom.cpp index ea28111..c8b7454 100644 --- a/WebCore/bindings/js/JSWebGLUnsignedIntArrayCustom.cpp +++ b/WebCore/bindings/js/JSWebGLUnsignedIntArrayCustom.cpp @@ -38,7 +38,7 @@ namespace WebCore { void JSWebGLUnsignedIntArray::indexSetter(JSC::ExecState* exec, unsigned index, JSC::JSValue value) { - impl()->set(index, static_cast<unsigned int>(value.toInt32(exec))); + impl()->set(index, static_cast<unsigned int>(value.toUInt32(exec))); } JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, WebGLUnsignedIntArray* object) @@ -54,7 +54,7 @@ JSC::JSValue JSWebGLUnsignedIntArray::set(JSC::ExecState* exec, JSC::ArgList con if (args.size() == 2 && args.at(0).isInt32()) { // void set(in unsigned long index, in long value); unsigned index = args.at(0).toUInt32(exec); - impl()->set(index, static_cast<signed char>(args.at(1).toInt32(exec))); + impl()->set(index, static_cast<unsigned int>(args.at(1).toUInt32(exec))); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSWebGLUnsignedShortArrayCustom.cpp b/WebCore/bindings/js/JSWebGLUnsignedShortArrayCustom.cpp index 898cc06..0c82c3e 100644 --- a/WebCore/bindings/js/JSWebGLUnsignedShortArrayCustom.cpp +++ b/WebCore/bindings/js/JSWebGLUnsignedShortArrayCustom.cpp @@ -54,7 +54,7 @@ JSC::JSValue JSWebGLUnsignedShortArray::set(JSC::ExecState* exec, JSC::ArgList c if (args.size() == 2 && args.at(0).isInt32()) { // void set(in unsigned long index, in long value); unsigned index = args.at(0).toUInt32(exec); - impl()->set(index, static_cast<signed char>(args.at(1).toInt32(exec))); + impl()->set(index, static_cast<unsigned short>(args.at(1).toInt32(exec))); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSWebSocketConstructor.h b/WebCore/bindings/js/JSWebSocketConstructor.h index 069647a..633e612 100644 --- a/WebCore/bindings/js/JSWebSocketConstructor.h +++ b/WebCore/bindings/js/JSWebSocketConstructor.h @@ -31,6 +31,8 @@ #ifndef JSWebSocketConstructor_h #define JSWebSocketConstructor_h +#if ENABLE(WEB_SOCKETS) + #include "JSDOMBinding.h" namespace WebCore { @@ -45,6 +47,8 @@ class JSWebSocketConstructor : public DOMConstructorObject { virtual const JSC::ClassInfo* classInfo() const { return &s_info; } }; -} // namespace WebCore +} // namespace WebCore + +#endif // ENABLE(WEB_SOCKETS) -#endif // JSWebSocketConstructor_h +#endif // JSWebSocketConstructor_h diff --git a/WebCore/bindings/js/JSWorkerContextBase.cpp b/WebCore/bindings/js/JSWorkerContextBase.cpp index f0c4efa..2491f4d 100644 --- a/WebCore/bindings/js/JSWorkerContextBase.cpp +++ b/WebCore/bindings/js/JSWorkerContextBase.cpp @@ -42,7 +42,7 @@ namespace WebCore { ASSERT_CLASS_FITS_IN_CELL(JSWorkerContextBase); -const ClassInfo JSWorkerContextBase::s_info = { "WorkerContext", 0, 0, 0 }; +const ClassInfo JSWorkerContextBase::s_info = { "WorkerContext", &JSDOMGlobalObject::s_info, 0, 0 }; JSWorkerContextBase::JSWorkerContextBase(NonNullPassRefPtr<JSC::Structure> structure, PassRefPtr<WorkerContext> impl) : JSDOMGlobalObject(structure, new JSDOMGlobalObjectData(normalWorld(*impl->script()->globalData())), this) diff --git a/WebCore/bindings/js/JSWorkerContextCustom.cpp b/WebCore/bindings/js/JSWorkerContextCustom.cpp index 490d9b1..ab28674 100644 --- a/WebCore/bindings/js/JSWorkerContextCustom.cpp +++ b/WebCore/bindings/js/JSWorkerContextCustom.cpp @@ -32,8 +32,10 @@ #include "JSDOMBinding.h" #include "JSDOMGlobalObject.h" #include "JSEventListener.h" +#include "JSEventSourceConstructor.h" #include "JSMessageChannelConstructor.h" #include "JSMessagePort.h" +#include "JSWebSocketConstructor.h" #include "JSWorkerLocation.h" #include "JSWorkerNavigator.h" #include "JSXMLHttpRequestConstructor.h" @@ -43,10 +45,6 @@ #include "WorkerNavigator.h" #include <interpreter/Interpreter.h> -#if ENABLE(EVENTSOURCE) -#include "JSEventSourceConstructor.h" -#endif - using namespace JSC; namespace WebCore { @@ -93,6 +91,13 @@ JSValue JSWorkerContext::xmlHttpRequest(ExecState* exec) const return getDOMConstructor<JSXMLHttpRequestConstructor>(exec, this); } +#if ENABLE(WEB_SOCKETS) +JSValue JSWorkerContext::webSocket(ExecState* exec) const +{ + return getDOMConstructor<JSWebSocketConstructor>(exec, this); +} +#endif + JSValue JSWorkerContext::importScripts(ExecState* exec, const ArgList& args) { if (!args.size()) diff --git a/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp b/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp index 7ee2720..d35d53a 100644 --- a/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp +++ b/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp @@ -29,18 +29,18 @@ #include "config.h" #include "JSXMLHttpRequest.h" +#include "Blob.h" #include "DOMWindow.h" #include "Document.h" #include "Event.h" -#include "File.h" #include "Frame.h" #include "FrameLoader.h" #include "HTMLDocument.h" +#include "JSBlob.h" #include "JSDOMWindowCustom.h" #include "JSDocument.h" #include "JSEvent.h" #include "JSEventListener.h" -#include "JSFile.h" #include "XMLHttpRequest.h" #include <runtime/Error.h> #include <interpreter/Interpreter.h> @@ -109,8 +109,8 @@ JSValue JSXMLHttpRequest::send(ExecState* exec, const ArgList& args) impl()->send(ec); else if (val.inherits(&JSDocument::s_info)) impl()->send(toDocument(val), ec); - else if (val.inherits(&JSFile::s_info)) - impl()->send(toFile(val), ec); + else if (val.inherits(&JSBlob::s_info)) + impl()->send(toBlob(val), ec); else impl()->send(val.toString(exec), ec); } diff --git a/WebCore/bindings/js/ScheduledAction.cpp b/WebCore/bindings/js/ScheduledAction.cpp index 3223e53..be90125 100644 --- a/WebCore/bindings/js/ScheduledAction.cpp +++ b/WebCore/bindings/js/ScheduledAction.cpp @@ -117,7 +117,7 @@ void ScheduledAction::execute(Document* document) return; RefPtr<Frame> frame = window->impl()->frame(); - if (!frame || !frame->script()->isEnabled()) + if (!frame || !frame->script()->canExecuteScripts()) return; frame->script()->setProcessingTimerCallback(true); diff --git a/WebCore/bindings/js/ScheduledAction.h b/WebCore/bindings/js/ScheduledAction.h index 4ea727d..dd13ab1 100644 --- a/WebCore/bindings/js/ScheduledAction.h +++ b/WebCore/bindings/js/ScheduledAction.h @@ -40,7 +40,7 @@ namespace WebCore { * time interval, either once or repeatedly. Used for window.setTimeout() * and window.setInterval() */ - class ScheduledAction { + class ScheduledAction : public Noncopyable { public: static ScheduledAction* create(JSC::ExecState*, const JSC::ArgList&, DOMWrapperWorld* isolatedWorld); diff --git a/WebCore/bindings/js/ScriptCachedFrameData.cpp b/WebCore/bindings/js/ScriptCachedFrameData.cpp index f2b64de..16f18d3 100644 --- a/WebCore/bindings/js/ScriptCachedFrameData.cpp +++ b/WebCore/bindings/js/ScriptCachedFrameData.cpp @@ -73,8 +73,6 @@ ScriptCachedFrameData::~ScriptCachedFrameData() void ScriptCachedFrameData::restore(Frame* frame) { - Page* page = frame->page(); - JSLock lock(SilenceAssertionsOnly); ScriptController* scriptController = frame->script(); @@ -89,8 +87,9 @@ void ScriptCachedFrameData::restore(Frame* frame) windowShell->setWindow(window); else { windowShell->setWindow(frame->domWindow()); - if (world == debuggerWorld()) { - scriptController->attachDebugger(page->debugger()); + + if (Page* page = frame->page()) { + scriptController->attachDebugger(windowShell, page->debugger()); windowShell->window()->setProfileGroup(page->group().identifier()); } } diff --git a/WebCore/bindings/js/ScriptCachedFrameData.h b/WebCore/bindings/js/ScriptCachedFrameData.h index 5bcaed7..15c23c5 100644 --- a/WebCore/bindings/js/ScriptCachedFrameData.h +++ b/WebCore/bindings/js/ScriptCachedFrameData.h @@ -40,7 +40,7 @@ namespace WebCore { class DOMWindow; class DOMWrapperWorld; - class ScriptCachedFrameData { + class ScriptCachedFrameData : public Noncopyable { typedef HashMap< RefPtr<DOMWrapperWorld>, JSC::ProtectedPtr<JSDOMWindow> > JSDOMWindowSet; public: diff --git a/WebCore/bindings/js/ScriptCallStack.h b/WebCore/bindings/js/ScriptCallStack.h index 1907564..52362ea 100644 --- a/WebCore/bindings/js/ScriptCallStack.h +++ b/WebCore/bindings/js/ScriptCallStack.h @@ -49,6 +49,7 @@ namespace WebCore { ~ScriptCallStack(); ScriptState* state() const { return m_exec; } + ScriptState* globalState() const { return m_exec->lexicalGlobalObject()->globalExec(); } // frame retrieval methods const ScriptCallFrame &at(unsigned); unsigned size(); diff --git a/WebCore/bindings/js/ScriptController.cpp b/WebCore/bindings/js/ScriptController.cpp index 8d34f88..083e931 100644 --- a/WebCore/bindings/js/ScriptController.cpp +++ b/WebCore/bindings/js/ScriptController.cpp @@ -102,7 +102,7 @@ ScriptValue ScriptController::evaluateInWorld(const ScriptSourceCode& sourceCode } // evaluate code. Returns the JS return value or 0 - // if there was none, an error occured or the type couldn't be converted. + // if there was none, an error occurred or the type couldn't be converted. // inlineCode is true for <a href="javascript:doSomething()"> // and false for <script>doSomething()</script>. Check if it has the @@ -156,7 +156,7 @@ ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) class IsolatedWorld : public DOMWrapperWorld { public: IsolatedWorld(JSGlobalData* globalData) - : DOMWrapperWorld(globalData) + : DOMWrapperWorld(globalData, false) { JSGlobalData::ClientData* clientData = globalData->clientData; ASSERT(clientData); @@ -183,19 +183,17 @@ void ScriptController::clearWindowShell() JSLock lock(SilenceAssertionsOnly); - // Clear the debugger from the current window before setting the new window. - DOMWrapperWorld* debugWorld = debuggerWorld(); - attachDebugger(0); - for (ShellMap::iterator iter = m_windowShells.begin(); iter != m_windowShells.end(); ++iter) { - DOMWrapperWorld* world = iter->first.get(); JSDOMWindowShell* windowShell = iter->second; + + // Clear the debugger from the current window before setting the new window. + attachDebugger(windowShell, 0); + windowShell->window()->willRemoveFromWindowShell(); windowShell->setWindow(m_frame->domWindow()); if (Page* page = m_frame->page()) { - if (world == debugWorld) - attachDebugger(page->debugger()); + attachDebugger(windowShell, page->debugger()); windowShell->window()->setProfileGroup(page->group().identifier()); } } @@ -215,8 +213,7 @@ JSDOMWindowShell* ScriptController::initScript(DOMWrapperWorld* world) windowShell->window()->updateDocument(); if (Page* page = m_frame->page()) { - if (world == debuggerWorld()) - attachDebugger(page->debugger()); + attachDebugger(windowShell, page->debugger()); windowShell->window()->setProfileGroup(page->group().identifier()); } @@ -291,16 +288,14 @@ bool ScriptController::anyPageIsProcessingUserGesture() const return false; } -bool ScriptController::isEnabled() +void ScriptController::attachDebugger(JSC::Debugger* debugger) { - Settings* settings = m_frame->settings(); - return m_frame->loader()->client()->allowJavaScript(settings && settings->isJavaScriptEnabled() && !m_frame->loader()->isSandboxed(SandboxScripts)); + for (ShellMap::iterator iter = m_windowShells.begin(); iter != m_windowShells.end(); ++iter) + attachDebugger(iter->second, debugger); } -void ScriptController::attachDebugger(JSC::Debugger* debugger) +void ScriptController::attachDebugger(JSDOMWindowShell* shell, JSC::Debugger* debugger) { - // FIXME: Should be able to debug isolated worlds. - JSDOMWindowShell* shell = existingWindowShell(debuggerWorld()); if (!shell) return; @@ -328,7 +323,7 @@ void ScriptController::updateSecurityOrigin() Bindings::RootObject* ScriptController::bindingRootObject() { - if (!isEnabled()) + if (!canExecuteScripts()) return 0; if (!m_bindingRootObject) { @@ -355,7 +350,7 @@ PassRefPtr<Bindings::RootObject> ScriptController::createRootObject(void* native NPObject* ScriptController::windowScriptNPObject() { if (!m_windowScriptNPObject) { - if (isEnabled()) { + if (canExecuteScripts()) { // JavaScript is enabled, so there is a JavaScript window object. // Return an NPObject bound to the window object. JSC::JSLock lock(SilenceAssertionsOnly); @@ -388,7 +383,7 @@ NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement JSObject* ScriptController::jsObjectForPluginElement(HTMLPlugInElement* plugin) { // Can't create JSObjects when JavaScript is disabled - if (!isEnabled()) + if (!canExecuteScripts()) return 0; // Create a JSObject bound to this element @@ -455,7 +450,7 @@ ScriptValue ScriptController::executeScriptInWorld(DOMWrapperWorld* world, const { ScriptSourceCode sourceCode(script, forceUserGesture ? KURL() : m_frame->loader()->url()); - if (!isEnabled() || isPaused()) + if (!canExecuteScripts() || isPaused()) return ScriptValue(); bool wasInExecuteScript = m_inExecuteScript; diff --git a/WebCore/bindings/js/ScriptController.h b/WebCore/bindings/js/ScriptController.h index 8801622..f3e5adf 100644 --- a/WebCore/bindings/js/ScriptController.h +++ b/WebCore/bindings/js/ScriptController.h @@ -110,9 +110,11 @@ public: bool processingUserGesture() const; bool anyPageIsProcessingUserGesture() const; - bool isEnabled(); + bool canExecuteScripts(); - void attachDebugger(JSC::Debugger*); + // Debugger can be 0 to detach any existing Debugger. + void attachDebugger(JSC::Debugger*); // Attaches/detaches in all worlds/window shells. + void attachDebugger(JSDOMWindowShell*, JSC::Debugger*); void setPaused(bool b) { m_paused = b; } bool isPaused() const { return m_paused; } diff --git a/WebCore/bindings/js/ScriptControllerMac.mm b/WebCore/bindings/js/ScriptControllerMac.mm index 650cb78..208aae8 100644 --- a/WebCore/bindings/js/ScriptControllerMac.mm +++ b/WebCore/bindings/js/ScriptControllerMac.mm @@ -107,7 +107,7 @@ PassScriptInstance ScriptController::createScriptInstanceForWidget(Widget* widge WebScriptObject* ScriptController::windowScriptObject() { - if (!isEnabled()) + if (!canExecuteScripts()) return 0; if (!m_windowScriptObject) { diff --git a/WebCore/bindings/js/ScriptEventListener.cpp b/WebCore/bindings/js/ScriptEventListener.cpp index 8399c7a..4325dc3 100644 --- a/WebCore/bindings/js/ScriptEventListener.cpp +++ b/WebCore/bindings/js/ScriptEventListener.cpp @@ -52,6 +52,9 @@ static const String& eventParameterName(bool isSVGEvent) PassRefPtr<JSLazyEventListener> createAttributeEventListener(Node* node, Attribute* attr) { ASSERT(node); + ASSERT(attr); + if (attr->isNull()) + return 0; int lineNumber = 1; String sourceURL; @@ -59,7 +62,7 @@ PassRefPtr<JSLazyEventListener> createAttributeEventListener(Node* node, Attribu // FIXME: We should be able to provide accurate source information for frameless documents, too (e.g. for importing nodes from XMLHttpRequest.responseXML). if (Frame* frame = node->document()->frame()) { ScriptController* scriptController = frame->script(); - if (!scriptController->isEnabled()) + if (!scriptController->canExecuteScripts()) return 0; if (!scriptController->xssAuditor()->canCreateInlineEventListener(attr->localName().string(), attr->value())) { @@ -79,11 +82,15 @@ PassRefPtr<JSLazyEventListener> createAttributeEventListener(Frame* frame, Attri if (!frame) return 0; + ASSERT(attr); + if (attr->isNull()) + return 0; + int lineNumber = 1; String sourceURL; ScriptController* scriptController = frame->script(); - if (!scriptController->isEnabled()) + if (!scriptController->canExecuteScripts()) return 0; if (!scriptController->xssAuditor()->canCreateInlineEventListener(attr->localName().string(), attr->value())) { diff --git a/WebCore/bindings/js/ScriptFunctionCall.cpp b/WebCore/bindings/js/ScriptFunctionCall.cpp index e38acb9..a2284bc 100644 --- a/WebCore/bindings/js/ScriptFunctionCall.cpp +++ b/WebCore/bindings/js/ScriptFunctionCall.cpp @@ -79,7 +79,7 @@ void ScriptFunctionCall::appendArgument(const JSC::UString& argument) void ScriptFunctionCall::appendArgument(const char* argument) { JSLock lock(SilenceAssertionsOnly); - m_arguments.append(jsString(m_exec, argument)); + m_arguments.append(jsString(m_exec, UString(argument))); } void ScriptFunctionCall::appendArgument(JSC::JSValue argument) diff --git a/WebCore/bindings/js/ScriptObject.h b/WebCore/bindings/js/ScriptObject.h index fed7339..0c993e1 100644 --- a/WebCore/bindings/js/ScriptObject.h +++ b/WebCore/bindings/js/ScriptObject.h @@ -47,6 +47,7 @@ namespace WebCore { ScriptObject(ScriptState*, JSC::JSObject*); ScriptObject() {} JSC::JSObject* jsObject() const { return asObject(jsValue()); } + ScriptState* scriptState() const { return m_scriptState; } bool set(const String& name, const String&); bool set(const char* name, const ScriptObject&); diff --git a/WebCore/bindings/js/ScriptState.cpp b/WebCore/bindings/js/ScriptState.cpp index b9f78ef..b9f334a 100644 --- a/WebCore/bindings/js/ScriptState.cpp +++ b/WebCore/bindings/js/ScriptState.cpp @@ -38,6 +38,12 @@ namespace WebCore { +ScriptState* mainWorldScriptState(Frame* frame) +{ + JSDOMWindowShell* shell = frame->script()->windowShell(mainThreadNormalWorld()); + return shell->window()->globalExec(); +} + ScriptState* scriptStateFromNode(DOMWrapperWorld* world, Node* node) { if (!node) @@ -48,7 +54,7 @@ ScriptState* scriptStateFromNode(DOMWrapperWorld* world, Node* node) Frame* frame = document->frame(); if (!frame) return 0; - if (!frame->script()->isEnabled()) + if (!frame->script()->canExecuteScripts()) return 0; return frame->script()->globalObject(world)->globalExec(); } diff --git a/WebCore/bindings/js/ScriptState.h b/WebCore/bindings/js/ScriptState.h index 6257929..0c7c575 100644 --- a/WebCore/bindings/js/ScriptState.h +++ b/WebCore/bindings/js/ScriptState.h @@ -36,6 +36,7 @@ namespace WebCore { class DOMWrapperWorld; + class Frame; class Node; class Page; @@ -45,6 +46,8 @@ namespace WebCore { // For now, the separation is purely by convention. typedef JSC::ExecState ScriptState; + ScriptState* mainWorldScriptState(Frame*); + ScriptState* scriptStateFromNode(DOMWrapperWorld*, Node*); ScriptState* scriptStateFromPage(DOMWrapperWorld*, Page*); diff --git a/WebCore/bindings/js/ScriptString.h b/WebCore/bindings/js/ScriptString.h index 6dab9a0..a33d639 100644 --- a/WebCore/bindings/js/ScriptString.h +++ b/WebCore/bindings/js/ScriptString.h @@ -33,6 +33,7 @@ #include "PlatformString.h" #include <runtime/UString.h> +#include <runtime/StringBuilder.h> namespace WebCore { @@ -57,7 +58,10 @@ public: ScriptString& operator+=(const String& s) { - m_str += s; + JSC::StringBuilder buffer; + buffer.append(m_str); + buffer.append(s); + m_str = buffer.release(); return *this; } diff --git a/WebCore/bindings/js/ScriptValue.cpp b/WebCore/bindings/js/ScriptValue.cpp index 5444e0e..ac92e14 100644 --- a/WebCore/bindings/js/ScriptValue.cpp +++ b/WebCore/bindings/js/ScriptValue.cpp @@ -32,8 +32,6 @@ #include <JavaScriptCore/APICast.h> #include <JavaScriptCore/JSValueRef.h> -#include "JSInspectedObjectWrapper.h" - #include <runtime/JSLock.h> #include <runtime/Protect.h> #include <runtime/UString.h> @@ -42,14 +40,6 @@ using namespace JSC; namespace WebCore { -#if ENABLE(INSPECTOR) -ScriptValue ScriptValue::quarantineValue(ScriptState* scriptState, const ScriptValue& value) -{ - JSLock lock(SilenceAssertionsOnly); - return ScriptValue(JSInspectedObjectWrapper::wrap(scriptState, value.jsValue())); -} -#endif - bool ScriptValue::getString(ScriptState* scriptState, String& result) const { if (!m_value) diff --git a/WebCore/bindings/js/ScriptValue.h b/WebCore/bindings/js/ScriptValue.h index e11fa55..b1eaa21 100644 --- a/WebCore/bindings/js/ScriptValue.h +++ b/WebCore/bindings/js/ScriptValue.h @@ -41,8 +41,6 @@ class String; class ScriptValue { public: - static ScriptValue quarantineValue(ScriptState* scriptState, const ScriptValue& value); - ScriptValue(JSC::JSValue value = JSC::JSValue()) : m_value(value) {} virtual ~ScriptValue() {} diff --git a/WebCore/bindings/js/ScriptWrappable.h b/WebCore/bindings/js/ScriptWrappable.h new file mode 100644 index 0000000..d70cab7 --- /dev/null +++ b/WebCore/bindings/js/ScriptWrappable.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2010, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ScriptWrappable_h +#define ScriptWrappable_h + +namespace WebCore { + +class ScriptWrappable { +public: + ScriptWrappable() { } +}; + +} // namespace WebCore + +#endif // ScriptWrappable_h diff --git a/WebCore/bindings/js/SerializedScriptValue.cpp b/WebCore/bindings/js/SerializedScriptValue.cpp index 7c4ad62..fd9cb59 100644 --- a/WebCore/bindings/js/SerializedScriptValue.cpp +++ b/WebCore/bindings/js/SerializedScriptValue.cpp @@ -28,12 +28,14 @@ #include "SerializedScriptValue.h" #include "File.h" +#include "FileList.h" #include "JSDOMGlobalObject.h" #include "JSFile.h" #include "JSFileList.h" #include <JavaScriptCore/APICast.h> #include <runtime/DateInstance.h> #include <runtime/ExceptionHelpers.h> +#include <runtime/JSLock.h> #include <runtime/PropertyNameArray.h> #include <wtf/HashTraits.h> #include <wtf/Vector.h> @@ -141,6 +143,28 @@ private: unsigned m_length; }; +class SerializedFileList : public SharedSerializedData { +public: + static PassRefPtr<SerializedFileList> create(const FileList* list) + { + return adoptRef(new SerializedFileList(list)); + } + + unsigned length() const { return m_files.size(); } + const String& item(unsigned idx) { return m_files[idx]; } + +private: + SerializedFileList(const FileList* list) + { + unsigned length = list->length(); + m_files.reserveCapacity(length); + for (unsigned i = 0; i < length; i++) + m_files.append(list->item(i)->path().crossThreadString()); + } + + Vector<String> m_files; +}; + SerializedScriptValueData::SerializedScriptValueData(RefPtr<SerializedObject> data) : m_type(ObjectType) , m_sharedData(data) @@ -153,6 +177,12 @@ SerializedScriptValueData::SerializedScriptValueData(RefPtr<SerializedArray> dat { } +SerializedScriptValueData::SerializedScriptValueData(const FileList* fileList) + : m_type(FileListType) + , m_sharedData(SerializedFileList::create(fileList)) +{ +} + SerializedScriptValueData::SerializedScriptValueData(const File* file) : m_type(FileType) , m_string(file->path().crossThreadString()) @@ -169,6 +199,11 @@ SerializedObject* SharedSerializedData::asObject() return static_cast<SerializedObject*>(this); } +SerializedFileList* SharedSerializedData::asFileList() +{ + return static_cast<SerializedFileList*>(this); +} + static const unsigned maximumFilterRecursion = 40000; enum WalkerState { StateUnknown, ArrayStartState, ArrayStartVisitMember, ArrayEndVisitMember, ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember }; @@ -496,6 +531,8 @@ struct SerializingTreeWalker : public BaseWalker { JSObject* obj = asObject(value); if (obj->inherits(&JSFile::s_info)) return SerializedScriptValueData(toFile(obj)); + if (obj->inherits(&JSFileList::s_info)) + return SerializedScriptValueData(toFileList(obj)); CallData unusedData; if (value.getCallData(unusedData) == CallTypeNone) @@ -575,8 +612,10 @@ struct DeserializingTreeWalker : public BaseWalker { typedef JSObject* OutputObject; typedef SerializedObject::PropertyNameList PropertyList; - DeserializingTreeWalker(ExecState* exec, bool mustCopy) + DeserializingTreeWalker(ExecState* exec, JSGlobalObject* globalObject, bool mustCopy) : BaseWalker(exec) + , m_globalObject(globalObject) + , m_isDOMGlobalObject(globalObject->inherits(&JSDOMGlobalObject::s_info)) , m_mustCopy(mustCopy) { } @@ -605,14 +644,14 @@ struct DeserializingTreeWalker : public BaseWalker { JSArray* createOutputArray(unsigned length) { - JSArray* array = constructEmptyArray(m_exec); + JSArray* array = constructEmptyArray(m_exec, m_globalObject); array->setLength(length); return array; } JSObject* createOutputObject() { - return constructEmptyObject(m_exec); + return constructEmptyObject(m_exec, m_globalObject); } uint32_t length(RefPtr<SerializedArray> array) @@ -655,13 +694,27 @@ struct DeserializingTreeWalker : public BaseWalker { case SerializedScriptValueData::NumberType: return jsNumber(m_exec, value.asDouble()); case SerializedScriptValueData::DateType: - return new (m_exec) DateInstance(m_exec, value.asDouble()); + return new (m_exec) DateInstance(m_exec, m_globalObject->dateStructure(), value.asDouble()); case SerializedScriptValueData::FileType: - return toJS(m_exec, static_cast<JSDOMGlobalObject*>(m_exec->lexicalGlobalObject()), File::create(value.asString().crossThreadString())); - default: + if (!m_isDOMGlobalObject) + return jsNull(); + return toJS(m_exec, static_cast<JSDOMGlobalObject*>(m_globalObject), File::create(value.asString().crossThreadString())); + case SerializedScriptValueData::FileListType: { + if (!m_isDOMGlobalObject) + return jsNull(); + RefPtr<FileList> result = FileList::create(); + SerializedFileList* serializedFileList = value.asFileList(); + unsigned length = serializedFileList->length(); + for (unsigned i = 0; i < length; i++) + result->append(File::create(serializedFileList->item(i))); + return toJS(m_exec, static_cast<JSDOMGlobalObject*>(m_globalObject), result.get()); + } + case SerializedScriptValueData::EmptyType: ASSERT_NOT_REACHED(); - return JSValue(); + return jsNull(); } + ASSERT_NOT_REACHED(); + return jsNull(); } void getPropertyNames(RefPtr<SerializedObject> object, Vector<SerializedObject::PropertyNameList, 16>& properties) @@ -699,12 +752,15 @@ struct DeserializingTreeWalker : public BaseWalker { } private: + void* operator new(size_t); + JSGlobalObject* m_globalObject; + bool m_isDOMGlobalObject; bool m_mustCopy; }; -JSValue SerializedScriptValueData::deserialize(ExecState* exec, bool mustCopy) const +JSValue SerializedScriptValueData::deserialize(ExecState* exec, JSGlobalObject* global, bool mustCopy) const { - DeserializingTreeWalker context(exec, mustCopy); + DeserializingTreeWalker context(exec, global, mustCopy); return walk<DeserializingTreeWalker>(context, *this); } @@ -808,11 +864,14 @@ struct TeardownTreeWalker { case SerializedScriptValueData::StringType: case SerializedScriptValueData::ImmediateType: case SerializedScriptValueData::NumberType: + case SerializedScriptValueData::DateType: + case SerializedScriptValueData::EmptyType: + case SerializedScriptValueData::FileType: + case SerializedScriptValueData::FileListType: return true; - default: - ASSERT_NOT_REACHED(); - return JSValue(); } + ASSERT_NOT_REACHED(); + return true; } void getPropertyNames(RefPtr<SerializedObject> object, Vector<SerializedObject::PropertyNameList, 16>& properties) @@ -860,6 +919,7 @@ SerializedScriptValue::~SerializedScriptValue() PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(JSContextRef originContext, JSValueRef apiValue, JSValueRef* exception) { + JSLock lock(SilenceAssertionsOnly); ExecState* exec = toJS(originContext); JSValue value = toJS(exec, apiValue); PassRefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::create(exec, value); @@ -875,8 +935,9 @@ PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(JSContextRef ori JSValueRef SerializedScriptValue::deserialize(JSContextRef destinationContext, JSValueRef* exception) { + JSLock lock(SilenceAssertionsOnly); ExecState* exec = toJS(destinationContext); - JSValue value = deserialize(exec); + JSValue value = deserialize(exec, exec->lexicalGlobalObject()); if (exec->hadException()) { if (exception) *exception = toRef(exec, exec->exception()); diff --git a/WebCore/bindings/js/SerializedScriptValue.h b/WebCore/bindings/js/SerializedScriptValue.h index 57a4a66..347d8f2 100644 --- a/WebCore/bindings/js/SerializedScriptValue.h +++ b/WebCore/bindings/js/SerializedScriptValue.h @@ -34,14 +34,17 @@ typedef const struct OpaqueJSValue* JSValueRef; namespace WebCore { class File; - class SerializedObject; + class FileList; class SerializedArray; + class SerializedFileList; + class SerializedObject; class SharedSerializedData : public RefCounted<SharedSerializedData> { public: virtual ~SharedSerializedData() { } SerializedArray* asArray(); SerializedObject* asObject(); + SerializedFileList* asFileList(); }; class SerializedScriptValue; @@ -56,12 +59,13 @@ namespace WebCore { ObjectType, ArrayType, StringType, - FileType + FileType, + FileListType }; SerializedType type() const { return m_type; } static SerializedScriptValueData serialize(JSC::ExecState*, JSC::JSValue); - JSC::JSValue deserialize(JSC::ExecState*, bool mustCopy) const; + JSC::JSValue deserialize(JSC::ExecState*, JSC::JSGlobalObject*, bool mustCopy) const; ~SerializedScriptValueData() { @@ -81,6 +85,7 @@ namespace WebCore { } explicit SerializedScriptValueData(const File*); + explicit SerializedScriptValueData(const FileList*); explicit SerializedScriptValueData(JSC::JSValue value) : m_type(ImmediateType) @@ -130,6 +135,13 @@ namespace WebCore { return m_sharedData->asArray(); } + SerializedFileList* asFileList() const + { + ASSERT(m_type == FileListType); + ASSERT(m_sharedData); + return m_sharedData->asFileList(); + } + operator bool() const { return m_type != EmptyType; } SerializedScriptValueData release() @@ -184,11 +196,11 @@ namespace WebCore { return m_value.asString(); } - JSC::JSValue deserialize(JSC::ExecState* exec) + JSC::JSValue deserialize(JSC::ExecState* exec, JSC::JSGlobalObject* globalObject) { if (!m_value) return JSC::jsNull(); - return m_value.deserialize(exec, m_mustCopy); + return m_value.deserialize(exec, globalObject, m_mustCopy); } JSValueRef deserialize(JSContextRef, JSValueRef* exception); diff --git a/WebCore/bindings/js/WorkerScriptController.cpp b/WebCore/bindings/js/WorkerScriptController.cpp index 5e27ef7..adcc089 100644 --- a/WebCore/bindings/js/WorkerScriptController.cpp +++ b/WebCore/bindings/js/WorkerScriptController.cpp @@ -58,9 +58,6 @@ WorkerScriptController::WorkerScriptController(WorkerContext* workerContext) WorkerScriptController::~WorkerScriptController() { m_workerContextWrapper = 0; // Unprotect the global object. - - ASSERT(!m_globalData->heap.protectedObjectCount()); - ASSERT(!m_globalData->heap.isBusy()); m_globalData->heap.destroy(); } |