diff options
Diffstat (limited to 'WebCore/bindings/v8')
152 files changed, 12852 insertions, 1389 deletions
diff --git a/WebCore/bindings/v8/ChildThreadDOMData.cpp b/WebCore/bindings/v8/ChildThreadDOMData.cpp new file mode 100644 index 0000000..77ce0f4 --- /dev/null +++ b/WebCore/bindings/v8/ChildThreadDOMData.cpp @@ -0,0 +1,48 @@ +/* + * 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: + * + * * 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. + */ + +#include "config.h" +#include "ChildThreadDOMData.h" + +namespace WebCore { + +ChildThreadDOMData::ChildThreadDOMData() + : m_defaultStore(this) +{ +} + +DOMDataStore& ChildThreadDOMData::getStore() +{ + ASSERT(!WTF::isMainThread()); + // Currently, child threads have only one world. + return m_defaultStore; +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/ChildThreadDOMData.h b/WebCore/bindings/v8/ChildThreadDOMData.h new file mode 100644 index 0000000..5097c86 --- /dev/null +++ b/WebCore/bindings/v8/ChildThreadDOMData.h @@ -0,0 +1,50 @@ +/* + * 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: + * + * * 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 ChildThreadDOMData_h +#define ChildThreadDOMData_h + +#include "DOMData.h" +#include "ScopedDOMDataStore.h" + +namespace WebCore { + + class ChildThreadDOMData : public DOMData { + public: + ChildThreadDOMData(); + DOMDataStore& getStore(); + + private: + ScopedDOMDataStore m_defaultStore; + }; + +} // namespace WebCore + +#endif // ChildThreadDOMData_h diff --git a/WebCore/bindings/v8/DOMData.cpp b/WebCore/bindings/v8/DOMData.cpp new file mode 100644 index 0000000..07254fe --- /dev/null +++ b/WebCore/bindings/v8/DOMData.cpp @@ -0,0 +1,130 @@ +/* + * 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: + * + * * 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. + */ + +#include "config.h" +#include "DOMData.h" + +#include "ChildThreadDOMData.h" +#include "MainThreadDOMData.h" + +namespace WebCore { + +DOMData::DOMData() + : m_delayedProcessingScheduled(false) + , m_isMainThread(WTF::isMainThread()) + , m_owningThread(WTF::currentThread()) +{ +} + +DOMData* DOMData::getCurrent() +{ + if (WTF::isMainThread()) + return getCurrentMainThread(); + + DEFINE_STATIC_LOCAL(WTF::ThreadSpecific<ChildThreadDOMData>, childThreadDOMData, ()); + return childThreadDOMData; +} + +DOMData* DOMData::getCurrentMainThread() +{ + ASSERT(WTF::isMainThread()); + DEFINE_STATIC_LOCAL(MainThreadDOMData, mainThreadDOMData, ()); + return &mainThreadDOMData; +} + +void DOMData::ensureDeref(V8ClassIndex::V8WrapperType type, void* domObject) +{ + if (m_owningThread == WTF::currentThread()) { + // No need to delay the work. We can deref right now. + derefObject(type, domObject); + return; + } + + // We need to do the deref on the correct thread. + m_delayedObjectMap.set(domObject, type); + + // Post a task to the owning thread in order to process the delayed queue. + // FIXME: For now, we can only post to main thread due to WTF task posting limitation. We will fix this when we work on nested worker. + if (!m_delayedProcessingScheduled) { + m_delayedProcessingScheduled = true; + if (isMainThread()) + WTF::callOnMainThread(&derefDelayedObjectsInCurrentThread, 0); + } +} + +void DOMData::derefObject(V8ClassIndex::V8WrapperType type, void* domObject) +{ + switch (type) { + case V8ClassIndex::NODE: + static_cast<Node*>(domObject)->deref(); + break; + +#define MakeCase(type, name) \ + case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break; + DOM_OBJECT_TYPES(MakeCase) // This includes both active and non-active. +#undef MakeCase + +#if ENABLE(SVG) +#define MakeCase(type, name) \ + case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break; + SVG_OBJECT_TYPES(MakeCase) // This also includes SVGElementInstance. +#undef MakeCase + +#define MakeCase(type, name) \ + case V8ClassIndex::type: \ + static_cast<V8SVGPODTypeWrapper<name>*>(domObject)->deref(); break; + SVG_POD_NATIVE_TYPES(MakeCase) +#undef MakeCase +#endif + + default: + ASSERT_NOT_REACHED(); + break; + } +} + +void DOMData::derefDelayedObjects() +{ + WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); + + m_delayedProcessingScheduled = false; + + for (DelayedObjectMap::iterator iter(m_delayedObjectMap.begin()); iter != m_delayedObjectMap.end(); ++iter) + derefObject(iter->second, iter->first); + + m_delayedObjectMap.clear(); +} + +void DOMData::derefDelayedObjectsInCurrentThread(void*) +{ + getCurrent()->derefDelayedObjects(); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/DOMData.h b/WebCore/bindings/v8/DOMData.h new file mode 100644 index 0000000..5effe7c --- /dev/null +++ b/WebCore/bindings/v8/DOMData.h @@ -0,0 +1,136 @@ +/* + * 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: + * + * * 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 DOMData_h +#define DOMData_h + +#include "DOMDataStore.h" + +namespace WebCore { + + // DOMData + // + // DOMData represents the all the DOM wrappers for a given thread. In + // particular, DOMData holds wrappers for all the isolated worlds in the + // thread. The DOMData for the main thread and the DOMData for child threads + // use different subclasses. + // + class DOMData : public Noncopyable { + public: + DOMData(); + + static DOMData* getCurrent(); + static DOMData* getCurrentMainThread(); // Caller must be on the main thread. + virtual DOMDataStore& getStore() = 0; + + template<typename T> + static void handleWeakObject(DOMDataStore::DOMWrapperMapType, v8::Handle<v8::Object>, T* domObject); + + void forgetDelayedObject(void* object) { m_delayedObjectMap.take(object); } + + // This is to ensure that we will deref DOM objects from the owning thread, + // not the GC thread. The helper function will be scheduled by the GC + // thread to get called from the owning thread. + static void derefDelayedObjectsInCurrentThread(void*); + void derefDelayedObjects(); + + template<typename T> + static void removeObjectsFromWrapperMap(DOMWrapperMap<T>& domMap); + + ThreadIdentifier owningThread() const { return m_owningThread; } + + private: + typedef WTF::HashMap<void*, V8ClassIndex::V8WrapperType> DelayedObjectMap; + + void ensureDeref(V8ClassIndex::V8WrapperType type, void* domObject); + static void derefObject(V8ClassIndex::V8WrapperType type, void* domObject); + + // Stores all the DOM objects that are delayed to be processed when the + // owning thread gains control. + DelayedObjectMap m_delayedObjectMap; + + // The flag to indicate if the task to do the delayed process has + // already been posted. + bool m_delayedProcessingScheduled; + + bool m_isMainThread; + ThreadIdentifier m_owningThread; + }; + + // Called when the dead object is not in GC thread's map. Go through all + // thread maps to find the one containing it. Then clear the JS reference + // and push the DOM object into the delayed queue for it to be deref-ed at + // later time from the owning thread. + // + // * This is called when the GC thread is not the owning thread. + // * This can be called on any thread that has GC running. + // * Only one V8 instance is running at a time due to V8::Locker. So we don't need to worry about concurrency. + // + template<typename T> + void DOMData::handleWeakObject(DOMDataStore::DOMWrapperMapType mapType, v8::Handle<v8::Object> v8Object, T* domObject) + { + + WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); + DOMDataList& list = DOMDataStore::allStores(); + for (size_t i = 0; i < list.size(); ++i) { + DOMDataStore* store = list[i]; + + DOMDataStore::InternalDOMWrapperMap<T>* domMap = static_cast<DOMDataStore::InternalDOMWrapperMap<T>*>(store->getDOMWrapperMap(mapType)); + + v8::Handle<v8::Object> wrapper = domMap->get(domObject); + if (*wrapper == *v8Object) { + // Clear the JS reference. + domMap->forgetOnly(domObject); + store->domData()->ensureDeref(V8DOMWrapper::domWrapperType(v8Object), domObject); + } + } + } + + template<typename T> + void DOMData::removeObjectsFromWrapperMap(DOMWrapperMap<T>& domMap) + { + for (typename WTF::HashMap<T*, v8::Object*>::iterator iter(domMap.impl().begin()); iter != domMap.impl().end(); ++iter) { + T* domObject = static_cast<T*>(iter->first); + v8::Persistent<v8::Object> v8Object(iter->second); + + V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(v8::Handle<v8::Object>::Cast(v8Object)); + + // Deref the DOM object. + derefObject(type, domObject); + + // Clear the JS wrapper. + v8Object.Dispose(); + } + domMap.impl().clear(); + } + +} // namespace WebCore + +#endif // DOMData_h diff --git a/WebCore/bindings/v8/DOMDataStore.cpp b/WebCore/bindings/v8/DOMDataStore.cpp new file mode 100644 index 0000000..a76ca53 --- /dev/null +++ b/WebCore/bindings/v8/DOMDataStore.cpp @@ -0,0 +1,199 @@ +/* + * 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: + * + * * 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. + */ + +#include "config.h" +#include "DOMDataStore.h" + +#include "DOMData.h" + +namespace WebCore { + +// DOM binding algorithm: +// +// There are two kinds of DOM objects: +// 1. DOM tree nodes, such as Document, HTMLElement, ... +// there classes implement TreeShared<T> interface; +// 2. Non-node DOM objects, such as CSSRule, Location, etc. +// these classes implement a ref-counted scheme. +// +// A DOM object may have a JS wrapper object. If a tree node +// is alive, its JS wrapper must be kept alive even it is not +// reachable from JS roots. +// However, JS wrappers of non-node objects can go away if +// not reachable from other JS objects. It works like a cache. +// +// DOM objects are ref-counted, and JS objects are traced from +// a set of root objects. They can create a cycle. To break +// cycles, we do following: +// Handles from DOM objects to JS wrappers are always weak, +// so JS wrappers of non-node object cannot create a cycle. +// Before starting a global GC, we create a virtual connection +// between nodes in the same tree in the JS heap. If the wrapper +// of one node in a tree is alive, wrappers of all nodes in +// the same tree are considered alive. This is done by creating +// object groups in GC prologue callbacks. The mark-compact +// collector will remove these groups after each GC. +// +// DOM objects should be deref-ed from the owning thread, not the GC thread +// that does not own them. In V8, GC can kick in from any thread. To ensure +// that DOM objects are always deref-ed from the owning thread when running +// V8 in multi-threading environment, we do following: +// 1. Maintain a thread specific DOM wrapper map for each object map. +// (We're using TLS support from WTF instead of base since V8Bindings +// does not depend on base. We further assume that all child threads +// running V8 instances are created by WTF and thus a destructor will +// be called to clean up all thread specific data.) +// 2. When GC happens: +// 2.1. If the dead object is in GC thread's map, remove the JS reference +// and deref the DOM object. +// 2.2. Otherwise, go through all thread maps to find the owning thread. +// Remove the JS reference from the owning thread's map and move the +// DOM object to a delayed queue. Post a task to the owning thread +// to have it deref-ed from the owning thread at later time. +// 3. When a thread is tearing down, invoke a cleanup routine to go through +// all objects in the delayed queue and the thread map and deref all of +// them. + + +DOMDataStore::DOMDataStore(DOMData* domData) + : m_domNodeMap(0) + , m_domObjectMap(0) + , m_activeDomObjectMap(0) +#if ENABLE(SVG) + , m_domSvgElementInstanceMap(0) + , m_domSvgObjectWithContextMap(0) +#endif + , m_domData(domData) +{ + WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); + DOMDataStore::allStores().append(this); +} + +DOMDataStore::~DOMDataStore() +{ + WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); + DOMDataStore::allStores().remove(DOMDataStore::allStores().find(this)); +} + +DOMDataList& DOMDataStore::allStores() +{ + DEFINE_STATIC_LOCAL(DOMDataList, staticDOMDataList, ()); + return staticDOMDataList; +} + +WTF::Mutex& DOMDataStore::allStoresMutex() +{ + DEFINE_STATIC_LOCAL(WTF::Mutex, staticDOMDataListMutex, ()); + return staticDOMDataListMutex; +} + +void DOMDataStore::forgetDelayedObject(DOMData* domData, void* object) +{ + domData->forgetDelayedObject(object); +} + +void* DOMDataStore::getDOMWrapperMap(DOMWrapperMapType type) +{ + switch (type) { + case DOMNodeMap: + return m_domNodeMap; + case DOMObjectMap: + return m_domObjectMap; + case ActiveDOMObjectMap: + return m_activeDomObjectMap; +#if ENABLE(SVG) + case DOMSVGElementInstanceMap: + return m_domSvgElementInstanceMap; + case DOMSVGObjectWithContextMap: + return m_domSvgObjectWithContextMap; +#endif + } + + ASSERT_NOT_REACHED(); + return 0; +} + +// Called when the object is near death (not reachable from JS roots). +// It is time to remove the entry from the table and dispose the handle. +void DOMDataStore::weakDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject) +{ + v8::HandleScope scope; + ASSERT(v8Object->IsObject()); + DOMData::handleWeakObject(DOMDataStore::DOMObjectMap, v8::Handle<v8::Object>::Cast(v8Object), domObject); +} + +void DOMDataStore::weakActiveDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject) +{ + v8::HandleScope scope; + ASSERT(v8Object->IsObject()); + DOMData::handleWeakObject(DOMDataStore::ActiveDOMObjectMap, v8::Handle<v8::Object>::Cast(v8Object), domObject); +} + +void DOMDataStore::weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* domObject) +{ + ASSERT(WTF::isMainThread()); + + Node* node = static_cast<Node*>(domObject); + + WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); + DOMDataList& list = DOMDataStore::allStores(); + for (size_t i = 0; i < list.size(); ++i) { + DOMDataStore* store = list[i]; + HashMap<Node*, v8::Object*>& domMapImpl = store->domNodeMap().impl(); + HashMap<Node*, v8::Object*>::iterator it = domMapImpl.find(node); + if (it == domMapImpl.end() || it->second != *v8Object) + continue; + ASSERT(store->domData()->owningThread() == WTF::currentThread()); + v8Object.Dispose(); + domMapImpl.remove(it); + node->deref(); // Nobody overrides Node::deref so it's safe + break; // There might be at most one wrapper for the node in world's maps + } +} + +#if ENABLE(SVG) + +void DOMDataStore::weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, void* domObject) +{ + v8::HandleScope scope; + ASSERT(v8Object->IsObject()); + DOMData::handleWeakObject(DOMDataStore::DOMSVGElementInstanceMap, v8::Handle<v8::Object>::Cast(v8Object), static_cast<SVGElementInstance*>(domObject)); +} + +void DOMDataStore::weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object, void* domObject) +{ + v8::HandleScope scope; + ASSERT(v8Object->IsObject()); + DOMData::handleWeakObject(DOMDataStore::DOMSVGObjectWithContextMap, v8::Handle<v8::Object>::Cast(v8Object), domObject); +} + +#endif // ENABLE(SVG) + +} // namespace WebCore diff --git a/WebCore/bindings/v8/DOMDataStore.h b/WebCore/bindings/v8/DOMDataStore.h new file mode 100644 index 0000000..b127089 --- /dev/null +++ b/WebCore/bindings/v8/DOMDataStore.h @@ -0,0 +1,142 @@ +/* + * 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: + * + * * 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 DOMDataStore_h +#define DOMDataStore_h + +#include "DOMObjectsInclude.h" + +#include <v8.h> +#include <wtf/HashMap.h> +#include <wtf/MainThread.h> +#include <wtf/Noncopyable.h> +#include <wtf/OwnPtr.h> +#include <wtf/StdLibExtras.h> +#include <wtf/Threading.h> +#include <wtf/ThreadSpecific.h> +#include <wtf/Vector.h> + +namespace WebCore { + + class DOMData; + + typedef WTF::Vector<DOMDataStore*> DOMDataList; + + // DOMDataStore + // + // DOMDataStore is the backing store that holds the maps between DOM objects + // and JavaScript objects. In general, each thread can have multiple backing + // stores, one per isolated world. + // + // This class doesn't manage the lifetime of the store. The data store + // lifetime is managed by subclasses. + // + class DOMDataStore : public Noncopyable { + public: + enum DOMWrapperMapType { + DOMNodeMap, + DOMObjectMap, + ActiveDOMObjectMap, +#if ENABLE(SVG) + DOMSVGElementInstanceMap, + DOMSVGObjectWithContextMap +#endif + }; + + template <class KeyType> + class InternalDOMWrapperMap : public DOMWrapperMap<KeyType> { + public: + InternalDOMWrapperMap(DOMData* domData, v8::WeakReferenceCallback callback) + : DOMWrapperMap<KeyType>(callback), m_domData(domData) { } + + virtual void forget(KeyType* object) + { + DOMWrapperMap<KeyType>::forget(object); + forgetDelayedObject(m_domData, object); + } + + void forgetOnly(KeyType* object) { DOMWrapperMap<KeyType>::forget(object); } + + private: + DOMData* m_domData; + }; + + DOMDataStore(DOMData*); + virtual ~DOMDataStore(); + + // A list of all DOMDataStore objects. Traversed during GC to find a thread-specific map that + // contains the object - so we can schedule the object to be deleted on the thread which created it. + static DOMDataList& allStores(); + // Mutex to protect against concurrent access of DOMDataList. + static WTF::Mutex& allStoresMutex(); + + // Helper function to avoid circular includes. + static void forgetDelayedObject(DOMData*, void* object); + + DOMData* domData() const { return m_domData; } + + void* getDOMWrapperMap(DOMWrapperMapType); + + InternalDOMWrapperMap<Node>& domNodeMap() { return *m_domNodeMap; } + InternalDOMWrapperMap<void>& domObjectMap() { return *m_domObjectMap; } + InternalDOMWrapperMap<void>& activeDomObjectMap() { return *m_activeDomObjectMap; } +#if ENABLE(SVG) + InternalDOMWrapperMap<SVGElementInstance>& domSvgElementInstanceMap() { return *m_domSvgElementInstanceMap; } + InternalDOMWrapperMap<void>& domSvgObjectWithContextMap() { return *m_domSvgObjectWithContextMap; } +#endif + + // Need by V8GCController. + static void weakActiveDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject); + + protected: + static void weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* domObject); + static void weakDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject); +#if ENABLE(SVG) + static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, void* domObject); + // SVG non-node elements may have a reference to a context node which should be notified when the element is change. + static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object, void* domObject); +#endif + + InternalDOMWrapperMap<Node>* m_domNodeMap; + InternalDOMWrapperMap<void>* m_domObjectMap; + InternalDOMWrapperMap<void>* m_activeDomObjectMap; +#if ENABLE(SVG) + InternalDOMWrapperMap<SVGElementInstance>* m_domSvgElementInstanceMap; + InternalDOMWrapperMap<void>* m_domSvgObjectWithContextMap; +#endif + + private: + // A back-pointer to the DOMData to which we belong. + DOMData* m_domData; + }; + +} // namespace WebCore + +#endif // DOMDataStore_h diff --git a/WebCore/bindings/v8/DOMObjectsInclude.h b/WebCore/bindings/v8/DOMObjectsInclude.h new file mode 100644 index 0000000..63464db --- /dev/null +++ b/WebCore/bindings/v8/DOMObjectsInclude.h @@ -0,0 +1,229 @@ +/* + * 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: + * + * * 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 DOMObjectsInclude_h +#define DOMObjectsInclude_h + +#include "AbstractWorker.h" +#include "BarInfo.h" +#include "CanvasGradient.h" +#include "CanvasPattern.h" +#include "CanvasPixelArray.h" +#include "CanvasRenderingContext2D.h" +#include "CanvasStyle.h" +#include "CharacterData.h" +#include "ClientRect.h" +#include "ClientRectList.h" +#include "Clipboard.h" +#include "Console.h" +#include "Counter.h" +#include "CSSCharsetRule.h" +#include "CSSFontFaceRule.h" +#include "CSSImportRule.h" +#include "CSSMediaRule.h" +#include "CSSPageRule.h" +#include "CSSRule.h" +#include "CSSRuleList.h" +#include "CSSStyleDeclaration.h" +#include "CSSStyleRule.h" +#include "CSSStyleSheet.h" +#include "CSSValueList.h" +#include "CSSVariablesDeclaration.h" +#include "CSSVariablesRule.h" +#include "Database.h" +#include "DocumentType.h" +#include "DocumentFragment.h" +#include "DOMCoreException.h" +#include "DOMImplementation.h" +#include "DOMParser.h" +#include "DOMSelection.h" +#include "DOMWindow.h" +#include "Entity.h" +#include "ErrorEvent.h" +#include "EventListener.h" +#include "EventTarget.h" +#include "Event.h" +#include "EventException.h" +#include "ExceptionCode.h" +#include "File.h" +#include "FileList.h" +#include "Frame.h" +#include "FrameLoader.h" +#include "FrameTree.h" +#include "History.h" +#include "HTMLNames.h" +#include "HTMLDocument.h" +#include "HTMLElement.h" +#include "HTMLImageElement.h" +#include "HTMLInputElement.h" +#include "HTMLSelectElement.h" +#include "HTMLOptionsCollection.h" +#include "ImageData.h" +#include "InspectorBackend.h" +#include "KeyboardEvent.h" +#include "Location.h" +#include "Media.h" +#include "MediaError.h" +#include "MediaList.h" +#include "MediaPlayer.h" +#include "MessageChannel.h" +#include "MessageEvent.h" +#include "MessagePort.h" +#include "MimeTypeArray.h" +#include "MouseEvent.h" +#include "MutationEvent.h" +#include "Navigator.h" // for MimeTypeArray +#include "NodeFilter.h" +#include "Notation.h" +#include "NodeList.h" +#include "NodeIterator.h" +#include "OverflowEvent.h" +#include "Page.h" +#include "Plugin.h" +#include "PluginArray.h" +#include "ProcessingInstruction.h" +#include "ProgressEvent.h" +#include "Range.h" +#include "RangeException.h" +#include "Rect.h" +#include "RGBColor.h" +#include "Screen.h" +#include "ScriptExecutionContext.h" +#include "SecurityOrigin.h" +#include "Settings.h" +#include "SharedWorker.h" +#include "SharedWorkerContext.h" +#include "SQLTransaction.h" +#include "SQLResultSet.h" +#include "SQLResultSetRowList.h" +#include "StyleSheet.h" +#include "StyleSheetList.h" +#include "SVGColor.h" +#include "SVGPaint.h" +#include "TextEvent.h" +#include "TextMetrics.h" +#include "TimeRanges.h" +#include "TreeWalker.h" +#include "XSLTProcessor.h" +#include "V8AbstractEventListener.h" +#include "V8CustomEventListener.h" +#include "V8DOMWindow.h" +#include "V8HTMLElement.h" +#include "V8LazyEventListener.h" +#include "V8NodeFilterCondition.h" +#include "V8ObjectEventListener.h" +#include "ValidityState.h" +#include "WebKitAnimationEvent.h" +#include "WebKitCSSKeyframeRule.h" +#include "WebKitCSSKeyframesRule.h" +#include "WebKitCSSMatrix.h" +#include "WebKitCSSTransformValue.h" +#include "WebKitPoint.h" +#include "WebKitTransitionEvent.h" +#include "WheelEvent.h" +#include "XMLHttpRequest.h" +#include "XMLHttpRequestException.h" +#include "XMLHttpRequestProgressEvent.h" +#include "XMLHttpRequestUpload.h" +#include "XMLSerializer.h" +#include "XPathException.h" +#include "XPathExpression.h" +#include "XPathNSResolver.h" +#include "XPathResult.h" + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +#include "DOMApplicationCache.h" +#endif + +#if ENABLE(DATAGRID) +#include "DataGridColumn.h" +#include "DataGridColumnList.h" +#endif // DATAGRID + +#if ENABLE(DOM_STORAGE) +#include "Storage.h" +#include "StorageEvent.h" +#endif // DOM_STORAGE + +#if ENABLE(SVG) +#include "SVGAngle.h" +#include "SVGAnimatedPoints.h" +#include "SVGElement.h" +#include "SVGElementInstance.h" +#include "SVGElementInstanceList.h" +#include "SVGException.h" +#include "SVGLength.h" +#include "SVGLengthList.h" +#include "SVGNumberList.h" +#include "SVGPathSeg.h" +#include "SVGPathSegArc.h" +#include "SVGPathSegClosePath.h" +#include "SVGPathSegCurvetoCubic.h" +#include "SVGPathSegCurvetoCubicSmooth.h" +#include "SVGPathSegCurvetoQuadratic.h" +#include "SVGPathSegCurvetoQuadraticSmooth.h" +#include "SVGPathSegLineto.h" +#include "SVGPathSegLinetoHorizontal.h" +#include "SVGPathSegLinetoVertical.h" +#include "SVGPathSegList.h" +#include "SVGPathSegMoveto.h" +#include "SVGPointList.h" +#include "SVGPreserveAspectRatio.h" +#include "SVGRenderingIntent.h" +#include "SVGStringList.h" +#include "SVGTransform.h" +#include "SVGTransformList.h" +#include "SVGUnitTypes.h" +#include "SVGURIReference.h" +#include "SVGZoomEvent.h" +#include "V8SVGPODTypeWrapper.h" +#endif // SVG + +#if ENABLE(WORKERS) +#include "DedicatedWorkerContext.h" +#include "Worker.h" +#include "WorkerContext.h" +#include "WorkerLocation.h" +#include "WorkerNavigator.h" +#endif // WORKERS + +#if ENABLE(XPATH) +#include "XPathEvaluator.h" +#endif // XPATH + +namespace WebCore { + + // A helper class for undetectable document.all + class HTMLAllCollection : public HTMLCollection { + }; + +} // namespace WebCore + +#endif // DOMObjectsInclude_h diff --git a/WebCore/bindings/v8/DerivedSourcesAllInOne.cpp b/WebCore/bindings/v8/DerivedSourcesAllInOne.cpp new file mode 100644 index 0000000..4962a92 --- /dev/null +++ b/WebCore/bindings/v8/DerivedSourcesAllInOne.cpp @@ -0,0 +1,338 @@ +/* + * 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: + * + * * 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. + */ + +// This source file coalesces the HTML elements into a single object file to +// reduce bloat and allow us to link release builds on 32-bit Windows. + +#include "bindings/V8AbstractWorker.cpp" +#include "bindings/V8Attr.cpp" +#include "bindings/V8BarInfo.cpp" +#include "bindings/V8CanvasGradient.cpp" +#include "bindings/V8CanvasPattern.cpp" +#include "bindings/V8CanvasPixelArray.cpp" +#include "bindings/V8CanvasRenderingContext2D.cpp" +#include "bindings/V8CDATASection.cpp" +#include "bindings/V8CharacterData.cpp" +#include "bindings/V8ClientRect.cpp" +#include "bindings/V8ClientRectList.cpp" +#include "bindings/V8Clipboard.cpp" +#include "bindings/V8Comment.cpp" +#include "bindings/V8Console.cpp" +#include "bindings/V8Counter.cpp" +#include "bindings/V8CSSCharsetRule.cpp" +#include "bindings/V8CSSFontFaceRule.cpp" +#include "bindings/V8CSSImportRule.cpp" +#include "bindings/V8CSSMediaRule.cpp" +#include "bindings/V8CSSPageRule.cpp" +#include "bindings/V8CSSPrimitiveValue.cpp" +#include "bindings/V8CSSRule.cpp" +#include "bindings/V8CSSRuleList.cpp" +#include "bindings/V8CSSStyleDeclaration.cpp" +#include "bindings/V8CSSStyleRule.cpp" +#include "bindings/V8CSSStyleSheet.cpp" +#include "bindings/V8CSSValue.cpp" +#include "bindings/V8CSSValueList.cpp" +#include "bindings/V8CSSVariablesDeclaration.cpp" +#include "bindings/V8CSSVariablesRule.cpp" +#include "bindings/V8Database.cpp" +#include "bindings/V8DataGridColumn.cpp" +#include "bindings/V8DataGridColumnList.cpp" +#include "bindings/V8DedicatedWorkerContext.cpp" +#include "bindings/V8Document.cpp" +#include "bindings/V8DocumentFragment.cpp" +#include "bindings/V8DocumentType.cpp" +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +#include "bindings/V8DOMApplicationCache.cpp" +#endif +#include "bindings/V8DOMCoreException.cpp" +#include "bindings/V8DOMImplementation.cpp" +#include "bindings/V8DOMParser.cpp" +#include "bindings/V8DOMSelection.cpp" +#include "bindings/V8DOMWindow.cpp" +#include "bindings/V8Element.cpp" +#include "bindings/V8Entity.cpp" +#include "bindings/V8EntityReference.cpp" +#include "bindings/V8ErrorEvent.cpp" +#include "bindings/V8Event.cpp" +#include "bindings/V8EventException.cpp" +#include "bindings/V8File.cpp" +#include "bindings/V8FileList.cpp" +#include "bindings/V8History.cpp" +#include "bindings/V8HTMLAllCollection.cpp" +#include "bindings/V8HTMLAnchorElement.cpp" +#include "bindings/V8HTMLAppletElement.cpp" +#include "bindings/V8HTMLAreaElement.cpp" +#include "bindings/V8HTMLAudioElement.cpp" +#include "bindings/V8HTMLBaseElement.cpp" +#include "bindings/V8HTMLBaseFontElement.cpp" +#include "bindings/V8HTMLBlockquoteElement.cpp" +#include "bindings/V8HTMLBodyElement.cpp" +#include "bindings/V8HTMLBRElement.cpp" +#include "bindings/V8HTMLButtonElement.cpp" +#include "bindings/V8HTMLCanvasElement.cpp" +#include "bindings/V8HTMLCollection.cpp" +#include "bindings/V8HTMLDataGridCellElement.cpp" +#include "bindings/V8HTMLDataGridColElement.cpp" +#include "bindings/V8HTMLDataGridElement.cpp" +#include "bindings/V8HTMLDataGridRowElement.cpp" +#include "bindings/V8HTMLDirectoryElement.cpp" +#include "bindings/V8HTMLDivElement.cpp" +#include "bindings/V8HTMLDListElement.cpp" +#include "bindings/V8HTMLDocument.cpp" +#include "bindings/V8HTMLElement.cpp" +#include "bindings/V8HTMLEmbedElement.cpp" +#include "bindings/V8HTMLFieldSetElement.cpp" +#include "bindings/V8HTMLFontElement.cpp" +#include "bindings/V8HTMLFormElement.cpp" +#include "bindings/V8HTMLFrameElement.cpp" +#include "bindings/V8HTMLFrameSetElement.cpp" +#include "bindings/V8HTMLHeadElement.cpp" +#include "bindings/V8HTMLHeadingElement.cpp" +#include "bindings/V8HTMLHRElement.cpp" +#include "bindings/V8HTMLHtmlElement.cpp" +#include "bindings/V8HTMLIFrameElement.cpp" +#include "bindings/V8HTMLImageElement.cpp" +#include "bindings/V8HTMLInputElement.cpp" +#include "bindings/V8HTMLIsIndexElement.cpp" +#include "bindings/V8HTMLLabelElement.cpp" +#include "bindings/V8HTMLLegendElement.cpp" +#include "bindings/V8HTMLLIElement.cpp" +#include "bindings/V8HTMLLinkElement.cpp" +#include "bindings/V8HTMLMapElement.cpp" +#include "bindings/V8HTMLMarqueeElement.cpp" +#include "bindings/V8HTMLMediaElement.cpp" +#include "bindings/V8HTMLMenuElement.cpp" +#include "bindings/V8HTMLMetaElement.cpp" +#include "bindings/V8HTMLModElement.cpp" +#include "bindings/V8HTMLObjectElement.cpp" +#include "bindings/V8HTMLOListElement.cpp" +#include "bindings/V8HTMLOptGroupElement.cpp" +#include "bindings/V8HTMLOptionElement.cpp" +#include "bindings/V8HTMLOptionsCollection.cpp" +#include "bindings/V8HTMLParagraphElement.cpp" +#include "bindings/V8HTMLParamElement.cpp" +#include "bindings/V8HTMLPreElement.cpp" +#include "bindings/V8HTMLQuoteElement.cpp" +#include "bindings/V8HTMLScriptElement.cpp" +#include "bindings/V8HTMLSelectElement.cpp" +#include "bindings/V8HTMLSourceElement.cpp" +#include "bindings/V8HTMLStyleElement.cpp" +#include "bindings/V8HTMLTableCaptionElement.cpp" +#include "bindings/V8HTMLTableCellElement.cpp" +#include "bindings/V8HTMLTableColElement.cpp" +#include "bindings/V8HTMLTableElement.cpp" +#include "bindings/V8HTMLTableRowElement.cpp" +#include "bindings/V8HTMLTableSectionElement.cpp" +#include "bindings/V8HTMLTextAreaElement.cpp" +#include "bindings/V8HTMLTitleElement.cpp" +#include "bindings/V8HTMLUListElement.cpp" +#include "bindings/V8HTMLVideoElement.cpp" +#include "bindings/V8ImageData.cpp" +#include "bindings/V8InspectorBackend.cpp" +#include "bindings/V8KeyboardEvent.cpp" +#include "bindings/V8Location.cpp" +#include "bindings/V8Media.cpp" +#include "bindings/V8MediaError.cpp" +#include "bindings/V8MediaList.cpp" +#include "bindings/V8MessageChannel.cpp" +#include "bindings/V8MessageEvent.cpp" +#include "bindings/V8MessagePort.cpp" +#include "bindings/V8MimeType.cpp" +#include "bindings/V8MimeTypeArray.cpp" +#include "bindings/V8MouseEvent.cpp" +#include "bindings/V8MutationEvent.cpp" +#include "bindings/V8NamedNodeMap.cpp" +#include "bindings/V8Navigator.cpp" +#include "bindings/V8Node.cpp" +#include "bindings/V8NodeFilter.cpp" +#include "bindings/V8NodeIterator.cpp" +#include "bindings/V8NodeList.cpp" +#include "bindings/V8Notation.cpp" +#include "bindings/V8OverflowEvent.cpp" +#include "bindings/V8Plugin.cpp" +#include "bindings/V8PluginArray.cpp" +#include "bindings/V8ProcessingInstruction.cpp" +#include "bindings/V8ProgressEvent.cpp" +#include "bindings/V8Range.cpp" +#include "bindings/V8RangeException.cpp" +#include "bindings/V8Rect.cpp" +#include "bindings/V8RGBColor.cpp" +#include "bindings/V8Screen.cpp" +#include "bindings/V8SharedWorker.cpp" +#include "bindings/V8SQLError.cpp" +#include "bindings/V8SQLResultSet.cpp" +#include "bindings/V8SQLResultSetRowList.cpp" +#include "bindings/V8SQLTransaction.cpp" +#if ENABLE(DOM_STORAGE) +#include "bindings/V8Storage.cpp" +#include "bindings/V8StorageEvent.cpp" +#endif +#include "bindings/V8StyleSheet.cpp" +#include "bindings/V8StyleSheetList.cpp" +#include "bindings/V8SVGAElement.cpp" +#include "bindings/V8SVGAltGlyphElement.cpp" +#include "bindings/V8SVGAngle.cpp" +#include "bindings/V8SVGAnimateColorElement.cpp" +#include "bindings/V8SVGAnimatedAngle.cpp" +#include "bindings/V8SVGAnimatedBoolean.cpp" +#include "bindings/V8SVGAnimatedEnumeration.cpp" +#include "bindings/V8SVGAnimatedInteger.cpp" +#include "bindings/V8SVGAnimatedLength.cpp" +#include "bindings/V8SVGAnimatedLengthList.cpp" +#include "bindings/V8SVGAnimatedNumber.cpp" +#include "bindings/V8SVGAnimatedNumberList.cpp" +#include "bindings/V8SVGAnimatedPoints.cpp" +#include "bindings/V8SVGAnimatedPreserveAspectRatio.cpp" +#include "bindings/V8SVGAnimatedRect.cpp" +#include "bindings/V8SVGAnimatedString.cpp" +#include "bindings/V8SVGAnimatedTransformList.cpp" +#include "bindings/V8SVGAnimateElement.cpp" +#include "bindings/V8SVGAnimateTransformElement.cpp" +#include "bindings/V8SVGAnimationElement.cpp" +#include "bindings/V8SVGCircleElement.cpp" +#include "bindings/V8SVGClipPathElement.cpp" +#include "bindings/V8SVGColor.cpp" +#include "bindings/V8SVGCursorElement.cpp" +#include "bindings/V8SVGDefinitionSrcElement.cpp" +#include "bindings/V8SVGDefsElement.cpp" +#include "bindings/V8SVGDescElement.cpp" +#include "bindings/V8SVGDocument.cpp" +#include "bindings/V8SVGElement.cpp" +#include "bindings/V8SVGElementInstance.cpp" +#include "bindings/V8SVGElementInstanceList.cpp" +#include "bindings/V8SVGEllipseElement.cpp" +#include "bindings/V8SVGException.cpp" +#include "bindings/V8SVGFontElement.cpp" +#include "bindings/V8SVGFontFaceElement.cpp" +#include "bindings/V8SVGFontFaceFormatElement.cpp" +#include "bindings/V8SVGFontFaceNameElement.cpp" +#include "bindings/V8SVGFontFaceSrcElement.cpp" +#include "bindings/V8SVGFontFaceUriElement.cpp" +#include "bindings/V8SVGForeignObjectElement.cpp" +#include "bindings/V8SVGGElement.cpp" +#include "bindings/V8SVGGlyphElement.cpp" +#include "bindings/V8SVGGradientElement.cpp" +#include "bindings/V8SVGImageElement.cpp" +#include "bindings/V8SVGLength.cpp" +#include "bindings/V8SVGLengthList.cpp" +#include "bindings/V8SVGLinearGradientElement.cpp" +#include "bindings/V8SVGLineElement.cpp" +#include "bindings/V8SVGMarkerElement.cpp" +#include "bindings/V8SVGMaskElement.cpp" +#include "bindings/V8SVGMatrix.cpp" +#include "bindings/V8SVGMetadataElement.cpp" +#include "bindings/V8SVGMissingGlyphElement.cpp" +#include "bindings/V8SVGNumber.cpp" +#include "bindings/V8SVGNumberList.cpp" +#include "bindings/V8SVGPaint.cpp" +#include "bindings/V8SVGPathElement.cpp" +#include "bindings/V8SVGPathSeg.cpp" +#include "bindings/V8SVGPathSegArcAbs.cpp" +#include "bindings/V8SVGPathSegArcRel.cpp" +#include "bindings/V8SVGPathSegClosePath.cpp" +#include "bindings/V8SVGPathSegCurvetoCubicAbs.cpp" +#include "bindings/V8SVGPathSegCurvetoCubicRel.cpp" +#include "bindings/V8SVGPathSegCurvetoCubicSmoothAbs.cpp" +#include "bindings/V8SVGPathSegCurvetoCubicSmoothRel.cpp" +#include "bindings/V8SVGPathSegCurvetoQuadraticAbs.cpp" +#include "bindings/V8SVGPathSegCurvetoQuadraticRel.cpp" +#include "bindings/V8SVGPathSegCurvetoQuadraticSmoothAbs.cpp" +#include "bindings/V8SVGPathSegCurvetoQuadraticSmoothRel.cpp" +#include "bindings/V8SVGPathSegLinetoAbs.cpp" +#include "bindings/V8SVGPathSegLinetoHorizontalAbs.cpp" +#include "bindings/V8SVGPathSegLinetoHorizontalRel.cpp" +#include "bindings/V8SVGPathSegLinetoRel.cpp" +#include "bindings/V8SVGPathSegLinetoVerticalAbs.cpp" +#include "bindings/V8SVGPathSegLinetoVerticalRel.cpp" +#include "bindings/V8SVGPathSegList.cpp" +#include "bindings/V8SVGPathSegMovetoAbs.cpp" +#include "bindings/V8SVGPathSegMovetoRel.cpp" +#include "bindings/V8SVGPatternElement.cpp" +#include "bindings/V8SVGPoint.cpp" +#include "bindings/V8SVGPointList.cpp" +#include "bindings/V8SVGPolygonElement.cpp" +#include "bindings/V8SVGPolylineElement.cpp" +#include "bindings/V8SVGPreserveAspectRatio.cpp" +#include "bindings/V8SVGRadialGradientElement.cpp" +#include "bindings/V8SVGRect.cpp" +#include "bindings/V8SVGRectElement.cpp" +#include "bindings/V8SVGRenderingIntent.cpp" +#include "bindings/V8SVGScriptElement.cpp" +#include "bindings/V8SVGSetElement.cpp" +#include "bindings/V8SVGStopElement.cpp" +#include "bindings/V8SVGStringList.cpp" +#include "bindings/V8SVGStyleElement.cpp" +#include "bindings/V8SVGSVGElement.cpp" +#include "bindings/V8SVGSwitchElement.cpp" +#include "bindings/V8SVGSymbolElement.cpp" +#include "bindings/V8SVGTextContentElement.cpp" +#include "bindings/V8SVGTextElement.cpp" +#include "bindings/V8SVGTextPathElement.cpp" +#include "bindings/V8SVGTextPositioningElement.cpp" +#include "bindings/V8SVGTitleElement.cpp" +#include "bindings/V8SVGTransform.cpp" +#include "bindings/V8SVGTransformList.cpp" +#include "bindings/V8SVGTRefElement.cpp" +#include "bindings/V8SVGTSpanElement.cpp" +#include "bindings/V8SVGUnitTypes.cpp" +#include "bindings/V8SVGURIReference.cpp" +#include "bindings/V8SVGUseElement.cpp" +#include "bindings/V8SVGViewElement.cpp" +#include "bindings/V8SVGZoomEvent.cpp" +#include "bindings/V8Text.cpp" +#include "bindings/V8TextEvent.cpp" +#include "bindings/V8TextMetrics.cpp" +#include "bindings/V8TimeRanges.cpp" +#include "bindings/V8TreeWalker.cpp" +#include "bindings/V8UIEvent.cpp" +#include "bindings/V8ValidityState.cpp" +#include "bindings/V8WebKitAnimationEvent.cpp" +#include "bindings/V8WebKitCSSKeyframeRule.cpp" +#include "bindings/V8WebKitCSSKeyframesRule.cpp" +#include "bindings/V8WebKitCSSMatrix.cpp" +#include "bindings/V8WebKitCSSTransformValue.cpp" +#include "bindings/V8WebKitPoint.cpp" +#include "bindings/V8WebKitTransitionEvent.cpp" +#include "bindings/V8WheelEvent.cpp" +#include "bindings/V8Worker.cpp" +#include "bindings/V8WorkerContext.cpp" +#include "bindings/V8WorkerLocation.cpp" +#include "bindings/V8WorkerNavigator.cpp" +#include "bindings/V8XMLHttpRequest.cpp" +#include "bindings/V8XMLHttpRequestException.cpp" +#include "bindings/V8XMLHttpRequestProgressEvent.cpp" +#include "bindings/V8XMLHttpRequestUpload.cpp" +#include "bindings/V8XMLSerializer.cpp" +#include "bindings/V8XPathEvaluator.cpp" +#include "bindings/V8XPathException.cpp" +#include "bindings/V8XPathExpression.cpp" +#include "bindings/V8XPathNSResolver.cpp" +#include "bindings/V8XPathResult.cpp" +#include "bindings/V8XSLTProcessor.cpp" diff --git a/WebCore/bindings/v8/MainThreadDOMData.cpp b/WebCore/bindings/v8/MainThreadDOMData.cpp new file mode 100644 index 0000000..ea34444 --- /dev/null +++ b/WebCore/bindings/v8/MainThreadDOMData.cpp @@ -0,0 +1,52 @@ +/* + * 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: + * + * * 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. + */ + +#include "config.h" +#include "MainThreadDOMData.h" + +#include "V8IsolatedWorld.h" + +namespace WebCore { + +MainThreadDOMData::MainThreadDOMData() + : m_defaultStore(this) +{ +} + +DOMDataStore& MainThreadDOMData::getStore() +{ + ASSERT(WTF::isMainThread()); + V8IsolatedWorld* world = V8IsolatedWorld::getEntered(); + if (world) + return *world->getDOMDataStore(); + return m_defaultStore; +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/MainThreadDOMData.h b/WebCore/bindings/v8/MainThreadDOMData.h new file mode 100644 index 0000000..5c78cec --- /dev/null +++ b/WebCore/bindings/v8/MainThreadDOMData.h @@ -0,0 +1,51 @@ +/* + * 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: + * + * * 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 MainThreadDOMData_h +#define MainThreadDOMData_h + +#include "DOMData.h" +#include "StaticDOMDataStore.h" + +namespace WebCore { + + class MainThreadDOMData : public DOMData { + public: + MainThreadDOMData(); + DOMDataStore& getStore(); + + private: + StaticDOMDataStore m_defaultStore; + // Note: The DOMDataStores for isolated world are owned by the world object. + }; + +} // namespace WebCore + +#endif // MainThreadDOMData_h diff --git a/WebCore/bindings/v8/NPV8Object.cpp b/WebCore/bindings/v8/NPV8Object.cpp new file mode 100644 index 0000000..15dc852 --- /dev/null +++ b/WebCore/bindings/v8/NPV8Object.cpp @@ -0,0 +1,509 @@ +/* + * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2007, 2008, 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 APPLE COMPUTER, 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 COMPUTER, 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 "NPV8Object.h" + +#include "ChromiumBridge.h" +#include "DOMWindow.h" +#include "Frame.h" +#include "OwnArrayPtr.h" +#include "PlatformString.h" +#include "ScriptController.h" +#include "V8CustomBinding.h" +#include "V8GCController.h" +#include "V8Helpers.h" +#include "V8NPUtils.h" +#include "V8Proxy.h" +#include "bindings/npruntime.h" +#include "npruntime_impl.h" +#include "npruntime_priv.h" + +#include <stdio.h> +#include <v8.h> +#include <wtf/StringExtras.h> + +using WebCore::toV8Context; +using WebCore::toV8Proxy; +using WebCore::V8ClassIndex; +using WebCore::V8Custom; +using WebCore::V8DOMWrapper; +using WebCore::V8GCController; +using WebCore::V8Proxy; + +// FIXME: Comments on why use malloc and free. +static NPObject* allocV8NPObject(NPP, NPClass*) +{ + return static_cast<NPObject*>(malloc(sizeof(V8NPObject))); +} + +static void freeV8NPObject(NPObject* npObject) +{ + V8NPObject* v8NpObject = reinterpret_cast<V8NPObject*>(npObject); +#ifndef NDEBUG + V8GCController::unregisterGlobalHandle(v8NpObject, v8NpObject->v8Object); +#endif + v8NpObject->v8Object.Dispose(); + free(v8NpObject); +} + +static v8::Handle<v8::Value>* createValueListFromVariantArgs(const NPVariant* arguments, uint32_t argumentCount, NPObject* owner) +{ + v8::Handle<v8::Value>* argv = new v8::Handle<v8::Value>[argumentCount]; + for (uint32_t index = 0; index < argumentCount; index++) { + const NPVariant* arg = &arguments[index]; + argv[index] = convertNPVariantToV8Object(arg, owner); + } + return argv; +} + +// Create an identifier (null terminated utf8 char*) from the NPIdentifier. +static v8::Local<v8::String> npIdentifierToV8Identifier(NPIdentifier name) +{ + PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(name); + if (identifier->isString) + return v8::String::New(static_cast<const char*>(identifier->value.string)); + + char buffer[32]; + snprintf(buffer, sizeof(buffer), "%d", identifier->value.number); + return v8::String::New(buffer); +} + +static NPClass V8NPObjectClass = { NP_CLASS_STRUCT_VERSION, + allocV8NPObject, + freeV8NPObject, + 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + +// NPAPI's npruntime functions. +NPClass* npScriptObjectClass = &V8NPObjectClass; + +NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, WebCore::DOMWindow* root) +{ + // Check to see if this object is already wrapped. + if (object->InternalFieldCount() == V8Custom::kNPObjectInternalFieldCount) { + v8::Local<v8::Value> typeIndex = object->GetInternalField(V8Custom::kDOMWrapperTypeIndex); + if (typeIndex->IsNumber() && typeIndex->Uint32Value() == V8ClassIndex::NPOBJECT) { + + NPObject* returnValue = V8DOMWrapper::convertToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, object); + _NPN_RetainObject(returnValue); + return returnValue; + } + } + + V8NPObject* v8npObject = reinterpret_cast<V8NPObject*>(_NPN_CreateObject(npp, &V8NPObjectClass)); + v8npObject->v8Object = v8::Persistent<v8::Object>::New(object); +#ifndef NDEBUG + V8GCController::registerGlobalHandle(WebCore::NPOBJECT, v8npObject, v8npObject->v8Object); +#endif + v8npObject->rootObject = root; + return reinterpret_cast<NPObject*>(v8npObject); +} + +bool _NPN_Invoke(NPP npp, NPObject* npObject, NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) +{ + if (!npObject) + return false; + + if (npObject->_class != npScriptObjectClass) { + if (npObject->_class->invoke) + return npObject->_class->invoke(npObject, methodName, arguments, argumentCount, result); + + VOID_TO_NPVARIANT(*result); + return true; + } + + V8NPObject* v8NpObject = reinterpret_cast<V8NPObject*>(npObject); + + PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(methodName); + if (!identifier->isString) + return false; + + v8::HandleScope handleScope; + // FIXME: should use the plugin's owner frame as the security context. + v8::Handle<v8::Context> context = toV8Context(npp, npObject); + if (context.IsEmpty()) + return false; + + v8::Context::Scope scope(context); + + if (methodName == _NPN_GetStringIdentifier("eval")) { + if (argumentCount != 1) + return false; + if (arguments[0].type != NPVariantType_String) + return false; + return _NPN_Evaluate(npp, npObject, const_cast<NPString*>(&arguments[0].value.stringValue), result); + } + + v8::Handle<v8::Value> functionObject = v8NpObject->v8Object->Get(v8::String::New(identifier->value.string)); + if (functionObject.IsEmpty() || functionObject->IsNull()) { + NULL_TO_NPVARIANT(*result); + return false; + } + if (functionObject->IsUndefined()) { + VOID_TO_NPVARIANT(*result); + return false; + } + + V8Proxy* proxy = toV8Proxy(npObject); + ASSERT(proxy); + + // Call the function object. + v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(functionObject); + OwnArrayPtr<v8::Handle<v8::Value> > argv(createValueListFromVariantArgs(arguments, argumentCount, npObject)); + v8::Local<v8::Value> resultObject = proxy->callFunction(function, v8NpObject->v8Object, argumentCount, argv.get()); + + // If we had an error, return false. The spec is a little unclear here, but says "Returns true if the method was + // successfully invoked". If we get an error return value, was that successfully invoked? + if (resultObject.IsEmpty()) + return false; + + convertV8ObjectToNPVariant(resultObject, npObject, result); + return true; +} + +// FIXME: Fix it same as _NPN_Invoke (HandleScope and such). +bool _NPN_InvokeDefault(NPP npp, NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) +{ + if (!npObject) + return false; + + if (npObject->_class != npScriptObjectClass) { + if (npObject->_class->invokeDefault) + return npObject->_class->invokeDefault(npObject, arguments, argumentCount, result); + + VOID_TO_NPVARIANT(*result); + return true; + } + + V8NPObject* v8NpObject = reinterpret_cast<V8NPObject*>(npObject); + + VOID_TO_NPVARIANT(*result); + + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = toV8Context(npp, npObject); + if (context.IsEmpty()) + return false; + + v8::Context::Scope scope(context); + + // Lookup the function object and call it. + v8::Handle<v8::Object> functionObject(v8NpObject->v8Object); + if (!functionObject->IsFunction()) + return false; + + v8::Local<v8::Value> resultObject; + v8::Handle<v8::Function> function(v8::Function::Cast(*functionObject)); + if (!function->IsNull()) { + V8Proxy* proxy = toV8Proxy(npObject); + ASSERT(proxy); + + OwnArrayPtr<v8::Handle<v8::Value> > argv(createValueListFromVariantArgs(arguments, argumentCount, npObject)); + resultObject = proxy->callFunction(function, functionObject, argumentCount, argv.get()); + } + // If we had an error, return false. The spec is a little unclear here, but says "Returns true if the method was + // successfully invoked". If we get an error return value, was that successfully invoked? + if (resultObject.IsEmpty()) + return false; + + convertV8ObjectToNPVariant(resultObject, npObject, result); + return true; +} + +bool _NPN_Evaluate(NPP npp, NPObject* npObject, NPString* npScript, NPVariant* result) +{ + bool popupsAllowed = WebCore::ChromiumBridge::popupsAllowed(npp); + return _NPN_EvaluateHelper(npp, popupsAllowed, npObject, npScript, result); +} + +bool _NPN_EvaluateHelper(NPP npp, bool popupsAllowed, NPObject* npObject, NPString* npScript, NPVariant* result) +{ + VOID_TO_NPVARIANT(*result); + if (!npObject) + return false; + + if (npObject->_class != npScriptObjectClass) + return false; + + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = toV8Context(npp, npObject); + if (context.IsEmpty()) + return false; + + V8Proxy* proxy = toV8Proxy(npObject); + ASSERT(proxy); + + v8::Context::Scope scope(context); + + WebCore::String filename; + if (!popupsAllowed) + filename = "npscript"; + + WebCore::String script = WebCore::String::fromUTF8(npScript->UTF8Characters, npScript->UTF8Length); + v8::Local<v8::Value> v8result = proxy->evaluate(WebCore::ScriptSourceCode(script, WebCore::KURL(filename)), 0); + + if (v8result.IsEmpty()) + return false; + + convertV8ObjectToNPVariant(v8result, npObject, result); + return true; +} + +bool _NPN_GetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, NPVariant* result) +{ + if (!npObject) + return false; + + if (npObject->_class == npScriptObjectClass) { + V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); + + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = toV8Context(npp, npObject); + if (context.IsEmpty()) + return false; + + v8::Context::Scope scope(context); + + v8::Handle<v8::Object> obj(object->v8Object); + v8::Local<v8::Value> v8result = obj->Get(npIdentifierToV8Identifier(propertyName)); + + convertV8ObjectToNPVariant(v8result, npObject, result); + return true; + } + + if (npObject->_class->hasProperty && npObject->_class->getProperty) { + if (npObject->_class->hasProperty(npObject, propertyName)) + return npObject->_class->getProperty(npObject, propertyName, result); + } + + VOID_TO_NPVARIANT(*result); + return false; +} + +bool _NPN_SetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, const NPVariant* value) +{ + if (!npObject) + return false; + + if (npObject->_class == npScriptObjectClass) { + V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); + + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = toV8Context(npp, npObject); + if (context.IsEmpty()) + return false; + + v8::Context::Scope scope(context); + + v8::Handle<v8::Object> obj(object->v8Object); + obj->Set(npIdentifierToV8Identifier(propertyName), + convertNPVariantToV8Object(value, object->rootObject->frame()->script()->windowScriptNPObject())); + return true; + } + + if (npObject->_class->setProperty) + return npObject->_class->setProperty(npObject, propertyName, value); + + return false; +} + +bool _NPN_RemoveProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName) +{ + if (!npObject) + return false; + if (npObject->_class != npScriptObjectClass) + return false; + + V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); + + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = toV8Context(npp, npObject); + if (context.IsEmpty()) + return false; + v8::Context::Scope scope(context); + + v8::Handle<v8::Object> obj(object->v8Object); + // FIXME: Verify that setting to undefined is right. + obj->Set(npIdentifierToV8Identifier(propertyName), v8::Undefined()); + return true; +} + +bool _NPN_HasProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName) +{ + if (!npObject) + return false; + + if (npObject->_class == npScriptObjectClass) { + V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); + + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = toV8Context(npp, npObject); + if (context.IsEmpty()) + return false; + v8::Context::Scope scope(context); + + v8::Handle<v8::Object> obj(object->v8Object); + return obj->Has(npIdentifierToV8Identifier(propertyName)); + } + + if (npObject->_class->hasProperty) + return npObject->_class->hasProperty(npObject, propertyName); + return false; +} + +bool _NPN_HasMethod(NPP npp, NPObject* npObject, NPIdentifier methodName) +{ + if (!npObject) + return false; + + if (npObject->_class == npScriptObjectClass) { + V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); + + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = toV8Context(npp, npObject); + if (context.IsEmpty()) + return false; + v8::Context::Scope scope(context); + + v8::Handle<v8::Object> obj(object->v8Object); + v8::Handle<v8::Value> prop = obj->Get(npIdentifierToV8Identifier(methodName)); + return prop->IsFunction(); + } + + if (npObject->_class->hasMethod) + return npObject->_class->hasMethod(npObject, methodName); + return false; +} + +void _NPN_SetException(NPObject* npObject, const NPUTF8 *message) +{ + if (npObject->_class != npScriptObjectClass) + return; + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = toV8Context(0, npObject); + if (context.IsEmpty()) + return; + + v8::Context::Scope scope(context); + V8Proxy::throwError(V8Proxy::GeneralError, message); +} + +bool _NPN_Enumerate(NPP npp, NPObject* npObject, NPIdentifier** identifier, uint32_t* count) +{ + if (!npObject) + return false; + + if (npObject->_class == npScriptObjectClass) { + V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); + + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = toV8Context(npp, npObject); + if (context.IsEmpty()) + return false; + v8::Context::Scope scope(context); + + v8::Handle<v8::Object> obj(object->v8Object); + + // FIXME: http://b/issue?id=1210340: Use a v8::Object::Keys() method when it exists, instead of evaluating javascript. + + // FIXME: Figure out how to cache this helper function. Run a helper function that collects the properties + // on the object into an array. + const char enumeratorCode[] = + "(function (obj) {" + " var props = [];" + " for (var prop in obj) {" + " props[props.length] = prop;" + " }" + " return props;" + "});"; + v8::Handle<v8::String> source = v8::String::New(enumeratorCode); + v8::Handle<v8::Script> script = v8::Script::Compile(source, 0); + v8::Handle<v8::Value> enumeratorObj = script->Run(); + v8::Handle<v8::Function> enumerator = v8::Handle<v8::Function>::Cast(enumeratorObj); + v8::Handle<v8::Value> argv[] = { obj }; + v8::Local<v8::Value> propsObj = enumerator->Call(v8::Handle<v8::Object>::Cast(enumeratorObj), ARRAYSIZE_UNSAFE(argv), argv); + if (propsObj.IsEmpty()) + return false; + + // Convert the results into an array of NPIdentifiers. + v8::Handle<v8::Array> props = v8::Handle<v8::Array>::Cast(propsObj); + *count = props->Length(); + *identifier = static_cast<NPIdentifier*>(malloc(sizeof(NPIdentifier*) * *count)); + for (uint32_t i = 0; i < *count; ++i) { + v8::Local<v8::Value> name = props->Get(v8::Integer::New(i)); + (*identifier)[i] = getStringIdentifier(v8::Local<v8::String>::Cast(name)); + } + return true; + } + + if (NP_CLASS_STRUCT_VERSION_HAS_ENUM(npObject->_class) && npObject->_class->enumerate) + return npObject->_class->enumerate(npObject, identifier, count); + + return false; +} + +bool _NPN_Construct(NPP npp, NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) +{ + if (!npObject) + return false; + + if (npObject->_class == npScriptObjectClass) { + V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); + + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = toV8Context(npp, npObject); + if (context.IsEmpty()) + return false; + v8::Context::Scope scope(context); + + // Lookup the constructor function. + v8::Handle<v8::Object> ctorObj(object->v8Object); + if (!ctorObj->IsFunction()) + return false; + + // Call the constructor. + v8::Local<v8::Value> resultObject; + v8::Handle<v8::Function> ctor(v8::Function::Cast(*ctorObj)); + if (!ctor->IsNull()) { + V8Proxy* proxy = toV8Proxy(npObject); + ASSERT(proxy); + + OwnArrayPtr<v8::Handle<v8::Value> > argv(createValueListFromVariantArgs(arguments, argumentCount, npObject)); + resultObject = proxy->newInstance(ctor, argumentCount, argv.get()); + } + + if (resultObject.IsEmpty()) + return false; + + convertV8ObjectToNPVariant(resultObject, npObject, result); + return true; + } + + if (NP_CLASS_STRUCT_VERSION_HAS_CTOR(npObject->_class) && npObject->_class->construct) + return npObject->_class->construct(npObject, arguments, argumentCount, result); + + return false; +} diff --git a/WebCore/bindings/v8/NPV8Object.h b/WebCore/bindings/v8/NPV8Object.h new file mode 100644 index 0000000..65a7ccf --- /dev/null +++ b/WebCore/bindings/v8/NPV8Object.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2006, 2007, 2008, 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: + * + * * 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 NPV8Object_h +#define NPV8Object_h + +#include "bindings/npruntime.h" +#include <v8.h> + +namespace WebCore { + class DOMWindow; +} + +extern NPClass* npScriptObjectClass; + +// A V8NPObject is a NPObject which carries additional V8-specific information. It is allocated and deallocated by +// AllocV8NPObject() and FreeV8NPObject() methods. +struct V8NPObject { + NPObject object; + v8::Persistent<v8::Object> v8Object; + WebCore::DOMWindow* rootObject; +}; + +struct PrivateIdentifier { + union { + const NPUTF8* string; + int32_t number; + } value; + bool isString; +}; + +NPObject* npCreateV8ScriptObject(NPP, v8::Handle<v8::Object>, WebCore::DOMWindow*); + +#endif // NPV8Object_h diff --git a/WebCore/bindings/v8/OwnHandle.h b/WebCore/bindings/v8/OwnHandle.h new file mode 100644 index 0000000..6580674 --- /dev/null +++ b/WebCore/bindings/v8/OwnHandle.h @@ -0,0 +1,82 @@ +/* + * 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: + * + * * 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 OwnHandle_h +#define OwnHandle_h + +#include <v8.h> + +namespace WebCore { + + template<typename T> + class OwnHandle { + public: + OwnHandle() { } + explicit OwnHandle(v8::Handle<T> handle) : m_handle(v8::Persistent<T>::New(handle)) { } + ~OwnHandle() { clear(); } + + v8::Handle<T> get() const { return m_handle; } + void set(v8::Handle<T> handle) { clear(); m_handle = v8::Persistent<T>::New(handle); } + + // FIXME: What if we release a weak handle? Won't the callback do the wrong thing? + v8::Persistent<T> release() { v8::Persistent<T> result = m_handle; m_handle.Clear(); return result; } + void adopt(v8::Persistent<T> handle) { clear(); m_handle = handle; } + + // Note: This is clear in the OwnPtr sense, not the v8::Handle sense. + void clear() + { + if (m_handle.IsEmpty()) + return; + m_handle.Dispose(); + m_handle.Clear(); + } + + // Make the underlying handle weak. The client doesn't get a callback, + // we just make the handle empty. + void makeWeak() + { + if (m_handle.IsEmpty()) + return; + m_handle.MakeWeak(this, &OwnHandle<T>::weakCallback); + } + + private: + static void weakCallback(v8::Persistent<v8::Value> object, void* ownHandle) + { + OwnHandle<T>* handle = static_cast<OwnHandle<T>*>(ownHandle); + handle->clear(); + } + + v8::Persistent<T> m_handle; + }; + +} // namespace WebCore + +#endif // OwnHandle_h diff --git a/WebCore/bindings/v8/ScheduledAction.cpp b/WebCore/bindings/v8/ScheduledAction.cpp index b1db8cf..44e8a37 100644 --- a/WebCore/bindings/v8/ScheduledAction.cpp +++ b/WebCore/bindings/v8/ScheduledAction.cpp @@ -50,7 +50,7 @@ ScheduledAction::ScheduledAction(v8::Handle<v8::Function> func, int argc, v8::Ha m_function = v8::Persistent<v8::Function>::New(func); #ifndef NDEBUG - V8Proxy::RegisterGlobalHandle(SCHEDULED_ACTION, this, m_function); + V8GCController::registerGlobalHandle(SCHEDULED_ACTION, this, m_function); #endif m_argc = argc; @@ -60,7 +60,7 @@ ScheduledAction::ScheduledAction(v8::Handle<v8::Function> func, int argc, v8::Ha m_argv[i] = v8::Persistent<v8::Value>::New(argv[i]); #ifndef NDEBUG - V8Proxy::RegisterGlobalHandle(SCHEDULED_ACTION, this, m_argv[i]); + V8GCController::registerGlobalHandle(SCHEDULED_ACTION, this, m_argv[i]); #endif } } else @@ -73,13 +73,13 @@ ScheduledAction::~ScheduledAction() return; #ifndef NDEBUG - V8Proxy::UnregisterGlobalHandle(this, m_function); + V8GCController::unregisterGlobalHandle(this, m_function); #endif m_function.Dispose(); for (int i = 0; i < m_argc; i++) { #ifndef NDEBUG - V8Proxy::UnregisterGlobalHandle(this, m_argv[i]); + V8GCController::unregisterGlobalHandle(this, m_argv[i]); #endif m_argv[i].Dispose(); } @@ -107,7 +107,7 @@ void ScheduledAction::execute(V8Proxy* proxy) LOCK_V8; v8::HandleScope handleScope; - v8::Local<v8::Context> v8Context = proxy->GetContext(); + v8::Local<v8::Context> v8Context = proxy->context(); if (v8Context.IsEmpty()) return; // JS may not be enabled. @@ -117,7 +117,7 @@ void ScheduledAction::execute(V8Proxy* proxy) // FIXME: Need to implement timeouts for preempting a long-running script. if (!m_function.IsEmpty() && m_function->IsFunction()) { - proxy->CallFunction(v8::Persistent<v8::Function>::Cast(m_function), v8Context->Global(), m_argc, m_argv); + proxy->callFunction(v8::Persistent<v8::Function>::Cast(m_function), v8Context->Global(), m_argc, m_argv); Document::updateStyleForAllDocuments(); } else proxy->evaluate(m_code, 0); @@ -136,7 +136,7 @@ void ScheduledAction::execute(WorkerContext* workerContext) if (!m_function.IsEmpty() && m_function->IsFunction()) { LOCK_V8; v8::HandleScope handleScope; - v8::Local<v8::Context> v8Context = scriptController->proxy()->GetContext(); + v8::Local<v8::Context> v8Context = scriptController->proxy()->context(); ASSERT(!v8Context.IsEmpty()); v8::Context::Scope scope(v8Context); m_function->Call(v8Context->Global(), m_argc, m_argv); diff --git a/WebCore/bindings/v8/ScopedDOMDataStore.cpp b/WebCore/bindings/v8/ScopedDOMDataStore.cpp new file mode 100644 index 0000000..19cd545 --- /dev/null +++ b/WebCore/bindings/v8/ScopedDOMDataStore.cpp @@ -0,0 +1,59 @@ +/* + * 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: + * + * * 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. + */ + +#include "config.h" +#include "ScopedDOMDataStore.h" + +namespace WebCore { + +ScopedDOMDataStore::ScopedDOMDataStore(DOMData* domData) + : DOMDataStore(domData) +{ + m_domNodeMap = new InternalDOMWrapperMap<Node>(domData, &DOMDataStore::weakNodeCallback); + m_domObjectMap = new InternalDOMWrapperMap<void>(domData, &DOMDataStore::weakDOMObjectCallback); + m_activeDomObjectMap = new InternalDOMWrapperMap<void>(domData, &DOMDataStore::weakActiveDOMObjectCallback); +#if ENABLE(SVG) + m_domSvgElementInstanceMap = new InternalDOMWrapperMap<SVGElementInstance>(domData, &DOMDataStore::weakSVGElementInstanceCallback); + m_domSvgObjectWithContextMap = new InternalDOMWrapperMap<void>(domData, &DOMDataStore::weakSVGObjectWithContextCallback); +#endif +} + +ScopedDOMDataStore::~ScopedDOMDataStore() +{ + delete m_domNodeMap; + delete m_domObjectMap; + delete m_activeDomObjectMap; +#if ENABLE(SVG) + delete m_domSvgElementInstanceMap; + delete m_domSvgObjectWithContextMap; +#endif +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/ScopedDOMDataStore.h b/WebCore/bindings/v8/ScopedDOMDataStore.h new file mode 100644 index 0000000..c63bab0 --- /dev/null +++ b/WebCore/bindings/v8/ScopedDOMDataStore.h @@ -0,0 +1,56 @@ +/* + * 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: + * + * * 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 ScopedDOMDataStore_h +#define ScopedDOMDataStore_h + +#include "DOMDataStore.h" + +namespace WebCore { + + // ScopedDOMDataStore + // + // ScopedDOMDataStore is a DOMDataStore that controls limits the lifetime of + // the store to the lifetime of the object itself. In other words, when the + // ScopedDOMDataStore object is deallocated, the maps that belong to the store + // are deallocated as well. + // + class ScopedDOMDataStore : public DOMDataStore { + public: + ScopedDOMDataStore(DOMData*); + + // This can be called when WTF thread is tearing down. + // We assume that all child threads running V8 instances are created by WTF. + virtual ~ScopedDOMDataStore(); + }; + +} // namespace WebCore + +#endif // ScopedDOMDataStore_h diff --git a/WebCore/bindings/v8/ScriptArray.cpp b/WebCore/bindings/v8/ScriptArray.cpp new file mode 100644 index 0000000..748ee19 --- /dev/null +++ b/WebCore/bindings/v8/ScriptArray.cpp @@ -0,0 +1,105 @@ +/* + * 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: + * + * * 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. + */ + +#include "config.h" +#include "ScriptArray.h" + +#include "ScriptScope.h" +#include "ScriptState.h" + +#include "Document.h" +#include "Frame.h" +#include "V8Binding.h" +#include "V8Proxy.h" + +#include <v8.h> + +namespace WebCore { + +ScriptArray::ScriptArray(ScriptState* scriptState, v8::Handle<v8::Array> v8Array) + : ScriptObject(scriptState, v8Array) +{ +} + +bool ScriptArray::set(unsigned index, const ScriptObject& value) +{ + ScriptScope scope(m_scriptState); + v8Object()->Set(v8::Integer::New(index), value.v8Value()); + return scope.success(); +} + +bool ScriptArray::set(unsigned index, const String& value) +{ + ScriptScope scope(m_scriptState); + v8Object()->Set(v8::Integer::New(index), v8String(value)); + return scope.success(); +} + +bool ScriptArray::set(unsigned index, double value) +{ + ScriptScope scope(m_scriptState); + v8Object()->Set(v8::Integer::New(index), v8::Number::New(value)); + return scope.success(); +} + +bool ScriptArray::set(unsigned index, long long value) +{ + ScriptScope scope(m_scriptState); + v8Object()->Set(v8::Integer::New(index), v8::Number::New(value)); + return scope.success(); +} + +bool ScriptArray::set(unsigned index, int value) +{ + ScriptScope scope(m_scriptState); + v8Object()->Set(v8::Integer::New(index), v8::Number::New(value)); + return scope.success(); +} + +bool ScriptArray::set(unsigned index, bool value) +{ + ScriptScope scope(m_scriptState); + v8Object()->Set(v8::Integer::New(index), v8Boolean(value)); + return scope.success(); +} + +unsigned ScriptArray::length() +{ + ScriptScope scope(m_scriptState); + return v8::Array::Cast(*v8Value())->Length(); +} + +ScriptArray ScriptArray::createNew(ScriptState* scriptState) +{ + ScriptScope scope(scriptState); + return ScriptArray(scriptState, v8::Array::New()); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptArray.h b/WebCore/bindings/v8/ScriptArray.h new file mode 100644 index 0000000..6e8f852 --- /dev/null +++ b/WebCore/bindings/v8/ScriptArray.h @@ -0,0 +1,58 @@ +/* + * 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: + * + * * 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 ScriptArray_h +#define ScriptArray_h + +#include "ScriptObject.h" + +#include <v8.h> + +namespace WebCore { + class ScriptState; + + class ScriptArray : public ScriptObject { + public: + ScriptArray(ScriptState* scriptState, v8::Handle<v8::Array>); + virtual ~ScriptArray() {} + + bool set(unsigned index, const ScriptObject&); + bool set(unsigned index, const String&); + bool set(unsigned index, double); + bool set(unsigned index, long long); + bool set(unsigned index, int); + bool set(unsigned index, bool); + unsigned length(); + + static ScriptArray createNew(ScriptState*); + }; +} + +#endif // ScriptArray_h diff --git a/WebCore/bindings/v8/ScriptCallStack.cpp b/WebCore/bindings/v8/ScriptCallStack.cpp index 9188dcf..8eb9478 100644 --- a/WebCore/bindings/v8/ScriptCallStack.cpp +++ b/WebCore/bindings/v8/ScriptCallStack.cpp @@ -39,7 +39,8 @@ namespace WebCore { ScriptCallStack::ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount) - : m_lastCaller(String(), V8Proxy::GetSourceName(), V8Proxy::GetSourceLineNumber() + 1, arguments, skipArgumentCount) + : m_lastCaller(String(), V8Proxy::sourceName(), V8Proxy::sourceLineNumber() + 1, arguments, skipArgumentCount) + , m_scriptState(new ScriptState(V8Proxy::retrieveFrameForCurrentContext())) { } diff --git a/WebCore/bindings/v8/ScriptCallStack.h b/WebCore/bindings/v8/ScriptCallStack.h index 2dfd484..9f628c8 100644 --- a/WebCore/bindings/v8/ScriptCallStack.h +++ b/WebCore/bindings/v8/ScriptCallStack.h @@ -35,6 +35,7 @@ #include "ScriptState.h" #include "ScriptValue.h" #include <wtf/Noncopyable.h> +#include <wtf/OwnPtr.h> namespace v8 { class Arguments; @@ -51,10 +52,10 @@ namespace WebCore { // FIXME: implement retrieving and storing call stack trace unsigned size() const { return 1; } - // FIXME: This method is obviously not implemented. - ScriptState* state() const { return 0; } + ScriptState* state() const { return m_scriptState.get(); } private: + OwnPtr<ScriptState> m_scriptState; ScriptCallFrame m_lastCaller; }; diff --git a/WebCore/bindings/v8/ScriptController.cpp b/WebCore/bindings/v8/ScriptController.cpp index eecff45..97a3553 100644 --- a/WebCore/bindings/v8/ScriptController.cpp +++ b/WebCore/bindings/v8/ScriptController.cpp @@ -47,11 +47,13 @@ #include "Frame.h" #include "Node.h" #include "NotImplemented.h" +#include "npruntime_impl.h" #include "npruntime_priv.h" #include "NPV8Object.h" #include "ScriptSourceCode.h" #include "ScriptState.h" #include "Widget.h" +#include "XSSAuditor.h" #include "V8Binding.h" #include "V8NPObject.h" @@ -76,17 +78,17 @@ Frame* ScriptController::retrieveFrameForCurrentContext() bool ScriptController::isSafeScript(Frame* target) { - return V8Proxy::CanAccessFrame(target, true); + return V8Proxy::canAccessFrame(target, true); } void ScriptController::gcProtectJSWrapper(void* domObject) { - V8Proxy::GCProtect(domObject); + V8GCController::gcProtect(domObject); } void ScriptController::gcUnprotectJSWrapper(void* domObject) { - V8Proxy::GCUnprotect(domObject); + V8GCController::gcUnprotect(domObject); } ScriptController::ScriptController(Frame* frame) @@ -99,6 +101,7 @@ ScriptController::ScriptController(Frame* frame) #if ENABLE(NETSCAPE_PLUGIN_API) , m_windowScriptNPObject(0) #endif + , m_XSSAuditor(new XSSAuditor(frame)) { } @@ -112,7 +115,7 @@ void ScriptController::clearScriptObjects() PluginObjectMap::iterator it = m_pluginObjects.begin(); for (; it != m_pluginObjects.end(); ++it) { _NPN_UnregisterObject(it->second); - NPN_ReleaseObject(it->second); + _NPN_ReleaseObject(it->second); } m_pluginObjects.clear(); @@ -147,18 +150,18 @@ bool ScriptController::processingUserGesture() const V8Proxy* activeProxy = activeFrame->script()->proxy(); LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(activeFrame); + v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(activeFrame); // FIXME: find all cases context can be empty: // 1) JS is disabled; // 2) page is NULL; - if (context.IsEmpty()) + if (v8Context.IsEmpty()) return true; - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); - v8::Handle<v8::Object> global = context->Global(); + v8::Handle<v8::Object> global = v8Context->Global(); v8::Handle<v8::Value> jsEvent = global->Get(v8::String::NewSymbol("event")); - Event* event = V8Proxy::ToNativeEvent(jsEvent); + Event* event = V8DOMWrapper::convertToNativeEvent(jsEvent); // Based on code from kjs_bindings.cpp. // Note: This is more liberal than Firefox's implementation. @@ -183,21 +186,41 @@ bool ScriptController::processingUserGesture() const return false; } -void ScriptController::evaluateInNewContext(const Vector<ScriptSourceCode>& sources) +void ScriptController::evaluateInNewWorld(const Vector<ScriptSourceCode>& sources, int extensionGroup) { - m_proxy->evaluateInNewContext(sources); + m_proxy->evaluateInNewWorld(sources, extensionGroup); +} + +void ScriptController::evaluateInNewContext(const Vector<ScriptSourceCode>& sources, int extensionGroup) +{ + m_proxy->evaluateInNewContext(sources, extensionGroup); } // Evaluate a script file in the environment of this proxy. ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) { +#ifdef MANUAL_MERGE_REQUIRED LOCK_V8; +#else // MANUAL_MERGE_REQUIRED + String sourceURL = sourceCode.url(); + + if (sourceURL.isNull() && !m_XSSAuditor->canEvaluateJavaScriptURL(sourceCode.source())) { + // This JavaScript URL is not safe to be evaluated. + return ScriptValue(); + } + + if (!sourceURL.isNull() && !m_XSSAuditor->canEvaluate(sourceCode.source())) { + // This script is not safe to be evaluated. + return ScriptValue(); + } + +#endif // MANUAL_MERGE_REQUIRED v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_proxy->frame()); - if (context.IsEmpty()) + v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(m_proxy->frame()); + if (v8Context.IsEmpty()) return ScriptValue(); - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); RefPtr<Frame> protect(m_frame); @@ -215,7 +238,7 @@ ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) void ScriptController::setEventHandlerLineNumber(int lineNumber) { - m_proxy->setEventHandlerLineno(lineNumber); + m_proxy->setEventHandlerLineNumber(lineNumber); } void ScriptController::finishedWithEvent(Event* event) @@ -229,16 +252,16 @@ void ScriptController::bindToWindowObject(Frame* frame, const String& key, NPObj LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(frame); - if (context.IsEmpty()) + v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(frame); + if (v8Context.IsEmpty()) return; - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); - v8::Handle<v8::Object> value = CreateV8ObjectForNPObject(object, 0); + v8::Handle<v8::Object> value = createV8ObjectForNPObject(object, 0); // Attach to the global object. - v8::Handle<v8::Object> global = context->Global(); + v8::Handle<v8::Object> global = v8Context->Global(); global->Set(v8String(key), value); } @@ -246,18 +269,18 @@ void ScriptController::collectGarbage() { LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_proxy->frame()); - if (context.IsEmpty()) + v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(m_proxy->frame()); + if (v8Context.IsEmpty()) return; - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); m_proxy->evaluate(ScriptSourceCode("if (window.gc) void(gc());"), 0); } bool ScriptController::haveInterpreter() const { - return m_proxy->ContextInitialized(); + return m_proxy->isContextInitialized(); } bool ScriptController::isEnabled() const @@ -309,9 +332,9 @@ PassScriptInstance ScriptController::createScriptInstanceForWidget(Widget* widge // // Inside the javascript engine, the engine can keep a reference to the // NPObject as part of its wrapper. However, before accessing the object - // it must consult the NPN_Registry. + // it must consult the _NPN_Registry. - v8::Local<v8::Object> wrapper = CreateV8ObjectForNPObject(npObject, 0); + v8::Local<v8::Object> wrapper = createV8ObjectForNPObject(npObject, 0); // Track the plugin object. We've been given a reference to the object. m_pluginObjects.set(widget, npObject); @@ -325,7 +348,7 @@ void ScriptController::cleanupScriptObjectsForPlugin(void* nativeHandle) if (it == m_pluginObjects.end()) return; _NPN_UnregisterObject(it->second); - NPN_ReleaseObject(it->second); + _NPN_ReleaseObject(it->second); m_pluginObjects.remove(it); } @@ -339,13 +362,13 @@ static NPObject* createScriptObject(Frame* frame) { LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(frame); - if (context.IsEmpty()) + v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(frame); + if (v8Context.IsEmpty()) return createNoScriptObject(); - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); DOMWindow* window = frame->domWindow(); - v8::Handle<v8::Value> global = V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, window); + v8::Handle<v8::Value> global = V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMWINDOW, window); ASSERT(global->IsObject()); return npCreateV8ScriptObject(0, v8::Handle<v8::Object>::Cast(global), window); } @@ -377,13 +400,13 @@ NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_frame); - if (context.IsEmpty()) + v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(m_frame); + if (v8Context.IsEmpty()) return createNoScriptObject(); - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); DOMWindow* window = m_frame->domWindow(); - v8::Handle<v8::Value> v8plugin = V8Proxy::ToV8Object(V8ClassIndex::HTMLEMBEDELEMENT, plugin); + v8::Handle<v8::Value> v8plugin = V8DOMWrapper::convertToV8Object(V8ClassIndex::HTMLEMBEDELEMENT, plugin); if (!v8plugin->IsObject()) return createNoScriptObject(); diff --git a/WebCore/bindings/v8/ScriptController.h b/WebCore/bindings/v8/ScriptController.h index 17703b5..47acf35 100644 --- a/WebCore/bindings/v8/ScriptController.h +++ b/WebCore/bindings/v8/ScriptController.h @@ -49,6 +49,7 @@ namespace WebCore { class ScriptState; class String; class Widget; + class XSSAuditor; class ScriptController { public: @@ -64,11 +65,17 @@ namespace WebCore { // as a string. ScriptValue evaluate(const ScriptSourceCode&); + // Executes JavaScript in a new world associated with the web frame. The + // script gets its own global scope, its own prototypes for intrinsic + // JavaScript objects (String, Array, and so-on), and its own wrappers for + // all DOM nodes and DOM constructors. + void evaluateInNewWorld(const Vector<ScriptSourceCode>&, int extensionGroup); + // Executes JavaScript in a new context associated with the web frame. The // script gets its own global scope and its own prototypes for intrinsic // JavaScript objects (String, Array, and so-on). It shares the wrappers for // all DOM nodes and DOM constructors. - void evaluateInNewContext(const Vector<ScriptSourceCode>&); + void evaluateInNewContext(const Vector<ScriptSourceCode>&, int extensionGroup); // JSC has a WindowShell object, but for V8, the ScriptController // is the WindowShell. @@ -81,6 +88,8 @@ namespace WebCore { ScriptState* state() const { return m_scriptState.get(); } + XSSAuditor* xssAuditor() { return m_XSSAuditor.get(); } + void collectGarbage(); // Creates a property of the global object of a frame. @@ -160,6 +169,8 @@ namespace WebCore { #if ENABLE(NETSCAPE_PLUGIN_API) NPObject* m_windowScriptNPObject; #endif + // The XSSAuditor associated with this ScriptController. + OwnPtr<XSSAuditor> m_XSSAuditor; }; } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptEventListener.cpp b/WebCore/bindings/v8/ScriptEventListener.cpp index 42c2529..7a8aa64 100644 --- a/WebCore/bindings/v8/ScriptEventListener.cpp +++ b/WebCore/bindings/v8/ScriptEventListener.cpp @@ -34,6 +34,7 @@ #include "Attribute.h" #include "Document.h" #include "Frame.h" +#include "XSSAuditor.h" namespace WebCore { @@ -46,6 +47,11 @@ PassRefPtr<V8LazyEventListener> createAttributeEventListener(Node* node, Attribu if (!frame) return 0; + if (!frame->script()->xssAuditor()->canCreateInlineEventListener(attr->localName().string(), attr->value())) { + // This script is not safe to execute. + return 0; + } + return V8LazyEventListener::create(frame, attr->value(), attr->localName().string(), node->isSVGElement()); } @@ -54,6 +60,11 @@ PassRefPtr<V8LazyEventListener> createAttributeEventListener(Frame* frame, Attri if (!frame) return 0; + if (!frame->script()->xssAuditor()->canCreateInlineEventListener(attr->localName().string(), attr->value())) { + // This script is not safe to execute. + return 0; + } + return V8LazyEventListener::create(frame, attr->value(), attr->localName().string(), frame->document()->isSVGDocument()); } diff --git a/WebCore/bindings/v8/ScriptFunctionCall.cpp b/WebCore/bindings/v8/ScriptFunctionCall.cpp index d2f7a52..2fa43d5 100644 --- a/WebCore/bindings/v8/ScriptFunctionCall.cpp +++ b/WebCore/bindings/v8/ScriptFunctionCall.cpp @@ -162,7 +162,7 @@ ScriptObject ScriptFunctionCall::construct(bool& hadException, bool reportExcept return ScriptObject(); } - return ScriptObject(result); + return ScriptObject(m_scriptState, result); } } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptInstance.cpp b/WebCore/bindings/v8/ScriptInstance.cpp index aa4a396..645b1da 100644 --- a/WebCore/bindings/v8/ScriptInstance.cpp +++ b/WebCore/bindings/v8/ScriptInstance.cpp @@ -62,7 +62,7 @@ void V8ScriptInstance::clear() if (m_instance.IsEmpty()) return; #ifndef NDEBUG - V8Proxy::UnregisterGlobalHandle(this, m_instance); + V8GCController::unregisterGlobalHandle(this, m_instance); #endif m_instance.Dispose(); m_instance.Clear(); @@ -76,7 +76,7 @@ void V8ScriptInstance::set(v8::Handle<v8::Object> instance) m_instance = v8::Persistent<v8::Object>::New(instance); #ifndef NDEBUG - V8Proxy::RegisterGlobalHandle(SCRIPTINSTANCE, this, m_instance); + V8GCController::registerGlobalHandle(SCRIPTINSTANCE, this, m_instance); #endif } diff --git a/WebCore/bindings/v8/ScriptObject.cpp b/WebCore/bindings/v8/ScriptObject.cpp index 59316f0..c64cfe4 100644 --- a/WebCore/bindings/v8/ScriptObject.cpp +++ b/WebCore/bindings/v8/ScriptObject.cpp @@ -43,8 +43,9 @@ namespace WebCore { -ScriptObject::ScriptObject(v8::Handle<v8::Object> v8Object) +ScriptObject::ScriptObject(ScriptState* scriptState, v8::Handle<v8::Object> v8Object) : ScriptValue(v8Object) + , m_scriptState(scriptState) { } @@ -54,51 +55,51 @@ v8::Local<v8::Object> ScriptObject::v8Object() const return v8::Local<v8::Object>(v8::Object::Cast(*v8Value())); } -bool ScriptObject::set(ScriptState* scriptState, const String& name, const String& value) +bool ScriptObject::set(const String& name, const String& value) { - ScriptScope scope(scriptState); + ScriptScope scope(m_scriptState); v8Object()->Set(v8String(name), v8String(value)); return scope.success(); } -bool ScriptObject::set(ScriptState* scriptState, const char* name, const ScriptObject& value) +bool ScriptObject::set(const char* name, const ScriptObject& value) { - ScriptScope scope(scriptState); + ScriptScope scope(m_scriptState); v8Object()->Set(v8::String::New(name), value.v8Value()); return scope.success(); } -bool ScriptObject::set(ScriptState* scriptState, const char* name, const String& value) +bool ScriptObject::set(const char* name, const String& value) { - ScriptScope scope(scriptState); + ScriptScope scope(m_scriptState); v8Object()->Set(v8::String::New(name), v8String(value)); return scope.success(); } -bool ScriptObject::set(ScriptState* scriptState, const char* name, double value) +bool ScriptObject::set(const char* name, double value) { - ScriptScope scope(scriptState); + ScriptScope scope(m_scriptState); v8Object()->Set(v8::String::New(name), v8::Number::New(value)); return scope.success(); } -bool ScriptObject::set(ScriptState* scriptState, const char* name, long long value) +bool ScriptObject::set(const char* name, long long value) { - ScriptScope scope(scriptState); + ScriptScope scope(m_scriptState); v8Object()->Set(v8::String::New(name), v8::Number::New(value)); return scope.success(); } -bool ScriptObject::set(ScriptState* scriptState, const char* name, int value) +bool ScriptObject::set(const char* name, int value) { - ScriptScope scope(scriptState); + ScriptScope scope(m_scriptState); v8Object()->Set(v8::String::New(name), v8::Number::New(value)); return scope.success(); } -bool ScriptObject::set(ScriptState* scriptState, const char* name, bool value) +bool ScriptObject::set(const char* name, bool value) { - ScriptScope scope(scriptState); + ScriptScope scope(m_scriptState); v8Object()->Set(v8::String::New(name), v8Boolean(value)); return scope.success(); } @@ -106,7 +107,7 @@ bool ScriptObject::set(ScriptState* scriptState, const char* name, bool value) ScriptObject ScriptObject::createNew(ScriptState* scriptState) { ScriptScope scope(scriptState); - return ScriptObject(v8::Object::New()); + return ScriptObject(scriptState, v8::Object::New()); } bool ScriptGlobalObject::set(ScriptState* scriptState, const char* name, const ScriptObject& value) @@ -116,12 +117,16 @@ bool ScriptGlobalObject::set(ScriptState* scriptState, const char* name, const S return scope.success(); } -bool ScriptGlobalObject::set(ScriptState* scriptState, const char* name, InspectorController* value) +bool ScriptGlobalObject::set(ScriptState* scriptState, const char* name, InspectorBackend* value) { ScriptScope scope(scriptState); +#ifdef MANUAL_MERGE_REQUIRED #if !PLATFORM(ANDROID) scope.global()->Set(v8::String::New(name), V8Proxy::ToV8Object(V8ClassIndex::INSPECTORCONTROLLER, value)); #endif +#else // MANUAL_MERGE_REQUIRED + scope.global()->Set(v8::String::New(name), V8DOMWrapper::convertToV8Object(V8ClassIndex::INSPECTORBACKEND, value)); +#endif // MANUAL_MERGE_REQUIRED return scope.success(); } @@ -135,7 +140,7 @@ bool ScriptGlobalObject::get(ScriptState* scriptState, const char* name, ScriptO if (!v8Value->IsObject()) return false; - value = ScriptObject(v8::Handle<v8::Object>(v8::Object::Cast(*v8Value))); + value = ScriptObject(scriptState, v8::Handle<v8::Object>(v8::Object::Cast(*v8Value))); return true; } diff --git a/WebCore/bindings/v8/ScriptObject.h b/WebCore/bindings/v8/ScriptObject.h index e5618ab..dcee3a5 100644 --- a/WebCore/bindings/v8/ScriptObject.h +++ b/WebCore/bindings/v8/ScriptObject.h @@ -36,32 +36,34 @@ #include <v8.h> namespace WebCore { - class InspectorController; + class InspectorBackend; class ScriptState; class ScriptObject : public ScriptValue { public: - ScriptObject(v8::Handle<v8::Object>); - ScriptObject() {} + ScriptObject(ScriptState*, v8::Handle<v8::Object>); + ScriptObject() {}; virtual ~ScriptObject() {} v8::Local<v8::Object> v8Object() const; - bool set(ScriptState*, const String& name, const String&); - bool set(ScriptState*, const char* name, const ScriptObject&); - bool set(ScriptState*, const char* name, const String&); - bool set(ScriptState*, const char* name, double); - bool set(ScriptState*, const char* name, long long); - bool set(ScriptState*, const char* name, int); - bool set(ScriptState*, const char* name, bool); + bool set(const String& name, const String&); + bool set(const char* name, const ScriptObject&); + bool set(const char* name, const String&); + bool set(const char* name, double); + bool set(const char* name, long long); + bool set(const char* name, int); + bool set(const char* name, bool); static ScriptObject createNew(ScriptState*); + protected: + ScriptState* m_scriptState; }; class ScriptGlobalObject { public: static bool set(ScriptState*, const char* name, const ScriptObject&); - static bool set(ScriptState*, const char* name, InspectorController*); + static bool set(ScriptState*, const char* name, InspectorBackend*); static bool get(ScriptState*, const char* name, ScriptObject&); static bool remove(ScriptState*, const char* name); private: diff --git a/WebCore/bindings/v8/ScriptObjectQuarantine.cpp b/WebCore/bindings/v8/ScriptObjectQuarantine.cpp index 8a7715e..053cf68 100644 --- a/WebCore/bindings/v8/ScriptObjectQuarantine.cpp +++ b/WebCore/bindings/v8/ScriptObjectQuarantine.cpp @@ -66,9 +66,18 @@ bool getQuarantinedScriptObject(Frame* frame, Storage* storage, ScriptObject& qu ASSERT(frame); ASSERT(storage); - // FIXME: Implement when DOM Storage V8 bindings are enabled +#if ENABLE(DOM_STORAGE) + v8::HandleScope handleScope; + v8::Local<v8::Context> context = V8Proxy::context(frame); + // FIXME: What if context.IsEmpty()? + v8::Context::Scope scope(context); + + v8::Handle<v8::Value> v8Storage = V8DOMWrapper::convertToV8Object(V8ClassIndex::STORAGE, storage); + quarantinedObject = ScriptObject(frame->script()->state(), v8::Local<v8::Object>(v8::Object::Cast(*v8Storage))); +#else ASSERT_NOT_REACHED(); quarantinedObject = ScriptObject(); +#endif return true; } @@ -77,11 +86,15 @@ bool getQuarantinedScriptObject(Node* node, ScriptObject& quarantinedObject) ASSERT(node); v8::HandleScope handleScope; - v8::Local<v8::Context> context = V8Proxy::GetContext(node->document()->page()->mainFrame()); + // FIXME: What if document() is null? + // FIXME: Why are we grabbing the mainFrame? + Frame* frame = node->document()->page()->mainFrame(); + v8::Local<v8::Context> context = V8Proxy::context(frame); + // FIXME: What if context.IsEmpty()? v8::Context::Scope scope(context); - v8::Handle<v8::Value> v8Node = V8Proxy::NodeToV8Object(node); - quarantinedObject = ScriptObject(v8::Local<v8::Object>(v8::Object::Cast(*v8Node))); + v8::Handle<v8::Value> v8Node = V8DOMWrapper::convertNodeToV8Object(node); + quarantinedObject = ScriptObject(frame->script()->state(), v8::Local<v8::Object>(v8::Object::Cast(*v8Node))); return true; } @@ -91,11 +104,14 @@ bool getQuarantinedScriptObject(DOMWindow* domWindow, ScriptObject& quarantinedO ASSERT(domWindow); v8::HandleScope handleScope; - v8::Local<v8::Context> context = V8Proxy::GetContext(domWindow->frame()); + Frame* frame = domWindow->frame(); + // FIXME: What if frame is null? + v8::Local<v8::Context> context = V8Proxy::context(frame); + // FIXME: What if context.IsEmpty()? v8::Context::Scope scope(context); - v8::Handle<v8::Value> v8DomWindow = V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, domWindow); - quarantinedObject = ScriptObject(v8::Local<v8::Object>(v8::Object::Cast(*v8DomWindow))); + v8::Handle<v8::Value> v8DomWindow = V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMWINDOW, domWindow); + quarantinedObject = ScriptObject(frame->script()->state(), v8::Local<v8::Object>(v8::Object::Cast(*v8DomWindow))); return true; } diff --git a/WebCore/bindings/v8/ScriptScope.cpp b/WebCore/bindings/v8/ScriptScope.cpp index 937f664..52cab10 100644 --- a/WebCore/bindings/v8/ScriptScope.cpp +++ b/WebCore/bindings/v8/ScriptScope.cpp @@ -43,7 +43,7 @@ namespace WebCore { ScriptScope::ScriptScope(ScriptState* scriptState, bool reportExceptions) - : m_context(V8Proxy::GetContext(scriptState->frame())) + : m_context(V8Proxy::context(scriptState->frame())) , m_scope(m_context) , m_scriptState(scriptState) , m_reportExceptions(reportExceptions) diff --git a/WebCore/bindings/v8/ScriptValue.h b/WebCore/bindings/v8/ScriptValue.h index 04e8819..004851b 100644 --- a/WebCore/bindings/v8/ScriptValue.h +++ b/WebCore/bindings/v8/ScriptValue.h @@ -53,7 +53,7 @@ public: m_value = v8::Persistent<v8::Value>::New(value); #ifndef NDEBUG - V8Proxy::RegisterGlobalHandle(SCRIPTVALUE, this, m_value); + V8GCController::registerGlobalHandle(SCRIPTVALUE, this, m_value); #endif } @@ -64,7 +64,7 @@ public: m_value = v8::Persistent<v8::Value>::New(value.m_value); #ifndef NDEBUG - V8Proxy::RegisterGlobalHandle(SCRIPTVALUE, this, m_value); + V8GCController::registerGlobalHandle(SCRIPTVALUE, this, m_value); #endif } @@ -80,7 +80,7 @@ public: m_value = v8::Persistent<v8::Value>::New(value.m_value); #ifndef NDEBUG - V8Proxy::RegisterGlobalHandle(SCRIPTVALUE, this, m_value); + V8GCController::registerGlobalHandle(SCRIPTVALUE, this, m_value); #endif return *this; @@ -122,7 +122,7 @@ public: return; #ifndef NDEBUG - V8Proxy::UnregisterGlobalHandle(this, m_value); + V8GCController::unregisterGlobalHandle(this, m_value); #endif m_value.Dispose(); m_value.Clear(); diff --git a/WebCore/bindings/v8/StaticDOMDataStore.cpp b/WebCore/bindings/v8/StaticDOMDataStore.cpp new file mode 100644 index 0000000..3a02c0b --- /dev/null +++ b/WebCore/bindings/v8/StaticDOMDataStore.cpp @@ -0,0 +1,55 @@ +/* + * 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: + * + * * 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. + */ + +#include "config.h" +#include "StaticDOMDataStore.h" + +namespace WebCore { + +StaticDOMDataStore::StaticDOMDataStore(DOMData* domData) + : DOMDataStore(domData) + , m_staticDomNodeMap(domData, &DOMDataStore::weakNodeCallback) + , m_staticDomObjectMap(domData, &DOMDataStore::weakDOMObjectCallback) + , m_staticActiveDomObjectMap(domData, &DOMDataStore::weakActiveDOMObjectCallback) +#if ENABLE(SVG) + , m_staticDomSvgElementInstanceMap(domData, &DOMDataStore::weakSVGElementInstanceCallback) + , m_staticDomSvgObjectWithContextMap(domData, &DOMDataStore::weakSVGObjectWithContextCallback) +#endif +{ + m_domNodeMap = &m_staticDomNodeMap; + m_domObjectMap = &m_staticDomObjectMap; + m_activeDomObjectMap = &m_staticActiveDomObjectMap; +#if ENABLE(SVG) + m_domSvgElementInstanceMap = &m_staticDomSvgElementInstanceMap; + m_domSvgObjectWithContextMap = &m_staticDomSvgObjectWithContextMap; +#endif +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/StaticDOMDataStore.h b/WebCore/bindings/v8/StaticDOMDataStore.h new file mode 100644 index 0000000..4cd0515 --- /dev/null +++ b/WebCore/bindings/v8/StaticDOMDataStore.h @@ -0,0 +1,63 @@ +/* + * 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: + * + * * 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 StaticDOMDataStore_h +#define StaticDOMDataStore_h + +#include "DOMDataStore.h" + +namespace WebCore { + +// StaticDOMDataStore +// +// StaticDOMDataStore is a DOMDataStore that manages the lifetime of the store +// statically. This encapsulates thread-specific DOM data for the main +// thread. All the maps in it are static. This is because we are unable to +// rely on WTF::ThreadSpecificThreadExit to do the cleanup since the place that +// tears down the main thread can not call any WTF functions. +// +class StaticDOMDataStore : public DOMDataStore { +public: + StaticDOMDataStore(DOMData*); + +private: + InternalDOMWrapperMap<Node> m_staticDomNodeMap; + InternalDOMWrapperMap<void> m_staticDomObjectMap; + InternalDOMWrapperMap<void> m_staticActiveDomObjectMap; +#if ENABLE(SVG) + InternalDOMWrapperMap<SVGElementInstance> m_staticDomSvgElementInstanceMap; + InternalDOMWrapperMap<void> m_staticDomSvgObjectWithContextMap; +#endif +}; + +} // namespace WebCore + +#endif // StaticDOMDataStore_h + diff --git a/WebCore/bindings/v8/V8AbstractEventListener.cpp b/WebCore/bindings/v8/V8AbstractEventListener.cpp index 07e944d..0c81846 100644 --- a/WebCore/bindings/v8/V8AbstractEventListener.cpp +++ b/WebCore/bindings/v8/V8AbstractEventListener.cpp @@ -48,6 +48,12 @@ V8AbstractEventListener::V8AbstractEventListener(Frame* frame, bool isAttribute) if (!m_frame) return; + // We might be called directly from the parser. + v8::HandleScope handleScope; + + m_context.set(V8Proxy::context(m_frame)); + m_context.makeWeak(); + // Get the position in the source if any. if (m_isAttribute && m_frame->document()->tokenizer()) { m_lineNumber = m_frame->document()->tokenizer()->lineNumber(); @@ -55,7 +61,7 @@ V8AbstractEventListener::V8AbstractEventListener(Frame* frame, bool isAttribute) } } -void V8AbstractEventListener::invokeEventHandler(v8::Handle<v8::Context> context, Event* event, v8::Handle<v8::Value> jsEvent, bool isWindowEvent) +void V8AbstractEventListener::invokeEventHandler(v8::Handle<v8::Context> v8Context, Event* event, v8::Handle<v8::Value> jsEvent, bool isWindowEvent) { // We push the event being processed into the global object, so that it can be exposed by DOMWindow's bindings. v8::Local<v8::String> eventSymbol = v8::String::NewSymbol("event"); @@ -67,11 +73,11 @@ void V8AbstractEventListener::invokeEventHandler(v8::Handle<v8::Context> context tryCatch.SetVerbose(true); // Save the old 'event' property so we can restore it later. - v8::Local<v8::Value> savedEvent = context->Global()->GetHiddenValue(eventSymbol); + v8::Local<v8::Value> savedEvent = v8Context->Global()->GetHiddenValue(eventSymbol); tryCatch.Reset(); // Make the event available in the global object, so DOMWindow can expose it. - context->Global()->SetHiddenValue(eventSymbol, jsEvent); + v8Context->Global()->SetHiddenValue(eventSymbol, jsEvent); tryCatch.Reset(); // Call the event handler. @@ -80,13 +86,13 @@ void V8AbstractEventListener::invokeEventHandler(v8::Handle<v8::Context> context // Restore the old event. This must be done for all exit paths through this method. if (savedEvent.IsEmpty()) - context->Global()->SetHiddenValue(eventSymbol, v8::Undefined()); + v8Context->Global()->SetHiddenValue(eventSymbol, v8::Undefined()); else - context->Global()->SetHiddenValue(eventSymbol, savedEvent); + v8Context->Global()->SetHiddenValue(eventSymbol, savedEvent); tryCatch.Reset(); } - ASSERT(!V8Proxy::HandleOutOfMemory() || returnValue.IsEmpty()); + ASSERT(!V8Proxy::handleOutOfMemory() || returnValue.IsEmpty()); if (returnValue.IsEmpty()) return; @@ -113,20 +119,20 @@ void V8AbstractEventListener::handleEvent(Event* event, bool isWindowEvent) LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_frame); - if (context.IsEmpty()) + v8::Handle<v8::Context> v8Context = m_context.get(); + if (v8Context.IsEmpty()) return; // m_frame can removed by the callback function, protect it until the callback function returns. RefPtr<Frame> protectFrame(m_frame); // Enter the V8 context in which to perform the event handling. - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); // Get the V8 wrapper for the event object. - v8::Handle<v8::Value> jsEvent = V8Proxy::EventToV8Object(event); + v8::Handle<v8::Value> jsEvent = V8DOMWrapper::convertEventToV8Object(event); - invokeEventHandler(context, event, jsEvent, isWindowEvent); + invokeEventHandler(v8Context, event, jsEvent, isWindowEvent); Document::updateStyleForAllDocuments(); } @@ -135,7 +141,7 @@ void V8AbstractEventListener::disposeListenerObject() { if (!m_listener.IsEmpty()) { #ifndef NDEBUG - V8Proxy::UnregisterGlobalHandle(this, m_listener); + V8GCController::unregisterGlobalHandle(this, m_listener); #endif m_listener.Dispose(); m_listener.Clear(); @@ -151,7 +157,7 @@ v8::Local<v8::Object> V8AbstractEventListener::getReceiverObject(Event* event, b return v8::Context::GetCurrent()->Global(); EventTarget* target = event->currentTarget(); - v8::Handle<v8::Value> value = V8Proxy::EventTargetToV8Object(target); + v8::Handle<v8::Value> value = V8DOMWrapper::convertEventTargetToV8Object(target); if (value.IsEmpty()) return v8::Local<v8::Object>(); return v8::Local<v8::Object>::New(v8::Handle<v8::Object>::Cast(value)); diff --git a/WebCore/bindings/v8/V8AbstractEventListener.h b/WebCore/bindings/v8/V8AbstractEventListener.h index ed643db..1521941 100644 --- a/WebCore/bindings/v8/V8AbstractEventListener.h +++ b/WebCore/bindings/v8/V8AbstractEventListener.h @@ -32,6 +32,7 @@ #define V8AbstractEventListener_h #include "EventListener.h" +#include "OwnHandle.h" #include <v8.h> namespace WebCore { @@ -39,11 +40,14 @@ namespace WebCore { class Event; class Frame; - // There are two kinds of event listeners: HTML or non-HMTL. onload, onfocus, etc (attributes) are always HTML event handler type; - // Event listeners added by Window.addEventListener or EventTargetNode::addEventListener are non-HTML type. + // There are two kinds of event listeners: HTML or non-HMTL. onload, + // onfocus, etc (attributes) are always HTML event handler type; Event + // listeners added by Window.addEventListener or + // EventTargetNode::addEventListener are non-HTML type. // // Why does this matter? - // WebKit does not allow duplicated HTML event handlers of the same type, but ALLOWs duplicated non-HTML event handlers. + // WebKit does not allow duplicated HTML event handlers of the same type, + // but ALLOWs duplicated non-HTML event handlers. class V8AbstractEventListener : public EventListener { public: virtual ~V8AbstractEventListener() { } @@ -65,6 +69,8 @@ namespace WebCore { virtual bool disconnected() const { return !m_frame; } + virtual bool isObjectListener() const { return false; } + protected: v8::Persistent<v8::Object> m_listener; @@ -83,6 +89,7 @@ namespace WebCore { // deleted. See fast/dom/replaceChild.html // FIXME: this could hold m_frame live until the event listener is deleted. Frame* m_frame; + OwnHandle<v8::Context> m_context; // Position in the HTML source for HTML event listeners. int m_lineNumber; diff --git a/WebCore/bindings/v8/V8Binding.cpp b/WebCore/bindings/v8/V8Binding.cpp new file mode 100644 index 0000000..c5d580a --- /dev/null +++ b/WebCore/bindings/v8/V8Binding.cpp @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2006, 2007, 2008, 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: + * + * * 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. + */ + +#include "config.h" +#include "V8Binding.h" + +#include "AtomicString.h" +#include "CString.h" +#include "MathExtras.h" +#include "PlatformString.h" +#include "StdLibExtras.h" +#include "StringBuffer.h" +#include "StringHash.h" +#include "Threading.h" + +#include <v8.h> + +namespace WebCore { + +// WebCoreStringResource is a helper class for v8ExternalString. It is used +// to manage the life-cycle of the underlying buffer of the external string. +class WebCoreStringResource : public v8::String::ExternalStringResource { +public: + explicit WebCoreStringResource(const String& string) + : m_plainString(string) + { +#ifndef NDEBUG + m_threadId = WTF::currentThread(); +#endif + v8::V8::AdjustAmountOfExternalAllocatedMemory(2 * length()); + } + + explicit WebCoreStringResource(const AtomicString& string) + : m_plainString(string) + , m_atomicString(string) + { +#ifndef NDEBUG + m_threadId = WTF::currentThread(); +#endif + v8::V8::AdjustAmountOfExternalAllocatedMemory(2 * length()); + } + + virtual ~WebCoreStringResource() + { +#ifndef NDEBUG + ASSERT(m_threadId == WTF::currentThread()); +#endif + int reducedExternalMemory = -2 * length(); + if (!m_plainString.impl()->inTable()) + reducedExternalMemory *= 2; + v8::V8::AdjustAmountOfExternalAllocatedMemory(reducedExternalMemory); + } + + const uint16_t* data() const + { + return reinterpret_cast<const uint16_t*>(m_plainString.characters()); + } + + size_t length() const { return m_plainString.length(); } + + String webcoreString() { return m_plainString; } + + AtomicString atomicString() + { +#ifndef NDEBUG + ASSERT(m_threadId == WTF::currentThread()); +#endif + if (m_atomicString.isNull()) { + m_atomicString = AtomicString(m_plainString); + if (!m_plainString.impl()->inTable()) + v8::V8::AdjustAmountOfExternalAllocatedMemory(2 * length()); + } + return m_atomicString; + } + + static WebCoreStringResource* toStringResource(v8::Handle<v8::String> v8String) + { + return static_cast<WebCoreStringResource*>(v8String->GetExternalStringResource()); + } + +private: + // A shallow copy of the string. Keeps the string buffer alive until the V8 engine garbage collects it. + String m_plainString; + // If this string is atomic or has been made atomic earlier the + // atomic string is held here. In the case where the string starts + // off non-atomic and becomes atomic later it is necessary to keep + // the original string alive because v8 may keep derived pointers + // into that string. + AtomicString m_atomicString; + +#ifndef NDEBUG + WTF::ThreadIdentifier m_threadId; +#endif +}; + +String v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode external, + StringType type) +{ + WebCoreStringResource* stringResource = WebCoreStringResource::toStringResource(v8String); + if (stringResource) + return stringResource->webcoreString(); + + int length = v8String->Length(); + if (!length) { + // Avoid trying to morph empty strings, as they do not have enough room to contain the external reference. + return StringImpl::empty(); + } + + UChar* buffer; + String result = String::createUninitialized(length, buffer); + v8String->Write(reinterpret_cast<uint16_t*>(buffer), 0, length); + + if (type == AtomicStringType) + result = AtomicString(result); + + if (external == Externalize) { + WebCoreStringResource* resource = new WebCoreStringResource(result); + if (!v8String->MakeExternal(resource)) { + // In case of a failure delete the external resource as it was not used. + delete resource; + } + } + return result; +} + +AtomicString v8StringToAtomicWebCoreString(v8::Handle<v8::String> v8String) +{ + WebCoreStringResource* stringResource = WebCoreStringResource::toStringResource(v8String); + if (!stringResource) { + // If this string hasn't been externalized, we force it now. + String plain = v8StringToWebCoreString(v8String, Externalize, AtomicStringType); + // If the string is empty there's no room to cache an atomic + // string so we bail out. + if (plain.isEmpty()) + return plain; + stringResource = WebCoreStringResource::toStringResource(v8String); + ASSERT(stringResource != NULL); + } + return stringResource->atomicString(); +} + +String v8ValueToWebCoreString(v8::Handle<v8::Value> object) +{ + if (object->IsString()) + return v8StringToWebCoreString(v8::Handle<v8::String>::Cast(object), Externalize, PlainStringType); + + if (object->IsInt32()) { + int value = object->Int32Value(); + // Most numbers used are <= 100. Even if they aren't used there's very little in using the space. + const int kLowNumbers = 100; + static AtomicString lowNumbers[kLowNumbers + 1]; + String webCoreString; + if (0 <= value && value <= kLowNumbers) { + webCoreString = lowNumbers[value]; + if (!webCoreString) { + AtomicString valueString = AtomicString(String::number(value)); + lowNumbers[value] = valueString; + webCoreString = valueString; + } + } else + webCoreString = String::number(value); + return webCoreString; + } + + v8::TryCatch block; + v8::Handle<v8::String> v8String = object->ToString(); + // Check for empty handles to handle the case where an exception + // is thrown as part of invoking toString on the objectect. + if (v8String.IsEmpty()) + return StringImpl::empty(); + return v8StringToWebCoreString(v8String, DoNotExternalize, PlainStringType); +} + +AtomicString v8ValueToAtomicWebCoreString(v8::Handle<v8::Value> v8Value) +{ + if (v8Value->IsString()) + return v8StringToAtomicWebCoreString(v8::Handle<v8::String>::Cast(v8Value)); + String string = v8ValueToWebCoreString(v8Value); + return AtomicString(string); +} + +v8::Handle<v8::String> v8String(const String& string) +{ + return v8ExternalString(string); +} + +static bool stringImplCacheEnabled = false; + +void enableStringImplCache() +{ + stringImplCacheEnabled = true; +} + +static v8::Local<v8::String> makeExternalString(const String& string) +{ + WebCoreStringResource* stringResource = new WebCoreStringResource(string); + v8::Local<v8::String> newString = v8::String::NewExternal(stringResource); + if (newString.IsEmpty()) + delete stringResource; + + return newString; +} + +typedef HashMap<StringImpl*, v8::String*> StringCache; + +static StringCache& getStringCache() +{ + ASSERT(WTF::isMainThread()); + DEFINE_STATIC_LOCAL(StringCache, mainThreadStringCache, ()); + return mainThreadStringCache; +} + +static void cachedStringCallback(v8::Persistent<v8::Value> wrapper, void* parameter) +{ + ASSERT(WTF::isMainThread()); + StringImpl* stringImpl = static_cast<StringImpl*>(parameter); + ASSERT(getStringCache().contains(stringImpl)); + getStringCache().remove(stringImpl); + wrapper.Dispose(); + stringImpl->deref(); +} + +v8::Local<v8::String> v8ExternalString(const String& string) +{ + if (!string.length()) + return v8::String::Empty(); + + if (!stringImplCacheEnabled) + return makeExternalString(string); + + StringImpl* stringImpl = string.impl(); + StringCache& stringCache = getStringCache(); + v8::String* cachedV8String = stringCache.get(stringImpl); + if (cachedV8String) + return v8::Local<v8::String>(cachedV8String); + + v8::Local<v8::String> newString = makeExternalString(string); + if (newString.IsEmpty()) + return newString; + + v8::Persistent<v8::String> wrapper = v8::Persistent<v8::String>::New(newString); + if (wrapper.IsEmpty()) + return newString; + + stringImpl->ref(); + wrapper.MakeWeak(stringImpl, cachedStringCallback); + stringCache.set(stringImpl, *wrapper); + + return newString; +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/V8Binding.h b/WebCore/bindings/v8/V8Binding.h index 9fce3f2..4f36f00 100644 --- a/WebCore/bindings/v8/V8Binding.h +++ b/WebCore/bindings/v8/V8Binding.h @@ -31,16 +31,91 @@ #ifndef V8Binding_h #define V8Binding_h -// FIXME: This is a temporary forwarding header until all bindings have migrated -// over and v8_binding actually becomes V8Binding. -#include "v8_binding.h" +#include "MathExtras.h" +#include "PlatformString.h" + +#include <v8.h> namespace WebCore { - // FIXME: Remove once migration is complete. + enum ExternalMode { + Externalize, + DoNotExternalize + }; + + enum StringType { + PlainStringType, + AtomicStringType + }; + + // Convert v8 types to a WebCore::String. If the V8 string is not already + // an external string then it is transformed into an external string at this + // point to avoid repeated conversions. + String v8StringToWebCoreString(v8::Handle<v8::String>, ExternalMode mode, StringType type); + String v8ValueToWebCoreString(v8::Handle<v8::Value>); + + // Convert v8 types to a WebCore::AtomicString. + AtomicString v8StringToAtomicWebCoreString(v8::Handle<v8::String>); + AtomicString v8ValueToAtomicWebCoreString(v8::Handle<v8::Value>); + + // Convert a string to a V8 string. + v8::Handle<v8::String> v8String(const String&); + + inline String toString(const String& string)
+ {
+ return string;
+ } + + // Return a V8 external string that shares the underlying buffer with the given + // WebCore string. The reference counting mechanism is used to keep the + // underlying buffer alive while the string is still live in the V8 engine. + v8::Local<v8::String> v8ExternalString(const String&); + + // Enables caching v8 wrappers created for WebCore::StringImpl. Currently this cache requires + // all the calls (both to convert WebCore::String to v8::String and to GC the handle) + // to be performed on the main thread. + void enableStringImplCache(); + + // Convert a value to a 32-bit integer. The conversion fails if the + // value cannot be converted to an integer or converts to nan or to an infinity. + inline int toInt32(v8::Handle<v8::Value> value, bool& ok) + { + ok = true; + + // Fast case. The value is already a 32-bit integer. + if (value->IsInt32()) + return value->Int32Value(); + + // Can the value be converted to a number? + v8::Local<v8::Number> numberObject = value->ToNumber(); + if (numberObject.IsEmpty()) { + ok = false; + return 0; + } + + // Does the value convert to nan or to an infinity? + double numberValue = numberObject->Value(); + if (isnan(numberValue) || isinf(numberValue)) { + ok = false; + return 0; + } + + // Can the value be converted to a 32-bit integer? + v8::Local<v8::Int32> intValue = value->ToInt32(); + if (intValue.IsEmpty()) { + ok = false; + return 0; + } + + // Return the result of the int32 conversion. + return intValue->Value(); + } + + // Convert a value to a 32-bit integer assuming the conversion cannot fail. inline int toInt32(v8::Handle<v8::Value> value) { - return ToInt32(value); + bool ok; + return toInt32(value, ok); } inline float toFloat(v8::Local<v8::Value> value) @@ -48,22 +123,17 @@ namespace WebCore { return static_cast<float>(value->NumberValue()); } - // FIXME: Remove once migration is complete. - inline String toWebCoreString(v8::Handle<v8::Value> obj) + // FIXME: Drop this in favor of the type specific v8ValueToWebCoreString when we rework the code generation. + inline String toWebCoreString(v8::Handle<v8::Value> object) { - return ToWebCoreString(obj); + return v8ValueToWebCoreString(object); } - // FIXME: Remove once migration is complete. + // The string returned by this function is still owned by the argument + // and will be deallocated when the argument is deallocated. inline const uint16_t* fromWebCoreString(const String& str) { - return FromWebCoreString(str); - } - - // FIXME: Rename valueToStringWithNullCheck once migration is complete. - inline String toWebCoreStringWithNullCheck(v8::Handle<v8::Value> value) - { - return valueToStringWithNullCheck(value); + return reinterpret_cast<const uint16_t*>(str.characters()); } inline bool isUndefinedOrNull(v8::Handle<v8::Value> value) @@ -75,7 +145,40 @@ namespace WebCore { { return value ? v8::True() : v8::False(); } + + inline String toWebCoreStringWithNullCheck(v8::Handle<v8::Value> value) + { + if (value->IsNull()) + return String(); + return v8ValueToWebCoreString(value); + } -} + inline String toWebCoreStringWithNullOrUndefinedCheck(v8::Handle<v8::Value> value) + { + if (value->IsNull() || value->IsUndefined()) + return String(); + return toWebCoreString(value); + } + + inline v8::Handle<v8::String> v8UndetectableString(const String& str) + { + return v8::String::NewUndetectable(fromWebCoreString(str), str.length()); + } + + inline v8::Handle<v8::Value> v8StringOrNull(const String& str) + { + return str.isNull() ? v8::Handle<v8::Value>(v8::Null()) : v8::Handle<v8::Value>(v8String(str)); + } + + inline v8::Handle<v8::Value> v8StringOrUndefined(const String& str) + { + return str.isNull() ? v8::Handle<v8::Value>(v8::Undefined()) : v8::Handle<v8::Value>(v8String(str)); + } + + inline v8::Handle<v8::Value> v8StringOrFalse(const String& str) + { + return str.isNull() ? v8::Handle<v8::Value>(v8::False()) : v8::Handle<v8::Value>(v8String(str)); + } +} // namespace WebCore #endif // V8Binding_h diff --git a/WebCore/bindings/v8/V8Collection.cpp b/WebCore/bindings/v8/V8Collection.cpp index 861f68a..c9fc9ac 100644 --- a/WebCore/bindings/v8/V8Collection.cpp +++ b/WebCore/bindings/v8/V8Collection.cpp @@ -48,14 +48,14 @@ v8::Handle<v8::Value> toOptionsCollectionSetter(uint32_t index, v8::Handle<v8::V // Check that the value is an HTMLOptionElement. If not, throw a TYPE_MISMATCH_ERR DOMException. if (!V8HTMLOptionElement::HasInstance(value)) { - V8Proxy::SetDOMException(TYPE_MISMATCH_ERR); + V8Proxy::setDOMException(TYPE_MISMATCH_ERR); return value; } - HTMLOptionElement* element = V8Proxy::DOMWrapperToNode<HTMLOptionElement>(v8::Handle<v8::Object>::Cast(value)); + HTMLOptionElement* element = V8DOMWrapper::convertDOMWrapperToNode<HTMLOptionElement>(v8::Handle<v8::Object>::Cast(value)); base->setOption(index, element, ec); - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return value; } diff --git a/WebCore/bindings/v8/V8Collection.h b/WebCore/bindings/v8/V8Collection.h index 1731f9c..cbfe921 100644 --- a/WebCore/bindings/v8/V8Collection.h +++ b/WebCore/bindings/v8/V8Collection.h @@ -47,8 +47,8 @@ namespace WebCore { return v8::Handle<v8::Value>(); V8ClassIndex::V8WrapperType type = V8ClassIndex::FromInt(implementationType->Int32Value()); if (type == V8ClassIndex::NODE) - return V8Proxy::NodeToV8Object(static_cast<Node*>(implementation)); - return V8Proxy::ToV8Object(type, implementation); + return V8DOMWrapper::convertNodeToV8Object(static_cast<Node*>(implementation)); + return V8DOMWrapper::convertToV8Object(type, implementation); } template<class T> static v8::Handle<v8::Value> getV8Object(PassRefPtr<T> implementation, v8::Local<v8::Value> implementationType) @@ -61,10 +61,10 @@ namespace WebCore { v8::Local<v8::Value> implementationType) { // FIXME: assert object is a collection type - ASSERT(V8Proxy::MaybeDOMWrapper(object)); - V8ClassIndex::V8WrapperType wrapperType = V8Proxy::GetDOMWrapperType(object); + ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); + V8ClassIndex::V8WrapperType wrapperType = V8DOMWrapper::domWrapperType(object); ASSERT(wrapperType != V8ClassIndex::NODE); - Collection* collection = V8Proxy::ToNativeObject<Collection>(wrapperType, object); + Collection* collection = V8DOMWrapper::convertToNativeObject<Collection>(wrapperType, object); String propertyName = toWebCoreString(name); return getV8Object<ItemType>(collection->namedItem(propertyName), implementationType); } @@ -87,8 +87,8 @@ namespace WebCore { // A template of named property accessor of HTMLSelectElement and HTMLFormElement. template<class Collection> static v8::Handle<v8::Value> nodeCollectionNamedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { - ASSERT(V8Proxy::MaybeDOMWrapper(info.Holder())); - ASSERT(V8Proxy::GetDOMWrapperType(info.Holder()) == V8ClassIndex::NODE); + ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); + ASSERT(V8DOMWrapper::domWrapperType(info.Holder()) == V8ClassIndex::NODE); v8::Handle<v8::Value> value = info.Holder()->GetRealNamedPropertyInPrototypeChain(name); if (!value.IsEmpty()) @@ -98,7 +98,7 @@ namespace WebCore { // properties. if (info.Holder()->HasRealNamedCallbackProperty(name)) return notHandledByInterceptor(); - Collection* collection = V8Proxy::DOMWrapperToNode<Collection>(info.Holder()); + Collection* collection = V8DOMWrapper::convertDOMWrapperToNode<Collection>(info.Holder()); String propertyName = toWebCoreString(name); void* implementation = collection->namedItem(propertyName); return getV8Object(implementation, info.Data()); @@ -109,10 +109,10 @@ namespace WebCore { v8::Local<v8::Value> implementationType) { // FIXME: Assert that object must be a collection type. - ASSERT(V8Proxy::MaybeDOMWrapper(object)); - V8ClassIndex::V8WrapperType wrapperType = V8Proxy::GetDOMWrapperType(object); + ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); + V8ClassIndex::V8WrapperType wrapperType = V8DOMWrapper::domWrapperType(object); ASSERT(wrapperType != V8ClassIndex::NODE); - Collection* collection = V8Proxy::ToNativeObject<Collection>(wrapperType, object); + Collection* collection = V8DOMWrapper::convertToNativeObject<Collection>(wrapperType, object); return getV8Object<ItemType>(collection->item(index), implementationType); } @@ -125,9 +125,9 @@ namespace WebCore { // A template of index interceptor of HTMLSelectElement and HTMLFormElement. template<class Collection> static v8::Handle<v8::Value> nodeCollectionIndexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) { - ASSERT(V8Proxy::MaybeDOMWrapper(info.Holder())); - ASSERT(V8Proxy::GetDOMWrapperType(info.Holder()) == V8ClassIndex::NODE); - Collection* collection = V8Proxy::DOMWrapperToNode<Collection>(info.Holder()); + ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); + ASSERT(V8DOMWrapper::domWrapperType(info.Holder()) == V8ClassIndex::NODE); + Collection* collection = V8DOMWrapper::convertDOMWrapperToNode<Collection>(info.Holder()); void* implementation = collection->item(index); return getV8Object(implementation, info.Data()); } @@ -135,9 +135,9 @@ namespace WebCore { // Get an array containing the names of indexed properties of HTMLSelectElement and HTMLFormElement. template<class Collection> static v8::Handle<v8::Array> nodeCollectionIndexedPropertyEnumerator(const v8::AccessorInfo& info) { - ASSERT(V8Proxy::MaybeDOMWrapper(info.Holder())); - ASSERT(V8Proxy::GetDOMWrapperType(info.Holder()) == V8ClassIndex::NODE); - Collection* collection = V8Proxy::DOMWrapperToNode<Collection>(info.Holder()); + ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); + ASSERT(V8DOMWrapper::domWrapperType(info.Holder()) == V8ClassIndex::NODE); + Collection* collection = V8DOMWrapper::convertDOMWrapperToNode<Collection>(info.Holder()); int length = collection->length(); v8::Handle<v8::Array> properties = v8::Array::New(length); for (int i = 0; i < length; ++i) { @@ -151,9 +151,9 @@ namespace WebCore { // Get an array containing the names of indexed properties in a collection. template<class Collection> static v8::Handle<v8::Array> collectionIndexedPropertyEnumerator(const v8::AccessorInfo& info) { - ASSERT(V8Proxy::MaybeDOMWrapper(info.Holder())); - V8ClassIndex::V8WrapperType wrapperType = V8Proxy::GetDOMWrapperType(info.Holder()); - Collection* collection = V8Proxy::ToNativeObject<Collection>(wrapperType, info.Holder()); + ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); + V8ClassIndex::V8WrapperType wrapperType = V8DOMWrapper::domWrapperType(info.Holder()); + Collection* collection = V8DOMWrapper::convertToNativeObject<Collection>(wrapperType, info.Holder()); int length = collection->length(); v8::Handle<v8::Array> properties = v8::Array::New(length); for (int i = 0; i < length; ++i) { @@ -169,9 +169,9 @@ namespace WebCore { template<class Collection> static v8::Handle<v8::Value> collectionStringOrNullIndexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) { // FIXME: assert that object must be a collection type - ASSERT(V8Proxy::MaybeDOMWrapper(info.Holder())); - V8ClassIndex::V8WrapperType wrapperType = V8Proxy::GetDOMWrapperType(info.Holder()); - Collection* collection = V8Proxy::ToNativeObject<Collection>(wrapperType, info.Holder()); + ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder())); + V8ClassIndex::V8WrapperType wrapperType = V8DOMWrapper::domWrapperType(info.Holder()); + Collection* collection = V8DOMWrapper::convertToNativeObject<Collection>(wrapperType, info.Holder()); String result = collection->item(index); return v8StringOrNull(result); } diff --git a/WebCore/bindings/v8/V8ConsoleMessage.cpp b/WebCore/bindings/v8/V8ConsoleMessage.cpp new file mode 100644 index 0000000..d9fe069 --- /dev/null +++ b/WebCore/bindings/v8/V8ConsoleMessage.cpp @@ -0,0 +1,128 @@ +/* + * 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: + * + * * 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. + */ + +#include "config.h" +#include "V8ConsoleMessage.h" + +#include "Console.h" +#include "DOMWindow.h" +#include "Frame.h" +#include "OwnPtr.h" +#include "Page.h" +#include "V8Binding.h" +#include "V8Proxy.h" + +namespace WebCore { + +Vector<V8ConsoleMessage>* V8ConsoleMessage::m_delayedMessages = 0; + +V8ConsoleMessage::V8ConsoleMessage(const String& string, const String& sourceID, unsigned lineNumber) + : m_string(string) + , m_sourceID(sourceID) + , m_lineNumber(lineNumber) +{ +} + +void V8ConsoleMessage::dispatchNow(Page* page) +{ + ASSERT(page); + + // Process any delayed messages to make sure that messages + // appear in the right order in the console. + processDelayed(); + + Console* console = page->mainFrame()->domWindow()->console(); + console->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, m_string, m_lineNumber, m_sourceID); +} + +void V8ConsoleMessage::dispatchLater() +{ + if (!m_delayedMessages) { + // Allocate a vector for the delayed messages. Will be + // deallocated when the delayed messages are processed + // in processDelayed(). + m_delayedMessages = new Vector<V8ConsoleMessage>(); + } + + m_delayedMessages->append(*this); +} + +void V8ConsoleMessage::processDelayed() +{ + if (!m_delayedMessages) + return; + + // Take ownership of the delayed vector to avoid re-entrancy issues. + OwnPtr<Vector<V8ConsoleMessage> > delayedMessages(m_delayedMessages); + m_delayedMessages = 0; + + // If we have a delayed vector it cannot be empty. + ASSERT(!delayedMessages->isEmpty()); + + // Add the delayed messages to the page of the active + // context. If that for some bizarre reason does not + // exist, we clear the list of delayed messages to avoid + // posting messages. We still deallocate the vector. + Frame* frame = V8Proxy::retrieveFrameForEnteredContext(); + if (!frame) + return; + Page* page = frame->page(); + if (!page) + return; + + // Iterate through all the delayed messages and add them + // to the console. + const int size = delayedMessages->size(); + for (int i = 0; i < size; ++i) + delayedMessages->at(i).dispatchNow(page); +} + +void V8ConsoleMessage::handler(v8::Handle<v8::Message> message, v8::Handle<v8::Value> data) +{ + // Use the frame where JavaScript is called from. + Frame* frame = V8Proxy::retrieveFrameForEnteredContext(); + if (!frame) + return; + Page* page = frame->page(); + if (!page) + return; + + v8::Handle<v8::String> errorMessageString = message->Get(); + ASSERT(!errorMessageString.IsEmpty()); + String errorMessage = toWebCoreString(errorMessageString); + + v8::Handle<v8::Value> resourceName = message->GetScriptResourceName(); + bool useURL = resourceName.IsEmpty() || !resourceName->IsString(); + String resourceNameString = useURL ? frame->document()->url() : toWebCoreString(resourceName); + V8ConsoleMessage consoleMessage(errorMessage, resourceNameString, message->GetLineNumber()); + consoleMessage.dispatchNow(page); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/V8ConsoleMessage.h b/WebCore/bindings/v8/V8ConsoleMessage.h new file mode 100644 index 0000000..a8f75ee --- /dev/null +++ b/WebCore/bindings/v8/V8ConsoleMessage.h @@ -0,0 +1,90 @@ +/* + * 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: + * + * * 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 V8ConsoleMessage_h +#define V8ConsoleMessage_h + +#include "PlatformString.h" +#include <v8.h> +#include <wtf/Vector.h> + +namespace WebCore { + + class Page; + + // V8ConsoleMessage encapsulates everything needed to + // log messages originating from JavaScript to the console. + class V8ConsoleMessage { + public: + V8ConsoleMessage(const String& string, const String& sourceID, unsigned lineNumber); + + // Add a message to the console. May end up calling JavaScript code + // indirectly through the inspector so only call this function when + // it is safe to do allocations. + void dispatchNow(Page*); + + // Add a message to the console but delay the reporting until it + // is safe to do so: Either when we leave JavaScript execution or + // when adding other console messages. The primary purpose of this + // method is to avoid calling into V8 to handle console messages + // when the VM is in a state that does not support GCs or allocations. + // Delayed messages are always reported in the page corresponding + // to the active context. + void dispatchLater(); + + // Process any delayed messages. May end up calling JavaScript code + // indirectly through the inspector so only call this function when + // it is safe to do allocations. + static void processDelayed(); + + // Convenience class for ensuring that delayed messages in the + // ConsoleMessageManager are processed quickly. + class Scope { + public: + Scope() { V8ConsoleMessage::processDelayed(); } + ~Scope() { V8ConsoleMessage::processDelayed(); } + }; + + // Callback from V8. + static void handler(v8::Handle<v8::Message>, v8::Handle<v8::Value> data); + + private: + const String m_string; + const String m_sourceID; + const unsigned m_lineNumber; + + // All delayed messages are stored in this vector. If the vector + // is 0, there are no delayed messages. + static Vector<V8ConsoleMessage>* m_delayedMessages; + }; + +} // namespace WebCore + +#endif // V8ConsoleMessage_h diff --git a/WebCore/bindings/v8/V8DOMMap.cpp b/WebCore/bindings/v8/V8DOMMap.cpp index 4645c02..2d6639f 100644 --- a/WebCore/bindings/v8/V8DOMMap.cpp +++ b/WebCore/bindings/v8/V8DOMMap.cpp @@ -31,19 +31,14 @@ #include "config.h" #include "V8DOMMap.h" +#include "DOMData.h" +#include "DOMDataStore.h" #include "DOMObjectsInclude.h" - -#include <v8.h> -#include <wtf/HashMap.h> -#include <wtf/MainThread.h> -#include <wtf/Noncopyable.h> -#include <wtf/StdLibExtras.h> -#include <wtf/Threading.h> -#include <wtf/ThreadSpecific.h> -#include <wtf/Vector.h> +#include "ScopedDOMDataStore.h" namespace WebCore { +#ifdef MANUAL_MERGE_REQUIRED // DOM binding algorithm: // // There are two kinds of DOM objects: @@ -289,291 +284,174 @@ template<typename T> static void handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMWrapperMapType mapType, V8ClassIndex::V8WrapperType objectType, T*); ThreadSpecificDOMData& getThreadSpecificDOMData() +#else // MANUAL_MERGE_REQUIRED +DOMDataStoreHandle::DOMDataStoreHandle() + : m_store(new ScopedDOMDataStore(DOMData::getCurrent())) +#endif // MANUAL_MERGE_REQUIRED { - if (WTF::isMainThread()) { - DEFINE_STATIC_LOCAL(MainThreadSpecificDOMData, mainThreadSpecificDOMData, ()); - return mainThreadSpecificDOMData; - } - return *threadSpecificDOMData; } -template <class KeyType> -void ThreadSpecificDOMData::InternalDOMWrapperMap<KeyType>::forget(KeyType* object) +DOMDataStoreHandle::~DOMDataStoreHandle() { - DOMWrapperMap<KeyType>::forget(object); - - ThreadSpecificDOMData::DelayedObjectMap& delayedObjectMap = getThreadSpecificDOMData().delayedObjectMap(); - delayedObjectMap.take(object); } DOMWrapperMap<Node>& getDOMNodeMap() { - return getThreadSpecificDOMData().domNodeMap(); + // Nodes only exist on the main thread. + return DOMData::getCurrentMainThread()->getStore().domNodeMap(); } DOMWrapperMap<void>& getDOMObjectMap() { - return getThreadSpecificDOMData().domObjectMap(); + return DOMData::getCurrent()->getStore().domObjectMap(); } DOMWrapperMap<void>& getActiveDOMObjectMap() { - return getThreadSpecificDOMData().activeDomObjectMap(); + return DOMData::getCurrent()->getStore().activeDomObjectMap(); } #if ENABLE(SVG) -DOMWrapperMap<SVGElementInstance>& getDOMSVGElementInstanceMap() -{ - return getThreadSpecificDOMData().domSvgElementInstanceMap(); -} -static void weakSVGElementInstanceCallback(v8::Persistent<v8::Value> v8Object, void* domObject) +DOMWrapperMap<SVGElementInstance>& getDOMSVGElementInstanceMap() { - SVGElementInstance* instance = static_cast<SVGElementInstance*>(domObject); - - ThreadSpecificDOMData::InternalDOMWrapperMap<SVGElementInstance>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<SVGElementInstance>&>(getDOMSVGElementInstanceMap()); - if (map.contains(instance)) { - instance->deref(); - map.forgetOnly(instance); - } else - handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMSVGElementInstanceMap, V8ClassIndex::SVGELEMENTINSTANCE, instance); + return DOMData::getCurrent()->getStore().domSvgElementInstanceMap(); } // Map of SVG objects with contexts to V8 objects DOMWrapperMap<void>& getDOMSVGObjectWithContextMap() { - return getThreadSpecificDOMData().domSvgObjectWithContextMap(); + return DOMData::getCurrent()->getStore().domSvgObjectWithContextMap(); } -static void weakSVGObjectWithContextCallback(v8::Persistent<v8::Value> v8Object, void* domObject) -{ - v8::HandleScope scope; - ASSERT(v8Object->IsObject()); - - V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(v8Object)); - - ThreadSpecificDOMData::InternalDOMWrapperMap<void>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<void>&>(getDOMSVGObjectWithContextMap()); - if (map.contains(domObject)) { - // The forget function removes object from the map and disposes the wrapper. - map.forgetOnly(domObject); - - switch (type) { -#define MakeCase(type, name) \ - case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break; - SVG_OBJECT_TYPES(MakeCase) -#undef MakeCase -#define MakeCase(type, name) \ - case V8ClassIndex::type: \ - static_cast<V8SVGPODTypeWrapper<name>*>(domObject)->deref(); break; - SVG_POD_NATIVE_TYPES(MakeCase) -#undef MakeCase - default: - ASSERT_NOT_REACHED(); - break; - } - } else - handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMSVGObjectWithContextMap, type, domObject); -} #endif // ENABLE(SVG) -// Called when the dead object is not in GC thread's map. Go through all thread maps to find the one containing it. -// Then clear the JS reference and push the DOM object into the delayed queue for it to be deref-ed at later time from the owning thread. -// * This is called when the GC thread is not the owning thread. -// * This can be called on any thread that has GC running. -// * Only one V8 instance is running at a time due to V8::Locker. So we don't need to worry about concurrency. -template<typename T> -static void handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMWrapperMapType mapType, V8ClassIndex::V8WrapperType objectType, T* object) +static void removeAllDOMObjectsInCurrentThreadHelper() { - WTF::MutexLocker locker(domDataListMutex()); - DOMDataList& list = domDataList(); - for (size_t i = 0; i < list.size(); ++i) { - ThreadSpecificDOMData* threadData = list[i]; + v8::HandleScope scope; - ThreadSpecificDOMData::InternalDOMWrapperMap<T>* domMap = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<T>*>(threadData->getDOMWrapperMap(mapType)); - if (domMap->contains(object)) { - // Clear the JS reference. - domMap->forgetOnly(object); + // Deref all objects in the delayed queue. + DOMData::getCurrent()->derefDelayedObjects(); - // Push into the delayed queue. - threadData->delayedObjectMap().set(object, objectType); + // The DOM objects with the following types only exist on the main thread. + if (WTF::isMainThread()) { + // Remove all DOM nodes. + DOMData::removeObjectsFromWrapperMap<Node>(getDOMNodeMap()); - // Post a task to the owning thread in order to process the delayed queue. - // FIXME: For now, we can only post to main thread due to WTF task posting limitation. We will fix this when we work on nested worker. - if (!threadData->delayedProcessingScheduled()) { - threadData->setDelayedProcessingScheduled(true); - if (threadData->isMainThread()) - WTF::callOnMainThread(&derefDelayedObjectsInCurrentThread, 0); - } +#if ENABLE(SVG) + // Remove all SVG element instances in the wrapper map. + DOMData::removeObjectsFromWrapperMap<SVGElementInstance>(getDOMSVGElementInstanceMap()); - break; - } + // Remove all SVG objects with context in the wrapper map. + DOMData::removeObjectsFromWrapperMap<void>(getDOMSVGObjectWithContextMap()); +#endif } -} - -// Called when the object is near death (not reachable from JS roots). -// It is time to remove the entry from the table and dispose the handle. -static void weakDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject) -{ - v8::HandleScope scope; - ASSERT(v8Object->IsObject()); - - V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(v8Object)); - ThreadSpecificDOMData::InternalDOMWrapperMap<void>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<void>&>(getDOMObjectMap()); - if (map.contains(domObject)) { - // The forget function removes object from the map and disposes the wrapper. - map.forgetOnly(domObject); + // Remove all DOM objects in the wrapper map. + DOMData::removeObjectsFromWrapperMap<void>(getDOMObjectMap()); - switch (type) { -#define MakeCase(type, name) \ - case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break; - DOM_OBJECT_TYPES(MakeCase) -#undef MakeCase - default: - ASSERT_NOT_REACHED(); - break; - } - } else - handleWeakObjectInOwningThread(ThreadSpecificDOMData::DOMObjectMap, type, domObject); + // Remove all active DOM objects in the wrapper map. + DOMData::removeObjectsFromWrapperMap<void>(getActiveDOMObjectMap()); } -void weakActiveDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject) +void removeAllDOMObjectsInCurrentThread() { - v8::HandleScope scope; - ASSERT(v8Object->IsObject()); - - V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(v8Object)); - - ThreadSpecificDOMData::InternalDOMWrapperMap<void>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<void>&>(getActiveDOMObjectMap()); - if (map.contains(domObject)) { - // The forget function removes object from the map and disposes the wrapper. - map.forgetOnly(domObject); - - switch (type) { -#define MakeCase(type, name) \ - case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break; - ACTIVE_DOM_OBJECT_TYPES(MakeCase) -#undef MakeCase - default: - ASSERT_NOT_REACHED(); - break; - } + // Use the locker only if it has already been invoked before, as by worker thread. + if (v8::Locker::IsActive()) { + v8::Locker locker; + removeAllDOMObjectsInCurrentThreadHelper(); } else - handleWeakObjectInOwningThread(ThreadSpecificDOMData::ActiveDOMObjectMap, type, domObject); + removeAllDOMObjectsInCurrentThreadHelper(); } -static void weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* domObject) + +void visitDOMNodesInCurrentThread(DOMWrapperMap<Node>::Visitor* visitor) { - Node* node = static_cast<Node*>(domObject); + v8::HandleScope scope; - ThreadSpecificDOMData::InternalDOMWrapperMap<Node>& map = static_cast<ThreadSpecificDOMData::InternalDOMWrapperMap<Node>&>(getDOMNodeMap()); - if (map.contains(node)) { - map.forgetOnly(node); - node->deref(); - } else - handleWeakObjectInOwningThread<Node>(ThreadSpecificDOMData::DOMNodeMap, V8ClassIndex::NODE, node); + WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); + DOMDataList& list = DOMDataStore::allStores(); + for (size_t i = 0; i < list.size(); ++i) { + DOMDataStore* store = list[i]; + if (!store->domData()->owningThread() == WTF::currentThread()) + continue; + + HashMap<Node*, v8::Object*>& map = store->domNodeMap().impl(); + for (HashMap<Node*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it) + visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second)); + } } -static void derefObject(V8ClassIndex::V8WrapperType type, void* domObject) +void visitDOMObjectsInCurrentThread(DOMWrapperMap<void>::Visitor* visitor) { - switch (type) { - case V8ClassIndex::NODE: - static_cast<Node*>(domObject)->deref(); - break; - -#define MakeCase(type, name) \ - case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break; - DOM_OBJECT_TYPES(MakeCase) // This includes both active and non-active. -#undef MakeCase + v8::HandleScope scope; -#if ENABLE(SVG) -#define MakeCase(type, name) \ - case V8ClassIndex::type: static_cast<name*>(domObject)->deref(); break; - SVG_OBJECT_TYPES(MakeCase) // This also includes SVGElementInstance. -#undef MakeCase - -#define MakeCase(type, name) \ - case V8ClassIndex::type: \ - static_cast<V8SVGPODTypeWrapper<name>*>(domObject)->deref(); break; - SVG_POD_NATIVE_TYPES(MakeCase) -#undef MakeCase -#endif + WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); + DOMDataList& list = DOMDataStore::allStores(); + for (size_t i = 0; i < list.size(); ++i) { + DOMDataStore* store = list[i]; + if (!store->domData()->owningThread() == WTF::currentThread()) + continue; - default: - ASSERT_NOT_REACHED(); - break; + HashMap<void*, v8::Object*> & map = store->domObjectMap().impl(); + for (HashMap<void*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it) + visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second)); } } -static void derefDelayedObjects() +void visitActiveDOMObjectsInCurrentThread(DOMWrapperMap<void>::Visitor* visitor) { - WTF::MutexLocker locker(domDataListMutex()); + v8::HandleScope scope; - getThreadSpecificDOMData().setDelayedProcessingScheduled(false); + WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); + DOMDataList& list = DOMDataStore::allStores(); + for (size_t i = 0; i < list.size(); ++i) { + DOMDataStore* store = list[i]; + if (!store->domData()->owningThread() == WTF::currentThread()) + continue; - ThreadSpecificDOMData::DelayedObjectMap& delayedObjectMap = getThreadSpecificDOMData().delayedObjectMap(); - for (ThreadSpecificDOMData::DelayedObjectMap::iterator iter(delayedObjectMap.begin()); iter != delayedObjectMap.end(); ++iter) { - derefObject(iter->second, iter->first); + HashMap<void*, v8::Object*>& map = store->activeDomObjectMap().impl(); + for (HashMap<void*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it) + visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second)); } - delayedObjectMap.clear(); } -static void derefDelayedObjectsInCurrentThread(void*) -{ - derefDelayedObjects(); -} +#if ENABLE(SVG) -template<typename T> -static void removeObjectsFromWrapperMap(DOMWrapperMap<T>& domMap) +void visitDOMSVGElementInstancesInCurrentThread(DOMWrapperMap<SVGElementInstance>::Visitor* visitor) { - for (typename WTF::HashMap<T*, v8::Object*>::iterator iter(domMap.impl().begin()); iter != domMap.impl().end(); ++iter) { - T* domObject = static_cast<T*>(iter->first); - v8::Persistent<v8::Object> v8Object(iter->second); - - V8ClassIndex::V8WrapperType type = V8Proxy::GetDOMWrapperType(v8::Handle<v8::Object>::Cast(v8Object)); + v8::HandleScope scope; - // Deref the DOM object. - derefObject(type, domObject); + WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); + DOMDataList& list = DOMDataStore::allStores(); + for (size_t i = 0; i < list.size(); ++i) { + DOMDataStore* store = list[i]; + if (!store->domData()->owningThread() == WTF::currentThread()) + continue; - // Clear the JS wrapper. - v8Object.Dispose(); + HashMap<SVGElementInstance*, v8::Object*> & map = store->domSvgElementInstanceMap().impl(); + for (HashMap<SVGElementInstance*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it) + visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second)); } - domMap.impl().clear(); } -static void removeAllDOMObjectsInCurrentThreadHelper() +void visitSVGObjectsInCurrentThread(DOMWrapperMap<void>::Visitor* visitor) { v8::HandleScope scope; - // Deref all objects in the delayed queue. - derefDelayedObjects(); - - // Remove all DOM nodes. - removeObjectsFromWrapperMap<Node>(getDOMNodeMap()); - - // Remove all DOM objects in the wrapper map. - removeObjectsFromWrapperMap<void>(getDOMObjectMap()); - - // Remove all active DOM objects in the wrapper map. - removeObjectsFromWrapperMap<void>(getActiveDOMObjectMap()); - -#if ENABLE(SVG) - // Remove all SVG element instances in the wrapper map. - removeObjectsFromWrapperMap<SVGElementInstance>(getDOMSVGElementInstanceMap()); + WTF::MutexLocker locker(DOMDataStore::allStoresMutex()); + DOMDataList& list = DOMDataStore::allStores(); + for (size_t i = 0; i < list.size(); ++i) { + DOMDataStore* store = list[i]; + if (!store->domData()->owningThread() == WTF::currentThread()) + continue; - // Remove all SVG objects with context in the wrapper map. - removeObjectsFromWrapperMap<void>(getDOMSVGObjectWithContextMap()); -#endif + HashMap<void*, v8::Object*>& map = store->domSvgObjectWithContextMap().impl(); + for (HashMap<void*, v8::Object*>::iterator it = map.begin(); it != map.end(); ++it) + visitor->visitDOMWrapper(it->first, v8::Persistent<v8::Object>(it->second)); + } } -void removeAllDOMObjectsInCurrentThread() -{ - // Use the locker only if it has already been invoked before, as by worker thread. - if (v8::Locker::IsActive()) { - v8::Locker locker; - removeAllDOMObjectsInCurrentThreadHelper(); - } else - removeAllDOMObjectsInCurrentThreadHelper(); -} +#endif } // namespace WebCore diff --git a/WebCore/bindings/v8/V8DOMMap.h b/WebCore/bindings/v8/V8DOMMap.h index 47fa765..eac39d2 100644 --- a/WebCore/bindings/v8/V8DOMMap.h +++ b/WebCore/bindings/v8/V8DOMMap.h @@ -32,6 +32,7 @@ #define V8DOMMap_h #include <wtf/HashMap.h> +#include <wtf/OwnPtr.h> #include <v8.h> namespace WebCore { @@ -48,10 +49,18 @@ namespace WebCore { WeakReferenceMap(v8::WeakReferenceCallback callback) : m_weakReferenceCallback(callback) { } virtual ~WeakReferenceMap() { +#ifdef MANUAL_MERGE_REQUIRED #ifndef NDEBUG +#else // MANUAL_MERGE_REQUIRED + #ifndef NDEBUG +#endif // MANUAL_MERGE_REQUIRED if (m_map.size() > 0) fprintf(stderr, "Leak %d JS wrappers.\n", m_map.size()); +#ifdef MANUAL_MERGE_REQUIRED #endif +#else // MANUAL_MERGE_REQUIRED + #endif +#endif // MANUAL_MERGE_REQUIRED } // Get the JS wrapper object of an object. @@ -89,23 +98,42 @@ namespace WebCore { v8::WeakReferenceCallback m_weakReferenceCallback; }; - template <class KeyType> class DOMWrapperMap : public WeakReferenceMap<KeyType, v8::Object> { public: DOMWrapperMap(v8::WeakReferenceCallback callback) : WeakReferenceMap<KeyType, v8::Object>(callback) { } + + class Visitor { + public: + virtual void visitDOMWrapper(KeyType* key, v8::Persistent<v8::Object> object) = 0; + }; }; - // Callback when JS wrapper of active DOM object is dead. - void weakActiveDOMObjectCallback(v8::Persistent<v8::Value> v8Object, void* domObject); + // An opaque class that represents a set of DOM wrappers. + class DOMDataStore; + + // A utility class to manage the lifetime of set of DOM wrappers. + class DOMDataStoreHandle { + public: + DOMDataStoreHandle(); + ~DOMDataStoreHandle(); + + DOMDataStore* getStore() const { return m_store.get(); } + + private: + OwnPtr<DOMDataStore> m_store; + }; // A map from DOM node to its JS wrapper. DOMWrapperMap<Node>& getDOMNodeMap(); + void visitDOMNodesInCurrentThread(DOMWrapperMap<Node>::Visitor*); // A map from a DOM object (non-node) to its JS wrapper. This map does not contain the DOM objects which can have pending activity (active dom objects). DOMWrapperMap<void>& getDOMObjectMap(); + void visitDOMObjectsInCurrentThread(DOMWrapperMap<void>::Visitor*); // A map from a DOM object to its JS wrapper for DOM objects which can have pending activity. DOMWrapperMap<void>& getActiveDOMObjectMap(); + void visitActiveDOMObjectsInCurrentThread(DOMWrapperMap<void>::Visitor*); // This should be called to remove all DOM objects associated with the current thread when it is tearing down. void removeAllDOMObjectsInCurrentThread(); @@ -113,9 +141,11 @@ namespace WebCore { #if ENABLE(SVG) // A map for SVGElementInstances to its JS wrapper. DOMWrapperMap<SVGElementInstance>& getDOMSVGElementInstanceMap(); + void visitSVGElementInstancesInCurrentThread(DOMWrapperMap<SVGElementInstance>::Visitor*); // Map of SVG objects with contexts to V8 objects. DOMWrapperMap<void>& getDOMSVGObjectWithContextMap(); + void visitDOMSVGObjectsInCurrentThread(DOMWrapperMap<void>::Visitor*); #endif } // namespace WebCore diff --git a/WebCore/bindings/v8/V8DOMWrapper.cpp b/WebCore/bindings/v8/V8DOMWrapper.cpp new file mode 100644 index 0000000..33d1147 --- /dev/null +++ b/WebCore/bindings/v8/V8DOMWrapper.cpp @@ -0,0 +1,1465 @@ +/* + * 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: + * + * * 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. + */ + +#include "config.h" +#include "V8DOMWrapper.h" + +#include "ChromiumBridge.h" +#include "CSSMutableStyleDeclaration.h" +#include "DOMObjectsInclude.h" +#include "DocumentLoader.h" +#include "FrameLoaderClient.h" +#include "ScriptController.h" +#include "V8Binding.h" +#include "V8Collection.h" +#include "V8CustomBinding.h" +#include "V8DOMMap.h" +#include "V8DOMWindow.h" +#include "V8Index.h" +#include "V8IsolatedWorld.h" +#include "WorkerContextExecutionProxy.h" + +#include <algorithm> +#include <utility> +#include <v8.h> +#include <v8-debug.h> +#include <wtf/Assertions.h> +#include <wtf/OwnArrayPtr.h> +#include <wtf/StdLibExtras.h> +#include <wtf/UnusedParam.h> + +namespace WebCore { + +typedef HashMap<Node*, v8::Object*> DOMNodeMap; +typedef HashMap<void*, v8::Object*> DOMObjectMap; + +// Get the string 'toString'. +static v8::Persistent<v8::String> GetToStringName() +{ + DEFINE_STATIC_LOCAL(v8::Persistent<v8::String>, value, ()); + if (value.IsEmpty()) + value = v8::Persistent<v8::String>::New(v8::String::New("toString")); + return value; +} + +static v8::Handle<v8::Value> ConstructorToString(const v8::Arguments& args) +{ + // The DOM constructors' toString functions grab the current toString + // for Functions by taking the toString function of itself and then + // calling it with the constructor as its receiver. This means that + // changes to the Function prototype chain or toString function are + // reflected when printing DOM constructors. The only wart is that + // changes to a DOM constructor's toString's toString will cause the + // toString of the DOM constructor itself to change. This is extremely + // obscure and unlikely to be a problem. + v8::Handle<v8::Value> value = args.Callee()->Get(GetToStringName()); + if (!value->IsFunction()) + return v8::String::New(""); + return v8::Handle<v8::Function>::Cast(value)->Call(args.This(), 0, 0); +} + +#if ENABLE(SVG) +v8::Handle<v8::Value> V8DOMWrapper::convertSVGElementInstanceToV8Object(SVGElementInstance* instance) +{ + if (!instance) + return v8::Null(); + + v8::Handle<v8::Object> existingInstance = getDOMSVGElementInstanceMap().get(instance); + if (!existingInstance.IsEmpty()) + return existingInstance; + + instance->ref(); + + // Instantiate the V8 object and remember it + v8::Handle<v8::Object> result = instantiateV8Object(V8ClassIndex::SVGELEMENTINSTANCE, V8ClassIndex::SVGELEMENTINSTANCE, instance); + if (!result.IsEmpty()) { + // Only update the DOM SVG element map if the result is non-empty. + getDOMSVGElementInstanceMap().set(instance, v8::Persistent<v8::Object>::New(result)); + } + return result; +} + +v8::Handle<v8::Value> V8DOMWrapper::convertSVGObjectWithContextToV8Object(V8ClassIndex::V8WrapperType type, void* object) +{ + if (!object) + return v8::Null(); + + v8::Persistent<v8::Object> result = getDOMSVGObjectWithContextMap().get(object); + if (!result.IsEmpty()) + return result; + + // Special case: SVGPathSegs need to be downcast to their real type + if (type == V8ClassIndex::SVGPATHSEG) + type = V8Custom::DowncastSVGPathSeg(object); + + v8::Local<v8::Object> v8Object = instantiateV8Object(type, type, object); + if (!v8Object.IsEmpty()) { + result = v8::Persistent<v8::Object>::New(v8Object); + switch (type) { +#define MAKE_CASE(TYPE, NAME) \ + case V8ClassIndex::TYPE: static_cast<NAME*>(object)->ref(); break; + SVG_OBJECT_TYPES(MAKE_CASE) +#undef MAKE_CASE +#define MAKE_CASE(TYPE, NAME) \ + case V8ClassIndex::TYPE: \ + static_cast<V8SVGPODTypeWrapper<NAME>*>(object)->ref(); break; + SVG_POD_NATIVE_TYPES(MAKE_CASE) +#undef MAKE_CASE + default: + ASSERT_NOT_REACHED(); + } + getDOMSVGObjectWithContextMap().set(object, result); + } + + return result; +} + +#endif + +bool V8DOMWrapper::domObjectHasJSWrapper(void* object) +{ + return getDOMObjectMap().contains(object) || getActiveDOMObjectMap().contains(object); +} + +// The caller must have increased obj's ref count. +void V8DOMWrapper::setJSWrapperForDOMObject(void* object, v8::Persistent<v8::Object> wrapper) +{ + ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper)); +#ifndef NDEBUG + V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper); + switch (type) { +#define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: + ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) + ASSERT_NOT_REACHED(); +#undef MAKE_CASE + default: + break; + } +#endif + getDOMObjectMap().set(object, wrapper); +} + +// The caller must have increased obj's ref count. +void V8DOMWrapper::setJSWrapperForActiveDOMObject(void* object, v8::Persistent<v8::Object> wrapper) +{ + ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper)); +#ifndef NDEBUG + V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper); + switch (type) { +#define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: break; + ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) + default: + ASSERT_NOT_REACHED(); +#undef MAKE_CASE + } +#endif + getActiveDOMObjectMap().set(object, wrapper); +} + +// The caller must have increased node's ref count. +void V8DOMWrapper::setJSWrapperForDOMNode(Node* node, v8::Persistent<v8::Object> wrapper) +{ + ASSERT(V8DOMWrapper::maybeDOMWrapper(wrapper)); + getDOMNodeMap().set(node, wrapper); +} + +v8::Persistent<v8::FunctionTemplate> V8DOMWrapper::getTemplate(V8ClassIndex::V8WrapperType type) +{ + v8::Persistent<v8::FunctionTemplate>* cacheCell = V8ClassIndex::GetCache(type); + if (!cacheCell->IsEmpty()) + return *cacheCell; + + // Not in the cache. + FunctionTemplateFactory factory = V8ClassIndex::GetFactory(type); + v8::Persistent<v8::FunctionTemplate> descriptor = factory(); + // DOM constructors are functions and should print themselves as such. + // However, we will later replace their prototypes with Object + // prototypes so we need to explicitly override toString on the + // instance itself. If we later make DOM constructors full objects + // we can give them class names instead and Object.prototype.toString + // will work so we can remove this code. + DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, toStringTemplate, ()); + if (toStringTemplate.IsEmpty()) + toStringTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(ConstructorToString)); + descriptor->Set(GetToStringName(), toStringTemplate); + switch (type) { + case V8ClassIndex::CSSSTYLEDECLARATION: + // The named property handler for style declarations has a + // setter. Therefore, the interceptor has to be on the object + // itself and not on the prototype object. + descriptor->InstanceTemplate()->SetNamedPropertyHandler( USE_NAMED_PROPERTY_GETTER(CSSStyleDeclaration), USE_NAMED_PROPERTY_SETTER(CSSStyleDeclaration)); + setCollectionStringOrNullIndexedGetter<CSSStyleDeclaration>(descriptor); + break; + case V8ClassIndex::CSSRULELIST: + setCollectionIndexedGetter<CSSRuleList, CSSRule>(descriptor, V8ClassIndex::CSSRULE); + break; + case V8ClassIndex::CSSVALUELIST: + setCollectionIndexedGetter<CSSValueList, CSSValue>(descriptor, V8ClassIndex::CSSVALUE); + break; + case V8ClassIndex::CSSVARIABLESDECLARATION: + setCollectionStringOrNullIndexedGetter<CSSVariablesDeclaration>(descriptor); + break; + case V8ClassIndex::WEBKITCSSTRANSFORMVALUE: + setCollectionIndexedGetter<WebKitCSSTransformValue, CSSValue>(descriptor, V8ClassIndex::CSSVALUE); + break; + case V8ClassIndex::HTMLALLCOLLECTION: + descriptor->InstanceTemplate()->MarkAsUndetectable(); // fall through + case V8ClassIndex::HTMLCOLLECTION: + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLCollection)); + descriptor->InstanceTemplate()->SetCallAsFunctionHandler(USE_CALLBACK(HTMLCollectionCallAsFunction)); + setCollectionIndexedGetter<HTMLCollection, Node>(descriptor, V8ClassIndex::NODE); + break; + case V8ClassIndex::HTMLOPTIONSCOLLECTION: + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLCollection)); + descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(HTMLOptionsCollection), USE_INDEXED_PROPERTY_SETTER(HTMLOptionsCollection)); + descriptor->InstanceTemplate()->SetCallAsFunctionHandler(USE_CALLBACK(HTMLCollectionCallAsFunction)); + break; + case V8ClassIndex::HTMLSELECTELEMENT: + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLSelectElementCollection)); + descriptor->InstanceTemplate()->SetIndexedPropertyHandler(nodeCollectionIndexedPropertyGetter<HTMLSelectElement>, USE_INDEXED_PROPERTY_SETTER(HTMLSelectElementCollection), + 0, 0, nodeCollectionIndexedPropertyEnumerator<HTMLSelectElement>, v8::Integer::New(V8ClassIndex::NODE)); + break; + case V8ClassIndex::HTMLDOCUMENT: { + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLDocument), 0, 0, USE_NAMED_PROPERTY_DELETER(HTMLDocument)); + + // We add an extra internal field to all Document wrappers for + // storing a per document DOMImplementation wrapper. + // + // Additionally, we add two extra internal fields for + // HTMLDocuments to implement temporary shadowing of + // document.all. One field holds an object that is used as a + // marker. The other field holds the marker object if + // document.all is not shadowed and some other value if + // document.all is shadowed. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kNodeMinimumInternalFieldCount); + instanceTemplate->SetInternalFieldCount(V8Custom::kHTMLDocumentInternalFieldCount); + break; + } +#if ENABLE(SVG) + case V8ClassIndex::SVGDOCUMENT: // fall through +#endif + case V8ClassIndex::DOCUMENT: { + // We add an extra internal field to all Document wrappers for + // storing a per document DOMImplementation wrapper. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kNodeMinimumInternalFieldCount); + instanceTemplate->SetInternalFieldCount( V8Custom::kDocumentMinimumInternalFieldCount); + break; + } + case V8ClassIndex::HTMLAPPLETELEMENT: // fall through + case V8ClassIndex::HTMLEMBEDELEMENT: // fall through + case V8ClassIndex::HTMLOBJECTELEMENT: + // HTMLAppletElement, HTMLEmbedElement and HTMLObjectElement are + // inherited from HTMLPlugInElement, and they share the same property + // handling code. + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLPlugInElement), USE_NAMED_PROPERTY_SETTER(HTMLPlugInElement)); + descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(HTMLPlugInElement), USE_INDEXED_PROPERTY_SETTER(HTMLPlugInElement)); + descriptor->InstanceTemplate()->SetCallAsFunctionHandler(USE_CALLBACK(HTMLPlugInElement)); + break; + case V8ClassIndex::HTMLFRAMESETELEMENT: + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLFrameSetElement)); + break; + case V8ClassIndex::HTMLFORMELEMENT: + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(HTMLFormElement)); + descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(HTMLFormElement), 0, 0, 0, nodeCollectionIndexedPropertyEnumerator<HTMLFormElement>, v8::Integer::New(V8ClassIndex::NODE)); + break; + case V8ClassIndex::STYLESHEET: // fall through + case V8ClassIndex::CSSSTYLESHEET: { + // We add an extra internal field to hold a reference to + // the owner node. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kDefaultWrapperInternalFieldCount); + instanceTemplate->SetInternalFieldCount(V8Custom::kStyleSheetInternalFieldCount); + break; + } + case V8ClassIndex::MEDIALIST: + setCollectionStringOrNullIndexedGetter<MediaList>(descriptor); + break; + case V8ClassIndex::MIMETYPEARRAY: + setCollectionIndexedAndNamedGetters<MimeTypeArray, MimeType>(descriptor, V8ClassIndex::MIMETYPE); + break; + case V8ClassIndex::NAMEDNODEMAP: + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(NamedNodeMap)); + descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(NamedNodeMap), 0, 0, 0, collectionIndexedPropertyEnumerator<NamedNodeMap>, v8::Integer::New(V8ClassIndex::NODE)); + break; +#if ENABLE(DOM_STORAGE) + case V8ClassIndex::STORAGE: + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(Storage), USE_NAMED_PROPERTY_SETTER(Storage), 0, USE_NAMED_PROPERTY_DELETER(Storage), V8Custom::v8StorageNamedPropertyEnumerator); + descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(Storage), USE_INDEXED_PROPERTY_SETTER(Storage), 0, USE_INDEXED_PROPERTY_DELETER(Storage)); + break; +#endif + case V8ClassIndex::NODELIST: + setCollectionIndexedGetter<NodeList, Node>(descriptor, V8ClassIndex::NODE); + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(NodeList)); + break; + case V8ClassIndex::PLUGIN: + setCollectionIndexedAndNamedGetters<Plugin, MimeType>(descriptor, V8ClassIndex::MIMETYPE); + break; + case V8ClassIndex::PLUGINARRAY: + setCollectionIndexedAndNamedGetters<PluginArray, Plugin>(descriptor, V8ClassIndex::PLUGIN); + break; + case V8ClassIndex::STYLESHEETLIST: + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(StyleSheetList)); + setCollectionIndexedGetter<StyleSheetList, StyleSheet>(descriptor, V8ClassIndex::STYLESHEET); + break; + case V8ClassIndex::DOMWINDOW: { + v8::Local<v8::Signature> defaultSignature = v8::Signature::New(descriptor); + + descriptor->PrototypeTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(DOMWindow)); + descriptor->PrototypeTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(DOMWindow)); + + descriptor->SetHiddenPrototype(true); + + // Reserve spaces for references to location, history and + // navigator objects. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + instanceTemplate->SetInternalFieldCount(V8Custom::kDOMWindowInternalFieldCount); + + // Set access check callbacks, but turned off initially. + // When a context is detached from a frame, turn on the access check. + // Turning on checks also invalidates inline caches of the object. + instanceTemplate->SetAccessCheckCallbacks(V8Custom::v8DOMWindowNamedSecurityCheck, V8Custom::v8DOMWindowIndexedSecurityCheck, v8::Integer::New(V8ClassIndex::DOMWINDOW), false); + break; + } + case V8ClassIndex::LOCATION: { + // For security reasons, these functions are on the instance + // instead of on the prototype object to insure that they cannot + // be overwritten. + v8::Local<v8::ObjectTemplate> instance = descriptor->InstanceTemplate(); + instance->SetAccessor(v8::String::New("reload"), V8Custom::v8LocationReloadAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly)); + instance->SetAccessor(v8::String::New("replace"), V8Custom::v8LocationReplaceAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly)); + instance->SetAccessor(v8::String::New("assign"), V8Custom::v8LocationAssignAccessorGetter, 0, v8::Handle<v8::Value>(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly)); + break; + } + case V8ClassIndex::HISTORY: + break; + + case V8ClassIndex::MESSAGECHANNEL: { + // Reserve two more internal fields for referencing the port1 + // and port2 wrappers. This ensures that the port wrappers are + // kept alive when the channel wrapper is. + descriptor->SetCallHandler(USE_CALLBACK(MessageChannelConstructor)); + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + instanceTemplate->SetInternalFieldCount(V8Custom::kMessageChannelInternalFieldCount); + break; + } + + case V8ClassIndex::MESSAGEPORT: { + // Reserve one more internal field for keeping event listeners. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + instanceTemplate->SetInternalFieldCount(V8Custom::kMessagePortInternalFieldCount); + break; + } + +#if ENABLE(WORKERS) + case V8ClassIndex::ABSTRACTWORKER: { + // Reserve one more internal field for keeping event listeners. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + instanceTemplate->SetInternalFieldCount(V8Custom::kAbstractWorkerInternalFieldCount); + break; + } + + case V8ClassIndex::DEDICATEDWORKERCONTEXT: { + // Reserve internal fields for keeping event listeners. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kDefaultWrapperInternalFieldCount); + instanceTemplate->SetInternalFieldCount(V8Custom::kDedicatedWorkerContextInternalFieldCount); + break; + } + + case V8ClassIndex::WORKER: { + // Reserve one more internal field for keeping event listeners. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + instanceTemplate->SetInternalFieldCount(V8Custom::kWorkerInternalFieldCount); + descriptor->SetCallHandler(USE_CALLBACK(WorkerConstructor)); + break; + } + + case V8ClassIndex::WORKERCONTEXT: { + // Reserve one more internal field for keeping event listeners. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + ASSERT(instanceTemplate->InternalFieldCount() == V8Custom::kDefaultWrapperInternalFieldCount); + instanceTemplate->SetInternalFieldCount(V8Custom::kWorkerContextMinimumInternalFieldCount); + break; + } + +#endif // WORKERS + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + case V8ClassIndex::DOMAPPLICATIONCACHE: { + // Reserve one more internal field for keeping event listeners. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + instanceTemplate->SetInternalFieldCount(V8Custom::kDOMApplicationCacheFieldCount); + break; + } +#endif + + // The following objects are created from JavaScript. + case V8ClassIndex::DOMPARSER: + descriptor->SetCallHandler(USE_CALLBACK(DOMParserConstructor)); + break; +#if ENABLE(VIDEO) + case V8ClassIndex::HTMLAUDIOELEMENT: + descriptor->SetCallHandler(USE_CALLBACK(HTMLAudioElementConstructor)); + break; +#endif + case V8ClassIndex::HTMLIMAGEELEMENT: + descriptor->SetCallHandler(USE_CALLBACK(HTMLImageElementConstructor)); + break; + case V8ClassIndex::HTMLOPTIONELEMENT: + descriptor->SetCallHandler(USE_CALLBACK(HTMLOptionElementConstructor)); + break; + case V8ClassIndex::WEBKITCSSMATRIX: + descriptor->SetCallHandler(USE_CALLBACK(WebKitCSSMatrixConstructor)); + break; + case V8ClassIndex::WEBKITPOINT: + descriptor->SetCallHandler(USE_CALLBACK(WebKitPointConstructor)); + break; + case V8ClassIndex::XMLSERIALIZER: + descriptor->SetCallHandler(USE_CALLBACK(XMLSerializerConstructor)); + break; + case V8ClassIndex::XMLHTTPREQUEST: { + // Reserve one more internal field for keeping event listeners. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + instanceTemplate->SetInternalFieldCount(V8Custom::kXMLHttpRequestInternalFieldCount); + descriptor->SetCallHandler(USE_CALLBACK(XMLHttpRequestConstructor)); + break; + } + case V8ClassIndex::XMLHTTPREQUESTUPLOAD: { + // Reserve one more internal field for keeping event listeners. + v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate(); + instanceTemplate->SetInternalFieldCount(V8Custom::kXMLHttpRequestInternalFieldCount); + break; + } + case V8ClassIndex::XPATHEVALUATOR: + descriptor->SetCallHandler(USE_CALLBACK(XPathEvaluatorConstructor)); + break; + case V8ClassIndex::XSLTPROCESSOR: + descriptor->SetCallHandler(USE_CALLBACK(XSLTProcessorConstructor)); + break; + case V8ClassIndex::CLIENTRECTLIST: + descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(ClientRectList)); + break; +#if ENABLE(DATAGRID) + case V8ClassIndex::DATAGRIDCOLUMNLIST: + descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(DataGridColumnList)); + descriptor->InstanceTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(DataGridColumnList)); + break; +#endif + default: + break; + } + + *cacheCell = descriptor; + return descriptor; +} + +v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> objectPrototype) +{ + // A DOM constructor is a function instance created from a DOM constructor + // template. There is one instance per context. A DOM constructor is + // different from a normal function in two ways: + // 1) it cannot be called as constructor (aka, used to create a DOM object) + // 2) its __proto__ points to Object.prototype rather than + // Function.prototype. + // The reason for 2) is that, in Safari, a DOM constructor is a normal JS + // object, but not a function. Hotmail relies on the fact that, in Safari, + // HTMLElement.__proto__ == Object.prototype. + v8::Handle<v8::FunctionTemplate> functionTemplate = getTemplate(type); + // Getting the function might fail if we're running out of + // stack or memory. + v8::TryCatch tryCatch; + v8::Local<v8::Function> value = functionTemplate->GetFunction(); + if (value.IsEmpty()) + return v8::Local<v8::Function>(); + // Hotmail fix, see comments above. + if (!objectPrototype.IsEmpty()) + value->Set(v8::String::New("__proto__"), objectPrototype); + return value; +} + +v8::Local<v8::Function> V8DOMWrapper::getConstructorForContext(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Context> context) +{ + // Enter the scope for this context to get the correct constructor. + v8::Context::Scope scope(context); + + return getConstructor(type, V8Proxy::getHiddenObjectPrototype(context)); +} + +v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, DOMWindow* window) +{ + Frame* frame = window->frame(); + if (!frame) + return v8::Local<v8::Function>(); + + v8::Handle<v8::Context> context = V8Proxy::context(frame); + if (context.IsEmpty()) + return v8::Local<v8::Function>(); + + return getConstructorForContext(type, context); +} + +v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, WorkerContext*) +{ + WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve(); + if (!proxy) + return v8::Local<v8::Function>(); + + v8::Handle<v8::Context> context = proxy->context(); + if (context.IsEmpty()) + return v8::Local<v8::Function>(); + + return getConstructorForContext(type, context); +} + +v8::Handle<v8::Value> V8DOMWrapper::convertToV8Object(V8ClassIndex::V8WrapperType type, void* impl) +{ + ASSERT(type != V8ClassIndex::EVENTLISTENER); + ASSERT(type != V8ClassIndex::EVENTTARGET); + ASSERT(type != V8ClassIndex::EVENT); + + // These objects can be constructed under WorkerContextExecutionProxy. They need special + // handling, since if we proceed below V8Proxy::retrieve() will get called and will crash. + if ((type == V8ClassIndex::DOMCOREEXCEPTION + || type == V8ClassIndex::RANGEEXCEPTION + || type == V8ClassIndex::EVENTEXCEPTION + || type == V8ClassIndex::XMLHTTPREQUESTEXCEPTION + || type == V8ClassIndex::MESSAGEPORT) + && WorkerContextExecutionProxy::retrieve()) { + return WorkerContextExecutionProxy::convertToV8Object(type, impl); + } + + bool isActiveDomObject = false; + switch (type) { +#define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: + DOM_NODE_TYPES(MAKE_CASE) +#if ENABLE(SVG) + SVG_NODE_TYPES(MAKE_CASE) +#endif + return convertNodeToV8Object(static_cast<Node*>(impl)); + case V8ClassIndex::CSSVALUE: + return convertCSSValueToV8Object(static_cast<CSSValue*>(impl)); + case V8ClassIndex::CSSRULE: + return convertCSSRuleToV8Object(static_cast<CSSRule*>(impl)); + case V8ClassIndex::STYLESHEET: + return convertStyleSheetToV8Object(static_cast<StyleSheet*>(impl)); + case V8ClassIndex::DOMWINDOW: + return convertWindowToV8Object(static_cast<DOMWindow*>(impl)); +#if ENABLE(SVG) + SVG_NONNODE_TYPES(MAKE_CASE) + if (type == V8ClassIndex::SVGELEMENTINSTANCE) + return convertSVGElementInstanceToV8Object(static_cast<SVGElementInstance*>(impl)); + return convertSVGObjectWithContextToV8Object(type, impl); +#endif + + ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) + isActiveDomObject = true; + break; + default: + break; + } + +#undef MAKE_CASE + + if (!impl) + return v8::Null(); + + // Non DOM node + v8::Persistent<v8::Object> result = isActiveDomObject ? getActiveDOMObjectMap().get(impl) : getDOMObjectMap().get(impl); + if (result.IsEmpty()) { + v8::Local<v8::Object> v8Object = instantiateV8Object(type, type, impl); + if (!v8Object.IsEmpty()) { + // Go through big switch statement, it has some duplications + // that were handled by code above (such as CSSVALUE, CSSRULE, etc). + switch (type) { +#define MAKE_CASE(TYPE, NAME) \ + case V8ClassIndex::TYPE: static_cast<NAME*>(impl)->ref(); break; + DOM_OBJECT_TYPES(MAKE_CASE) +#undef MAKE_CASE + default: + ASSERT_NOT_REACHED(); + } + result = v8::Persistent<v8::Object>::New(v8Object); + if (isActiveDomObject) + setJSWrapperForActiveDOMObject(impl, result); + else + setJSWrapperForDOMObject(impl, result); + + if (type == V8ClassIndex::CANVASPIXELARRAY) { + CanvasPixelArray* pixels = reinterpret_cast<CanvasPixelArray*>(impl); + result->SetIndexedPropertiesToPixelData(pixels->data()->data(), pixels->length()); + } + + // Special case for non-node objects associated with a + // DOMWindow. Both Safari and FF let the JS wrappers for these + // objects survive GC. To mimic their behavior, V8 creates + // hidden references from the DOMWindow to these wrapper + // objects. These references get cleared when the DOMWindow is + // reused by a new page. + switch (type) { + case V8ClassIndex::CONSOLE: + setHiddenWindowReference(static_cast<Console*>(impl)->frame(), V8Custom::kDOMWindowConsoleIndex, result); + break; + case V8ClassIndex::HISTORY: + setHiddenWindowReference(static_cast<History*>(impl)->frame(), V8Custom::kDOMWindowHistoryIndex, result); + break; + case V8ClassIndex::NAVIGATOR: + setHiddenWindowReference(static_cast<Navigator*>(impl)->frame(), V8Custom::kDOMWindowNavigatorIndex, result); + break; + case V8ClassIndex::SCREEN: + setHiddenWindowReference(static_cast<Screen*>(impl)->frame(), V8Custom::kDOMWindowScreenIndex, result); + break; + case V8ClassIndex::LOCATION: + setHiddenWindowReference(static_cast<Location*>(impl)->frame(), V8Custom::kDOMWindowLocationIndex, result); + break; + case V8ClassIndex::DOMSELECTION: + setHiddenWindowReference(static_cast<DOMSelection*>(impl)->frame(), V8Custom::kDOMWindowDOMSelectionIndex, result); + break; + case V8ClassIndex::BARINFO: { + BarInfo* barInfo = static_cast<BarInfo*>(impl); + Frame* frame = barInfo->frame(); + switch (barInfo->type()) { + case BarInfo::Locationbar: + setHiddenWindowReference(frame, V8Custom::kDOMWindowLocationbarIndex, result); + break; + case BarInfo::Menubar: + setHiddenWindowReference(frame, V8Custom::kDOMWindowMenubarIndex, result); + break; + case BarInfo::Personalbar: + setHiddenWindowReference(frame, V8Custom::kDOMWindowPersonalbarIndex, result); + break; + case BarInfo::Scrollbars: + setHiddenWindowReference(frame, V8Custom::kDOMWindowScrollbarsIndex, result); + break; + case BarInfo::Statusbar: + setHiddenWindowReference(frame, V8Custom::kDOMWindowStatusbarIndex, result); + break; + case BarInfo::Toolbar: + setHiddenWindowReference(frame, V8Custom::kDOMWindowToolbarIndex, result); + break; + } + break; + } + default: + break; + } + } + } + return result; +} + +void V8DOMWrapper::setHiddenWindowReference(Frame* frame, const int internalIndex, v8::Handle<v8::Object> jsObject) +{ + // Get DOMWindow + if (!frame) + return; // Object might be detached from window + v8::Handle<v8::Context> context = V8Proxy::context(frame); + if (context.IsEmpty()) + return; + + ASSERT(internalIndex < V8Custom::kDOMWindowInternalFieldCount); + + v8::Handle<v8::Object> global = context->Global(); + // Look for real DOM wrapper. + global = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, global); + ASSERT(!global.IsEmpty()); + ASSERT(global->GetInternalField(internalIndex)->IsUndefined()); + global->SetInternalField(internalIndex, jsObject); +} + +V8ClassIndex::V8WrapperType V8DOMWrapper::domWrapperType(v8::Handle<v8::Object> object) +{ + ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); + v8::Handle<v8::Value> type = object->GetInternalField(V8Custom::kDOMWrapperTypeIndex); + return V8ClassIndex::FromInt(type->Int32Value()); +} + +void* V8DOMWrapper::convertToSVGPODTypeImpl(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> object) +{ + return isWrapperOfType(object, type) ? convertDOMWrapperToNative<void>(v8::Handle<v8::Object>::Cast(object)) : 0; +} + +PassRefPtr<NodeFilter> V8DOMWrapper::wrapNativeNodeFilter(v8::Handle<v8::Value> filter) +{ + // A NodeFilter is used when walking through a DOM tree or iterating tree + // nodes. + // FIXME: we may want to cache NodeFilterCondition and NodeFilter + // object, but it is minor. + // NodeFilter is passed to NodeIterator that has a ref counted pointer + // to NodeFilter. NodeFilter has a ref counted pointer to NodeFilterCondition. + // In NodeFilterCondition, filter object is persisted in its constructor, + // and disposed in its destructor. + if (!filter->IsFunction()) + return 0; + + NodeFilterCondition* condition = new V8NodeFilterCondition(filter); + return NodeFilter::create(condition); +} + +v8::Local<v8::Object> V8DOMWrapper::instantiateV8Object(V8Proxy* proxy, V8ClassIndex::V8WrapperType descriptorType, V8ClassIndex::V8WrapperType cptrType, void* impl) +{ + // Make a special case for document.all + if (descriptorType == V8ClassIndex::HTMLCOLLECTION && static_cast<HTMLCollection*>(impl)->type() == DocAll) + descriptorType = V8ClassIndex::HTMLALLCOLLECTION; + + if (V8IsolatedWorld::getEntered()) { + // This effectively disables the wrapper cache for isolated worlds. + proxy = 0; + // FIXME: Do we need a wrapper cache for the isolated world? We should + // see if the performance gains are worth while. + } else if (!proxy) + proxy = V8Proxy::retrieve(); + + v8::Local<v8::Object> instance; + if (proxy) + instance = proxy->createWrapperFromCache(descriptorType); + else { + v8::Local<v8::Function> function = getTemplate(descriptorType)->GetFunction(); + instance = SafeAllocation::newInstance(function); + } + if (!instance.IsEmpty()) { + // Avoid setting the DOM wrapper for failed allocations. + setDOMWrapper(instance, V8ClassIndex::ToInt(cptrType), impl); + } + return instance; +} + +void V8DOMWrapper::setDOMWrapper(v8::Handle<v8::Object> object, int type, void* cptr) +{ + ASSERT(object->InternalFieldCount() >= 2); + object->SetPointerInInternalField(V8Custom::kDOMWrapperObjectIndex, cptr); + object->SetInternalField(V8Custom::kDOMWrapperTypeIndex, v8::Integer::New(type)); +} + +#ifndef NDEBUG +bool V8DOMWrapper::maybeDOMWrapper(v8::Handle<v8::Value> value) +{ + if (value.IsEmpty() || !value->IsObject()) + return false; + + v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); + if (!object->InternalFieldCount()) + return false; + + ASSERT(object->InternalFieldCount() >= V8Custom::kDefaultWrapperInternalFieldCount); + + v8::Handle<v8::Value> type = object->GetInternalField(V8Custom::kDOMWrapperTypeIndex); + ASSERT(type->IsInt32()); + ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() && type->Int32Value() < V8ClassIndex::CLASSINDEX_END); + + v8::Handle<v8::Value> wrapper = object->GetInternalField(V8Custom::kDOMWrapperObjectIndex); + ASSERT(wrapper->IsNumber() || wrapper->IsExternal()); + + return true; +} +#endif + +bool V8DOMWrapper::isDOMEventWrapper(v8::Handle<v8::Value> value) +{ + // All kinds of events use EVENT as dom type in JS wrappers. + // See EventToV8Object + return isWrapperOfType(value, V8ClassIndex::EVENT); +} + +bool V8DOMWrapper::isWrapperOfType(v8::Handle<v8::Value> value, V8ClassIndex::V8WrapperType classType) +{ + if (value.IsEmpty() || !value->IsObject()) + return false; + + v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); + if (!object->InternalFieldCount()) + return false; + + ASSERT(object->InternalFieldCount() >= V8Custom::kDefaultWrapperInternalFieldCount); + + v8::Handle<v8::Value> wrapper = object->GetInternalField(V8Custom::kDOMWrapperObjectIndex); + ASSERT(wrapper->IsNumber() || wrapper->IsExternal()); + + v8::Handle<v8::Value> type = object->GetInternalField(V8Custom::kDOMWrapperTypeIndex); + ASSERT(type->IsInt32()); + ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() && type->Int32Value() < V8ClassIndex::CLASSINDEX_END); + + return V8ClassIndex::FromInt(type->Int32Value()) == classType; +} + +#if ENABLE(VIDEO) +#define FOR_EACH_VIDEO_TAG(macro) \ + macro(audio, AUDIO) \ + macro(source, SOURCE) \ + macro(video, VIDEO) +#else +#define FOR_EACH_VIDEO_TAG(macro) +#endif + +#if ENABLE(DATAGRID) +#define FOR_EACH_DATAGRID_TAG(macro) \ + macro(datagrid, DATAGRID) \ + macro(dcell, DATAGRIDCELL) \ + macro(dcol, DATAGRIDCOL) \ + macro(drow, DATAGRIDROW) +#else +#define FOR_EACH_DATAGRID_TAG(macro) +#endif + +#define FOR_EACH_TAG(macro) \ + FOR_EACH_DATAGRID_TAG(macro) \ + macro(a, ANCHOR) \ + macro(applet, APPLET) \ + macro(area, AREA) \ + macro(base, BASE) \ + macro(basefont, BASEFONT) \ + macro(blockquote, BLOCKQUOTE) \ + macro(body, BODY) \ + macro(br, BR) \ + macro(button, BUTTON) \ + macro(caption, TABLECAPTION) \ + macro(col, TABLECOL) \ + macro(colgroup, TABLECOL) \ + macro(del, MOD) \ + macro(canvas, CANVAS) \ + macro(dir, DIRECTORY) \ + macro(div, DIV) \ + macro(dl, DLIST) \ + macro(embed, EMBED) \ + macro(fieldset, FIELDSET) \ + macro(font, FONT) \ + macro(form, FORM) \ + macro(frame, FRAME) \ + macro(frameset, FRAMESET) \ + macro(h1, HEADING) \ + macro(h2, HEADING) \ + macro(h3, HEADING) \ + macro(h4, HEADING) \ + macro(h5, HEADING) \ + macro(h6, HEADING) \ + macro(head, HEAD) \ + macro(hr, HR) \ + macro(html, HTML) \ + macro(img, IMAGE) \ + macro(iframe, IFRAME) \ + macro(image, IMAGE) \ + macro(input, INPUT) \ + macro(ins, MOD) \ + macro(isindex, ISINDEX) \ + macro(keygen, SELECT) \ + macro(label, LABEL) \ + macro(legend, LEGEND) \ + macro(li, LI) \ + macro(link, LINK) \ + macro(listing, PRE) \ + macro(map, MAP) \ + macro(marquee, MARQUEE) \ + macro(menu, MENU) \ + macro(meta, META) \ + macro(object, OBJECT) \ + macro(ol, OLIST) \ + macro(optgroup, OPTGROUP) \ + macro(option, OPTION) \ + macro(p, PARAGRAPH) \ + macro(param, PARAM) \ + macro(pre, PRE) \ + macro(q, QUOTE) \ + macro(script, SCRIPT) \ + macro(select, SELECT) \ + macro(style, STYLE) \ + macro(table, TABLE) \ + macro(thead, TABLESECTION) \ + macro(tbody, TABLESECTION) \ + macro(tfoot, TABLESECTION) \ + macro(td, TABLECELL) \ + macro(th, TABLECELL) \ + macro(tr, TABLEROW) \ + macro(textarea, TEXTAREA) \ + macro(title, TITLE) \ + macro(ul, ULIST) \ + macro(xmp, PRE) + +V8ClassIndex::V8WrapperType V8DOMWrapper::htmlElementType(HTMLElement* element) +{ + typedef HashMap<String, V8ClassIndex::V8WrapperType> WrapperTypeMap; + DEFINE_STATIC_LOCAL(WrapperTypeMap, wrapperTypeMap, ()); + if (wrapperTypeMap.isEmpty()) { +#define ADD_TO_HASH_MAP(tag, name) \ + wrapperTypeMap.set(#tag, V8ClassIndex::HTML##name##ELEMENT); + FOR_EACH_TAG(ADD_TO_HASH_MAP) +#if ENABLE(VIDEO) + if (MediaPlayer::isAvailable()) { + FOR_EACH_VIDEO_TAG(ADD_TO_HASH_MAP) + } +#endif +#undef ADD_TO_HASH_MAP + } + + V8ClassIndex::V8WrapperType type = wrapperTypeMap.get(element->localName().impl()); + if (!type) + return V8ClassIndex::HTMLELEMENT; + return type; +} +#undef FOR_EACH_TAG + +#if ENABLE(SVG) + +#if ENABLE(SVG_ANIMATION) +#define FOR_EACH_ANIMATION_TAG(macro) \ + macro(animateColor, ANIMATECOLOR) \ + macro(animate, ANIMATE) \ + macro(animateTransform, ANIMATETRANSFORM) \ + macro(set, SET) +#else +#define FOR_EACH_ANIMATION_TAG(macro) +#endif + +#if ENABLE(SVG_FILTERS) +#define FOR_EACH_FILTERS_TAG(macro) \ + macro(feBlend, FEBLEND) \ + macro(feColorMatrix, FECOLORMATRIX) \ + macro(feComponentTransfer, FECOMPONENTTRANSFER) \ + macro(feComposite, FECOMPOSITE) \ + macro(feDiffuseLighting, FEDIFFUSELIGHTING) \ + macro(feDisplacementMap, FEDISPLACEMENTMAP) \ + macro(feDistantLight, FEDISTANTLIGHT) \ + macro(feFlood, FEFLOOD) \ + macro(feFuncA, FEFUNCA) \ + macro(feFuncB, FEFUNCB) \ + macro(feFuncG, FEFUNCG) \ + macro(feFuncR, FEFUNCR) \ + macro(feGaussianBlur, FEGAUSSIANBLUR) \ + macro(feImage, FEIMAGE) \ + macro(feMerge, FEMERGE) \ + macro(feMergeNode, FEMERGENODE) \ + macro(feOffset, FEOFFSET) \ + macro(fePointLight, FEPOINTLIGHT) \ + macro(feSpecularLighting, FESPECULARLIGHTING) \ + macro(feSpotLight, FESPOTLIGHT) \ + macro(feTile, FETILE) \ + macro(feTurbulence, FETURBULENCE) \ + macro(filter, FILTER) +#else +#define FOR_EACH_FILTERS_TAG(macro) +#endif + +#if ENABLE(SVG_FONTS) +#define FOR_EACH_FONTS_TAG(macro) \ + macro(definition-src, DEFINITIONSRC) \ + macro(font-face, FONTFACE) \ + macro(font-face-format, FONTFACEFORMAT) \ + macro(font-face-name, FONTFACENAME) \ + macro(font-face-src, FONTFACESRC) \ + macro(font-face-uri, FONTFACEURI) +#else +#define FOR_EACH_FONTS_TAG(marco) +#endif + +#if ENABLE(SVG_FOREIGN_OBJECT) +#define FOR_EACH_FOREIGN_OBJECT_TAG(macro) \ + macro(foreignObject, FOREIGNOBJECT) +#else +#define FOR_EACH_FOREIGN_OBJECT_TAG(macro) +#endif + +#if ENABLE(SVG_USE) +#define FOR_EACH_USE_TAG(macro) \ + macro(use, USE) +#else +#define FOR_EACH_USE_TAG(macro) +#endif + +#define FOR_EACH_TAG(macro) \ + FOR_EACH_ANIMATION_TAG(macro) \ + FOR_EACH_FILTERS_TAG(macro) \ + FOR_EACH_FONTS_TAG(macro) \ + FOR_EACH_FOREIGN_OBJECT_TAG(macro) \ + FOR_EACH_USE_TAG(macro) \ + macro(a, A) \ + macro(altGlyph, ALTGLYPH) \ + macro(circle, CIRCLE) \ + macro(clipPath, CLIPPATH) \ + macro(cursor, CURSOR) \ + macro(defs, DEFS) \ + macro(desc, DESC) \ + macro(ellipse, ELLIPSE) \ + macro(g, G) \ + macro(glyph, GLYPH) \ + macro(image, IMAGE) \ + macro(linearGradient, LINEARGRADIENT) \ + macro(line, LINE) \ + macro(marker, MARKER) \ + macro(mask, MASK) \ + macro(metadata, METADATA) \ + macro(path, PATH) \ + macro(pattern, PATTERN) \ + macro(polyline, POLYLINE) \ + macro(polygon, POLYGON) \ + macro(radialGradient, RADIALGRADIENT) \ + macro(rect, RECT) \ + macro(script, SCRIPT) \ + macro(stop, STOP) \ + macro(style, STYLE) \ + macro(svg, SVG) \ + macro(switch, SWITCH) \ + macro(symbol, SYMBOL) \ + macro(text, TEXT) \ + macro(textPath, TEXTPATH) \ + macro(title, TITLE) \ + macro(tref, TREF) \ + macro(tspan, TSPAN) \ + macro(view, VIEW) \ + // end of macro + +V8ClassIndex::V8WrapperType V8DOMWrapper::svgElementType(SVGElement* element) +{ + typedef HashMap<String, V8ClassIndex::V8WrapperType> WrapperTypeMap; + DEFINE_STATIC_LOCAL(WrapperTypeMap, wrapperTypeMap, ()); + if (wrapperTypeMap.isEmpty()) { +#define ADD_TO_HASH_MAP(tag, name) \ + wrapperTypeMap.set(#tag, V8ClassIndex::SVG##name##ELEMENT); + FOR_EACH_TAG(ADD_TO_HASH_MAP) +#undef ADD_TO_HASH_MAP + } + + V8ClassIndex::V8WrapperType type = wrapperTypeMap.get(element->localName().impl()); + if (!type) + return V8ClassIndex::SVGELEMENT; + return type; +} +#undef FOR_EACH_TAG + +#endif // ENABLE(SVG) + +v8::Handle<v8::Value> V8DOMWrapper::convertEventToV8Object(Event* event) +{ + if (!event) + return v8::Null(); + + v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(event); + if (!wrapper.IsEmpty()) + return wrapper; + + V8ClassIndex::V8WrapperType type = V8ClassIndex::EVENT; + + if (event->isUIEvent()) { + if (event->isKeyboardEvent()) + type = V8ClassIndex::KEYBOARDEVENT; + else if (event->isTextEvent()) + type = V8ClassIndex::TEXTEVENT; + else if (event->isMouseEvent()) + type = V8ClassIndex::MOUSEEVENT; + else if (event->isWheelEvent()) + type = V8ClassIndex::WHEELEVENT; +#if ENABLE(SVG) + else if (event->isSVGZoomEvent()) + type = V8ClassIndex::SVGZOOMEVENT; +#endif + else + type = V8ClassIndex::UIEVENT; + } else if (event->isMutationEvent()) + type = V8ClassIndex::MUTATIONEVENT; + else if (event->isOverflowEvent()) + type = V8ClassIndex::OVERFLOWEVENT; + else if (event->isMessageEvent()) + type = V8ClassIndex::MESSAGEEVENT; + else if (event->isProgressEvent()) { + if (event->isXMLHttpRequestProgressEvent()) + type = V8ClassIndex::XMLHTTPREQUESTPROGRESSEVENT; + else + type = V8ClassIndex::PROGRESSEVENT; + } else if (event->isWebKitAnimationEvent()) + type = V8ClassIndex::WEBKITANIMATIONEVENT; + else if (event->isWebKitTransitionEvent()) + type = V8ClassIndex::WEBKITTRANSITIONEVENT; +#if ENABLE(WORKERS) + else if (event->isErrorEvent()) + type = V8ClassIndex::ERROREVENT; +#endif + + + v8::Handle<v8::Object> result = instantiateV8Object(type, V8ClassIndex::EVENT, event); + if (result.IsEmpty()) { + // Instantiation failed. Avoid updating the DOM object map and + // return null which is already handled by callers of this function + // in case the event is NULL. + return v8::Null(); + } + + event->ref(); // fast ref + setJSWrapperForDOMObject(event, v8::Persistent<v8::Object>::New(result)); + + return result; +} + +static const V8ClassIndex::V8WrapperType mapping[] = { + V8ClassIndex::INVALID_CLASS_INDEX, // NONE + V8ClassIndex::INVALID_CLASS_INDEX, // ELEMENT_NODE needs special treatment + V8ClassIndex::ATTR, // ATTRIBUTE_NODE + V8ClassIndex::TEXT, // TEXT_NODE + V8ClassIndex::CDATASECTION, // CDATA_SECTION_NODE + V8ClassIndex::ENTITYREFERENCE, // ENTITY_REFERENCE_NODE + V8ClassIndex::ENTITY, // ENTITY_NODE + V8ClassIndex::PROCESSINGINSTRUCTION, // PROCESSING_INSTRUCTION_NODE + V8ClassIndex::COMMENT, // COMMENT_NODE + V8ClassIndex::INVALID_CLASS_INDEX, // DOCUMENT_NODE needs special treatment + V8ClassIndex::DOCUMENTTYPE, // DOCUMENT_TYPE_NODE + V8ClassIndex::DOCUMENTFRAGMENT, // DOCUMENT_FRAGMENT_NODE + V8ClassIndex::NOTATION, // NOTATION_NODE + V8ClassIndex::NODE, // XPATH_NAMESPACE_NODE +}; + +// Caller checks node is not null. +v8::Handle<v8::Value> V8DOMWrapper::convertNodeToV8Object(Node* node) +{ + if (!node) + return v8::Null(); + + // Find a proxy for this node. + // + // Note that if proxy is found, we might initialize the context which can + // instantiate a document wrapper. Therefore, we get the proxy before + // checking if the node already has a wrapper. + V8Proxy* proxy = 0; + Document* document = node->document(); + if (document) { + Frame* frame = document->frame(); + proxy = V8Proxy::retrieve(frame); + if (proxy) + proxy->initContextIfNeeded(); + } + + DOMWrapperMap<Node>& domNodeMap = getDOMNodeMap(); + v8::Handle<v8::Object> wrapper = domNodeMap.get(node); + if (!wrapper.IsEmpty()) + return wrapper; + + bool isDocument = false; // document type node has special handling + V8ClassIndex::V8WrapperType type; + + Node::NodeType nodeType = node->nodeType(); + if (nodeType == Node::ELEMENT_NODE) { + if (node->isHTMLElement()) + type = htmlElementType(static_cast<HTMLElement*>(node)); +#if ENABLE(SVG) + else if (node->isSVGElement()) + type = svgElementType(static_cast<SVGElement*>(node)); +#endif + else + type = V8ClassIndex::ELEMENT; + } else if (nodeType == Node::DOCUMENT_NODE) { + isDocument = true; + Document* document = static_cast<Document*>(node); + if (document->isHTMLDocument()) + type = V8ClassIndex::HTMLDOCUMENT; +#if ENABLE(SVG) + else if (document->isSVGDocument()) + type = V8ClassIndex::SVGDOCUMENT; +#endif + else + type = V8ClassIndex::DOCUMENT; + } else { + ASSERT(nodeType < sizeof(mapping)/sizeof(mapping[0])); + type = mapping[nodeType]; + ASSERT(type != V8ClassIndex::INVALID_CLASS_INDEX); + } + + v8::Handle<v8::Context> context; + if (proxy) + context = V8Proxy::context(proxy->frame()); + + // Enter the node's context and create the wrapper in that context. + if (!context.IsEmpty()) + context->Enter(); + + v8::Local<v8::Object> result = instantiateV8Object(proxy, type, V8ClassIndex::NODE, node); + + // Exit the node's context if it was entered. + if (!context.IsEmpty()) + context->Exit(); + + if (result.IsEmpty()) { + // If instantiation failed it's important not to add the result + // to the DOM node map. Instead we return an empty handle, which + // should already be handled by callers of this function in case + // the node is NULL. + return result; + } + + node->ref(); + domNodeMap.set(node, v8::Persistent<v8::Object>::New(result)); + + if (isDocument) { + if (proxy) + proxy->updateDocumentWrapper(result); + + if (type == V8ClassIndex::HTMLDOCUMENT) { + // Create marker object and insert it in two internal fields. + // This is used to implement temporary shadowing of + // document.all. + ASSERT(result->InternalFieldCount() == V8Custom::kHTMLDocumentInternalFieldCount); + v8::Local<v8::Object> marker = v8::Object::New(); + result->SetInternalField(V8Custom::kHTMLDocumentMarkerIndex, marker); + result->SetInternalField(V8Custom::kHTMLDocumentShadowIndex, marker); + } + } + + return result; +} + +// A JS object of type EventTarget is limited to a small number of possible classes. +// Check EventTarget.h for new type conversion methods +v8::Handle<v8::Value> V8DOMWrapper::convertEventTargetToV8Object(EventTarget* target) +{ + if (!target) + return v8::Null(); + +#if ENABLE(SVG) + SVGElementInstance* instance = target->toSVGElementInstance(); + if (instance) + return convertToV8Object(V8ClassIndex::SVGELEMENTINSTANCE, instance); +#endif + +#if ENABLE(WORKERS) + Worker* worker = target->toWorker(); + if (worker) + return convertToV8Object(V8ClassIndex::WORKER, worker); +#endif // WORKERS + + Node* node = target->toNode(); + if (node) + return convertNodeToV8Object(node); + + if (DOMWindow* domWindow = target->toDOMWindow()) + return convertToV8Object(V8ClassIndex::DOMWINDOW, domWindow); + + // XMLHttpRequest is created within its JS counterpart. + XMLHttpRequest* xmlHttpRequest = target->toXMLHttpRequest(); + if (xmlHttpRequest) { + v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(xmlHttpRequest); + ASSERT(!wrapper.IsEmpty()); + return wrapper; + } + + // MessagePort is created within its JS counterpart + MessagePort* port = target->toMessagePort(); + if (port) { + v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(port); + ASSERT(!wrapper.IsEmpty()); + return wrapper; + } + + XMLHttpRequestUpload* upload = target->toXMLHttpRequestUpload(); + if (upload) { + v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(upload); + ASSERT(!wrapper.IsEmpty()); + return wrapper; + } + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + DOMApplicationCache* domAppCache = target->toDOMApplicationCache(); + if (domAppCache) + return convertToV8Object(V8ClassIndex::DOMAPPLICATIONCACHE, domAppCache); +#endif + + ASSERT(0); + return notHandledByInterceptor(); +} + +v8::Handle<v8::Value> V8DOMWrapper::convertEventListenerToV8Object(EventListener* listener) +{ + if (!listener) + return v8::Null(); + + // FIXME: can a user take a lazy event listener and set to other places? + V8AbstractEventListener* v8listener = static_cast<V8AbstractEventListener*>(listener); + return v8listener->getListenerObject(); +} + +v8::Handle<v8::Value> V8DOMWrapper::convertDOMImplementationToV8Object(DOMImplementation* impl) +{ + v8::Handle<v8::Object> result = instantiateV8Object(V8ClassIndex::DOMIMPLEMENTATION, V8ClassIndex::DOMIMPLEMENTATION, impl); + if (result.IsEmpty()) { + // If the instantiation failed, we ignore it and return null instead + // of returning an empty handle. + return v8::Null(); + } + return result; +} + +v8::Handle<v8::Value> V8DOMWrapper::convertStyleSheetToV8Object(StyleSheet* sheet) +{ + if (!sheet) + return v8::Null(); + + v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(sheet); + if (!wrapper.IsEmpty()) + return wrapper; + + V8ClassIndex::V8WrapperType type = V8ClassIndex::STYLESHEET; + if (sheet->isCSSStyleSheet()) + type = V8ClassIndex::CSSSTYLESHEET; + + v8::Handle<v8::Object> result = instantiateV8Object(type, V8ClassIndex::STYLESHEET, sheet); + if (!result.IsEmpty()) { + // Only update the DOM object map if the result is non-empty. + sheet->ref(); + setJSWrapperForDOMObject(sheet, v8::Persistent<v8::Object>::New(result)); + } + + // Add a hidden reference from stylesheet object to its owner node. + Node* ownerNode = sheet->ownerNode(); + if (ownerNode) { + v8::Handle<v8::Object> owner = v8::Handle<v8::Object>::Cast(convertNodeToV8Object(ownerNode)); + result->SetInternalField(V8Custom::kStyleSheetOwnerNodeIndex, owner); + } + + return result; +} + +v8::Handle<v8::Value> V8DOMWrapper::convertCSSValueToV8Object(CSSValue* value) +{ + if (!value) + return v8::Null(); + + v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(value); + if (!wrapper.IsEmpty()) + return wrapper; + + V8ClassIndex::V8WrapperType type; + + if (value->isWebKitCSSTransformValue()) + type = V8ClassIndex::WEBKITCSSTRANSFORMVALUE; + else if (value->isValueList()) + type = V8ClassIndex::CSSVALUELIST; + else if (value->isPrimitiveValue()) + type = V8ClassIndex::CSSPRIMITIVEVALUE; +#if ENABLE(SVG) + else if (value->isSVGPaint()) + type = V8ClassIndex::SVGPAINT; + else if (value->isSVGColor()) + type = V8ClassIndex::SVGCOLOR; +#endif + else + type = V8ClassIndex::CSSVALUE; + + v8::Handle<v8::Object> result = instantiateV8Object(type, V8ClassIndex::CSSVALUE, value); + if (!result.IsEmpty()) { + // Only update the DOM object map if the result is non-empty. + value->ref(); + setJSWrapperForDOMObject(value, v8::Persistent<v8::Object>::New(result)); + } + + return result; +} + +v8::Handle<v8::Value> V8DOMWrapper::convertCSSRuleToV8Object(CSSRule* rule) +{ + if (!rule) + return v8::Null(); + + v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(rule); + if (!wrapper.IsEmpty()) + return wrapper; + + V8ClassIndex::V8WrapperType type; + + switch (rule->type()) { + case CSSRule::STYLE_RULE: + type = V8ClassIndex::CSSSTYLERULE; + break; + case CSSRule::CHARSET_RULE: + type = V8ClassIndex::CSSCHARSETRULE; + break; + case CSSRule::IMPORT_RULE: + type = V8ClassIndex::CSSIMPORTRULE; + break; + case CSSRule::MEDIA_RULE: + type = V8ClassIndex::CSSMEDIARULE; + break; + case CSSRule::FONT_FACE_RULE: + type = V8ClassIndex::CSSFONTFACERULE; + break; + case CSSRule::PAGE_RULE: + type = V8ClassIndex::CSSPAGERULE; + break; + case CSSRule::VARIABLES_RULE: + type = V8ClassIndex::CSSVARIABLESRULE; + break; + case CSSRule::WEBKIT_KEYFRAME_RULE: + type = V8ClassIndex::WEBKITCSSKEYFRAMERULE; + break; + case CSSRule::WEBKIT_KEYFRAMES_RULE: + type = V8ClassIndex::WEBKITCSSKEYFRAMESRULE; + break; + default: // CSSRule::UNKNOWN_RULE + type = V8ClassIndex::CSSRULE; + break; + } + + v8::Handle<v8::Object> result = instantiateV8Object(type, V8ClassIndex::CSSRULE, rule); + if (!result.IsEmpty()) { + // Only update the DOM object map if the result is non-empty. + rule->ref(); + setJSWrapperForDOMObject(rule, v8::Persistent<v8::Object>::New(result)); + } + return result; +} + +v8::Handle<v8::Value> V8DOMWrapper::convertWindowToV8Object(DOMWindow* window) +{ + if (!window) + return v8::Null(); + // Initializes environment of a frame, and return the global object + // of the frame. + Frame* frame = window->frame(); + if (!frame) + return v8::Handle<v8::Object>(); + + // Special case: Because of evaluateInNewContext() one DOMWindow can have + // multiple contexts and multiple global objects associated with it. When + // code running in one of those contexts accesses the window object, we + // want to return the global object associated with that context, not + // necessarily the first global object associated with that DOMWindow. + v8::Handle<v8::Context> currentContext = v8::Context::GetCurrent(); + v8::Handle<v8::Object> currentGlobal = currentContext->Global(); + v8::Handle<v8::Object> windowWrapper = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, currentGlobal); + if (!windowWrapper.IsEmpty()) { + if (convertDOMWrapperToNative<DOMWindow>(windowWrapper) == window) + return currentGlobal; + } + + // Otherwise, return the global object associated with this frame. + v8::Handle<v8::Context> context = V8Proxy::context(frame); + if (context.IsEmpty()) + return v8::Handle<v8::Object>(); + + v8::Handle<v8::Object> global = context->Global(); + ASSERT(!global.IsEmpty()); + return global; +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/V8DOMWrapper.h b/WebCore/bindings/v8/V8DOMWrapper.h new file mode 100644 index 0000000..57b3a69 --- /dev/null +++ b/WebCore/bindings/v8/V8DOMWrapper.h @@ -0,0 +1,260 @@ +/* + * 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: + * + * * 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 V8DOMWrapper_h +#define V8DOMWrapper_h + +#include "Event.h" +#include "Node.h" +#include "NodeFilter.h" +#include "PlatformString.h" // for WebCore::String +#include "V8CustomBinding.h" +#include "V8Index.h" +#include "V8Utilities.h" +#include <v8.h> + +namespace WebCore { + + // FIXME: This probably aren't all needed. + class CSSRule; + class CSSRuleList; + class CSSStyleDeclaration; + class CSSValue; + class CSSValueList; + class ClientRectList; + class DOMImplementation; + class DOMWindow; + class Document; + class Element; + class Event; + class EventListener; + class EventTarget; + class Frame; + class HTMLCollection; + class HTMLDocument; + class HTMLElement; + class HTMLOptionsCollection; + class MediaList; + class MimeType; + class MimeTypeArray; + class NamedNodeMap; + class Navigator; + class Node; + class NodeFilter; + class NodeList; + class Plugin; + class PluginArray; + class SVGElement; +#if ENABLE(SVG) + class SVGElementInstance; +#endif + class Screen; + class ScriptExecutionContext; +#if ENABLE(DOM_STORAGE) + class Storage; + class StorageEvent; +#endif + class String; + class StyleSheet; + class StyleSheetList; + class V8EventListener; + class V8ObjectEventListener; + class WorkerContext; + + class V8DOMWrapper { + public: +#ifndef NDEBUG + // Checks if a v8 value can be a DOM wrapper + static bool maybeDOMWrapper(v8::Handle<v8::Value>); +#endif + + // Sets contents of a DOM wrapper. + static void setDOMWrapper(v8::Handle<v8::Object>, int type, void* ptr); + + static v8::Handle<v8::Object> lookupDOMWrapper(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Object> object) + { + return object.IsEmpty() ? object : object->FindInstanceInPrototypeChain(getTemplate(type)); + } + + // A helper function extract native object pointer from a DOM wrapper + // and cast to the specified type. + template <class C> + static C* convertDOMWrapperToNative(v8::Handle<v8::Object> object) + { + ASSERT(maybeDOMWrapper(object)); + return reinterpret_cast<C*>(object->GetPointerFromInternalField(V8Custom::kDOMWrapperObjectIndex)); + } + + template <class C> + static C* convertDOMWrapperToNode(v8::Handle<v8::Object> object) + { + ASSERT(maybeDOMWrapper(object)); + ASSERT(domWrapperType(object) == V8ClassIndex::NODE); + return convertDOMWrapperToNative<C>(object); + } + + template<typename T> + static v8::Handle<v8::Value> convertToV8Object(V8ClassIndex::V8WrapperType type, PassRefPtr<T> imp) + { + return convertToV8Object(type, imp.get()); + } + + static v8::Handle<v8::Value> convertToV8Object(V8ClassIndex::V8WrapperType, void*); + + // Fast-path for Node objects. + static v8::Handle<v8::Value> convertNodeToV8Object(PassRefPtr<Node> node) + { + return convertNodeToV8Object(node.get()); + } + + static v8::Handle<v8::Value> convertNodeToV8Object(Node*); + + template <class C> + static C* convertToNativeObject(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Object> object) + { + // Native event listener is per frame, it cannot be handled by this generic function. + ASSERT(type != V8ClassIndex::EVENTLISTENER); + ASSERT(type != V8ClassIndex::EVENTTARGET); + + ASSERT(maybeDOMWrapper(object)); + +#ifndef NDEBUG + const bool typeIsValid = +#define MAKE_CASE(TYPE, NAME) (type != V8ClassIndex::TYPE) && + DOM_NODE_TYPES(MAKE_CASE) +#if ENABLE(SVG) + SVG_NODE_TYPES(MAKE_CASE) +#endif +#undef MAKE_CASE + true; + ASSERT(typeIsValid); +#endif + + return convertDOMWrapperToNative<C>(object); + } + + static V8ClassIndex::V8WrapperType domWrapperType(v8::Handle<v8::Object>); + + static v8::Handle<v8::Value> convertEventToV8Object(PassRefPtr<Event> event) + { + return convertEventToV8Object(event.get()); + } + + static v8::Handle<v8::Value> convertEventToV8Object(Event*); + + static Event* convertToNativeEvent(v8::Handle<v8::Value> jsEvent) + { + if (!isDOMEventWrapper(jsEvent)) + return 0; + return convertDOMWrapperToNative<Event>(v8::Handle<v8::Object>::Cast(jsEvent)); + } + + static v8::Handle<v8::Value> convertEventTargetToV8Object(PassRefPtr<EventTarget> eventTarget) + { + return convertEventTargetToV8Object(eventTarget.get()); + } + + static v8::Handle<v8::Value> convertEventTargetToV8Object(EventTarget*); + + // Wrap and unwrap JS event listeners. + static v8::Handle<v8::Value> convertEventListenerToV8Object(PassRefPtr<Event> eventListener) + { + return convertEventListenerToV8Object(eventListener.get()); + } + + static v8::Handle<v8::Value> convertEventListenerToV8Object(EventListener*); + + // DOMImplementation is a singleton and it is handled in a special + // way. A wrapper is generated per document and stored in an + // internal field of the document. + static v8::Handle<v8::Value> convertDOMImplementationToV8Object(DOMImplementation*); + + // Wrap JS node filter in C++. + static PassRefPtr<NodeFilter> wrapNativeNodeFilter(v8::Handle<v8::Value>); + + static v8::Persistent<v8::FunctionTemplate> getTemplate(V8ClassIndex::V8WrapperType); + static v8::Local<v8::Function> getConstructorForContext(V8ClassIndex::V8WrapperType, v8::Handle<v8::Context>); + static v8::Local<v8::Function> getConstructor(V8ClassIndex::V8WrapperType, v8::Handle<v8::Value> objectPrototype); + static v8::Local<v8::Function> getConstructor(V8ClassIndex::V8WrapperType, DOMWindow*); + static v8::Local<v8::Function> getConstructor(V8ClassIndex::V8WrapperType, WorkerContext*); + + // Checks whether a DOM object has a JS wrapper. + static bool domObjectHasJSWrapper(void*); + // Set JS wrapper of a DOM object, the caller in charge of increase ref. + static void setJSWrapperForDOMObject(void*, v8::Persistent<v8::Object>); + static void setJSWrapperForActiveDOMObject(void*, v8::Persistent<v8::Object>); + static void setJSWrapperForDOMNode(Node*, v8::Persistent<v8::Object>); + + // Check whether a V8 value is a wrapper of type |classType|. + static bool isWrapperOfType(v8::Handle<v8::Value>, V8ClassIndex::V8WrapperType); + + static void* convertToSVGPODTypeImpl(V8ClassIndex::V8WrapperType, v8::Handle<v8::Value>); + + // Check whether a V8 value is a DOM Event wrapper. + static bool isDOMEventWrapper(v8::Handle<v8::Value>); + + static v8::Handle<v8::Value> convertStyleSheetToV8Object(StyleSheet*); + static v8::Handle<v8::Value> convertCSSValueToV8Object(CSSValue*); + static v8::Handle<v8::Value> convertCSSRuleToV8Object(CSSRule*); + // Returns the JS wrapper of a window object, initializes the environment + // of the window frame if needed. + static v8::Handle<v8::Value> convertWindowToV8Object(DOMWindow*); + +#if ENABLE(SVG) + static v8::Handle<v8::Value> convertSVGElementInstanceToV8Object(SVGElementInstance*); + static v8::Handle<v8::Value> convertSVGObjectWithContextToV8Object(V8ClassIndex::V8WrapperType, void*); +#endif + + private: + // Set hidden references in a DOMWindow object of a frame. + static void setHiddenWindowReference(Frame*, const int internalIndex, v8::Handle<v8::Object>); + + static V8ClassIndex::V8WrapperType htmlElementType(HTMLElement*); +#if ENABLE(SVG) + static V8ClassIndex::V8WrapperType svgElementType(SVGElement*); +#endif + + // The first V8WrapperType specifies the function descriptor + // used to create JS object. The second V8WrapperType specifies + // the actual type of the void* for type casting. + // For example, a HTML element has HTMLELEMENT for the first V8WrapperType, but always + // use NODE as the second V8WrapperType. JS wrapper stores the second + // V8WrapperType and the void* as internal fields. + static v8::Local<v8::Object> instantiateV8Object(V8ClassIndex::V8WrapperType descType, V8ClassIndex::V8WrapperType cptrType, void* impl) + { + return instantiateV8Object(NULL, descType, cptrType, impl); + } + + static v8::Local<v8::Object> instantiateV8Object(V8Proxy*, V8ClassIndex::V8WrapperType, V8ClassIndex::V8WrapperType, void*); + }; + +} + +#endif // V8DOMWrapper_h diff --git a/WebCore/bindings/v8/custom/V8DOMStringListCustom.cpp b/WebCore/bindings/v8/V8DataGridDataSource.cpp index 52d4399..6fff1f5 100644 --- a/WebCore/bindings/v8/custom/V8DOMStringListCustom.cpp +++ b/WebCore/bindings/v8/V8DataGridDataSource.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007-2009 Google Inc. All rights reserved. + * 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 @@ -29,34 +29,37 @@ */ #include "config.h" -#include "DOMStringList.h" -#include "V8Binding.h" -#include "V8CustomBinding.h" -#include "V8Proxy.h" +#if ENABLE(DATAGRID) + +#include "V8DataGridDataSource.h" + +#include "Document.h" +#include "Frame.h" +#include "HTMLDataGridElement.h" +#include "V8HTMLDataGridElement.h" + namespace WebCore { -INDEXED_PROPERTY_GETTER(DOMStringList) +V8DataGridDataSource::V8DataGridDataSource(v8::Handle<v8::Value> dataSource, Frame* frame) + : m_dataSource(v8::Persistent<v8::Value>::New(dataSource)) + , m_frame(frame) { - INC_STATS("DOM.DOMStringList.IndexedPropertyGetter"); - DOMStringList* imp = V8Proxy::DOMWrapperToNative<DOMStringList>(info.Holder()); - return v8String(imp->item(index)); +#ifndef NDEBUG + V8GCController::registerGlobalHandle(DATASOURCE, this, m_dataSource); +#endif } -CALLBACK_FUNC_DECL(DOMStringListItem) +V8DataGridDataSource::~V8DataGridDataSource() { - INC_STATS("DOM.DOMStringListItem()"); - if (!args.Length()) - return v8::Null(); - - uint32_t index = args[0]->Uint32Value(); - - DOMStringList* imp = V8Proxy::DOMWrapperToNative<DOMStringList>(args.Holder()); - if (index >= imp->length()) - return v8::Null(); - - return v8String(imp->item(index)); +#ifndef NDEBUG + V8GCController::unregisterGlobalHandle(this, m_dataSource); +#endif + m_dataSource.Dispose(); + m_dataSource.Clear(); } } // namespace WebCore + +#endif // ENABLE(DATAGRID) diff --git a/WebCore/bindings/v8/V8DataGridDataSource.h b/WebCore/bindings/v8/V8DataGridDataSource.h new file mode 100644 index 0000000..7f6d8d8 --- /dev/null +++ b/WebCore/bindings/v8/V8DataGridDataSource.h @@ -0,0 +1,81 @@ +/* + * 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: + * + * * 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 V8DataGridDataSource_h +#define V8DataGridDataSource_h + +#if ENABLE(DATAGRID) + +#include "DataGridDataSource.h" +#include <v8.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class Frame; +class HTMLDataGridElement; + +class V8DataGridDataSource : public DataGridDataSource { +public: + static PassRefPtr<V8DataGridDataSource> create(v8::Handle<v8::Value> dataSource, Frame* frame) + { + return adoptRef(new V8DataGridDataSource(dataSource, frame)); + } + + virtual ~V8DataGridDataSource(); + + virtual bool isJSDataGridDataSource() const { return true; } + v8::Handle<v8::Value> jsDataSource() const { return m_dataSource; } + +private: + V8DataGridDataSource(v8::Handle<v8::Value>, Frame*); + + v8::Persistent<v8::Value> m_dataSource; + RefPtr<Frame> m_frame; +}; + +inline V8DataGridDataSource* asV8DataGridDataSource(DataGridDataSource* dataSource) +{ + ASSERT(dataSource->isJSDataGridDataSource()); + return static_cast<V8DataGridDataSource*>(dataSource); +} + +inline const V8DataGridDataSource* asV8DataGridDataSource(const DataGridDataSource* dataSource) +{ + ASSERT(dataSource->isJSDataGridDataSource()); + return static_cast<const V8DataGridDataSource*>(dataSource); +} + +} // namespace WebCore + +#endif // ENABLE(DATAGRID) +#endif // V8DataGridDataSource_h diff --git a/WebCore/bindings/v8/V8EventListenerList.cpp b/WebCore/bindings/v8/V8EventListenerList.cpp index df60028..c9aaa12 100644 --- a/WebCore/bindings/v8/V8EventListenerList.cpp +++ b/WebCore/bindings/v8/V8EventListenerList.cpp @@ -182,4 +182,14 @@ V8EventListener* V8EventListenerList::find(v8::Local<v8::Object> object, bool is return 0; } +PassRefPtr<V8EventListener> V8EventListenerList::findWrapper(v8::Local<v8::Value> object, bool isAttribute) +{ + ASSERT(v8::Context::InContext()); + if (!object->IsObject()) + return 0; + + // FIXME: Should this be v8::Local<v8::Object>::Cast instead? + return find(object->ToObject(), isAttribute); +} + } // namespace WebCore diff --git a/WebCore/bindings/v8/V8EventListenerList.h b/WebCore/bindings/v8/V8EventListenerList.h index d7799b8..4255050 100644 --- a/WebCore/bindings/v8/V8EventListenerList.h +++ b/WebCore/bindings/v8/V8EventListenerList.h @@ -35,7 +35,10 @@ #include <wtf/Vector.h> #include <wtf/HashMap.h> +#include "PassRefPtr.h" + namespace WebCore { + class Frame; class V8EventListener; class V8EventListenerListIterator; @@ -67,6 +70,10 @@ namespace WebCore { void clear(); size_t size() { return m_table.size(); } + PassRefPtr<V8EventListener> findWrapper(v8::Local<v8::Value>, bool isAttribute); + template<typename WrapperType> + PassRefPtr<V8EventListener> findOrCreateWrapper(Frame*, v8::Local<v8::Value>, bool isAttribute); + private: ListenerMultiMap m_table; @@ -93,6 +100,25 @@ namespace WebCore { size_t m_vectorIndex; }; + template<typename WrapperType> + PassRefPtr<V8EventListener> V8EventListenerList::findOrCreateWrapper(Frame* frame, v8::Local<v8::Value> object, bool isAttribute) + { + ASSERT(v8::Context::InContext()); + if (!object->IsObject()) + return 0; + + // FIXME: Should this be v8::Local<v8::Object>::Cast instead? + V8EventListener* wrapper = find(object->ToObject(), isAttribute); + if (wrapper) + return wrapper; + + // Create a new one, and add to cache. + RefPtr<WrapperType> newListener = WrapperType::create(frame, v8::Local<v8::Object>::Cast(object), isAttribute); + add(newListener.get()); + + return newListener; + }; + } // namespace WebCore #endif // V8EventListenerList_h diff --git a/WebCore/bindings/v8/V8GCController.cpp b/WebCore/bindings/v8/V8GCController.cpp new file mode 100644 index 0000000..1b7c5ad --- /dev/null +++ b/WebCore/bindings/v8/V8GCController.cpp @@ -0,0 +1,442 @@ +/* + * 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: + * + * * 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. + */ + +#include "config.h" +#include "V8GCController.h" + +#include "DOMDataStore.h" +#include "DOMObjectsInclude.h" +#include "V8DOMMap.h" +#include "V8Index.h" +#include "V8Proxy.h" + +#include <algorithm> +#include <utility> +#include <v8.h> +#include <v8-debug.h> +#include <wtf/HashMap.h> +#include <wtf/StdLibExtras.h> +#include <wtf/UnusedParam.h> + +namespace WebCore { + +#ifndef NDEBUG +// Keeps track of global handles created (not JS wrappers +// of DOM objects). Often these global handles are source +// of leaks. +// +// If you want to let a C++ object hold a persistent handle +// to a JS object, you should register the handle here to +// keep track of leaks. +// +// When creating a persistent handle, call: +// +// #ifndef NDEBUG +// V8GCController::registerGlobalHandle(type, host, handle); +// #endif +// +// When releasing the handle, call: +// +// #ifndef NDEBUG +// V8GCController::unregisterGlobalHandle(type, host, handle); +// #endif +// +typedef HashMap<v8::Value*, GlobalHandleInfo*> GlobalHandleMap; + +static GlobalHandleMap& globalHandleMap() +{ + DEFINE_STATIC_LOCAL(GlobalHandleMap, staticGlobalHandleMap, ()); + return staticGlobalHandleMap; +} + +// The function is the place to set the break point to inspect +// live global handles. Leaks are often come from leaked global handles. +static void enumerateGlobalHandles() +{ + for (GlobalHandleMap::iterator it = globalHandleMap().begin(), end = globalHandleMap().end(); it != end; ++it) { + GlobalHandleInfo* info = it->second; + UNUSED_PARAM(info); + v8::Value* handle = it->first; + UNUSED_PARAM(handle); + } +} + +void V8GCController::registerGlobalHandle(GlobalHandleType type, void* host, v8::Persistent<v8::Value> handle) +{ + ASSERT(!globalHandleMap().contains(*handle)); + globalHandleMap().set(*handle, new GlobalHandleInfo(host, type)); +} + +void V8GCController::unregisterGlobalHandle(void* host, v8::Persistent<v8::Value> handle) +{ + ASSERT(globalHandleMap().contains(*handle)); + GlobalHandleInfo* info = globalHandleMap().take(*handle); + ASSERT(info->m_host == host); + delete info; +} +#endif // ifndef NDEBUG + +typedef HashMap<Node*, v8::Object*> DOMNodeMap; +typedef HashMap<void*, v8::Object*> DOMObjectMap; + +#ifndef NDEBUG + +static void enumerateDOMObjectMap(DOMObjectMap& wrapperMap) +{ + for (DOMObjectMap::iterator it = wrapperMap.begin(), end = wrapperMap.end(); it != end; ++it) { + v8::Persistent<v8::Object> wrapper(it->second); + V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper); + void* object = it->first; + UNUSED_PARAM(type); + UNUSED_PARAM(object); + } +} + +class DOMObjectVisitor : public DOMWrapperMap<void>::Visitor { +public: + void visitDOMWrapper(void* object, v8::Persistent<v8::Object> wrapper) + { + V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper); + UNUSED_PARAM(type); + UNUSED_PARAM(object); + } +}; + +class EnsureWeakDOMNodeVisitor : public DOMWrapperMap<Node>::Visitor { +public: + void visitDOMWrapper(Node* object, v8::Persistent<v8::Object> wrapper) + { + UNUSED_PARAM(object); + ASSERT(wrapper.IsWeak()); + } +}; + +#endif // NDEBUG + +// A map from a DOM node to its JS wrapper, the wrapper +// is kept as a strong reference to survive GCs. +static DOMObjectMap& gcProtectedMap() +{ + DEFINE_STATIC_LOCAL(DOMObjectMap, staticGcProtectedMap, ()); + return staticGcProtectedMap; +} + +void V8GCController::gcProtect(void* domObject) +{ + if (!domObject) + return; + if (gcProtectedMap().contains(domObject)) + return; + if (!getDOMObjectMap().contains(domObject)) + return; + + // Create a new (strong) persistent handle for the object. + v8::Persistent<v8::Object> wrapper = getDOMObjectMap().get(domObject); + if (wrapper.IsEmpty()) + return; + + gcProtectedMap().set(domObject, *v8::Persistent<v8::Object>::New(wrapper)); +} + +void V8GCController::gcUnprotect(void* domObject) +{ + if (!domObject) + return; + if (!gcProtectedMap().contains(domObject)) + return; + + // Dispose the strong reference. + v8::Persistent<v8::Object> wrapper(gcProtectedMap().take(domObject)); + wrapper.Dispose(); +} + +class GCPrologueVisitor : public DOMWrapperMap<void>::Visitor { +public: + void visitDOMWrapper(void* object, v8::Persistent<v8::Object> wrapper) + { + ASSERT(wrapper.IsWeak()); + V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper); + switch (type) { +#define MAKE_CASE(TYPE, NAME) \ + case V8ClassIndex::TYPE: { \ + NAME* impl = static_cast<NAME*>(object); \ + if (impl->hasPendingActivity()) \ + wrapper.ClearWeak(); \ + break; \ + } + ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) + default: + ASSERT_NOT_REACHED(); +#undef MAKE_CASE + } + + // Additional handling of message port ensuring that entangled ports also + // have their wrappers entangled. This should ideally be handled when the + // ports are actually entangled in MessagePort::entangle, but to avoid + // forking MessagePort.* this is postponed to GC time. Having this postponed + // has the drawback that the wrappers are "entangled/unentangled" for each + // GC even though their entaglement most likely is still the same. + if (type == V8ClassIndex::MESSAGEPORT) { + // Get the port and its entangled port. + MessagePort* port1 = static_cast<MessagePort*>(object); + MessagePort* port2 = port1->locallyEntangledPort(); + + // If we are remotely entangled, then mark this object as reachable + // (we can't determine reachability directly as the remote object is + // out-of-proc). + if (port1->isEntangled() && !port2) + wrapper.ClearWeak(); + + if (port2) { + // As ports are always entangled in pairs only perform the entanglement + // once for each pair (see ASSERT in MessagePort::unentangle()). + if (port1 < port2) { + v8::Handle<v8::Value> port1Wrapper = V8DOMWrapper::convertToV8Object(V8ClassIndex::MESSAGEPORT, port1); + v8::Handle<v8::Value> port2Wrapper = V8DOMWrapper::convertToV8Object(V8ClassIndex::MESSAGEPORT, port2); + ASSERT(port1Wrapper->IsObject()); + v8::Handle<v8::Object>::Cast(port1Wrapper)->SetInternalField(V8Custom::kMessagePortEntangledPortIndex, port2Wrapper); + ASSERT(port2Wrapper->IsObject()); + v8::Handle<v8::Object>::Cast(port2Wrapper)->SetInternalField(V8Custom::kMessagePortEntangledPortIndex, port1Wrapper); + } + } else { + // Remove the wrapper entanglement when a port is not entangled. + if (V8DOMWrapper::domObjectHasJSWrapper(port1)) { + v8::Handle<v8::Value> wrapper = V8DOMWrapper::convertToV8Object(V8ClassIndex::MESSAGEPORT, port1); + ASSERT(wrapper->IsObject()); + v8::Handle<v8::Object>::Cast(wrapper)->SetInternalField(V8Custom::kMessagePortEntangledPortIndex, v8::Undefined()); + } + } + } +} +}; + +class GrouperItem { +public: + GrouperItem(uintptr_t groupId, Node* node, v8::Persistent<v8::Object> wrapper) + : m_groupId(groupId) + , m_node(node) + , m_wrapper(wrapper) + { + } + + uintptr_t groupId() const { return m_groupId; } + Node* node() const { return m_node; } + v8::Persistent<v8::Object> wrapper() const { return m_wrapper; } + +private: + uintptr_t m_groupId; + Node* m_node; + v8::Persistent<v8::Object> m_wrapper; +}; + +bool operator<(const GrouperItem& a, const GrouperItem& b) +{ + return a.groupId() < b.groupId(); +} + +typedef Vector<GrouperItem> GrouperList; + +class ObjectGrouperVisitor : public DOMWrapperMap<Node>::Visitor { +public: + ObjectGrouperVisitor() + { + // FIXME: grouper_.reserveCapacity(node_map.size()); ? + } + + void visitDOMWrapper(Node* node, v8::Persistent<v8::Object> wrapper) + { + + // If the node is in document, put it in the ownerDocument's object group. + // + // If an image element was created by JavaScript "new Image", + // it is not in a document. However, if the load event has not + // been fired (still onloading), it is treated as in the document. + // + // Otherwise, the node is put in an object group identified by the root + // element of the tree to which it belongs. + uintptr_t groupId; + if (node->inDocument() || (node->hasTagName(HTMLNames::imgTag) && !static_cast<HTMLImageElement*>(node)->haveFiredLoadEvent())) + groupId = reinterpret_cast<uintptr_t>(node->document()); + else { + Node* root = node; + while (root->parent()) + root = root->parent(); + + // If the node is alone in its DOM tree (doesn't have a parent or any + // children) then the group will be filtered out later anyway. + if (root == node && !node->hasChildNodes()) + return; + + groupId = reinterpret_cast<uintptr_t>(root); + } + m_grouper.append(GrouperItem(groupId, node, wrapper)); + } + + void applyGrouping() + { + // Group by sorting by the group id. + std::sort(m_grouper.begin(), m_grouper.end()); + + // FIXME Should probably work in iterators here, but indexes were easier for my simple mind. + for (size_t i = 0; i < m_grouper.size(); ) { + // Seek to the next key (or the end of the list). + size_t nextKeyIndex = m_grouper.size(); + for (size_t j = i; j < m_grouper.size(); ++j) { + if (m_grouper[i].groupId() != m_grouper[j].groupId()) { + nextKeyIndex = j; + break; + } + } + + ASSERT(nextKeyIndex > i); + + // We only care about a group if it has more than one object. If it only + // has one object, it has nothing else that needs to be kept alive. + if (nextKeyIndex - i <= 1) { + i = nextKeyIndex; + continue; + } + + Vector<v8::Persistent<v8::Value> > group; + group.reserveCapacity(nextKeyIndex - i); + for (; i < nextKeyIndex; ++i) { + Node* node = m_grouper[i].node(); + v8::Persistent<v8::Value> wrapper = m_grouper[i].wrapper(); + if (!wrapper.IsEmpty()) + group.append(wrapper); + /* FIXME: Re-enabled this code to avoid GCing these wrappers! + Currently this depends on looking up the wrapper + during a GC, but we don't know which isolated world + we're in, so it's unclear which map to look in... + + // If the node is styled and there is a wrapper for the inline + // style declaration, we need to keep that style declaration + // wrapper alive as well, so we add it to the object group. + if (node->isStyledElement()) { + StyledElement* element = reinterpret_cast<StyledElement*>(node); + CSSStyleDeclaration* style = element->inlineStyleDecl(); + if (style != NULL) { + wrapper = getDOMObjectMap().get(style); + if (!wrapper.IsEmpty()) + group.append(wrapper); + } + } + */ + } + + if (group.size() > 1) + v8::V8::AddObjectGroup(&group[0], group.size()); + + ASSERT(i == nextKeyIndex); + } + } + +private: + GrouperList m_grouper; +}; + +// Create object groups for DOM tree nodes. +void V8GCController::gcPrologue() +{ + v8::HandleScope scope; + +#ifndef NDEBUG + DOMObjectVisitor domObjectVisitor; + visitDOMObjectsInCurrentThread(&domObjectVisitor); +#endif + + // Run through all objects with possible pending activity making their + // wrappers non weak if there is pending activity. + GCPrologueVisitor prologueVisitor; + visitActiveDOMObjectsInCurrentThread(&prologueVisitor); + + // Create object groups. + ObjectGrouperVisitor objectGrouperVisitor; + visitDOMNodesInCurrentThread(&objectGrouperVisitor); + objectGrouperVisitor.applyGrouping(); +} + +class GCEpilogueVisitor : public DOMWrapperMap<void>::Visitor { +public: + void visitDOMWrapper(void* object, v8::Persistent<v8::Object> wrapper) + { + V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper); + switch (type) { +#define MAKE_CASE(TYPE, NAME) \ + case V8ClassIndex::TYPE: { \ + NAME* impl = static_cast<NAME*>(object); \ + if (impl->hasPendingActivity()) { \ + ASSERT(!wrapper.IsWeak()); \ + wrapper.MakeWeak(impl, &DOMDataStore::weakActiveDOMObjectCallback); \ + } \ + break; \ + } +ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) + default: + ASSERT_NOT_REACHED(); +#undef MAKE_CASE + } + + if (type == V8ClassIndex::MESSAGEPORT) { + MessagePort* port1 = static_cast<MessagePort*>(object); + MessagePort* port2 = port1->locallyEntangledPort(); + if (port1->isEntangled() && !port2) { + // We marked this port as reachable in GCPrologueVisitor. Undo this now since the + // port could be not reachable in the future if it gets disentangled (and also + // GCPrologueVisitor expects to see all handles marked as weak). + wrapper.MakeWeak(port1, &DOMDataStore::weakActiveDOMObjectCallback); + } + } + } +}; + +void V8GCController::gcEpilogue() +{ + v8::HandleScope scope; + + // Run through all objects with pending activity making their wrappers weak + // again. + GCEpilogueVisitor epilogueVisitor; + visitActiveDOMObjectsInCurrentThread(&epilogueVisitor); + +#ifndef NDEBUG + // Check all survivals are weak. + DOMObjectVisitor domObjectVisitor; + visitDOMObjectsInCurrentThread(&domObjectVisitor); + + EnsureWeakDOMNodeVisitor weakDOMNodeVisitor; + visitDOMNodesInCurrentThread(&weakDOMNodeVisitor); + + enumerateDOMObjectMap(gcProtectedMap()); + enumerateGlobalHandles(); +#endif +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/V8GCController.h b/WebCore/bindings/v8/V8GCController.h new file mode 100644 index 0000000..7441bf0 --- /dev/null +++ b/WebCore/bindings/v8/V8GCController.h @@ -0,0 +1,85 @@ +/* + * 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: + * + * * 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 V8GCController_h +#define V8GCController_h + +#include <v8.h> + +namespace WebCore { + +#ifndef NDEBUG + +#define GlobalHandleTypeList(V) \ + V(PROXY) \ + V(NPOBJECT) \ + V(SCHEDULED_ACTION) \ + V(EVENT_LISTENER) \ + V(NODE_FILTER) \ + V(SCRIPTINSTANCE) \ + V(SCRIPTVALUE) \ + V(DATASOURCE) + + + // Host information of persistent handles. + enum GlobalHandleType { +#define ENUM(name) name, + GlobalHandleTypeList(ENUM) +#undef ENUM + }; + + class GlobalHandleInfo { + public: + GlobalHandleInfo(void* host, GlobalHandleType type) : m_host(host), m_type(type) { } + void* m_host; + GlobalHandleType m_type; + }; + +#endif // NDEBUG + + class V8GCController { + public: + // Protect/Unprotect JS wrappers of a DOM object. + static void gcProtect(void* domObject); + static void gcUnprotect(void* domObject); + +#ifndef NDEBUG + // For debugging and leak detection purpose. + static void registerGlobalHandle(GlobalHandleType, void*, v8::Persistent<v8::Value>); + static void unregisterGlobalHandle(void*, v8::Persistent<v8::Value>); +#endif + + static void gcPrologue(); + static void gcEpilogue(); + }; + +} + +#endif // V8GCController_h diff --git a/WebCore/bindings/v8/V8Helpers.cpp b/WebCore/bindings/v8/V8Helpers.cpp new file mode 100644 index 0000000..a690017 --- /dev/null +++ b/WebCore/bindings/v8/V8Helpers.cpp @@ -0,0 +1,59 @@ +/* +* Copyright (C) 2008, 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: +* +* * 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. +*/ + +#include "config.h" +#include "V8Helpers.h" + +#include "DOMWindow.h" +#include "NPV8Object.h" +#include "V8Index.h" +#include "V8Proxy.h" + +namespace WebCore { + +void wrapNPObject(v8::Handle<v8::Object> object, NPObject* npObject) +{ + V8DOMWrapper::setDOMWrapper(object, V8ClassIndex::NPOBJECT, npObject); +} + +v8::Local<v8::Context> toV8Context(NPP npp, NPObject* npObject) +{ + V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); + return V8Proxy::mainWorldContext(object->rootObject->frame()); +} + +V8Proxy* toV8Proxy(NPObject* npObject) +{ + V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); + Frame* frame = object->rootObject->frame(); + return V8Proxy::retrieve(frame); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/V8Helpers.h b/WebCore/bindings/v8/V8Helpers.h new file mode 100644 index 0000000..469833e --- /dev/null +++ b/WebCore/bindings/v8/V8Helpers.h @@ -0,0 +1,49 @@ +/* +* Copyright (C) 2006, 2007, 2008, 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: +* +* * 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 V8Helpers_h +#define V8Helpers_h + +#include "npruntime.h" +#include <v8.h> + +namespace WebCore { + class V8Proxy; + + // Associates an NPObject with a V8 object. + void wrapNPObject(v8::Handle<v8::Object>, NPObject*); + + v8::Local<v8::Context> toV8Context(NPP, NPObject*); + + V8Proxy* toV8Proxy(NPObject*); + +} // namespace WebCore + +#endif // V8Helpers_h diff --git a/WebCore/bindings/v8/V8HiddenPropertyName.cpp b/WebCore/bindings/v8/V8HiddenPropertyName.cpp new file mode 100644 index 0000000..16ac232 --- /dev/null +++ b/WebCore/bindings/v8/V8HiddenPropertyName.cpp @@ -0,0 +1,55 @@ +/* + * 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: + * + * * 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. + */ + +#include "config.h" +#include "V8HiddenPropertyName.h" + +namespace WebCore { + +v8::Handle<v8::String> V8HiddenPropertyName::objectPrototype() +{ + static v8::Persistent<v8::String>* string = createString("WebCore::V8HiddenPropertyName::objectPrototype"); + + return *string; +} + +v8::Handle<v8::String> V8HiddenPropertyName::isolatedWorld() +{ + static v8::Persistent<v8::String>* string = createString("WebCore::V8HiddenPropertyName::isolatedWorld"); + + return *string; +} + +v8::Persistent<v8::String>* V8HiddenPropertyName::createString(const char* key) +{ + return new v8::Persistent<v8::String>(v8::Persistent<v8::String>::New(v8::String::NewSymbol(key))); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/V8HiddenPropertyName.h b/WebCore/bindings/v8/V8HiddenPropertyName.h new file mode 100644 index 0000000..874b525 --- /dev/null +++ b/WebCore/bindings/v8/V8HiddenPropertyName.h @@ -0,0 +1,49 @@ +/* + * 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: + * + * * 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 V8HiddenPropertyName_h +#define V8HiddenPropertyName_h + +#include <v8.h> + +namespace WebCore { + + class V8HiddenPropertyName { + public: + static v8::Handle<v8::String> objectPrototype(); + static v8::Handle<v8::String> isolatedWorld(); + + private: + static v8::Persistent<v8::String>* createString(const char* key); + }; + +} + +#endif // V8HiddenPropertyName_h diff --git a/WebCore/bindings/v8/V8Index.cpp b/WebCore/bindings/v8/V8Index.cpp new file mode 100644 index 0000000..8ac3669 --- /dev/null +++ b/WebCore/bindings/v8/V8Index.cpp @@ -0,0 +1,425 @@ +/* + * Copyright (C) 2008, 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: + * + * * 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. + */ + +#include "config.h" +#include "V8Index.h" + +#include "V8Attr.h" +#include "V8BarInfo.h" +#include "V8CanvasRenderingContext2D.h" +#include "V8CanvasGradient.h" +#include "V8CanvasPattern.h" +#include "V8CanvasPixelArray.h" +#include "V8CDATASection.h" +#include "V8CharacterData.h" +#include "V8ClientRect.h" +#include "V8ClientRectList.h" +#include "V8Clipboard.h" +#include "V8Comment.h" +#include "V8Console.h" +#include "V8Counter.h" +#include "V8CSSStyleDeclaration.h" +#include "V8CSSRule.h" +#include "V8CSSStyleRule.h" +#include "V8CSSCharsetRule.h" +#include "V8CSSImportRule.h" +#include "V8CSSMediaRule.h" +#include "V8CSSFontFaceRule.h" +#include "V8CSSPageRule.h" +#include "V8CSSRuleList.h" +#include "V8CSSPrimitiveValue.h" +#include "V8CSSValue.h" +#include "V8CSSValueList.h" +#include "V8CSSStyleSheet.h" +#include "V8CSSVariablesDeclaration.h" +#include "V8CSSVariablesRule.h" +#include "V8DataGridColumn.h" +#include "V8DataGridColumnList.h" +#include "V8Database.h" +#include "V8Document.h" +#include "V8DocumentFragment.h" +#include "V8DocumentType.h" +#include "V8Element.h" +#include "V8Entity.h" +#include "V8EntityReference.h" +#include "V8File.h" +#include "V8FileList.h" +#include "V8History.h" +#include "V8HTMLAllCollection.h" +#include "V8HTMLCanvasElement.h" +#include "V8HTMLCollection.h" +#include "V8HTMLDocument.h" +#include "V8HTMLElement.h" +#include "V8HTMLOptionsCollection.h" +#include "V8HTMLAnchorElement.h" +#include "V8HTMLAppletElement.h" +#include "V8HTMLAreaElement.h" +#include "V8HTMLBaseElement.h" +#include "V8HTMLBaseFontElement.h" +#include "V8HTMLBlockquoteElement.h" +#include "V8HTMLBodyElement.h" +#include "V8HTMLBRElement.h" +#include "V8HTMLButtonElement.h" +#include "V8HTMLCanvasElement.h" +#include "V8HTMLModElement.h" +#include "V8HTMLDataGridCellElement.h" +#include "V8HTMLDataGridColElement.h" +#include "V8HTMLDataGridElement.h" +#include "V8HTMLDataGridRowElement.h" +#include "V8HTMLDirectoryElement.h" +#include "V8HTMLDivElement.h" +#include "V8HTMLDListElement.h" +#include "V8HTMLEmbedElement.h" +#include "V8HTMLFieldSetElement.h" +#include "V8HTMLFormElement.h" +#include "V8HTMLFontElement.h" +#include "V8HTMLFrameElement.h" +#include "V8HTMLFrameSetElement.h" +#include "V8HTMLHeadingElement.h" +#include "V8HTMLHeadElement.h" +#include "V8HTMLHRElement.h" +#include "V8HTMLHtmlElement.h" +#include "V8HTMLIFrameElement.h" +#include "V8HTMLImageElement.h" +#include "V8HTMLInputElement.h" +#include "V8HTMLIsIndexElement.h" +#include "V8HTMLLabelElement.h" +#include "V8HTMLLegendElement.h" +#include "V8HTMLLIElement.h" +#include "V8HTMLLinkElement.h" +#include "V8HTMLMapElement.h" +#include "V8HTMLMarqueeElement.h" +#include "V8HTMLMenuElement.h" +#include "V8HTMLMetaElement.h" +#include "V8HTMLObjectElement.h" +#include "V8HTMLOListElement.h" +#include "V8HTMLOptGroupElement.h" +#include "V8HTMLOptionElement.h" +#include "V8HTMLParagraphElement.h" +#include "V8HTMLParamElement.h" +#include "V8HTMLPreElement.h" +#include "V8HTMLQuoteElement.h" +#include "V8HTMLScriptElement.h" +#include "V8HTMLSelectElement.h" +#include "V8HTMLStyleElement.h" +#include "V8HTMLTableCaptionElement.h" +#include "V8HTMLTableColElement.h" +#include "V8HTMLTableElement.h" +#include "V8HTMLTableSectionElement.h" +#include "V8HTMLTableCellElement.h" +#include "V8HTMLTableRowElement.h" +#include "V8HTMLTextAreaElement.h" +#include "V8HTMLTitleElement.h" +#include "V8HTMLUListElement.h" +#include "V8ImageData.h" +#include "V8InspectorBackend.h" +#include "V8Media.h" +#include "V8MediaList.h" +#include "V8MessageChannel.h" +#include "V8MessageEvent.h" +#include "V8MessagePort.h" +#include "V8NamedNodeMap.h" +#include "V8Node.h" +#include "V8NodeList.h" +#include "V8NodeFilter.h" +#include "V8Notation.h" +#include "V8ProcessingInstruction.h" +#include "V8ProgressEvent.h" +#include "V8StyleSheet.h" +#include "V8Text.h" +#include "V8TextEvent.h" +#include "V8DOMCoreException.h" +#include "V8DOMParser.h" +#include "V8DOMWindow.h" +#include "V8ErrorEvent.h" +#include "V8Event.h" +#include "V8EventException.h" +#include "V8KeyboardEvent.h" +#include "V8MouseEvent.h" +#include "V8ValidityState.h" +#include "V8WebKitAnimationEvent.h" +#include "V8WebKitCSSKeyframeRule.h" +#include "V8WebKitCSSKeyframesRule.h" +#include "V8WebKitCSSMatrix.h" +#include "V8WebKitCSSTransformValue.h" +#include "V8WebKitPoint.h" +#include "V8WebKitTransitionEvent.h" +#include "V8WheelEvent.h" +#include "V8UIEvent.h" +#include "V8MutationEvent.h" +#include "V8OverflowEvent.h" +#include "V8Location.h" +#include "V8Screen.h" +#include "V8DOMSelection.h" +#include "V8Navigator.h" +#include "V8MimeType.h" +#include "V8MimeTypeArray.h" +#include "V8Plugin.h" +#include "V8PluginArray.h" +#include "V8Range.h" +#include "V8RangeException.h" +#include "V8Rect.h" +#include "V8SQLError.h" +#include "V8SQLResultSet.h" +#include "V8SQLResultSetRowList.h" +#include "V8SQLTransaction.h" +#include "V8NodeIterator.h" +#include "V8TextMetrics.h" +#include "V8TreeWalker.h" +#include "V8StyleSheetList.h" +#include "V8DOMImplementation.h" +#include "V8XPathResult.h" +#include "V8XPathException.h" +#include "V8XPathExpression.h" +#include "V8XPathNSResolver.h" +#include "V8XMLHttpRequest.h" +#include "V8XMLHttpRequestException.h" +#include "V8XMLHttpRequestProgressEvent.h" +#include "V8XMLHttpRequestUpload.h" +#include "V8XMLSerializer.h" +#include "V8XPathEvaluator.h" +#include "V8XSLTProcessor.h" +#include "V8RGBColor.h" + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +#include "V8DOMApplicationCache.h" +#endif + +#if ENABLE(DOM_STORAGE) +#include "V8Storage.h" +#include "V8StorageEvent.h" +#endif + +#if ENABLE(SVG_ANIMATION) +#include "V8SVGAnimateColorElement.h" +#include "V8SVGAnimateElement.h" +#include "V8SVGAnimateTransformElement.h" +#include "V8SVGAnimationElement.h" +#include "V8SVGSetElement.h" +#endif + +#if ENABLE(SVG_FILTERS) +#include "V8SVGComponentTransferFunctionElement.h" +#include "V8SVGFEBlendElement.h" +#include "V8SVGFEColorMatrixElement.h" +#include "V8SVGFEComponentTransferElement.h" +#include "V8SVGFECompositeElement.h" +#include "V8SVGFEDiffuseLightingElement.h" +#include "V8SVGFEDisplacementMapElement.h" +#include "V8SVGFEDistantLightElement.h" +#include "V8SVGFEFloodElement.h" +#include "V8SVGFEFuncAElement.h" +#include "V8SVGFEFuncBElement.h" +#include "V8SVGFEFuncGElement.h" +#include "V8SVGFEFuncRElement.h" +#include "V8SVGFEGaussianBlurElement.h" +#include "V8SVGFEImageElement.h" +#include "V8SVGFEMergeElement.h" +#include "V8SVGFEMergeNodeElement.h" +#include "V8SVGFEOffsetElement.h" +#include "V8SVGFEPointLightElement.h" +#include "V8SVGFESpecularLightingElement.h" +#include "V8SVGFESpotLightElement.h" +#include "V8SVGFETileElement.h" +#include "V8SVGFETurbulenceElement.h" +#include "V8SVGFilterElement.h" +#endif + +#if ENABLE(SVG_FONTS) +#include "V8SVGDefinitionSrcElement.h" +#include "V8SVGFontFaceElement.h" +#include "V8SVGFontFaceFormatElement.h" +#include "V8SVGFontFaceNameElement.h" +#include "V8SVGFontFaceSrcElement.h" +#include "V8SVGFontFaceUriElement.h" +#endif + +#if ENABLE(SVG_FOREIGN_OBJECT) +#include "V8SVGForeignObjectElement.h" +#endif + +#if ENABLE(SVG_USE) +#include "V8SVGUseElement.h" +#endif + +#if ENABLE(SVG) +#include "V8SVGAElement.h" +#include "V8SVGAltGlyphElement.h" +#include "V8SVGCircleElement.h" +#include "V8SVGClipPathElement.h" +#include "V8SVGCursorElement.h" +#include "V8SVGDefsElement.h" +#include "V8SVGDescElement.h" +#include "V8SVGElement.h" +#include "V8SVGEllipseElement.h" +#include "V8SVGException.h" +#include "V8SVGGElement.h" +#include "V8SVGGlyphElement.h" +#include "V8SVGGradientElement.h" +#include "V8SVGImageElement.h" +#include "V8SVGLinearGradientElement.h" +#include "V8SVGLineElement.h" +#include "V8SVGMarkerElement.h" +#include "V8SVGMaskElement.h" +#include "V8SVGMetadataElement.h" +#include "V8SVGPathElement.h" +#include "V8SVGPatternElement.h" +#include "V8SVGPolygonElement.h" +#include "V8SVGPolylineElement.h" +#include "V8SVGRadialGradientElement.h" +#include "V8SVGRectElement.h" +#include "V8SVGScriptElement.h" +#include "V8SVGStopElement.h" +#include "V8SVGStyleElement.h" +#include "V8SVGSVGElement.h" +#include "V8SVGSwitchElement.h" +#include "V8SVGSymbolElement.h" +#include "V8SVGTextContentElement.h" +#include "V8SVGTextElement.h" +#include "V8SVGTextPathElement.h" +#include "V8SVGTextPositioningElement.h" +#include "V8SVGTitleElement.h" +#include "V8SVGTRefElement.h" +#include "V8SVGTSpanElement.h" +#include "V8SVGViewElement.h" +#include "V8SVGAngle.h" +#include "V8SVGAnimatedAngle.h" +#include "V8SVGAnimatedBoolean.h" +#include "V8SVGAnimatedEnumeration.h" +#include "V8SVGAnimatedInteger.h" +#include "V8SVGAnimatedLength.h" +#include "V8SVGAnimatedLengthList.h" +#include "V8SVGAnimatedNumber.h" +#include "V8SVGAnimatedNumberList.h" +#include "V8SVGAnimatedPoints.h" +#include "V8SVGAnimatedPreserveAspectRatio.h" +#include "V8SVGAnimatedRect.h" +#include "V8SVGAnimatedString.h" +#include "V8SVGAnimatedTransformList.h" +#include "V8SVGColor.h" +#include "V8SVGDocument.h" +#include "V8SVGElementInstance.h" +#include "V8SVGElementInstanceList.h" +#include "V8SVGLength.h" +#include "V8SVGLengthList.h" +#include "V8SVGMatrix.h" +#include "V8SVGNumber.h" +#include "V8SVGNumberList.h" +#include "V8SVGPaint.h" +#include "V8SVGPathSeg.h" +#include "V8SVGPathSegArcAbs.h" +#include "V8SVGPathSegArcRel.h" +#include "V8SVGPathSegClosePath.h" +#include "V8SVGPathSegCurvetoCubicAbs.h" +#include "V8SVGPathSegCurvetoCubicRel.h" +#include "V8SVGPathSegCurvetoCubicSmoothAbs.h" +#include "V8SVGPathSegCurvetoCubicSmoothRel.h" +#include "V8SVGPathSegCurvetoQuadraticAbs.h" +#include "V8SVGPathSegCurvetoQuadraticRel.h" +#include "V8SVGPathSegCurvetoQuadraticSmoothAbs.h" +#include "V8SVGPathSegCurvetoQuadraticSmoothRel.h" +#include "V8SVGPathSegLinetoAbs.h" +#include "V8SVGPathSegLinetoHorizontalAbs.h" +#include "V8SVGPathSegLinetoHorizontalRel.h" +#include "V8SVGPathSegLinetoRel.h" +#include "V8SVGPathSegLinetoVerticalAbs.h" +#include "V8SVGPathSegLinetoVerticalRel.h" +#include "V8SVGPathSegList.h" +#include "V8SVGPathSegMovetoAbs.h" +#include "V8SVGPathSegMovetoRel.h" +#include "V8SVGPoint.h" +#include "V8SVGPointList.h" +#include "V8SVGPreserveAspectRatio.h" +#include "V8SVGRect.h" +#include "V8SVGRenderingIntent.h" +#include "V8SVGStringList.h" +#include "V8SVGTransform.h" +#include "V8SVGTransformList.h" +#include "V8SVGUnitTypes.h" +#include "V8SVGURIReference.h" +#include "V8SVGZoomEvent.h" +#endif + +#if ENABLE(VIDEO) +#include "V8HTMLAudioElement.h" +#include "V8HTMLMediaElement.h" +#include "V8HTMLSourceElement.h" +#include "V8HTMLVideoElement.h" +#include "V8MediaError.h" +#include "V8TimeRanges.h" +#endif + +#if ENABLE(WORKERS) +#include "V8AbstractWorker.h" +#include "V8DedicatedWorkerContext.h" +#include "V8Worker.h" +#include "V8WorkerContext.h" +#include "V8WorkerLocation.h" +#include "V8WorkerNavigator.h" +#endif + +#if ENABLE(SHARED_WORKERS) +#include "V8SharedWorker.h" +#endif + +namespace WebCore { + +FunctionTemplateFactory V8ClassIndex::GetFactory(V8WrapperType type) +{ + switch (type) { +#define MAKE_CASE(type, name)\ + case V8ClassIndex::type: return V8##name::GetTemplate; + WRAPPER_TYPES(MAKE_CASE) +#undef MAKE_CASE + default: return NULL; + } +} + + +#define MAKE_CACHE(type, name)\ + static v8::Persistent<v8::FunctionTemplate> name##_cache_; + ALL_WRAPPER_TYPES(MAKE_CACHE) +#undef MAKE_CACHE + + +v8::Persistent<v8::FunctionTemplate>* V8ClassIndex::GetCache(V8WrapperType type) +{ + switch (type) { +#define MAKE_CASE(type, name)\ + case V8ClassIndex::type: return &name##_cache_; + ALL_WRAPPER_TYPES(MAKE_CASE) +#undef MAKE_CASE + default: + ASSERT(false); + return NULL; + } +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/V8Index.h b/WebCore/bindings/v8/V8Index.h index 58af42e..d81537d 100644 --- a/WebCore/bindings/v8/V8Index.h +++ b/WebCore/bindings/v8/V8Index.h @@ -31,8 +31,537 @@ #ifndef V8Index_h #define V8Index_h -// FIXME: This is a temporary forwarding header until all bindings have migrated -// over and v8_index actually becomes V8Index. -#include "v8_index.h" +#include <v8.h> +#include "PlatformString.h" // for WebCore::String + +namespace WebCore { + +typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); + +#if ENABLE(DATAGRID) +#define DATAGRID_HTMLELEMENT_TYPES(V) \ + V(HTMLDATAGRIDCELLELEMENT, HTMLDataGridCellElement) \ + V(HTMLDATAGRIDCOLELEMENT, HTMLDataGridColElement) \ + V(HTMLDATAGRIDELEMENT, HTMLDataGridElement) \ + V(HTMLDATAGRIDROWELEMENT, HTMLDataGridRowElement) +#define DATAGRID_NONNODE_TYPES(V) \ + V(DATAGRIDCOLUMN, DataGridColumn) \ + V(DATAGRIDCOLUMNLIST, DataGridColumnList) +#else +#define DATAGRID_HTMLELEMENT_TYPES(V) +#define DATAGRID_NONNODE_TYPES(V) +#endif + +#if ENABLE(VIDEO) +#define VIDEO_HTMLELEMENT_TYPES(V) \ + V(HTMLAUDIOELEMENT, HTMLAudioElement) \ + V(HTMLMEDIAELEMENT, HTMLMediaElement) \ + V(HTMLSOURCEELEMENT, HTMLSourceElement) \ + V(HTMLVIDEOELEMENT, HTMLVideoElement) +#define VIDEO_NONNODE_TYPES(V) \ + V(MEDIAERROR, MediaError) \ + V(TIMERANGES, TimeRanges) +#else +#define VIDEO_HTMLELEMENT_TYPES(V) +#define VIDEO_NONNODE_TYPES(V) +#endif + +#if ENABLE(WORKERS) +#define WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V) \ + V(WORKER, Worker) + +#define WORKER_NONNODE_WRAPPER_TYPES(V) \ + V(ABSTRACTWORKER, AbstractWorker) \ + V(DEDICATEDWORKERCONTEXT, DedicatedWorkerContext) \ + V(WORKERCONTEXT, WorkerContext) \ + V(WORKERLOCATION, WorkerLocation) \ + V(WORKERNAVIGATOR, WorkerNavigator) +#else +#define WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V) +#define WORKER_NONNODE_WRAPPER_TYPES(V) +#endif + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +#define APPLICATIONCACHE_NONNODE_WRAPPER_TYPES(V) \ + V(DOMAPPLICATIONCACHE, DOMApplicationCache) +#else +#define APPLICATIONCACHE_NONNODE_WRAPPER_TYPES(V) +#endif + +#if ENABLE(SHARED_WORKERS) +#define SHARED_WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V) \ + V(SHAREDWORKER, SharedWorker) +#define SHARED_WORKER_NONNODE_WRAPPER_TYPES(V) +#else +#define SHARED_WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V) +#define SHARED_WORKER_NONNODE_WRAPPER_TYPES(V) +#endif + +#define DOM_NODE_TYPES(V) \ + V(ATTR, Attr) \ + V(CHARACTERDATA, CharacterData) \ + V(CDATASECTION, CDATASection) \ + V(COMMENT, Comment) \ + V(DOCUMENT, Document) \ + V(DOCUMENTFRAGMENT, DocumentFragment) \ + V(DOCUMENTTYPE, DocumentType) \ + V(ELEMENT, Element) \ + V(ENTITY, Entity) \ + V(ENTITYREFERENCE, EntityReference) \ + V(HTMLDOCUMENT, HTMLDocument) \ + V(NODE, Node) \ + V(NOTATION, Notation) \ + V(PROCESSINGINSTRUCTION, ProcessingInstruction) \ + V(TEXT, Text) \ + V(HTMLANCHORELEMENT, HTMLAnchorElement) \ + V(HTMLAPPLETELEMENT, HTMLAppletElement) \ + V(HTMLAREAELEMENT, HTMLAreaElement) \ + V(HTMLBASEELEMENT, HTMLBaseElement) \ + V(HTMLBASEFONTELEMENT, HTMLBaseFontElement) \ + V(HTMLBLOCKQUOTEELEMENT, HTMLBlockquoteElement) \ + V(HTMLBODYELEMENT, HTMLBodyElement) \ + V(HTMLBRELEMENT, HTMLBRElement) \ + V(HTMLBUTTONELEMENT, HTMLButtonElement) \ + V(HTMLCANVASELEMENT, HTMLCanvasElement) \ + V(HTMLDIRECTORYELEMENT, HTMLDirectoryElement) \ + V(HTMLDIVELEMENT, HTMLDivElement) \ + V(HTMLDLISTELEMENT, HTMLDListElement) \ + V(HTMLEMBEDELEMENT, HTMLEmbedElement) \ + V(HTMLFIELDSETELEMENT, HTMLFieldSetElement) \ + V(HTMLFONTELEMENT, HTMLFontElement) \ + V(HTMLFORMELEMENT, HTMLFormElement) \ + V(HTMLFRAMEELEMENT, HTMLFrameElement) \ + V(HTMLFRAMESETELEMENT, HTMLFrameSetElement) \ + V(HTMLHEADINGELEMENT, HTMLHeadingElement) \ + V(HTMLHEADELEMENT, HTMLHeadElement) \ + V(HTMLHRELEMENT, HTMLHRElement) \ + V(HTMLHTMLELEMENT, HTMLHtmlElement) \ + V(HTMLIFRAMEELEMENT, HTMLIFrameElement) \ + V(HTMLIMAGEELEMENT, HTMLImageElement) \ + V(HTMLINPUTELEMENT, HTMLInputElement) \ + V(HTMLISINDEXELEMENT, HTMLIsIndexElement) \ + V(HTMLLABELELEMENT, HTMLLabelElement) \ + V(HTMLLEGENDELEMENT, HTMLLegendElement) \ + V(HTMLLIELEMENT, HTMLLIElement) \ + V(HTMLLINKELEMENT, HTMLLinkElement) \ + V(HTMLMAPELEMENT, HTMLMapElement) \ + V(HTMLMARQUEEELEMENT, HTMLMarqueeElement) \ + V(HTMLMENUELEMENT, HTMLMenuElement) \ + V(HTMLMETAELEMENT, HTMLMetaElement) \ + V(HTMLMODELEMENT, HTMLModElement) \ + V(HTMLOBJECTELEMENT, HTMLObjectElement) \ + V(HTMLOLISTELEMENT, HTMLOListElement) \ + V(HTMLOPTGROUPELEMENT, HTMLOptGroupElement) \ + V(HTMLOPTIONELEMENT, HTMLOptionElement) \ + V(HTMLPARAGRAPHELEMENT, HTMLParagraphElement) \ + V(HTMLPARAMELEMENT, HTMLParamElement) \ + V(HTMLPREELEMENT, HTMLPreElement) \ + V(HTMLQUOTEELEMENT, HTMLQuoteElement) \ + V(HTMLSCRIPTELEMENT, HTMLScriptElement) \ + V(HTMLSELECTELEMENT, HTMLSelectElement) \ + V(HTMLSTYLEELEMENT, HTMLStyleElement) \ + V(HTMLTABLECAPTIONELEMENT, HTMLTableCaptionElement) \ + V(HTMLTABLECOLELEMENT, HTMLTableColElement) \ + V(HTMLTABLEELEMENT, HTMLTableElement) \ + V(HTMLTABLESECTIONELEMENT, HTMLTableSectionElement) \ + V(HTMLTABLECELLELEMENT, HTMLTableCellElement) \ + V(HTMLTABLEROWELEMENT, HTMLTableRowElement) \ + V(HTMLTEXTAREAELEMENT, HTMLTextAreaElement) \ + V(HTMLTITLEELEMENT, HTMLTitleElement) \ + V(HTMLULISTELEMENT, HTMLUListElement) \ + V(HTMLELEMENT, HTMLElement) \ + DATAGRID_HTMLELEMENT_TYPES(V) \ + VIDEO_HTMLELEMENT_TYPES(V) + +#if ENABLE(SVG_ANIMATION) +#define SVG_ANIMATION_ELEMENT_TYPES(V) \ + V(SVGANIMATECOLORELEMENT, SVGAnimateColorElement) \ + V(SVGANIMATEELEMENT, SVGAnimateElement) \ + V(SVGANIMATETRANSFORMELEMENT, SVGAnimateTransformElement) \ + V(SVGANIMATIONELEMENT, SVGAnimationElement) \ + V(SVGSETELEMENT, SVGSetElement) +#else +#define SVG_ANIMATION_ELEMENT_TYPES(V) +#endif + +#if ENABLE(SVG_FILTERS) +#define SVG_FILTERS_ELEMENT_TYPES(V) \ + V(SVGCOMPONENTTRANSFERFUNCTIONELEMENT, SVGComponentTransferFunctionElement)\ + V(SVGFEBLENDELEMENT, SVGFEBlendElement) \ + V(SVGFECOLORMATRIXELEMENT, SVGFEColorMatrixElement) \ + V(SVGFECOMPONENTTRANSFERELEMENT, SVGFEComponentTransferElement) \ + V(SVGFECOMPOSITEELEMENT, SVGFECompositeElement) \ + V(SVGFEDIFFUSELIGHTINGELEMENT, SVGFEDiffuseLightingElement) \ + V(SVGFEDISPLACEMENTMAPELEMENT, SVGFEDisplacementMapElement) \ + V(SVGFEDISTANTLIGHTELEMENT, SVGFEDistantLightElement) \ + V(SVGFEFLOODELEMENT, SVGFEFloodElement) \ + V(SVGFEFUNCAELEMENT, SVGFEFuncAElement) \ + V(SVGFEFUNCBELEMENT, SVGFEFuncBElement) \ + V(SVGFEFUNCGELEMENT, SVGFEFuncGElement) \ + V(SVGFEFUNCRELEMENT, SVGFEFuncRElement) \ + V(SVGFEGAUSSIANBLURELEMENT, SVGFEGaussianBlurElement) \ + V(SVGFEIMAGEELEMENT, SVGFEImageElement) \ + V(SVGFEMERGEELEMENT, SVGFEMergeElement) \ + V(SVGFEMERGENODEELEMENT, SVGFEMergeNodeElement) \ + V(SVGFEOFFSETELEMENT, SVGFEOffsetElement) \ + V(SVGFEPOINTLIGHTELEMENT, SVGFEPointLightElement) \ + V(SVGFESPECULARLIGHTINGELEMENT, SVGFESpecularLightingElement) \ + V(SVGFESPOTLIGHTELEMENT, SVGFESpotLightElement) \ + V(SVGFETILEELEMENT, SVGFETileElement) \ + V(SVGFETURBULENCEELEMENT, SVGFETurbulenceElement) \ + V(SVGFILTERELEMENT, SVGFilterElement) +#else +#define SVG_FILTERS_ELEMENT_TYPES(V) +#endif + +#if ENABLE(SVG_FONTS) +#define SVG_FONTS_ELEMENT_TYPES(V) \ + V(SVGDEFINITIONSRCELEMENT, SVGDefinitionSrcElement) \ + V(SVGFONTFACEELEMENT, SVGFontFaceElement) \ + V(SVGFONTFACEFORMATELEMENT, SVGFontFaceFormatElement) \ + V(SVGFONTFACENAMEELEMENT, SVGFontFaceNameElement) \ + V(SVGFONTFACESRCELEMENT, SVGFontFaceSrcElement) \ + V(SVGFONTFACEURIELEMENT, SVGFontFaceUriElement) +#else +#define SVG_FONTS_ELEMENT_TYPES(V) +#endif + +#if ENABLE(SVG_FOREIGN_OBJECT) +#define SVG_FOREIGN_OBJECT_ELEMENT_TYPES(V) \ + V(SVGFOREIGNOBJECTELEMENT, SVGForeignObjectElement) +#else +#define SVG_FOREIGN_OBJECT_ELEMENT_TYPES(V) +#endif + +#if ENABLE(SVG_USE) +#define SVG_USE_ELEMENT_TYPES(V) \ + V(SVGUSEELEMENT, SVGUseElement) +#else +#define SVG_USE_ELEMENT_TYPES(V) +#endif + +#if ENABLE(SVG) +#define SVG_NODE_TYPES(V) \ + SVG_ANIMATION_ELEMENT_TYPES(V) \ + SVG_FILTERS_ELEMENT_TYPES(V) \ + SVG_FONTS_ELEMENT_TYPES(V) \ + SVG_FOREIGN_OBJECT_ELEMENT_TYPES(V) \ + SVG_USE_ELEMENT_TYPES(V) \ + V(SVGAELEMENT, SVGAElement) \ + V(SVGALTGLYPHELEMENT, SVGAltGlyphElement) \ + V(SVGCIRCLEELEMENT, SVGCircleElement) \ + V(SVGCLIPPATHELEMENT, SVGClipPathElement) \ + V(SVGCURSORELEMENT, SVGCursorElement) \ + V(SVGDEFSELEMENT, SVGDefsElement) \ + V(SVGDESCELEMENT, SVGDescElement) \ + V(SVGELLIPSEELEMENT, SVGEllipseElement) \ + V(SVGGELEMENT, SVGGElement) \ + V(SVGGLYPHELEMENT, SVGGlyphElement) \ + V(SVGGRADIENTELEMENT, SVGGradientElement) \ + V(SVGIMAGEELEMENT, SVGImageElement) \ + V(SVGLINEARGRADIENTELEMENT, SVGLinearGradientElement) \ + V(SVGLINEELEMENT, SVGLineElement) \ + V(SVGMARKERELEMENT, SVGMarkerElement) \ + V(SVGMASKELEMENT, SVGMaskElement) \ + V(SVGMETADATAELEMENT, SVGMetadataElement) \ + V(SVGPATHELEMENT, SVGPathElement) \ + V(SVGPATTERNELEMENT, SVGPatternElement) \ + V(SVGPOLYGONELEMENT, SVGPolygonElement) \ + V(SVGPOLYLINEELEMENT, SVGPolylineElement) \ + V(SVGRADIALGRADIENTELEMENT, SVGRadialGradientElement) \ + V(SVGRECTELEMENT, SVGRectElement) \ + V(SVGSCRIPTELEMENT, SVGScriptElement) \ + V(SVGSTOPELEMENT, SVGStopElement) \ + V(SVGSTYLEELEMENT, SVGStyleElement) \ + V(SVGSVGELEMENT, SVGSVGElement) \ + V(SVGSWITCHELEMENT, SVGSwitchElement) \ + V(SVGSYMBOLELEMENT, SVGSymbolElement) \ + V(SVGTEXTCONTENTELEMENT, SVGTextContentElement) \ + V(SVGTEXTELEMENT, SVGTextElement) \ + V(SVGTEXTPATHELEMENT, SVGTextPathElement) \ + V(SVGTEXTPOSITIONINGELEMENT, SVGTextPositioningElement) \ + V(SVGTITLEELEMENT, SVGTitleElement) \ + V(SVGTREFELEMENT, SVGTRefElement) \ + V(SVGTSPANELEMENT, SVGTSpanElement) \ + V(SVGVIEWELEMENT, SVGViewElement) \ + V(SVGELEMENT, SVGElement) \ + V(SVGDOCUMENT, SVGDocument) +#endif // SVG + + +// ACTIVE_DOM_OBJECT_TYPES are DOM_OBJECT_TYPES that need special treatement +// during GC. +#define ACTIVE_DOM_OBJECT_TYPES(V) \ + V(MESSAGEPORT, MessagePort) \ + V(XMLHTTPREQUEST, XMLHttpRequest) \ + WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V) \ + SHARED_WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V) + +// NOTE: DOM_OBJECT_TYPES is split into two halves because +// Visual Studio's Intellinonsense crashes when macros get +// too large. 10-29-08 +// DOM_OBJECT_TYPES are non-node DOM types. +#define DOM_OBJECT_TYPES_1(V) \ + V(BARINFO, BarInfo) \ + V(CANVASGRADIENT, CanvasGradient) \ + V(CANVASPATTERN, CanvasPattern) \ + V(CANVASRENDERINGCONTEXT2D, CanvasRenderingContext2D) \ + V(CLIENTRECT, ClientRect) \ + V(CLIENTRECTLIST, ClientRectList) \ + V(CLIPBOARD, Clipboard) \ + V(CONSOLE, Console) \ + V(COUNTER, Counter) \ + V(CSSCHARSETRULE, CSSCharsetRule) \ + V(CSSFONTFACERULE, CSSFontFaceRule) \ + V(CSSIMPORTRULE, CSSImportRule) \ + V(CSSMEDIARULE, CSSMediaRule) \ + V(CSSPAGERULE, CSSPageRule) \ + V(CSSPRIMITIVEVALUE, CSSPrimitiveValue) \ + V(CSSRULE, CSSRule) \ + V(CSSRULELIST, CSSRuleList) \ + V(CSSSTYLEDECLARATION, CSSStyleDeclaration) \ + V(CSSSTYLERULE, CSSStyleRule) \ + V(CSSSTYLESHEET, CSSStyleSheet) \ + V(CSSVALUE, CSSValue) \ + V(CSSVALUELIST, CSSValueList) \ + V(CSSVARIABLESDECLARATION, CSSVariablesDeclaration) \ + V(CSSVARIABLESRULE, CSSVariablesRule) \ + V(DOMCOREEXCEPTION, DOMCoreException) \ + V(DOMIMPLEMENTATION, DOMImplementation) \ + V(DOMPARSER, DOMParser) \ + V(DOMSELECTION, DOMSelection) \ + V(DOMWINDOW, DOMWindow) \ + V(EVENT, Event) \ + V(EVENTEXCEPTION, EventException) \ + V(FILE, File) \ + V(FILELIST, FileList) \ + V(HISTORY, History) \ + V(HTMLALLCOLLECTION, HTMLAllCollection) \ + V(HTMLCOLLECTION, HTMLCollection) \ + V(HTMLOPTIONSCOLLECTION, HTMLOptionsCollection) \ + V(IMAGEDATA, ImageData) \ + V(CANVASPIXELARRAY, CanvasPixelArray) \ + V(INSPECTORBACKEND, InspectorBackend) \ + V(KEYBOARDEVENT, KeyboardEvent) \ + V(LOCATION, Location) \ + V(MEDIA, Media) \ + V(MEDIALIST, MediaList) + +#define DOM_OBJECT_TYPES_2(V) \ + V(MESSAGECHANNEL, MessageChannel) \ + V(MESSAGEEVENT, MessageEvent) \ + V(MIMETYPE, MimeType) \ + V(MIMETYPEARRAY, MimeTypeArray) \ + V(MOUSEEVENT, MouseEvent) \ + V(MUTATIONEVENT, MutationEvent) \ + V(NAMEDNODEMAP, NamedNodeMap) \ + V(NAVIGATOR, Navigator) \ + V(NODEFILTER, NodeFilter) \ + V(NODEITERATOR, NodeIterator) \ + V(NODELIST, NodeList) \ + V(OVERFLOWEVENT, OverflowEvent) \ + V(PLUGIN, Plugin) \ + V(PLUGINARRAY, PluginArray) \ + V(PROGRESSEVENT, ProgressEvent) \ + V(RANGE, Range) \ + V(RANGEEXCEPTION, RangeException) \ + V(RECT, Rect) \ + V(RGBCOLOR, RGBColor) \ + V(SCREEN, Screen) \ + V(STYLESHEET, StyleSheet) \ + V(STYLESHEETLIST, StyleSheetList) \ + V(TEXTEVENT, TextEvent) \ + V(TEXTMETRICS, TextMetrics) \ + V(TREEWALKER, TreeWalker) \ + V(UIEVENT, UIEvent) \ + V(VALIDITYSTATE, ValidityState) \ + V(WEBKITANIMATIONEVENT, WebKitAnimationEvent) \ + V(WEBKITCSSKEYFRAMERULE, WebKitCSSKeyframeRule) \ + V(WEBKITCSSKEYFRAMESRULE, WebKitCSSKeyframesRule) \ + V(WEBKITCSSMATRIX, WebKitCSSMatrix) \ + V(WEBKITPOINT, WebKitPoint) \ + V(WEBKITCSSTRANSFORMVALUE, WebKitCSSTransformValue) \ + V(WEBKITTRANSITIONEVENT, WebKitTransitionEvent) \ + V(WHEELEVENT, WheelEvent) \ + V(XMLHTTPREQUESTUPLOAD, XMLHttpRequestUpload) \ + V(XMLHTTPREQUESTEXCEPTION, XMLHttpRequestException) \ + V(XMLHTTPREQUESTPROGRESSEVENT, XMLHttpRequestProgressEvent) \ + V(XMLSERIALIZER, XMLSerializer) \ + V(XPATHEVALUATOR, XPathEvaluator) \ + V(XPATHEXCEPTION, XPathException) \ + V(XPATHEXPRESSION, XPathExpression) \ + V(XPATHNSRESOLVER, XPathNSResolver) \ + V(XPATHRESULT, XPathResult) \ + V(XSLTPROCESSOR, XSLTProcessor) \ + ACTIVE_DOM_OBJECT_TYPES(V) \ + APPLICATIONCACHE_NONNODE_WRAPPER_TYPES(V) \ + DATAGRID_NONNODE_TYPES(V) \ + VIDEO_NONNODE_TYPES(V) \ + SHARED_WORKER_NONNODE_WRAPPER_TYPES(V) \ + WORKER_NONNODE_WRAPPER_TYPES(V) + +#if ENABLE(DATABASE) +#define DOM_OBJECT_DATABASE_TYPES(V) \ + V(DATABASE, Database) \ + V(SQLERROR, SQLError) \ + V(SQLRESULTSET, SQLResultSet) \ + V(SQLRESULTSETROWLIST, SQLResultSetRowList) \ + V(SQLTRANSACTION, SQLTransaction) +#else +#define DOM_OBJECT_DATABASE_TYPES(V) +#endif + +#if ENABLE(DOM_STORAGE) +#define DOM_OBJECT_STORAGE_TYPES(V) \ + V(STORAGE, Storage) \ + V(STORAGEEVENT, StorageEvent) +#else +#define DOM_OBJECT_STORAGE_TYPES(V) +#endif + +#if ENABLE(WORKERS) +#define DOM_OBJECT_WORKERS_TYPES(V) \ + V(ERROREVENT, ErrorEvent) +#else +#define DOM_OBJECT_WORKERS_TYPES(V) +#endif + +#define DOM_OBJECT_TYPES(V) \ + DOM_OBJECT_TYPES_1(V) \ + DOM_OBJECT_TYPES_2(V) \ + DOM_OBJECT_DATABASE_TYPES(V) \ + DOM_OBJECT_STORAGE_TYPES(V) \ + DOM_OBJECT_WORKERS_TYPES(V) + +#if ENABLE(SVG) +// SVG_OBJECT_TYPES are svg non-node, non-pod types. +#define SVG_OBJECT_TYPES(V) \ + V(SVGANGLE, SVGAngle) \ + V(SVGANIMATEDANGLE, SVGAnimatedAngle) \ + V(SVGANIMATEDBOOLEAN, SVGAnimatedBoolean) \ + V(SVGANIMATEDENUMERATION, SVGAnimatedEnumeration) \ + V(SVGANIMATEDINTEGER, SVGAnimatedInteger) \ + V(SVGANIMATEDLENGTH, SVGAnimatedLength) \ + V(SVGANIMATEDLENGTHLIST, SVGAnimatedLengthList) \ + V(SVGANIMATEDNUMBER, SVGAnimatedNumber) \ + V(SVGANIMATEDNUMBERLIST, SVGAnimatedNumberList) \ + V(SVGANIMATEDPRESERVEASPECTRATIO, SVGAnimatedPreserveAspectRatio) \ + V(SVGANIMATEDRECT, SVGAnimatedRect) \ + V(SVGANIMATEDSTRING, SVGAnimatedString) \ + V(SVGANIMATEDTRANSFORMLIST, SVGAnimatedTransformList) \ + V(SVGCOLOR, SVGColor) \ + V(SVGELEMENTINSTANCE, SVGElementInstance) \ + V(SVGELEMENTINSTANCELIST, SVGElementInstanceList) \ + V(SVGEXCEPTION, SVGException) \ + V(SVGLENGTHLIST, SVGLengthList) \ + V(SVGNUMBERLIST, SVGNumberList) \ + V(SVGPAINT, SVGPaint) \ + V(SVGPATHSEG, SVGPathSeg) \ + V(SVGPATHSEGARCABS, SVGPathSegArcAbs) \ + V(SVGPATHSEGARCREL, SVGPathSegArcRel) \ + V(SVGPATHSEGCLOSEPATH, SVGPathSegClosePath) \ + V(SVGPATHSEGCURVETOCUBICABS, SVGPathSegCurvetoCubicAbs) \ + V(SVGPATHSEGCURVETOCUBICREL, SVGPathSegCurvetoCubicRel) \ + V(SVGPATHSEGCURVETOCUBICSMOOTHABS, SVGPathSegCurvetoCubicSmoothAbs) \ + V(SVGPATHSEGCURVETOCUBICSMOOTHREL, SVGPathSegCurvetoCubicSmoothRel) \ + V(SVGPATHSEGCURVETOQUADRATICABS, SVGPathSegCurvetoQuadraticAbs) \ + V(SVGPATHSEGCURVETOQUADRATICREL, SVGPathSegCurvetoQuadraticRel) \ + V(SVGPATHSEGCURVETOQUADRATICSMOOTHABS, SVGPathSegCurvetoQuadraticSmoothAbs)\ + V(SVGPATHSEGCURVETOQUADRATICSMOOTHREL, SVGPathSegCurvetoQuadraticSmoothRel)\ + V(SVGPATHSEGLINETOABS, SVGPathSegLinetoAbs) \ + V(SVGPATHSEGLINETOHORIZONTALABS, SVGPathSegLinetoHorizontalAbs) \ + V(SVGPATHSEGLINETOHORIZONTALREL, SVGPathSegLinetoHorizontalRel) \ + V(SVGPATHSEGLINETOREL, SVGPathSegLinetoRel) \ + V(SVGPATHSEGLINETOVERTICALABS, SVGPathSegLinetoVerticalAbs) \ + V(SVGPATHSEGLINETOVERTICALREL, SVGPathSegLinetoVerticalRel) \ + V(SVGPATHSEGLIST, SVGPathSegList) \ + V(SVGPATHSEGMOVETOABS, SVGPathSegMovetoAbs) \ + V(SVGPATHSEGMOVETOREL, SVGPathSegMovetoRel) \ + V(SVGPOINTLIST, SVGPointList) \ + V(SVGPRESERVEASPECTRATIO, SVGPreserveAspectRatio) \ + V(SVGRENDERINGINTENT, SVGRenderingIntent) \ + V(SVGSTRINGLIST, SVGStringList) \ + V(SVGTRANSFORMLIST, SVGTransformList) \ + V(SVGUNITTYPES, SVGUnitTypes) \ + V(SVGZOOMEVENT, SVGZoomEvent) + +// SVG POD types should list all types whose IDL has PODType declaration. +#define SVG_POD_TYPES(V) \ + V(SVGLENGTH, SVGLength) \ + V(SVGTRANSFORM, SVGTransform) \ + V(SVGMATRIX, SVGMatrix) \ + V(SVGNUMBER, SVGNumber) \ + V(SVGPOINT, SVGPoint) \ + V(SVGRECT, SVGRect) + +// POD types can have different implementation names, see CodeGenerateV8.pm. +#define SVG_POD_NATIVE_TYPES(V) \ + V(SVGLENGTH, SVGLength) \ + V(SVGTRANSFORM, SVGTransform) \ + V(SVGMATRIX, TransformationMatrix) \ + V(SVGNUMBER, float) \ + V(SVGPOINT, FloatPoint) \ + V(SVGRECT, FloatRect) + +// Shouldn't generate code for these two types. +#define SVG_NO_WRAPPER_TYPES(V) \ + V(SVGURIREFERENCE, SVGURIReference) \ + V(SVGANIMATEDPOINTS, SVGAnimatedPoints) + +// SVG_NONNODE_TYPES are SVG non-node object types, pod typs and +// numerical types. +#define SVG_NONNODE_TYPES(V) \ + SVG_OBJECT_TYPES(V) \ + SVG_POD_TYPES(V) +#endif // SVG + +// EVENTTARGET, EVENTLISTENER, and NPOBJECT do not have V8 wrappers. +#define DOM_NO_WRAPPER_TYPES(V) \ + V(EVENTTARGET, EventTarget) \ + V(EVENTLISTENER, EventListener) \ + V(NPOBJECT, NPObject) + +#if ENABLE(SVG) +#define WRAPPER_TYPES(V) DOM_NODE_TYPES(V) DOM_OBJECT_TYPES(V) SVG_NODE_TYPES(V) SVG_NONNODE_TYPES(V) +#define NO_WRAPPER_TYPES(V) DOM_NO_WRAPPER_TYPES(V) SVG_NO_WRAPPER_TYPES(V) +#else // SVG +#define WRAPPER_TYPES(V) DOM_NODE_TYPES(V) DOM_OBJECT_TYPES(V) +#define NO_WRAPPER_TYPES(V) DOM_NO_WRAPPER_TYPES(V) +#endif // SVG + +#define ALL_WRAPPER_TYPES(V) WRAPPER_TYPES(V) NO_WRAPPER_TYPES(V) + + class V8ClassIndex { + public: + // Type must start at non-negative numbers. See ToInt, FromInt. + enum V8WrapperType { + INVALID_CLASS_INDEX = 0, + +#define DEFINE_ENUM(name, type) name, + ALL_WRAPPER_TYPES(DEFINE_ENUM) +#undef DEFINE_ENUM + + CLASSINDEX_END, + WRAPPER_TYPE_COUNT = CLASSINDEX_END + }; + + // FIXME: Convert to toInt after all the bindings are in one place. + static int ToInt(V8WrapperType type) { return static_cast<int>(type); } + + // FIXME: Convert to fromInt after all the bindings are in one place. + static V8WrapperType FromInt(int v) { + ASSERT(INVALID_CLASS_INDEX <= v && v < CLASSINDEX_END); + return static_cast<V8WrapperType>(v); + } + + // FIXME: Convert to getFactory after all the bindings are in one place. + static FunctionTemplateFactory GetFactory(V8WrapperType type); + + // Returns a field to be used as cache for the template for the given type + // FIXME: Convert to getCache after all the bindings are in one place. + static v8::Persistent<v8::FunctionTemplate>* GetCache(V8WrapperType type); + }; + +} #endif // V8Index_h diff --git a/WebCore/bindings/v8/V8IsolatedWorld.cpp b/WebCore/bindings/v8/V8IsolatedWorld.cpp new file mode 100644 index 0000000..1457545 --- /dev/null +++ b/WebCore/bindings/v8/V8IsolatedWorld.cpp @@ -0,0 +1,126 @@ +/* + * 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: + * + * * 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. + */ + +#include "config.h" + +#include "V8IsolatedWorld.h" + +#include <v8.h> + +#include "Frame.h" +#include "FrameLoaderClient.h" +#include "HashMap.h" +#include "ScriptController.h" +#include "V8DOMWindow.h" +#include "V8HiddenPropertyName.h" + +namespace WebCore { + +static int isolatedWorldCount = 0; + +static void contextWeakReferenceCallback(v8::Persistent<v8::Value> object, void* isolated_world) +{ + // Our context is going away. Time to clean up the world. + V8IsolatedWorld* world = static_cast<V8IsolatedWorld*>(isolated_world); + delete world; +} + +void V8IsolatedWorld::evaluate(const Vector<ScriptSourceCode>& sources, V8Proxy* proxy, int extensionGroup) +{ + v8::HandleScope scope; + v8::Persistent<v8::Context> context = proxy->createNewContext(v8::Handle<v8::Object>(), extensionGroup); + + // Run code in the new context. + v8::Context::Scope context_scope(context); + + // The lifetime of this object is controlled by the V8 GC. + // We need to create the world before touching DOM wrappers. + V8IsolatedWorld* world = new V8IsolatedWorld(context); + + V8Proxy::installHiddenObjectPrototype(context); + proxy->installDOMWindow(context, proxy->frame()->domWindow()); + + proxy->frame()->loader()->client()->didCreateIsolatedScriptContext(); + + for (size_t i = 0; i < sources.size(); ++i) + proxy->evaluate(sources[i], 0); + + // Using the default security token means that the canAccess is always + // called, which is slow. + // FIXME: Use tokens where possible. This will mean keeping track of all + // created contexts so that they can all be updated when the + // document domain + // changes. + // FIXME: Move this statement above proxy->evaluate? It seems like we + // should set up the token before running the script. + context->UseDefaultSecurityToken(); + + context.Dispose(); + // WARNING! This might well delete |world|. +} + +V8IsolatedWorld::V8IsolatedWorld(v8::Handle<v8::Context> context) + : m_context(v8::Persistent<v8::Context>::New(context)) +{ + ++isolatedWorldCount; + m_context.MakeWeak(this, &contextWeakReferenceCallback); + m_context->Global()->SetHiddenValue(V8HiddenPropertyName::isolatedWorld(), v8::External::Wrap(this)); +} + +V8IsolatedWorld::~V8IsolatedWorld() +{ + --isolatedWorldCount; + m_context.Dispose(); + m_context.Clear(); +} + +V8IsolatedWorld* V8IsolatedWorld::getEntered() +{ + if (isolatedWorldCount == 0) { + // This is a temporary performance optimization. Essentially, + // GetHiddenValue is too slow for this code path. We need to get the + // V8 team to add a real property to v8::Context for isolated worlds. + // Until then, we optimize the common case of not having any isolated + // worlds at all. + return 0; + } + + if (!v8::Context::InContext()) + return 0; + v8::HandleScope scope; + + v8::Local<v8::Value> world = v8::Context::GetEntered()->Global()->GetHiddenValue(V8HiddenPropertyName::isolatedWorld()); + if (world.IsEmpty()) + return 0; + + return static_cast<V8IsolatedWorld*>(v8::External::Unwrap(world)); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/V8IsolatedWorld.h b/WebCore/bindings/v8/V8IsolatedWorld.h new file mode 100644 index 0000000..2036e65 --- /dev/null +++ b/WebCore/bindings/v8/V8IsolatedWorld.h @@ -0,0 +1,98 @@ +/* + * 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: + * + * * 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 V8IsolatedWorld_h +#define V8IsolatedWorld_h + +#include <v8.h> + +#include "V8DOMMap.h" +#include "V8Index.h" +#include "V8Utilities.h" +#include "ScriptSourceCode.h" // for WebCore::ScriptSourceCode + +namespace WebCore { + + class V8Proxy; + + // V8IsolatedWorld + // + // V8IsolatedWorld represents a isolated execution environment for + // JavaScript. Each isolated world executes in parallel with the main + // JavaScript world. An isolated world has access to the same DOM data + // structures as the main world but none of the JavaScript pointers. + // + // It is an error to ever share a JavaScript pointer between two isolated + // worlds or between an isolated world and the main world. Because + // isolated worlds have access to the DOM, they need their own DOM wrappers + // to avoid having pointers to the main world's DOM wrappers (which are + // JavaScript objects). + // + class V8IsolatedWorld { + public: + ~V8IsolatedWorld(); + + // Evaluate JavaScript in a new isolated world. The script has access + // to the DOM of the document associated with |proxy|. + static void evaluate(const Vector<ScriptSourceCode>& sources, V8Proxy* proxy, int extensionGroup); + + // Returns the isolated world associated with + // v8::Context::GetEntered(). Because worlds are isolated, the entire + // JavaScript call stack should be from the same isolated world. + // Returns NULL if the entered context is from the main world. + // + // FIXME: Consider edge cases with DOM mutation events that might + // violate this invariant. + // + static V8IsolatedWorld* getEntered(); + + v8::Handle<v8::Context> context() { return m_context; } + + DOMDataStore* getDOMDataStore() const { return m_domDataStore.getStore(); } + + private: + // The lifetime of an isolated world is managed by the V8 garbage + // collector. In particular, the object created by this constructor is + // freed when |context| is garbage collected. + explicit V8IsolatedWorld(v8::Handle<v8::Context> context); + + // The v8::Context for the isolated world. This object is keep on the + // heap as long as |m_context| has not been garbage collected. + v8::Persistent<v8::Context> m_context; + + // The backing store for the isolated world's DOM wrappers. This class + // doesn't have visibility into the wrappers. This handle simply helps + // manage their lifetime. + DOMDataStoreHandle m_domDataStore; + }; + +} // namespace WebCore + +#endif // V8IsolatedWorld_h diff --git a/WebCore/bindings/v8/V8LazyEventListener.cpp b/WebCore/bindings/v8/V8LazyEventListener.cpp index f0e81de..59fa7be 100644 --- a/WebCore/bindings/v8/V8LazyEventListener.cpp +++ b/WebCore/bindings/v8/V8LazyEventListener.cpp @@ -54,7 +54,7 @@ V8LazyEventListener::~V8LazyEventListener() // Dispose wrapped function if (!m_wrappedFunction.IsEmpty()) { #ifndef NDEBUG - V8Proxy::UnregisterGlobalHandle(this, m_wrappedFunction); + V8GCController::unregisterGlobalHandle(this, m_wrappedFunction); #endif m_wrappedFunction.Dispose(); m_wrappedFunction.Clear(); @@ -77,12 +77,12 @@ v8::Local<v8::Function> V8LazyEventListener::getListenerFunction() v8::HandleScope handleScope; // Use the outer scope to hold context. - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_frame); + v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(m_frame); // Bail out if we could not get the context. - if (context.IsEmpty()) + if (v8Context.IsEmpty()) return v8::Local<v8::Function>(); - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); // Wrap function around the event code. The parenthesis around the function are needed so that evaluating the code yields // the function value. Without the parenthesis the function value is thrown away. @@ -102,19 +102,19 @@ v8::Local<v8::Function> V8LazyEventListener::getListenerFunction() code.append("\n})"); v8::Handle<v8::String> codeExternalString = v8ExternalString(code); - v8::Handle<v8::Script> script = V8Proxy::CompileScript(codeExternalString, m_frame->document()->url(), m_lineNumber - 1); + v8::Handle<v8::Script> script = V8Proxy::compileScript(codeExternalString, m_frame->document()->url(), m_lineNumber - 1); if (!script.IsEmpty()) { V8Proxy* proxy = V8Proxy::retrieve(m_frame); ASSERT(proxy); - v8::Local<v8::Value> value = proxy->RunScript(script, false); + v8::Local<v8::Value> value = proxy->runScript(script, false); if (!value.IsEmpty()) { ASSERT(value->IsFunction()); v8::Local<v8::Function> listenerFunction = v8::Local<v8::Function>::Cast(value); - listenerFunction->SetName(v8::String::New(FromWebCoreString(m_functionName), m_functionName.length())); + listenerFunction->SetName(v8::String::New(fromWebCoreString(m_functionName), m_functionName.length())); m_listener = v8::Persistent<v8::Function>::New(listenerFunction); #ifndef NDEBUG - V8Proxy::RegisterGlobalHandle(EVENT_LISTENER, this, m_listener); + V8GCController::registerGlobalHandle(EVENT_LISTENER, this, m_listener); #endif } } @@ -134,7 +134,7 @@ v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(v8::Handle<v8::Va v8::Handle<v8::Value> parameters[1] = { jsEvent }; V8Proxy* proxy = V8Proxy::retrieve(m_frame); - return proxy->CallFunction(handlerFunction, receiver, 1, parameters); + return proxy->callFunction(handlerFunction, receiver, 1, parameters); } @@ -158,12 +158,12 @@ v8::Local<v8::Function> V8LazyEventListener::getWrappedListenerFunction() v8::HandleScope handleScope; // Use the outer scope to hold context. - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_frame); + v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(m_frame); // Bail out if we cannot get the context. - if (context.IsEmpty()) + if (v8Context.IsEmpty()) return v8::Local<v8::Function>(); - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); // FIXME: cache the wrapper function. @@ -184,11 +184,11 @@ v8::Local<v8::Function> V8LazyEventListener::getWrappedListenerFunction() // Insert '\n' otherwise //-style comments could break the handler. code.append( "\n}).call(this, evt);}}}})"); v8::Handle<v8::String> codeExternalString = v8ExternalString(code); - v8::Handle<v8::Script> script = V8Proxy::CompileScript(codeExternalString, m_frame->document()->url(), m_lineNumber); + v8::Handle<v8::Script> script = V8Proxy::compileScript(codeExternalString, m_frame->document()->url(), m_lineNumber); if (!script.IsEmpty()) { V8Proxy* proxy = V8Proxy::retrieve(m_frame); ASSERT(proxy); - v8::Local<v8::Value> value = proxy->RunScript(script, false); + v8::Local<v8::Value> value = proxy->runScript(script, false); if (!value.IsEmpty()) { ASSERT(value->IsFunction()); @@ -218,7 +218,7 @@ v8::Local<v8::Function> V8LazyEventListener::getWrappedListenerFunction() } #ifndef NDEBUG - V8Proxy::RegisterGlobalHandle(EVENT_LISTENER, this, m_wrappedFunction); + V8GCController::registerGlobalHandle(EVENT_LISTENER, this, m_wrappedFunction); #endif m_wrappedFunction->SetName(v8::String::New(fromWebCoreString(m_functionName), m_functionName.length())); } diff --git a/WebCore/bindings/v8/V8NPObject.cpp b/WebCore/bindings/v8/V8NPObject.cpp new file mode 100644 index 0000000..b6bf0f7 --- /dev/null +++ b/WebCore/bindings/v8/V8NPObject.cpp @@ -0,0 +1,351 @@ +/* +* Copyright (C) 2006, 2007, 2008, 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: +* +* * 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. +*/ + +#include "config.h" + +#include "V8NPObject.h" + +#include "HTMLPlugInElement.h" +#include "NPV8Object.h" +#include "V8CustomBinding.h" +#include "V8DOMMap.h" +#include "V8HTMLAppletElement.h" +#include "V8HTMLEmbedElement.h" +#include "V8HTMLObjectElement.h" +#include "V8Helpers.h" +#include "V8NPUtils.h" +#include "V8Proxy.h" +#include "npruntime_impl.h" +#include "npruntime_priv.h" +#include "wtf/OwnArrayPtr.h" + +using namespace WebCore; + +enum InvokeFunctionType { + InvokeMethod = 1, + InvokeConstruct = 2, + InvokeDefault = 3 +}; + +// FIXME: need comments. +// Params: holder could be HTMLEmbedElement or NPObject +static v8::Handle<v8::Value> npObjectInvokeImpl(const v8::Arguments& args, InvokeFunctionType functionId) +{ + NPObject* npObject; + + // These three types are subtypes of HTMLPlugInElement. + if (V8HTMLAppletElement::HasInstance(args.Holder()) || V8HTMLEmbedElement::HasInstance(args.Holder()) + || V8HTMLObjectElement::HasInstance(args.Holder())) { + // The holder object is a subtype of HTMLPlugInElement. + HTMLPlugInElement* element = V8DOMWrapper::convertDOMWrapperToNode<HTMLPlugInElement>(args.Holder()); + ScriptInstance scriptInstance = element->getInstance(); + if (scriptInstance) + npObject = V8DOMWrapper::convertToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, scriptInstance->instance()); + else + npObject = 0; + } else { + // The holder object is not a subtype of HTMLPlugInElement, it must be an NPObject which has three + // internal fields. + if (args.Holder()->InternalFieldCount() != V8Custom::kNPObjectInternalFieldCount) + return throwError("NPMethod called on non-NPObject", V8Proxy::ReferenceError); + + npObject = V8DOMWrapper::convertToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, args.Holder()); + } + + // Verify that our wrapper wasn't using a NPObject which has already been deleted. + if (!npObject || !_NPN_IsAlive(npObject)) + return throwError("NPObject deleted", V8Proxy::ReferenceError); + + // Wrap up parameters. + int numArgs = args.Length(); + OwnArrayPtr<NPVariant> npArgs(new NPVariant[numArgs]); + + for (int i = 0; i < numArgs; i++) + convertV8ObjectToNPVariant(args[i], npObject, &npArgs[i]); + + NPVariant result; + VOID_TO_NPVARIANT(result); + + switch (functionId) { + case InvokeMethod: + if (npObject->_class->invoke) { + v8::Handle<v8::String> functionName(v8::String::Cast(*args.Data())); + NPIdentifier identifier = getStringIdentifier(functionName); + npObject->_class->invoke(npObject, identifier, npArgs.get(), numArgs, &result); + } + break; + case InvokeConstruct: + if (npObject->_class->construct) + npObject->_class->construct(npObject, npArgs.get(), numArgs, &result); + break; + case InvokeDefault: + if (npObject->_class->invokeDefault) + npObject->_class->invokeDefault(npObject, npArgs.get(), numArgs, &result); + break; + default: + break; + } + + for (int i=0; i < numArgs; i++) + _NPN_ReleaseVariantValue(&npArgs[i]); + + // Unwrap return values. + v8::Handle<v8::Value> returnValue = convertNPVariantToV8Object(&result, npObject); + _NPN_ReleaseVariantValue(&result); + + return returnValue; +} + + +v8::Handle<v8::Value> npObjectMethodHandler(const v8::Arguments& args) +{ + return npObjectInvokeImpl(args, InvokeMethod); +} + + +v8::Handle<v8::Value> npObjectInvokeDefaultHandler(const v8::Arguments& args) +{ + if (args.IsConstructCall()) + return npObjectInvokeImpl(args, InvokeConstruct); + else + return npObjectInvokeImpl(args, InvokeDefault); +} + + +static void weakTemplateCallback(v8::Persistent<v8::Value>, void* parameter); + +// NPIdentifier is PrivateIdentifier*. +static WeakReferenceMap<PrivateIdentifier, v8::FunctionTemplate> staticTemplateMap(&weakTemplateCallback); + +static void weakTemplateCallback(v8::Persistent<v8::Value> object, void* parameter) +{ + PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(parameter); + ASSERT(identifier); + ASSERT(staticTemplateMap.contains(identifier)); + + staticTemplateMap.forget(identifier); +} + + +static v8::Handle<v8::Value> npObjectGetProperty(v8::Local<v8::Object> self, NPIdentifier identifier, v8::Local<v8::Value> key) +{ + NPObject* npObject = V8DOMWrapper::convertToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, self); + + // Verify that our wrapper wasn't using a NPObject which + // has already been deleted. + if (!npObject || !_NPN_IsAlive(npObject)) + return throwError("NPObject deleted", V8Proxy::ReferenceError); + + + if (npObject->_class->hasProperty && npObject->_class->hasProperty(npObject, identifier) + && npObject->_class->getProperty) { + + NPVariant result; + VOID_TO_NPVARIANT(result); + if (!npObject->_class->getProperty(npObject, identifier, &result)) + return v8::Handle<v8::Value>(); + + v8::Handle<v8::Value> returnValue = convertNPVariantToV8Object(&result, npObject); + _NPN_ReleaseVariantValue(&result); + return returnValue; + + } else if (key->IsString() && npObject->_class->hasMethod && npObject->_class->hasMethod(npObject, identifier)) { + PrivateIdentifier* id = static_cast<PrivateIdentifier*>(identifier); + v8::Persistent<v8::FunctionTemplate> functionTemplate = staticTemplateMap.get(id); + // Cache templates using identifier as the key. + if (functionTemplate.IsEmpty()) { + // Create a new template. + v8::Local<v8::FunctionTemplate> temp = v8::FunctionTemplate::New(); + temp->SetCallHandler(npObjectMethodHandler, key); + functionTemplate = v8::Persistent<v8::FunctionTemplate>::New(temp); + staticTemplateMap.set(id, functionTemplate); + } + + // FunctionTemplate caches function for each context. + v8::Local<v8::Function> v8Function = functionTemplate->GetFunction(); + v8Function->SetName(v8::Handle<v8::String>::Cast(key)); + return v8Function; + } + + return v8::Handle<v8::Value>(); +} + +v8::Handle<v8::Value> npObjectNamedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + NPIdentifier identifier = getStringIdentifier(name); + return npObjectGetProperty(info.Holder(), identifier, name); +} + +v8::Handle<v8::Value> npObjectIndexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) +{ + NPIdentifier identifier = _NPN_GetIntIdentifier(index); + return npObjectGetProperty(info.Holder(), identifier, v8::Number::New(index)); +} + +v8::Handle<v8::Value> npObjectGetNamedProperty(v8::Local<v8::Object> self, v8::Local<v8::String> name) +{ + NPIdentifier identifier = getStringIdentifier(name); + return npObjectGetProperty(self, identifier, name); +} + +v8::Handle<v8::Value> npObjectGetIndexedProperty(v8::Local<v8::Object> self, uint32_t index) +{ + NPIdentifier identifier = _NPN_GetIntIdentifier(index); + return npObjectGetProperty(self, identifier, v8::Number::New(index)); +} + +static v8::Handle<v8::Value> npObjectSetProperty(v8::Local<v8::Object> self, NPIdentifier identifier, v8::Local<v8::Value> value) +{ + NPObject* npObject = V8DOMWrapper::convertToNativeObject<NPObject>(V8ClassIndex::NPOBJECT, self); + + // Verify that our wrapper wasn't using a NPObject which has already been deleted. + if (!npObject || !_NPN_IsAlive(npObject)) { + throwError("NPObject deleted", V8Proxy::ReferenceError); + return value; // Intercepted, but an exception was thrown. + } + + if (npObject->_class->hasProperty && npObject->_class->hasProperty(npObject, identifier) + && npObject->_class->setProperty) { + + NPVariant npValue; + VOID_TO_NPVARIANT(npValue); + convertV8ObjectToNPVariant(value, npObject, &npValue); + bool success = npObject->_class->setProperty(npObject, identifier, &npValue); + _NPN_ReleaseVariantValue(&npValue); + if (success) + return value; // Intercept the call. + } + return notHandledByInterceptor(); +} + + +v8::Handle<v8::Value> npObjectNamedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + NPIdentifier identifier = getStringIdentifier(name); + return npObjectSetProperty(info.Holder(), identifier, value); +} + + +v8::Handle<v8::Value> npObjectIndexedPropertySetter(uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + NPIdentifier identifier = _NPN_GetIntIdentifier(index); + return npObjectSetProperty(info.Holder(), identifier, value); +} + +v8::Handle<v8::Value> npObjectSetNamedProperty(v8::Local<v8::Object> self, v8::Local<v8::String> name, v8::Local<v8::Value> value) +{ + NPIdentifier identifier = getStringIdentifier(name); + return npObjectSetProperty(self, identifier, value); +} + +v8::Handle<v8::Value> npObjectSetIndexedProperty(v8::Local<v8::Object> self, uint32_t index, v8::Local<v8::Value> value) +{ + NPIdentifier identifier = _NPN_GetIntIdentifier(index); + return npObjectSetProperty(self, identifier, value); +} + + +static void weakNPObjectCallback(v8::Persistent<v8::Value>, void* parameter); + +static DOMWrapperMap<NPObject> staticNPObjectMap(&weakNPObjectCallback); + +static void weakNPObjectCallback(v8::Persistent<v8::Value> object, void* parameter) +{ + NPObject* npObject = static_cast<NPObject*>(parameter); + ASSERT(staticNPObjectMap.contains(npObject)); + ASSERT(npObject); + + // Must remove from our map before calling _NPN_ReleaseObject(). _NPN_ReleaseObject can call ForgetV8ObjectForNPObject, which + // uses the table as well. + staticNPObjectMap.forget(npObject); + + if (_NPN_IsAlive(npObject)) + _NPN_ReleaseObject(npObject); +} + + +v8::Local<v8::Object> createV8ObjectForNPObject(NPObject* object, NPObject* root) +{ + static v8::Persistent<v8::FunctionTemplate> npObjectDesc; + + ASSERT(v8::Context::InContext()); + + // If this is a v8 object, just return it. + if (object->_class == npScriptObjectClass) { + V8NPObject* v8NPObject = reinterpret_cast<V8NPObject*>(object); + return v8::Local<v8::Object>::New(v8NPObject->v8Object); + } + + // If we've already wrapped this object, just return it. + if (staticNPObjectMap.contains(object)) + return v8::Local<v8::Object>::New(staticNPObjectMap.get(object)); + + // FIXME: we should create a Wrapper type as a subclass of JSObject. It has two internal fields, field 0 is the wrapped + // pointer, and field 1 is the type. There should be an api function that returns unused type id. The same Wrapper type + // can be used by DOM bindings. + if (npObjectDesc.IsEmpty()) { + npObjectDesc = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New()); + npObjectDesc->InstanceTemplate()->SetInternalFieldCount(V8Custom::kNPObjectInternalFieldCount); + npObjectDesc->InstanceTemplate()->SetNamedPropertyHandler(npObjectNamedPropertyGetter, npObjectNamedPropertySetter); + npObjectDesc->InstanceTemplate()->SetIndexedPropertyHandler(npObjectIndexedPropertyGetter, npObjectIndexedPropertySetter); + npObjectDesc->InstanceTemplate()->SetCallAsFunctionHandler(npObjectInvokeDefaultHandler); + } + + v8::Handle<v8::Function> v8Function = npObjectDesc->GetFunction(); + v8::Local<v8::Object> value = SafeAllocation::newInstance(v8Function); + + // If we were unable to allocate the instance, we avoid wrapping and registering the NP object. + if (value.IsEmpty()) + return value; + + wrapNPObject(value, object); + + // KJS retains the object as part of its wrapper (see Bindings::CInstance). + _NPN_RetainObject(object); + + _NPN_RegisterObject(object, root); + + // Maintain a weak pointer for v8 so we can cleanup the object. + v8::Persistent<v8::Object> weakRef = v8::Persistent<v8::Object>::New(value); + staticNPObjectMap.set(object, weakRef); + + return value; +} + +void forgetV8ObjectForNPObject(NPObject* object) +{ + if (staticNPObjectMap.contains(object)) { + v8::HandleScope scope; + v8::Persistent<v8::Object> handle(staticNPObjectMap.get(object)); + V8DOMWrapper::setDOMWrapper(handle, WebCore::V8ClassIndex::NPOBJECT, 0); + staticNPObjectMap.forget(object); + _NPN_ReleaseObject(object); + } +} diff --git a/WebCore/bindings/v8/V8NPObject.h b/WebCore/bindings/v8/V8NPObject.h new file mode 100644 index 0000000..0a759b5 --- /dev/null +++ b/WebCore/bindings/v8/V8NPObject.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2006, 2007, 2008, 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: + * + * * 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 V8NPObject_h +#define V8NPObject_h + +#include <v8.h> +#include "third_party/npapi/bindings/npruntime.h" + +// These functions can be replaced by normal JS operation. +// Getters +v8::Handle<v8::Value> npObjectNamedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo&); +v8::Handle<v8::Value> npObjectIndexedPropertyGetter(uint32_t index, const v8::AccessorInfo&); +v8::Handle<v8::Value> npObjectGetNamedProperty(v8::Local<v8::Object> self, v8::Local<v8::String> name); +v8::Handle<v8::Value> npObjectGetIndexedProperty(v8::Local<v8::Object> self, uint32_t index); + +// Setters +v8::Handle<v8::Value> npObjectNamedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value>, const v8::AccessorInfo&); +v8::Handle<v8::Value> npObjectIndexedPropertySetter(uint32_t index, const v8::AccessorInfo&); +v8::Handle<v8::Value> npObjectSetNamedProperty(v8::Local<v8::Object> self, v8::Local<v8::String> name, v8::Local<v8::Value>); +v8::Handle<v8::Value> npObjectSetIndexedProperty(v8::Local<v8::Object> self, uint32_t index, v8::Local<v8::Value>); + +v8::Handle<v8::Value> npObjectInvokeDefaultHandler(const v8::Arguments&); + +// Get a wrapper for a NPObject. +// If the object is already wrapped, the pre-existing wrapper will be returned. If the object is not wrapped, wrap it, and +// give V8 a weak reference to the wrapper which will cleanup when there are no more JS references to the object. +v8::Local<v8::Object> createV8ObjectForNPObject(NPObject*, NPObject* root); + +// Tell V8 to forcibly remove an object. +// This is used at plugin teardown so that the caller can aggressively unload the plugin library. After calling this +// function, the persistent handle to the wrapper will be gone, and the wrapped NPObject will be removed so that it +// cannot be referred to. +void forgetV8ObjectForNPObject(NPObject*); + +#endif // V8NPObject_h diff --git a/WebCore/bindings/v8/V8NPUtils.cpp b/WebCore/bindings/v8/V8NPUtils.cpp new file mode 100644 index 0000000..17855d7 --- /dev/null +++ b/WebCore/bindings/v8/V8NPUtils.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2008, 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: + * + * * 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. + */ + +#include "config.h" + +#include "V8NPUtils.h" + +#include "DOMWindow.h" +#include "Frame.h" +#include "PlatformString.h" +#undef LOG + +#include "NPV8Object.h" +#include "V8NPObject.h" +#include "V8Proxy.h" +#include "npruntime_impl.h" +#include "npruntime_priv.h" + +void convertV8ObjectToNPVariant(v8::Local<v8::Value> object, NPObject* owner, NPVariant* result) +{ + VOID_TO_NPVARIANT(*result); + + // It is really the caller's responsibility to deal with the empty handle case because there could be different actions to + // take in different contexts. + ASSERT(!object.IsEmpty()); + + if (object.IsEmpty()) + return; + + if (object->IsInt32()) + INT32_TO_NPVARIANT(object->NumberValue(), *result); + else if (object->IsNumber()) + DOUBLE_TO_NPVARIANT(object->NumberValue(), *result); + else if (object->IsBoolean()) + BOOLEAN_TO_NPVARIANT(object->BooleanValue(), *result); + else if (object->IsNull()) + NULL_TO_NPVARIANT(*result); + else if (object->IsUndefined()) + VOID_TO_NPVARIANT(*result); + else if (object->IsString()) { + v8::String::Utf8Value utf8(object); + char* utf8_chars = strdup(*utf8); + STRINGN_TO_NPVARIANT(utf8_chars, utf8.length(), *result); + } else if (object->IsObject()) { + WebCore::DOMWindow* window = WebCore::V8Proxy::retrieveWindow(WebCore::V8Proxy::currentContext()); + NPObject* npobject = npCreateV8ScriptObject(0, v8::Handle<v8::Object>::Cast(object), window); + if (npobject) + _NPN_RegisterObject(npobject, owner); + OBJECT_TO_NPVARIANT(npobject, *result); + } +} + + +v8::Handle<v8::Value> convertNPVariantToV8Object(const NPVariant* variant, NPObject* npobject) +{ + NPVariantType type = variant->type; + + switch (type) { + case NPVariantType_Int32: + return v8::Integer::New(NPVARIANT_TO_INT32(*variant)); + case NPVariantType_Double: + return v8::Number::New(NPVARIANT_TO_DOUBLE(*variant)); + case NPVariantType_Bool: + return NPVARIANT_TO_BOOLEAN(*variant) ? v8::True() : v8::False(); + case NPVariantType_Null: + return v8::Null(); + case NPVariantType_Void: + return v8::Undefined(); + case NPVariantType_String: { + NPString src = NPVARIANT_TO_STRING(*variant); + return v8::String::New(src.UTF8Characters, src.UTF8Length); + } + case NPVariantType_Object: { + NPObject* obj = NPVARIANT_TO_OBJECT(*variant); + if (obj->_class == npScriptObjectClass) + return reinterpret_cast<V8NPObject*>(obj)->v8Object; + return createV8ObjectForNPObject(obj, npobject); + } + default: + return v8::Undefined(); + } +} + +// Helper function to create an NPN String Identifier from a v8 string. +NPIdentifier getStringIdentifier(v8::Handle<v8::String> str) +{ + const int kStackBufferSize = 100; + + int bufferLength = str->Utf8Length() + 1; + if (bufferLength <= kStackBufferSize) { + // Use local stack buffer to avoid heap allocations for small strings. Here we should only use the stack space for + // stackBuffer when it's used, not when we use the heap. + // + // WriteUtf8 is guaranteed to generate a null-terminated string because bufferLength is constructed to be one greater + // than the string length. + char stackBuffer[kStackBufferSize]; + str->WriteUtf8(stackBuffer, bufferLength); + return _NPN_GetStringIdentifier(stackBuffer); + } + + v8::String::Utf8Value utf8(str); + return _NPN_GetStringIdentifier(*utf8); +} diff --git a/WebCore/bindings/v8/V8NPUtils.h b/WebCore/bindings/v8/V8NPUtils.h new file mode 100644 index 0000000..82a74b3 --- /dev/null +++ b/WebCore/bindings/v8/V8NPUtils.h @@ -0,0 +1,46 @@ +/* Copyright (C) 2006, 2007, 2008, 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: + * + * * 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 V8NPUtils_h +#define V8NPUtils_h + +#include <v8.h> +#include "third_party/npapi/bindings/npruntime.h" + +// Convert a V8 Value of any type (string, bool, object, etc) to a NPVariant. +void convertV8ObjectToNPVariant(v8::Local<v8::Value>, NPObject*, NPVariant*); + +// Convert a NPVariant (string, bool, object, etc) back to a V8 Value. The owner object is the NPObject which relates to the +// object, if the object is an Object. The created NPObject will be tied to the lifetime of the owner. +v8::Handle<v8::Value> convertNPVariantToV8Object(const NPVariant*, NPObject*); + +// Helper function to create an NPN String Identifier from a v8 string. +NPIdentifier getStringIdentifier(v8::Handle<v8::String>); + +#endif // V8NPUtils_h diff --git a/WebCore/bindings/v8/V8NodeFilterCondition.cpp b/WebCore/bindings/v8/V8NodeFilterCondition.cpp index b5ae30c..9f57a44 100644 --- a/WebCore/bindings/v8/V8NodeFilterCondition.cpp +++ b/WebCore/bindings/v8/V8NodeFilterCondition.cpp @@ -44,14 +44,14 @@ V8NodeFilterCondition::V8NodeFilterCondition(v8::Handle<v8::Value> filter) : m_filter(v8::Persistent<v8::Value>::New(filter)) { #ifndef NDEBUG - V8Proxy::RegisterGlobalHandle(NODE_FILTER, this, m_filter); + V8GCController::registerGlobalHandle(NODE_FILTER, this, m_filter); #endif } V8NodeFilterCondition::~V8NodeFilterCondition() { #ifndef NDEBUG - V8Proxy::UnregisterGlobalHandle(this, m_filter); + V8GCController::unregisterGlobalHandle(this, m_filter); #endif m_filter.Dispose(); m_filter.Clear(); @@ -69,12 +69,12 @@ short V8NodeFilterCondition::acceptNode(ScriptState* state, Node* node) const v8::Handle<v8::Object> object = v8::Context::GetCurrent()->Global(); v8::Handle<v8::Function> callback = v8::Handle<v8::Function>::Cast(m_filter); OwnArrayPtr<v8::Handle<v8::Value> > args(new v8::Handle<v8::Value>[1]); - args[0] = V8Proxy::ToV8Object(V8ClassIndex::NODE, node); + args[0] = V8DOMWrapper::convertToV8Object(V8ClassIndex::NODE, node); V8Proxy* proxy = V8Proxy::retrieve(); ASSERT(proxy); - v8::Handle<v8::Value> result = proxy->CallFunction(callback, object, 1, args.get()); + v8::Handle<v8::Value> result = proxy->callFunction(callback, object, 1, args.get()); if (exceptionCatcher.HasCaught()) { state->setException(exceptionCatcher.Exception()); diff --git a/WebCore/bindings/v8/V8ObjectEventListener.cpp b/WebCore/bindings/v8/V8ObjectEventListener.cpp index 584962a..f10766c 100644 --- a/WebCore/bindings/v8/V8ObjectEventListener.cpp +++ b/WebCore/bindings/v8/V8ObjectEventListener.cpp @@ -45,7 +45,7 @@ static void weakObjectEventListenerCallback(v8::Persistent<v8::Value>, void* par if (frame) { V8Proxy* proxy = V8Proxy::retrieve(frame); if (proxy) - proxy->RemoveObjectEventListener(listener); + proxy->objectListeners()->remove(listener); // Because the listener is no longer in the list, it must be disconnected from the frame to avoid dangling frame pointer // in the destructor. @@ -54,6 +54,23 @@ static void weakObjectEventListenerCallback(v8::Persistent<v8::Value>, void* par listener->disposeListenerObject(); } +// An object event listener wrapper only holds a weak reference to the +// JS function. A strong reference can create a cycle. +// +// The lifetime of these objects is bounded by the life time of the JS +// wrapper of XHR or Node. So we can create a hidden reference from +// the JS wrapper to to its JS function. +// +// (map) +// XHR or Node <---------- JS_wrapper +// | (hidden) : ^ +// V V : (may be reachable by closure) +// V8_listener --------> JS_function +// (weak) <-- may create a cycle if it is strong +// +// The persistent reference is made weak in the constructor of +// V8ObjectEventListener. + V8ObjectEventListener::V8ObjectEventListener(Frame* frame, v8::Local<v8::Object> listener, bool isInline) : V8EventListener(frame, listener, isInline) { @@ -66,7 +83,7 @@ V8ObjectEventListener::~V8ObjectEventListener() ASSERT(!m_listener.IsEmpty()); V8Proxy* proxy = V8Proxy::retrieve(m_frame); if (proxy) - proxy->RemoveObjectEventListener(this); + proxy->objectListeners()->remove(this); } disposeListenerObject(); diff --git a/WebCore/bindings/v8/V8ObjectEventListener.h b/WebCore/bindings/v8/V8ObjectEventListener.h index 501bdac..3c5ae10 100644 --- a/WebCore/bindings/v8/V8ObjectEventListener.h +++ b/WebCore/bindings/v8/V8ObjectEventListener.h @@ -47,6 +47,8 @@ namespace WebCore { return adoptRef(new V8ObjectEventListener(frame, listener, isInline)); } + virtual bool isObjectListener() const { return true; } + private: V8ObjectEventListener(Frame*, v8::Local<v8::Object> listener, bool isInline); virtual ~V8ObjectEventListener(); diff --git a/WebCore/bindings/v8/V8Proxy.cpp b/WebCore/bindings/v8/V8Proxy.cpp new file mode 100644 index 0000000..02bf086 --- /dev/null +++ b/WebCore/bindings/v8/V8Proxy.cpp @@ -0,0 +1,1279 @@ +/* + * Copyright (C) 2008, 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: + * + * * 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. + */ + +#include "config.h" +#include "V8Proxy.h" + +#include "ChromiumBridge.h" +#include "CSSMutableStyleDeclaration.h" +#include "DOMObjectsInclude.h" +#include "DocumentLoader.h" +#include "FrameLoaderClient.h" +#include "ScriptController.h" +#include "V8Binding.h" +#include "V8Collection.h" +#include "V8ConsoleMessage.h" +#include "V8CustomBinding.h" +#include "V8DOMMap.h" +#include "V8DOMWindow.h" +#include "V8HiddenPropertyName.h" +#include "V8Index.h" +#include "V8IsolatedWorld.h" + +#include <algorithm> +#include <utility> +#include <v8.h> +#include <v8-debug.h> +#include <wtf/Assertions.h> +#include <wtf/OwnArrayPtr.h> +#include <wtf/StdLibExtras.h> +#include <wtf/UnusedParam.h> + +namespace WebCore { + +v8::Persistent<v8::Context> V8Proxy::m_utilityContext; + +// Static list of registered extensions +V8ExtensionList V8Proxy::m_extensions; + +const char* V8Proxy::kContextDebugDataType = "type"; +const char* V8Proxy::kContextDebugDataValue = "value"; + +void batchConfigureAttributes(v8::Handle<v8::ObjectTemplate> instance, v8::Handle<v8::ObjectTemplate> proto, const BatchedAttribute* attributes, size_t attributeCount) +{ + for (size_t i = 0; i < attributeCount; ++i) { + const BatchedAttribute* attribute = &attributes[i]; + (attribute->onProto ? proto : instance)->SetAccessor(v8::String::New(attribute->name), + attribute->getter, + attribute->setter, + attribute->data == V8ClassIndex::INVALID_CLASS_INDEX ? v8::Handle<v8::Value>() : v8::Integer::New(V8ClassIndex::ToInt(attribute->data)), + attribute->settings, + attribute->attribute); + } +} + +void batchConfigureConstants(v8::Handle<v8::FunctionTemplate> functionDescriptor, v8::Handle<v8::ObjectTemplate> proto, const BatchedConstant* constants, size_t constantCount) +{ + for (size_t i = 0; i < constantCount; ++i) { + const BatchedConstant* constant = &constants[i]; + functionDescriptor->Set(v8::String::New(constant->name), v8::Integer::New(constant->value), v8::ReadOnly); + proto->Set(v8::String::New(constant->name), v8::Integer::New(constant->value), v8::ReadOnly); + } +} + +typedef HashMap<Node*, v8::Object*> DOMNodeMap; +typedef HashMap<void*, v8::Object*> DOMObjectMap; + +#if ENABLE(SVG) +// Map of SVG objects with contexts to their contexts +static HashMap<void*, SVGElement*>& svgObjectToContextMap() +{ + typedef HashMap<void*, SVGElement*> SvgObjectToContextMap; + DEFINE_STATIC_LOCAL(SvgObjectToContextMap, staticSvgObjectToContextMap, ()); + return staticSvgObjectToContextMap; +} + +void V8Proxy::setSVGContext(void* object, SVGElement* context) +{ + if (!object) + return; + + SVGElement* oldContext = svgObjectToContextMap().get(object); + + if (oldContext == context) + return; + + if (oldContext) + oldContext->deref(); + + if (context) + context->ref(); + + svgObjectToContextMap().set(object, context); +} + +SVGElement* V8Proxy::svgContext(void* object) +{ + return svgObjectToContextMap().get(object); +} + +#endif + +typedef HashMap<int, v8::FunctionTemplate*> FunctionTemplateMap; + +bool AllowAllocation::m_current = false; + +void logInfo(Frame* frame, const String& message, const String& url) +{ + Page* page = frame->page(); + if (!page) + return; + V8ConsoleMessage consoleMessage(message, url, 0); + consoleMessage.dispatchNow(page); +} + +enum DelayReporting { + ReportLater, + ReportNow +}; + +static void reportUnsafeAccessTo(Frame* target, DelayReporting delay) +{ + ASSERT(target); + Document* targetDocument = target->document(); + if (!targetDocument) + return; + + Frame* source = V8Proxy::retrieveFrameForEnteredContext(); + if (!source || !source->document()) + return; // Ignore error if the source document is gone. + + Document* sourceDocument = source->document(); + + // FIXME: This error message should contain more specifics of why the same + // origin check has failed. + String str = String::format("Unsafe JavaScript attempt to access frame " + "with URL %s from frame with URL %s. " + "Domains, protocols and ports must match.\n", + targetDocument->url().string().utf8().data(), + sourceDocument->url().string().utf8().data()); + + // Build a console message with fake source ID and line number. + const String kSourceID = ""; + const int kLineNumber = 1; + V8ConsoleMessage message(str, kSourceID, kLineNumber); + + if (delay == ReportNow) { + // NOTE: Safari prints the message in the target page, but it seems like + // it should be in the source page. Even for delayed messages, we put it in + // the source page; see V8ConsoleMessage::processDelayed(). + message.dispatchNow(source->page()); + } else { + ASSERT(delay == ReportLater); + // We cannot safely report the message eagerly, because this may cause + // allocations and GCs internally in V8 and we cannot handle that at this + // point. Therefore we delay the reporting. + message.dispatchLater(); + } +} + +static void reportUnsafeJavaScriptAccess(v8::Local<v8::Object> host, v8::AccessType type, v8::Local<v8::Value> data) +{ + Frame* target = V8Custom::GetTargetFrame(host, data); + if (target) + reportUnsafeAccessTo(target, ReportLater); +} + +static void handleFatalErrorInV8() +{ + // FIXME: We temporarily deal with V8 internal error situations + // such as out-of-memory by crashing the renderer. + CRASH(); +} + +static void reportFatalErrorInV8(const char* location, const char* message) +{ + // V8 is shutdown, we cannot use V8 api. + // The only thing we can do is to disable JavaScript. + // FIXME: clean up V8Proxy and disable JavaScript. + printf("V8 error: %s (%s)\n", message, location); + handleFatalErrorInV8(); +} + +V8Proxy::~V8Proxy() +{ + clearForClose(); + destroyGlobal(); +} + +void V8Proxy::destroyGlobal() +{ + if (!m_global.IsEmpty()) { +#ifndef NDEBUG + V8GCController::unregisterGlobalHandle(this, m_global); +#endif + m_global.Dispose(); + m_global.Clear(); + } +} + +static void disconnectEventListenersInList(V8EventListenerList& list) +{ + V8EventListenerList::iterator it = list.begin(); + while (it != list.end()) { + (*it)->disconnectFrame(); + ++it; + } + list.clear(); +} + +void V8Proxy::disconnectEventListeners() +{ + disconnectEventListenersInList(m_eventListeners); + disconnectEventListenersInList(m_objectListeners); +} + +v8::Handle<v8::Script> V8Proxy::compileScript(v8::Handle<v8::String> code, const String& fileName, int baseLine) +{ + const uint16_t* fileNameString = fromWebCoreString(fileName); + v8::Handle<v8::String> name = v8::String::New(fileNameString, fileName.length()); + v8::Handle<v8::Integer> line = v8::Integer::New(baseLine); + v8::ScriptOrigin origin(name, line); + v8::Handle<v8::Script> script = v8::Script::Compile(code, &origin); + return script; +} + +bool V8Proxy::handleOutOfMemory() +{ + v8::Local<v8::Context> context = v8::Context::GetCurrent(); + + if (!context->HasOutOfMemoryException()) + return false; + + // Warning, error, disable JS for this frame? + Frame* frame = V8Proxy::retrieveFrame(context); + + V8Proxy* proxy = V8Proxy::retrieve(frame); + if (proxy) { + // Clean m_context, and event handlers. + proxy->clearForClose(); + + proxy->destroyGlobal(); + } + + ChromiumBridge::notifyJSOutOfMemory(frame); + + // Disable JS. + Settings* settings = frame->settings(); + ASSERT(settings); + settings->setJavaScriptEnabled(false); + + return true; +} + +void V8Proxy::evaluateInNewWorld(const Vector<ScriptSourceCode>& sources, int extensionGroup) +{ + initContextIfNeeded(); + V8IsolatedWorld::evaluate(sources, this, extensionGroup); +} + +void V8Proxy::evaluateInNewContext(const Vector<ScriptSourceCode>& sources, int extensionGroup) +{ + initContextIfNeeded(); + + v8::HandleScope handleScope; + + // Set up the DOM window as the prototype of the new global object. + v8::Handle<v8::Context> windowContext = m_context; + v8::Handle<v8::Object> windowGlobal = windowContext->Global(); + v8::Handle<v8::Object> windowWrapper = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, windowGlobal); + + ASSERT(V8DOMWrapper::convertDOMWrapperToNative<DOMWindow>(windowWrapper) == m_frame->domWindow()); + + v8::Persistent<v8::Context> context = createNewContext(v8::Handle<v8::Object>(), extensionGroup); + v8::Context::Scope contextScope(context); + + // Setup context id for JS debugger. + v8::Handle<v8::Object> contextData = v8::Object::New(); + v8::Handle<v8::Value> windowContextData = windowContext->GetData(); + if (windowContextData->IsObject()) { + v8::Handle<v8::String> propertyName = v8::String::New(kContextDebugDataValue); + contextData->Set(propertyName, v8::Object::Cast(*windowContextData)->Get(propertyName)); + } + contextData->Set(v8::String::New(kContextDebugDataType), v8::String::New("injected")); + context->SetData(contextData); + + v8::Handle<v8::Object> global = context->Global(); + + v8::Handle<v8::String> implicitProtoString = v8::String::New("__proto__"); + global->Set(implicitProtoString, windowWrapper); + + // Give the code running in the new context a way to get access to the + // original context. + global->Set(v8::String::New("contentWindow"), windowGlobal); + + m_frame->loader()->client()->didCreateIsolatedScriptContext(); + + // Run code in the new context. + for (size_t i = 0; i < sources.size(); ++i) + evaluate(sources[i], 0); + + // Using the default security token means that the canAccess is always + // called, which is slow. + // FIXME: Use tokens where possible. This will mean keeping track of all + // created contexts so that they can all be updated when the document domain + // changes. + context->UseDefaultSecurityToken(); + context.Dispose(); +} + +v8::Local<v8::Value> V8Proxy::evaluate(const ScriptSourceCode& source, Node* node) +{ + ASSERT(v8::Context::InContext()); + + // Compile the script. + v8::Local<v8::String> code = v8ExternalString(source.source()); + ChromiumBridge::traceEventBegin("v8.compile", node, ""); + + // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at + // 1, whereas v8 starts at 0. + v8::Handle<v8::Script> script = compileScript(code, source.url(), source.startLine() - 1); + ChromiumBridge::traceEventEnd("v8.compile", node, ""); + + ChromiumBridge::traceEventBegin("v8.run", node, ""); + v8::Local<v8::Value> result; + { + // Isolate exceptions that occur when executing the code. These + // exceptions should not interfere with javascript code we might + // evaluate from C++ when returning from here. + v8::TryCatch tryCatch; + tryCatch.SetVerbose(true); + + // Set inlineCode to true for <a href="javascript:doSomething()"> + // and false for <script>doSomething</script>. We make a rough guess at + // this based on whether the script source has a URL. + result = runScript(script, source.url().string().isNull()); + } + ChromiumBridge::traceEventEnd("v8.run", node, ""); + return result; +} + +v8::Local<v8::Value> V8Proxy::runScript(v8::Handle<v8::Script> script, bool isInlineCode) +{ + if (script.IsEmpty()) + return notHandledByInterceptor(); + + // Compute the source string and prevent against infinite recursion. + if (m_recursion >= kMaxRecursionDepth) { + v8::Local<v8::String> code = v8ExternalString("throw RangeError('Recursion too deep')"); + // FIXME: Ideally, we should be able to re-use the origin of the + // script passed to us as the argument instead of using an empty string + // and 0 baseLine. + script = compileScript(code, "", 0); + } + + if (handleOutOfMemory()) + ASSERT(script.IsEmpty()); + + if (script.IsEmpty()) + return notHandledByInterceptor(); + + // Save the previous value of the inlineCode flag and update the flag for + // the duration of the script invocation. + bool previousInlineCode = inlineCode(); + setInlineCode(isInlineCode); + + // Run the script and keep track of the current recursion depth. + v8::Local<v8::Value> result; + { + V8ConsoleMessage::Scope scope; + m_recursion++; + + // See comment in V8Proxy::callFunction. + m_frame->keepAlive(); + + result = script->Run(); + m_recursion--; + } + + if (handleOutOfMemory()) + ASSERT(result.IsEmpty()); + + // Handle V8 internal error situation (Out-of-memory). + if (result.IsEmpty()) + return notHandledByInterceptor(); + + // Restore inlineCode flag. + setInlineCode(previousInlineCode); + + if (v8::V8::IsDead()) + handleFatalErrorInV8(); + + return result; +} + +v8::Local<v8::Value> V8Proxy::callFunction(v8::Handle<v8::Function> function, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> args[]) +{ + // For now, we don't put any artificial limitations on the depth + // of recursion that stems from calling functions. This is in + // contrast to the script evaluations. + v8::Local<v8::Value> result; + { + V8ConsoleMessage::Scope scope; + + // Evaluating the JavaScript could cause the frame to be deallocated, + // so we start the keep alive timer here. + // Frame::keepAlive method adds the ref count of the frame and sets a + // timer to decrease the ref count. It assumes that the current JavaScript + // execution finishs before firing the timer. + m_frame->keepAlive(); + + result = function->Call(receiver, argc, args); + } + + if (v8::V8::IsDead()) + handleFatalErrorInV8(); + + return result; +} + +v8::Local<v8::Value> V8Proxy::newInstance(v8::Handle<v8::Function> constructor, int argc, v8::Handle<v8::Value> args[]) +{ + // No artificial limitations on the depth of recursion, see comment in + // V8Proxy::callFunction. + v8::Local<v8::Value> result; + { + V8ConsoleMessage::Scope scope; + + // See comment in V8Proxy::callFunction. + m_frame->keepAlive(); + + result = constructor->NewInstance(argc, args); + } + + if (v8::V8::IsDead()) + handleFatalErrorInV8(); + + return result; +} + +v8::Local<v8::Object> V8Proxy::createWrapperFromCache(V8ClassIndex::V8WrapperType type) +{ + int classIndex = V8ClassIndex::ToInt(type); + v8::Local<v8::Object> clone(m_wrapperBoilerplates->CloneElementAt(classIndex)); + if (!clone.IsEmpty()) + return clone; + + // Not in cache. + initContextIfNeeded(); + v8::Context::Scope scope(m_context); + v8::Local<v8::Function> function = V8DOMWrapper::getConstructor(type, getHiddenObjectPrototype(m_context)); + v8::Local<v8::Object> instance = SafeAllocation::newInstance(function); + if (!instance.IsEmpty()) { + m_wrapperBoilerplates->Set(v8::Integer::New(classIndex), instance); + return instance->Clone(); + } + return notHandledByInterceptor(); +} + +bool V8Proxy::isContextInitialized() +{ + // m_context, m_global, and m_wrapperBoilerplates should + // all be non-empty if if m_context is non-empty. + ASSERT(m_context.IsEmpty() || !m_global.IsEmpty()); + ASSERT(m_context.IsEmpty() || !m_wrapperBoilerplates.IsEmpty()); + return !m_context.IsEmpty(); +} + +DOMWindow* V8Proxy::retrieveWindow(v8::Handle<v8::Context> context) +{ + v8::Handle<v8::Object> global = context->Global(); + ASSERT(!global.IsEmpty()); + global = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, global); + ASSERT(!global.IsEmpty()); + return V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, global); +} + +Frame* V8Proxy::retrieveFrame(v8::Handle<v8::Context> context) +{ + return retrieveWindow(context)->frame(); +} + +Frame* V8Proxy::retrieveFrameForEnteredContext() +{ + v8::Handle<v8::Context> context = v8::Context::GetEntered(); + if (context.IsEmpty()) + return 0; + return retrieveFrame(context); +} + +Frame* V8Proxy::retrieveFrameForCurrentContext() +{ + v8::Handle<v8::Context> context = v8::Context::GetCurrent(); + if (context.IsEmpty()) + return 0; + return retrieveFrame(context); +} + +Frame* V8Proxy::retrieveFrameForCallingContext() +{ + v8::Handle<v8::Context> context = v8::Context::GetCalling(); + if (context.IsEmpty()) + return 0; + return retrieveFrame(context); +} + +V8Proxy* V8Proxy::retrieve() +{ + DOMWindow* window = retrieveWindow(currentContext()); + ASSERT(window); + return retrieve(window->frame()); +} + +V8Proxy* V8Proxy::retrieve(Frame* frame) +{ + if (!frame) + return 0; + return frame->script()->isEnabled() ? frame->script()->proxy() : 0; +} + +V8Proxy* V8Proxy::retrieve(ScriptExecutionContext* context) +{ + if (!context->isDocument()) + return 0; + return retrieve(static_cast<Document*>(context)->frame()); +} + +void V8Proxy::disconnectFrame() +{ + disconnectEventListeners(); +} + +bool V8Proxy::isEnabled() +{ + Settings* settings = m_frame->settings(); + if (!settings) + return false; + + // In the common case, JavaScript is enabled and we're done. + if (settings->isJavaScriptEnabled()) + return true; + + // If JavaScript has been disabled, we need to look at the frame to tell + // whether this script came from the web or the embedder. Scripts from the + // embedder are safe to run, but scripts from the other sources are + // disallowed. + Document* document = m_frame->document(); + if (!document) + return false; + + SecurityOrigin* origin = document->securityOrigin(); + if (origin->protocol().isEmpty()) + return false; // Uninitialized document + + if (origin->protocol() == "http" || origin->protocol() == "https") + return false; // Web site + + // FIXME: the following are application decisions, and they should + // not be made at this layer. instead, we should bridge out to the + // embedder to allow them to override policy here. + + if (origin->protocol() == ChromiumBridge::uiResourceProtocol()) + return true; // Embedder's scripts are ok to run + + // If the scheme is ftp: or file:, an empty file name indicates a directory + // listing, which requires JavaScript to function properly. + const char* kDirProtocols[] = { "ftp", "file" }; + for (size_t i = 0; i < arraysize(kDirProtocols); ++i) { + if (origin->protocol() == kDirProtocols[i]) { + const KURL& url = document->url(); + return url.pathAfterLastSlash() == url.pathEnd(); + } + } + + return false; // Other protocols fall through to here +} + +void V8Proxy::updateDocumentWrapper(v8::Handle<v8::Value> wrapper) +{ + clearDocumentWrapper(); + + ASSERT(m_document.IsEmpty()); + m_document = v8::Persistent<v8::Value>::New(wrapper); +#ifndef NDEBUG + V8GCController::registerGlobalHandle(PROXY, this, m_document); +#endif +} + +void V8Proxy::clearDocumentWrapper() +{ + if (!m_document.IsEmpty()) { +#ifndef NDEBUG + V8GCController::unregisterGlobalHandle(this, m_document); +#endif + m_document.Dispose(); + m_document.Clear(); + } +} + +void V8Proxy::updateDocumentWrapperCache() +{ + v8::HandleScope handleScope; + v8::Context::Scope contextScope(context()); + + // If the document has no frame, NodeToV8Object might get the + // document wrapper for a document that is about to be deleted. + // If the ForceSet below causes a garbage collection, the document + // might get deleted and the global handle for the document + // wrapper cleared. Using the cleared global handle will lead to + // crashes. In this case we clear the cache and let the DOMWindow + // accessor handle access to the document. + if (!m_frame->document()->frame()) { + clearDocumentWrapperCache(); + return; + } + + v8::Handle<v8::Value> documentWrapper = V8DOMWrapper::convertNodeToV8Object(m_frame->document()); + + // If instantiation of the document wrapper fails, clear the cache + // and let the DOMWindow accessor handle access to the document. + if (documentWrapper.IsEmpty()) { + clearDocumentWrapperCache(); + return; + } + m_context->Global()->ForceSet(v8::String::New("document"), documentWrapper, static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete)); +} + +void V8Proxy::clearDocumentWrapperCache() +{ + ASSERT(!m_context.IsEmpty()); + m_context->Global()->ForceDelete(v8::String::New("document")); +} + +void V8Proxy::disposeContextHandles() +{ + if (!m_context.IsEmpty()) { + m_frame->loader()->client()->didDestroyScriptContextForFrame(); + m_context.Dispose(); + m_context.Clear(); + } + + if (!m_wrapperBoilerplates.IsEmpty()) { +#ifndef NDEBUG + V8GCController::unregisterGlobalHandle(this, m_wrapperBoilerplates); +#endif + m_wrapperBoilerplates.Dispose(); + m_wrapperBoilerplates.Clear(); + } +} + +void V8Proxy::clearForClose() +{ + if (!m_context.IsEmpty()) { + v8::HandleScope handleScope; + + clearDocumentWrapper(); + disposeContextHandles(); + } +} + +void V8Proxy::clearForNavigation() +{ + disconnectEventListeners(); + + if (!m_context.IsEmpty()) { + v8::HandleScope handle; + clearDocumentWrapper(); + + v8::Context::Scope contextScope(m_context); + + // Clear the document wrapper cache before turning on access checks on + // the old DOMWindow wrapper. This way, access to the document wrapper + // will be protected by the security checks on the DOMWindow wrapper. + clearDocumentWrapperCache(); + + // Turn on access check on the old DOMWindow wrapper. + v8::Handle<v8::Object> wrapper = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, m_global); + ASSERT(!wrapper.IsEmpty()); + wrapper->TurnOnAccessCheck(); + + // Separate the context from its global object. + m_context->DetachGlobal(); + + disposeContextHandles(); + } +} + +void V8Proxy::setSecurityToken() +{ + Document* document = m_frame->document(); + // Setup security origin and security token. + if (!document) { + m_context->UseDefaultSecurityToken(); + return; + } + + // Ask the document's SecurityOrigin to generate a security token. + // If two tokens are equal, then the SecurityOrigins canAccess each other. + // If two tokens are not equal, then we have to call canAccess. + // Note: we can't use the HTTPOrigin if it was set from the DOM. + SecurityOrigin* origin = document->securityOrigin(); + String token; + if (!origin->domainWasSetInDOM()) + token = document->securityOrigin()->toString(); + + // An empty or "null" token means we always have to call + // canAccess. The toString method on securityOrigins returns the + // string "null" for empty security origins and for security + // origins that should only allow access to themselves. In this + // case, we use the global object as the security token to avoid + // calling canAccess when a script accesses its own objects. + if (token.isEmpty() || token == "null") { + m_context->UseDefaultSecurityToken(); + return; + } + + CString utf8Token = token.utf8(); + // NOTE: V8 does identity comparison in fast path, must use a symbol + // as the security token. + m_context->SetSecurityToken(v8::String::NewSymbol(utf8Token.data(), utf8Token.length())); +} + +void V8Proxy::updateDocument() +{ + if (!m_frame->document()) + return; + + if (m_global.IsEmpty()) + return; + + // There is an existing JavaScript wrapper for the global object + // of this frame. JavaScript code in other frames might hold a + // reference to this wrapper. We eagerly initialize the JavaScript + // context for the new document to make property access on the + // global object wrapper succeed. + initContextIfNeeded(); + + // We have a new document and we need to update the cache. + updateDocumentWrapperCache(); + + updateSecurityOrigin(); +} + +void V8Proxy::updateSecurityOrigin() +{ + v8::HandleScope scope; + setSecurityToken(); +} + +// Same origin policy implementation: +// +// Same origin policy prevents JS code from domain A access JS & DOM objects +// in a different domain B. There are exceptions and several objects are +// accessible by cross-domain code. For example, the window.frames object is +// accessible by code from a different domain, but window.document is not. +// +// The binding code sets security check callbacks on a function template, +// and accessing instances of the template calls the callback function. +// The callback function checks same origin policy. +// +// Callback functions are expensive. V8 uses a security token string to do +// fast access checks for the common case where source and target are in the +// same domain. A security token is a string object that represents +// the protocol/url/port of a domain. +// +// There are special cases where a security token matching is not enough. +// For example, JavaScript can set its domain to a super domain by calling +// document.setDomain(...). In these cases, the binding code can reset +// a context's security token to its global object so that the fast access +// check will always fail. + +// Check if the current execution context can access a target frame. +// First it checks same domain policy using the lexical context +// +// This is equivalent to KJS::Window::allowsAccessFrom(ExecState*, String&). +bool V8Proxy::canAccessPrivate(DOMWindow* targetWindow) +{ + ASSERT(targetWindow); + + String message; + + DOMWindow* originWindow = retrieveWindow(currentContext()); + if (originWindow == targetWindow) + return true; + + if (!originWindow) + return false; + + const SecurityOrigin* activeSecurityOrigin = originWindow->securityOrigin(); + const SecurityOrigin* targetSecurityOrigin = targetWindow->securityOrigin(); + + // We have seen crashes were the security origin of the target has not been + // initialized. Defend against that. + if (!targetSecurityOrigin) + return false; + + if (activeSecurityOrigin->canAccess(targetSecurityOrigin)) + return true; + + // Allow access to a "about:blank" page if the dynamic context is a + // detached context of the same frame as the blank page. + if (targetSecurityOrigin->isEmpty() && originWindow->frame() == targetWindow->frame()) + return true; + + return false; +} + +bool V8Proxy::canAccessFrame(Frame* target, bool reportError) +{ + // The subject is detached from a frame, deny accesses. + if (!target) + return false; + + if (!canAccessPrivate(target->domWindow())) { + if (reportError) + reportUnsafeAccessTo(target, ReportNow); + return false; + } + return true; +} + +bool V8Proxy::checkNodeSecurity(Node* node) +{ + if (!node) + return false; + + Frame* target = node->document()->frame(); + + if (!target) + return false; + + return canAccessFrame(target, true); +} + +v8::Persistent<v8::Context> V8Proxy::createNewContext(v8::Handle<v8::Object> global, int extensionGroup) +{ + v8::Persistent<v8::Context> result; + + // The activeDocumentLoader pointer could be NULL during frame shutdown. + if (!m_frame->loader()->activeDocumentLoader()) + return result; + + // Create a new environment using an empty template for the shadow + // object. Reuse the global object if one has been created earlier. + v8::Persistent<v8::ObjectTemplate> globalTemplate = V8DOMWindow::GetShadowObjectTemplate(); + if (globalTemplate.IsEmpty()) + return result; + + // Install a security handler with V8. + globalTemplate->SetAccessCheckCallbacks(V8Custom::v8DOMWindowNamedSecurityCheck, V8Custom::v8DOMWindowIndexedSecurityCheck, v8::Integer::New(V8ClassIndex::DOMWINDOW)); + + // Dynamically tell v8 about our extensions now. + OwnArrayPtr<const char*> extensionNames(new const char*[m_extensions.size()]); + int index = 0; + for (V8ExtensionList::iterator it = m_extensions.begin(); it != m_extensions.end(); ++it) { + if (it->group && it->group != extensionGroup) + continue; + + // Note: we check the loader URL here instead of the document URL + // because we might be currently loading an URL into a blank page. + // See http://code.google.com/p/chromium/issues/detail?id=10924 + if (it->scheme.length() > 0 && (it->scheme != m_frame->loader()->activeDocumentLoader()->url().protocol() || it->scheme != m_frame->page()->mainFrame()->loader()->activeDocumentLoader()->url().protocol())) + continue; + + extensionNames[index++] = it->extension->name(); + } + v8::ExtensionConfiguration extensions(index, extensionNames.get()); + result = v8::Context::New(&extensions, globalTemplate, global); + + return result; +} + +bool V8Proxy::installDOMWindow(v8::Handle<v8::Context> context, DOMWindow* window) +{ + v8::Handle<v8::String> implicitProtoString = v8::String::New("__proto__"); + if (implicitProtoString.IsEmpty()) + return false; + + // Create a new JS window object and use it as the prototype for the shadow global object. + v8::Handle<v8::Function> windowConstructor = V8DOMWrapper::getConstructor(V8ClassIndex::DOMWINDOW, getHiddenObjectPrototype(context)); + v8::Local<v8::Object> jsWindow = SafeAllocation::newInstance(windowConstructor); + // Bail out if allocation failed. + if (jsWindow.IsEmpty()) + return false; + + // Wrap the window. + V8DOMWrapper::setDOMWrapper(jsWindow, V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), window); + + window->ref(); + V8DOMWrapper::setJSWrapperForDOMObject(window, v8::Persistent<v8::Object>::New(jsWindow)); + + // Insert the window instance as the prototype of the shadow object. + v8::Handle<v8::Object> v8Global = context->Global(); + v8Global->Set(implicitProtoString, jsWindow); + return true; +} + +// Create a new environment and setup the global object. +// +// The global object corresponds to a DOMWindow instance. However, to +// allow properties of the JS DOMWindow instance to be shadowed, we +// use a shadow object as the global object and use the JS DOMWindow +// instance as the prototype for that shadow object. The JS DOMWindow +// instance is undetectable from javascript code because the __proto__ +// accessors skip that object. +// +// The shadow object and the DOMWindow instance are seen as one object +// from javascript. The javascript object that corresponds to a +// DOMWindow instance is the shadow object. When mapping a DOMWindow +// instance to a V8 object, we return the shadow object. +// +// To implement split-window, see +// 1) https://bugs.webkit.org/show_bug.cgi?id=17249 +// 2) https://wiki.mozilla.org/Gecko:SplitWindow +// 3) https://bugzilla.mozilla.org/show_bug.cgi?id=296639 +// we need to split the shadow object further into two objects: +// an outer window and an inner window. The inner window is the hidden +// prototype of the outer window. The inner window is the default +// global object of the context. A variable declared in the global +// scope is a property of the inner window. +// +// The outer window sticks to a Frame, it is exposed to JavaScript +// via window.window, window.self, window.parent, etc. The outer window +// has a security token which is the domain. The outer window cannot +// have its own properties. window.foo = 'x' is delegated to the +// inner window. +// +// When a frame navigates to a new page, the inner window is cut off +// the outer window, and the outer window identify is preserved for +// the frame. However, a new inner window is created for the new page. +// If there are JS code holds a closure to the old inner window, +// it won't be able to reach the outer window via its global object. +void V8Proxy::initContextIfNeeded() +{ + // Bail out if the context has already been initialized. + if (!m_context.IsEmpty()) + return; + + // Create a handle scope for all local handles. + v8::HandleScope handleScope; + + // Setup the security handlers and message listener. This only has + // to be done once. + static bool isV8Initialized = false; + if (!isV8Initialized) { + // Tells V8 not to call the default OOM handler, binding code + // will handle it. + v8::V8::IgnoreOutOfMemoryException(); + v8::V8::SetFatalErrorHandler(reportFatalErrorInV8); + + v8::V8::SetGlobalGCPrologueCallback(&V8GCController::gcPrologue); + v8::V8::SetGlobalGCEpilogueCallback(&V8GCController::gcEpilogue); + + v8::V8::AddMessageListener(&V8ConsoleMessage::handler); + + v8::V8::SetFailedAccessCheckCallbackFunction(reportUnsafeJavaScriptAccess); + + isV8Initialized = true; + } + + m_context = createNewContext(m_global, 0); + if (m_context.IsEmpty()) + return; + + // Starting from now, use local context only. + v8::Local<v8::Context> v8Context = context(); + v8::Context::Scope contextScope(v8Context); + + // Store the first global object created so we can reuse it. + if (m_global.IsEmpty()) { + m_global = v8::Persistent<v8::Object>::New(v8Context->Global()); + // Bail out if allocation of the first global objects fails. + if (m_global.IsEmpty()) { + disposeContextHandles(); + return; + } +#ifndef NDEBUG + V8GCController::registerGlobalHandle(PROXY, this, m_global); +#endif + } + + installHiddenObjectPrototype(m_context); + m_wrapperBoilerplates = v8::Persistent<v8::Array>::New(v8::Array::New(V8ClassIndex::WRAPPER_TYPE_COUNT)); + // Bail out if allocation failed. + if (m_wrapperBoilerplates.IsEmpty()) { + disposeContextHandles(); + return; + } +#ifndef NDEBUG + V8GCController::registerGlobalHandle(PROXY, this, m_wrapperBoilerplates); +#endif + + if (!installDOMWindow(v8Context, m_frame->domWindow())) + disposeContextHandles(); + + updateDocument(); + + setSecurityToken(); + + m_frame->loader()->client()->didCreateScriptContextForFrame(); + m_frame->loader()->dispatchWindowObjectAvailable(); +} + +void V8Proxy::setDOMException(int exceptionCode) +{ + if (exceptionCode <= 0) + return; + + ExceptionCodeDescription description; + getExceptionCodeDescription(exceptionCode, description); + + v8::Handle<v8::Value> exception; + switch (description.type) { + case DOMExceptionType: + exception = V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMCOREEXCEPTION, DOMCoreException::create(description)); + break; + case RangeExceptionType: + exception = V8DOMWrapper::convertToV8Object(V8ClassIndex::RANGEEXCEPTION, RangeException::create(description)); + break; + case EventExceptionType: + exception = V8DOMWrapper::convertToV8Object(V8ClassIndex::EVENTEXCEPTION, EventException::create(description)); + break; + case XMLHttpRequestExceptionType: + exception = V8DOMWrapper::convertToV8Object(V8ClassIndex::XMLHTTPREQUESTEXCEPTION, XMLHttpRequestException::create(description)); + break; +#if ENABLE(SVG) + case SVGExceptionType: + exception = V8DOMWrapper::convertToV8Object(V8ClassIndex::SVGEXCEPTION, SVGException::create(description)); + break; +#endif +#if ENABLE(XPATH) + case XPathExceptionType: + exception = V8DOMWrapper::convertToV8Object(V8ClassIndex::XPATHEXCEPTION, XPathException::create(description)); + break; +#endif + } + + ASSERT(!exception.IsEmpty()); + v8::ThrowException(exception); +} + +v8::Handle<v8::Value> V8Proxy::throwError(ErrorType type, const char* message) +{ + switch (type) { + case RangeError: + return v8::ThrowException(v8::Exception::RangeError(v8String(message))); + case ReferenceError: + return v8::ThrowException(v8::Exception::ReferenceError(v8String(message))); + case SyntaxError: + return v8::ThrowException(v8::Exception::SyntaxError(v8String(message))); + case TypeError: + return v8::ThrowException(v8::Exception::TypeError(v8String(message))); + case GeneralError: + return v8::ThrowException(v8::Exception::Error(v8String(message))); + default: + ASSERT_NOT_REACHED(); + return notHandledByInterceptor(); + } +} + +v8::Local<v8::Context> V8Proxy::context(Frame* frame) +{ + v8::Local<v8::Context> context = V8Proxy::mainWorldContext(frame); + if (context.IsEmpty()) + return v8::Local<v8::Context>(); + + if (V8IsolatedWorld* world = V8IsolatedWorld::getEntered()) { + context = v8::Local<v8::Context>::New(world->context()); + if (frame != V8Proxy::retrieveFrame(context)) + return v8::Local<v8::Context>(); + } + + return context; +} + +v8::Local<v8::Context> V8Proxy::mainWorldContext(Frame* frame) +{ + V8Proxy* proxy = retrieve(frame); + if (!proxy) + return v8::Local<v8::Context>(); + + proxy->initContextIfNeeded(); + return proxy->context(); +} + +v8::Local<v8::Context> V8Proxy::currentContext() +{ + return v8::Context::GetCurrent(); +} + +v8::Handle<v8::Value> V8Proxy::checkNewLegal(const v8::Arguments& args) +{ + if (!AllowAllocation::m_current) + return throwError(TypeError, "Illegal constructor"); + + return args.This(); +} + +void V8Proxy::bindJsObjectToWindow(Frame* frame, const char* name, int type, v8::Handle<v8::FunctionTemplate> descriptor, void* impl) +{ + // Get environment. + v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(frame); + if (v8Context.IsEmpty()) + return; // JS not enabled. + + v8::Context::Scope scope(v8Context); + v8::Handle<v8::Object> instance = descriptor->GetFunction(); + V8DOMWrapper::setDOMWrapper(instance, type, impl); + + v8::Handle<v8::Object> global = v8Context->Global(); + global->Set(v8::String::New(name), instance); +} + +void V8Proxy::processConsoleMessages() +{ + V8ConsoleMessage::processDelayed(); +} + +// Create the utility context for holding JavaScript functions used internally +// which are not visible to JavaScript executing on the page. +void V8Proxy::createUtilityContext() +{ + ASSERT(m_utilityContext.IsEmpty()); + + v8::HandleScope scope; + v8::Handle<v8::ObjectTemplate> globalTemplate = v8::ObjectTemplate::New(); + m_utilityContext = v8::Context::New(0, globalTemplate); + v8::Context::Scope contextScope(m_utilityContext); + + // Compile JavaScript function for retrieving the source line of the top + // JavaScript stack frame. + DEFINE_STATIC_LOCAL(const char*, frameSourceLineSource, + ("function frameSourceLine(exec_state) {" + " return exec_state.frame(0).sourceLine();" + "}")); + v8::Script::Compile(v8::String::New(frameSourceLineSource))->Run(); + + // Compile JavaScript function for retrieving the source name of the top + // JavaScript stack frame. + DEFINE_STATIC_LOCAL(const char*, frameSourceNameSource, + ("function frameSourceName(exec_state) {" + " var frame = exec_state.frame(0);" + " if (frame.func().resolved() && " + " frame.func().script() && " + " frame.func().script().name()) {" + " return frame.func().script().name();" + " }" + "}")); + v8::Script::Compile(v8::String::New(frameSourceNameSource))->Run(); +} + +int V8Proxy::sourceLineNumber() +{ + v8::HandleScope scope; + v8::Handle<v8::Context> v8UtilityContext = V8Proxy::utilityContext(); + if (v8UtilityContext.IsEmpty()) + return 0; + v8::Context::Scope contextScope(v8UtilityContext); + v8::Handle<v8::Function> frameSourceLine; + frameSourceLine = v8::Local<v8::Function>::Cast(v8UtilityContext->Global()->Get(v8::String::New("frameSourceLine"))); + if (frameSourceLine.IsEmpty()) + return 0; + v8::Handle<v8::Value> result = v8::Debug::Call(frameSourceLine); + if (result.IsEmpty()) + return 0; + return result->Int32Value(); +} + +String V8Proxy::sourceName() +{ + v8::HandleScope scope; + v8::Handle<v8::Context> v8UtilityContext = utilityContext(); + if (v8UtilityContext.IsEmpty()) + return String(); + v8::Context::Scope contextScope(v8UtilityContext); + v8::Handle<v8::Function> frameSourceName; + frameSourceName = v8::Local<v8::Function>::Cast(v8UtilityContext->Global()->Get(v8::String::New("frameSourceName"))); + if (frameSourceName.IsEmpty()) + return String(); + return toWebCoreString(v8::Debug::Call(frameSourceName)); +} + +void V8Proxy::registerExtensionWithV8(v8::Extension* extension) { + // If the extension exists in our list, it was already registered with V8. + for (V8ExtensionList::iterator it = m_extensions.begin(); it != m_extensions.end(); ++it) { + if (it->extension == extension) + return; + } + + v8::RegisterExtension(extension); +} + +void V8Proxy::registerExtension(v8::Extension* extension, const String& schemeRestriction) +{ + registerExtensionWithV8(extension); + V8ExtensionInfo info = {schemeRestriction, 0, extension}; + m_extensions.push_back(info); +} + +void V8Proxy::registerExtension(v8::Extension* extension, int extensionGroup) +{ + registerExtensionWithV8(extension); + V8ExtensionInfo info = {String(), extensionGroup, extension}; + m_extensions.push_back(info); +} + +bool V8Proxy::setContextDebugId(int debugId) +{ + ASSERT(debugId > 0); + if (m_context.IsEmpty()) + return false; + v8::HandleScope scope; + if (!m_context->GetData()->IsUndefined()) + return false; + + v8::Context::Scope contextScope(m_context); + v8::Handle<v8::Object> contextData = v8::Object::New(); + contextData->Set(v8::String::New(kContextDebugDataType), v8::String::New("page")); + contextData->Set(v8::String::New(kContextDebugDataValue), v8::Integer::New(debugId)); + m_context->SetData(contextData); + return true; +} + +int V8Proxy::contextDebugId(v8::Handle<v8::Context> context) +{ + v8::HandleScope scope; + if (!context->GetData()->IsObject()) + return -1; + v8::Handle<v8::Value> data = context->GetData()->ToObject()->Get( v8::String::New(kContextDebugDataValue)); + return data->IsInt32() ? data->Int32Value() : -1; +} + +v8::Handle<v8::Value> V8Proxy::getHiddenObjectPrototype(v8::Handle<v8::Context> context) +{ + return context->Global()->GetHiddenValue(V8HiddenPropertyName::objectPrototype()); +} + +void V8Proxy::installHiddenObjectPrototype(v8::Handle<v8::Context> context) +{ + v8::Handle<v8::String> objectString = v8::String::New("Object"); + v8::Handle<v8::String> prototypeString = v8::String::New("prototype"); + v8::Handle<v8::String> hiddenObjectPrototypeString = V8HiddenPropertyName::objectPrototype(); + // Bail out if allocation failed. + if (objectString.IsEmpty() || prototypeString.IsEmpty() || hiddenObjectPrototypeString.IsEmpty()) + return; + + v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(context->Global()->Get(objectString)); + v8::Handle<v8::Value> objectPrototype = object->Get(prototypeString); + + context->Global()->SetHiddenValue(hiddenObjectPrototypeString, objectPrototype); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/V8Proxy.h b/WebCore/bindings/v8/V8Proxy.h index c21e0dd..caa991c 100644 --- a/WebCore/bindings/v8/V8Proxy.h +++ b/WebCore/bindings/v8/V8Proxy.h @@ -31,12 +31,437 @@ #ifndef V8Proxy_h #define V8Proxy_h -// FIXME: This is a temporary forwarding header until all bindings have migrated -// over and v8_proxy actually becomes V8Proxy. -#include "v8_proxy.h" +#include "ChromiumBridge.h" +#include "Node.h" +#include "NodeFilter.h" +#include "PlatformString.h" // for WebCore::String +#include "ScriptSourceCode.h" // for WebCore::ScriptSourceCode +#include "SecurityOrigin.h" // for WebCore::SecurityOrigin +#include "V8CustomBinding.h" +#include "V8DOMMap.h" +#include "V8DOMWrapper.h" +#include "V8EventListenerList.h" +#include "V8GCController.h" +#include "V8Index.h" +#include "V8Utilities.h" +#include <v8.h> +#include <wtf/Assertions.h> +#include <wtf/PassRefPtr.h> // so generated bindings don't have to +#include <wtf/Vector.h> + +#include <iterator> +#include <list> + +#ifdef ENABLE_DOM_STATS_COUNTERS +#define INC_STATS(name) ChromiumBridge::incrementStatsCounter(name) +#else +#define INC_STATS(name) +#endif namespace WebCore { + class CSSRule; + class CSSRuleList; + class CSSStyleDeclaration; + class CSSValue; + class CSSValueList; + class ClientRectList; + class DOMImplementation; + class DOMWindow; + class Document; + class Element; + class Event; + class EventListener; + class EventTarget; + class Frame; + class HTMLCollection; + class HTMLDocument; + class HTMLElement; + class HTMLOptionsCollection; + class MediaList; + class MimeType; + class MimeTypeArray; + class NamedNodeMap; + class Navigator; + class Node; + class NodeFilter; + class NodeList; + class Plugin; + class PluginArray; + class SVGElement; +#if ENABLE(SVG) + class SVGElementInstance; +#endif + class Screen; + class ScriptExecutionContext; +#if ENABLE(DOM_STORAGE) + class Storage; + class StorageEvent; +#endif + class String; + class StyleSheet; + class StyleSheetList; + class V8EventListener; + class V8ObjectEventListener; + + // FIXME: use standard logging facilities in WebCore. + void logInfo(Frame*, const String& message, const String& url); + + // The following Batch structs and methods are used for setting multiple + // properties on an ObjectTemplate, used from the generated bindings + // initialization (ConfigureXXXTemplate). This greatly reduces the binary + // size by moving from code driven setup to data table driven setup. + + // BatchedAttribute translates into calls to SetAccessor() on either the + // instance or the prototype ObjectTemplate, based on |onProto|. + struct BatchedAttribute { + const char* const name; + v8::AccessorGetter getter; + v8::AccessorSetter setter; + V8ClassIndex::V8WrapperType data; + v8::AccessControl settings; + v8::PropertyAttribute attribute; + bool onProto; + }; + + void batchConfigureAttributes(v8::Handle<v8::ObjectTemplate>, v8::Handle<v8::ObjectTemplate>, const BatchedAttribute*, size_t attributeCount); + + // BatchedConstant translates into calls to Set() for setting up an object's + // constants. It sets the constant on both the FunctionTemplate and the + // ObjectTemplate. PropertyAttributes is always ReadOnly. + struct BatchedConstant { + const char* const name; + int value; + }; + + void batchConfigureConstants(v8::Handle<v8::FunctionTemplate>, v8::Handle<v8::ObjectTemplate>, const BatchedConstant*, size_t constantCount); + + const int kMaxRecursionDepth = 20; + + // Information about an extension that is registered for use with V8. If + // scheme is non-empty, it contains the URL scheme the extension should be + // used with. If group is non-zero, the extension will only be loaded into + // script contexts that belong to that group. Otherwise, the extension is + // used with all schemes and contexts. + struct V8ExtensionInfo { + String scheme; + int group; + v8::Extension* extension; + }; + typedef std::list<V8ExtensionInfo> V8ExtensionList; + + class V8Proxy { + public: + // The types of javascript errors that can be thrown. + enum ErrorType { + RangeError, + ReferenceError, + SyntaxError, + TypeError, + GeneralError + }; + + explicit V8Proxy(Frame* frame) : m_frame(frame), m_inlineCode(false), m_timerCallback(false), m_recursion(0) { } + + ~V8Proxy(); + + Frame* frame() { return m_frame; } + + // Clear page-specific data, but keep the global object identify. + void clearForNavigation(); + + // Clear page-specific data before shutting down the proxy object. + void clearForClose(); + + // Update document object of the frame. + void updateDocument(); + + // Update the security origin of a document + // (e.g., after setting docoument.domain). + void updateSecurityOrigin(); + + // Destroy the global object. + void destroyGlobal(); + + // FIXME: Need comment. User Gesture related. + bool inlineCode() const { return m_inlineCode; } + void setInlineCode(bool value) { m_inlineCode = value; } + + bool timerCallback() const { return m_timerCallback; } + void setTimerCallback(bool value) { m_timerCallback = value; } + + // Has the context for this proxy been initialized? + bool isContextInitialized(); + + // Disconnects the proxy from its owner frame, + // and clears all timeouts on the DOM window. + void disconnectFrame(); + + bool isEnabled(); + + V8EventListenerList* eventListeners() { return &m_eventListeners; } + V8EventListenerList* objectListeners() { return &m_objectListeners; } + +#if ENABLE(SVG) + static void setSVGContext(void*, SVGElement*); + static SVGElement* svgContext(void*); +#endif + + void setEventHandlerLineNumber(int lineNumber) { m_handlerLineNumber = lineNumber; } + void finishedWithEvent(Event*) { } + + // Evaluate JavaScript in a new isolated world. The script gets its own + // global scope, its own prototypes for intrinsic JavaScript objects (String, + // Array, and so-on), and its own wrappers for all DOM nodes and DOM + // constructors. + void evaluateInNewWorld(const Vector<ScriptSourceCode>& sources, int extensionGroup); + + // Evaluate JavaScript in a new context. The script gets its own global scope + // and its own prototypes for intrinsic JavaScript objects (String, Array, + // and so-on). It shares the wrappers for all DOM nodes and DOM constructors. + void evaluateInNewContext(const Vector<ScriptSourceCode>&, int extensionGroup); + + // Evaluate a script file in the current execution environment. + // The caller must hold an execution context. + // If cannot evalute the script, it returns an error. + v8::Local<v8::Value> evaluate(const ScriptSourceCode&, Node*); + + // Run an already compiled script. + v8::Local<v8::Value> runScript(v8::Handle<v8::Script>, bool isInlineCode); + + // Call the function with the given receiver and arguments. + v8::Local<v8::Value> callFunction(v8::Handle<v8::Function>, v8::Handle<v8::Object>, int argc, v8::Handle<v8::Value> argv[]); + + // Call the function as constructor with the given arguments. + v8::Local<v8::Value> newInstance(v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[]); + + // To create JS Wrapper objects, we create a cache of a 'boiler plate' + // object, and then simply Clone that object each time we need a new one. + // This is faster than going through the full object creation process. + v8::Local<v8::Object> createWrapperFromCache(V8ClassIndex::V8WrapperType); + + // Returns the window object associated with a context. + static DOMWindow* retrieveWindow(v8::Handle<v8::Context>); + // Returns V8Proxy object of the currently executing context. + static V8Proxy* retrieve(); + // Returns V8Proxy object associated with a frame. + static V8Proxy* retrieve(Frame*); + // Returns V8Proxy object associated with a script execution context. + static V8Proxy* retrieve(ScriptExecutionContext*); + + // Returns the frame object of the window object associated with + // a context. + static Frame* retrieveFrame(v8::Handle<v8::Context>); + + + // The three functions below retrieve WebFrame instances relating the + // currently executing JavaScript. Since JavaScript can make function calls + // across frames, though, we need to be more precise. + // + // For example, imagine that a JS function in frame A calls a function in + // frame B, which calls native code, which wants to know what the 'active' + // frame is. + // + // The 'entered context' is the context where execution first entered the + // script engine; the context that is at the bottom of the JS function stack. + // RetrieveFrameForEnteredContext() would return Frame A in our example. + // This frame is often referred to as the "dynamic global object." + // + // The 'current context' is the context the JS engine is currently inside of; + // the context that is at the top of the JS function stack. + // RetrieveFrameForCurrentContext() would return Frame B in our example. + // This frame is often referred to as the "lexical global object." + // + // Finally, the 'calling context' is the context one below the current + // context on the JS function stack. For example, if function f calls + // function g, then the calling context will be the context associated with + // f. This context is commonly used by DOM security checks because they want + // to know who called them. + // + // If you are unsure which of these functions to use, ask abarth. + // + // NOTE: These cannot be declared as inline function, because VS complains at + // linking time. + static Frame* retrieveFrameForEnteredContext(); + static Frame* retrieveFrameForCurrentContext(); + static Frame* retrieveFrameForCallingContext(); + + // Returns V8 Context of a frame. If none exists, creates + // a new context. It is potentially slow and consumes memory. + static v8::Local<v8::Context> context(Frame*); + static v8::Local<v8::Context> mainWorldContext(Frame*); + static v8::Local<v8::Context> currentContext(); + + // If the current context causes out of memory, JavaScript setting + // is disabled and it returns true. + static bool handleOutOfMemory(); + + // Check if the active execution context can access the target frame. + static bool canAccessFrame(Frame*, bool reportError); + + // Check if it is safe to access the given node from the + // current security context. + static bool checkNodeSecurity(Node*); + + static v8::Handle<v8::Value> checkNewLegal(const v8::Arguments&); + + static v8::Handle<v8::Script> compileScript(v8::Handle<v8::String> code, const String& fileName, int baseLine); + + // If the exception code is different from zero, a DOM exception is + // schedule to be thrown. + static void setDOMException(int exceptionCode); + + // Schedule an error object to be thrown. + static v8::Handle<v8::Value> throwError(ErrorType, const char* message); + + // Create an instance of a function descriptor and set to the global object + // as a named property. Used by v8_test_shell. + static void bindJsObjectToWindow(Frame*, const char* name, int type, v8::Handle<v8::FunctionTemplate>, void*); + + template <int tag, typename T> + static v8::Handle<v8::Value> constructDOMObject(const v8::Arguments&); + + // Process any pending JavaScript console messages. + static void processConsoleMessages(); + + // Function for retrieving the line number and source name for the top + // JavaScript stack frame. + static int sourceLineNumber(); + static String sourceName(); + + // Returns a local handle of the context. + v8::Local<v8::Context> context() + { + return v8::Local<v8::Context>::New(m_context); + } + + bool setContextDebugId(int id); + static int contextDebugId(v8::Handle<v8::Context>); + + static v8::Handle<v8::Value> getHiddenObjectPrototype(v8::Handle<v8::Context>); + // WARNING: Call |installHiddenObjectPrototype| only on fresh contexts! + static void installHiddenObjectPrototype(v8::Handle<v8::Context>); + + // Registers a v8 extension to be available on webpages. The two forms + // offer various restrictions on what types of contexts the extension is + // loaded into. If a scheme is provided, only pages whose URL has the given + // scheme will match. If extensionGroup is provided, the extension will + // only be loaded into scripts run via evaluateInNewWorld with the + // matching group. Will only affect v8 contexts initialized after this + // call. Takes ownership of the v8::Extension object passed. + static void registerExtension(v8::Extension*, const String& schemeRestriction); + static void registerExtension(v8::Extension*, int extensionGroup); + + // FIXME: Separate these concerns from V8Proxy? + v8::Persistent<v8::Context> createNewContext(v8::Handle<v8::Object> global, int extensionGroup); + static bool installDOMWindow(v8::Handle<v8::Context> context, DOMWindow* window); + + void initContextIfNeeded(); + void updateDocumentWrapper(v8::Handle<v8::Value> wrapper); + + private: + static const char* kContextDebugDataType; + static const char* kContextDebugDataValue; + + void disconnectEventListeners(); + void setSecurityToken(); + void clearDocumentWrapper(); + + // The JavaScript wrapper for the document object is cached on the global + // object for fast access. UpdateDocumentWrapperCache sets the wrapper + // for the current document on the global object. ClearDocumentWrapperCache + // deletes the document wrapper from the global object. + void updateDocumentWrapperCache(); + void clearDocumentWrapperCache(); + + // Dispose global handles of m_contexts and friends. + void disposeContextHandles(); + + static bool canAccessPrivate(DOMWindow*); + + static const char* rangeExceptionName(int exceptionCode); + static const char* eventExceptionName(int exceptionCode); + static const char* xmlHttpRequestExceptionName(int exceptionCode); + static const char* domExceptionName(int exceptionCode); + +#if ENABLE(XPATH) + static const char* xpathExceptionName(int exceptionCode); +#endif + +#if ENABLE(SVG) + static const char* svgExceptionName(int exceptionCode); +#endif + + static void createUtilityContext(); + + // Returns a local handle of the utility context. + static v8::Local<v8::Context> utilityContext() + { + if (m_utilityContext.IsEmpty()) + createUtilityContext(); + return v8::Local<v8::Context>::New(m_utilityContext); + } + + static void registerExtensionWithV8(v8::Extension*); + + Frame* m_frame; + + v8::Persistent<v8::Context> m_context; + // For each possible type of wrapper, we keep a boilerplate object. + // The boilerplate is used to create additional wrappers of the same + // type. We keep a single persistent handle to an array of the + // activated boilerplates. + v8::Persistent<v8::Array> m_wrapperBoilerplates; + + v8::Persistent<v8::Object> m_global; + v8::Persistent<v8::Value> m_document; + + // Utility context holding JavaScript functions used internally. + static v8::Persistent<v8::Context> m_utilityContext; + + int m_handlerLineNumber; + + // A list of event listeners created for this frame, + // the list gets cleared when removing all timeouts. + V8EventListenerList m_eventListeners; + + // A list of event listeners create for XMLHttpRequest object for this frame, + // the list gets cleared when removing all timeouts. + V8EventListenerList m_objectListeners; + + // True for <a href="javascript:foo()"> and false for <script>foo()</script>. + // Only valid during execution. + bool m_inlineCode; + + // True when executing from within a timer callback. Only valid during + // execution. + bool m_timerCallback; + + // Track the recursion depth to be able to avoid too deep recursion. The V8 + // engine allows much more recursion than KJS does so we need to guard against + // excessive recursion in the binding layer. + int m_recursion; + + // List of extensions registered with the context. + static V8ExtensionList m_extensions; + }; + + template <int tag, typename T> + v8::Handle<v8::Value> V8Proxy::constructDOMObject(const v8::Arguments& args) + { + if (!args.IsConstructCall()) + return throwError(V8Proxy::TypeError, "DOM object constructor cannot be called as a function."); + + // Note: it's OK to let this RefPtr go out of scope because we also call + // SetDOMWrapper(), which effectively holds a reference to obj. + RefPtr<T> obj = T::create(); + V8DOMWrapper::setDOMWrapper(args.Holder(), tag, obj.get()); + obj->ref(); + V8DOMWrapper::setJSWrapperForDOMObject(obj.get(), v8::Persistent<v8::Object>::New(args.Holder())); + return args.Holder(); + } + + // Used by an interceptor callback that it hasn't found anything to // intercept. inline static v8::Local<v8::Object> notHandledByInterceptor() @@ -48,22 +473,15 @@ namespace WebCore { { return v8::Local<v8::Boolean>(); } - - // FIXME: Remove once migration is complete. - inline static DOMWrapperMap<void>& domObjectMap() - { - return GetDOMObjectMap(); - } - - inline v8::Handle<v8::Primitive> throwError(const char* message, V8Proxy::ErrorType type = V8Proxy::TYPE_ERROR) + inline v8::Handle<v8::Primitive> throwError(const char* message, V8Proxy::ErrorType type = V8Proxy::TypeError) { - V8Proxy::ThrowError(type, message); + V8Proxy::throwError(type, message); return v8::Undefined(); } inline v8::Handle<v8::Primitive> throwError(ExceptionCode ec) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Undefined(); } @@ -76,7 +494,7 @@ namespace WebCore { template <class T> inline v8::Handle<v8::Object> toV8(PassRefPtr<T> object, v8::Local<v8::Object> holder) { object->ref(); - V8Proxy::SetJSWrapperForDOMObject(object.get(), v8::Persistent<v8::Object>::New(holder)); + V8DOMWrapper::setJSWrapperForDOMObject(object.get(), v8::Persistent<v8::Object>::New(holder)); return holder; } diff --git a/WebCore/bindings/v8/V8SVGPODTypeWrapper.h b/WebCore/bindings/v8/V8SVGPODTypeWrapper.h new file mode 100644 index 0000000..b6e47af --- /dev/null +++ b/WebCore/bindings/v8/V8SVGPODTypeWrapper.h @@ -0,0 +1,413 @@ +/* + * Copyright (C) 2006, 2008 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Google. 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 COMPUTER, 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 COMPUTER, 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 V8SVGPODTypeWrapper_h +#define V8SVGPODTypeWrapper_h + +#if ENABLE(SVG) + +#include <utility> + +#include "SVGElement.h" +#include "SVGList.h" +#include "V8Proxy.h" + +#include <wtf/Assertions.h> +#include <wtf/HashFunctions.h> +#include <wtf/HashMap.h> +#include <wtf/RefCounted.h> +#include <wtf/StdLibExtras.h> + +namespace WebCore { + +template<typename PODType> +class V8SVGPODTypeWrapper : public RefCounted<V8SVGPODTypeWrapper<PODType> > { +public: + V8SVGPODTypeWrapper() { } + virtual ~V8SVGPODTypeWrapper() { } + virtual operator PODType() = 0; + virtual void commitChange(PODType, SVGElement*) = 0; +}; + +template<typename PODType> +class V8SVGPODTypeWrapperCreatorForList : public V8SVGPODTypeWrapper<PODType> { +public: + typedef SVGPODListItem<PODType> PODListItemPtrType; + + typedef PODType (SVGPODListItem<PODType>::*GetterMethod)() const; + typedef void (SVGPODListItem<PODType>::*SetterMethod)(PODType); + + static PassRefPtr<V8SVGPODTypeWrapperCreatorForList> create(PassRefPtr<PODListItemPtrType> creator, const QualifiedName& attributeName) + { + return adoptRef(new V8SVGPODTypeWrapperCreatorForList(creator, attributeName)); + } + + virtual ~V8SVGPODTypeWrapperCreatorForList() { } + + // Getter wrapper + virtual operator PODType() { return (m_creator.get()->*m_getter)(); } + + // Setter wrapper + virtual void commitChange(PODType type, SVGElement* context) + { + if (!m_setter) + return; + + (m_creator.get()->*m_setter)(type); + + if (context) + context->svgAttributeChanged(m_associatedAttributeName); + } + +private: + V8SVGPODTypeWrapperCreatorForList(PassRefPtr<PODListItemPtrType> creator, const QualifiedName& attributeName) + : m_creator(creator) + , m_getter(&SVGPODListItem<PODType>::value) + , m_setter(&SVGPODListItem<PODType>::setValue) + , m_associatedAttributeName(attributeName) + { + ASSERT(m_creator); + ASSERT(m_getter); + ASSERT(m_setter); + } + + // Update callbacks + RefPtr<SVGPODListItem<PODType> > m_creator; + GetterMethod m_getter; + SetterMethod m_setter; + const QualifiedName& m_associatedAttributeName; +}; + +template<typename PODType> +class V8SVGStaticPODTypeWrapper : public V8SVGPODTypeWrapper<PODType> { +public: + static PassRefPtr<V8SVGStaticPODTypeWrapper> create(PODType type) + { + return adoptRef(new V8SVGStaticPODTypeWrapper(type)); + } + + virtual ~V8SVGStaticPODTypeWrapper() { } + + // Getter wrapper + virtual operator PODType() { return m_podType; } + + // Setter wrapper + virtual void commitChange(PODType type, SVGElement*) + { + m_podType = type; + } + +protected: + V8SVGStaticPODTypeWrapper(PODType type) + : m_podType(type) + { + } + + PODType m_podType; +}; + +template<typename PODType, typename ParentTypeArg> +class V8SVGStaticPODTypeWrapperWithPODTypeParent : public V8SVGStaticPODTypeWrapper<PODType> { +public: + typedef V8SVGPODTypeWrapper<ParentTypeArg> ParentType; + + static PassRefPtr<V8SVGStaticPODTypeWrapperWithPODTypeParent> create(PODType type, PassRefPtr<ParentType> parent) + { + return adoptRef(new V8SVGStaticPODTypeWrapperWithPODTypeParent(type, parent)); + } + + virtual void commitChange(PODType type, SVGElement* context) + { + V8SVGStaticPODTypeWrapper<PODType>::commitChange(type, context); + m_parentType->commitChange(ParentTypeArg(type), context); + } + +private: + V8SVGStaticPODTypeWrapperWithPODTypeParent(PODType type, PassRefPtr<ParentType> parent) + : V8SVGStaticPODTypeWrapper<PODType>(type) + , m_parentType(parent) + { + } + + RefPtr<ParentType> m_parentType; +}; + +template<typename PODType, typename ParentType> +class V8SVGStaticPODTypeWrapperWithParent : public V8SVGPODTypeWrapper<PODType> { +public: + typedef PODType (ParentType::*GetterMethod)() const; + typedef void (ParentType::*SetterMethod)(const PODType&); + + static PassRefPtr<V8SVGStaticPODTypeWrapperWithParent> create(PassRefPtr<ParentType> parent, GetterMethod getter, SetterMethod setter) + { + return adoptRef(new V8SVGStaticPODTypeWrapperWithParent(parent, getter, setter)); + } + + virtual operator PODType() + { + return (m_parent.get()->*m_getter)(); + } + + virtual void commitChange(PODType type, SVGElement* context) + { + (m_parent.get()->*m_setter)(type); + } + +private: + V8SVGStaticPODTypeWrapperWithParent(PassRefPtr<ParentType> parent, GetterMethod getter, SetterMethod setter) + : m_parent(parent) + , m_getter(getter) + , m_setter(setter) + { + ASSERT(m_parent); + ASSERT(m_getter); + ASSERT(m_setter); + } + + RefPtr<ParentType> m_parent; + GetterMethod m_getter; + SetterMethod m_setter; +}; + +template<typename PODType, typename PODTypeCreator> +class V8SVGDynamicPODTypeWrapper : public V8SVGPODTypeWrapper<PODType> { +public: + typedef PODType (PODTypeCreator::*GetterMethod)() const; + typedef void (PODTypeCreator::*SetterMethod)(PODType); + typedef void (*CacheRemovalCallback)(V8SVGPODTypeWrapper<PODType>*); + + static PassRefPtr<V8SVGDynamicPODTypeWrapper> create(PassRefPtr<PODTypeCreator> creator, GetterMethod getter, SetterMethod setter, CacheRemovalCallback cacheRemovalCallback) + { + return adoptRef(new V8SVGDynamicPODTypeWrapper(creator, getter, setter, cacheRemovalCallback)); + } + + virtual ~V8SVGDynamicPODTypeWrapper() { + ASSERT(m_cacheRemovalCallback); + + (*m_cacheRemovalCallback)(this); + } + + // Getter wrapper + virtual operator PODType() { return (m_creator.get()->*m_getter)(); } + + // Setter wrapper + virtual void commitChange(PODType type, SVGElement* context) + { + (m_creator.get()->*m_setter)(type); + + if (context) + context->svgAttributeChanged(m_creator->associatedAttributeName()); + } + +private: + V8SVGDynamicPODTypeWrapper(PassRefPtr<PODTypeCreator> creator, GetterMethod getter, SetterMethod setter, CacheRemovalCallback cacheRemovalCallback) + : m_creator(creator) + , m_getter(getter) + , m_setter(setter) + , m_cacheRemovalCallback(cacheRemovalCallback) + { + ASSERT(m_creator); // |creator|'s pointer was taken by m_creator. + ASSERT(getter); + ASSERT(setter); + ASSERT(cacheRemovalCallback); + } + + // Update callbacks + RefPtr<PODTypeCreator> m_creator; + GetterMethod m_getter; + SetterMethod m_setter; + CacheRemovalCallback m_cacheRemovalCallback; +}; + +// Caching facilities +template<typename PODType, typename PODTypeCreator> +struct PODTypeWrapperCacheInfo { + typedef PODType (PODTypeCreator::*GetterMethod)() const; + typedef void (PODTypeCreator::*SetterMethod)(PODType); + + // Empty value + PODTypeWrapperCacheInfo() + : creator(0) + , getter(0) + , setter(0) + , fieldHash(0) + { } + + // Deleted value + explicit PODTypeWrapperCacheInfo(WTF::HashTableDeletedValueType) + : creator(reinterpret_cast<PODTypeCreator*>(-1)) + , getter(0) + , setter(0) + , fieldHash(0) + { + } + + bool isHashTableDeletedValue() const + { + return creator == reinterpret_cast<PODTypeCreator*>(-1); + } + + PODTypeWrapperCacheInfo(PODTypeCreator* _creator, GetterMethod _getter, SetterMethod _setter, unsigned _fieldHash) + : creator(_creator) + , getter(_getter) + , setter(_setter) + , fieldHash(_fieldHash) + { + ASSERT(creator); + ASSERT(getter); + } + + bool operator==(const PODTypeWrapperCacheInfo& other) const + { + return creator == other.creator && fieldHash == other.fieldHash && getter == other.getter && setter == other.setter; + } + + PODTypeCreator* creator; + GetterMethod getter; + SetterMethod setter; + unsigned fieldHash; +}; + +template<typename PODType, typename PODTypeCreator> +struct PODTypeWrapperCacheInfoHash { + static unsigned hash(const PODTypeWrapperCacheInfo<PODType, PODTypeCreator>& info) + { + // We can't hash member function pointers, but we have enough material + // to hash the pointer and field identifier, and on a collision + // operator== will still differentiate the member function pointers. + return WTF::PairHash<void*, unsigned>::hash(std::pair<void*, unsigned>(info.creator, info.fieldHash)); + } + + static bool equal(const PODTypeWrapperCacheInfo<PODType, PODTypeCreator>& a, const PODTypeWrapperCacheInfo<PODType, PODTypeCreator>& b) + { + return a == b; + } + + static const bool safeToCompareToEmptyOrDeleted = true; +}; + +template<typename PODType, typename PODTypeCreator> +struct PODTypeWrapperCacheInfoTraits : WTF::GenericHashTraits<PODTypeWrapperCacheInfo<PODType, PODTypeCreator> > { + typedef PODTypeWrapperCacheInfo<PODType, PODTypeCreator> CacheInfo; + + static const bool emptyValueIsZero = true; + static const bool needsDestruction = false; + + static const CacheInfo& emptyValue() + { + DEFINE_STATIC_LOCAL(CacheInfo, key, ()); + return key; + } + + static void constructDeletedValue(CacheInfo& slot) + { + new (&slot) CacheInfo(WTF::HashTableDeletedValue); + } + + static bool isDeletedValue(const CacheInfo& value) + { + return value.isHashTableDeletedValue(); + } +}; + +template<typename PODType, typename PODTypeCreator> +class V8SVGDynamicPODTypeWrapperCache { +public: + typedef PODType (PODTypeCreator::*GetterMethod)() const; + typedef void (PODTypeCreator::*SetterMethod)(PODType); + + typedef PODTypeWrapperCacheInfo<PODType, PODTypeCreator> CacheInfo; + typedef PODTypeWrapperCacheInfoHash<PODType, PODTypeCreator> CacheInfoHash; + typedef PODTypeWrapperCacheInfoTraits<PODType, PODTypeCreator> CacheInfoTraits; + + typedef V8SVGPODTypeWrapper<PODType> WrapperBase; + typedef V8SVGDynamicPODTypeWrapper<PODType, PODTypeCreator> DynamicWrapper; + + typedef HashMap<CacheInfo, DynamicWrapper*, CacheInfoHash, CacheInfoTraits> DynamicWrapperHashMap; + typedef typename DynamicWrapperHashMap::const_iterator DynamicWrapperHashMapIterator; + + static DynamicWrapperHashMap& dynamicWrapperHashMap() + { + DEFINE_STATIC_LOCAL(DynamicWrapperHashMap, dynamicWrapperHashMap, ()); + return dynamicWrapperHashMap; + } + + // Used for readwrite attributes only + static PassRefPtr<WrapperBase> lookupOrCreateWrapper(PODTypeCreator* creator, GetterMethod getter, SetterMethod setter, unsigned fieldHash) + { + DynamicWrapperHashMap& map(dynamicWrapperHashMap()); + CacheInfo info(creator, getter, setter, fieldHash); + + if (map.contains(info)) + return map.get(info); + + RefPtr<DynamicWrapper> wrapper = V8SVGDynamicPODTypeWrapper<PODType, PODTypeCreator>::create(creator, getter, setter, forgetWrapper); + map.set(info, wrapper.get()); + return wrapper.release(); + } + + static void forgetWrapper(V8SVGPODTypeWrapper<PODType>* wrapper) + { + 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; + } + } +}; + +class V8SVGPODTypeUtil { +public: + template <class P> + static P toSVGPODType(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> object, bool& ok); +}; + +template <class P> +P V8SVGPODTypeUtil::toSVGPODType(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> object, bool& ok) +{ + void *wrapper = V8DOMWrapper::convertToSVGPODTypeImpl(type, object); + if (wrapper == NULL) { + ok = false; + return P(); + } else { + ok = true; + return *static_cast<V8SVGPODTypeWrapper<P>*>(wrapper); + } +} + +} // namespace WebCore + +#endif // ENABLE(SVG) +#endif // V8SVGPODTypeWrapper_h diff --git a/WebCore/bindings/v8/V8Utilities.cpp b/WebCore/bindings/v8/V8Utilities.cpp index 395a8df..c1ac6d4 100644 --- a/WebCore/bindings/v8/V8Utilities.cpp +++ b/WebCore/bindings/v8/V8Utilities.cpp @@ -58,7 +58,8 @@ void createHiddenDependency(v8::Local<v8::Object> object, v8::Local<v8::Value> v void removeHiddenDependency(v8::Local<v8::Object> object, v8::Local<v8::Value> value, int cacheIndex) { v8::Local<v8::Value> cache = object->GetInternalField(cacheIndex); - ASSERT(cache->IsArray()); + if (!cache->IsArray()) + return; v8::Local<v8::Array> cacheArray = v8::Local<v8::Array>::Cast(cache); for (int i = cacheArray->Length() - 1; i >= 0; --i) { v8::Local<v8::Value> cached = cacheArray->Get(v8::Integer::New(i)); @@ -67,9 +68,6 @@ void removeHiddenDependency(v8::Local<v8::Object> object, v8::Local<v8::Value> v return; } } - - // We should only get here if we try to remove an event listener that was never added. - ASSERT_NOT_REACHED(); } bool processingUserGesture() diff --git a/WebCore/bindings/v8/V8Utilities.h b/WebCore/bindings/v8/V8Utilities.h index fdabc7a..781d2bb 100644 --- a/WebCore/bindings/v8/V8Utilities.h +++ b/WebCore/bindings/v8/V8Utilities.h @@ -31,6 +31,7 @@ #ifndef V8Utilities_h #define V8Utilities_h +#ifdef MANUAL_MERGE_REQUIRED // FIXME: Remove once chromium dependencies on v8_utility.h are removed. #define V8UTILITIES_DEFINED 1 #if ENABLE(V8_LOCKERS) @@ -39,6 +40,8 @@ #define LOCK_V8 ((void) 0) #endif +#else // MANUAL_MERGE_REQUIRED +#endif // MANUAL_MERGE_REQUIRED #include <v8.h> namespace WebCore { @@ -80,11 +83,6 @@ namespace WebCore { static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::Function>); static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::ObjectTemplate>); static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[]); - - // FIXME: These NewInstance functions are here to ease upstreaming. Remove along with V8UTILITIES_DEFINED once chromium dependencies on v8_utility.h are removed. - static inline v8::Local<v8::Object> NewInstance(v8::Handle<v8::Function>); - static inline v8::Local<v8::Object> NewInstance(v8::Handle<v8::ObjectTemplate>); - static inline v8::Local<v8::Object> NewInstance(v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[]); }; v8::Local<v8::Object> SafeAllocation::newInstance(v8::Handle<v8::Function> function) @@ -111,22 +109,6 @@ namespace WebCore { return function->NewInstance(argc, argv); } - // FIXME: These NewInstance functions are here to ease upstreaming. Remove along with V8UTILITIES_DEFINED once chromium dependencies on v8_utility.h are removed. - v8::Local<v8::Object> SafeAllocation::NewInstance(v8::Handle<v8::Function> function) - { - return newInstance(function); - } - - v8::Local<v8::Object> SafeAllocation::NewInstance(v8::Handle<v8::ObjectTemplate> objectTemplate) - { - return newInstance(objectTemplate); - } - - v8::Local<v8::Object> SafeAllocation::NewInstance(v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[]) - { - return newInstance(function, argc, argv); - } - } // namespace WebCore #endif // V8Utilities_h diff --git a/WebCore/bindings/v8/V8WorkerContextEventListener.cpp b/WebCore/bindings/v8/V8WorkerContextEventListener.cpp index a21d3eb..9ed7e32 100644 --- a/WebCore/bindings/v8/V8WorkerContextEventListener.cpp +++ b/WebCore/bindings/v8/V8WorkerContextEventListener.cpp @@ -35,7 +35,11 @@ #include "V8WorkerContextEventListener.h" #include "Event.h" +#ifdef MANUAL_MERGE_REQUIRED #include "V8Utilities.h" +#else // MANUAL_MERGE_REQUIRED +#include "V8Binding.h" +#endif // MANUAL_MERGE_REQUIRED #include "WorkerContextExecutionProxy.h" namespace WebCore { @@ -49,7 +53,7 @@ V8WorkerContextEventListener::V8WorkerContextEventListener(WorkerContextExecutio V8WorkerContextEventListener::~V8WorkerContextEventListener() { if (m_proxy) - m_proxy->RemoveEventListener(this); + m_proxy->removeEventListener(this); disposeListenerObject(); } @@ -66,7 +70,7 @@ void V8WorkerContextEventListener::handleEvent(Event* event, bool isWindowEvent) LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = m_proxy->GetContext(); + v8::Handle<v8::Context> context = m_proxy->context(); if (context.IsEmpty()) return; @@ -74,11 +78,57 @@ void V8WorkerContextEventListener::handleEvent(Event* event, bool isWindowEvent) v8::Context::Scope scope(context); // Get the V8 wrapper for the event object. - v8::Handle<v8::Value> jsEvent = WorkerContextExecutionProxy::EventToV8Object(event); + v8::Handle<v8::Value> jsEvent = WorkerContextExecutionProxy::convertEventToV8Object(event); invokeEventHandler(context, event, jsEvent, isWindowEvent); } +bool V8WorkerContextEventListener::reportError(const String& message, const String& url, int lineNumber) +{ + // Is the EventListener disconnected? + if (disconnected()) + return false; + + // The callback function can clear the event listener and destroy 'this' object. Keep a local reference to it. + RefPtr<V8AbstractEventListener> protect(this); + + v8::HandleScope handleScope; + + v8::Handle<v8::Context> context = m_proxy->context(); + if (context.IsEmpty()) + return false; + + // Enter the V8 context in which to perform the event handling. + v8::Context::Scope scope(context); + + v8::Local<v8::Value> returnValue; + { + // Catch exceptions thrown in calling the function so they do not propagate to javascript code that caused the event to fire. + v8::TryCatch tryCatch; + tryCatch.SetVerbose(true); + + // Call the function. + if (!m_listener.IsEmpty() && m_listener->IsFunction()) { + v8::Local<v8::Function> callFunction = v8::Local<v8::Function>::New(v8::Persistent<v8::Function>::Cast(m_listener)); + v8::Local<v8::Object> thisValue = v8::Context::GetCurrent()->Global(); + + v8::Handle<v8::Value> parameters[3] = { v8String(message), v8String(url), v8::Integer::New(lineNumber) }; + returnValue = callFunction->Call(thisValue, 3, parameters); + } + + // If an error occurs while handling the script error, it should be bubbled up. + if (tryCatch.HasCaught()) { + tryCatch.Reset(); + return false; + } + } + + // If the function returns false, then the error is handled. Otherwise, the error is not handled. + bool errorHandled = returnValue->IsBoolean() && !returnValue->BooleanValue(); + + return errorHandled; +} + v8::Local<v8::Value> V8WorkerContextEventListener::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event, bool isWindowEvent) { v8::Local<v8::Function> handlerFunction = getListenerFunction(); @@ -103,7 +153,7 @@ v8::Local<v8::Object> V8WorkerContextEventListener::getReceiverObject(Event* eve return v8::Context::GetCurrent()->Global(); EventTarget* target = event->currentTarget(); - v8::Handle<v8::Value> value = WorkerContextExecutionProxy::EventTargetToV8Object(target); + v8::Handle<v8::Value> value = WorkerContextExecutionProxy::convertEventTargetToV8Object(target); if (value.IsEmpty()) return v8::Local<v8::Object>(); return v8::Local<v8::Object>::New(v8::Handle<v8::Object>::Cast(value)); diff --git a/WebCore/bindings/v8/V8WorkerContextEventListener.h b/WebCore/bindings/v8/V8WorkerContextEventListener.h index 8e56a73..c901c51 100644 --- a/WebCore/bindings/v8/V8WorkerContextEventListener.h +++ b/WebCore/bindings/v8/V8WorkerContextEventListener.h @@ -52,6 +52,7 @@ namespace WebCore { virtual ~V8WorkerContextEventListener(); virtual void handleEvent(Event*, bool isWindowEvent); + virtual bool reportError(const String& message, const String& url, int lineNumber); virtual bool disconnected() const { return !m_proxy; } WorkerContextExecutionProxy* proxy() const { return m_proxy; } diff --git a/WebCore/bindings/v8/V8WorkerContextObjectEventListener.cpp b/WebCore/bindings/v8/V8WorkerContextObjectEventListener.cpp index bec25f1..ce56563 100644 --- a/WebCore/bindings/v8/V8WorkerContextObjectEventListener.cpp +++ b/WebCore/bindings/v8/V8WorkerContextObjectEventListener.cpp @@ -43,7 +43,7 @@ static void weakObjectEventListenerCallback(v8::Persistent<v8::Value>, void* par V8WorkerContextObjectEventListener* listener = static_cast<V8WorkerContextObjectEventListener*>(parameter); // Remove the wrapper - listener->proxy()->RemoveEventListener(listener); + listener->proxy()->removeEventListener(listener); listener->disposeListenerObject(); } diff --git a/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp b/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp index c87cdea..f80d88f 100644 --- a/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp +++ b/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp @@ -35,9 +35,16 @@ #include "WorkerContextExecutionProxy.h" +#include "DOMCoreException.h" +#include "DedicatedWorkerContext.h" +#include "Event.h" +#include "EventException.h" +#include "MessagePort.h" +#include "RangeException.h" #include "V8Binding.h" +#include "V8DOMMap.h" +#include "V8Index.h" #include "V8Proxy.h" -#include "Event.h" #include "V8WorkerContextEventListener.h" #include "V8WorkerContextObjectEventListener.h" #include "Worker.h" @@ -45,48 +52,17 @@ #include "WorkerLocation.h" #include "WorkerNavigator.h" #include "WorkerScriptController.h" +#include "XMLHttpRequest.h" +#include "XMLHttpRequestException.h" namespace WebCore { -static bool isWorkersEnabled = false; - static void reportFatalErrorInV8(const char* location, const char* message) { // FIXME: We temporarily deal with V8 internal error situations such as out-of-memory by crashing the worker. CRASH(); } -static void handleConsoleMessage(v8::Handle<v8::Message> message, v8::Handle<v8::Value> data) -{ - WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve(); - if (!proxy) - return; - - WorkerContext* workerContext = proxy->workerContext(); - if (!workerContext) - return; - - v8::Handle<v8::String> errorMessageString = message->Get(); - ASSERT(!errorMessageString.IsEmpty()); - String errorMessage = ToWebCoreString(errorMessageString); - - v8::Handle<v8::Value> resourceName = message->GetScriptResourceName(); - bool useURL = (resourceName.IsEmpty() || !resourceName->IsString()); - String resourceNameString = useURL ? workerContext->url() : ToWebCoreString(resourceName); - - workerContext->addMessage(ConsoleDestination, JSMessageSource, ErrorMessageLevel, errorMessage, message->GetLineNumber(), resourceNameString); -} - -bool WorkerContextExecutionProxy::isWebWorkersEnabled() -{ - return isWorkersEnabled; -} - -void WorkerContextExecutionProxy::setIsWebWorkersEnabled(bool value) -{ - isWorkersEnabled = value; -} - WorkerContextExecutionProxy::WorkerContextExecutionProxy(WorkerContext* workerContext) : m_workerContext(workerContext) , m_recursion(0) @@ -102,8 +78,7 @@ WorkerContextExecutionProxy::~WorkerContextExecutionProxy() void WorkerContextExecutionProxy::dispose() { // Disconnect all event listeners. - if (m_listeners.get()) - { + if (m_listeners.get()) { for (V8EventListenerList::iterator iterator(m_listeners->begin()); iterator != m_listeners->end(); ++iterator) static_cast<V8WorkerContextEventListener*>(*iterator)->disconnect(); @@ -127,13 +102,16 @@ void WorkerContextExecutionProxy::dispose() WorkerContextExecutionProxy* WorkerContextExecutionProxy::retrieve() { + // Happens on frame destruction, check otherwise GetCurrent() will crash. + if (!v8::Context::InContext()) + return 0; v8::Handle<v8::Context> context = v8::Context::GetCurrent(); v8::Handle<v8::Object> global = context->Global(); - global = V8Proxy::LookupDOMWrapper(V8ClassIndex::WORKERCONTEXT, global); + global = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::WORKERCONTEXT, global); // Return 0 if the current executing context is not the worker context. if (global.IsEmpty()) return 0; - WorkerContext* workerContext = V8Proxy::ToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, global); + WorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, global); return workerContext->script()->proxy(); } @@ -149,6 +127,7 @@ void WorkerContextExecutionProxy::initV8IfNeeded() v8::V8::IgnoreOutOfMemoryException(); v8::V8::SetFatalErrorHandler(reportFatalErrorInV8); +#ifdef MANUAL_MERGE_REQUIRED // Set up the handler for V8 error message. v8::V8::AddMessageListener(handleConsoleMessage); @@ -156,6 +135,8 @@ void WorkerContextExecutionProxy::initV8IfNeeded() const int workerThreadPreemptionIntervalMs = 5; v8::Locker::StartPreemption(workerThreadPreemptionIntervalMs); #endif +#else // MANUAL_MERGE_REQUIRED +#endif // MANUAL_MERGE_REQUIRED v8Initialized = true; } @@ -177,7 +158,7 @@ void WorkerContextExecutionProxy::initContextIfNeeded() v8::Handle<v8::String> implicitProtoString = v8::String::New("__proto__"); // Create a new JS object and use it as the prototype for the shadow global object. - v8::Handle<v8::Function> workerContextConstructor = GetConstructor(V8ClassIndex::WORKERCONTEXT); + v8::Handle<v8::Function> workerContextConstructor = V8DOMWrapper::getConstructorForContext(V8ClassIndex::DEDICATEDWORKERCONTEXT, context); v8::Local<v8::Object> jsWorkerContext = SafeAllocation::newInstance(workerContextConstructor); // Bail out if allocation failed. if (jsWorkerContext.IsEmpty()) { @@ -186,9 +167,9 @@ void WorkerContextExecutionProxy::initContextIfNeeded() } // Wrap the object. - V8Proxy::SetDOMWrapper(jsWorkerContext, V8ClassIndex::ToInt(V8ClassIndex::WORKERCONTEXT), m_workerContext); + V8DOMWrapper::setDOMWrapper(jsWorkerContext, V8ClassIndex::ToInt(V8ClassIndex::DEDICATEDWORKERCONTEXT), m_workerContext); - V8Proxy::SetJSWrapperForDOMObject(m_workerContext, v8::Persistent<v8::Object>::New(jsWorkerContext)); + V8DOMWrapper::setJSWrapperForDOMObject(m_workerContext, v8::Persistent<v8::Object>::New(jsWorkerContext)); m_workerContext->ref(); // Insert the object instance as the prototype of the shadow object. @@ -198,45 +179,47 @@ void WorkerContextExecutionProxy::initContextIfNeeded() m_listeners.set(new V8EventListenerList()); } -v8::Local<v8::Function> WorkerContextExecutionProxy::GetConstructor(V8ClassIndex::V8WrapperType type) -{ - // Enter the context of the proxy to make sure that the function is - // constructed in the context corresponding to this proxy. - v8::Context::Scope scope(m_context); - v8::Handle<v8::FunctionTemplate> functionTemplate = V8Proxy::GetTemplate(type); - - // Getting the function might fail if we're running out of stack or memory. - v8::TryCatch tryCatch; - v8::Local<v8::Function> value = functionTemplate->GetFunction(); - if (value.IsEmpty()) - return v8::Local<v8::Function>(); - - return value; -} - -v8::Handle<v8::Value> WorkerContextExecutionProxy::ToV8Object(V8ClassIndex::V8WrapperType type, void* impl) +v8::Handle<v8::Value> WorkerContextExecutionProxy::convertToV8Object(V8ClassIndex::V8WrapperType type, void* impl) { if (!impl) return v8::Null(); - if (type == V8ClassIndex::WORKERCONTEXT) - return WorkerContextToV8Object(static_cast<WorkerContext*>(impl)); + if (type == V8ClassIndex::DEDICATEDWORKERCONTEXT) + return convertWorkerContextToV8Object(static_cast<WorkerContext*>(impl)); + + bool isActiveDomObject = false; + switch (type) { +#define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE: + ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) + isActiveDomObject = true; + break; +#undef MAKE_CASE + default: + break; + } - if (type == V8ClassIndex::WORKER) { + if (isActiveDomObject) { v8::Persistent<v8::Object> result = getActiveDOMObjectMap().get(impl); if (!result.IsEmpty()) return result; v8::Local<v8::Object> object = toV8(type, type, impl); - if (!object.IsEmpty()) - static_cast<Worker*>(impl)->ref(); + switch (type) { +#define MAKE_CASE(TYPE, NAME) \ + case V8ClassIndex::TYPE: static_cast<NAME*>(impl)->ref(); break; + ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE) +#undef MAKE_CASE + default: + ASSERT_NOT_REACHED(); + } + result = v8::Persistent<v8::Object>::New(object); - V8Proxy::SetJSWrapperForDOMObject(impl, result); + V8DOMWrapper::setJSWrapperForActiveDOMObject(impl, result); return result; } // Non DOM node - v8::Persistent<v8::Object> result = domObjectMap().get(impl); + v8::Persistent<v8::Object> result = getDOMObjectMap().get(impl); if (result.IsEmpty()) { v8::Local<v8::Object> object = toV8(type, type, impl); if (!object.IsEmpty()) { @@ -247,22 +230,34 @@ v8::Handle<v8::Value> WorkerContextExecutionProxy::ToV8Object(V8ClassIndex::V8Wr case V8ClassIndex::WORKERNAVIGATOR: static_cast<WorkerNavigator*>(impl)->ref(); break; + case V8ClassIndex::DOMCOREEXCEPTION: + static_cast<DOMCoreException*>(impl)->ref(); + break; + case V8ClassIndex::RANGEEXCEPTION: + static_cast<RangeException*>(impl)->ref(); + break; + case V8ClassIndex::EVENTEXCEPTION: + static_cast<EventException*>(impl)->ref(); + break; + case V8ClassIndex::XMLHTTPREQUESTEXCEPTION: + static_cast<XMLHttpRequestException*>(impl)->ref(); + break; default: ASSERT(false); } result = v8::Persistent<v8::Object>::New(object); - V8Proxy::SetJSWrapperForDOMObject(impl, result); + V8DOMWrapper::setJSWrapperForDOMObject(impl, result); } } return result; } -v8::Handle<v8::Value> WorkerContextExecutionProxy::EventToV8Object(Event* event) +v8::Handle<v8::Value> WorkerContextExecutionProxy::convertEventToV8Object(Event* event) { if (!event) return v8::Null(); - v8::Handle<v8::Object> wrapper = domObjectMap().get(event); + v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(event); if (!wrapper.IsEmpty()) return wrapper; @@ -274,73 +269,79 @@ v8::Handle<v8::Value> WorkerContextExecutionProxy::EventToV8Object(Event* event) v8::Handle<v8::Object> result = toV8(type, V8ClassIndex::EVENT, event); if (result.IsEmpty()) { // Instantiation failed. Avoid updating the DOM object map and return null which - // is already handled by callers of this function in case the event is NULL. + // is already handled by callers of this function in case the event is null. return v8::Null(); } event->ref(); // fast ref - V8Proxy::SetJSWrapperForDOMObject(event, v8::Persistent<v8::Object>::New(result)); + V8DOMWrapper::setJSWrapperForDOMObject(event, v8::Persistent<v8::Object>::New(result)); return result; } -// A JS object of type EventTarget in the worker context can only be Worker or WorkerContext. -v8::Handle<v8::Value> WorkerContextExecutionProxy::EventTargetToV8Object(EventTarget* target) +v8::Handle<v8::Value> WorkerContextExecutionProxy::convertEventTargetToV8Object(EventTarget* target) { if (!target) return v8::Null(); - WorkerContext* workerContext = target->toWorkerContext(); + DedicatedWorkerContext* workerContext = target->toDedicatedWorkerContext(); if (workerContext) - return WorkerContextToV8Object(workerContext); + return convertWorkerContextToV8Object(workerContext); Worker* worker = target->toWorker(); if (worker) - return ToV8Object(V8ClassIndex::WORKER, worker); + return convertToV8Object(V8ClassIndex::WORKER, worker); + + XMLHttpRequest* xhr = target->toXMLHttpRequest(); + if (xhr) + return convertToV8Object(V8ClassIndex::XMLHTTPREQUEST, xhr); + + MessagePort* mp = target->toMessagePort(); + if (mp) + return convertToV8Object(V8ClassIndex::MESSAGEPORT, mp); ASSERT_NOT_REACHED(); return v8::Handle<v8::Value>(); } -v8::Handle<v8::Value> WorkerContextExecutionProxy::WorkerContextToV8Object(WorkerContext* workerContext) +v8::Handle<v8::Value> WorkerContextExecutionProxy::convertWorkerContextToV8Object(WorkerContext* workerContext) { if (!workerContext) return v8::Null(); - v8::Handle<v8::Context> context = workerContext->script()->proxy()->GetContext(); + v8::Handle<v8::Context> context = workerContext->script()->proxy()->context(); v8::Handle<v8::Object> global = context->Global(); ASSERT(!global.IsEmpty()); return global; } -v8::Local<v8::Object> WorkerContextExecutionProxy::toV8(V8ClassIndex::V8WrapperType descType, V8ClassIndex::V8WrapperType cptrType, void* impl) +v8::Local<v8::Object> WorkerContextExecutionProxy::toV8(V8ClassIndex::V8WrapperType descriptorType, V8ClassIndex::V8WrapperType cptrType, void* impl) { v8::Local<v8::Function> function; WorkerContextExecutionProxy* proxy = retrieve(); if (proxy) - function = proxy->GetConstructor(descType); + function = V8DOMWrapper::getConstructor(descriptorType, proxy->workerContext()); else - function = V8Proxy::GetTemplate(descType)->GetFunction(); + function = V8DOMWrapper::getTemplate(descriptorType)->GetFunction(); v8::Local<v8::Object> instance = SafeAllocation::newInstance(function); - if (!instance.IsEmpty()) { + if (!instance.IsEmpty()) // Avoid setting the DOM wrapper for failed allocations. - V8Proxy::SetDOMWrapper(instance, V8ClassIndex::ToInt(cptrType), impl); - } + V8DOMWrapper::setDOMWrapper(instance, V8ClassIndex::ToInt(cptrType), impl); return instance; } bool WorkerContextExecutionProxy::forgetV8EventObject(Event* event) { - if (domObjectMap().contains(event)) { - domObjectMap().forget(event); + if (getDOMObjectMap().contains(event)) { + getDOMObjectMap().forget(event); return true; - } else - return false; + } + return false; } -v8::Local<v8::Value> WorkerContextExecutionProxy::evaluate(const String& script, const String& fileName, int baseLine) +ScriptValue WorkerContextExecutionProxy::evaluate(const String& script, const String& fileName, int baseLine, WorkerContextExecutionState* state) { LOCK_V8; v8::HandleScope hs; @@ -348,9 +349,27 @@ v8::Local<v8::Value> WorkerContextExecutionProxy::evaluate(const String& script, initContextIfNeeded(); v8::Context::Scope scope(m_context); + v8::TryCatch exceptionCatcher; + v8::Local<v8::String> scriptString = v8ExternalString(script); - v8::Handle<v8::Script> compiledScript = V8Proxy::CompileScript(scriptString, fileName, baseLine); - return runScript(compiledScript); + v8::Handle<v8::Script> compiledScript = V8Proxy::compileScript(scriptString, fileName, baseLine); + v8::Local<v8::Value> result = runScript(compiledScript); + + if (exceptionCatcher.HasCaught()) { + v8::Local<v8::Message> message = exceptionCatcher.Message(); + state->hadException = true; + state->exception = ScriptValue(exceptionCatcher.Exception()); + state->errorMessage = toWebCoreString(message->Get()); + state->lineNumber = message->GetLineNumber(); + state->sourceURL = toWebCoreString(message->GetScriptResourceName()); + exceptionCatcher.Reset(); + } else + state->hadException = false; + + if (result.IsEmpty() || result->IsUndefined()) + return ScriptValue(); + + return ScriptValue(result); } v8::Local<v8::Value> WorkerContextExecutionProxy::runScript(v8::Handle<v8::Script> script) @@ -361,10 +380,10 @@ v8::Local<v8::Value> WorkerContextExecutionProxy::runScript(v8::Handle<v8::Scrip // Compute the source string and prevent against infinite recursion. if (m_recursion >= kMaxRecursionDepth) { v8::Local<v8::String> code = v8ExternalString("throw RangeError('Recursion too deep')"); - script = V8Proxy::CompileScript(code, "", 0); + script = V8Proxy::compileScript(code, "", 0); } - if (V8Proxy::HandleOutOfMemory()) + if (V8Proxy::handleOutOfMemory()) ASSERT(script.IsEmpty()); if (script.IsEmpty()) @@ -416,7 +435,7 @@ PassRefPtr<V8EventListener> WorkerContextExecutionProxy::findOrCreateObjectEvent return findOrCreateEventListenerHelper(object, isInline, findOnly, true); } -void WorkerContextExecutionProxy::RemoveEventListener(V8EventListener* listener) +void WorkerContextExecutionProxy::removeEventListener(V8EventListener* listener) { m_listeners->remove(listener); } diff --git a/WebCore/bindings/v8/WorkerContextExecutionProxy.h b/WebCore/bindings/v8/WorkerContextExecutionProxy.h index dad191c..75024df 100644 --- a/WebCore/bindings/v8/WorkerContextExecutionProxy.h +++ b/WebCore/bindings/v8/WorkerContextExecutionProxy.h @@ -34,9 +34,10 @@ #if ENABLE(WORKERS) -#include <v8.h> +#include "ScriptValue.h" #include "V8EventListenerList.h" #include "V8Index.h" +#include <v8.h> #include <wtf/OwnPtr.h> #include <wtf/Vector.h> @@ -48,24 +49,27 @@ namespace WebCore { class V8WorkerContextEventListener; class WorkerContext; + struct WorkerContextExecutionState { + WorkerContextExecutionState() : hadException(false), lineNumber(0) { } + + bool hadException; + ScriptValue exception; + String errorMessage; + int lineNumber; + String sourceURL; + }; + class WorkerContextExecutionProxy { public: WorkerContextExecutionProxy(WorkerContext*); ~WorkerContextExecutionProxy(); - // FIXME: following function sshould have camelCased names once V8 code-generating script is migrated. - v8::Local<v8::Context> GetContext() { return v8::Local<v8::Context>::New(m_context); } - v8::Local<v8::Function> GetConstructor(V8ClassIndex::V8WrapperType); - void RemoveEventListener(V8EventListener*); - - static v8::Handle<v8::Value> ToV8Object(V8ClassIndex::V8WrapperType type, void* impl); - static v8::Handle<v8::Value> EventToV8Object(Event* event); - static v8::Handle<v8::Value> EventTargetToV8Object(EventTarget* target); - static v8::Handle<v8::Value> WorkerContextToV8Object(WorkerContext* wc); + void removeEventListener(V8EventListener*); // Finds/creates event listener wrappers. PassRefPtr<V8EventListener> findOrCreateEventListener(v8::Local<v8::Value> listener, bool isInline, bool findOnly); PassRefPtr<V8EventListener> findOrCreateObjectEventListener(v8::Local<v8::Value> object, bool isInline, bool findOnly); + PassRefPtr<V8EventListener> findOrCreateEventListenerHelper(v8::Local<v8::Value> object, bool isInline, bool findOnly, bool createObjectEventListener); // Track the event so that we can detach it from the JS wrapper when a worker // terminates. This is needed because we need to be able to dispose these @@ -73,7 +77,10 @@ namespace WebCore { void trackEvent(Event*); // Evaluate a script file in the current execution environment. - v8::Local<v8::Value> evaluate(const String& script, const String& fileName, int baseLine); + ScriptValue evaluate(const String& script, const String& fileName, int baseLine, WorkerContextExecutionState*); + + // Returns a local handle of the context. + v8::Local<v8::Context> context() { return v8::Local<v8::Context>::New(m_context); } // Returns WorkerContext object. WorkerContext* workerContext() { return m_workerContext; } @@ -81,20 +88,26 @@ namespace WebCore { // Returns WorkerContextExecutionProxy object of the currently executing context. 0 will be returned if the current executing context is not the worker context. static WorkerContextExecutionProxy* retrieve(); - // Enables HTML5 worker support. - static bool isWebWorkersEnabled(); - static void setIsWebWorkersEnabled(bool); + // We have to keep all these conversion functions here before WorkerContextExecutionProxy is refactor-ed. + template<typename T> + static v8::Handle<v8::Value> convertToV8Object(V8ClassIndex::V8WrapperType type, PassRefPtr<T> impl) + { + return convertToV8Object(type, impl.get()); + } + static v8::Handle<v8::Value> convertToV8Object(V8ClassIndex::V8WrapperType, void* impl); + static v8::Handle<v8::Value> convertEventToV8Object(Event*); + static v8::Handle<v8::Value> convertEventTargetToV8Object(EventTarget*); + static v8::Handle<v8::Value> convertWorkerContextToV8Object(WorkerContext*); private: void initV8IfNeeded(); void initContextIfNeeded(); void dispose(); - PassRefPtr<V8EventListener> findOrCreateEventListenerHelper(v8::Local<v8::Value> object, bool isInline, bool findOnly, bool createObjectEventListener); // Run an already compiled script. v8::Local<v8::Value> runScript(v8::Handle<v8::Script>); - static v8::Local<v8::Object> toV8(V8ClassIndex::V8WrapperType descType, V8ClassIndex::V8WrapperType cptrType, void* impl); + static v8::Local<v8::Object> toV8(V8ClassIndex::V8WrapperType descriptorType, V8ClassIndex::V8WrapperType cptrType, void* impl); static bool forgetV8EventObject(Event*); diff --git a/WebCore/bindings/v8/WorkerScriptController.cpp b/WebCore/bindings/v8/WorkerScriptController.cpp index b3ede11..f2311bf 100644 --- a/WebCore/bindings/v8/WorkerScriptController.cpp +++ b/WebCore/bindings/v8/WorkerScriptController.cpp @@ -40,6 +40,7 @@ #include "ScriptValue.h" #include "DOMTimer.h" #include "V8DOMMap.h" +#include "V8Proxy.h" #include "WorkerContext.h" #include "WorkerContextExecutionProxy.h" #include "WorkerObjectProxy.h" @@ -61,21 +62,27 @@ WorkerScriptController::~WorkerScriptController() ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode) { + return evaluate(sourceCode, 0); +} + +ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, ScriptValue* exception) +{ { MutexLocker lock(m_sharedDataMutex); if (m_executionForbidden) return ScriptValue(); } - v8::Local<v8::Value> result = m_proxy->evaluate(sourceCode.source(), sourceCode.url().string(), sourceCode.startLine() - 1); - m_workerContext->thread()->workerObjectProxy().reportPendingActivity(m_workerContext->hasPendingActivity()); - return ScriptValue(); -} + WorkerContextExecutionState state; + ScriptValue result = m_proxy->evaluate(sourceCode.source(), sourceCode.url().string(), sourceCode.startLine() - 1, &state); + if (state.hadException) { + if (exception) + *exception = state.exception; + else + m_workerContext->reportException(state.errorMessage, state.lineNumber, state.sourceURL); + } -ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, ScriptValue* /* exception */) -{ - // FIXME: Need to return an exception. - return evaluate(sourceCode); + return result; } void WorkerScriptController::forbidExecution() @@ -85,9 +92,9 @@ void WorkerScriptController::forbidExecution() m_executionForbidden = true; } -void WorkerScriptController::setException(ScriptValue /* exception */) +void WorkerScriptController::setException(ScriptValue exception) { - notImplemented(); + throwError(*exception.v8Value()); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp b/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp new file mode 100644 index 0000000..ce759eb --- /dev/null +++ b/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp @@ -0,0 +1,139 @@ +/* + * 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: + * + * * 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. + */ + +#include "config.h" + +#if ENABLE(WORKERS) + +#include "AbstractWorker.h" + +#include "ExceptionCode.h" +#include "ScriptExecutionContext.h" +#include "V8Binding.h" +#include "V8CustomBinding.h" +#include "V8ObjectEventListener.h" +#include "V8Proxy.h" +#include "V8Utilities.h" +#include "WorkerContextExecutionProxy.h" + +namespace WebCore { + +PassRefPtr<EventListener> getEventListener(AbstractWorker* worker, v8::Local<v8::Value> value, bool isAttribute, bool findOnly) +{ + if (worker->scriptExecutionContext()->isWorkerContext()) { + WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); + ASSERT(workerContextProxy); + return workerContextProxy->findOrCreateObjectEventListener(value, isAttribute, findOnly); + } + + V8Proxy* proxy = V8Proxy::retrieve(worker->scriptExecutionContext()); + if (proxy) { + V8EventListenerList* list = proxy->objectListeners(); + return findOnly ? list->findWrapper(value, isAttribute) : list->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, isAttribute); + } + + return 0; +} + +ACCESSOR_GETTER(AbstractWorkerOnerror) +{ + INC_STATS(L"DOM.AbstractWorker.onerror._get"); + AbstractWorker* worker = V8DOMWrapper::convertToNativeObject<AbstractWorker>(V8ClassIndex::ABSTRACTWORKER, info.Holder()); + if (worker->onerror()) { + V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(worker->onerror()); + v8::Local<v8::Object> v8Listener = listener->getListenerObject(); + return v8Listener; + } + return v8::Undefined(); +} + +ACCESSOR_SETTER(AbstractWorkerOnerror) +{ + INC_STATS(L"DOM.AbstractWorker.onerror._set"); + AbstractWorker* worker = V8DOMWrapper::convertToNativeObject<AbstractWorker>(V8ClassIndex::ABSTRACTWORKER, info.Holder()); + V8ObjectEventListener* oldListener = static_cast<V8ObjectEventListener*>(worker->onerror()); + if (value->IsNull()) { + if (oldListener) { + v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); + removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kAbstractWorkerRequestCacheIndex); + } + + // Clear the listener. + worker->setOnerror(0); + } else { + RefPtr<EventListener> listener = getEventListener(worker, value, true, false); + if (listener) { + if (oldListener) { + v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); + removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kAbstractWorkerRequestCacheIndex); + } + + worker->setOnerror(listener); + createHiddenDependency(info.Holder(), value, V8Custom::kAbstractWorkerRequestCacheIndex); + } + } +} + +CALLBACK_FUNC_DECL(AbstractWorkerAddEventListener) +{ + INC_STATS(L"DOM.AbstractWorker.addEventListener()"); + AbstractWorker* worker = V8DOMWrapper::convertToNativeObject<AbstractWorker>(V8ClassIndex::ABSTRACTWORKER, args.Holder()); + + RefPtr<EventListener> listener = getEventListener(worker, args[1], false, false); + if (listener) { + String type = toWebCoreString(args[0]); + bool useCapture = args[2]->BooleanValue(); + worker->addEventListener(type, listener, useCapture); + + createHiddenDependency(args.Holder(), args[1], V8Custom::kAbstractWorkerRequestCacheIndex); + } + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(AbstractWorkerRemoveEventListener) +{ + INC_STATS(L"DOM.AbstractWorker.removeEventListener()"); + AbstractWorker* worker = V8DOMWrapper::convertToNativeObject<AbstractWorker>(V8ClassIndex::ABSTRACTWORKER, args.Holder()); + + RefPtr<EventListener> listener = getEventListener(worker, args[1], false, true); + if (listener) { + String type = toWebCoreString(args[0]); + bool useCapture = args[2]->BooleanValue(); + worker->removeEventListener(type, listener.get(), useCapture); + + removeHiddenDependency(args.Holder(), args[1], V8Custom::kAbstractWorkerRequestCacheIndex); + } + + return v8::Undefined(); +} + +} // namespace WebCore + +#endif // ENABLE(WORKERS) diff --git a/WebCore/bindings/v8/custom/V8AttrCustom.cpp b/WebCore/bindings/v8/custom/V8AttrCustom.cpp index f34a441..81f1586 100644 --- a/WebCore/bindings/v8/custom/V8AttrCustom.cpp +++ b/WebCore/bindings/v8/custom/V8AttrCustom.cpp @@ -42,7 +42,7 @@ namespace WebCore { ACCESSOR_SETTER(AttrValue) { - Attr* imp = V8Proxy::DOMWrapperToNode<Attr>(info.Holder()); + Attr* imp = V8DOMWrapper::convertDOMWrapperToNode<Attr>(info.Holder()); String attrValue = toWebCoreStringWithNullCheck(value); Element* ownerElement = imp->ownerElement(); diff --git a/WebCore/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp b/WebCore/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp index 1ad0e7a..6bd0035 100644 --- a/WebCore/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp +++ b/WebCore/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp @@ -161,7 +161,7 @@ NAMED_PROPERTY_GETTER(CSSStyleDeclaration) // Search the style declaration. CSSStyleDeclaration* imp = - V8Proxy::ToNativeObject<CSSStyleDeclaration>(V8ClassIndex::CSSSTYLEDECLARATION, info.Holder()); + V8DOMWrapper::convertToNativeObject<CSSStyleDeclaration>(V8ClassIndex::CSSSTYLEDECLARATION, info.Holder()); CSSPropertyInfo* propInfo = cssPropertyInfo(name); // Do not handle non-property names. @@ -195,13 +195,13 @@ NAMED_PROPERTY_SETTER(CSSStyleDeclaration) { INC_STATS("DOM.CSSStyleDeclaration.NamedPropertySetter"); CSSStyleDeclaration* imp = - V8Proxy::ToNativeObject<CSSStyleDeclaration>( + V8DOMWrapper::convertToNativeObject<CSSStyleDeclaration>( V8ClassIndex::CSSSTYLEDECLARATION, info.Holder()); CSSPropertyInfo* propInfo = cssPropertyInfo(name); if (!propInfo) return notHandledByInterceptor(); - String propertyValue = valueToStringWithNullCheck(value); + String propertyValue = toWebCoreStringWithNullCheck(value); if (propInfo->hadPixelOrPosPrefix) propertyValue.append("px"); diff --git a/WebCore/bindings/v8/custom/V8CanvasPixelArrayCustom.cpp b/WebCore/bindings/v8/custom/V8CanvasPixelArrayCustom.cpp index 28f6b59..5fe2710 100644 --- a/WebCore/bindings/v8/custom/V8CanvasPixelArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8CanvasPixelArrayCustom.cpp @@ -41,7 +41,7 @@ namespace WebCore { INDEXED_PROPERTY_GETTER(CanvasPixelArray) { INC_STATS("DOM.CanvasPixelArray.IndexedPropertyGetter"); - CanvasPixelArray* pixelBuffer = V8Proxy::ToNativeObject<CanvasPixelArray>(V8ClassIndex::CANVASPIXELARRAY, info.Holder()); + CanvasPixelArray* pixelBuffer = V8DOMWrapper::convertToNativeObject<CanvasPixelArray>(V8ClassIndex::CANVASPIXELARRAY, info.Holder()); if ((index < 0) || (index >= pixelBuffer->length())) return v8::Undefined(); @@ -55,7 +55,7 @@ INDEXED_PROPERTY_GETTER(CanvasPixelArray) INDEXED_PROPERTY_SETTER(CanvasPixelArray) { INC_STATS("DOM.CanvasPixelArray.IndexedPropertySetter"); - CanvasPixelArray* pixelBuffer = V8Proxy::ToNativeObject<CanvasPixelArray>(V8ClassIndex::CANVASPIXELARRAY, info.Holder()); + CanvasPixelArray* pixelBuffer = V8DOMWrapper::convertToNativeObject<CanvasPixelArray>(V8ClassIndex::CANVASPIXELARRAY, info.Holder()); if ((index >= 0) && (index < pixelBuffer->length())) pixelBuffer->set(index, value->NumberValue()); diff --git a/WebCore/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp b/WebCore/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp index 26086ab..676610c 100644 --- a/WebCore/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp +++ b/WebCore/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp @@ -43,6 +43,7 @@ #include "V8CustomBinding.h" #include "V8HTMLCanvasElement.h" #include "V8HTMLImageElement.h" +#include "V8HTMLVideoElement.h" #include "V8Proxy.h" namespace WebCore { @@ -50,10 +51,10 @@ namespace WebCore { static v8::Handle<v8::Value> toV8(CanvasStyle* style) { if (style->canvasGradient()) - return V8Proxy::ToV8Object(V8ClassIndex::CANVASGRADIENT, style->canvasGradient()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::CANVASGRADIENT, style->canvasGradient()); if (style->canvasPattern()) - return V8Proxy::ToV8Object(V8ClassIndex::CANVASPATTERN, style->canvasPattern()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::CANVASPATTERN, style->canvasPattern()); return v8String(style->color()); } @@ -64,35 +65,35 @@ static PassRefPtr<CanvasStyle> toCanvasStyle(v8::Handle<v8::Value> value) return CanvasStyle::create(toWebCoreString(value)); if (V8CanvasGradient::HasInstance(value)) - return CanvasStyle::create(V8Proxy::DOMWrapperToNative<CanvasGradient>(value)); + return CanvasStyle::create(V8DOMWrapper::convertDOMWrapperToNative<CanvasGradient>(v8::Handle<v8::Object>::Cast(value))); if (V8CanvasPattern::HasInstance(value)) - return CanvasStyle::create(V8Proxy::DOMWrapperToNative<CanvasPattern>(value)); + return CanvasStyle::create(V8DOMWrapper::convertDOMWrapperToNative<CanvasPattern>(v8::Handle<v8::Object>::Cast(value))); return 0; } ACCESSOR_GETTER(CanvasRenderingContext2DStrokeStyle) { - CanvasRenderingContext2D* impl = V8Proxy::DOMWrapperToNative<CanvasRenderingContext2D>(info.Holder()); + CanvasRenderingContext2D* impl = V8DOMWrapper::convertDOMWrapperToNative<CanvasRenderingContext2D>(info.Holder()); return toV8(impl->strokeStyle()); } ACCESSOR_SETTER(CanvasRenderingContext2DStrokeStyle) { - CanvasRenderingContext2D* impl = V8Proxy::DOMWrapperToNative<CanvasRenderingContext2D>(info.Holder()); + CanvasRenderingContext2D* impl = V8DOMWrapper::convertDOMWrapperToNative<CanvasRenderingContext2D>(info.Holder()); impl->setStrokeStyle(toCanvasStyle(value)); } ACCESSOR_GETTER(CanvasRenderingContext2DFillStyle) { - CanvasRenderingContext2D* impl = V8Proxy::DOMWrapperToNative<CanvasRenderingContext2D>(info.Holder()); + CanvasRenderingContext2D* impl = V8DOMWrapper::convertDOMWrapperToNative<CanvasRenderingContext2D>(info.Holder()); return toV8(impl->fillStyle()); } ACCESSOR_SETTER(CanvasRenderingContext2DFillStyle) { - CanvasRenderingContext2D* impl = V8Proxy::DOMWrapperToNative<CanvasRenderingContext2D>(info.Holder()); + CanvasRenderingContext2D* impl = V8DOMWrapper::convertDOMWrapperToNative<CanvasRenderingContext2D>(info.Holder()); impl->setFillStyle(toCanvasStyle(value)); } @@ -101,17 +102,17 @@ ACCESSOR_SETTER(CanvasRenderingContext2DFillStyle) CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetStrokeColor) { INC_STATS("DOM.CanvasRenderingContext2D.setStrokeColor()"); - CanvasRenderingContext2D* context = V8Proxy::ToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); switch (args.Length()) { case 1: if (args[0]->IsString()) - context->setStrokeColor(ToWebCoreString(args[0])); + context->setStrokeColor(toWebCoreString(args[0])); else context->setStrokeColor(toFloat(args[0])); break; case 2: if (args[0]->IsString()) - context->setStrokeColor(ToWebCoreString(args[0]), toFloat(args[1])); + context->setStrokeColor(toWebCoreString(args[0]), toFloat(args[1])); else context->setStrokeColor(toFloat(args[0]), toFloat(args[1])); break; @@ -122,7 +123,7 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetStrokeColor) context->setStrokeColor(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])); break; default: - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "setStrokeColor: Invalid number of arguments"); + V8Proxy::throwError(V8Proxy::SyntaxError, "setStrokeColor: Invalid number of arguments"); break; } return v8::Undefined(); @@ -131,17 +132,17 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetStrokeColor) CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetFillColor) { INC_STATS("DOM.CanvasRenderingContext2D.setFillColor()"); - CanvasRenderingContext2D* context = V8Proxy::ToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); switch (args.Length()) { case 1: if (args[0]->IsString()) - context->setFillColor(ToWebCoreString(args[0])); + context->setFillColor(toWebCoreString(args[0])); else context->setFillColor(toFloat(args[0])); break; case 2: if (args[0]->IsString()) - context->setFillColor(ToWebCoreString(args[0]), toFloat(args[1])); + context->setFillColor(toWebCoreString(args[0]), toFloat(args[1])); else context->setFillColor(toFloat(args[0]), toFloat(args[1])); break; @@ -152,7 +153,7 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetFillColor) context->setFillColor(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])); break; default: - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "setFillColor: Invalid number of arguments"); + V8Proxy::throwError(V8Proxy::SyntaxError, "setFillColor: Invalid number of arguments"); break; } return v8::Undefined(); @@ -161,13 +162,13 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetFillColor) CALLBACK_FUNC_DECL(CanvasRenderingContext2DStrokeRect) { INC_STATS("DOM.CanvasRenderingContext2D.strokeRect()"); - CanvasRenderingContext2D* context = V8Proxy::ToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); if (args.Length() == 5) context->strokeRect(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])); else if (args.Length() == 4) context->strokeRect(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3])); else { - V8Proxy::SetDOMException(INDEX_SIZE_ERR); + V8Proxy::setDOMException(INDEX_SIZE_ERR); return notHandledByInterceptor(); } return v8::Undefined(); @@ -176,7 +177,7 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DStrokeRect) CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetShadow) { INC_STATS("DOM.CanvasRenderingContext2D.setShadow()"); - CanvasRenderingContext2D* context = V8Proxy::ToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); switch (args.Length()) { case 3: @@ -184,13 +185,13 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetShadow) break; case 4: if (args[3]->IsString()) - context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), ToWebCoreString(args[3])); + context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toWebCoreString(args[3])); else context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3])); break; case 5: if (args[3]->IsString()) - context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), ToWebCoreString(args[3]), toFloat(args[4])); + context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toWebCoreString(args[3]), toFloat(args[4])); else context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])); break; @@ -201,7 +202,7 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetShadow) context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), toFloat(args[5]), toFloat(args[6]), toFloat(args[7])); break; default: - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "setShadow: Invalid number of arguments"); + V8Proxy::throwError(V8Proxy::SyntaxError, "setShadow: Invalid number of arguments"); break; } @@ -211,13 +212,13 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DSetShadow) CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImage) { INC_STATS("DOM.CanvasRenderingContext2D.drawImage()"); - CanvasRenderingContext2D* context = V8Proxy::ToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); v8::Handle<v8::Value> arg = args[0]; if (V8HTMLImageElement::HasInstance(arg)) { ExceptionCode ec = 0; - HTMLImageElement* image_element = V8Proxy::DOMWrapperToNode<HTMLImageElement>(arg); + HTMLImageElement* image_element = V8DOMWrapper::convertDOMWrapperToNode<HTMLImageElement>(v8::Handle<v8::Object>::Cast(arg)); switch (args.Length()) { case 3: context->drawImage(image_element, toFloat(args[1]), toFloat(args[2])); @@ -225,7 +226,7 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImage) case 5: context->drawImage(image_element, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), ec); if (ec != 0) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return notHandledByInterceptor(); } break; @@ -235,13 +236,12 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImage) FloatRect(toFloat(args[5]), toFloat(args[6]), toFloat(args[7]), toFloat(args[8])), ec); if (ec != 0) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return notHandledByInterceptor(); } break; default: - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "drawImage: Invalid number of arguments"); - return v8::Undefined(); + return throwError("drawImage: Invalid number of arguments", V8Proxy::SyntaxError); } return v8::Undefined(); } @@ -249,7 +249,7 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImage) // HTMLCanvasElement if (V8HTMLCanvasElement::HasInstance(arg)) { ExceptionCode ec = 0; - HTMLCanvasElement* canvas_element = V8Proxy::DOMWrapperToNode<HTMLCanvasElement>(arg); + HTMLCanvasElement* canvas_element = V8DOMWrapper::convertDOMWrapperToNode<HTMLCanvasElement>(v8::Handle<v8::Object>::Cast(arg)); switch (args.Length()) { case 3: context->drawImage(canvas_element, toFloat(args[1]), toFloat(args[2])); @@ -257,7 +257,7 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImage) case 5: context->drawImage(canvas_element, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), ec); if (ec != 0) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return notHandledByInterceptor(); } break; @@ -267,33 +267,65 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImage) FloatRect(toFloat(args[5]), toFloat(args[6]), toFloat(args[7]), toFloat(args[8])), ec); if (ec != 0) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return notHandledByInterceptor(); } break; default: - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "drawImage: Invalid number of arguments"); - return v8::Undefined(); + return throwError("drawImage: Invalid number of arguments", V8Proxy::SyntaxError); } return v8::Undefined(); } - V8Proxy::SetDOMException(TYPE_MISMATCH_ERR); +#if ENABLE(VIDEO) + // HTMLVideoElement + if (V8HTMLVideoElement::HasInstance(arg)) { + ExceptionCode ec = 0; + HTMLVideoElement* video_element = V8DOMWrapper::convertDOMWrapperToNode<HTMLVideoElement>(v8::Handle<v8::Object>::Cast(arg)); + switch (args.Length()) { + case 3: + context->drawImage(video_element, toFloat(args[1]), toFloat(args[2])); + break; + case 5: + context->drawImage(video_element, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), ec); + if (ec != 0) { + V8Proxy::setDOMException(ec); + return notHandledByInterceptor(); + } + break; + case 9: + context->drawImage(video_element, + FloatRect(toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])), + FloatRect(toFloat(args[5]), toFloat(args[6]), toFloat(args[7]), toFloat(args[8])), + ec); + if (ec != 0) { + V8Proxy::setDOMException(ec); + return notHandledByInterceptor(); + } + break; + default: + return throwError("drawImage: Invalid number of arguments", V8Proxy::SyntaxError); + } + return v8::Undefined(); + } +#endif + + V8Proxy::setDOMException(TYPE_MISMATCH_ERR); return notHandledByInterceptor(); } CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImageFromRect) { INC_STATS("DOM.CanvasRenderingContext2D.drawImageFromRect()"); - CanvasRenderingContext2D* context = V8Proxy::ToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); v8::Handle<v8::Value> arg = args[0]; if (V8HTMLImageElement::HasInstance(arg)) { - HTMLImageElement* image_element = V8Proxy::DOMWrapperToNode<HTMLImageElement>(arg); - context->drawImageFromRect(image_element, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), toFloat(args[5]), toFloat(args[6]), toFloat(args[7]), toFloat(args[8]), ToWebCoreString(args[9])); + HTMLImageElement* image_element = V8DOMWrapper::convertDOMWrapperToNode<HTMLImageElement>(v8::Handle<v8::Object>::Cast(arg)); + context->drawImageFromRect(image_element, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), toFloat(args[5]), toFloat(args[6]), toFloat(args[7]), toFloat(args[8]), toWebCoreString(args[9])); } else - V8Proxy::ThrowError(V8Proxy::TYPE_ERROR, "drawImageFromRect: Invalid type of arguments"); + V8Proxy::throwError(V8Proxy::TypeError, "drawImageFromRect: Invalid type of arguments"); return v8::Undefined(); } @@ -301,33 +333,33 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DDrawImageFromRect) CALLBACK_FUNC_DECL(CanvasRenderingContext2DCreatePattern) { INC_STATS("DOM.CanvasRenderingContext2D.createPattern()"); - CanvasRenderingContext2D* context = V8Proxy::ToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); v8::Handle<v8::Value> arg = args[0]; if (V8HTMLImageElement::HasInstance(arg)) { - HTMLImageElement* image_element = V8Proxy::DOMWrapperToNode<HTMLImageElement>(arg); + HTMLImageElement* image_element = V8DOMWrapper::convertDOMWrapperToNode<HTMLImageElement>(v8::Handle<v8::Object>::Cast(arg)); ExceptionCode ec = 0; - RefPtr<CanvasPattern> pattern = context->createPattern(image_element, valueToStringWithNullCheck(args[1]), ec); + RefPtr<CanvasPattern> pattern = context->createPattern(image_element, toWebCoreStringWithNullCheck(args[1]), ec); if (ec != 0) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return notHandledByInterceptor(); } - return V8Proxy::ToV8Object(V8ClassIndex::CANVASPATTERN, pattern.get()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::CANVASPATTERN, pattern.release()); } if (V8HTMLCanvasElement::HasInstance(arg)) { - HTMLCanvasElement* canvas_element = V8Proxy::DOMWrapperToNode<HTMLCanvasElement>(arg); + HTMLCanvasElement* canvas_element = V8DOMWrapper::convertDOMWrapperToNode<HTMLCanvasElement>(v8::Handle<v8::Object>::Cast(arg)); ExceptionCode ec = 0; - RefPtr<CanvasPattern> pattern = context->createPattern(canvas_element, valueToStringWithNullCheck(args[1]), ec); + RefPtr<CanvasPattern> pattern = context->createPattern(canvas_element, toWebCoreStringWithNullCheck(args[1]), ec); if (ec != 0) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return notHandledByInterceptor(); } - return V8Proxy::ToV8Object(V8ClassIndex::CANVASPATTERN, pattern.get()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::CANVASPATTERN, pattern.release()); } - V8Proxy::SetDOMException(TYPE_MISMATCH_ERR); + V8Proxy::setDOMException(TYPE_MISMATCH_ERR); return notHandledByInterceptor(); } @@ -335,17 +367,17 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DFillText) { INC_STATS("DOM.CanvasRenderingContext2D.fillText()"); - CanvasRenderingContext2D* context = V8Proxy::ToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); // Two forms: // * fillText(text, x, y) // * fillText(text, x, y, maxWidth) if (args.Length() < 3 || args.Length() > 4) { - V8Proxy::SetDOMException(SYNTAX_ERR); + V8Proxy::setDOMException(SYNTAX_ERR); return notHandledByInterceptor(); } - String text = ToWebCoreString(args[0]); + String text = toWebCoreString(args[0]); float x = toFloat(args[1]); float y = toFloat(args[2]); @@ -361,17 +393,17 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DFillText) CALLBACK_FUNC_DECL(CanvasRenderingContext2DStrokeText) { INC_STATS("DOM.CanvasRenderingContext2D.strokeText()"); - CanvasRenderingContext2D* context = V8Proxy::ToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); // Two forms: // * strokeText(text, x, y) // * strokeText(text, x, y, maxWidth) if (args.Length() < 3 || args.Length() > 4) { - V8Proxy::SetDOMException(SYNTAX_ERR); + V8Proxy::setDOMException(SYNTAX_ERR); return notHandledByInterceptor(); } - String text = ToWebCoreString(args[0]); + String text = toWebCoreString(args[0]); float x = toFloat(args[1]); float y = toFloat(args[2]); @@ -392,20 +424,20 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DPutImageData) // * putImageData(ImageData, x, y) // * putImageData(ImageData, x, y, dirtyX, dirtyY, dirtyWidth, dirtyHeight) if (args.Length() != 3 && args.Length() != 7) { - V8Proxy::SetDOMException(SYNTAX_ERR); + V8Proxy::setDOMException(SYNTAX_ERR); return notHandledByInterceptor(); } - CanvasRenderingContext2D* context = V8Proxy::ToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); + CanvasRenderingContext2D* context = V8DOMWrapper::convertToNativeObject<CanvasRenderingContext2D>(V8ClassIndex::CANVASRENDERINGCONTEXT2D, args.Holder()); ImageData* imageData = 0; // Need to check that the argument is of the correct type, since - // ToNativeObject() expects it to be correct. If the argument was incorrect + // convertToNativeObject() expects it to be correct. If the argument was incorrect // we leave it null, and putImageData() will throw the correct exception // (TYPE_MISMATCH_ERR). - if (V8Proxy::IsWrapperOfType(args[0], V8ClassIndex::IMAGEDATA)) - imageData = V8Proxy::ToNativeObject<ImageData>(V8ClassIndex::IMAGEDATA, args[0]); + if (V8DOMWrapper::isWrapperOfType(args[0], V8ClassIndex::IMAGEDATA)) + imageData = V8DOMWrapper::convertToNativeObject<ImageData>(V8ClassIndex::IMAGEDATA, v8::Handle<v8::Object>::Cast(args[0])); ExceptionCode ec = 0; @@ -415,7 +447,7 @@ CALLBACK_FUNC_DECL(CanvasRenderingContext2DPutImageData) context->putImageData(imageData, toFloat(args[1]), toFloat(args[2]), ec); if (ec != 0) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return notHandledByInterceptor(); } diff --git a/WebCore/bindings/v8/custom/V8ClientRectListCustom.cpp b/WebCore/bindings/v8/custom/V8ClientRectListCustom.cpp index e3f89b9..3c62e14 100644 --- a/WebCore/bindings/v8/custom/V8ClientRectListCustom.cpp +++ b/WebCore/bindings/v8/custom/V8ClientRectListCustom.cpp @@ -44,12 +44,12 @@ namespace WebCore { INDEXED_PROPERTY_GETTER(ClientRectList) { INC_STATS("DOM.ClientRectList.IndexedPropertyGetter"); - ClientRectList* imp = V8Proxy::ToNativeObject<ClientRectList>(V8ClassIndex::CLIENTRECTLIST, info.Holder()); + ClientRectList* imp = V8DOMWrapper::convertToNativeObject<ClientRectList>(V8ClassIndex::CLIENTRECTLIST, info.Holder()); RefPtr<ClientRect> result = imp->item(index); if (!result) return notHandledByInterceptor(); - return V8Proxy::ToV8Object(V8ClassIndex::CLIENTRECT, result.get()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::CLIENTRECT, result.release()); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8ClipboardCustom.cpp b/WebCore/bindings/v8/custom/V8ClipboardCustom.cpp index eff5511..4526304 100644 --- a/WebCore/bindings/v8/custom/V8ClipboardCustom.cpp +++ b/WebCore/bindings/v8/custom/V8ClipboardCustom.cpp @@ -47,7 +47,7 @@ namespace WebCore { ACCESSOR_GETTER(ClipboardTypes) { INC_STATS("DOM.Clipboard.types()"); - Clipboard* clipboard = V8Proxy::ToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, info.Holder()); + Clipboard* clipboard = V8DOMWrapper::convertToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, info.Holder()); HashSet<String> types = clipboard->types(); if (types.isEmpty()) @@ -65,7 +65,7 @@ ACCESSOR_GETTER(ClipboardTypes) CALLBACK_FUNC_DECL(ClipboardClearData) { INC_STATS("DOM.Clipboard.clearData()"); - Clipboard* clipboard = V8Proxy::ToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, args.Holder()); + Clipboard* clipboard = V8DOMWrapper::convertToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, args.Holder()); if (!args.Length()) { clipboard->clearAllData(); @@ -73,7 +73,7 @@ CALLBACK_FUNC_DECL(ClipboardClearData) } if (args.Length() != 1) - return throwError("clearData: Invalid number of arguments", V8Proxy::SYNTAX_ERROR); + return throwError("clearData: Invalid number of arguments", V8Proxy::SyntaxError); String type = toWebCoreString(args[0]); clipboard->clearData(type); @@ -83,10 +83,10 @@ CALLBACK_FUNC_DECL(ClipboardClearData) CALLBACK_FUNC_DECL(ClipboardGetData) { INC_STATS("DOM.Clipboard.getData()"); - Clipboard* clipboard = V8Proxy::ToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, args.Holder()); + Clipboard* clipboard = V8DOMWrapper::convertToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, args.Holder()); if (args.Length() != 1) - return throwError("getData: Invalid number of arguments", V8Proxy::SYNTAX_ERROR); + return throwError("getData: Invalid number of arguments", V8Proxy::SyntaxError); bool success; String result = clipboard->getData(toWebCoreString(args[0]), success); @@ -99,10 +99,10 @@ CALLBACK_FUNC_DECL(ClipboardGetData) CALLBACK_FUNC_DECL(ClipboardSetData) { INC_STATS("DOM.Clipboard.setData()"); - Clipboard* clipboard = V8Proxy::ToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, args.Holder()); + Clipboard* clipboard = V8DOMWrapper::convertToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, args.Holder()); if (args.Length() != 2) - return throwError("setData: Invalid number of arguments", V8Proxy::SYNTAX_ERROR); + return throwError("setData: Invalid number of arguments", V8Proxy::SyntaxError); String type = toWebCoreString(args[0]); String data = toWebCoreString(args[1]); @@ -112,20 +112,20 @@ CALLBACK_FUNC_DECL(ClipboardSetData) CALLBACK_FUNC_DECL(ClipboardSetDragImage) { INC_STATS("DOM.Clipboard.setDragImage()"); - Clipboard* clipboard = V8Proxy::ToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, args.Holder()); + Clipboard* clipboard = V8DOMWrapper::convertToNativeObject<Clipboard>(V8ClassIndex::CLIPBOARD, args.Holder()); if (!clipboard->isForDragging()) return v8::Undefined(); if (args.Length() != 3) - return throwError("setDragImage: Invalid number of arguments", V8Proxy::SYNTAX_ERROR); + return throwError("setDragImage: Invalid number of arguments", V8Proxy::SyntaxError); int x = toInt32(args[1]); int y = toInt32(args[2]); Node* node = 0; if (V8Node::HasInstance(args[0])) - node = V8Proxy::DOMWrapperToNode<Node>(args[0]); + node = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])); if (!node || !node->isElementNode()) return throwError("setDragImageFromElement: Invalid first argument"); diff --git a/WebCore/bindings/v8/custom/V8CustomBinding.cpp b/WebCore/bindings/v8/custom/V8CustomBinding.cpp index 7789797..ee45abd 100644 --- a/WebCore/bindings/v8/custom/V8CustomBinding.cpp +++ b/WebCore/bindings/v8/custom/V8CustomBinding.cpp @@ -49,9 +49,9 @@ namespace WebCore { bool allowSettingFrameSrcToJavascriptUrl(HTMLFrameElementBase* frame, String value) { - if (protocolIs(parseURL(value), "javascript")) { + if (protocolIs(deprecatedParseURL(value), "javascript")) { Node* contentDoc = frame->contentDocument(); - if (contentDoc && !V8Proxy::CheckNodeSecurity(contentDoc)) + if (contentDoc && !V8Proxy::checkNodeSecurity(contentDoc)) return false; } return true; @@ -64,6 +64,7 @@ bool allowSettingSrcToJavascriptURL(Element* element, String name, String value) return true; } +#ifdef MANUAL_MERGE_REQUIRED // DOMImplementation is a singleton in WebCore. If we use our normal // mapping from DOM objects to V8 wrappers, the same wrapper will be // shared for all frames in the same process. This is a major @@ -179,4 +180,121 @@ V8ClassIndex::V8WrapperType V8Custom::DowncastSVGPathSeg(void* pathSeg) #endif // ENABLE(SVG) +#else // MANUAL_MERGE_REQUIRED +// DOMImplementation is a singleton in WebCore. If we use our normal +// mapping from DOM objects to V8 wrappers, the same wrapper will be +// shared for all frames in the same process. This is a major +// security problem. Therefore, we generate a DOMImplementation +// wrapper per document and store it in an internal field of the +// document. Since the DOMImplementation object is a singleton, we do +// not have to do anything to keep the DOMImplementation object alive +// for the lifetime of the wrapper. +ACCESSOR_GETTER(DocumentImplementation) +{ + ASSERT(info.Holder()->InternalFieldCount() >= kDocumentMinimumInternalFieldCount); + + // Check if the internal field already contains a wrapper. + v8::Local<v8::Value> implementation = info.Holder()->GetInternalField(kDocumentImplementationIndex); + if (!implementation->IsUndefined()) + return implementation; + + // Generate a wrapper. + Document* document = V8DOMWrapper::convertDOMWrapperToNative<Document>(info.Holder()); + v8::Handle<v8::Value> wrapper = V8DOMWrapper::convertDOMImplementationToV8Object(document->implementation()); + + // Store the wrapper in the internal field. + info.Holder()->SetInternalField(kDocumentImplementationIndex, wrapper); + + return wrapper; +} + +// --------------- Security Checks ------------------------- +INDEXED_ACCESS_CHECK(History) +{ + ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::HISTORY); + // Only allow same origin access. + History* history = V8DOMWrapper::convertToNativeObject<History>(V8ClassIndex::HISTORY, host); + return V8Proxy::canAccessFrame(history->frame(), false); +} + +NAMED_ACCESS_CHECK(History) +{ + ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::HISTORY); + // Only allow same origin access. + History* history = V8DOMWrapper::convertToNativeObject<History>(V8ClassIndex::HISTORY, host); + return V8Proxy::canAccessFrame(history->frame(), false); +} + +#undef INDEXED_ACCESS_CHECK +#undef NAMED_ACCESS_CHECK +#undef NAMED_PROPERTY_GETTER +#undef NAMED_PROPERTY_SETTER + +Frame* V8Custom::GetTargetFrame(v8::Local<v8::Object> host, v8::Local<v8::Value> data) +{ + Frame* target = 0; + switch (V8ClassIndex::FromInt(data->Int32Value())) { + case V8ClassIndex::DOMWINDOW: { + v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, host); + if (window.IsEmpty()) + return target; + + DOMWindow* targetWindow = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window); + target = targetWindow->frame(); + break; + } + case V8ClassIndex::LOCATION: { + History* history = V8DOMWrapper::convertToNativeObject<History>(V8ClassIndex::HISTORY, host); + target = history->frame(); + break; + } + case V8ClassIndex::HISTORY: { + Location* location = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, host); + target = location->frame(); + break; + } + default: + break; + } + return target; +} + +#if ENABLE(SVG) +V8ClassIndex::V8WrapperType V8Custom::DowncastSVGPathSeg(void* pathSeg) +{ + WebCore::SVGPathSeg* realPathSeg = reinterpret_cast<WebCore::SVGPathSeg*>(pathSeg); + + switch (realPathSeg->pathSegType()) { +#define MAKE_CASE(svgValue, v8Value) case WebCore::SVGPathSeg::svgValue: return V8ClassIndex::v8Value + + MAKE_CASE(PATHSEG_CLOSEPATH, SVGPATHSEGCLOSEPATH); + MAKE_CASE(PATHSEG_MOVETO_ABS, SVGPATHSEGMOVETOABS); + MAKE_CASE(PATHSEG_MOVETO_REL, SVGPATHSEGMOVETOREL); + MAKE_CASE(PATHSEG_LINETO_ABS, SVGPATHSEGLINETOABS); + MAKE_CASE(PATHSEG_LINETO_REL, SVGPATHSEGLINETOREL); + MAKE_CASE(PATHSEG_CURVETO_CUBIC_ABS, SVGPATHSEGCURVETOCUBICABS); + MAKE_CASE(PATHSEG_CURVETO_CUBIC_REL, SVGPATHSEGCURVETOCUBICREL); + MAKE_CASE(PATHSEG_CURVETO_QUADRATIC_ABS, SVGPATHSEGCURVETOQUADRATICABS); + MAKE_CASE(PATHSEG_CURVETO_QUADRATIC_REL, SVGPATHSEGCURVETOQUADRATICREL); + MAKE_CASE(PATHSEG_ARC_ABS, SVGPATHSEGARCABS); + MAKE_CASE(PATHSEG_ARC_REL, SVGPATHSEGARCREL); + MAKE_CASE(PATHSEG_LINETO_HORIZONTAL_ABS, SVGPATHSEGLINETOHORIZONTALABS); + MAKE_CASE(PATHSEG_LINETO_HORIZONTAL_REL, SVGPATHSEGLINETOHORIZONTALREL); + MAKE_CASE(PATHSEG_LINETO_VERTICAL_ABS, SVGPATHSEGLINETOVERTICALABS); + MAKE_CASE(PATHSEG_LINETO_VERTICAL_REL, SVGPATHSEGLINETOVERTICALREL); + MAKE_CASE(PATHSEG_CURVETO_CUBIC_SMOOTH_ABS, SVGPATHSEGCURVETOCUBICSMOOTHABS); + MAKE_CASE(PATHSEG_CURVETO_CUBIC_SMOOTH_REL, SVGPATHSEGCURVETOCUBICSMOOTHREL); + MAKE_CASE(PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS, SVGPATHSEGCURVETOQUADRATICSMOOTHABS); + MAKE_CASE(PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL, SVGPATHSEGCURVETOQUADRATICSMOOTHREL); + +#undef MAKE_CASE + + default: + return V8ClassIndex::INVALID_CLASS_INDEX; + } +} + +#endif // ENABLE(SVG) + +#endif // MANUAL_MERGE_REQUIRED } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomBinding.h b/WebCore/bindings/v8/custom/V8CustomBinding.h index e039c6f..42aca44 100644 --- a/WebCore/bindings/v8/custom/V8CustomBinding.h +++ b/WebCore/bindings/v8/custom/V8CustomBinding.h @@ -91,6 +91,7 @@ namespace WebCore { bool allowSettingFrameSrcToJavascriptUrl(HTMLFrameElementBase*, String value); bool allowSettingSrcToJavascriptURL(Element*, String name, String value); +#ifdef MANUAL_MERGE_REQUIRED class V8Custom { public: // Constants. @@ -542,6 +543,469 @@ namespace WebCore { static void WindowSetLocation(DOMWindow*, const String&); }; +#else // MANUAL_MERGE_REQUIRED + class V8Custom { + public: + // Constants. + static const int kDOMWrapperTypeIndex = 0; + static const int kDOMWrapperObjectIndex = 1; + static const int kDefaultWrapperInternalFieldCount = 2; + + static const int kNPObjectInternalFieldCount = kDefaultWrapperInternalFieldCount + 0; + + static const int kNodeEventListenerCacheIndex = kDefaultWrapperInternalFieldCount + 0; + static const int kNodeMinimumInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; + + static const int kDocumentImplementationIndex = kNodeMinimumInternalFieldCount + 0; + static const int kDocumentMinimumInternalFieldCount = kNodeMinimumInternalFieldCount + 1; + + static const int kHTMLDocumentMarkerIndex = kDocumentMinimumInternalFieldCount + 0; + static const int kHTMLDocumentShadowIndex = kDocumentMinimumInternalFieldCount + 1; + static const int kHTMLDocumentInternalFieldCount = kDocumentMinimumInternalFieldCount + 2; + + static const int kXMLHttpRequestCacheIndex = kDefaultWrapperInternalFieldCount + 0; + static const int kXMLHttpRequestInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; + + static const int kMessageChannelPort1Index = kDefaultWrapperInternalFieldCount + 0; + static const int kMessageChannelPort2Index = kDefaultWrapperInternalFieldCount + 1; + static const int kMessageChannelInternalFieldCount = kDefaultWrapperInternalFieldCount + 2; + + static const int kMessagePortRequestCacheIndex = kDefaultWrapperInternalFieldCount + 0; + static const int kMessagePortEntangledPortIndex = kDefaultWrapperInternalFieldCount + 1; + static const int kMessagePortInternalFieldCount = kDefaultWrapperInternalFieldCount + 2; + +#if ENABLE(WORKERS) + static const int kWorkerRequestCacheIndex = kDefaultWrapperInternalFieldCount + 0; + static const int kWorkerInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; + + static const int kWorkerContextRequestCacheIndex = kDefaultWrapperInternalFieldCount + 0; + static const int kWorkerContextMinimumInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; + + static const int kDedicatedWorkerContextRequestCacheIndex = kWorkerContextMinimumInternalFieldCount + 0; + static const int kDedicatedWorkerContextInternalFieldCount = kWorkerContextMinimumInternalFieldCount + 1; + + static const int kAbstractWorkerRequestCacheIndex = kDefaultWrapperInternalFieldCount + 0; + static const int kAbstractWorkerInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; +#endif + + static const int kDOMWindowConsoleIndex = kDefaultWrapperInternalFieldCount + 0; + static const int kDOMWindowHistoryIndex = kDefaultWrapperInternalFieldCount + 1; + static const int kDOMWindowLocationbarIndex = kDefaultWrapperInternalFieldCount + 2; + static const int kDOMWindowMenubarIndex = kDefaultWrapperInternalFieldCount + 3; + static const int kDOMWindowNavigatorIndex = kDefaultWrapperInternalFieldCount + 4; + static const int kDOMWindowPersonalbarIndex = kDefaultWrapperInternalFieldCount + 5; + static const int kDOMWindowScreenIndex = kDefaultWrapperInternalFieldCount + 6; + static const int kDOMWindowScrollbarsIndex = kDefaultWrapperInternalFieldCount + 7; + static const int kDOMWindowSelectionIndex = kDefaultWrapperInternalFieldCount + 8; + static const int kDOMWindowStatusbarIndex = kDefaultWrapperInternalFieldCount + 9; + static const int kDOMWindowToolbarIndex = kDefaultWrapperInternalFieldCount + 10; + static const int kDOMWindowLocationIndex = kDefaultWrapperInternalFieldCount + 11; + static const int kDOMWindowDOMSelectionIndex = kDefaultWrapperInternalFieldCount + 12; + static const int kDOMWindowInternalFieldCount = kDefaultWrapperInternalFieldCount + 13; + + static const int kStyleSheetOwnerNodeIndex = kDefaultWrapperInternalFieldCount + 0; + static const int kStyleSheetInternalFieldCount = kDefaultWrapperInternalFieldCount + 1; + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + static const int kDOMApplicationCacheCacheIndex = kDefaultWrapperInternalFieldCount + 0; + static const int kDOMApplicationCacheFieldCount = kDefaultWrapperInternalFieldCount + 1; +#endif + +#define DECLARE_PROPERTY_ACCESSOR_GETTER(NAME) \ + static v8::Handle<v8::Value> v8##NAME##AccessorGetter( \ + v8::Local<v8::String> name, const v8::AccessorInfo& info) + +#define DECLARE_PROPERTY_ACCESSOR_SETTER(NAME) \ + static void v8##NAME##AccessorSetter(v8::Local<v8::String> name, \ + v8::Local<v8::Value> value, const v8::AccessorInfo& info) + +#define DECLARE_PROPERTY_ACCESSOR(NAME) DECLARE_PROPERTY_ACCESSOR_GETTER(NAME); DECLARE_PROPERTY_ACCESSOR_SETTER(NAME) + +#define DECLARE_NAMED_PROPERTY_GETTER(NAME) \ + static v8::Handle<v8::Value> v8##NAME##NamedPropertyGetter( \ + v8::Local<v8::String> name, const v8::AccessorInfo& info) + +#define DECLARE_NAMED_PROPERTY_SETTER(NAME) \ + static v8::Handle<v8::Value> v8##NAME##NamedPropertySetter( \ + v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) + +#define DECLARE_NAMED_PROPERTY_DELETER(NAME) \ + static v8::Handle<v8::Boolean> v8##NAME##NamedPropertyDeleter( \ + v8::Local<v8::String> name, const v8::AccessorInfo& info) + +#define USE_NAMED_PROPERTY_GETTER(NAME) V8Custom::v8##NAME##NamedPropertyGetter + +#define USE_NAMED_PROPERTY_SETTER(NAME) V8Custom::v8##NAME##NamedPropertySetter + +#define USE_NAMED_PROPERTY_DELETER(NAME) V8Custom::v8##NAME##NamedPropertyDeleter + +#define DECLARE_INDEXED_PROPERTY_GETTER(NAME) \ + static v8::Handle<v8::Value> v8##NAME##IndexedPropertyGetter( \ + uint32_t index, const v8::AccessorInfo& info) + +#define DECLARE_INDEXED_PROPERTY_SETTER(NAME) \ + static v8::Handle<v8::Value> v8##NAME##IndexedPropertySetter( \ + uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info) + +#define DECLARE_INDEXED_PROPERTY_DELETER(NAME) \ + static v8::Handle<v8::Boolean> v8##NAME##IndexedPropertyDeleter( \ + uint32_t index, const v8::AccessorInfo& info) + +#define USE_INDEXED_PROPERTY_GETTER(NAME) V8Custom::v8##NAME##IndexedPropertyGetter + +#define USE_INDEXED_PROPERTY_SETTER(NAME) V8Custom::v8##NAME##IndexedPropertySetter + +#define USE_INDEXED_PROPERTY_DELETER(NAME) V8Custom::v8##NAME##IndexedPropertyDeleter + +#define DECLARE_CALLBACK(NAME) static v8::Handle<v8::Value> v8##NAME##Callback(const v8::Arguments& args) + +#define USE_CALLBACK(NAME) V8Custom::v8##NAME##Callback + +#define DECLARE_NAMED_ACCESS_CHECK(NAME) \ + static bool v8##NAME##NamedSecurityCheck(v8::Local<v8::Object> host, \ + v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value> data) + +#define DECLARE_INDEXED_ACCESS_CHECK(NAME) \ + static bool v8##NAME##IndexedSecurityCheck(v8::Local<v8::Object> host, \ + uint32_t index, v8::AccessType type, v8::Local<v8::Value> data) + + DECLARE_PROPERTY_ACCESSOR(CanvasRenderingContext2DStrokeStyle); + DECLARE_PROPERTY_ACCESSOR(CanvasRenderingContext2DFillStyle); + DECLARE_PROPERTY_ACCESSOR_GETTER(DOMWindowEvent); + DECLARE_PROPERTY_ACCESSOR_GETTER(DOMWindowCrypto); + DECLARE_PROPERTY_ACCESSOR_SETTER(DOMWindowLocation); + DECLARE_PROPERTY_ACCESSOR_SETTER(DOMWindowOpener); + + DECLARE_PROPERTY_ACCESSOR(DocumentLocation); + DECLARE_PROPERTY_ACCESSOR(DocumentImplementation); + DECLARE_PROPERTY_ACCESSOR_GETTER(EventSrcElement); + DECLARE_PROPERTY_ACCESSOR(EventReturnValue); + DECLARE_PROPERTY_ACCESSOR_GETTER(EventDataTransfer); + DECLARE_PROPERTY_ACCESSOR_GETTER(EventClipboardData); + + DECLARE_PROPERTY_ACCESSOR(DOMWindowEventHandler); + DECLARE_PROPERTY_ACCESSOR(NodeEventHandler); + + DECLARE_CALLBACK(HTMLCanvasElementGetContext); + + DECLARE_PROPERTY_ACCESSOR_SETTER(HTMLFrameElementSrc); + DECLARE_PROPERTY_ACCESSOR_SETTER(HTMLFrameElementLocation); + DECLARE_PROPERTY_ACCESSOR_SETTER(HTMLIFrameElementSrc); + + DECLARE_PROPERTY_ACCESSOR_SETTER(AttrValue); + + DECLARE_PROPERTY_ACCESSOR(HTMLOptionsCollectionLength); + + DECLARE_CALLBACK(HTMLInputElementSetSelectionRange); + + DECLARE_PROPERTY_ACCESSOR(HTMLInputElementSelectionStart); + DECLARE_PROPERTY_ACCESSOR(HTMLInputElementSelectionEnd); + + DECLARE_NAMED_ACCESS_CHECK(Location); + DECLARE_INDEXED_ACCESS_CHECK(History); + + DECLARE_NAMED_ACCESS_CHECK(History); + DECLARE_INDEXED_ACCESS_CHECK(Location); + + DECLARE_CALLBACK(HTMLCollectionItem); + DECLARE_CALLBACK(HTMLCollectionNamedItem); + DECLARE_CALLBACK(HTMLCollectionCallAsFunction); + + DECLARE_CALLBACK(HTMLSelectElementRemove); + + DECLARE_CALLBACK(HTMLOptionsCollectionRemove); + DECLARE_CALLBACK(HTMLOptionsCollectionAdd); + + DECLARE_CALLBACK(HTMLDocumentWrite); + DECLARE_CALLBACK(HTMLDocumentWriteln); + DECLARE_CALLBACK(HTMLDocumentOpen); + DECLARE_PROPERTY_ACCESSOR(HTMLDocumentAll); + DECLARE_NAMED_PROPERTY_GETTER(HTMLDocument); + DECLARE_NAMED_PROPERTY_DELETER(HTMLDocument); + + DECLARE_CALLBACK(DocumentEvaluate); + DECLARE_CALLBACK(DocumentGetCSSCanvasContext); + + DECLARE_CALLBACK(DOMWindowAddEventListener); + DECLARE_CALLBACK(DOMWindowRemoveEventListener); + DECLARE_CALLBACK(DOMWindowPostMessage); + DECLARE_CALLBACK(DOMWindowSetTimeout); + DECLARE_CALLBACK(DOMWindowSetInterval); + DECLARE_CALLBACK(DOMWindowAtob); + DECLARE_CALLBACK(DOMWindowBtoa); + DECLARE_CALLBACK(DOMWindowNOP); + DECLARE_CALLBACK(DOMWindowToString); + DECLARE_CALLBACK(DOMWindowShowModalDialog); + DECLARE_CALLBACK(DOMWindowOpen); + DECLARE_CALLBACK(DOMWindowClearTimeout); + DECLARE_CALLBACK(DOMWindowClearInterval); + + DECLARE_CALLBACK(DOMParserConstructor); + DECLARE_CALLBACK(HTMLAudioElementConstructor); + DECLARE_CALLBACK(HTMLImageElementConstructor); + DECLARE_CALLBACK(HTMLOptionElementConstructor); + DECLARE_CALLBACK(MessageChannelConstructor); + DECLARE_CALLBACK(WebKitCSSMatrixConstructor); + DECLARE_CALLBACK(WebKitPointConstructor); + DECLARE_CALLBACK(XMLHttpRequestConstructor); + DECLARE_CALLBACK(XMLSerializerConstructor); + DECLARE_CALLBACK(XPathEvaluatorConstructor); + DECLARE_CALLBACK(XSLTProcessorConstructor); + + DECLARE_CALLBACK(XSLTProcessorImportStylesheet); + DECLARE_CALLBACK(XSLTProcessorTransformToFragment); + DECLARE_CALLBACK(XSLTProcessorTransformToDocument); + DECLARE_CALLBACK(XSLTProcessorSetParameter); + DECLARE_CALLBACK(XSLTProcessorGetParameter); + DECLARE_CALLBACK(XSLTProcessorRemoveParameter); + + DECLARE_CALLBACK(CSSPrimitiveValueGetRGBColorValue); + + DECLARE_CALLBACK(CanvasRenderingContext2DSetStrokeColor); + DECLARE_CALLBACK(CanvasRenderingContext2DSetFillColor); + DECLARE_CALLBACK(CanvasRenderingContext2DStrokeRect); + DECLARE_CALLBACK(CanvasRenderingContext2DSetShadow); + DECLARE_CALLBACK(CanvasRenderingContext2DDrawImage); + DECLARE_CALLBACK(CanvasRenderingContext2DDrawImageFromRect); + DECLARE_CALLBACK(CanvasRenderingContext2DCreatePattern); + DECLARE_CALLBACK(CanvasRenderingContext2DFillText); + DECLARE_CALLBACK(CanvasRenderingContext2DStrokeText); + DECLARE_CALLBACK(CanvasRenderingContext2DPutImageData); + + DECLARE_PROPERTY_ACCESSOR_GETTER(ClipboardTypes); + DECLARE_CALLBACK(ClipboardClearData); + DECLARE_CALLBACK(ClipboardGetData); + DECLARE_CALLBACK(ClipboardSetData); + DECLARE_CALLBACK(ClipboardSetDragImage); + + DECLARE_CALLBACK(ElementQuerySelector); + DECLARE_CALLBACK(ElementQuerySelectorAll); + DECLARE_CALLBACK(ElementSetAttribute); + DECLARE_CALLBACK(ElementSetAttributeNode); + DECLARE_CALLBACK(ElementSetAttributeNS); + DECLARE_CALLBACK(ElementSetAttributeNodeNS); + + DECLARE_PROPERTY_ACCESSOR_SETTER(LocationProtocol); + DECLARE_PROPERTY_ACCESSOR_SETTER(LocationHost); + DECLARE_PROPERTY_ACCESSOR_SETTER(LocationHostname); + DECLARE_PROPERTY_ACCESSOR_SETTER(LocationPort); + DECLARE_PROPERTY_ACCESSOR_SETTER(LocationPathname); + DECLARE_PROPERTY_ACCESSOR_SETTER(LocationSearch); + DECLARE_PROPERTY_ACCESSOR_SETTER(LocationHash); + DECLARE_PROPERTY_ACCESSOR_SETTER(LocationHref); + DECLARE_PROPERTY_ACCESSOR_GETTER(LocationAssign); + DECLARE_PROPERTY_ACCESSOR_GETTER(LocationReplace); + DECLARE_PROPERTY_ACCESSOR_GETTER(LocationReload); + DECLARE_CALLBACK(LocationAssign); + DECLARE_CALLBACK(LocationReplace); + DECLARE_CALLBACK(LocationReload); + DECLARE_CALLBACK(LocationToString); + DECLARE_CALLBACK(LocationValueOf); + + DECLARE_CALLBACK(NodeAddEventListener); + DECLARE_CALLBACK(NodeRemoveEventListener); + DECLARE_CALLBACK(NodeInsertBefore); + DECLARE_CALLBACK(NodeReplaceChild); + DECLARE_CALLBACK(NodeRemoveChild); + DECLARE_CALLBACK(NodeAppendChild); + + // We actually only need this because WebKit has + // navigator.appVersion as custom. Our version just + // passes through. + DECLARE_PROPERTY_ACCESSOR(NavigatorAppVersion); + + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestOnabort); + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestOnerror); + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestOnload); + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestOnloadstart); + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestOnprogress); + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestOnreadystatechange); + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestResponseText); + DECLARE_CALLBACK(XMLHttpRequestAddEventListener); + DECLARE_CALLBACK(XMLHttpRequestRemoveEventListener); + DECLARE_CALLBACK(XMLHttpRequestOpen); + DECLARE_CALLBACK(XMLHttpRequestSend); + DECLARE_CALLBACK(XMLHttpRequestSetRequestHeader); + DECLARE_CALLBACK(XMLHttpRequestGetResponseHeader); + DECLARE_CALLBACK(XMLHttpRequestOverrideMimeType); + DECLARE_CALLBACK(XMLHttpRequestDispatchEvent); + + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestUploadOnabort); + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestUploadOnerror); + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestUploadOnload); + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestUploadOnloadstart); + DECLARE_PROPERTY_ACCESSOR(XMLHttpRequestUploadOnprogress); + DECLARE_CALLBACK(XMLHttpRequestUploadAddEventListener); + DECLARE_CALLBACK(XMLHttpRequestUploadRemoveEventListener); + DECLARE_CALLBACK(XMLHttpRequestUploadDispatchEvent); + + DECLARE_CALLBACK(TreeWalkerParentNode); + DECLARE_CALLBACK(TreeWalkerFirstChild); + DECLARE_CALLBACK(TreeWalkerLastChild); + DECLARE_CALLBACK(TreeWalkerNextNode); + DECLARE_CALLBACK(TreeWalkerPreviousNode); + DECLARE_CALLBACK(TreeWalkerNextSibling); + DECLARE_CALLBACK(TreeWalkerPreviousSibling); + + DECLARE_CALLBACK(InspectorBackendProfiles); + DECLARE_CALLBACK(InspectorBackendHighlightDOMNode); + DECLARE_CALLBACK(InspectorBackendAddResourceSourceToFrame); + DECLARE_CALLBACK(InspectorBackendAddSourceToFrame); + DECLARE_CALLBACK(InspectorBackendSearch); + DECLARE_CALLBACK(InspectorBackendSetting); + DECLARE_CALLBACK(InspectorBackendInspectedWindow); + DECLARE_CALLBACK(InspectorBackendSetSetting); + DECLARE_CALLBACK(InspectorBackendCurrentCallFrame); + DECLARE_CALLBACK(InspectorBackendDebuggerEnabled); + DECLARE_CALLBACK(InspectorBackendPauseOnExceptions); + DECLARE_CALLBACK(InspectorBackendProfilerEnabled); +#if ENABLE(DATABASE) + DECLARE_CALLBACK(InspectorBackendDatabaseTableNames); +#endif + DECLARE_CALLBACK(InspectorBackendWrapCallback); + + DECLARE_CALLBACK(NodeIteratorNextNode); + DECLARE_CALLBACK(NodeIteratorPreviousNode); + + DECLARE_CALLBACK(NodeFilterAcceptNode); + + DECLARE_CALLBACK(HTMLFormElementSubmit); + + DECLARE_NAMED_PROPERTY_GETTER(DOMWindow); + DECLARE_INDEXED_PROPERTY_GETTER(DOMWindow); + DECLARE_NAMED_ACCESS_CHECK(DOMWindow); + DECLARE_INDEXED_ACCESS_CHECK(DOMWindow); + + DECLARE_NAMED_PROPERTY_GETTER(HTMLFrameSetElement); + DECLARE_NAMED_PROPERTY_GETTER(HTMLFormElement); + DECLARE_NAMED_PROPERTY_GETTER(NodeList); + DECLARE_NAMED_PROPERTY_GETTER(NamedNodeMap); + DECLARE_NAMED_PROPERTY_GETTER(CSSStyleDeclaration); + DECLARE_NAMED_PROPERTY_SETTER(CSSStyleDeclaration); + DECLARE_NAMED_PROPERTY_GETTER(HTMLPlugInElement); + DECLARE_NAMED_PROPERTY_SETTER(HTMLPlugInElement); + DECLARE_INDEXED_PROPERTY_GETTER(HTMLPlugInElement); + DECLARE_INDEXED_PROPERTY_SETTER(HTMLPlugInElement); + + DECLARE_CALLBACK(HTMLPlugInElement); + + DECLARE_NAMED_PROPERTY_GETTER(StyleSheetList); + DECLARE_INDEXED_PROPERTY_GETTER(NamedNodeMap); + DECLARE_INDEXED_PROPERTY_GETTER(HTMLFormElement); + DECLARE_INDEXED_PROPERTY_GETTER(HTMLOptionsCollection); + DECLARE_INDEXED_PROPERTY_SETTER(HTMLOptionsCollection); + DECLARE_NAMED_PROPERTY_GETTER(HTMLSelectElementCollection); + DECLARE_INDEXED_PROPERTY_SETTER(HTMLSelectElementCollection); + DECLARE_NAMED_PROPERTY_GETTER(HTMLCollection); + + DECLARE_INDEXED_PROPERTY_GETTER(CanvasPixelArray); + DECLARE_INDEXED_PROPERTY_SETTER(CanvasPixelArray); + + DECLARE_PROPERTY_ACCESSOR(MessagePortOnmessage); + DECLARE_PROPERTY_ACCESSOR(MessagePortOnclose); + DECLARE_CALLBACK(MessagePortStartConversation); + DECLARE_CALLBACK(MessagePortAddEventListener); + DECLARE_CALLBACK(MessagePortRemoveEventListener); + + DECLARE_CALLBACK(DatabaseChangeVersion); + DECLARE_CALLBACK(DatabaseTransaction); + DECLARE_CALLBACK(SQLTransactionExecuteSql); + DECLARE_CALLBACK(SQLResultSetRowListItem); + + DECLARE_INDEXED_PROPERTY_GETTER(ClientRectList); + +#if ENABLE(DATAGRID) + DECLARE_PROPERTY_ACCESSOR(HTMLDataGridElementDataSource); + DECLARE_INDEXED_PROPERTY_GETTER(DataGridColumnList); + DECLARE_NAMED_PROPERTY_GETTER(DataGridColumnList); +#endif + +#if ENABLE(DOM_STORAGE) + DECLARE_INDEXED_PROPERTY_GETTER(Storage); + DECLARE_INDEXED_PROPERTY_SETTER(Storage); + DECLARE_INDEXED_PROPERTY_DELETER(Storage); + DECLARE_NAMED_PROPERTY_GETTER(Storage); + DECLARE_NAMED_PROPERTY_SETTER(Storage); + DECLARE_NAMED_PROPERTY_DELETER(Storage); + static v8::Handle<v8::Array> v8StorageNamedPropertyEnumerator(const v8::AccessorInfo& info); +#endif + +#if ENABLE(SVG) + DECLARE_PROPERTY_ACCESSOR_GETTER(SVGLengthValue); + DECLARE_CALLBACK(SVGLengthConvertToSpecifiedUnits); + DECLARE_CALLBACK(SVGMatrixInverse); + DECLARE_CALLBACK(SVGMatrixRotateFromVector); + DECLARE_CALLBACK(SVGElementInstanceAddEventListener); + DECLARE_CALLBACK(SVGElementInstanceRemoveEventListener); +#endif + +#if ENABLE(WORKERS) + DECLARE_PROPERTY_ACCESSOR(AbstractWorkerOnerror); + DECLARE_CALLBACK(AbstractWorkerAddEventListener); + DECLARE_CALLBACK(AbstractWorkerRemoveEventListener); + + DECLARE_PROPERTY_ACCESSOR(DedicatedWorkerContextOnmessage); + + DECLARE_PROPERTY_ACCESSOR(WorkerOnmessage); + DECLARE_CALLBACK(WorkerConstructor); + + DECLARE_PROPERTY_ACCESSOR_GETTER(WorkerContextSelf); + DECLARE_PROPERTY_ACCESSOR(WorkerContextOnerror); + DECLARE_CALLBACK(WorkerContextImportScripts); + DECLARE_CALLBACK(WorkerContextSetTimeout); + DECLARE_CALLBACK(WorkerContextClearTimeout); + DECLARE_CALLBACK(WorkerContextSetInterval); + DECLARE_CALLBACK(WorkerContextClearInterval); + DECLARE_CALLBACK(WorkerContextAddEventListener); + DECLARE_CALLBACK(WorkerContextRemoveEventListener); +#endif + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + DECLARE_PROPERTY_ACCESSOR(DOMApplicationCacheEventHandler); + DECLARE_CALLBACK(DOMApplicationCacheAddEventListener); + DECLARE_CALLBACK(DOMApplicationCacheRemoveEventListener); +#endif + +#if ENABLE(SHARED_WORKERS) + DECLARE_CALLBACK(SharedWorkerConstructor); +#endif + +#undef DECLARE_INDEXED_ACCESS_CHECK +#undef DECLARE_NAMED_ACCESS_CHECK + +#undef DECLARE_PROPERTY_ACCESSOR_SETTER +#undef DECLARE_PROPERTY_ACCESSOR_GETTER +#undef DECLARE_PROPERTY_ACCESSOR + +#undef DECLARE_NAMED_PROPERTY_GETTER +#undef DECLARE_NAMED_PROPERTY_SETTER +#undef DECLARE_NAMED_PROPERTY_DELETER + +#undef DECLARE_INDEXED_PROPERTY_GETTER +#undef DECLARE_INDEXED_PROPERTY_SETTER +#undef DECLARE_INDEXED_PROPERTY_DELETER + +#undef DECLARE_CALLBACK + + // Returns the NPObject corresponding to an HTMLElement object. + static NPObject* GetHTMLPlugInElementNPObject(v8::Handle<v8::Object>); + + // Returns the owner frame pointer of a DOM wrapper object. It only works for + // these DOM objects requiring cross-domain access check. + static Frame* GetTargetFrame(v8::Local<v8::Object> host, v8::Local<v8::Value> data); + + // Special case for downcasting SVG path segments. +#if ENABLE(SVG) + static V8ClassIndex::V8WrapperType DowncastSVGPathSeg(void* pathSeg); +#endif + + private: + static v8::Handle<v8::Value> WindowSetTimeoutImpl(const v8::Arguments&, bool singleShot); + static void ClearTimeoutImpl(const v8::Arguments&); + static void WindowSetLocation(DOMWindow*, const String&); + }; + +#endif // MANUAL_MERGE_REQUIRED } // namespace WebCore #endif // V8CustomBinding_h diff --git a/WebCore/bindings/v8/custom/V8CustomEventListener.cpp b/WebCore/bindings/v8/custom/V8CustomEventListener.cpp index bd9e307..305da8d 100644 --- a/WebCore/bindings/v8/custom/V8CustomEventListener.cpp +++ b/WebCore/bindings/v8/custom/V8CustomEventListener.cpp @@ -40,7 +40,7 @@ V8EventListener::V8EventListener(Frame* frame, v8::Local<v8::Object> listener, b { m_listener = v8::Persistent<v8::Object>::New(listener); #ifndef NDEBUG - V8Proxy::RegisterGlobalHandle(EVENT_LISTENER, this, m_listener); + V8GCController::registerGlobalHandle(EVENT_LISTENER, this, m_listener); #endif } @@ -49,7 +49,7 @@ V8EventListener::~V8EventListener() if (m_frame) { V8Proxy* proxy = V8Proxy::retrieve(m_frame); if (proxy) - proxy->RemoveV8EventListener(this); + proxy->eventListeners()->remove(this); } disposeListenerObject(); @@ -83,7 +83,9 @@ v8::Local<v8::Value> V8EventListener::callListenerFunction(v8::Handle<v8::Value> v8::Handle<v8::Value> parameters[1] = { jsEvent }; V8Proxy* proxy = V8Proxy::retrieve(m_frame); - return proxy->CallFunction(handlerFunction, receiver, 1, parameters); + if (!proxy) + return v8::Local<v8::Value>(); + return proxy->callFunction(handlerFunction, receiver, 1, parameters); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.cpp index daa9b34..2abdb15 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.cpp @@ -55,15 +55,15 @@ void V8CustomSQLStatementCallback::handleEvent(SQLTransaction* transaction, SQLR LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_frame.get()); + v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); if (context.IsEmpty()) return; v8::Context::Scope scope(context); v8::Handle<v8::Value> argv[] = { - V8Proxy::ToV8Object(V8ClassIndex::SQLTRANSACTION, transaction), - V8Proxy::ToV8Object(V8ClassIndex::SQLRESULTSET, resultSet) + V8DOMWrapper::convertToV8Object(V8ClassIndex::SQLTRANSACTION, transaction), + V8DOMWrapper::convertToV8Object(V8ClassIndex::SQLRESULTSET, resultSet) }; // Protect the frame until the callback returns. diff --git a/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp index 6c7aba2..4b84ebe 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp @@ -55,15 +55,15 @@ bool V8CustomSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_frame.get()); + v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); if (context.IsEmpty()) return true; v8::Context::Scope scope(context); v8::Handle<v8::Value> argv[] = { - V8Proxy::ToV8Object(V8ClassIndex::SQLTRANSACTION, transaction), - V8Proxy::ToV8Object(V8ClassIndex::SQLERROR, error) + V8DOMWrapper::convertToV8Object(V8ClassIndex::SQLTRANSACTION, transaction), + V8DOMWrapper::convertToV8Object(V8ClassIndex::SQLERROR, error) }; // Protect the frame until the callback returns. diff --git a/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.cpp index c255483..704115e 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.cpp @@ -56,14 +56,14 @@ void V8CustomSQLTransactionCallback::handleEvent(SQLTransaction* transaction, bo LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_frame.get()); + v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); if (context.IsEmpty()) return; v8::Context::Scope scope(context); v8::Handle<v8::Value> argv[] = { - V8Proxy::ToV8Object(V8ClassIndex::SQLTRANSACTION, transaction) + V8DOMWrapper::convertToV8Object(V8ClassIndex::SQLTRANSACTION, transaction) }; // Protect the frame until the callback returns. diff --git a/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp index 8dcb0a8..f30467c 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp @@ -55,14 +55,14 @@ void V8CustomSQLTransactionErrorCallback::handleEvent(SQLError* error) LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_frame.get()); + v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); if (context.IsEmpty()) return; v8::Context::Scope scope(context); v8::Handle<v8::Value> argv[] = { - V8Proxy::ToV8Object(V8ClassIndex::SQLERROR, error) + V8DOMWrapper::convertToV8Object(V8ClassIndex::SQLERROR, error) }; // Protect the frame until the callback returns. diff --git a/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp b/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp index b2972e4..925271f 100644 --- a/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp @@ -51,7 +51,7 @@ void V8CustomVoidCallback::handleEvent() LOCK_V8; v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::GetContext(m_frame.get()); + v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); if (context.IsEmpty()) return; @@ -88,7 +88,7 @@ bool invokeCallback(v8::Persistent<v8::Object> callback, int argc, v8::Handle<v8 V8Proxy* proxy = V8Proxy::retrieve(); ASSERT(proxy); - v8::Handle<v8::Value> result = proxy->CallFunction(callbackFunction, thisObject, argc, argv); + v8::Handle<v8::Value> result = proxy->callFunction(callbackFunction, thisObject, argc, argv); callbackReturnValue = !result.IsEmpty() && result->IsBoolean() && result->BooleanValue(); diff --git a/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.cpp b/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.cpp new file mode 100644 index 0000000..3341924 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.cpp @@ -0,0 +1,93 @@ +// Copyright (c) 2008, 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. + +#include "config.h" +#include "V8CustomXPathNSResolver.h" + +#if ENABLE(XPATH) + +#include "PlatformString.h" +#include "V8Binding.h" +#include "V8Proxy.h" + +namespace WebCore { + +PassRefPtr<V8CustomXPathNSResolver> V8CustomXPathNSResolver::create(v8::Handle<v8::Object> resolver) +{ + return adoptRef(new V8CustomXPathNSResolver(resolver)); +} + +V8CustomXPathNSResolver::V8CustomXPathNSResolver(v8::Handle<v8::Object> resolver) + : m_resolver(resolver) +{ +} + +V8CustomXPathNSResolver::~V8CustomXPathNSResolver() +{ +} + +String V8CustomXPathNSResolver::lookupNamespaceURI(const String& prefix) +{ + v8::Handle<v8::Function> lookupNamespaceURIFunc; + v8::Handle<v8::String> lookupNamespaceURIName = v8::String::New("lookupNamespaceURI"); + + // Check if the resolver has a function property named lookupNamespaceURI. + if (m_resolver->Has(lookupNamespaceURIName)) { + v8::Handle<v8::Value> lookupNamespaceURI = m_resolver->Get(lookupNamespaceURIName); + if (lookupNamespaceURI->IsFunction()) + lookupNamespaceURIFunc = v8::Handle<v8::Function>::Cast(lookupNamespaceURI); + } + + if (lookupNamespaceURIFunc.IsEmpty() && !m_resolver->IsFunction()) { + Frame* frame = V8Proxy::retrieveFrameForEnteredContext(); + logInfo(frame, "XPathNSResolver does not have a lookupNamespaceURI method.", String()); + return String(); + } + + // Catch exceptions from calling the namespace resolver. + v8::TryCatch try_catch; + try_catch.SetVerbose(true); // Print exceptions to console. + + const int argc = 1; + v8::Handle<v8::Value> argv[argc] = { v8String(prefix) }; + v8::Handle<v8::Function> function = lookupNamespaceURIFunc.IsEmpty() ? v8::Handle<v8::Function>::Cast(m_resolver) : lookupNamespaceURIFunc; + + V8Proxy* proxy = V8Proxy::retrieve(); + v8::Handle<v8::Value> retval = proxy->callFunction(function, m_resolver, argc, argv); + + // Eat exceptions from namespace resolver and return an empty string. This will most likely cause NAMESPACE_ERR. + if (try_catch.HasCaught()) + return String(); + + return toWebCoreStringWithNullCheck(retval); +} + +} // namespace WebCore + +#endif // ENABLE(XPATH) diff --git a/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.h b/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.h new file mode 100644 index 0000000..f1dc65c --- /dev/null +++ b/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.h @@ -0,0 +1,63 @@ +/* + * 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: + * + * * 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 V8CustomXPathNSResolver_h +#define V8CustomXPathNSResolver_h + +#if ENABLE(XPATH) + +#include "XPathNSResolver.h" +#include <v8.h> +#include <wtf/Forward.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class String; + +class V8CustomXPathNSResolver : public XPathNSResolver { +public: + static PassRefPtr<V8CustomXPathNSResolver> create(v8::Handle<v8::Object> resolver); + + virtual ~V8CustomXPathNSResolver(); + virtual String lookupNamespaceURI(const String& prefix); + +private: + V8CustomXPathNSResolver(v8::Handle<v8::Object> resolver); + + v8::Handle<v8::Object> m_resolver; // Handle to resolver object. +}; + +} // namespace WebCore + +#endif // ENABLE(XPATH) + +#endif // V8CustomXPathNSResolver_h diff --git a/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp b/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp index 2ed1638..dd05b45 100644 --- a/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009 Google Inc. All rights reserved. + * 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 @@ -33,9 +33,10 @@ #if ENABLE(OFFLINE_WEB_APPLICATIONS) +#include "ApplicationCacheHost.h" #include "V8Binding.h" -#include "V8Document.h" #include "V8CustomBinding.h" +#include "V8Document.h" #include "V8ObjectEventListener.h" #include "V8Proxy.h" #include "V8Utilities.h" @@ -48,17 +49,10 @@ static const bool kFindOrCreate = false; static PassRefPtr<EventListener> argumentToEventListener(DOMApplicationCache* appcache, v8::Local<v8::Value> value, bool findOnly) { -#if 0 && ENABLE(WORKERS) - // FIXME: this is not tested yet - WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); - if (workerContextProxy) - return workerContextProxy->findOrCreateObjectEventListener(value, false, findOnly); -#endif - V8Proxy* proxy = V8Proxy::retrieve(appcache->scriptExecutionContext()); if (proxy) - return findOnly ? proxy->FindObjectEventListener(value, false) - : proxy->FindOrCreateObjectEventListener(value, false); + return findOnly ? proxy->objectListeners()->findWrapper(value, false) + : proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); return 0; } @@ -67,30 +61,28 @@ static v8::Local<v8::Object> eventListenerToV8Object(EventListener* listener) return (static_cast<V8ObjectEventListener*>(listener))->getListenerObject(); } -static inline String toEventType(v8::Local<v8::String> value) +static inline ApplicationCacheHost::EventID toEventID(v8::Local<v8::String> value) { String key = toWebCoreString(value); ASSERT(key.startsWith("on")); - return key.substring(2); + return DOMApplicationCache::toEventID(key.substring(2)); } // Handles appcache.onfooevent attribute getting ACCESSOR_GETTER(DOMApplicationCacheEventHandler) { INC_STATS("DOMApplicationCache.onevent_getter"); - DOMApplicationCache* appcache = V8Proxy::ToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, info.Holder()); - if (EventListener* listener = appcache->getAttributeEventListener(toEventType(name))) { - return eventListenerToV8Object(listener); - } - return v8::Null(); + DOMApplicationCache* appcache = V8DOMWrapper::convertToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, info.Holder()); + EventListener* listener = appcache->getAttributeEventListener(toEventID(name)); + return eventListenerToV8Object(listener); } // Handles appcache.onfooevent attribute setting ACCESSOR_SETTER(DOMApplicationCacheEventHandler) { INC_STATS("DOMApplicationCache.onevent_setter"); - DOMApplicationCache* appcache = V8Proxy::ToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, info.Holder()); - String eventType = toEventType(name); + DOMApplicationCache* appcache = V8DOMWrapper::convertToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, info.Holder()); + ApplicationCacheHost::EventID eventType = toEventID(name); if (EventListener* oldListener = appcache->getAttributeEventListener(eventType)) { v8::Local<v8::Object> object = eventListenerToV8Object(oldListener); @@ -111,7 +103,7 @@ ACCESSOR_SETTER(DOMApplicationCacheEventHandler) CALLBACK_FUNC_DECL(DOMApplicationCacheAddEventListener) { INC_STATS("DOMApplicationCache.addEventListener()"); - DOMApplicationCache* appcache = V8Proxy::ToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, args.Holder()); + DOMApplicationCache* appcache = V8DOMWrapper::convertToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, args.Holder()); RefPtr<EventListener> listener = argumentToEventListener(appcache, args[1], kFindOrCreate); if (listener) { @@ -127,7 +119,7 @@ CALLBACK_FUNC_DECL(DOMApplicationCacheAddEventListener) CALLBACK_FUNC_DECL(DOMApplicationCacheRemoveEventListener) { INC_STATS("DOMApplicationCache.removeEventListener()"); - DOMApplicationCache* appcache = V8Proxy::ToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, args.Holder()); + DOMApplicationCache* appcache = V8DOMWrapper::convertToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, args.Holder()); RefPtr<EventListener> listener = argumentToEventListener(appcache, args[1], kFindOnly); if (listener) { diff --git a/WebCore/bindings/v8/custom/V8DOMParserConstructor.cpp b/WebCore/bindings/v8/custom/V8DOMParserConstructor.cpp index f96b889..4af5c6e 100644 --- a/WebCore/bindings/v8/custom/V8DOMParserConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8DOMParserConstructor.cpp @@ -39,7 +39,7 @@ namespace WebCore { CALLBACK_FUNC_DECL(DOMParserConstructor) { INC_STATS("DOM.DOMParser.Contructor"); - return V8Proxy::ConstructDOMObject<V8ClassIndex::DOMPARSER, DOMParser>(args); + return V8Proxy::constructDOMObject<V8ClassIndex::DOMPARSER, DOMParser>(args); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp b/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp index c13c3b2..7d0b9e6 100644 --- a/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp @@ -64,12 +64,12 @@ v8::Handle<v8::Value> V8Custom::WindowSetTimeoutImpl(const v8::Arguments& args, if (argumentCount < 1) return v8::Undefined(); - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); if (!imp->frame()) return v8::Undefined(); - if (!V8Proxy::CanAccessFrame(imp->frame(), true)) + if (!V8Proxy::canAccessFrame(imp->frame(), true)) return v8::Undefined(); ScriptExecutionContext* scriptContext = static_cast<ScriptExecutionContext*>(imp->frame()->document()); @@ -124,7 +124,7 @@ static bool isAscii(const String& str) static v8::Handle<v8::Value> convertBase64(const String& str, bool encode) { if (!isAscii(str)) { - V8Proxy::SetDOMException(INVALID_CHARACTER_ERR); + V8Proxy::setDOMException(INVALID_CHARACTER_ERR); return notHandledByInterceptor(); } @@ -137,7 +137,7 @@ static v8::Handle<v8::Value> convertBase64(const String& str, bool encode) base64Encode(inputCharacters, outputCharacters); else { if (!base64Decode(inputCharacters, outputCharacters)) - return throwError("Cannot decode base64", V8Proxy::GENERAL_ERROR); + return throwError("Cannot decode base64", V8Proxy::GeneralError); } return v8String(String(outputCharacters.data(), outputCharacters.size())); @@ -161,20 +161,20 @@ ACCESSOR_GETTER(DOMWindowCrypto) ACCESSOR_SETTER(DOMWindowLocation) { - v8::Handle<v8::Object> holder = V8Proxy::LookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); if (holder.IsEmpty()) return; - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); WindowSetLocation(imp, toWebCoreString(value)); } ACCESSOR_SETTER(DOMWindowOpener) { - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder()); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder()); - if (!V8Proxy::CanAccessFrame(imp->frame(), true)) + if (!V8Proxy::canAccessFrame(imp->frame(), true)) return; // Opener can be shadowed if it is in the same domain. @@ -197,9 +197,9 @@ ACCESSOR_SETTER(DOMWindowOpener) CALLBACK_FUNC_DECL(DOMWindowAddEventListener) { INC_STATS("DOM.DOMWindow.addEventListener()"); - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); - if (!V8Proxy::CanAccessFrame(imp->frame(), true)) + if (!V8Proxy::canAccessFrame(imp->frame(), true)) return v8::Undefined(); if (!imp->frame()) @@ -214,7 +214,7 @@ CALLBACK_FUNC_DECL(DOMWindowAddEventListener) if (!proxy) return v8::Undefined(); - RefPtr<EventListener> listener = proxy->FindOrCreateV8EventListener(args[1], false); + RefPtr<EventListener> listener = proxy->eventListeners()->findOrCreateWrapper<V8EventListener>(proxy->frame(), args[1], false); if (listener) { String eventType = toWebCoreString(args[0]); @@ -229,9 +229,9 @@ CALLBACK_FUNC_DECL(DOMWindowAddEventListener) CALLBACK_FUNC_DECL(DOMWindowRemoveEventListener) { INC_STATS("DOM.DOMWindow.removeEventListener()"); - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); - if (!V8Proxy::CanAccessFrame(imp->frame(), true)) + if (!V8Proxy::canAccessFrame(imp->frame(), true)) return v8::Undefined(); if (!imp->frame()) @@ -245,7 +245,7 @@ CALLBACK_FUNC_DECL(DOMWindowRemoveEventListener) if (!proxy) return v8::Undefined(); - RefPtr<EventListener> listener = proxy->FindV8EventListener(args[1], false); + RefPtr<EventListener> listener = proxy->eventListeners()->findWrapper(args[1], false); if (listener) { String eventType = toWebCoreString(args[0]); @@ -259,13 +259,12 @@ CALLBACK_FUNC_DECL(DOMWindowRemoveEventListener) CALLBACK_FUNC_DECL(DOMWindowPostMessage) { INC_STATS("DOM.DOMWindow.postMessage()"); - DOMWindow* window = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); + DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); DOMWindow* source = V8Proxy::retrieveFrameForCallingContext()->domWindow(); ASSERT(source->frame()); v8::TryCatch tryCatch; - String message = toWebCoreString(args[0]); MessagePort* port = 0; String targetOrigin; @@ -275,11 +274,11 @@ CALLBACK_FUNC_DECL(DOMWindowPostMessage) // or // postMessage(message, targetOrigin); if (args.Length() > 2) { - if (V8Proxy::IsWrapperOfType(args[1], V8ClassIndex::MESSAGEPORT)) - port = V8Proxy::ToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, args[1]); - targetOrigin = valueToStringWithNullOrUndefinedCheck(args[2]); + if (V8DOMWrapper::isWrapperOfType(args[1], V8ClassIndex::MESSAGEPORT)) + port = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, v8::Handle<v8::Object>::Cast(args[1])); + targetOrigin = toWebCoreStringWithNullOrUndefinedCheck(args[2]); } else { - targetOrigin = valueToStringWithNullOrUndefinedCheck(args[1]); + targetOrigin = toWebCoreStringWithNullOrUndefinedCheck(args[1]); } if (tryCatch.HasCaught()) @@ -288,7 +287,7 @@ CALLBACK_FUNC_DECL(DOMWindowPostMessage) ExceptionCode ec = 0; window->postMessage(message, port, targetOrigin, source, ec); if (ec) - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Undefined(); } @@ -296,13 +295,13 @@ CALLBACK_FUNC_DECL(DOMWindowPostMessage) CALLBACK_FUNC_DECL(DOMWindowAtob) { INC_STATS("DOM.DOMWindow.atob()"); - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); - if (!V8Proxy::CanAccessFrame(imp->frame(), true)) + if (!V8Proxy::canAccessFrame(imp->frame(), true)) return v8::Undefined(); if (args.Length() < 1) - return throwError("Not enough arguments", V8Proxy::SYNTAX_ERROR); + return throwError("Not enough arguments", V8Proxy::SyntaxError); if (args[0]->IsNull()) return v8String(""); @@ -314,13 +313,13 @@ CALLBACK_FUNC_DECL(DOMWindowAtob) CALLBACK_FUNC_DECL(DOMWindowBtoa) { INC_STATS("DOM.DOMWindow.btoa()"); - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); - if (!V8Proxy::CanAccessFrame(imp->frame(), true)) + if (!V8Proxy::canAccessFrame(imp->frame(), true)) return v8::Undefined(); if (args.Length() < 1) - return throwError("Not enough arguments", V8Proxy::SYNTAX_ERROR); + return throwError("Not enough arguments", V8Proxy::SyntaxError); if (args[0]->IsNull()) return v8String(""); @@ -373,11 +372,11 @@ static String eventNameFromAttributeName(const String& name) ACCESSOR_SETTER(DOMWindowEventHandler) { - v8::Handle<v8::Object> holder = V8Proxy::LookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); if (holder.IsEmpty()) return; - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); if (!imp->frame()) return; @@ -396,8 +395,7 @@ ACCESSOR_SETTER(DOMWindowEventHandler) if (!proxy) return; - RefPtr<EventListener> listener = - proxy->FindOrCreateV8EventListener(value, true); + RefPtr<EventListener> listener = proxy->eventListeners()->findOrCreateWrapper<V8EventListener>(proxy->frame(), value, true); if (listener) imp->setAttributeEventListener(eventType, listener); } @@ -405,11 +403,11 @@ ACCESSOR_SETTER(DOMWindowEventHandler) ACCESSOR_GETTER(DOMWindowEventHandler) { - v8::Handle<v8::Object> holder = V8Proxy::LookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); if (holder.IsEmpty()) return v8::Undefined(); - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); if (!imp->frame()) return v8::Undefined(); @@ -421,7 +419,7 @@ ACCESSOR_GETTER(DOMWindowEventHandler) String eventType = eventNameFromAttributeName(key); EventListener* listener = imp->getAttributeEventListener(eventType); - return V8Proxy::EventListenerToV8Object(listener); + return V8DOMWrapper::convertEventListenerToV8Object(listener); } static bool canShowModalDialogNow(const Frame* frame) @@ -518,7 +516,7 @@ static Frame* createWindow(Frame* callingFrame, // Set dialog arguments on the global object of the new frame. if (!dialogArgs.IsEmpty()) { - v8::Local<v8::Context> context = V8Proxy::GetContext(newFrame); + v8::Local<v8::Context> context = V8Proxy::context(newFrame); if (!context.IsEmpty()) { v8::Context::Scope scope(context); context->Global()->Set(v8::String::New("dialogArguments"), dialogArgs); @@ -544,11 +542,11 @@ static Frame* createWindow(Frame* callingFrame, CALLBACK_FUNC_DECL(DOMWindowShowModalDialog) { INC_STATS("DOM.DOMWindow.showModalDialog()"); - DOMWindow* window = V8Proxy::ToNativeObject<DOMWindow>( + DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>( V8ClassIndex::DOMWINDOW, args.Holder()); Frame* frame = window->frame(); - if (!frame || !V8Proxy::CanAccessFrame(frame, true)) + if (!frame || !V8Proxy::canAccessFrame(frame, true)) return v8::Undefined(); Frame* callingFrame = V8Proxy::retrieveFrameForCallingContext(); @@ -562,9 +560,9 @@ CALLBACK_FUNC_DECL(DOMWindowShowModalDialog) if (!canShowModalDialogNow(frame) || !allowPopUp()) return v8::Undefined(); - String url = valueToStringWithNullOrUndefinedCheck(args[0]); + String url = toWebCoreStringWithNullOrUndefinedCheck(args[0]); v8::Local<v8::Value> dialogArgs = args[1]; - String featureArgs = valueToStringWithNullOrUndefinedCheck(args[2]); + String featureArgs = toWebCoreStringWithNullOrUndefinedCheck(args[2]); const HashMap<String, String> features = parseModalDialogFeatures(featureArgs); @@ -611,7 +609,7 @@ CALLBACK_FUNC_DECL(DOMWindowShowModalDialog) // Hold on to the context of the dialog window long enough to retrieve the // value of the return value property. - v8::Local<v8::Context> context = V8Proxy::GetContext(dialogFrame); + v8::Local<v8::Context> context = V8Proxy::context(dialogFrame); // Run the dialog. dialogFrame->page()->chrome()->runModal(); @@ -633,10 +631,10 @@ CALLBACK_FUNC_DECL(DOMWindowShowModalDialog) CALLBACK_FUNC_DECL(DOMWindowOpen) { INC_STATS("DOM.DOMWindow.open()"); - DOMWindow* parent = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); + DOMWindow* parent = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder()); Frame* frame = parent->frame(); - if (!frame || !V8Proxy::CanAccessFrame(frame, true)) + if (!frame || !V8Proxy::canAccessFrame(frame, true)) return v8::Undefined(); Frame* callingFrame = V8Proxy::retrieveFrameForCallingContext(); @@ -651,7 +649,7 @@ CALLBACK_FUNC_DECL(DOMWindowOpen) if (!page) return v8::Undefined(); - String urlString = valueToStringWithNullOrUndefinedCheck(args[0]); + String urlString = toWebCoreStringWithNullOrUndefinedCheck(args[0]); AtomicString frameName = (args[1]->IsUndefined() || args[1]->IsNull()) ? "_blank" : AtomicString(toWebCoreString(args[1])); // Because FrameTree::find() returns true for empty strings, we must check @@ -691,7 +689,7 @@ CALLBACK_FUNC_DECL(DOMWindowOpen) frame->loader()->scheduleLocationChange(completedUrl, referrer, false, userGesture); } - return V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, frame->domWindow()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMWINDOW, frame->domWindow()); } // In the case of a named frame or a new window, we'll use the @@ -700,7 +698,7 @@ CALLBACK_FUNC_DECL(DOMWindowOpen) // Parse the values, and then work with a copy of the parsed values // so we can restore the values we may not want to overwrite after // we do the multiple monitor fixes. - WindowFeatures rawFeatures(valueToStringWithNullOrUndefinedCheck(args[2])); + WindowFeatures rawFeatures(toWebCoreStringWithNullOrUndefinedCheck(args[2])); WindowFeatures windowFeatures(rawFeatures); FloatRect screenRect = screenAvailableRect(page->mainFrame()->view()); @@ -751,18 +749,18 @@ CALLBACK_FUNC_DECL(DOMWindowOpen) if (!frame) return v8::Undefined(); - return V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, frame->domWindow()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMWINDOW, frame->domWindow()); } INDEXED_PROPERTY_GETTER(DOMWindow) { INC_STATS("DOM.DOMWindow.IndexedPropertyGetter"); - v8::Handle<v8::Object> holder = V8Proxy::LookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); if (holder.IsEmpty()) return notHandledByInterceptor(); - DOMWindow* window = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); + DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); if (!window) return notHandledByInterceptor(); @@ -772,7 +770,7 @@ INDEXED_PROPERTY_GETTER(DOMWindow) Frame* child = frame->tree()->child(index); if (child) - return V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, child->domWindow()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMWINDOW, child->domWindow()); return notHandledByInterceptor(); } @@ -782,11 +780,11 @@ NAMED_PROPERTY_GETTER(DOMWindow) { INC_STATS("DOM.DOMWindow.NamedPropertyGetter"); - v8::Handle<v8::Object> holder = V8Proxy::LookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This()); if (holder.IsEmpty()) return notHandledByInterceptor(); - DOMWindow* window = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); + DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); if (!window) return notHandledByInterceptor(); @@ -799,7 +797,7 @@ NAMED_PROPERTY_GETTER(DOMWindow) AtomicString propName = v8StringToAtomicWebCoreString(name); Frame* child = frame->tree()->child(propName); if (child) - return V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, child->domWindow()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMWINDOW, child->domWindow()); // Search IDL functions defined in the prototype v8::Handle<v8::Value> result = holder->GetRealNamedPropertyInPrototypeChain(name); @@ -812,9 +810,9 @@ NAMED_PROPERTY_GETTER(DOMWindow) RefPtr<HTMLCollection> items = doc->windowNamedItems(propName); if (items->length() >= 1) { if (items->length() == 1) - return V8Proxy::NodeToV8Object(items->firstItem()); + return V8DOMWrapper::convertNodeToV8Object(items->firstItem()); else - return V8Proxy::ToV8Object(V8ClassIndex::HTMLCOLLECTION, items.get()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::HTMLCOLLECTION, items.release()); } } @@ -855,9 +853,9 @@ CALLBACK_FUNC_DECL(DOMWindowSetInterval) void V8Custom::ClearTimeoutImpl(const v8::Arguments& args) { - v8::Handle<v8::Value> holder = args.Holder(); - DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); - if (!V8Proxy::CanAccessFrame(imp->frame(), true)) + v8::Handle<v8::Object> holder = args.Holder(); + DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder); + if (!V8Proxy::canAccessFrame(imp->frame(), true)) return; ScriptExecutionContext* context = static_cast<ScriptExecutionContext*>(imp->frame()->document()); int handle = toInt32(args[0]); @@ -882,11 +880,11 @@ CALLBACK_FUNC_DECL(DOMWindowClearInterval) NAMED_ACCESS_CHECK(DOMWindow) { ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::DOMWINDOW); - v8::Handle<v8::Value> window = V8Proxy::LookupDOMWrapper(V8ClassIndex::DOMWINDOW, host); + v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, host); if (window.IsEmpty()) return false; // the frame is gone. - DOMWindow* targetWindow = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window); + DOMWindow* targetWindow = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window); ASSERT(targetWindow); @@ -902,17 +900,17 @@ NAMED_ACCESS_CHECK(DOMWindow) return true; } - return V8Proxy::CanAccessFrame(target, false); + return V8Proxy::canAccessFrame(target, false); } INDEXED_ACCESS_CHECK(DOMWindow) { ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::DOMWINDOW); - v8::Handle<v8::Value> window = V8Proxy::LookupDOMWrapper(V8ClassIndex::DOMWINDOW, host); + v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, host); if (window.IsEmpty()) return false; - DOMWindow* targetWindow = V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window); + DOMWindow* targetWindow = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window); ASSERT(targetWindow); @@ -924,7 +922,7 @@ INDEXED_ACCESS_CHECK(DOMWindow) if ((type == v8::ACCESS_GET || type == v8::ACCESS_HAS) && target->tree()->child(index)) return true; - return V8Proxy::CanAccessFrame(target, false); + return V8Proxy::canAccessFrame(target, false); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8DataGridColumnListCustom.cpp b/WebCore/bindings/v8/custom/V8DataGridColumnListCustom.cpp new file mode 100644 index 0000000..1dde996 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8DataGridColumnListCustom.cpp @@ -0,0 +1,75 @@ +/* + * 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: + * + * * 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. + */ + +#include "config.h" +#include "DataGridColumnList.h" + +#include "Document.h" +#include "V8Binding.h" +#include "V8CustomBinding.h" +#include "V8Proxy.h" + +#if ENABLE(DATAGRID) + +namespace WebCore { + +INDEXED_PROPERTY_GETTER(DataGridColumnList) +{ + INC_STATS("DataGridColumnList.IndexedPropertyGetter"); + DataGridColumnList* imp = V8DOMWrapper::convertToNativeObject<DataGridColumnList>(V8ClassIndex::DATAGRIDCOLUMNLIST, info.Holder()); + DataGridColumn* result = imp->item(index); + if (!result) + return notHandledByInterceptor(); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::DATAGRIDCOLUMN, result); +} + +NAMED_PROPERTY_GETTER(DataGridColumnList) +{ + INC_STATS("DataGridColumnList.NamedPropertyGetter"); + // Search the prototype chain first. + v8::Handle<v8::Value> value = info.Holder()->GetRealNamedPropertyInPrototypeChain(name); + if (!value.IsEmpty()) + return value; + + // Then look for IDL defined properties on the object itself. + if (info.Holder()->HasRealNamedCallbackProperty(name)) + return notHandledByInterceptor(); + + // Finally, look up a column by name. + DataGridColumnList* imp = V8DOMWrapper::convertToNativeObject<DataGridColumnList>(V8ClassIndex::DATAGRIDCOLUMNLIST, info.Holder()); + DataGridColumn* result = imp->itemWithName(toWebCoreString(name)); + if (!result) + return notHandledByInterceptor(); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::DATAGRIDCOLUMN, result); +} + +} // namespace WebCore + +#endif // ENABLE(DATAGRID) diff --git a/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp b/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp index 6996d35..dbaa942 100644 --- a/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp @@ -32,14 +32,23 @@ #if ENABLE(DATABASE) +#ifdef MANUAL_MERGE_REQUIRED #include "v8_binding.h" #include "v8_proxy.h" +#else // MANUAL_MERGE_REQUIRED +#endif // MANUAL_MERGE_REQUIRED #include "Database.h" +#ifdef MANUAL_MERGE_REQUIRED #include "V8CustomBinding.h" +#else // MANUAL_MERGE_REQUIRED +#include "V8Binding.h" +#include "V8CustomBinding.h" +#endif // MANUAL_MERGE_REQUIRED #include "V8CustomSQLTransactionCallback.h" #include "V8CustomSQLTransactionErrorCallback.h" #include "V8CustomVoidCallback.h" +#include "V8Proxy.h" namespace WebCore { @@ -53,37 +62,33 @@ CALLBACK_FUNC_DECL(DatabaseTransaction) { INC_STATS("DOM.Database.transaction()"); - if (args.Length() == 0) { - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "Transaction callback is required."); - return v8::Undefined(); - } + if (!args.Length()) + return throwError("Transaction callback is required.", V8Proxy::SyntaxError); - if (!args[0]->IsObject()) { - V8Proxy::ThrowError(V8Proxy::TYPE_ERROR, "Transaction callback must be of valid type."); - return v8::Undefined(); - } + if (!args[0]->IsObject()) + return throwError("Transaction callback must be of valid type."); - Database* database = V8Proxy::ToNativeObject<Database>(V8ClassIndex::DATABASE, args.Holder()); + Database* database = V8DOMWrapper::convertToNativeObject<Database>(V8ClassIndex::DATABASE, args.Holder()); - Frame* frame = V8Proxy::retrieveFrame(); + Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); + if (!frame) + return v8::Undefined(); RefPtr<V8CustomSQLTransactionCallback> callback = V8CustomSQLTransactionCallback::create(args[0], frame); RefPtr<V8CustomSQLTransactionErrorCallback> errorCallback; if (args.Length() > 1) { - if (!args[1]->IsObject()) { - V8Proxy::ThrowError(V8Proxy::TYPE_ERROR, "Transaction error callback must be of valid type."); - return v8::Undefined(); - } + if (!args[1]->IsObject()) + return throwError("Transaction error callback must be of valid type."); + errorCallback = V8CustomSQLTransactionErrorCallback::create(args[1], frame); } RefPtr<V8CustomVoidCallback> successCallback; if (args.Length() > 2) { - if (!args[1]->IsObject()) { - V8Proxy::ThrowError(V8Proxy::TYPE_ERROR, "Transaction success callback must be of valid type."); - return v8::Undefined(); - } + if (!args[1]->IsObject()) + return throwError("Transaction success callback must be of valid type."); + successCallback = V8CustomVoidCallback::create(args[2], frame); } diff --git a/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp b/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp new file mode 100644 index 0000000..f13e45e --- /dev/null +++ b/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp @@ -0,0 +1,84 @@ +/* + * 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: + * + * * 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. + */ + +#include "config.h" + +#if ENABLE(WORKERS) + +#include "WorkerContextExecutionProxy.h" + +#include "DedicatedWorkerContext.h" +#include "V8Proxy.h" +#include "V8WorkerContextEventListener.h" + +namespace WebCore { + +ACCESSOR_GETTER(DedicatedWorkerContextOnmessage) +{ + INC_STATS(L"DOM.DedicatedWorkerContext.onmessage._get"); + DedicatedWorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<DedicatedWorkerContext>(V8ClassIndex::DEDICATEDWORKERCONTEXT, info.Holder()); + if (workerContext->onmessage()) { + V8WorkerContextEventListener* listener = static_cast<V8WorkerContextEventListener*>(workerContext->onmessage()); + v8::Local<v8::Object> v8Listener = listener->getListenerObject(); + return v8Listener; + } + return v8::Undefined(); +} + +ACCESSOR_SETTER(DedicatedWorkerContextOnmessage) +{ + INC_STATS(L"DOM.DedicatedWorkerContext.onmessage._set"); + DedicatedWorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<DedicatedWorkerContext>(V8ClassIndex::DEDICATEDWORKERCONTEXT, info.Holder()); + V8WorkerContextEventListener* oldListener = static_cast<V8WorkerContextEventListener*>(workerContext->onmessage()); + if (value->IsNull()) { + if (workerContext->onmessage()) { + v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); + removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kDedicatedWorkerContextRequestCacheIndex); + } + + // Clear the listener. + workerContext->setOnmessage(0); + } else { + RefPtr<V8EventListener> listener = workerContext->script()->proxy()->findOrCreateEventListener(v8::Local<v8::Object>::Cast(value), false, false); + if (listener) { + if (oldListener) { + v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); + removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kDedicatedWorkerContextRequestCacheIndex); + } + + workerContext->setOnmessage(listener); + createHiddenDependency(info.Holder(), value, V8Custom::kDedicatedWorkerContextRequestCacheIndex); + } + } +} + +} // namespace WebCore + +#endif // ENABLE(WORKERS) diff --git a/WebCore/bindings/v8/custom/V8DocumentCustom.cpp b/WebCore/bindings/v8/custom/V8DocumentCustom.cpp index 3eadce7..60fc22f 100644 --- a/WebCore/bindings/v8/custom/V8DocumentCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DocumentCustom.cpp @@ -32,13 +32,13 @@ #include "Document.h" #include "ExceptionCode.h" -#include "JSXPathNSResolver.h" #include "Node.h" #include "XPathNSResolver.h" #include "XPathResult.h" #include "V8Binding.h" #include "V8CustomBinding.h" +#include "V8CustomXPathNSResolver.h" #include "V8Node.h" #include "V8Proxy.h" @@ -54,52 +54,61 @@ namespace WebCore { CALLBACK_FUNC_DECL(DocumentEvaluate) { INC_STATS("DOM.Document.evaluate()"); +#ifdef MANUAL_MERGE_REQUIRED #if ENABLE(XPATH) Document* document = V8Proxy::DOMWrapperToNode<Document>(args.Holder()); +#else // MANUAL_MERGE_REQUIRED + + RefPtr<Document> document = V8DOMWrapper::convertDOMWrapperToNode<Document>(args.Holder()); +#endif // MANUAL_MERGE_REQUIRED ExceptionCode ec = 0; String expression = toWebCoreString(args[0]); - Node* contextNode = 0; + RefPtr<Node> contextNode; if (V8Node::HasInstance(args[1])) - contextNode = V8Proxy::DOMWrapperToNode<Node>(args[1]); + contextNode = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[1])); - XPathNSResolver* resolver = 0; + RefPtr<XPathNSResolver> resolver; if (V8XPathNSResolver::HasInstance(args[2])) - resolver = V8Proxy::ToNativeObject<XPathNSResolver>(V8ClassIndex::XPATHNSRESOLVER, args[2]); + resolver = V8DOMWrapper::convertToNativeObject<XPathNSResolver>(V8ClassIndex::XPATHNSRESOLVER, v8::Handle<v8::Object>::Cast(args[2])); else if (args[2]->IsObject()) - resolver = new JSXPathNSResolver(args[2]->ToObject()); + resolver = V8CustomXPathNSResolver::create(args[2]->ToObject()); else if (!args[2]->IsNull() && !args[2]->IsUndefined()) return throwError(TYPE_MISMATCH_ERR); int type = toInt32(args[3]); - XPathResult* inResult = 0; + RefPtr<XPathResult> inResult; if (V8XPathResult::HasInstance(args[4])) - inResult = V8Proxy::ToNativeObject<XPathResult>(V8ClassIndex::XPATHRESULT, args[4]); + inResult = V8DOMWrapper::convertToNativeObject<XPathResult>(V8ClassIndex::XPATHRESULT, v8::Handle<v8::Object>::Cast(args[4])); v8::TryCatch exceptionCatcher; - RefPtr<XPathResult> result = document->evaluate(expression, contextNode, resolver, type, inResult, ec); + RefPtr<XPathResult> result = document->evaluate(expression, contextNode.get(), resolver.get(), type, inResult.get(), ec); if (exceptionCatcher.HasCaught()) return throwError(exceptionCatcher.Exception()); if (ec) return throwError(ec); +#ifdef MANUAL_MERGE_REQUIRED return V8Proxy::ToV8Object(V8ClassIndex::XPATHRESULT, result.get()); #else return throwError(NOT_SUPPORTED_ERR); #endif +#else // MANUAL_MERGE_REQUIRED + return V8DOMWrapper::convertToV8Object(V8ClassIndex::XPATHRESULT, result.release()); +#endif // MANUAL_MERGE_REQUIRED } CALLBACK_FUNC_DECL(DocumentGetCSSCanvasContext) { INC_STATS("DOM.Document.getCSSCanvasContext"); - v8::Handle<v8::Value> holder = args.Holder(); - Document* imp = V8Proxy::DOMWrapperToNode<Document>(holder); + v8::Handle<v8::Object> holder = args.Holder(); + Document* imp = V8DOMWrapper::convertDOMWrapperToNode<Document>(holder); String contextId = toWebCoreString(args[0]); String name = toWebCoreString(args[1]); int width = toInt32(args[2]); int height = toInt32(args[3]); CanvasRenderingContext2D* result = imp->getCSSCanvasContext(contextId, name, width, height); - return V8Proxy::ToV8Object(V8ClassIndex::CANVASRENDERINGCONTEXT2D, result); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::CANVASRENDERINGCONTEXT2D, result); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8DocumentLocationCustom.cpp b/WebCore/bindings/v8/custom/V8DocumentLocationCustom.cpp index dfcacef..440bbdc 100644 --- a/WebCore/bindings/v8/custom/V8DocumentLocationCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DocumentLocationCustom.cpp @@ -34,17 +34,17 @@ namespace WebCore { ACCESSOR_GETTER(DocumentLocation) { - Document* document = V8Proxy::DOMWrapperToNative<Document>(info.Holder()); + Document* document = V8DOMWrapper::convertDOMWrapperToNative<Document>(info.Holder()); if (!document->frame()) return v8::Null(); DOMWindow* window = document->frame()->domWindow(); - return V8Proxy::ToV8Object(V8ClassIndex::LOCATION, window->location()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::LOCATION, window->location()); } ACCESSOR_SETTER(DocumentLocation) { - Document* document = V8Proxy::DOMWrapperToNative<Document>(info.Holder()); + Document* document = V8DOMWrapper::convertDOMWrapperToNative<Document>(info.Holder()); if (!document->frame()) return; diff --git a/WebCore/bindings/v8/custom/V8ElementCustom.cpp b/WebCore/bindings/v8/custom/V8ElementCustom.cpp index 64a9d3d..e17e0a9 100644 --- a/WebCore/bindings/v8/custom/V8ElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8ElementCustom.cpp @@ -34,7 +34,6 @@ #include "Attr.h" #include "CSSHelper.h" #include "Document.h" -#include "EventListener.h" #include "ExceptionCode.h" #include "HTMLFrameElementBase.h" #include "HTMLNames.h" @@ -43,7 +42,6 @@ #include "V8Attr.h" #include "V8Binding.h" #include "V8CustomBinding.h" -#include "V8CustomEventListener.h" #include "V8Proxy.h" #include <wtf/RefPtr.h> @@ -53,7 +51,7 @@ namespace WebCore { CALLBACK_FUNC_DECL(ElementSetAttribute) { INC_STATS("DOM.Element.setAttribute()"); - Element* element = V8Proxy::DOMWrapperToNode<Element>(args.Holder()); + Element* element = V8DOMWrapper::convertDOMWrapperToNode<Element>(args.Holder()); String name = toWebCoreString(args[0]); String value = toWebCoreString(args[1]); @@ -74,8 +72,8 @@ CALLBACK_FUNC_DECL(ElementSetAttributeNode) if (!V8Attr::HasInstance(args[0])) return throwError(TYPE_MISMATCH_ERR); - Attr* newAttr = V8Proxy::DOMWrapperToNode<Attr>(args[0]); - Element* element = V8Proxy::DOMWrapperToNode<Element>(args.Holder()); + Attr* newAttr = V8DOMWrapper::convertDOMWrapperToNode<Attr>(v8::Handle<v8::Object>::Cast(args[0])); + Element* element = V8DOMWrapper::convertDOMWrapperToNode<Element>(args.Holder()); if (!allowSettingSrcToJavascriptURL(element, newAttr->name(), newAttr->value())) return v8::Undefined(); @@ -85,13 +83,13 @@ CALLBACK_FUNC_DECL(ElementSetAttributeNode) if (ec) throwError(ec); - return V8Proxy::NodeToV8Object(result.get()); + return V8DOMWrapper::convertNodeToV8Object(result.release()); } CALLBACK_FUNC_DECL(ElementSetAttributeNS) { INC_STATS("DOM.Element.setAttributeNS()"); - Element* element = V8Proxy::DOMWrapperToNode<Element>(args.Holder()); + Element* element = V8DOMWrapper::convertDOMWrapperToNode<Element>(args.Holder()); String namespaceURI = toWebCoreStringWithNullCheck(args[0]); String qualifiedName = toWebCoreString(args[1]); String value = toWebCoreString(args[2]); @@ -113,8 +111,8 @@ CALLBACK_FUNC_DECL(ElementSetAttributeNodeNS) if (!V8Attr::HasInstance(args[0])) return throwError(TYPE_MISMATCH_ERR); - Attr* newAttr = V8Proxy::DOMWrapperToNode<Attr>(args[0]); - Element* element = V8Proxy::DOMWrapperToNode<Element>(args.Holder()); + Attr* newAttr = V8DOMWrapper::convertDOMWrapperToNode<Attr>(v8::Handle<v8::Object>::Cast(args[0])); + Element* element = V8DOMWrapper::convertDOMWrapperToNode<Element>(args.Holder()); if (!allowSettingSrcToJavascriptURL(element, newAttr->name(), newAttr->value())) return v8::Undefined(); @@ -124,45 +122,7 @@ CALLBACK_FUNC_DECL(ElementSetAttributeNodeNS) if (ec) throwError(ec); - return V8Proxy::NodeToV8Object(result.get()); -} - -static inline String toEventType(v8::Local<v8::String> value) -{ - String key = toWebCoreString(value); - ASSERT(key.startsWith("on")); - return key.substring(2); -} - -ACCESSOR_SETTER(ElementEventHandler) -{ - Node* node = V8Proxy::DOMWrapperToNode<Node>(info.Holder()); - - String eventType = toEventType(name); - - // Set handler if the value is a function. Otherwise, clear the - // event handler. - if (value->IsFunction()) { - V8Proxy* proxy = V8Proxy::retrieve(node->document()->frame()); - // the document might be created using createDocument, - // which does not have a frame, use the active frame - if (!proxy) - proxy = V8Proxy::retrieve(V8Proxy::retrieveFrameForEnteredContext()); - if (!proxy) - return; - - if (RefPtr<EventListener> listener = proxy->FindOrCreateV8EventListener(value, true)) - node->setAttributeEventListener(eventType, listener); - } else - node->clearAttributeEventListener(eventType); -} - -ACCESSOR_GETTER(ElementEventHandler) -{ - Node* node = V8Proxy::DOMWrapperToNode<Node>(info.Holder()); - - EventListener* listener = node->getAttributeEventListener(toEventType(name)); - return V8Proxy::EventListenerToV8Object(listener); + return V8DOMWrapper::convertNodeToV8Object(result.release()); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8EventCustom.cpp b/WebCore/bindings/v8/custom/V8EventCustom.cpp index 1dae845..8bac40f 100644 --- a/WebCore/bindings/v8/custom/V8EventCustom.cpp +++ b/WebCore/bindings/v8/custom/V8EventCustom.cpp @@ -43,39 +43,39 @@ namespace WebCore { ACCESSOR_SETTER(EventReturnValue) { - Event* event = V8Proxy::DOMWrapperToNative<Event>(info.Holder()); + Event* event = V8DOMWrapper::convertDOMWrapperToNative<Event>(info.Holder()); event->setDefaultPrevented(!value->BooleanValue()); } ACCESSOR_GETTER(EventDataTransfer) { - Event* event = V8Proxy::DOMWrapperToNative<Event>(info.Holder()); + Event* event = V8DOMWrapper::convertDOMWrapperToNative<Event>(info.Holder()); if (event->isDragEvent()) - return V8Proxy::ToV8Object(V8ClassIndex::CLIPBOARD, static_cast<MouseEvent*>(event)->clipboard()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::CLIPBOARD, static_cast<MouseEvent*>(event)->clipboard()); return v8::Undefined(); } ACCESSOR_GETTER(EventClipboardData) { - Event* event = V8Proxy::DOMWrapperToNative<Event>(info.Holder()); + Event* event = V8DOMWrapper::convertDOMWrapperToNative<Event>(info.Holder()); if (event->isClipboardEvent()) - return V8Proxy::ToV8Object(V8ClassIndex::CLIPBOARD, static_cast<ClipboardEvent*>(event)->clipboard()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::CLIPBOARD, static_cast<ClipboardEvent*>(event)->clipboard()); return v8::Undefined(); } ACCESSOR_GETTER(EventSrcElement) { - Event* event = V8Proxy::DOMWrapperToNative<Event>(info.Holder()); - return V8Proxy::EventTargetToV8Object(event->target()); + Event* event = V8DOMWrapper::convertDOMWrapperToNative<Event>(info.Holder()); + return V8DOMWrapper::convertEventTargetToV8Object(event->target()); } ACCESSOR_GETTER(EventReturnValue) { - Event* event = V8Proxy::DOMWrapperToNative<Event>(info.Holder()); + Event* event = V8DOMWrapper::convertDOMWrapperToNative<Event>(info.Holder()); return event->defaultPrevented() ? v8::False() : v8::True(); } diff --git a/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp new file mode 100644 index 0000000..6f9b761 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp @@ -0,0 +1,74 @@ +/* + * 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: + * + * * 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. + */ + +#include "config.h" +#include "HTMLAudioElement.h" + +#include "Document.h" +#include "Frame.h" +#include "HTMLNames.h" + +#include "V8Binding.h" +#include "V8Proxy.h" + +#include <wtf/RefPtr.h> + +namespace WebCore { + +CALLBACK_FUNC_DECL(HTMLAudioElementConstructor) +{ + INC_STATS("DOM.HTMLAudioElement.Contructor"); + + if (!args.IsConstructCall()) + return throwError("DOM object constructor cannot be called as a function."); + + Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); + if (!frame) + return throwError("Audio constructor associated frame is unavailable", V8Proxy::ReferenceError); + + Document* document = frame->document(); + if (!document) + return throwError("Audio constructor associated document is unavailable", V8Proxy::ReferenceError); + + // Make sure the document is added to the DOM Node map. Otherwise, the HTMLAudioElement instance + // may end up being the only node in the map and get garbage-ccollected prematurely. + V8DOMWrapper::convertNodeToV8Object(document); + + RefPtr<HTMLAudioElement> audio = new HTMLAudioElement(HTMLNames::audioTag, document); + if (args.Length() > 0) + audio->setSrc(toWebCoreString(args[0])); + + V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::NODE), audio.get()); + audio->ref(); + V8DOMWrapper::setJSWrapperForDOMNode(audio.get(), v8::Persistent<v8::Object>::New(args.Holder())); + return args.Holder(); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp index cf66e39..6ba9367 100644 --- a/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp @@ -40,12 +40,12 @@ namespace WebCore { CALLBACK_FUNC_DECL(HTMLCanvasElementGetContext) { - INC_STATS("DOM.HTMLCanvasElement.getContext"); - v8::Handle<v8::Value> holder = args.Holder(); - HTMLCanvasElement* imp = V8Proxy::DOMWrapperToNode<HTMLCanvasElement>(holder); - String contextId = ToWebCoreString(args[0]); + INC_STATS("DOM.HTMLCanvasElement.context"); + v8::Handle<v8::Object> holder = args.Holder(); + HTMLCanvasElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLCanvasElement>(holder); + String contextId = toWebCoreString(args[0]); CanvasRenderingContext2D* result = imp->getContext(contextId); - return V8Proxy::ToV8Object(V8ClassIndex::CANVASRENDERINGCONTEXT2D, result); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::CANVASRENDERINGCONTEXT2D, result); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8HTMLCollectionCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLCollectionCustom.cpp index 1436a48..7c9b40f 100644 --- a/WebCore/bindings/v8/custom/V8HTMLCollectionCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLCollectionCustom.cpp @@ -47,10 +47,10 @@ static v8::Handle<v8::Value> getNamedItems(HTMLCollection* collection, AtomicStr return v8::Handle<v8::Value>(); if (namedItems.size() == 1) - return V8Proxy::NodeToV8Object(namedItems.at(0).get()); + return V8DOMWrapper::convertNodeToV8Object(namedItems.at(0).release()); NodeList* list = new V8NamedNodesCollection(namedItems); - return V8Proxy::ToV8Object(V8ClassIndex::NODELIST, list); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::NODELIST, list); } static v8::Handle<v8::Value> getItem(HTMLCollection* collection, v8::Handle<v8::Value> argument) @@ -66,7 +66,7 @@ static v8::Handle<v8::Value> getItem(HTMLCollection* collection, v8::Handle<v8:: } RefPtr<Node> result = collection->item(index->Uint32Value()); - return V8Proxy::NodeToV8Object(result.get()); + return V8DOMWrapper::convertNodeToV8Object(result.release()); } NAMED_PROPERTY_GETTER(HTMLCollection) @@ -84,21 +84,21 @@ NAMED_PROPERTY_GETTER(HTMLCollection) return v8::Handle<v8::Value>(); // Finally, search the DOM structure. - HTMLCollection* imp = V8Proxy::ToNativeObject<HTMLCollection>(V8ClassIndex::HTMLCOLLECTION, info.Holder()); + HTMLCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLCollection>(V8ClassIndex::HTMLCOLLECTION, info.Holder()); return getNamedItems(imp, v8StringToAtomicWebCoreString(name)); } CALLBACK_FUNC_DECL(HTMLCollectionItem) { INC_STATS("DOM.HTMLCollection.item()"); - HTMLCollection* imp = V8Proxy::ToNativeObject<HTMLCollection>(V8ClassIndex::HTMLCOLLECTION, args.Holder()); + HTMLCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLCollection>(V8ClassIndex::HTMLCOLLECTION, args.Holder()); return getItem(imp, args[0]); } CALLBACK_FUNC_DECL(HTMLCollectionNamedItem) { INC_STATS("DOM.HTMLCollection.namedItem()"); - HTMLCollection* imp = V8Proxy::ToNativeObject<HTMLCollection>(V8ClassIndex::HTMLCOLLECTION, args.Holder()); + HTMLCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLCollection>(V8ClassIndex::HTMLCOLLECTION, args.Holder()); v8::Handle<v8::Value> result = getNamedItems(imp, toWebCoreString(args[0])); if (result.IsEmpty()) @@ -113,7 +113,7 @@ CALLBACK_FUNC_DECL(HTMLCollectionCallAsFunction) if (args.Length() < 1) return v8::Undefined(); - HTMLCollection* imp = V8Proxy::ToNativeObject<HTMLCollection>(V8ClassIndex::HTMLCOLLECTION, args.Holder()); + HTMLCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLCollection>(V8ClassIndex::HTMLCOLLECTION, args.Holder()); if (args.Length() == 1) return getItem(imp, args[0]); @@ -128,7 +128,7 @@ CALLBACK_FUNC_DECL(HTMLCollectionCallAsFunction) Node* node = imp->namedItem(name); while (node) { if (!current) - return V8Proxy::NodeToV8Object(node); + return V8DOMWrapper::convertNodeToV8Object(node); node = imp->nextNamedItem(name); current--; diff --git a/WebCore/bindings/v8/custom/V8HTMLDataGridElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLDataGridElementCustom.cpp new file mode 100644 index 0000000..0ef4150 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8HTMLDataGridElementCustom.cpp @@ -0,0 +1,70 @@ +/* + * 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: + * + * * 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. + */ + +#include "config.h" +#include "HTMLDataGridElement.h" + +#include "Document.h" +#include "V8Binding.h" +#include "V8CustomBinding.h" +#include "V8DataGridDataSource.h" +#include "V8Proxy.h" + +#if ENABLE(DATAGRID) + +namespace WebCore { + +ACCESSOR_GETTER(HTMLDataGridElementDataSource) +{ + INC_STATS("DOM.HTMLDataGridElement.dataSource._get"); + v8::Handle<v8::Object> holder = info.Holder(); + HTMLDataGridElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLDataGridElement>(holder); + DataGridDataSource* dataSource = imp->dataSource(); + if (dataSource && dataSource->isJSDataGridDataSource()) + return asV8DataGridDataSource(dataSource)->jsDataSource(); + return v8::Null(); +} + +ACCESSOR_SETTER(HTMLDataGridElementDataSource) +{ + INC_STATS("DOM.HTMLDataGridElement.dataSource._set"); + v8::Handle<v8::Object> holder = info.Holder(); + HTMLDataGridElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLDataGridElement>(holder); + RefPtr<DataGridDataSource> dataSource; + if (!value.IsEmpty()) { + Frame *frame = imp->document()->frame(); + dataSource = V8DataGridDataSource::create(value, frame); + } + imp->setDataSource(dataSource.get()); +} + +} // namespace WebCore + +#endif // ENABLE(DATAGRID) diff --git a/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp index 34bf89c..a0c3d74 100644 --- a/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp @@ -78,7 +78,7 @@ NAMED_PROPERTY_GETTER(HTMLDocument) return value; } - HTMLDocument* htmlDocument = V8Proxy::DOMWrapperToNode<HTMLDocument>(info.Holder()); + HTMLDocument* htmlDocument = V8DOMWrapper::convertDOMWrapperToNode<HTMLDocument>(info.Holder()); // Fast case for named elements that are not there. if (!htmlDocument->hasNamedItem(key.impl()) && !htmlDocument->hasExtraNamedItem(key.impl())) @@ -92,12 +92,12 @@ NAMED_PROPERTY_GETTER(HTMLDocument) Node* node = items->firstItem(); Frame* frame = 0; if (node->hasTagName(HTMLNames::iframeTag) && (frame = static_cast<HTMLIFrameElement*>(node)->contentFrame())) - return V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, frame->domWindow()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMWINDOW, frame->domWindow()); - return V8Proxy::NodeToV8Object(node); + return V8DOMWrapper::convertNodeToV8Object(node); } - return V8Proxy::ToV8Object(V8ClassIndex::HTMLCOLLECTION, items.get()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::HTMLCOLLECTION, items.release()); } // HTMLDocument ---------------------------------------------------------------- @@ -117,7 +117,7 @@ static String writeHelperGetString(const v8::Arguments& args) CALLBACK_FUNC_DECL(HTMLDocumentWrite) { INC_STATS("DOM.HTMLDocument.write()"); - HTMLDocument* htmlDocument = V8Proxy::DOMWrapperToNode<HTMLDocument>(args.Holder()); + HTMLDocument* htmlDocument = V8DOMWrapper::convertDOMWrapperToNode<HTMLDocument>(args.Holder()); Frame* frame = V8Proxy::retrieveFrameForCallingContext(); ASSERT(frame); htmlDocument->write(writeHelperGetString(args), frame->document()); @@ -127,7 +127,7 @@ CALLBACK_FUNC_DECL(HTMLDocumentWrite) CALLBACK_FUNC_DECL(HTMLDocumentWriteln) { INC_STATS("DOM.HTMLDocument.writeln()"); - HTMLDocument* htmlDocument = V8Proxy::DOMWrapperToNode<HTMLDocument>(args.Holder()); + HTMLDocument* htmlDocument = V8DOMWrapper::convertDOMWrapperToNode<HTMLDocument>(args.Holder()); Frame* frame = V8Proxy::retrieveFrameForCallingContext(); ASSERT(frame); htmlDocument->writeln(writeHelperGetString(args), frame->document()); @@ -137,12 +137,12 @@ CALLBACK_FUNC_DECL(HTMLDocumentWriteln) CALLBACK_FUNC_DECL(HTMLDocumentOpen) { INC_STATS("DOM.HTMLDocument.open()"); - HTMLDocument* htmlDocument = V8Proxy::DOMWrapperToNode<HTMLDocument>(args.Holder()); + HTMLDocument* htmlDocument = V8DOMWrapper::convertDOMWrapperToNode<HTMLDocument>(args.Holder()); if (args.Length() > 2) { if (Frame* frame = htmlDocument->frame()) { // Fetch the global object for the frame. - v8::Local<v8::Context> context = V8Proxy::GetContext(frame); + v8::Local<v8::Context> context = V8Proxy::context(frame); // Bail out if we cannot get the context. if (context.IsEmpty()) return v8::Undefined(); @@ -162,7 +162,7 @@ CALLBACK_FUNC_DECL(HTMLDocumentOpen) V8Proxy* proxy = V8Proxy::retrieve(frame); ASSERT(proxy); - v8::Local<v8::Value> result = proxy->CallFunction(v8::Local<v8::Function>::Cast(function), global, args.Length(), params); + v8::Local<v8::Value> result = proxy->callFunction(v8::Local<v8::Function>::Cast(function), global, args.Length(), params); delete[] params; return result; } @@ -179,9 +179,8 @@ ACCESSOR_GETTER(HTMLDocumentAll) INC_STATS("DOM.HTMLDocument.all._get"); v8::HandleScope scope; v8::Handle<v8::Object> holder = info.Holder(); - HTMLDocument* htmlDocument = V8Proxy::DOMWrapperToNode<HTMLDocument>(holder); - RefPtr<HTMLCollection> collection = WTF::getPtr(htmlDocument->all()); - return V8Proxy::ToV8Object(V8ClassIndex::HTMLCOLLECTION, WTF::getPtr(collection)); + HTMLDocument* htmlDocument = V8DOMWrapper::convertDOMWrapperToNode<HTMLDocument>(holder); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::HTMLCOLLECTION, htmlDocument->all()); } ACCESSOR_SETTER(HTMLDocumentAll) diff --git a/WebCore/bindings/v8/custom/V8HTMLFormElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLFormElementCustom.cpp index 27ab7e3..1ec09f7 100644 --- a/WebCore/bindings/v8/custom/V8HTMLFormElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLFormElementCustom.cpp @@ -42,19 +42,19 @@ namespace WebCore { INDEXED_PROPERTY_GETTER(HTMLFormElement) { INC_STATS("DOM.HTMLFormElement.IndexedPropertyGetter"); - HTMLFormElement* form = V8Proxy::DOMWrapperToNode<HTMLFormElement>(info.Holder()); - + HTMLFormElement* form = V8DOMWrapper::convertDOMWrapperToNode<HTMLFormElement>(info.Holder()); + RefPtr<Node> formElement = form->elements()->item(index); if (!formElement) return notHandledByInterceptor(); - return V8Proxy::NodeToV8Object(formElement.get()); + return V8DOMWrapper::convertNodeToV8Object(formElement.release()); } NAMED_PROPERTY_GETTER(HTMLFormElement) { INC_STATS("DOM.HTMLFormElement.NamedPropertyGetter"); - HTMLFormElement* imp = V8Proxy::DOMWrapperToNode<HTMLFormElement>(info.Holder()); + HTMLFormElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLFormElement>(info.Holder()); AtomicString v = v8StringToAtomicWebCoreString(name); // Call getNamedElements twice, first time check if it has a value @@ -74,15 +74,15 @@ NAMED_PROPERTY_GETTER(HTMLFormElement) ASSERT(!elements.isEmpty()); if (elements.size() == 1) - return V8Proxy::NodeToV8Object(elements.at(0).get()); + return V8DOMWrapper::convertNodeToV8Object(elements.at(0).release()); NodeList* collection = new V8NamedNodesCollection(elements); - return V8Proxy::ToV8Object(V8ClassIndex::NODELIST, collection); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::NODELIST, collection); } - + CALLBACK_FUNC_DECL(HTMLFormElementSubmit) { INC_STATS("DOM.HTMLFormElement.submit()"); - HTMLFormElement* form = V8Proxy::DOMWrapperToNative<HTMLFormElement>(args.Holder()); + HTMLFormElement* form = V8DOMWrapper::convertDOMWrapperToNative<HTMLFormElement>(args.Holder()); form->submit(0, false, false); return v8::Undefined(); } diff --git a/WebCore/bindings/v8/custom/V8HTMLFrameElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLFrameElementCustom.cpp index bfc4c28..4f865dd 100644 --- a/WebCore/bindings/v8/custom/V8HTMLFrameElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLFrameElementCustom.cpp @@ -39,7 +39,7 @@ namespace WebCore { ACCESSOR_SETTER(HTMLFrameElementSrc) { - HTMLFrameElement* frame = V8Proxy::DOMWrapperToNode<HTMLFrameElement>(info.Holder()); + HTMLFrameElement* frame = V8DOMWrapper::convertDOMWrapperToNode<HTMLFrameElement>(info.Holder()); String srcValue = toWebCoreStringWithNullCheck(value); if (!allowSettingFrameSrcToJavascriptUrl(frame, srcValue)) @@ -50,7 +50,7 @@ ACCESSOR_SETTER(HTMLFrameElementSrc) ACCESSOR_SETTER(HTMLFrameElementLocation) { - HTMLFrameElement* frame = V8Proxy::DOMWrapperToNode<HTMLFrameElement>(info.Holder()); + HTMLFrameElement* frame = V8DOMWrapper::convertDOMWrapperToNode<HTMLFrameElement>(info.Holder()); String locationValue = toWebCoreStringWithNullCheck(value); if (!allowSettingFrameSrcToJavascriptUrl(frame, locationValue)) diff --git a/WebCore/bindings/v8/custom/V8HTMLFrameSetElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLFrameSetElementCustom.cpp index 220af02..e8e2e72 100644 --- a/WebCore/bindings/v8/custom/V8HTMLFrameSetElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLFrameSetElementCustom.cpp @@ -47,14 +47,14 @@ namespace WebCore { NAMED_PROPERTY_GETTER(HTMLFrameSetElement) { INC_STATS("DOM.HTMLFrameSetElement.NamedPropertyGetter"); - HTMLFrameSetElement* imp = V8Proxy::DOMWrapperToNode<HTMLFrameSetElement>(info.Holder()); + HTMLFrameSetElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLFrameSetElement>(info.Holder()); Node* frameNode = imp->children()->namedItem(v8StringToAtomicWebCoreString(name)); if (frameNode && frameNode->hasTagName(HTMLNames::frameTag)) { Document* doc = static_cast<HTMLFrameElement*>(frameNode)->contentDocument(); if (!doc) return v8::Undefined(); if (Frame* frame = doc->frame()) - return V8Proxy::ToV8Object(V8ClassIndex::DOMWINDOW, frame->domWindow()); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMWINDOW, frame->domWindow()); } return notHandledByInterceptor(); } diff --git a/WebCore/bindings/v8/custom/V8HTMLIFrameElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLIFrameElementCustom.cpp index 3739a4e..ce2c29a 100644 --- a/WebCore/bindings/v8/custom/V8HTMLIFrameElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLIFrameElementCustom.cpp @@ -39,8 +39,8 @@ namespace WebCore { ACCESSOR_SETTER(HTMLIFrameElementSrc) { - HTMLIFrameElement* iframe = V8Proxy::DOMWrapperToNode<HTMLIFrameElement>(info.Holder()); - String v = valueToStringWithNullCheck(value); + HTMLIFrameElement* iframe = V8DOMWrapper::convertDOMWrapperToNode<HTMLIFrameElement>(info.Holder()); + String v = toWebCoreStringWithNullCheck(value); if (!allowSettingFrameSrcToJavascriptUrl(iframe, v)) return; diff --git a/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp index afcc29d..91ebd5f 100644 --- a/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp @@ -49,24 +49,28 @@ CALLBACK_FUNC_DECL(HTMLImageElementConstructor) if (!args.IsConstructCall()) return throwError("DOM object constructor cannot be called as a function."); - Document* document = V8Proxy::retrieveFrame()->document(); + Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); + if (!frame) + return throwError("Image constructor associated frame is unavailable", V8Proxy::ReferenceError); + + Document* document = frame->document(); if (!document) - return throwError("Image constructor associated document is unavailable", V8Proxy::REFERENCE_ERROR); + return throwError("Image constructor associated document is unavailable", V8Proxy::ReferenceError); // Make sure the document is added to the DOM Node map. Otherwise, the HTMLImageElement instance // may end up being the only node in the map and get garbage-ccollected prematurely. - V8Proxy::NodeToV8Object(document); + V8DOMWrapper::convertNodeToV8Object(document); - RefPtr<HTMLImageElement> image = new HTMLImageElement(HTMLNames::imgTag, V8Proxy::retrieveFrame()->document()); + RefPtr<HTMLImageElement> image = new HTMLImageElement(HTMLNames::imgTag, document); if (args.Length() > 0) { image->setWidth(toInt32(args[0])); if (args.Length() > 1) image->setHeight(toInt32(args[1])); } - V8Proxy::SetDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::NODE), image.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::NODE), image.get()); image->ref(); - V8Proxy::SetJSWrapperForDOMNode(image.get(), v8::Persistent<v8::Object>::New(args.Holder())); + V8DOMWrapper::setJSWrapperForDOMNode(image.get(), v8::Persistent<v8::Object>::New(args.Holder())); return args.Holder(); } diff --git a/WebCore/bindings/v8/custom/V8HTMLInputElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLInputElementCustom.cpp index 628634d..63fbcec 100644 --- a/WebCore/bindings/v8/custom/V8HTMLInputElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLInputElementCustom.cpp @@ -41,7 +41,7 @@ ACCESSOR_GETTER(HTMLInputElementSelectionStart) { INC_STATS("DOM.HTMLInputElement.selectionStart._get"); v8::Handle<v8::Object> holder = info.Holder(); - HTMLInputElement* imp = V8Proxy::DOMWrapperToNode<HTMLInputElement>(holder); + HTMLInputElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLInputElement>(holder); if (!imp->canHaveSelection()) return throwError("Accessing selectionStart on an input element that cannot have a selection."); @@ -54,7 +54,7 @@ ACCESSOR_SETTER(HTMLInputElementSelectionStart) { INC_STATS("DOM.HTMLInputElement.selectionStart._set"); v8::Handle<v8::Object> holder = info.Holder(); - HTMLInputElement* imp = V8Proxy::DOMWrapperToNode<HTMLInputElement>(holder); + HTMLInputElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLInputElement>(holder); if (!imp->canHaveSelection()) { throwError("Accessing selectionStart on an input element that cannot have a selection."); @@ -67,7 +67,7 @@ ACCESSOR_GETTER(HTMLInputElementSelectionEnd) { INC_STATS("DOM.HTMLInputElement.selectionEnd._get"); v8::Handle<v8::Object> holder = info.Holder(); - HTMLInputElement* imp = V8Proxy::DOMWrapperToNode<HTMLInputElement>(holder); + HTMLInputElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLInputElement>(holder); if (!imp->canHaveSelection()) return throwError("Accessing selectionEnd on an input element that cannot have a selection."); @@ -80,7 +80,7 @@ ACCESSOR_SETTER(HTMLInputElementSelectionEnd) { INC_STATS("DOM.HTMLInputElement.selectionEnd._set"); v8::Handle<v8::Object> holder = info.Holder(); - HTMLInputElement* imp = V8Proxy::DOMWrapperToNode<HTMLInputElement>(holder); + HTMLInputElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLInputElement>(holder); if (!imp->canHaveSelection()) { throwError("Accessing selectionEnd on an input element that cannot have a selection."); @@ -94,7 +94,7 @@ CALLBACK_FUNC_DECL(HTMLInputElementSetSelectionRange) { INC_STATS("DOM.HTMLInputElement.setSelectionRange"); v8::Handle<v8::Object> holder = args.Holder(); - HTMLInputElement* imp = V8Proxy::DOMWrapperToNode<HTMLInputElement>(holder); + HTMLInputElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLInputElement>(holder); if (!imp->canHaveSelection()) return throwError("Calling setSelectionRange on an input element that cannot have a selection."); diff --git a/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp index 93a9b68..c22d127 100644 --- a/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp @@ -50,11 +50,15 @@ CALLBACK_FUNC_DECL(HTMLOptionElementConstructor) if (!args.IsConstructCall()) return throwError("DOM object constructor cannot be called as a function."); - Document* document = V8Proxy::retrieveFrame()->document(); + Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); + if (!frame) + return throwError("Option constructor associated frame is unavailable", V8Proxy::ReferenceError); + + Document* document = frame->document(); if (!document) - return throwError("Option constructor associated document is unavailable", V8Proxy::REFERENCE_ERROR); + return throwError("Option constructor associated document is unavailable", V8Proxy::ReferenceError); - RefPtr<HTMLOptionElement> option = new HTMLOptionElement(HTMLNames::optionTag, V8Proxy::retrieveFrame()->document()); + RefPtr<HTMLOptionElement> option = new HTMLOptionElement(HTMLNames::optionTag, document); ExceptionCode ec = 0; RefPtr<Text> text = document->createTextNode(""); @@ -81,9 +85,9 @@ CALLBACK_FUNC_DECL(HTMLOptionElementConstructor) } } - V8Proxy::SetDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::NODE), option.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::NODE), option.get()); option->ref(); - V8Proxy::SetJSWrapperForDOMNode(option.get(), v8::Persistent<v8::Object>::New(args.Holder())); + V8DOMWrapper::setJSWrapperForDOMNode(option.get(), v8::Persistent<v8::Object>::New(args.Holder())); return args.Holder(); } diff --git a/WebCore/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp index 9f0d25e..02c3499 100644 --- a/WebCore/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp @@ -46,7 +46,7 @@ namespace WebCore { CALLBACK_FUNC_DECL(HTMLOptionsCollectionRemove) { INC_STATS("DOM.HTMLOptionsCollection.remove()"); - HTMLOptionsCollection* imp = V8Proxy::ToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, args.Holder()); + HTMLOptionsCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, args.Holder()); HTMLSelectElement* base = static_cast<HTMLSelectElement*>(imp->base()); return removeElement(base, args); } @@ -55,11 +55,11 @@ CALLBACK_FUNC_DECL(HTMLOptionsCollectionAdd) { INC_STATS("DOM.HTMLOptionsCollection.add()"); if (!V8HTMLOptionElement::HasInstance(args[0])) { - V8Proxy::SetDOMException(TYPE_MISMATCH_ERR); + V8Proxy::setDOMException(TYPE_MISMATCH_ERR); return v8::Undefined(); } - HTMLOptionsCollection* imp = V8Proxy::ToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, args.Holder()); - HTMLOptionElement* option = V8Proxy::DOMWrapperToNode<HTMLOptionElement>(args[0]); + HTMLOptionsCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, args.Holder()); + HTMLOptionElement* option = V8DOMWrapper::convertDOMWrapperToNode<HTMLOptionElement>(v8::Handle<v8::Object>(v8::Handle<v8::Object>::Cast(args[0]))); ExceptionCode ec = 0; if (args.Length() < 2) @@ -67,7 +67,7 @@ CALLBACK_FUNC_DECL(HTMLOptionsCollectionAdd) else { bool ok; v8::TryCatch try_catch; - int index = ToInt32(args[1], ok); + int index = toInt32(args[1], ok); if (try_catch.HasCaught()) return v8::Undefined(); @@ -79,7 +79,7 @@ CALLBACK_FUNC_DECL(HTMLOptionsCollectionAdd) } if (ec != 0) - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Undefined(); } @@ -87,7 +87,7 @@ CALLBACK_FUNC_DECL(HTMLOptionsCollectionAdd) ACCESSOR_GETTER(HTMLOptionsCollectionLength) { INC_STATS("DOM.HTMLOptionsCollection.length._get"); - HTMLOptionsCollection* imp = V8Proxy::ToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, info.Holder()); + HTMLOptionsCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, info.Holder()); int v = imp->length(); return v8::Integer::New(v); } @@ -95,7 +95,7 @@ ACCESSOR_GETTER(HTMLOptionsCollectionLength) ACCESSOR_SETTER(HTMLOptionsCollectionLength) { INC_STATS("DOM.HTMLOptionsCollection.length._set"); - HTMLOptionsCollection* imp = V8Proxy::ToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, info.Holder()); + HTMLOptionsCollection* imp = V8DOMWrapper::convertToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, info.Holder()); double v = value->NumberValue(); unsigned newLength = 0; ExceptionCode ec = 0; @@ -110,25 +110,25 @@ ACCESSOR_SETTER(HTMLOptionsCollectionLength) if (!ec) imp->setLength(value->Uint32Value(), ec); - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); } INDEXED_PROPERTY_GETTER(HTMLOptionsCollection) { INC_STATS("DOM.HTMLOptionsCollection.IndexedPropertyGetter"); - HTMLOptionsCollection* collection = V8Proxy::ToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, info.Holder()); + HTMLOptionsCollection* collection = V8DOMWrapper::convertToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, info.Holder()); RefPtr<Node> result = collection->item(index); if (!result) return notHandledByInterceptor(); - return V8Proxy::NodeToV8Object(result.get()); + return V8DOMWrapper::convertNodeToV8Object(result.release()); } INDEXED_PROPERTY_SETTER(HTMLOptionsCollection) { INC_STATS("DOM.HTMLOptionsCollection.IndexedPropertySetter"); - HTMLOptionsCollection* collection = V8Proxy::ToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, info.Holder()); + HTMLOptionsCollection* collection = V8DOMWrapper::convertToNativeObject<HTMLOptionsCollection>(V8ClassIndex::HTMLOPTIONSCOLLECTION, info.Holder()); HTMLSelectElement* base = static_cast<HTMLSelectElement*>(collection->base()); return toOptionsCollectionSetter(index, value, base); } diff --git a/WebCore/bindings/v8/custom/V8HTMLPlugInElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLPlugInElementCustom.cpp index a6e41a1..13c82f3 100644 --- a/WebCore/bindings/v8/custom/V8HTMLPlugInElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLPlugInElementCustom.cpp @@ -35,17 +35,15 @@ #include "V8Binding.h" #include "V8CustomBinding.h" +#include "V8NPObject.h" #include "V8Proxy.h" -// FIXME: The name of this file will change once refactoring is complete -#include "v8_npobject.h" - namespace WebCore { NAMED_PROPERTY_GETTER(HTMLPlugInElement) { INC_STATS("DOM.HTMLPlugInElement.NamedPropertyGetter"); - HTMLPlugInElement* imp = V8Proxy::DOMWrapperToNode<HTMLPlugInElement>(info.Holder()); + HTMLPlugInElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLPlugInElement>(info.Holder()); ScriptInstance scriptInstance = imp->getInstance(); if (!scriptInstance) return notHandledByInterceptor(); @@ -54,13 +52,13 @@ NAMED_PROPERTY_GETTER(HTMLPlugInElement) if (instance.IsEmpty()) return notHandledByInterceptor(); - return NPObjectGetNamedProperty(instance, name); + return npObjectGetNamedProperty(instance, name); } NAMED_PROPERTY_SETTER(HTMLPlugInElement) { INC_STATS("DOM.HTMLPlugInElement.NamedPropertySetter"); - HTMLPlugInElement* imp = V8Proxy::DOMWrapperToNode<HTMLPlugInElement>(info.Holder()); + HTMLPlugInElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLPlugInElement>(info.Holder()); ScriptInstance scriptInstance = imp->getInstance(); if (!scriptInstance) return notHandledByInterceptor(); @@ -69,19 +67,19 @@ NAMED_PROPERTY_SETTER(HTMLPlugInElement) if (instance.IsEmpty()) return notHandledByInterceptor(); - return NPObjectSetNamedProperty(instance, name, value); + return npObjectSetNamedProperty(instance, name, value); } CALLBACK_FUNC_DECL(HTMLPlugInElement) { INC_STATS("DOM.HTMLPluginElement()"); - return NPObjectInvokeDefaultHandler(args); + return npObjectInvokeDefaultHandler(args); } INDEXED_PROPERTY_GETTER(HTMLPlugInElement) { INC_STATS("DOM.HTMLPlugInElement.IndexedPropertyGetter"); - HTMLPlugInElement* imp = V8Proxy::DOMWrapperToNode<HTMLPlugInElement>(info.Holder()); + HTMLPlugInElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLPlugInElement>(info.Holder()); ScriptInstance scriptInstance = imp->getInstance(); if (!scriptInstance) return notHandledByInterceptor(); @@ -90,13 +88,13 @@ INDEXED_PROPERTY_GETTER(HTMLPlugInElement) if (instance.IsEmpty()) return notHandledByInterceptor(); - return NPObjectGetIndexedProperty(instance, index); + return npObjectGetIndexedProperty(instance, index); } INDEXED_PROPERTY_SETTER(HTMLPlugInElement) { INC_STATS("DOM.HTMLPlugInElement.IndexedPropertySetter"); - HTMLPlugInElement* imp = V8Proxy::DOMWrapperToNode<HTMLPlugInElement>(info.Holder()); + HTMLPlugInElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLPlugInElement>(info.Holder()); ScriptInstance scriptInstance = imp->getInstance(); if (!scriptInstance) return notHandledByInterceptor(); @@ -105,7 +103,7 @@ INDEXED_PROPERTY_SETTER(HTMLPlugInElement) if (instance.IsEmpty()) return notHandledByInterceptor(); - return NPObjectSetIndexedProperty(instance, index, value); + return npObjectSetIndexedProperty(instance, index, value); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8HTMLSelectElementCollectionCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLSelectElementCollectionCustom.cpp index 8b3b72a..0dfa515 100644 --- a/WebCore/bindings/v8/custom/V8HTMLSelectElementCollectionCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLSelectElementCollectionCustom.cpp @@ -43,7 +43,7 @@ namespace WebCore { NAMED_PROPERTY_GETTER(HTMLSelectElementCollection) { INC_STATS("DOM.HTMLSelectElementCollection.NamedPropertySetter"); - HTMLSelectElement* select = V8Proxy::DOMWrapperToNode<HTMLSelectElement>(info.Holder()); + HTMLSelectElement* select = V8DOMWrapper::convertDOMWrapperToNode<HTMLSelectElement>(info.Holder()); v8::Handle<v8::Value> value = info.Holder()->GetRealNamedPropertyInPrototypeChain(name); if (!value.IsEmpty()) @@ -62,16 +62,16 @@ NAMED_PROPERTY_GETTER(HTMLSelectElementCollection) return notHandledByInterceptor(); if (items.size() == 1) - return V8Proxy::NodeToV8Object(items.at(0).get()); + return V8DOMWrapper::convertNodeToV8Object(items.at(0).release()); NodeList* list = new V8NamedNodesCollection(items); - return V8Proxy::ToV8Object(V8ClassIndex::NODELIST, list); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::NODELIST, list); } INDEXED_PROPERTY_SETTER(HTMLSelectElementCollection) { INC_STATS("DOM.HTMLSelectElementCollection.IndexedPropertySetter"); - HTMLSelectElement* select = V8Proxy::DOMWrapperToNode<HTMLSelectElement>(info.Holder()); + HTMLSelectElement* select = V8DOMWrapper::convertDOMWrapperToNode<HTMLSelectElement>(info.Holder()); return toOptionsCollectionSetter(index, value, select); } diff --git a/WebCore/bindings/v8/custom/V8HTMLSelectElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLSelectElementCustom.cpp index 97f7726..661ffa2 100644 --- a/WebCore/bindings/v8/custom/V8HTMLSelectElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLSelectElementCustom.cpp @@ -44,19 +44,19 @@ namespace WebCore { CALLBACK_FUNC_DECL(HTMLSelectElementRemove) { INC_STATS("DOM.HTMLSelectElement.remove"); - HTMLSelectElement* imp = V8Proxy::DOMWrapperToNode<HTMLSelectElement>(args.Holder()); + HTMLSelectElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLSelectElement>(args.Holder()); return removeElement(imp, args); } v8::Handle<v8::Value> removeElement(HTMLSelectElement* imp, const v8::Arguments& args) { if (V8HTMLOptionElement::HasInstance(args[0])) { - HTMLOptionElement* element = V8Proxy::DOMWrapperToNode<HTMLOptionElement>(args[0]); + HTMLOptionElement* element = V8DOMWrapper::convertDOMWrapperToNode<HTMLOptionElement>(v8::Handle<v8::Object>::Cast(args[0])); imp->remove(element->index()); return v8::Undefined(); } - imp->remove(ToInt32(args[0])); + imp->remove(toInt32(args[0])); return v8::Undefined(); } diff --git a/WebCore/bindings/v8/custom/V8InspectorControllerCustom.cpp b/WebCore/bindings/v8/custom/V8InspectorBackendCustom.cpp index a85c0d6..2571df4 100644 --- a/WebCore/bindings/v8/custom/V8InspectorControllerCustom.cpp +++ b/WebCore/bindings/v8/custom/V8InspectorBackendCustom.cpp @@ -29,12 +29,13 @@ */ #include "config.h" -#include "InspectorController.h" +#include "InspectorBackend.h" #include "DOMWindow.h" #include "Frame.h" #include "FrameLoader.h" #include "ExceptionCode.h" +#include "InspectorController.h" #include "InspectorResource.h" #include "NotImplemented.h" #include "Node.h" @@ -49,58 +50,31 @@ namespace WebCore { -CALLBACK_FUNC_DECL(InspectorControllerHighlightDOMNode) +CALLBACK_FUNC_DECL(InspectorBackendHighlightDOMNode) { - INC_STATS("InspectorController.highlightDOMNode()"); + INC_STATS("InspectorBackend.highlightDOMNode()"); if (args.Length() < 1) return v8::Undefined(); - Node* node = V8Proxy::DOMWrapperToNode<Node>(args[0]); + Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])); if (!node) return v8::Undefined(); - InspectorController* inspectorController = V8Proxy::ToNativeObject<InspectorController>(V8ClassIndex::INSPECTORCONTROLLER, args.Holder()); - inspectorController->highlight(node); + InspectorBackend* inspectorBackend = V8DOMWrapper::convertToNativeObject<InspectorBackend>(V8ClassIndex::INSPECTORBACKEND, args.Holder()); + inspectorBackend->highlight(node); return v8::Undefined(); } -CALLBACK_FUNC_DECL(InspectorControllerGetResourceDocumentNode) +CALLBACK_FUNC_DECL(InspectorBackendSearch) { - INC_STATS("InspectorController.getResourceDocumentNode()"); - - if (args.Length() < 1) - return v8::Undefined(); - - if (!args[1]->IsNumber()) - return v8::Undefined(); - - unsigned identifier = args[1]->Int32Value(); - - InspectorController* inspectorController = V8Proxy::ToNativeObject<InspectorController>(V8ClassIndex::INSPECTORCONTROLLER, args.Holder()); - RefPtr<InspectorResource> resource = inspectorController->resources().get(identifier); - ASSERT(resource); - if (!resource) - return v8::Undefined(); - - Frame* frame = resource->frame(); - Document* document = frame->document(); - - if (document->isPluginDocument() || document->isImageDocument() || document->isMediaDocument()) - return v8::Undefined(); - - return V8Proxy::ToV8Object(V8ClassIndex::DOCUMENT, document); -} - -CALLBACK_FUNC_DECL(InspectorControllerSearch) -{ - INC_STATS("InspectorController.search()"); + INC_STATS("InspectorBackend.search()"); if (args.Length() < 2) return v8::Undefined(); - Node* node = V8Proxy::DOMWrapperToNode<Node>(args[0]); + Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])); if (!node) return v8::Undefined(); @@ -124,7 +98,7 @@ CALLBACK_FUNC_DECL(InspectorControllerSearch) if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM)) break; - result->Set(v8::Number::New(index++), V8Proxy::ToV8Object<Range>(V8ClassIndex::RANGE, resultRange.get())); + result->Set(v8::Number::New(index++), V8DOMWrapper::convertToV8Object(V8ClassIndex::RANGE, resultRange.release())); setStart(searchRange.get(), newStart); } while (true); @@ -133,25 +107,28 @@ CALLBACK_FUNC_DECL(InspectorControllerSearch) } #if ENABLE(DATABASE) -CALLBACK_FUNC_DECL(InspectorControllerDatabaseTableNames) +CALLBACK_FUNC_DECL(InspectorBackendDatabaseTableNames) { - INC_STATS("InspectorController.databaseTableNames()"); + INC_STATS("InspectorBackend.databaseTableNames()"); v8::Local<v8::Array> result = v8::Array::New(0); return result; } #endif -CALLBACK_FUNC_DECL(InspectorControllerInspectedWindow) +CALLBACK_FUNC_DECL(InspectorBackendInspectedWindow) { - INC_STATS("InspectorController.inspectedWindow()"); + INC_STATS("InspectorBackend.inspectedWindow()"); - InspectorController* inspectorController = V8Proxy::ToNativeObject<InspectorController>(V8ClassIndex::INSPECTORCONTROLLER, args.Holder()); - return V8Proxy::ToV8Object<DOMWindow>(V8ClassIndex::DOMWINDOW, inspectorController->inspectedPage()->mainFrame()->domWindow()); + InspectorBackend* inspectorBackend = V8DOMWrapper::convertToNativeObject<InspectorBackend>(V8ClassIndex::INSPECTORBACKEND, args.Holder()); + InspectorController* ic = inspectorBackend->inspectorController(); + if (!ic) + return v8::Undefined(); + return V8DOMWrapper::convertToV8Object<DOMWindow>(V8ClassIndex::DOMWINDOW, ic->inspectedPage()->mainFrame()->domWindow()); } -CALLBACK_FUNC_DECL(InspectorControllerSetting) +CALLBACK_FUNC_DECL(InspectorBackendSetting) { - INC_STATS("InspectorController.setting()"); + INC_STATS("InspectorBackend.setting()"); if (args.Length() < 1) return v8::Undefined(); @@ -160,8 +137,11 @@ CALLBACK_FUNC_DECL(InspectorControllerSetting) if (key.isEmpty()) return v8::Undefined(); - InspectorController* inspectorController = V8Proxy::ToNativeObject<InspectorController>(V8ClassIndex::INSPECTORCONTROLLER, args.Holder()); - const InspectorController::Setting& setting = inspectorController ->setting(key); + InspectorBackend* inspectorBackend = V8DOMWrapper::convertToNativeObject<InspectorBackend>(V8ClassIndex::INSPECTORBACKEND, args.Holder()); + InspectorController* ic = inspectorBackend->inspectorController(); + if (!ic) + return v8::Undefined(); + const InspectorController::Setting& setting = ic->setting(key); switch (setting.type()) { default: @@ -186,9 +166,9 @@ CALLBACK_FUNC_DECL(InspectorControllerSetting) } } -CALLBACK_FUNC_DECL(InspectorControllerSetSetting) +CALLBACK_FUNC_DECL(InspectorBackendSetSetting) { - INC_STATS("InspectorController.setSetting()"); + INC_STATS("InspectorBackend.setSetting()"); if (args.Length() < 2) return v8::Undefined(); @@ -221,15 +201,17 @@ CALLBACK_FUNC_DECL(InspectorControllerSetSetting) } else return v8::Undefined(); - InspectorController* inspectorController = V8Proxy::ToNativeObject<InspectorController>(V8ClassIndex::INSPECTORCONTROLLER, args.Holder()); - inspectorController->setSetting(key, setting); + InspectorBackend* inspectorBackend = V8DOMWrapper::convertToNativeObject<InspectorBackend>(V8ClassIndex::INSPECTORBACKEND, args.Holder()); + InspectorController* ic = inspectorBackend->inspectorController(); + if (ic) + inspectorBackend->inspectorController()->setSetting(key, setting); return v8::Undefined(); } -CALLBACK_FUNC_DECL(InspectorControllerWrapCallback) +CALLBACK_FUNC_DECL(InspectorBackendWrapCallback) { - INC_STATS("InspectorController.wrapCallback()"); + INC_STATS("InspectorBackend.wrapCallback()"); return args[0]; } diff --git a/WebCore/bindings/v8/custom/V8LocationCustom.cpp b/WebCore/bindings/v8/custom/V8LocationCustom.cpp index c5f3b1d..3f3ff6b 100644 --- a/WebCore/bindings/v8/custom/V8LocationCustom.cpp +++ b/WebCore/bindings/v8/custom/V8LocationCustom.cpp @@ -62,7 +62,7 @@ ACCESSOR_SETTER(LocationHash) { INC_STATS("DOM.Location.hash._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); String hash = toWebCoreString(value); Frame* frame = imp->frame(); @@ -70,13 +70,13 @@ ACCESSOR_SETTER(LocationHash) return; KURL url = frame->loader()->url(); - String oldRef = url.ref(); + String oldRef = url.fragmentIdentifier(); if (hash.startsWith("#")) hash = hash.substring(1); if (oldRef == hash || (oldRef.isNull() && hash.isEmpty())) return; - url.setRef(hash); + url.setFragmentIdentifier(hash); navigateIfAllowed(frame, url, false, false); } @@ -85,7 +85,7 @@ ACCESSOR_SETTER(LocationHost) { INC_STATS("DOM.Location.host._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); String host = toWebCoreString(value); Frame* frame = imp->frame(); @@ -105,7 +105,7 @@ ACCESSOR_SETTER(LocationHostname) { INC_STATS("DOM.Location.hostname._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); String hostname = toWebCoreString(value); Frame* frame = imp->frame(); @@ -122,7 +122,7 @@ ACCESSOR_SETTER(LocationHref) { INC_STATS("DOM.Location.href._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); Frame* frame = imp->frame(); if (!frame) @@ -142,7 +142,7 @@ ACCESSOR_SETTER(LocationPathname) { INC_STATS("DOM.Location.pathname._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); String pathname = toWebCoreString(value); Frame* frame = imp->frame(); @@ -159,7 +159,7 @@ ACCESSOR_SETTER(LocationPort) { INC_STATS("DOM.Location.port._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); String port = toWebCoreString(value); Frame* frame = imp->frame(); @@ -176,7 +176,7 @@ ACCESSOR_SETTER(LocationProtocol) { INC_STATS("DOM.Location.protocol._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); String protocol = toWebCoreString(value); Frame* frame = imp->frame(); @@ -193,7 +193,7 @@ ACCESSOR_SETTER(LocationSearch) { INC_STATS("DOM.Location.search._set"); v8::Handle<v8::Object> holder = info.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); String query = toWebCoreString(value); Frame* frame = imp->frame(); @@ -210,14 +210,14 @@ ACCESSOR_GETTER(LocationReload) { INC_STATS("DOM.Location.reload._get"); static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(v8LocationReloadCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); - v8::Handle<v8::Object> holder = V8Proxy::LookupDOMWrapper(V8ClassIndex::LOCATION, info.This()); + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::LOCATION, info.This()); if (holder.IsEmpty()) { // can only reach here by 'object.__proto__.func', and it should passed // domain security check already return privateTemplate->GetFunction(); } - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); - if (!V8Proxy::CanAccessFrame(imp->frame(), false)) { + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + if (!V8Proxy::canAccessFrame(imp->frame(), false)) { static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(v8LocationReloadCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); return sharedTemplate->GetFunction(); } else @@ -228,14 +228,14 @@ ACCESSOR_GETTER(LocationReplace) { INC_STATS("DOM.Location.replace._get"); static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(v8LocationReplaceCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); - v8::Handle<v8::Object> holder = V8Proxy::LookupDOMWrapper(V8ClassIndex::LOCATION, info.This()); + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::LOCATION, info.This()); if (holder.IsEmpty()) { // can only reach here by 'object.__proto__.func', and it should passed // domain security check already return privateTemplate->GetFunction(); } - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); - if (!V8Proxy::CanAccessFrame(imp->frame(), false)) { + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + if (!V8Proxy::canAccessFrame(imp->frame(), false)) { static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(v8LocationReplaceCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); return sharedTemplate->GetFunction(); } else @@ -247,14 +247,14 @@ ACCESSOR_GETTER(LocationAssign) INC_STATS("DOM.Location.assign._get"); static v8::Persistent<v8::FunctionTemplate> privateTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(v8LocationAssignCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); - v8::Handle<v8::Object> holder = V8Proxy::LookupDOMWrapper(V8ClassIndex::LOCATION, info.This()); + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::LOCATION, info.This()); if (holder.IsEmpty()) { // can only reach here by 'object.__proto__.func', and it should passed // domain security check already return privateTemplate->GetFunction(); } - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); - if (!V8Proxy::CanAccessFrame(imp->frame(), false)) { + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + if (!V8Proxy::canAccessFrame(imp->frame(), false)) { static v8::Persistent<v8::FunctionTemplate> sharedTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(v8LocationAssignCallback, v8::Handle<v8::Value>(), v8::Signature::New(V8Location::GetRawTemplate()))); return sharedTemplate->GetFunction(); } else @@ -266,8 +266,8 @@ CALLBACK_FUNC_DECL(LocationReload) // FIXME: we ignore the "forceget" parameter. INC_STATS("DOM.Location.reload"); - v8::Handle<v8::Value> holder = args.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + v8::Handle<v8::Object> holder = args.Holder(); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); Frame* frame = imp->frame(); if (!frame || !ScriptController::isSafeScript(frame)) @@ -281,8 +281,8 @@ CALLBACK_FUNC_DECL(LocationReload) CALLBACK_FUNC_DECL(LocationReplace) { INC_STATS("DOM.Location.replace"); - v8::Handle<v8::Value> holder = args.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + v8::Handle<v8::Object> holder = args.Holder(); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); Frame* frame = imp->frame(); if (!frame) @@ -302,8 +302,8 @@ CALLBACK_FUNC_DECL(LocationReplace) CALLBACK_FUNC_DECL(LocationAssign) { INC_STATS("DOM.Location.assign"); - v8::Handle<v8::Value> holder = args.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + v8::Handle<v8::Object> holder = args.Holder(); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); Frame* frame = imp->frame(); if (!frame) @@ -333,9 +333,9 @@ CALLBACK_FUNC_DECL(LocationValueOf) CALLBACK_FUNC_DECL(LocationToString) { INC_STATS("DOM.Location.toString"); - v8::Handle<v8::Value> holder = args.Holder(); - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, holder); - if (!V8Proxy::CanAccessFrame(imp->frame(), true)) + v8::Handle<v8::Object> holder = args.Holder(); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, holder); + if (!V8Proxy::canAccessFrame(imp->frame(), true)) return v8::Undefined(); String result = imp->href(); return v8String(result); @@ -345,16 +345,16 @@ INDEXED_ACCESS_CHECK(Location) { ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::LOCATION); // Only allow same origin access - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, host); - return V8Proxy::CanAccessFrame(imp->frame(), false); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, host); + return V8Proxy::canAccessFrame(imp->frame(), false); } NAMED_ACCESS_CHECK(Location) { ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::LOCATION); // Only allow same origin access - Location* imp = V8Proxy::ToNativeObject<Location>(V8ClassIndex::LOCATION, host); - return V8Proxy::CanAccessFrame(imp->frame(), false); + Location* imp = V8DOMWrapper::convertToNativeObject<Location>(V8ClassIndex::LOCATION, host); + return V8Proxy::canAccessFrame(imp->frame(), false); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp b/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp index 3a41467..f45aecf 100644 --- a/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp @@ -31,12 +31,14 @@ #include "config.h" #include "MessageChannel.h" -#include "Document.h" -#include "Frame.h" - #include "V8Binding.h" #include "V8Proxy.h" +#include "Document.h" +#include "Frame.h" +#include "WorkerContext.h" +#include "WorkerContextExecutionProxy.h" + #include <wtf/RefPtr.h> namespace WebCore { @@ -44,32 +46,37 @@ namespace WebCore { CALLBACK_FUNC_DECL(MessageChannelConstructor) { INC_STATS("DOM.MessageChannel.Constructor"); - // FIXME: The logic here is almost exact duplicate of V8::ConstructDOMObject. + // FIXME: The logic here is almost exact duplicate of V8::constructDOMObject. // Consider refactoring to reduce duplication. if (!args.IsConstructCall()) return throwError("DOM object constructor cannot be called as a function."); - // Get the document. - Frame* frame = V8Proxy::retrieveFrame(); - if (!frame) - return v8::Undefined(); - - Document* document = frame->document(); + // Get the ScriptExecutionContext (WorkerContext or Document) + ScriptExecutionContext* context = 0; + WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve(); + if (proxy) + context = proxy->workerContext(); + else { + Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); + if (!frame) + return v8::Undefined(); + context = frame->document(); + } // Note: it's OK to let this RefPtr go out of scope because we also call // SetDOMWrapper(), which effectively holds a reference to obj. - RefPtr<MessageChannel> obj = MessageChannel::create(document); + RefPtr<MessageChannel> obj = MessageChannel::create(context); v8::Local<v8::Object> messageChannel = args.Holder(); // Create references from the MessageChannel wrapper to the two // MessagePort wrappers to make sure that the MessagePort wrappers // stay alive as long as the MessageChannel wrapper is around. - messageChannel->SetInternalField(kMessageChannelPort1Index, V8Proxy::ToV8Object(V8ClassIndex::MESSAGEPORT, obj->port1())); - messageChannel->SetInternalField(kMessageChannelPort2Index, V8Proxy::ToV8Object(V8ClassIndex::MESSAGEPORT, obj->port2())); + messageChannel->SetInternalField(kMessageChannelPort1Index, V8DOMWrapper::convertToV8Object(V8ClassIndex::MESSAGEPORT, obj->port1())); + messageChannel->SetInternalField(kMessageChannelPort2Index, V8DOMWrapper::convertToV8Object(V8ClassIndex::MESSAGEPORT, obj->port2())); // Setup the standard wrapper object internal fields. - V8Proxy::SetDOMWrapper(messageChannel, V8ClassIndex::MESSAGECHANNEL, obj.get()); + V8DOMWrapper::setDOMWrapper(messageChannel, V8ClassIndex::MESSAGECHANNEL, obj.get()); return toV8(obj.release(), messageChannel); } diff --git a/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp b/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp index fce04b6..95d248c 100644 --- a/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp +++ b/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp @@ -37,20 +37,38 @@ #include "V8ObjectEventListener.h" #include "V8Proxy.h" #include "V8Utilities.h" +#include "WorkerContextExecutionProxy.h" namespace WebCore { +PassRefPtr<EventListener> getEventListener(MessagePort* messagePort, v8::Local<v8::Value> value, bool findOnly, bool createObjectEventListener) +{ + V8Proxy* proxy = V8Proxy::retrieve(messagePort->scriptExecutionContext()); + if (proxy) { + V8EventListenerList* list = proxy->objectListeners(); + return findOnly ? list->findWrapper(value, false) : list->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); + } + +#if ENABLE(WORKERS) + WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); + if (workerContextProxy) + return workerContextProxy->findOrCreateEventListenerHelper(value, false, findOnly, createObjectEventListener); +#endif + + return PassRefPtr<EventListener>(); +} + ACCESSOR_GETTER(MessagePortOnmessage) { INC_STATS("DOM.MessagePort.onmessage._get"); - MessagePort* messagePort = V8Proxy::ToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, info.Holder()); - return V8Proxy::EventListenerToV8Object(messagePort->onmessage()); + MessagePort* messagePort = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, info.Holder()); + return V8DOMWrapper::convertEventListenerToV8Object(messagePort->onmessage()); } ACCESSOR_SETTER(MessagePortOnmessage) { INC_STATS("DOM.MessagePort.onmessage._set"); - MessagePort* messagePort = V8Proxy::ToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, info.Holder()); + MessagePort* messagePort = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, info.Holder()); if (value->IsNull()) { if (messagePort->onmessage()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(messagePort->onmessage()); @@ -61,11 +79,7 @@ ACCESSOR_SETTER(MessagePortOnmessage) messagePort->setOnmessage(0); } else { - V8Proxy* proxy = V8Proxy::retrieve(messagePort->scriptExecutionContext()); - if (!proxy) - return; - - RefPtr<EventListener> listener = proxy->FindOrCreateObjectEventListener(value, false); + RefPtr<EventListener> listener = getEventListener(messagePort, value, false, false); if (listener) { messagePort->setOnmessage(listener); createHiddenDependency(info.Holder(), value, V8Custom::kMessagePortRequestCacheIndex); @@ -73,64 +87,11 @@ ACCESSOR_SETTER(MessagePortOnmessage) } } -ACCESSOR_GETTER(MessagePortOnclose) -{ - INC_STATS("DOM.MessagePort.onclose._get"); - MessagePort* messagePort = V8Proxy::ToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, info.Holder()); - return V8Proxy::EventListenerToV8Object(messagePort->onclose()); -} - -ACCESSOR_SETTER(MessagePortOnclose) -{ - INC_STATS("DOM.MessagePort.onclose._set"); - MessagePort* messagePort = V8Proxy::ToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, info.Holder()); - if (value->IsNull()) { - if (messagePort->onclose()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(messagePort->onclose()); - removeHiddenDependency(info.Holder(), listener->getListenerObject(), V8Custom::kXMLHttpRequestCacheIndex); - } - - // Clear the listener. - messagePort->setOnclose(0); - } else { - V8Proxy* proxy = V8Proxy::retrieve(messagePort->scriptExecutionContext()); - if (!proxy) - return; - - RefPtr<EventListener> listener = proxy->FindOrCreateObjectEventListener(value, false); - if (listener) { - messagePort->setOnclose(listener); - createHiddenDependency(info.Holder(), value, V8Custom::kMessagePortRequestCacheIndex); - } - } -} - -CALLBACK_FUNC_DECL(MessagePortStartConversation) -{ - INC_STATS("DOM.MessagePort.StartConversation()"); - if (args.Length() < 1) - return throwError("Not enough arguments", V8Proxy::SYNTAX_ERROR); - MessagePort* messagePort = V8Proxy::ToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, args.Holder()); - - V8Proxy* proxy = V8Proxy::retrieve(messagePort->scriptExecutionContext()); - if (!proxy) - return v8::Undefined(); - - RefPtr<MessagePort> port = messagePort->startConversation(messagePort->scriptExecutionContext(), toWebCoreString(args[0])); - v8::Handle<v8::Value> wrapper = V8Proxy::ToV8Object(V8ClassIndex::MESSAGEPORT, port.get()); - return wrapper; -} - CALLBACK_FUNC_DECL(MessagePortAddEventListener) { - INC_STATS("DOM.MessagePort.AddEventListener()"); - MessagePort* messagePort = V8Proxy::ToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, args.Holder()); - - V8Proxy* proxy = V8Proxy::retrieve(messagePort->scriptExecutionContext()); - if (!proxy) - return v8::Undefined(); - - RefPtr<EventListener> listener = proxy->FindOrCreateObjectEventListener(args[1], false); + INC_STATS("DOM.MessagePort.addEventListener()"); + MessagePort* messagePort = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, args.Holder()); + RefPtr<EventListener> listener = getEventListener(messagePort, args[1], false, true); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); @@ -143,15 +104,9 @@ CALLBACK_FUNC_DECL(MessagePortAddEventListener) CALLBACK_FUNC_DECL(MessagePortRemoveEventListener) { - INC_STATS("DOM.MessagePort.RemoveEventListener()"); - MessagePort* messagePort = V8Proxy::ToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, args.Holder()); - - V8Proxy* proxy = V8Proxy::retrieve(messagePort->scriptExecutionContext()); - if (!proxy) - return v8::Undefined(); // probably leaked - - RefPtr<EventListener> listener = proxy->FindObjectEventListener(args[1], false); - + INC_STATS("DOM.MessagePort.removeEventListener()"); + MessagePort* messagePort = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, args.Holder()); + RefPtr<EventListener> listener = getEventListener(messagePort, args[1], true, true); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); diff --git a/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp b/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp index 8e529cc..afa90b7 100644 --- a/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp @@ -42,12 +42,12 @@ namespace WebCore { INDEXED_PROPERTY_GETTER(NamedNodeMap) { INC_STATS("DOM.NamedNodeMap.IndexedPropertyGetter"); - NamedNodeMap* imp = V8Proxy::ToNativeObject<NamedNodeMap>(V8ClassIndex::NAMEDNODEMAP, info.Holder()); + NamedNodeMap* imp = V8DOMWrapper::convertToNativeObject<NamedNodeMap>(V8ClassIndex::NAMEDNODEMAP, info.Holder()); RefPtr<Node> result = imp->item(index); if (!result) return notHandledByInterceptor(); - return V8Proxy::NodeToV8Object(result.get()); + return V8DOMWrapper::convertNodeToV8Object(result.release()); } NAMED_PROPERTY_GETTER(NamedNodeMap) @@ -63,12 +63,12 @@ NAMED_PROPERTY_GETTER(NamedNodeMap) return notHandledByInterceptor(); // Finally, search the DOM. - NamedNodeMap* imp = V8Proxy::ToNativeObject<NamedNodeMap>(V8ClassIndex::NAMEDNODEMAP, info.Holder()); + NamedNodeMap* imp = V8DOMWrapper::convertToNativeObject<NamedNodeMap>(V8ClassIndex::NAMEDNODEMAP, info.Holder()); RefPtr<Node> result = imp->getNamedItem(toWebCoreString(name)); if (!result) return notHandledByInterceptor(); - return V8Proxy::NodeToV8Object(result.get()); + return V8DOMWrapper::convertNodeToV8Object(result.release()); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp b/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp index 9adfe25..6a7b209 100644 --- a/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NavigatorCustom.cpp @@ -41,7 +41,7 @@ ACCESSOR_GETTER(NavigatorAppVersion) { INC_STATS("DOM.Navigator.appVersion"); v8::Handle<v8::Object> holder = info.Holder(); - Navigator* navigator = V8Proxy::ToNativeObject<Navigator>(V8ClassIndex::NAVIGATOR, holder); + Navigator* navigator = V8DOMWrapper::convertToNativeObject<Navigator>(V8ClassIndex::NAVIGATOR, holder); return v8StringOrUndefined(navigator->appVersion()); } diff --git a/WebCore/bindings/v8/custom/V8NodeCustom.cpp b/WebCore/bindings/v8/custom/V8NodeCustom.cpp index e81e8b5..6b0d740 100644 --- a/WebCore/bindings/v8/custom/V8NodeCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NodeCustom.cpp @@ -34,30 +34,86 @@ #include "Document.h" #include "EventListener.h" +#include "V8AbstractEventListener.h" #include "V8Binding.h" #include "V8CustomBinding.h" #include "V8CustomEventListener.h" #include "V8Node.h" +#include "V8ObjectEventListener.h" #include "V8Proxy.h" #include <wtf/RefPtr.h> namespace WebCore { -CALLBACK_FUNC_DECL(NodeAddEventListener) +static inline String toEventType(v8::Local<v8::String> value) { - INC_STATS("DOM.Node.addEventListener()"); - Node* node = V8Proxy::DOMWrapperToNode<Node>(args.Holder()); + String key = toWebCoreString(value); + ASSERT(key.startsWith("on")); + return key.substring(2); +} - V8Proxy* proxy = V8Proxy::retrieve(node->document()->frame()); +static PassRefPtr<EventListener> getEventListener(Node* node, v8::Local<v8::Value> value, bool isAttribute, bool findOnly) +{ + V8Proxy* proxy = V8Proxy::retrieve(node->scriptExecutionContext()); + // The document might be created using createDocument, which does + // not have a frame, use the active frame. if (!proxy) - return v8::Undefined(); + proxy = V8Proxy::retrieve(V8Proxy::retrieveFrameForEnteredContext()); + + if (proxy) { + V8EventListenerList* list = proxy->objectListeners(); + return findOnly ? list->findWrapper(value, isAttribute) : list->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, isAttribute); + } + + return 0; +} + +ACCESSOR_SETTER(NodeEventHandler) +{ + Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(info.Holder()); + String eventType = toEventType(name); + + // Remove hidden dependency on the old event handler. + if (EventListener* listener = node->getAttributeEventListener(eventType)) { + if (static_cast<V8AbstractEventListener*>(listener)->isObjectListener()) { + v8::Local<v8::Object> v8Listener = static_cast<V8ObjectEventListener*>(listener)->getListenerObject(); + removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kNodeEventListenerCacheIndex); + } + } + + // Set handler if the value is a function. + if (value->IsFunction()) { + RefPtr<EventListener> listener = getEventListener(node, value, true, false); + if (listener) { + node->setAttributeEventListener(eventType, listener); + createHiddenDependency(info.Holder(), value, V8Custom::kNodeEventListenerCacheIndex); + } + } else { + // Otherwise, clear the handler. + node->clearAttributeEventListener(eventType); + } +} + +ACCESSOR_GETTER(NodeEventHandler) +{ + Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(info.Holder()); + + EventListener* listener = node->getAttributeEventListener(toEventType(name)); + return V8DOMWrapper::convertEventListenerToV8Object(listener); +} - RefPtr<EventListener> listener = proxy->FindOrCreateV8EventListener(args[1], false); +CALLBACK_FUNC_DECL(NodeAddEventListener) +{ + INC_STATS("DOM.Node.addEventListener()"); + Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(args.Holder()); + + RefPtr<EventListener> listener = getEventListener(node, args[1], false, false); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); node->addEventListener(type, listener, useCapture); + createHiddenDependency(args.Holder(), args[1], V8Custom::kNodeEventListenerCacheIndex); } return v8::Undefined(); } @@ -65,20 +121,17 @@ CALLBACK_FUNC_DECL(NodeAddEventListener) CALLBACK_FUNC_DECL(NodeRemoveEventListener) { INC_STATS("DOM.Node.removeEventListener()"); - Node* node = V8Proxy::DOMWrapperToNode<Node>(args.Holder()); + Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(args.Holder()); - V8Proxy* proxy = V8Proxy::retrieve(node->document()->frame()); // It is possbile that the owner document of the node is detached - // from the frame, return immediately in this case. + // from the frame. // See issue http://b/878909 - if (!proxy) - return v8::Undefined(); - - RefPtr<EventListener> listener = proxy->FindV8EventListener(args[1], false); + RefPtr<EventListener> listener = getEventListener(node, args[1], false, true); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); node->removeEventListener(type, listener.get(), useCapture); + removeHiddenDependency(args.Holder(), args[1], V8Custom::kNodeEventListenerCacheIndex); } return v8::Undefined(); @@ -88,14 +141,14 @@ CALLBACK_FUNC_DECL(NodeRemoveEventListener) CALLBACK_FUNC_DECL(NodeInsertBefore) { INC_STATS("DOM.Node.insertBefore"); - v8::Handle<v8::Value> holder = args.Holder(); - Node* imp = V8Proxy::DOMWrapperToNode<Node>(holder); + v8::Handle<v8::Object> holder = args.Holder(); + Node* imp = V8DOMWrapper::convertDOMWrapperToNode<Node>(holder); ExceptionCode ec = 0; - Node* newChild = V8Node::HasInstance(args[0]) ? V8Proxy::DOMWrapperToNode<Node>(args[0]) : 0; - Node* refChild = V8Node::HasInstance(args[1]) ? V8Proxy::DOMWrapperToNode<Node>(args[1]) : 0; + Node* newChild = V8Node::HasInstance(args[0]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])) : 0; + Node* refChild = V8Node::HasInstance(args[1]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[1])) : 0; bool success = imp->insertBefore(newChild, refChild, ec, true); if (ec) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Handle<v8::Value>(); } if (success) @@ -107,14 +160,14 @@ CALLBACK_FUNC_DECL(NodeInsertBefore) CALLBACK_FUNC_DECL(NodeReplaceChild) { INC_STATS("DOM.Node.replaceChild"); - v8::Handle<v8::Value> holder = args.Holder(); - Node* imp = V8Proxy::DOMWrapperToNode<Node>(holder); + v8::Handle<v8::Object> holder = args.Holder(); + Node* imp = V8DOMWrapper::convertDOMWrapperToNode<Node>(holder); ExceptionCode ec = 0; - Node* newChild = V8Node::HasInstance(args[0]) ? V8Proxy::DOMWrapperToNode<Node>(args[0]) : 0; - Node* oldChild = V8Node::HasInstance(args[1]) ? V8Proxy::DOMWrapperToNode<Node>(args[1]) : 0; + Node* newChild = V8Node::HasInstance(args[0]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])) : 0; + Node* oldChild = V8Node::HasInstance(args[1]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[1])) : 0; bool success = imp->replaceChild(newChild, oldChild, ec, true); if (ec) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Handle<v8::Value>(); } if (success) @@ -125,13 +178,13 @@ CALLBACK_FUNC_DECL(NodeReplaceChild) CALLBACK_FUNC_DECL(NodeRemoveChild) { INC_STATS("DOM.Node.removeChild"); - v8::Handle<v8::Value> holder = args.Holder(); - Node* imp = V8Proxy::DOMWrapperToNode<Node>(holder); + v8::Handle<v8::Object> holder = args.Holder(); + Node* imp = V8DOMWrapper::convertDOMWrapperToNode<Node>(holder); ExceptionCode ec = 0; - Node* oldChild = V8Node::HasInstance(args[0]) ? V8Proxy::DOMWrapperToNode<Node>(args[0]) : 0; + Node* oldChild = V8Node::HasInstance(args[0]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])) : 0; bool success = imp->removeChild(oldChild, ec); if (ec) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Handle<v8::Value>(); } if (success) @@ -143,13 +196,13 @@ CALLBACK_FUNC_DECL(NodeRemoveChild) CALLBACK_FUNC_DECL(NodeAppendChild) { INC_STATS("DOM.Node.appendChild"); - v8::Handle<v8::Value> holder = args.Holder(); - Node* imp = V8Proxy::DOMWrapperToNode<Node>(holder); + v8::Handle<v8::Object> holder = args.Holder(); + Node* imp = V8DOMWrapper::convertDOMWrapperToNode<Node>(holder); ExceptionCode ec = 0; - Node* newChild = V8Node::HasInstance(args[0]) ? V8Proxy::DOMWrapperToNode<Node>(args[0]) : 0; + Node* newChild = V8Node::HasInstance(args[0]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])) : 0; bool success = imp->appendChild(newChild, ec, true ); if (ec) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Handle<v8::Value>(); } if (success) diff --git a/WebCore/bindings/v8/custom/V8NodeIteratorCustom.cpp b/WebCore/bindings/v8/custom/V8NodeIteratorCustom.cpp index 48e6b8f..47ae8ee 100644 --- a/WebCore/bindings/v8/custom/V8NodeIteratorCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NodeIteratorCustom.cpp @@ -53,13 +53,13 @@ static inline v8::Handle<v8::Value> toV8(PassRefPtr<Node> object, ExceptionCode if (!object) return v8::Null(); - return V8Proxy::NodeToV8Object(object.get()); + return V8DOMWrapper::convertNodeToV8Object(object); } CALLBACK_FUNC_DECL(NodeIteratorNextNode) { INC_STATS("DOM.NodeIterator.nextNode()"); - NodeIterator* nodeIterator = V8Proxy::ToNativeObject<NodeIterator>(V8ClassIndex::NODEITERATOR, args.Holder()); + NodeIterator* nodeIterator = V8DOMWrapper::convertToNativeObject<NodeIterator>(V8ClassIndex::NODEITERATOR, args.Holder()); ExceptionCode ec = 0; ScriptState state; @@ -70,7 +70,7 @@ CALLBACK_FUNC_DECL(NodeIteratorNextNode) CALLBACK_FUNC_DECL(NodeIteratorPreviousNode) { INC_STATS("DOM.NodeIterator.previousNode()"); - NodeIterator* nodeIterator = V8Proxy::ToNativeObject<NodeIterator>(V8ClassIndex::NODEITERATOR, args.Holder()); + NodeIterator* nodeIterator = V8DOMWrapper::convertToNativeObject<NodeIterator>(V8ClassIndex::NODEITERATOR, args.Holder()); ExceptionCode ec = 0; ScriptState state; diff --git a/WebCore/bindings/v8/custom/V8NodeListCustom.cpp b/WebCore/bindings/v8/custom/V8NodeListCustom.cpp index 27a47f5..ad10952 100644 --- a/WebCore/bindings/v8/custom/V8NodeListCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NodeListCustom.cpp @@ -36,24 +36,26 @@ #include "V8Proxy.h" #include <wtf/RefPtr.h> +#include <wtf/StdLibExtras.h> namespace WebCore { NAMED_PROPERTY_GETTER(NodeList) { INC_STATS("DOM.NodeList.NamedPropertyGetter"); - NodeList* list = V8Proxy::ToNativeObject<NodeList>(V8ClassIndex::NODELIST, info.Holder()); + NodeList* list = V8DOMWrapper::convertToNativeObject<NodeList>(V8ClassIndex::NODELIST, info.Holder()); String key = toWebCoreString(name); // Length property cannot be overridden. - if (key == "length") - return v8::Number::New(list->length()); + DEFINE_STATIC_LOCAL(const AtomicString, length, ("length")); + if (key == length) + return v8::Integer::New(list->length()); RefPtr<Node> result = list->itemWithName(key); if (!result) return notHandledByInterceptor(); - return V8Proxy::NodeToV8Object(result.get()); + return V8DOMWrapper::convertNodeToV8Object(result.release()); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8SQLResultSetRowListCustom.cpp b/WebCore/bindings/v8/custom/V8SQLResultSetRowListCustom.cpp index eaeb26d..aced4ee 100644 --- a/WebCore/bindings/v8/custom/V8SQLResultSetRowListCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SQLResultSetRowListCustom.cpp @@ -32,11 +32,20 @@ #if ENABLE(DATABASE) +#ifdef MANUAL_MERGE_REQUIRED #include "v8_binding.h" #include "v8_proxy.h" +#else // MANUAL_MERGE_REQUIRED +#endif // MANUAL_MERGE_REQUIRED #include "SQLResultSetRowList.h" +#ifdef MANUAL_MERGE_REQUIRED #include "V8CustomBinding.h" +#else // MANUAL_MERGE_REQUIRED +#include "V8Binding.h" +#include "V8CustomBinding.h" +#include "V8Proxy.h" +#endif // MANUAL_MERGE_REQUIRED namespace WebCore { @@ -45,20 +54,20 @@ CALLBACK_FUNC_DECL(SQLResultSetRowListItem) INC_STATS("DOM.SQLResultSetRowList.item()"); if (args.Length() == 0) { - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "Item index is required."); + V8Proxy::throwError(V8Proxy::SyntaxError, "Item index is required."); return v8::Undefined(); } if (!args[0]->IsNumber()) { - V8Proxy::ThrowError(V8Proxy::TYPE_ERROR, "Item index must be a number."); + V8Proxy::throwError(V8Proxy::TypeError, "Item index must be a number."); return v8::Undefined(); } - SQLResultSetRowList* rowList = V8Proxy::ToNativeObject<SQLResultSetRowList>(V8ClassIndex::SQLRESULTSETROWLIST, args.Holder()); + SQLResultSetRowList* rowList = V8DOMWrapper::convertToNativeObject<SQLResultSetRowList>(V8ClassIndex::SQLRESULTSETROWLIST, args.Holder()); unsigned long index = args[0]->IntegerValue(); if (index < 0 || index >= rowList->length()) { - V8Proxy::ThrowError(V8Proxy::RANGE_ERROR, "Item index is out of range."); + V8Proxy::throwError(V8Proxy::RangeError, "Item index is out of range."); return v8::Undefined(); } diff --git a/WebCore/bindings/v8/custom/V8SQLTransactionCustom.cpp b/WebCore/bindings/v8/custom/V8SQLTransactionCustom.cpp index 15cd379..b9b86fc 100644 --- a/WebCore/bindings/v8/custom/V8SQLTransactionCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SQLTransactionCustom.cpp @@ -32,14 +32,23 @@ #if ENABLE(DATABASE) +#ifdef MANUAL_MERGE_REQUIRED #include "v8_binding.h" #include "v8_proxy.h" +#else // MANUAL_MERGE_REQUIRED +#endif // MANUAL_MERGE_REQUIRED #include "Database.h" #include "SQLValue.h" +#ifdef MANUAL_MERGE_REQUIRED #include "V8CustomBinding.h" +#else // MANUAL_MERGE_REQUIRED +#include "V8Binding.h" +#include "V8CustomBinding.h" +#endif // MANUAL_MERGE_REQUIRED #include "V8CustomSQLStatementCallback.h" #include "V8CustomSQLStatementErrorCallback.h" +#include "V8Proxy.h" #include <wtf/Vector.h> using namespace WTF; @@ -51,18 +60,18 @@ CALLBACK_FUNC_DECL(SQLTransactionExecuteSql) INC_STATS("DOM.SQLTransaction.executeSql()"); if (args.Length() == 0) { - V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "SQL statement is required."); + V8Proxy::throwError(V8Proxy::SyntaxError, "SQL statement is required."); return v8::Undefined(); } - String statement = ToWebCoreString(args[0]); + String statement = toWebCoreString(args[0]); Vector<SQLValue> sqlValues; if (args.Length() > 1) { // FIXME: Make this work for v8::Arrayish objects, as well if (!args[1]->IsArray()) { - V8Proxy::ThrowError(V8Proxy::TYPE_ERROR, "Statement arguments must be an v8::Array."); + V8Proxy::throwError(V8Proxy::TypeError, "Statement arguments must be an v8::Array."); return v8::Undefined(); } @@ -76,18 +85,18 @@ CALLBACK_FUNC_DECL(SQLTransactionExecuteSql) else if (value->IsNumber()) sqlValues.append(SQLValue(value->NumberValue())); else - sqlValues.append(SQLValue(ToWebCoreString(value))); + sqlValues.append(SQLValue(toWebCoreString(value))); } } - SQLTransaction* transaction = V8Proxy::ToNativeObject<SQLTransaction>(V8ClassIndex::SQLTRANSACTION, args.Holder()); + SQLTransaction* transaction = V8DOMWrapper::convertToNativeObject<SQLTransaction>(V8ClassIndex::SQLTRANSACTION, args.Holder()); - Frame* frame = V8Proxy::retrieveFrame(); + Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); RefPtr<SQLStatementCallback> callback; if (args.Length() > 2) { if (!args[2]->IsObject()) { - V8Proxy::ThrowError(V8Proxy::TYPE_ERROR, "Statement callback must be of valid type."); + V8Proxy::throwError(V8Proxy::TypeError, "Statement callback must be of valid type."); return v8::Undefined(); } @@ -98,7 +107,7 @@ CALLBACK_FUNC_DECL(SQLTransactionExecuteSql) RefPtr<SQLStatementErrorCallback> errorCallback; if (args.Length() > 3) { if (!args[2]->IsObject()) { - V8Proxy::ThrowError(V8Proxy::TYPE_ERROR, "Statement error callback must be of valid type."); + V8Proxy::throwError(V8Proxy::TypeError, "Statement error callback must be of valid type."); return v8::Undefined(); } @@ -108,7 +117,7 @@ CALLBACK_FUNC_DECL(SQLTransactionExecuteSql) ExceptionCode ec = 0; transaction->executeSQL(statement, sqlValues, callback, errorCallback, ec); - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Undefined(); } diff --git a/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp b/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp index 351b030..ce9c345 100644 --- a/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp @@ -47,13 +47,13 @@ namespace WebCore { CALLBACK_FUNC_DECL(SVGElementInstanceAddEventListener) { INC_STATS("DOM.SVGElementInstance.AddEventListener()"); - SVGElementInstance* instance = V8Proxy::DOMWrapperToNative<SVGElementInstance>(args.Holder()); + SVGElementInstance* instance = V8DOMWrapper::convertDOMWrapperToNative<SVGElementInstance>(args.Holder()); V8Proxy* proxy = V8Proxy::retrieve(instance->scriptExecutionContext()); if (!proxy) return v8::Undefined(); - RefPtr<EventListener> listener = proxy->FindOrCreateV8EventListener(args[1], false); + RefPtr<EventListener> listener = proxy->eventListeners()->findOrCreateWrapper<V8EventListener>(proxy->frame(), args[1], false); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); @@ -66,13 +66,13 @@ CALLBACK_FUNC_DECL(SVGElementInstanceAddEventListener) CALLBACK_FUNC_DECL(SVGElementInstanceRemoveEventListener) { INC_STATS("DOM.SVGElementInstance.RemoveEventListener()"); - SVGElementInstance* instance = V8Proxy::DOMWrapperToNative<SVGElementInstance>(args.Holder()); + SVGElementInstance* instance = V8DOMWrapper::convertDOMWrapperToNative<SVGElementInstance>(args.Holder()); V8Proxy* proxy = V8Proxy::retrieve(instance->scriptExecutionContext()); if (!proxy) return v8::Undefined(); - RefPtr<EventListener> listener = proxy->FindV8EventListener(args[1], false); + RefPtr<EventListener> listener = proxy->eventListeners()->findWrapper(args[1], false); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); diff --git a/WebCore/bindings/v8/custom/V8SVGLengthCustom.cpp b/WebCore/bindings/v8/custom/V8SVGLengthCustom.cpp index a2a4d49..9f75f5a 100644 --- a/WebCore/bindings/v8/custom/V8SVGLengthCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SVGLengthCustom.cpp @@ -44,17 +44,17 @@ namespace WebCore { ACCESSOR_GETTER(SVGLengthValue) { INC_STATS("DOM.SVGLength.value"); - V8SVGPODTypeWrapper<SVGLength>* wrapper = V8Proxy::ToNativeObject<V8SVGPODTypeWrapper<SVGLength> >(V8ClassIndex::SVGLENGTH, info.Holder()); + V8SVGPODTypeWrapper<SVGLength>* wrapper = V8DOMWrapper::convertToNativeObject<V8SVGPODTypeWrapper<SVGLength> >(V8ClassIndex::SVGLENGTH, info.Holder()); SVGLength imp = *wrapper; - return v8::Number::New(imp.value(V8Proxy::GetSVGContext(wrapper))); + return v8::Number::New(imp.value(V8Proxy::svgContext(wrapper))); } CALLBACK_FUNC_DECL(SVGLengthConvertToSpecifiedUnits) { INC_STATS("DOM.SVGLength.convertToSpecifiedUnits"); - V8SVGPODTypeWrapper<SVGLength>* wrapper = V8Proxy::ToNativeObject<V8SVGPODTypeWrapper<SVGLength> >(V8ClassIndex::SVGLENGTH, args.Holder()); + V8SVGPODTypeWrapper<SVGLength>* wrapper = V8DOMWrapper::convertToNativeObject<V8SVGPODTypeWrapper<SVGLength> >(V8ClassIndex::SVGLENGTH, args.Holder()); SVGLength imp = *wrapper; - SVGElement* context = V8Proxy::GetSVGContext(wrapper); + SVGElement* context = V8Proxy::svgContext(wrapper); imp.convertToSpecifiedUnits(toInt32(args[0]), context); wrapper->commitChange(imp, context); return v8::Undefined(); diff --git a/WebCore/bindings/v8/custom/V8SVGMatrixCustom.cpp b/WebCore/bindings/v8/custom/V8SVGMatrixCustom.cpp index b69202b..3766397 100644 --- a/WebCore/bindings/v8/custom/V8SVGMatrixCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SVGMatrixCustom.cpp @@ -46,7 +46,7 @@ namespace WebCore { CALLBACK_FUNC_DECL(SVGMatrixInverse) { INC_STATS("DOM.SVGMatrix.inverse()"); - TransformationMatrix matrix = *V8Proxy::ToNativeObject<V8SVGPODTypeWrapper<TransformationMatrix> >(V8ClassIndex::SVGMATRIX, args.Holder()); + TransformationMatrix matrix = *V8DOMWrapper::convertToNativeObject<V8SVGPODTypeWrapper<TransformationMatrix> >(V8ClassIndex::SVGMATRIX, args.Holder()); ExceptionCode ec = 0; TransformationMatrix result = matrix.inverse(); @@ -54,17 +54,17 @@ CALLBACK_FUNC_DECL(SVGMatrixInverse) ec = SVGException::SVG_MATRIX_NOT_INVERTABLE; if (ec != 0) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Handle<v8::Value>(); } - return V8Proxy::ToV8Object(V8ClassIndex::SVGMATRIX, new V8SVGStaticPODTypeWrapper<TransformationMatrix>(result)); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::SVGMATRIX, V8SVGStaticPODTypeWrapper<TransformationMatrix>::create(result)); } CALLBACK_FUNC_DECL(SVGMatrixRotateFromVector) { INC_STATS("DOM.SVGMatrix.rotateFromVector()"); - TransformationMatrix matrix = *V8Proxy::ToNativeObject<V8SVGPODTypeWrapper<TransformationMatrix> >(V8ClassIndex::SVGMATRIX, args.Holder()); + TransformationMatrix matrix = *V8DOMWrapper::convertToNativeObject<V8SVGPODTypeWrapper<TransformationMatrix> >(V8ClassIndex::SVGMATRIX, args.Holder()); ExceptionCode ec = 0; float x = toFloat(args[0]); float y = toFloat(args[1]); @@ -74,11 +74,11 @@ CALLBACK_FUNC_DECL(SVGMatrixRotateFromVector) ec = SVGException::SVG_INVALID_VALUE_ERR; if (ec != 0) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Handle<v8::Value>(); } - return V8Proxy::ToV8Object(V8ClassIndex::SVGMATRIX, new V8SVGStaticPODTypeWrapper<TransformationMatrix>(result)); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::SVGMATRIX, V8SVGStaticPODTypeWrapper<TransformationMatrix>::create(result)); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp b/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp new file mode 100644 index 0000000..3ab2f8e --- /dev/null +++ b/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp @@ -0,0 +1,97 @@ +/* + * 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: + * + * * 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. + */ + +#include "config.h" + +#if ENABLE(SHARED_WORKERS) + +#include "SharedWorker.h" + +#include "ExceptionCode.h" +#include "Frame.h" +#include "V8Binding.h" +#include "V8CustomBinding.h" +#include "V8ObjectEventListener.h" +#include "V8Proxy.h" +#include "V8Utilities.h" +#include "WorkerContext.h" +#include "WorkerContextExecutionProxy.h" + +namespace WebCore { + +CALLBACK_FUNC_DECL(SharedWorkerConstructor) +{ + INC_STATS(L"DOM.SharedWorker.Constructor"); + + if (!args.IsConstructCall()) + return throwError("DOM object constructor cannot be called as a function."); + + if (args.Length() < 2) + return throwError("Not enough arguments", V8Proxy::SyntaxError); + + v8::TryCatch tryCatch; + v8::Handle<v8::String> scriptUrl = args[0]->ToString(); + v8::Handle<v8::String> name = args[1]->ToString(); + if (tryCatch.HasCaught()) + return throwError(tryCatch.Exception()); + + if (scriptUrl.IsEmpty()) + return v8::Undefined(); + + // Get the script execution context. + ScriptExecutionContext* context = 0; + WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve(); + if (proxy) + context = proxy->workerContext(); + else { + Frame* frame = V8Proxy::retrieveFrame(); + if (!frame) + return v8::Undefined(); + context = frame->document(); + } + + // Create the worker object. + // Note: it's OK to let this RefPtr go out of scope because we also call SetDOMWrapper(), which effectively holds a reference to obj. + ExceptionCode ec = 0; + RefPtr<SharedWorker> obj = SharedWorker::create(toWebCoreString(scriptUrl), toWebCoreString(name), context, ec); + + // Setup the standard wrapper object internal fields. + v8::Handle<v8::Object> wrapperObject = args.Holder(); + V8Proxy::setDOMWrapper(wrapperObject, V8ClassIndex::SHAREDWORKER, obj.get()); + + obj->ref(); + V8Proxy::setJSWrapperForActiveDOMObject(obj.get(), v8::Persistent<v8::Object>::New(wrapperObject)); + + return wrapperObject; +} + +} // namespace WebCore + +#endif // ENABLE(SHARED_WORKERS) diff --git a/WebCore/bindings/v8/custom/V8StorageCustom.cpp b/WebCore/bindings/v8/custom/V8StorageCustom.cpp index af8b4c8..b54e50e 100755 --- a/WebCore/bindings/v8/custom/V8StorageCustom.cpp +++ b/WebCore/bindings/v8/custom/V8StorageCustom.cpp @@ -42,13 +42,12 @@ namespace WebCore { // Get an array containing the names of indexed properties in a collection. v8::Handle<v8::Array> V8Custom::v8StorageNamedPropertyEnumerator(const v8::AccessorInfo& info) { - Storage* storage = V8Proxy::ToNativeObject<Storage>(V8ClassIndex::STORAGE, info.Holder()); + Storage* storage = V8DOMWrapper::convertToNativeObject<Storage>(V8ClassIndex::STORAGE, info.Holder()); unsigned int length = storage->length(); v8::Handle<v8::Array> properties = v8::Array::New(length); for (unsigned int i = 0; i < length; ++i) { - ExceptionCode ec = 0; - String key = storage->key(i, ec); - ASSERT(!ec); + String key = storage->key(i); + ASSERT(!key.isNull()); String val = storage->getItem(key); properties->Set(v8::Integer::New(i), v8String(key)); } @@ -58,7 +57,7 @@ v8::Handle<v8::Array> V8Custom::v8StorageNamedPropertyEnumerator(const v8::Acces static v8::Handle<v8::Value> storageGetter(v8::Local<v8::String> v8Name, const v8::AccessorInfo& info) { - Storage* storage = V8Proxy::ToNativeObject<Storage>(V8ClassIndex::STORAGE, info.Holder()); + Storage* storage = V8DOMWrapper::convertToNativeObject<Storage>(V8ClassIndex::STORAGE, info.Holder()); String name = toWebCoreString(v8Name); if (storage->contains(name)) @@ -82,7 +81,7 @@ NAMED_PROPERTY_GETTER(Storage) static v8::Handle<v8::Value> storageSetter(v8::Local<v8::String> v8Name, v8::Local<v8::Value> v8Value, const v8::AccessorInfo& info) { - Storage* storage = V8Proxy::ToNativeObject<Storage>(V8ClassIndex::STORAGE, info.Holder()); + Storage* storage = V8DOMWrapper::convertToNativeObject<Storage>(V8ClassIndex::STORAGE, info.Holder()); String name = toWebCoreString(v8Name); String value = toWebCoreString(v8Value); @@ -117,7 +116,7 @@ NAMED_PROPERTY_SETTER(Storage) static v8::Handle<v8::Boolean> storageDeleter(v8::Local<v8::String> v8Name, const v8::AccessorInfo& info) { - Storage* storage = V8Proxy::ToNativeObject<Storage>(V8ClassIndex::STORAGE, info.Holder()); + Storage* storage = V8DOMWrapper::convertToNativeObject<Storage>(V8ClassIndex::STORAGE, info.Holder()); String name = toWebCoreString(v8Name); if (storage->contains(name)) { diff --git a/WebCore/bindings/v8/custom/V8StyleSheetListCustom.cpp b/WebCore/bindings/v8/custom/V8StyleSheetListCustom.cpp index a362ce5..ecd0153 100644 --- a/WebCore/bindings/v8/custom/V8StyleSheetListCustom.cpp +++ b/WebCore/bindings/v8/custom/V8StyleSheetListCustom.cpp @@ -45,12 +45,12 @@ NAMED_PROPERTY_GETTER(StyleSheetList) return notHandledByInterceptor(); // Search style sheet. - StyleSheetList* imp = V8Proxy::ToNativeObject<StyleSheetList>(V8ClassIndex::STYLESHEETLIST, info.Holder()); + StyleSheetList* imp = V8DOMWrapper::convertToNativeObject<StyleSheetList>(V8ClassIndex::STYLESHEETLIST, info.Holder()); HTMLStyleElement* item = imp->getNamedItem(toWebCoreString(name)); if (!item) return notHandledByInterceptor(); - return V8Proxy::ToV8Object(V8ClassIndex::HTMLSTYLEELEMENT, item); + return V8DOMWrapper::convertToV8Object(V8ClassIndex::HTMLSTYLEELEMENT, item); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8TreeWalkerCustom.cpp b/WebCore/bindings/v8/custom/V8TreeWalkerCustom.cpp index baf49c0..5052b7a 100644 --- a/WebCore/bindings/v8/custom/V8TreeWalkerCustom.cpp +++ b/WebCore/bindings/v8/custom/V8TreeWalkerCustom.cpp @@ -51,13 +51,13 @@ static inline v8::Handle<v8::Value> toV8(PassRefPtr<Node> object, ScriptState* s if (!object) return v8::Null(); - return V8Proxy::NodeToV8Object(object.get()); + return V8DOMWrapper::convertNodeToV8Object(object); } CALLBACK_FUNC_DECL(TreeWalkerParentNode) { INC_STATS("DOM.TreeWalker.parentNode()"); - TreeWalker* treeWalker = V8Proxy::ToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); + TreeWalker* treeWalker = V8DOMWrapper::convertToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); ScriptState state; RefPtr<Node> result = treeWalker->parentNode(&state); @@ -67,7 +67,7 @@ CALLBACK_FUNC_DECL(TreeWalkerParentNode) CALLBACK_FUNC_DECL(TreeWalkerFirstChild) { INC_STATS("DOM.TreeWalker.firstChild()"); - TreeWalker* treeWalker = V8Proxy::ToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); + TreeWalker* treeWalker = V8DOMWrapper::convertToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); ScriptState state; RefPtr<Node> result = treeWalker->firstChild(&state); @@ -77,7 +77,7 @@ CALLBACK_FUNC_DECL(TreeWalkerFirstChild) CALLBACK_FUNC_DECL(TreeWalkerLastChild) { INC_STATS("DOM.TreeWalker.lastChild()"); - TreeWalker* treeWalker = V8Proxy::ToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); + TreeWalker* treeWalker = V8DOMWrapper::convertToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); ScriptState state; RefPtr<Node> result = treeWalker->lastChild(&state); @@ -87,7 +87,7 @@ CALLBACK_FUNC_DECL(TreeWalkerLastChild) CALLBACK_FUNC_DECL(TreeWalkerNextNode) { INC_STATS("DOM.TreeWalker.nextNode()"); - TreeWalker* treeWalker = V8Proxy::ToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); + TreeWalker* treeWalker = V8DOMWrapper::convertToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); ScriptState state; RefPtr<Node> result = treeWalker->nextNode(&state); @@ -97,7 +97,7 @@ CALLBACK_FUNC_DECL(TreeWalkerNextNode) CALLBACK_FUNC_DECL(TreeWalkerPreviousNode) { INC_STATS("DOM.TreeWalker.previousNode()"); - TreeWalker* treeWalker = V8Proxy::ToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); + TreeWalker* treeWalker = V8DOMWrapper::convertToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); ScriptState state; RefPtr<Node> result = treeWalker->previousNode(&state); @@ -107,7 +107,7 @@ CALLBACK_FUNC_DECL(TreeWalkerPreviousNode) CALLBACK_FUNC_DECL(TreeWalkerNextSibling) { INC_STATS("DOM.TreeWalker.nextSibling()"); - TreeWalker* treeWalker = V8Proxy::ToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); + TreeWalker* treeWalker = V8DOMWrapper::convertToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); ScriptState state; RefPtr<Node> result = treeWalker->nextSibling(&state); @@ -117,7 +117,7 @@ CALLBACK_FUNC_DECL(TreeWalkerNextSibling) CALLBACK_FUNC_DECL(TreeWalkerPreviousSibling) { INC_STATS("DOM.TreeWalker.previousSibling()"); - TreeWalker* treeWalker = V8Proxy::ToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); + TreeWalker* treeWalker = V8DOMWrapper::convertToNativeObject<TreeWalker>(V8ClassIndex::TREEWALKER, args.Holder()); ScriptState state; RefPtr<Node> result = treeWalker->previousSibling(&state); diff --git a/WebCore/bindings/v8/custom/V8WebKitCSSMatrixConstructor.cpp b/WebCore/bindings/v8/custom/V8WebKitCSSMatrixConstructor.cpp index b07d288..4819064 100644 --- a/WebCore/bindings/v8/custom/V8WebKitCSSMatrixConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8WebKitCSSMatrixConstructor.cpp @@ -47,7 +47,11 @@ namespace WebCore { CALLBACK_FUNC_DECL(WebKitCSSMatrixConstructor) { INC_STATS("DOM.WebKitCSSMatrix.Constructor"); - // FIXME: The logic here is almost exact duplicate of V8::ConstructDOMObject. + + if (!args.IsConstructCall()) + return throwError("DOM object constructor cannot be called as a function."); + + // FIXME: The logic here is almost exact duplicate of V8::constructDOMObject. // Consider refactoring to reduce duplication. String cssValue; if (args.Length() >= 1) @@ -59,7 +63,7 @@ CALLBACK_FUNC_DECL(WebKitCSSMatrixConstructor) throwError(ec); // Transform the holder into a wrapper object for the matrix. - V8Proxy::SetDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::WEBKITCSSMATRIX), matrix.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::WEBKITCSSMATRIX), matrix.get()); return toV8(matrix.release(), args.Holder()); } diff --git a/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp b/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp index d70ebf1..dd19a88 100755 --- a/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp @@ -40,7 +40,7 @@ namespace WebCore { CALLBACK_FUNC_DECL(WebKitPointConstructor) { INC_STATS("DOM.WebKitPoint.Constructor"); - return V8Proxy::ConstructDOMObject<V8ClassIndex::WEBKITPOINT, WebKitPoint>(args); + return V8Proxy::constructDOMObject<V8ClassIndex::WEBKITPOINT, WebKitPoint>(args); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp b/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp index a67cb10..b526040 100755 --- a/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp @@ -32,11 +32,8 @@ #if ENABLE(WORKERS) -#include "WorkerContextExecutionProxy.h" - -#include "ExceptionCode.h" #include "DOMTimer.h" -#include "NotImplemented.h" +#include "ExceptionCode.h" #include "ScheduledAction.h" #include "V8Binding.h" #include "V8CustomBinding.h" @@ -44,50 +41,51 @@ #include "V8Utilities.h" #include "V8WorkerContextEventListener.h" #include "WorkerContext.h" +#include "WorkerContextExecutionProxy.h" namespace WebCore { ACCESSOR_GETTER(WorkerContextSelf) { INC_STATS(L"DOM.WorkerContext.self._get"); - WorkerContext* workerContext = V8Proxy::ToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder()); - return WorkerContextExecutionProxy::WorkerContextToV8Object(workerContext); + WorkerContext* workerContext = V8DOMWrapper::convertDOMWrapperToNative<WorkerContext>(info.Holder()); + return WorkerContextExecutionProxy::convertWorkerContextToV8Object(workerContext); } -ACCESSOR_GETTER(WorkerContextOnmessage) +ACCESSOR_GETTER(WorkerContextOnerror) { - INC_STATS(L"DOM.WorkerContext.onmessage._get"); - WorkerContext* workerContext = V8Proxy::ToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder()); - if (workerContext->onmessage()) { - V8WorkerContextEventListener* listener = static_cast<V8WorkerContextEventListener*>(workerContext->onmessage()); + INC_STATS(L"DOM.WorkerContext.onerror._get"); + WorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder()); + if (workerContext->onerror()) { + V8WorkerContextEventListener* listener = static_cast<V8WorkerContextEventListener*>(workerContext->onerror()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); return v8Listener; } return v8::Undefined(); } -ACCESSOR_SETTER(WorkerContextOnmessage) +ACCESSOR_SETTER(WorkerContextOnerror) { - INC_STATS(L"DOM.WorkerContext.onmessage._set"); - WorkerContext* workerContext = V8Proxy::ToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder()); - V8WorkerContextEventListener* oldListener = static_cast<V8WorkerContextEventListener*>(workerContext->onmessage()); + INC_STATS(L"DOM.WorkerContext.onerror._set"); + WorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder()); + V8WorkerContextEventListener* oldListener = static_cast<V8WorkerContextEventListener*>(workerContext->onerror()); if (value->IsNull()) { - if (workerContext->onmessage()) { + if (workerContext->onerror()) { v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kWorkerContextRequestCacheIndex); } // Clear the listener. - workerContext->setOnmessage(0); + workerContext->setOnerror(0); } else { - RefPtr<V8EventListener> listener = workerContext->script()->proxy()->findOrCreateEventListener(v8::Local<v8::Object>::Cast(value), false, false); + RefPtr<V8EventListener> listener = workerContext->script()->proxy()->findOrCreateEventListener(v8::Local<v8::Object>::Cast(value), true, false); if (listener) { if (oldListener) { v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kWorkerContextRequestCacheIndex); } - workerContext->setOnmessage(listener); + workerContext->setOnerror(listener); createHiddenDependency(info.Holder(), value, V8Custom::kWorkerContextRequestCacheIndex); } } @@ -95,7 +93,7 @@ ACCESSOR_SETTER(WorkerContextOnmessage) v8::Handle<v8::Value> SetTimeoutOrInterval(const v8::Arguments& args, bool singleShot) { - WorkerContext* workerContext = V8Proxy::ToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, args.Holder()); + WorkerContext* workerContext = V8DOMWrapper::convertDOMWrapperToNative<WorkerContext>(args.Holder()); int argumentCount = args.Length(); if (argumentCount < 1) @@ -106,7 +104,7 @@ v8::Handle<v8::Value> SetTimeoutOrInterval(const v8::Arguments& args, bool singl int timerId; if (function->IsString()) { - WebCore::String stringFunction = ToWebCoreString(function); + WebCore::String stringFunction = toWebCoreString(function); timerId = DOMTimer::install(workerContext, new ScheduledAction(stringFunction, workerContext->url()), timeout, singleShot); } else if (function->IsFunction()) { size_t paramCount = argumentCount >= 2 ? argumentCount - 2 : 0; @@ -129,7 +127,29 @@ v8::Handle<v8::Value> SetTimeoutOrInterval(const v8::Arguments& args, bool singl CALLBACK_FUNC_DECL(WorkerContextImportScripts) { INC_STATS(L"DOM.WorkerContext.importScripts()"); - notImplemented(); + if (!args.Length()) + return v8::Undefined(); + + String callerURL = V8Proxy::sourceName(); + int callerLine = V8Proxy::sourceLineNumber() + 1; + + Vector<String> urls; + for (int i = 0; i < args.Length(); i++) { + v8::TryCatch tryCatch; + v8::Handle<v8::String> scriptUrl = args[i]->ToString(); + if (tryCatch.HasCaught() || scriptUrl.IsEmpty()) + return v8::Undefined(); + urls.append(toWebCoreString(scriptUrl)); + } + + WorkerContext* workerContext = V8DOMWrapper::convertDOMWrapperToNative<WorkerContext>(args.Holder()); + + ExceptionCode ec = 0; + workerContext->importScripts(urls, callerURL, callerLine, ec); + + if (ec) + return throwError(ec); + return v8::Undefined(); } @@ -139,7 +159,8 @@ CALLBACK_FUNC_DECL(WorkerContextSetTimeout) return SetTimeoutOrInterval(args, true); } -CALLBACK_FUNC_DECL(WorkerContextSetInterval) { +CALLBACK_FUNC_DECL(WorkerContextSetInterval) +{ INC_STATS(L"DOM.WorkerContext.setInterval()"); return SetTimeoutOrInterval(args, false); } @@ -147,7 +168,7 @@ CALLBACK_FUNC_DECL(WorkerContextSetInterval) { CALLBACK_FUNC_DECL(WorkerContextAddEventListener) { INC_STATS(L"DOM.WorkerContext.addEventListener()"); - WorkerContext* workerContext = V8Proxy::ToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, args.Holder()); + WorkerContext* workerContext = V8DOMWrapper::convertDOMWrapperToNative<WorkerContext>(args.Holder()); RefPtr<V8EventListener> listener = workerContext->script()->proxy()->findOrCreateEventListener(v8::Local<v8::Object>::Cast(args[1]), false, false); @@ -164,7 +185,7 @@ CALLBACK_FUNC_DECL(WorkerContextAddEventListener) CALLBACK_FUNC_DECL(WorkerContextRemoveEventListener) { INC_STATS(L"DOM.WorkerContext.removeEventListener()"); - WorkerContext* workerContext = V8Proxy::ToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, args.Holder()); + WorkerContext* workerContext = V8DOMWrapper::convertDOMWrapperToNative<WorkerContext>(args.Holder()); WorkerContextExecutionProxy* proxy = workerContext->script()->proxy(); RefPtr<V8EventListener> listener = proxy->findOrCreateEventListener(v8::Local<v8::Object>::Cast(args[1]), false, true); diff --git a/WebCore/bindings/v8/custom/V8WorkerCustom.cpp b/WebCore/bindings/v8/custom/V8WorkerCustom.cpp index 3edaa8e..32450b8 100755 --- a/WebCore/bindings/v8/custom/V8WorkerCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WorkerCustom.cpp @@ -50,23 +50,17 @@ CALLBACK_FUNC_DECL(WorkerConstructor) { INC_STATS(L"DOM.Worker.Constructor"); - if (!WorkerContextExecutionProxy::isWebWorkersEnabled()) { - return throwError("Worker is not enabled.", V8Proxy::SYNTAX_ERROR); - } - - if (!args.IsConstructCall()) { + if (!args.IsConstructCall()) return throwError("DOM object constructor cannot be called as a function."); - } - if (args.Length() == 0) { - return throwError("Not enough arguments", V8Proxy::SYNTAX_ERROR); - } + if (!args.Length()) + return throwError("Not enough arguments", V8Proxy::SyntaxError); v8::TryCatch tryCatch; v8::Handle<v8::String> scriptUrl = args[0]->ToString(); - if (tryCatch.HasCaught()) { + if (tryCatch.HasCaught()) return throwError(tryCatch.Exception()); - } + if (scriptUrl.IsEmpty()) return v8::Undefined(); @@ -76,38 +70,42 @@ CALLBACK_FUNC_DECL(WorkerConstructor) if (proxy) context = proxy->workerContext(); else { - Frame* frame = V8Proxy::retrieveFrame(); + Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); if (!frame) return v8::Undefined(); context = frame->document(); } // Create the worker object. - // Note: it's OK to let this RefPtr go out of scope because we also call SetDOMWrapper(), which effectively holds a reference to obj. + // Note: it's OK to let this RefPtr go out of scope because we also call setDOMWrapper(), which effectively holds a reference to obj. ExceptionCode ec = 0; RefPtr<Worker> obj = Worker::create(toWebCoreString(scriptUrl), context, ec); + if (ec) + return throwError(ec); // Setup the standard wrapper object internal fields. v8::Handle<v8::Object> wrapperObject = args.Holder(); - V8Proxy::SetDOMWrapper(wrapperObject, V8ClassIndex::WORKER, obj.get()); + V8DOMWrapper::setDOMWrapper(wrapperObject, V8ClassIndex::WORKER, obj.get()); obj->ref(); - V8Proxy::SetJSWrapperForActiveDOMObject(obj.get(), v8::Persistent<v8::Object>::New(wrapperObject)); + V8DOMWrapper::setJSWrapperForActiveDOMObject(obj.get(), v8::Persistent<v8::Object>::New(wrapperObject)); return wrapperObject; } -PassRefPtr<EventListener> getEventListener(Worker* worker, v8::Local<v8::Value> value, bool findOnly) +PassRefPtr<EventListener> getEventListener(Worker* worker, v8::Local<v8::Value> value, bool isAttribute, bool findOnly) { if (worker->scriptExecutionContext()->isWorkerContext()) { WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); ASSERT(workerContextProxy); - return workerContextProxy->findOrCreateObjectEventListener(value, false, findOnly); + return workerContextProxy->findOrCreateObjectEventListener(value, isAttribute, findOnly); } V8Proxy* proxy = V8Proxy::retrieve(worker->scriptExecutionContext()); - if (proxy) - return findOnly ? proxy->FindObjectEventListener(value, false) : proxy->FindOrCreateObjectEventListener(value, false); + if (proxy) { + V8EventListenerList* list = proxy->objectListeners(); + return findOnly ? list->findWrapper(value, isAttribute) : list->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, isAttribute); + } return 0; } @@ -115,7 +113,7 @@ PassRefPtr<EventListener> getEventListener(Worker* worker, v8::Local<v8::Value> ACCESSOR_GETTER(WorkerOnmessage) { INC_STATS(L"DOM.Worker.onmessage._get"); - Worker* worker = V8Proxy::ToNativeObject<Worker>(V8ClassIndex::WORKER, info.Holder()); + Worker* worker = V8DOMWrapper::convertToNativeObject<Worker>(V8ClassIndex::WORKER, info.Holder()); if (worker->onmessage()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(worker->onmessage()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -127,7 +125,7 @@ ACCESSOR_GETTER(WorkerOnmessage) ACCESSOR_SETTER(WorkerOnmessage) { INC_STATS(L"DOM.Worker.onmessage._set"); - Worker* worker = V8Proxy::ToNativeObject<Worker>(V8ClassIndex::WORKER, info.Holder()); + Worker* worker = V8DOMWrapper::convertToNativeObject<Worker>(V8ClassIndex::WORKER, info.Holder()); V8ObjectEventListener* oldListener = static_cast<V8ObjectEventListener*>(worker->onmessage()); if (value->IsNull()) { if (oldListener) { @@ -138,7 +136,7 @@ ACCESSOR_SETTER(WorkerOnmessage) // Clear the listener. worker->setOnmessage(0); } else { - RefPtr<EventListener> listener = getEventListener(worker, value, false); + RefPtr<EventListener> listener = getEventListener(worker, value, true, false); if (listener) { if (oldListener) { v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); @@ -151,78 +149,6 @@ ACCESSOR_SETTER(WorkerOnmessage) } } -ACCESSOR_GETTER(WorkerOnerror) -{ - INC_STATS(L"DOM.Worker.onerror._get"); - Worker* worker = V8Proxy::ToNativeObject<Worker>(V8ClassIndex::WORKER, info.Holder()); - if (worker->onerror()) { - V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(worker->onerror()); - v8::Local<v8::Object> v8Listener = listener->getListenerObject(); - return v8Listener; - } - return v8::Undefined(); -} - -ACCESSOR_SETTER(WorkerOnerror) -{ - INC_STATS(L"DOM.Worker.onerror._set"); - Worker* worker = V8Proxy::ToNativeObject<Worker>(V8ClassIndex::WORKER, info.Holder()); - V8ObjectEventListener* oldListener = static_cast<V8ObjectEventListener*>(worker->onerror()); - if (value->IsNull()) { - if (oldListener) { - v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); - removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kWorkerRequestCacheIndex); - } - - // Clear the listener. - worker->setOnerror(0); - } else { - RefPtr<EventListener> listener = getEventListener(worker, value, false); - if (listener) { - if (oldListener) { - v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject(); - removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kWorkerRequestCacheIndex); - } - - worker->setOnerror(listener); - createHiddenDependency(info.Holder(), value, V8Custom::kWorkerRequestCacheIndex); - } - } -} - -CALLBACK_FUNC_DECL(WorkerAddEventListener) -{ - INC_STATS(L"DOM.Worker.addEventListener()"); - Worker* worker = V8Proxy::ToNativeObject<Worker>(V8ClassIndex::WORKER, args.Holder()); - - RefPtr<EventListener> listener = getEventListener(worker, args[1], false); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - worker->addEventListener(type, listener, useCapture); - - createHiddenDependency(args.Holder(), args[1], V8Custom::kWorkerRequestCacheIndex); - } - return v8::Undefined(); -} - -CALLBACK_FUNC_DECL(WorkerRemoveEventListener) -{ - INC_STATS(L"DOM.Worker.removeEventListener()"); - Worker* worker = V8Proxy::ToNativeObject<Worker>(V8ClassIndex::WORKER, args.Holder()); - - RefPtr<EventListener> listener = getEventListener(worker, args[1], true); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - worker->removeEventListener(type, listener.get(), useCapture); - - removeHiddenDependency(args.Holder(), args[1], V8Custom::kWorkerRequestCacheIndex); - } - - return v8::Undefined(); -} - } // namespace WebCore #endif // ENABLE(WORKERS) diff --git a/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp b/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp index c913c08..02ce8e2 100644 --- a/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp @@ -46,7 +46,7 @@ CALLBACK_FUNC_DECL(XMLHttpRequestConstructor) INC_STATS("DOM.XMLHttpRequest.Constructor"); if (!args.IsConstructCall()) - return throwError("DOM object constructor cannot be called as a function.", V8Proxy::TYPE_ERROR); + return throwError("DOM object constructor cannot be called as a function.", V8Proxy::TypeError); // Expect no parameters. // Allocate a XMLHttpRequest object as its internal field. @@ -55,15 +55,21 @@ CALLBACK_FUNC_DECL(XMLHttpRequestConstructor) WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve(); if (proxy) context = proxy->workerContext(); - else + else { +#endif + Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); + if (!frame) + return throwError("XMLHttpRequest constructor's associated frame is not available", V8Proxy::ReferenceError); + context = frame->document(); +#if ENABLE(WORKERS) + } #endif - context = V8Proxy::retrieveFrame()->document(); RefPtr<XMLHttpRequest> xmlHttpRequest = XMLHttpRequest::create(context); - V8Proxy::SetDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::XMLHTTPREQUEST), xmlHttpRequest.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::XMLHTTPREQUEST), xmlHttpRequest.get()); // Add object to the wrapper map. xmlHttpRequest->ref(); - V8Proxy::SetJSWrapperForActiveDOMObject(xmlHttpRequest.get(), v8::Persistent<v8::Object>::New(args.Holder())); + V8DOMWrapper::setJSWrapperForActiveDOMObject(xmlHttpRequest.get(), v8::Persistent<v8::Object>::New(args.Holder())); return args.Holder(); } diff --git a/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp b/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp index cb80a4f..7204a61 100644 --- a/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp +++ b/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp @@ -44,7 +44,7 @@ namespace WebCore { -PassRefPtr<EventListener> getEventListener(XMLHttpRequest* xmlHttpRequest, v8::Local<v8::Value> value, bool findOnly) +static PassRefPtr<EventListener> getEventListener(XMLHttpRequest* xmlHttpRequest, v8::Local<v8::Value> value, bool findOnly) { #if ENABLE(WORKERS) WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); @@ -53,8 +53,10 @@ PassRefPtr<EventListener> getEventListener(XMLHttpRequest* xmlHttpRequest, v8::L #endif V8Proxy* proxy = V8Proxy::retrieve(xmlHttpRequest->scriptExecutionContext()); - if (proxy) - return findOnly ? proxy->FindObjectEventListener(value, false) : proxy->FindOrCreateObjectEventListener(value, false); + if (proxy) { + V8EventListenerList* list = proxy->objectListeners(); + return findOnly ? list->findWrapper(value, false) : list->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); + } return PassRefPtr<EventListener>(); } @@ -62,7 +64,7 @@ PassRefPtr<EventListener> getEventListener(XMLHttpRequest* xmlHttpRequest, v8::L ACCESSOR_GETTER(XMLHttpRequestOnabort) { INC_STATS("DOM.XMLHttpRequest.onabort._get"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (xmlHttpRequest->onabort()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onabort()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -74,7 +76,7 @@ ACCESSOR_GETTER(XMLHttpRequestOnabort) ACCESSOR_SETTER(XMLHttpRequestOnabort) { INC_STATS("DOM.XMLHttpRequest.onabort._set"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (value->IsNull()) { if (xmlHttpRequest->onabort()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onabort()); @@ -96,7 +98,7 @@ ACCESSOR_SETTER(XMLHttpRequestOnabort) ACCESSOR_GETTER(XMLHttpRequestOnerror) { INC_STATS("DOM.XMLHttpRequest.onerror._get"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (xmlHttpRequest->onerror()) { RefPtr<V8ObjectEventListener> listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onerror()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -108,7 +110,7 @@ ACCESSOR_GETTER(XMLHttpRequestOnerror) ACCESSOR_SETTER(XMLHttpRequestOnerror) { INC_STATS("DOM.XMLHttpRequest.onerror._set"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (value->IsNull()) { if (xmlHttpRequest->onerror()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onerror()); @@ -130,7 +132,7 @@ ACCESSOR_SETTER(XMLHttpRequestOnerror) ACCESSOR_GETTER(XMLHttpRequestOnload) { INC_STATS("DOM.XMLHttpRequest.onload._get"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (xmlHttpRequest->onload()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onload()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -142,7 +144,7 @@ ACCESSOR_GETTER(XMLHttpRequestOnload) ACCESSOR_SETTER(XMLHttpRequestOnload) { INC_STATS("DOM.XMLHttpRequest.onload._set"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (value->IsNull()) { if (xmlHttpRequest->onload()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onload()); @@ -164,7 +166,7 @@ ACCESSOR_SETTER(XMLHttpRequestOnload) ACCESSOR_GETTER(XMLHttpRequestOnloadstart) { INC_STATS("DOM.XMLHttpRequest.onloadstart._get"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (xmlHttpRequest->onloadstart()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onloadstart()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -176,7 +178,7 @@ ACCESSOR_GETTER(XMLHttpRequestOnloadstart) ACCESSOR_SETTER(XMLHttpRequestOnloadstart) { INC_STATS("DOM.XMLHttpRequest.onloadstart._set"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (value->IsNull()) { if (xmlHttpRequest->onloadstart()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onloadstart()); @@ -198,7 +200,7 @@ ACCESSOR_SETTER(XMLHttpRequestOnloadstart) ACCESSOR_GETTER(XMLHttpRequestOnprogress) { INC_STATS("DOM.XMLHttpRequest.onprogress._get"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (xmlHttpRequest->onprogress()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onprogress()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -210,7 +212,7 @@ ACCESSOR_GETTER(XMLHttpRequestOnprogress) ACCESSOR_SETTER(XMLHttpRequestOnprogress) { INC_STATS("DOM.XMLHttpRequest.onprogress._set"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (value->IsNull()) { if (xmlHttpRequest->onprogress()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onprogress()); @@ -232,7 +234,7 @@ ACCESSOR_SETTER(XMLHttpRequestOnprogress) ACCESSOR_GETTER(XMLHttpRequestOnreadystatechange) { INC_STATS("DOM.XMLHttpRequest.onreadystatechange._get"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (xmlHttpRequest->onreadystatechange()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onreadystatechange()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -244,7 +246,7 @@ ACCESSOR_GETTER(XMLHttpRequestOnreadystatechange) ACCESSOR_SETTER(XMLHttpRequestOnreadystatechange) { INC_STATS("DOM.XMLHttpRequest.onreadystatechange._set"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); if (value->IsNull()) { if (xmlHttpRequest->onreadystatechange()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onreadystatechange()); @@ -268,14 +270,14 @@ ACCESSOR_GETTER(XMLHttpRequestResponseText) // FIXME: This is only needed because webkit set this getter as custom. // So we need a custom method to avoid forking the IDL file. INC_STATS("DOM.XMLHttpRequest.responsetext._get"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder()); return v8StringOrNull(xmlHttpRequest->responseText()); } CALLBACK_FUNC_DECL(XMLHttpRequestAddEventListener) { INC_STATS("DOM.XMLHttpRequest.addEventListener()"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); RefPtr<EventListener> listener = getEventListener(xmlHttpRequest, args[1], false); if (listener) { @@ -291,7 +293,7 @@ CALLBACK_FUNC_DECL(XMLHttpRequestAddEventListener) CALLBACK_FUNC_DECL(XMLHttpRequestRemoveEventListener) { INC_STATS("DOM.XMLHttpRequest.removeEventListener()"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); RefPtr<EventListener> listener = getEventListener(xmlHttpRequest, args[1], true); if (listener) { @@ -315,9 +317,9 @@ CALLBACK_FUNC_DECL(XMLHttpRequestOpen) // open(method, url, async, user, passwd) if (args.Length() < 2) - return throwError("Not enough arguments", V8Proxy::SYNTAX_ERROR); + return throwError("Not enough arguments", V8Proxy::SyntaxError); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); String method = toWebCoreString(args[0]); String urlstring = toWebCoreString(args[1]); @@ -345,10 +347,10 @@ CALLBACK_FUNC_DECL(XMLHttpRequestOpen) ExceptionCode ec = 0; String user, passwd; if (args.Length() >= 4 && !args[3]->IsUndefined()) { - user = valueToStringWithNullCheck(args[3]); + user = toWebCoreStringWithNullCheck(args[3]); if (args.Length() >= 5 && !args[4]->IsUndefined()) { - passwd = valueToStringWithNullCheck(args[4]); + passwd = toWebCoreStringWithNullCheck(args[4]); xmlHttpRequest->open(method, url, async, user, passwd, ec); } else xmlHttpRequest->open(method, url, async, user, ec); @@ -370,7 +372,7 @@ static bool IsDocumentType(v8::Handle<v8::Value> value) CALLBACK_FUNC_DECL(XMLHttpRequestSend) { INC_STATS("DOM.XMLHttpRequest.send()"); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); ExceptionCode ec = 0; if (args.Length() < 1) @@ -380,11 +382,11 @@ CALLBACK_FUNC_DECL(XMLHttpRequestSend) // FIXME: upstream handles "File" objects too. if (IsDocumentType(arg)) { v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); - Document* document = V8Proxy::DOMWrapperToNode<Document>(object); + Document* document = V8DOMWrapper::convertDOMWrapperToNode<Document>(object); ASSERT(document); xmlHttpRequest->send(document, ec); } else - xmlHttpRequest->send(valueToStringWithNullCheck(arg), ec); + xmlHttpRequest->send(toWebCoreStringWithNullCheck(arg), ec); } if (ec) @@ -396,9 +398,9 @@ CALLBACK_FUNC_DECL(XMLHttpRequestSend) CALLBACK_FUNC_DECL(XMLHttpRequestSetRequestHeader) { INC_STATS("DOM.XMLHttpRequest.setRequestHeader()"); if (args.Length() < 2) - return throwError("Not enough arguments", V8Proxy::SYNTAX_ERROR); + return throwError("Not enough arguments", V8Proxy::SyntaxError); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); ExceptionCode ec = 0; String header = toWebCoreString(args[0]); String value = toWebCoreString(args[1]); @@ -412,9 +414,9 @@ CALLBACK_FUNC_DECL(XMLHttpRequestGetResponseHeader) { INC_STATS("DOM.XMLHttpRequest.getResponseHeader()"); if (args.Length() < 1) - return throwError("Not enough arguments", V8Proxy::SYNTAX_ERROR); + return throwError("Not enough arguments", V8Proxy::SyntaxError); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); ExceptionCode ec = 0; String header = toWebCoreString(args[0]); String result = xmlHttpRequest->getResponseHeader(header, ec); @@ -427,9 +429,9 @@ CALLBACK_FUNC_DECL(XMLHttpRequestOverrideMimeType) { INC_STATS("DOM.XMLHttpRequest.overrideMimeType()"); if (args.Length() < 1) - return throwError("Not enough arguments", V8Proxy::SYNTAX_ERROR); + return throwError("Not enough arguments", V8Proxy::SyntaxError); - XMLHttpRequest* xmlHttpRequest = V8Proxy::ToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); + XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder()); String value = toWebCoreString(args[0]); xmlHttpRequest->overrideMimeType(value); return v8::Undefined(); diff --git a/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp b/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp index 7afa82c..bbc69dd 100644 --- a/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp +++ b/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp @@ -46,7 +46,7 @@ namespace WebCore { ACCESSOR_GETTER(XMLHttpRequestUploadOnabort) { INC_STATS("DOM.XMLHttpRequestUpload.onabort._get"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); if (xmlHttpRequestUpload->onabort()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onabort()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -58,7 +58,7 @@ ACCESSOR_GETTER(XMLHttpRequestUploadOnabort) ACCESSOR_SETTER(XMLHttpRequestUploadOnabort) { INC_STATS("DOM.XMLHttpRequestUpload.onabort._set"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); if (value->IsNull()) { if (xmlHttpRequestUpload->onabort()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onabort()); @@ -74,7 +74,7 @@ ACCESSOR_SETTER(XMLHttpRequestUploadOnabort) if (!proxy) return; - RefPtr<EventListener> listener = proxy->FindOrCreateObjectEventListener(value, false); + RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); if (listener) { xmlHttpRequestUpload->setOnabort(listener); createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex); @@ -85,7 +85,7 @@ ACCESSOR_SETTER(XMLHttpRequestUploadOnabort) ACCESSOR_GETTER(XMLHttpRequestUploadOnerror) { INC_STATS("DOM.XMLHttpRequestUpload.onerror._get"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); if (xmlHttpRequestUpload->onerror()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onerror()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -97,7 +97,7 @@ ACCESSOR_GETTER(XMLHttpRequestUploadOnerror) ACCESSOR_SETTER(XMLHttpRequestUploadOnerror) { INC_STATS("DOM.XMLHttpRequestUpload.onerror._set"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); if (value->IsNull()) { if (xmlHttpRequestUpload->onerror()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onerror()); @@ -113,7 +113,7 @@ ACCESSOR_SETTER(XMLHttpRequestUploadOnerror) if (!proxy) return; - RefPtr<EventListener> listener = proxy->FindOrCreateObjectEventListener(value, false); + RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); if (listener) { xmlHttpRequestUpload->setOnerror(listener); createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex); @@ -124,7 +124,7 @@ ACCESSOR_SETTER(XMLHttpRequestUploadOnerror) ACCESSOR_GETTER(XMLHttpRequestUploadOnload) { INC_STATS("DOM.XMLHttpRequestUpload.onload._get"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); if (xmlHttpRequestUpload->onload()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onload()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -136,7 +136,7 @@ ACCESSOR_GETTER(XMLHttpRequestUploadOnload) ACCESSOR_SETTER(XMLHttpRequestUploadOnload) { INC_STATS("DOM.XMLHttpRequestUpload.onload._set"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); if (value->IsNull()) { if (xmlHttpRequestUpload->onload()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onload()); @@ -152,7 +152,7 @@ ACCESSOR_SETTER(XMLHttpRequestUploadOnload) if (!proxy) return; - RefPtr<EventListener> listener = proxy->FindOrCreateObjectEventListener(value, false); + RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); if (listener) { xmlHttpRequestUpload->setOnload(listener); createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex); @@ -163,7 +163,7 @@ ACCESSOR_SETTER(XMLHttpRequestUploadOnload) ACCESSOR_GETTER(XMLHttpRequestUploadOnloadstart) { INC_STATS("DOM.XMLHttpRequestUpload.onloadstart._get"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); if (xmlHttpRequestUpload->onloadstart()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onloadstart()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -175,7 +175,7 @@ ACCESSOR_GETTER(XMLHttpRequestUploadOnloadstart) ACCESSOR_SETTER(XMLHttpRequestUploadOnloadstart) { INC_STATS("DOM.XMLHttpRequestUpload.onloadstart._set"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); if (value->IsNull()) { if (xmlHttpRequestUpload->onloadstart()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onloadstart()); @@ -191,7 +191,7 @@ ACCESSOR_SETTER(XMLHttpRequestUploadOnloadstart) if (!proxy) return; - RefPtr<EventListener> listener = proxy->FindOrCreateObjectEventListener(value, false); + RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); if (listener) { xmlHttpRequestUpload->setOnloadstart(listener); createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex); @@ -202,7 +202,7 @@ ACCESSOR_SETTER(XMLHttpRequestUploadOnloadstart) ACCESSOR_GETTER(XMLHttpRequestUploadOnprogress) { INC_STATS("DOM.XMLHttpRequestUpload.onprogress._get"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); if (xmlHttpRequestUpload->onprogress()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onprogress()); v8::Local<v8::Object> v8Listener = listener->getListenerObject(); @@ -214,7 +214,7 @@ ACCESSOR_GETTER(XMLHttpRequestUploadOnprogress) ACCESSOR_SETTER(XMLHttpRequestUploadOnprogress) { INC_STATS("DOM.XMLHttpRequestUpload.onprogress._set"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder()); if (value->IsNull()) { if (xmlHttpRequestUpload->onprogress()) { V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onprogress()); @@ -230,7 +230,7 @@ ACCESSOR_SETTER(XMLHttpRequestUploadOnprogress) if (!proxy) return; - RefPtr<EventListener> listener = proxy->FindOrCreateObjectEventListener(value, false); + RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false); if (listener) { xmlHttpRequestUpload->setOnprogress(listener); createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex); @@ -241,14 +241,14 @@ ACCESSOR_SETTER(XMLHttpRequestUploadOnprogress) CALLBACK_FUNC_DECL(XMLHttpRequestUploadAddEventListener) { INC_STATS("DOM.XMLHttpRequestUpload.addEventListener()"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, args.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, args.Holder()); XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest(); V8Proxy* proxy = V8Proxy::retrieve(xmlHttpRequest->scriptExecutionContext()); if (!proxy) return v8::Undefined(); - RefPtr<EventListener> listener = proxy->FindOrCreateObjectEventListener(args[1], false); + RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), args[1], false); if (listener) { String type = toWebCoreString(args[0]); bool useCapture = args[2]->BooleanValue(); @@ -262,14 +262,14 @@ CALLBACK_FUNC_DECL(XMLHttpRequestUploadAddEventListener) CALLBACK_FUNC_DECL(XMLHttpRequestUploadRemoveEventListener) { INC_STATS("DOM.XMLHttpRequestUpload.removeEventListener()"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8Proxy::ToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, args.Holder()); + XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, args.Holder()); XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest(); V8Proxy* proxy = V8Proxy::retrieve(xmlHttpRequest->scriptExecutionContext()); if (!proxy) return v8::Undefined(); // Probably leaked. - RefPtr<EventListener> listener = proxy->FindObjectEventListener(args[1], false); + RefPtr<EventListener> listener = proxy->objectListeners()->findWrapper(args[1], false); if (listener) { String type = toWebCoreString(args[0]); diff --git a/WebCore/bindings/v8/custom/V8XMLSerializerConstructor.cpp b/WebCore/bindings/v8/custom/V8XMLSerializerConstructor.cpp index 7b20293..dd1c3ad 100644 --- a/WebCore/bindings/v8/custom/V8XMLSerializerConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8XMLSerializerConstructor.cpp @@ -39,7 +39,7 @@ namespace WebCore { CALLBACK_FUNC_DECL(XMLSerializerConstructor) { INC_STATS("DOM.XMLSerializer.Constructor"); - return V8Proxy::ConstructDOMObject<V8ClassIndex::XMLSERIALIZER, XMLSerializer>(args); + return V8Proxy::constructDOMObject<V8ClassIndex::XMLSERIALIZER, XMLSerializer>(args); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8XPathEvaluatorConstructor.cpp b/WebCore/bindings/v8/custom/V8XPathEvaluatorConstructor.cpp index 84d75db..69a8635 100644 --- a/WebCore/bindings/v8/custom/V8XPathEvaluatorConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8XPathEvaluatorConstructor.cpp @@ -39,7 +39,7 @@ namespace WebCore { CALLBACK_FUNC_DECL(XPathEvaluatorConstructor) { INC_STATS("DOM.XPathEvaluator.Constructor"); - return V8Proxy::ConstructDOMObject<V8ClassIndex::XPATHEVALUATOR, XPathEvaluator>(args); + return V8Proxy::constructDOMObject<V8ClassIndex::XPATHEVALUATOR, XPathEvaluator>(args); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8XSLTProcessorCustom.cpp b/WebCore/bindings/v8/custom/V8XSLTProcessorCustom.cpp index d470f84..1ad7d4a 100644 --- a/WebCore/bindings/v8/custom/V8XSLTProcessorCustom.cpp +++ b/WebCore/bindings/v8/custom/V8XSLTProcessorCustom.cpp @@ -48,7 +48,7 @@ namespace WebCore { CALLBACK_FUNC_DECL(XSLTProcessorConstructor) { INC_STATS("DOM.XSLTProcessor.Constructor"); - return V8Proxy::ConstructDOMObject<V8ClassIndex::XSLTPROCESSOR, XSLTProcessor>(args); + return V8Proxy::constructDOMObject<V8ClassIndex::XSLTPROCESSOR, XSLTProcessor>(args); } @@ -58,9 +58,9 @@ CALLBACK_FUNC_DECL(XSLTProcessorImportStylesheet) if (!V8Node::HasInstance(args[0])) return v8::Undefined(); - XSLTProcessor* imp = V8Proxy::ToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); + XSLTProcessor* imp = V8DOMWrapper::convertToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); - Node* node = V8Proxy::DOMWrapperToNode<Node>(args[0]); + Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])); imp->importStylesheet(node); return v8::Undefined(); } @@ -72,12 +72,12 @@ CALLBACK_FUNC_DECL(XSLTProcessorTransformToFragment) if (!V8Node::HasInstance(args[0]) || !V8Document::HasInstance(args[1])) return v8::Undefined(); - XSLTProcessor* imp = V8Proxy::ToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); + XSLTProcessor* imp = V8DOMWrapper::convertToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); - Node* source = V8Proxy::DOMWrapperToNode<Node>(args[0]); - Document* owner = V8Proxy::DOMWrapperToNode<Document>(args[1]); + Node* source = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])); + Document* owner = V8DOMWrapper::convertDOMWrapperToNode<Document>(v8::Handle<v8::Object>::Cast(args[1])); RefPtr<DocumentFragment> result = imp->transformToFragment(source, owner); - return V8Proxy::NodeToV8Object(result.get()); + return V8DOMWrapper::convertNodeToV8Object(result.release()); } @@ -88,9 +88,9 @@ CALLBACK_FUNC_DECL(XSLTProcessorTransformToDocument) if (!V8Node::HasInstance(args[0])) return v8::Undefined(); - XSLTProcessor* imp = V8Proxy::ToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); + XSLTProcessor* imp = V8DOMWrapper::convertToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); - Node* source = V8Proxy::DOMWrapperToNode<Node>(args[0]); + Node* source = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])); if (!source) return v8::Undefined(); @@ -98,7 +98,7 @@ CALLBACK_FUNC_DECL(XSLTProcessorTransformToDocument) if (!result) return v8::Undefined(); - return V8Proxy::NodeToV8Object(result.get()); + return V8DOMWrapper::convertNodeToV8Object(result.release()); } @@ -108,7 +108,7 @@ CALLBACK_FUNC_DECL(XSLTProcessorSetParameter) if (isUndefinedOrNull(args[1]) || isUndefinedOrNull(args[2])) return v8::Undefined(); - XSLTProcessor* imp = V8Proxy::ToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); + XSLTProcessor* imp = V8DOMWrapper::convertToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); String namespaceURI = toWebCoreString(args[0]); String localName = toWebCoreString(args[1]); @@ -125,7 +125,7 @@ CALLBACK_FUNC_DECL(XSLTProcessorGetParameter) if (isUndefinedOrNull(args[1])) return v8::Undefined(); - XSLTProcessor* imp = V8Proxy::ToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); + XSLTProcessor* imp = V8DOMWrapper::convertToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); String namespaceURI = toWebCoreString(args[0]); String localName = toWebCoreString(args[1]); @@ -142,7 +142,7 @@ CALLBACK_FUNC_DECL(XSLTProcessorRemoveParameter) if (isUndefinedOrNull(args[1])) return v8::Undefined(); - XSLTProcessor* imp = V8Proxy::ToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); + XSLTProcessor* imp = V8DOMWrapper::convertToNativeObject<XSLTProcessor>(V8ClassIndex::XSLTPROCESSOR, args.Holder()); String namespaceURI = toWebCoreString(args[0]); String localName = toWebCoreString(args[1]); diff --git a/WebCore/bindings/v8/npruntime.cpp b/WebCore/bindings/v8/npruntime.cpp new file mode 100644 index 0000000..64a1927 --- /dev/null +++ b/WebCore/bindings/v8/npruntime.cpp @@ -0,0 +1,442 @@ +/* + * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2007-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 APPLE COMPUTER, 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 COMPUTER, 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 "NPV8Object.h" +#include "npruntime_impl.h" +#include "npruntime_priv.h" +#include "V8NPObject.h" + +#include <wtf/HashMap.h> +#include <wtf/HashSet.h> +#include <wtf/Assertions.h> + +// FIXME: Consider removing locks if we're singlethreaded already. +// The static initializer here should work okay, but we want to avoid +// static initialization in general. + +namespace { + +// We use StringKey here as the key-type to avoid a string copy to +// construct the map key and for faster comparisons than strcmp. +class StringKey { +public: + explicit StringKey(const char* str) : m_string(str), m_length(strlen(str)) { } + StringKey() : m_string(0), m_length(0) { } + explicit StringKey(WTF::HashTableDeletedValueType) : m_string(hashTableDeletedValue()), m_length(0) { } + + StringKey& operator=(const StringKey& other) + { + this->m_string = other.m_string; + this->m_length = other.m_length; + return *this; + } + + bool isHashTableDeletedValue() const + { + return m_string == hashTableDeletedValue(); + } + + const char* m_string; + size_t m_length; + +private: + const char* hashTableDeletedValue() const + { + return reinterpret_cast<const char*>(-1); + } +}; + +inline bool operator==(const StringKey& x, const StringKey& y) +{ + if (x.m_length != y.m_length) + return false; + if (x.m_string == y.m_string) + return true; + + ASSERT(!x.isHashTableDeletedValue() && !y.isHashTableDeletedValue()); + return !memcmp(x.m_string, y.m_string, y.m_length); +} + +// Implement WTF::DefaultHash<StringKey>::Hash interface. +struct StringKeyHash { + static unsigned hash(const StringKey& key) + { + // Compute string hash. + unsigned hash = 0; + size_t len = key.m_length; + const char* str = key.m_string; + for (size_t i = 0; i < len; i++) { + char c = str[i]; + hash += c; + hash += (hash << 10); + hash ^= (hash >> 6); + } + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + if (hash == 0) + hash = 27; + return hash; + } + + static bool equal(const StringKey& x, const StringKey& y) + { + return x == y; + } + + static const bool safeToCompareToEmptyOrDeleted = true; +}; + +} // namespace + +// Implement HashTraits<StringKey> +struct StringKeyHashTraits : WTF::GenericHashTraits<StringKey> { + static void constructDeletedValue(StringKey& slot) + { + new (&slot) StringKey(WTF::HashTableDeletedValue); + } + + static bool isDeletedValue(const StringKey& value) + { + return value.isHashTableDeletedValue(); + } +}; + +typedef WTF::HashMap<StringKey, PrivateIdentifier*, StringKeyHash, StringKeyHashTraits> StringIdentifierMap; + +static StringIdentifierMap* getStringIdentifierMap() +{ + static StringIdentifierMap* stringIdentifierMap = 0; + if (!stringIdentifierMap) + stringIdentifierMap = new StringIdentifierMap(); + return stringIdentifierMap; +} + +typedef WTF::HashMap<int, PrivateIdentifier*> IntIdentifierMap; + +static IntIdentifierMap* getIntIdentifierMap() +{ + static IntIdentifierMap* intIdentifierMap = 0; + if (!intIdentifierMap) + intIdentifierMap = new IntIdentifierMap(); + return intIdentifierMap; +} + +extern "C" { + +NPIdentifier _NPN_GetStringIdentifier(const NPUTF8* name) +{ + ASSERT(name); + + if (name) { + + StringKey key(name); + StringIdentifierMap* identMap = getStringIdentifierMap(); + StringIdentifierMap::iterator iter = identMap->find(key); + if (iter != identMap->end()) + return static_cast<NPIdentifier>(iter->second); + + size_t nameLen = key.m_length; + + // We never release identifiers, so this dictionary will grow. + PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(malloc(sizeof(PrivateIdentifier) + nameLen + 1)); + char* nameStorage = reinterpret_cast<char*>(identifier + 1); + memcpy(nameStorage, name, nameLen + 1); + identifier->isString = true; + identifier->value.string = reinterpret_cast<NPUTF8*>(nameStorage); + key.m_string = nameStorage; + identMap->set(key, identifier); + return (NPIdentifier)identifier; + } + + return 0; +} + +void _NPN_GetStringIdentifiers(const NPUTF8** names, int32_t nameCount, NPIdentifier* identifiers) +{ + ASSERT(names); + ASSERT(identifiers); + + if (names && identifiers) { + for (int i = 0; i < nameCount; i++) + identifiers[i] = _NPN_GetStringIdentifier(names[i]); + } +} + +NPIdentifier _NPN_GetIntIdentifier(int32_t intId) +{ + // Special case for -1 and 0, both cannot be used as key in HashMap. + if (!intId || intId == -1) { + static PrivateIdentifier* minusOneOrZeroIds[2]; + PrivateIdentifier* id = minusOneOrZeroIds[intId + 1]; + if (!id) { + id = reinterpret_cast<PrivateIdentifier*>(malloc(sizeof(PrivateIdentifier))); + id->isString = false; + id->value.number = intId; + minusOneOrZeroIds[intId + 1] = id; + } + return (NPIdentifier) id; + } + + IntIdentifierMap* identMap = getIntIdentifierMap(); + IntIdentifierMap::iterator iter = identMap->find(intId); + if (iter != identMap->end()) + return static_cast<NPIdentifier>(iter->second); + + // We never release identifiers, so this dictionary will grow. + PrivateIdentifier* identifier = reinterpret_cast<PrivateIdentifier*>(malloc(sizeof(PrivateIdentifier))); + identifier->isString = false; + identifier->value.number = intId; + identMap->set(intId, identifier); + return (NPIdentifier)identifier; +} + +bool _NPN_IdentifierIsString(NPIdentifier identifier) +{ + PrivateIdentifier* privateIdentifier = reinterpret_cast<PrivateIdentifier*>(identifier); + return privateIdentifier->isString; +} + +NPUTF8 *_NPN_UTF8FromIdentifier(NPIdentifier identifier) +{ + PrivateIdentifier* privateIdentifier = reinterpret_cast<PrivateIdentifier*>(identifier); + if (!privateIdentifier->isString || !privateIdentifier->value.string) + return 0; + + return (NPUTF8*) strdup(privateIdentifier->value.string); +} + +int32_t _NPN_IntFromIdentifier(NPIdentifier identifier) +{ + PrivateIdentifier* privateIdentifier = reinterpret_cast<PrivateIdentifier*>(identifier); + if (privateIdentifier->isString) + return 0; + return privateIdentifier->value.number; +} + +void _NPN_ReleaseVariantValue(NPVariant* variant) +{ + ASSERT(variant); + + if (variant->type == NPVariantType_Object) { + _NPN_ReleaseObject(variant->value.objectValue); + variant->value.objectValue = 0; + } else if (variant->type == NPVariantType_String) { + free((void*)variant->value.stringValue.UTF8Characters); + variant->value.stringValue.UTF8Characters = 0; + variant->value.stringValue.UTF8Length = 0; + } + + variant->type = NPVariantType_Void; +} + +NPObject *_NPN_CreateObject(NPP npp, NPClass* npClass) +{ + ASSERT(npClass); + + if (npClass) { + NPObject* npObject; + if (npClass->allocate != 0) + npObject = npClass->allocate(npp, npClass); + else + npObject = reinterpret_cast<NPObject*>(malloc(sizeof(NPObject))); + + npObject->_class = npClass; + npObject->referenceCount = 1; + return npObject; + } + + return 0; +} + +NPObject* _NPN_RetainObject(NPObject* npObject) +{ + ASSERT(npObject); + ASSERT(npObject->referenceCount > 0); + + if (npObject) + npObject->referenceCount++; + + return npObject; +} + +// _NPN_DeallocateObject actually deletes the object. Technically, +// callers should use _NPN_ReleaseObject. Webkit exposes this function +// to kill objects which plugins may not have properly released. +void _NPN_DeallocateObject(NPObject* npObject) +{ + ASSERT(npObject); + ASSERT(npObject->referenceCount >= 0); + + if (npObject) { + // NPObjects that remain in pure C++ may never have wrappers. + // Hence, if it's not already alive, don't unregister it. + // If it is alive, unregister it as the *last* thing we do + // so that it can do as much cleanup as possible on its own. + if (_NPN_IsAlive(npObject)) + _NPN_UnregisterObject(npObject); + + npObject->referenceCount = -1; + if (npObject->_class->deallocate) + npObject->_class->deallocate(npObject); + else + free(npObject); + } +} + +void _NPN_ReleaseObject(NPObject* npObject) +{ + ASSERT(npObject); + ASSERT(npObject->referenceCount >= 1); + + if (npObject && npObject->referenceCount >= 1) { + if (!--npObject->referenceCount) + _NPN_DeallocateObject(npObject); + } +} + +void _NPN_InitializeVariantWithStringCopy(NPVariant* variant, const NPString* value) +{ + variant->type = NPVariantType_String; + variant->value.stringValue.UTF8Length = value->UTF8Length; + variant->value.stringValue.UTF8Characters = reinterpret_cast<NPUTF8*>(malloc(sizeof(NPUTF8) * value->UTF8Length)); + memcpy((void*)variant->value.stringValue.UTF8Characters, value->UTF8Characters, sizeof(NPUTF8) * value->UTF8Length); +} + + +// NPN_Registry +// +// The registry is designed for quick lookup of NPObjects. +// JS needs to be able to quickly lookup a given NPObject to determine +// if it is alive or not. +// The browser needs to be able to quickly lookup all NPObjects which are +// "owned" by an object. +// +// The liveObjectMap is a hash table of all live objects to their owner +// objects. Presence in this table is used primarily to determine if +// objects are live or not. +// +// The rootObjectMap is a hash table of root objects to a set of +// objects that should be deactivated in sync with the root. A +// root is defined as a top-level owner object. This is used on +// Frame teardown to deactivate all objects associated +// with a particular plugin. + +typedef WTF::HashSet<NPObject*> NPObjectSet; +typedef WTF::HashMap<NPObject*, NPObject*> NPObjectMap; +typedef WTF::HashMap<NPObject*, NPObjectSet*> NPRootObjectMap; + +// A map of live NPObjects with pointers to their Roots. +NPObjectMap liveObjectMap; + +// A map of the root objects and the list of NPObjects +// associated with that object. +NPRootObjectMap rootObjectMap; + +void _NPN_RegisterObject(NPObject* npObject, NPObject* owner) +{ + ASSERT(npObject); + + // Check if already registered. + if (liveObjectMap.find(npObject) != liveObjectMap.end()) + return; + + if (!owner) { + // Registering a new owner object. + ASSERT(rootObjectMap.find(npObject) == rootObjectMap.end()); + rootObjectMap.set(npObject, new NPObjectSet()); + } else { + // Always associate this object with it's top-most parent. + // Since we always flatten, we only have to look up one level. + NPObjectMap::iterator ownerEntry = liveObjectMap.find(owner); + NPObject* parent = 0; + if (liveObjectMap.end() != ownerEntry) + parent = ownerEntry->second; + + if (parent) + owner = parent; + ASSERT(rootObjectMap.find(npObject) == rootObjectMap.end()); + if (rootObjectMap.find(owner) != rootObjectMap.end()) + rootObjectMap.get(owner)->add(npObject); + } + + ASSERT(liveObjectMap.find(npObject) == liveObjectMap.end()); + liveObjectMap.set(npObject, owner); +} + +void _NPN_UnregisterObject(NPObject* npObject) +{ + ASSERT(npObject); + ASSERT(liveObjectMap.find(npObject) != liveObjectMap.end()); + + NPObject* owner = 0; + if (liveObjectMap.find(npObject) != liveObjectMap.end()) + owner = liveObjectMap.find(npObject)->second; + + if (!owner) { + // Unregistering a owner object; also unregister it's descendants. + ASSERT(rootObjectMap.find(npObject) != rootObjectMap.end()); + NPObjectSet* set = rootObjectMap.get(npObject); + while (set->size() > 0) { +#ifndef NDEBUG + int size = set->size(); +#endif + NPObject* sub_object = *(set->begin()); + // The sub-object should not be a owner! + ASSERT(rootObjectMap.find(sub_object) == rootObjectMap.end()); + + // First, unregister the object. + set->remove(sub_object); + liveObjectMap.remove(sub_object); + + // Remove the JS references to the object. + forgetV8ObjectForNPObject(sub_object); + + ASSERT(set->size() < size); + } + delete set; + rootObjectMap.remove(npObject); + } else { + NPRootObjectMap::iterator ownerEntry = rootObjectMap.find(owner); + if (ownerEntry != rootObjectMap.end()) { + NPObjectSet* list = ownerEntry->second; + ASSERT(list->find(npObject) != list->end()); + list->remove(npObject); + } + } + + liveObjectMap.remove(npObject); + forgetV8ObjectForNPObject(npObject); +} + +bool _NPN_IsAlive(NPObject* npObject) +{ + return liveObjectMap.find(npObject) != liveObjectMap.end(); +} + +} // extern "C" diff --git a/WebCore/bindings/v8/npruntime_impl.h b/WebCore/bindings/v8/npruntime_impl.h new file mode 100644 index 0000000..31c0f42 --- /dev/null +++ b/WebCore/bindings/v8/npruntime_impl.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2008, 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: + * + * * 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 npruntime_impl_h +#define npruntime_impl_h + +#include "bindings/npruntime.h" + +// This file exists to support WebCore, which expects to be able to call upon +// portions of the NPRuntime implementation. + +#ifdef __cplusplus +extern "C" { +#endif + +NPIdentifier _NPN_GetStringIdentifier(const NPUTF8* name); +void _NPN_GetStringIdentifiers(const NPUTF8** names, int32_t nameCount, NPIdentifier*); +NPIdentifier _NPN_GetIntIdentifier(int32_t intId); +bool _NPN_IdentifierIsString(NPIdentifier); +NPUTF8 *_NPN_UTF8FromIdentifier(NPIdentifier); +int32_t _NPN_IntFromIdentifier(NPIdentifier); +void _NPN_ReleaseVariantValue(NPVariant*); +NPObject *_NPN_CreateObject(NPP, NPClass*); +NPObject* _NPN_RetainObject(NPObject*); +void _NPN_ReleaseObject(NPObject*); +bool _NPN_Invoke(NPP, NPObject*, NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result); +bool _NPN_InvokeDefault(NPP, NPObject*, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result); +bool _NPN_Evaluate(NPP, NPObject*, NPString* npScript, NPVariant* result); +bool _NPN_EvaluateHelper(NPP, bool popupsAllowed, NPObject*, NPString* npScript, NPVariant* result); +bool _NPN_GetProperty(NPP, NPObject*, NPIdentifier propertyName, NPVariant* result); +bool _NPN_SetProperty(NPP, NPObject*, NPIdentifier propertyName, const NPVariant* value); +bool _NPN_RemoveProperty(NPP, NPObject*, NPIdentifier propertyName); +bool _NPN_HasProperty(NPP, NPObject*, NPIdentifier propertyName); +bool _NPN_HasMethod(NPP, NPObject*, NPIdentifier methodName); +void _NPN_SetException(NPObject*, const NPUTF8 *message); +bool _NPN_Enumerate(NPP, NPObject*, NPIdentifier**, uint32_t* count); +bool _NPN_Construct(NPP, NPObject*, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif diff --git a/WebCore/bindings/v8/npruntime_internal.h b/WebCore/bindings/v8/npruntime_internal.h new file mode 100644 index 0000000..75bf2b0 --- /dev/null +++ b/WebCore/bindings/v8/npruntime_internal.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2007 Collabora, Ltd. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * This is a internal include header for npapi.h + * + * Some of the #defines which are in X11 headers conflict with type and enum + * names in JavaScriptCore and WebCore + * This header #undefs those defines to fix the conflicts + * If you need to include npapi.h or npruntime.h when building on X11, + * include this file instead of the actual npapi.h or npruntime.h + */ + +#include "npapi.h" +#include "npruntime.h" +#include "npfunctions.h" + +#ifdef XP_UNIX + #include <X11/Xresource.h> + + #undef None + #undef Above + #undef Below + #undef Auto + #undef Complex + #undef Status +#endif diff --git a/WebCore/bindings/v8/npruntime_priv.h b/WebCore/bindings/v8/npruntime_priv.h new file mode 100644 index 0000000..3887758 --- /dev/null +++ b/WebCore/bindings/v8/npruntime_priv.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2003, 2006 Apple Computer, 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 COMPUTER, 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 COMPUTER, 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 npruntime_priv_h +#define npruntime_priv_h + +#include "third_party/npapi/bindings/npruntime.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + _NPN_InitializeVariantWithStringCopy() will copy string data. The string data + will be deallocated by calls to NPReleaseVariantValue(). +*/ +void _NPN_InitializeVariantWithStringCopy(NPVariant*, const NPString*); +void _NPN_DeallocateObject(NPObject*); + +// The following routines allow the browser to aggressively cleanup NPObjects +// on a per plugin basis. All NPObjects used through the NPRuntime API should +// be "registered" while they are alive. After an object has been +// deleted, it is possible for Javascript to have a reference to that object +// which has not yet been garbage collected. Javascript access to NPObjects +// will reference this registry to determine if the object is accessible or +// not. + +// Windows introduces an additional complication for objects created by the +// plugin. Plugins load inside of a DLL. Each DLL has it's own heap. If +// the browser unloads the plugin DLL, all objects created within the DLL's +// heap instantly become invalid. Normally, when WebKit drops the reference +// on the top-level plugin object, it tells the plugin manager that the +// plugin can be destroyed, which can unload the DLL. So, we must eliminate +// all pointers to any object ever created by the plugin. + +// We generally associate NPObjects with an owner. The owner of an NPObject +// is an NPObject which, when destroyed, also destroys all objects it owns. +// For example, if an NPAPI plugin creates 10 sub-NPObjects, all 11 objects +// (the NPAPI plugin + its 10 sub-objects) should become inaccessible +// simultaneously. + +// The ownership hierarchy is flat, and not a tree. Imagine the following +// object creation: +// PluginObject +// | +// +-- Creates -----> Object1 +// | +// +-- Creates -----> Object2 +// +// PluginObject will be the "owner" for both Object1 and Object2. + +// Register an NPObject with the runtime. If the owner is NULL, the +// object is treated as an owning object. If owner is not NULL, +// this object will be registered as owned by owner's top-level owner. +void _NPN_RegisterObject(NPObject*, NPObject* owner); + +// Unregister an NPObject with the runtime. If obj is an owning +// object, this call will also unregister all of the owned objects. +void _NPN_UnregisterObject(NPObject*); + +// Check to see if an object is registered with the runtime. +// Return true if registered, false otherwise. +bool _NPN_IsAlive(NPObject*); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif // npruntime_priv_h |