diff options
Diffstat (limited to 'WebCore/bindings/v8')
145 files changed, 4276 insertions, 2582 deletions
diff --git a/WebCore/bindings/v8/DOMData.cpp b/WebCore/bindings/v8/DOMData.cpp index 417426f..568fc2c 100644 --- a/WebCore/bindings/v8/DOMData.cpp +++ b/WebCore/bindings/v8/DOMData.cpp @@ -39,9 +39,7 @@ namespace WebCore { DOMData::DOMData() - : m_delayedProcessingScheduled(false) - , m_isMainThread(WTF::isMainThread()) - , m_owningThread(WTF::currentThread()) + : m_owningThread(WTF::currentThread()) { } @@ -58,72 +56,9 @@ DOMData* DOMData::getCurrent() return childThreadDOMData; } -void DOMData::ensureDeref(V8ClassIndex::V8WrapperType type, void* domObject) +void DOMData::derefObject(WrapperTypeInfo* 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(); + type->derefObject(domObject); } } // namespace WebCore diff --git a/WebCore/bindings/v8/DOMData.h b/WebCore/bindings/v8/DOMData.h index 7fa9e7d..4d7331b 100644 --- a/WebCore/bindings/v8/DOMData.h +++ b/WebCore/bindings/v8/DOMData.h @@ -32,6 +32,7 @@ #define DOMData_h #include "DOMDataStore.h" +#include "V8DOMWrapper.h" namespace WebCore { @@ -53,62 +54,39 @@ namespace WebCore { template<typename T> static void handleWeakObject(DOMDataStore::DOMWrapperMapType, v8::Persistent<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(AbstractWeakReferenceMap<T, v8::Object>& 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); + static void derefObject(WrapperTypeInfo* type, void* domObject); template<typename T> class WrapperMapObjectRemover : public WeakReferenceMap<T, v8::Object>::Visitor { public: virtual void visitDOMWrapper(T* domObject, v8::Persistent<v8::Object> v8Object) { - V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(v8Object); + WrapperTypeInfo* type = V8DOMWrapper::domWrapperType(v8Object); derefObject(type, domObject); v8Object.Dispose(); } }; - // 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; }; template<typename T> void DOMData::handleWeakObject(DOMDataStore::DOMWrapperMapType mapType, v8::Persistent<v8::Object> v8Object, T* domObject) { - ASSERT(WTF::isMainThread()); DOMDataList& list = DOMDataStore::allStores(); for (size_t i = 0; i < list.size(); ++i) { DOMDataStore* store = list[i]; + ASSERT(store->domData()->owningThread() == WTF::currentThread()); - DOMDataStore::InternalDOMWrapperMap<T>* domMap = static_cast<DOMDataStore::InternalDOMWrapperMap<T>*>(store->getDOMWrapperMap(mapType)); - - if (domMap->removeIfPresent(domObject, v8Object)) { - ASSERT(store->domData()->owningThread() == WTF::currentThread()); + DOMWrapperMap<T>* domMap = static_cast<DOMWrapperMap<T>*>(store->getDOMWrapperMap(mapType)); + if (domMap->removeIfPresent(domObject, v8Object)) store->domData()->derefObject(V8DOMWrapper::domWrapperType(v8Object), domObject); - } } } diff --git a/WebCore/bindings/v8/DOMDataStore.cpp b/WebCore/bindings/v8/DOMDataStore.cpp index e181ebc..5d609d8 100644 --- a/WebCore/bindings/v8/DOMDataStore.cpp +++ b/WebCore/bindings/v8/DOMDataStore.cpp @@ -114,11 +114,6 @@ WTF::Mutex& DOMDataStore::allStoresMutex() return staticDOMDataListMutex; } -void DOMDataStore::forgetDelayedObject(DOMData* domData, void* object) -{ - domData->forgetDelayedObject(object); -} - void* DOMDataStore::getDOMWrapperMap(DOMWrapperMapType type) { switch (type) { diff --git a/WebCore/bindings/v8/DOMDataStore.h b/WebCore/bindings/v8/DOMDataStore.h index 54a49e7..c39a0ed 100644 --- a/WebCore/bindings/v8/DOMDataStore.h +++ b/WebCore/bindings/v8/DOMDataStore.h @@ -31,7 +31,7 @@ #ifndef DOMDataStore_h #define DOMDataStore_h -#include "DOMObjectsInclude.h" +#include "V8DOMMap.h" #include "V8Node.h" #include <v8.h> @@ -47,6 +47,7 @@ namespace WebCore { class DOMData; + class DOMDataStore; typedef WTF::Vector<DOMDataStore*> DOMDataList; @@ -160,22 +161,6 @@ namespace WebCore { #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); - } - - private: - DOMData* m_domData; - }; - class IntrusiveDOMWrapperMap : public AbstractWeakReferenceMap<Node, v8::Object> { public: IntrusiveDOMWrapperMap(v8::WeakReferenceCallback callback) @@ -252,25 +237,21 @@ namespace WebCore { 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. + // A list of all DOMDataStore objects in the current V8 instance (thread). Normally, each World has a DOMDataStore. 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); DOMNodeMapping& domNodeMap() { return *m_domNodeMap; } - InternalDOMWrapperMap<void>& domObjectMap() { return *m_domObjectMap; } - InternalDOMWrapperMap<void>& activeDomObjectMap() { return *m_activeDomObjectMap; } + DOMWrapperMap<void>& domObjectMap() { return *m_domObjectMap; } + DOMWrapperMap<void>& activeDomObjectMap() { return *m_activeDomObjectMap; } #if ENABLE(SVG) - InternalDOMWrapperMap<SVGElementInstance>& domSvgElementInstanceMap() { return *m_domSvgElementInstanceMap; } - InternalDOMWrapperMap<void>& domSvgObjectWithContextMap() { return *m_domSvgObjectWithContextMap; } + DOMWrapperMap<SVGElementInstance>& domSvgElementInstanceMap() { return *m_domSvgElementInstanceMap; } + DOMWrapperMap<void>& domSvgObjectWithContextMap() { return *m_domSvgObjectWithContextMap; } #endif // Need by V8GCController. @@ -286,11 +267,11 @@ namespace WebCore { #endif DOMNodeMapping* m_domNodeMap; - InternalDOMWrapperMap<void>* m_domObjectMap; - InternalDOMWrapperMap<void>* m_activeDomObjectMap; + DOMWrapperMap<void>* m_domObjectMap; + DOMWrapperMap<void>* m_activeDomObjectMap; #if ENABLE(SVG) - InternalDOMWrapperMap<SVGElementInstance>* m_domSvgElementInstanceMap; - InternalDOMWrapperMap<void>* m_domSvgObjectWithContextMap; + DOMWrapperMap<SVGElementInstance>* m_domSvgElementInstanceMap; + DOMWrapperMap<void>* m_domSvgObjectWithContextMap; #endif private: diff --git a/WebCore/bindings/v8/DOMWrapperWorld.h b/WebCore/bindings/v8/DOMWrapperWorld.h index f54cd4e..2a9df30 100644 --- a/WebCore/bindings/v8/DOMWrapperWorld.h +++ b/WebCore/bindings/v8/DOMWrapperWorld.h @@ -43,6 +43,7 @@ namespace WebCore { class DOMWrapperWorld : public RefCounted<DOMWrapperWorld> { public: static PassRefPtr<DOMWrapperWorld> create() { return adoptRef(new DOMWrapperWorld()); } + virtual ~DOMWrapperWorld() {} protected: DOMWrapperWorld(); diff --git a/WebCore/bindings/v8/DateExtension.cpp b/WebCore/bindings/v8/DateExtension.cpp index abf8967..f2b6242 100644 --- a/WebCore/bindings/v8/DateExtension.cpp +++ b/WebCore/bindings/v8/DateExtension.cpp @@ -88,7 +88,7 @@ void DateExtension::setAllowSleep(bool allow) return; v8::Handle<v8::Value> argv[1]; - argv[0] = v8::String::New(allow ? "false" : "true"); + argv[0] = v8::Boolean::New(!allow); v8::Handle<v8::Function>::Cast(sleepFunctionHandle)->Call(v8::Object::New(), 1, argv); } diff --git a/WebCore/bindings/v8/JavaScriptCallFrame.cpp b/WebCore/bindings/v8/JavaScriptCallFrame.cpp new file mode 100644 index 0000000..049321b --- /dev/null +++ b/WebCore/bindings/v8/JavaScriptCallFrame.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2010, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JavaScriptCallFrame.h" + +#if ENABLE(JAVASCRIPT_DEBUGGER) + +#include "V8Binding.h" + +namespace WebCore { + +JavaScriptCallFrame::JavaScriptCallFrame(v8::Handle<v8::Context> debuggerContext, v8::Handle<v8::Object> callFrame) + : m_debuggerContext(debuggerContext) + , m_callFrame(callFrame) +{ +} + +JavaScriptCallFrame::~JavaScriptCallFrame() +{ +} + +JavaScriptCallFrame* JavaScriptCallFrame::caller() +{ + if (!m_caller) { + v8::HandleScope handleScope; + v8::Context::Scope contextScope(m_debuggerContext.get()); + v8::Handle<v8::Value> callerFrame = m_callFrame.get()->Get(v8String("caller")); + if (!callerFrame->IsObject()) + return 0; + m_caller = JavaScriptCallFrame::create(m_debuggerContext.get(), v8::Handle<v8::Object>::Cast(callerFrame)); + } + return m_caller.get(); +} + +int JavaScriptCallFrame::sourceID() const +{ + v8::HandleScope handleScope; + v8::Context::Scope contextScope(m_debuggerContext.get()); + v8::Handle<v8::Value> result = m_callFrame.get()->Get(v8String("sourceID")); + if (result->IsInt32()) + return result->Int32Value(); + return 0; +} + +int JavaScriptCallFrame::line() const +{ + v8::HandleScope handleScope; + v8::Context::Scope contextScope(m_debuggerContext.get()); + v8::Handle<v8::Value> result = m_callFrame.get()->Get(v8String("line")); + if (result->IsInt32()) + return result->Int32Value(); + return 0; +} + +String JavaScriptCallFrame::functionName() const +{ + v8::HandleScope handleScope; + v8::Context::Scope contextScope(m_debuggerContext.get()); + v8::Handle<v8::Value> result = m_callFrame.get()->Get(v8String("functionName")); + return toWebCoreString(result); +} + +v8::Handle<v8::Value> JavaScriptCallFrame::scopeChain() const +{ + v8::Handle<v8::Array> scopeChain = v8::Handle<v8::Array>::Cast(m_callFrame.get()->Get(v8String("scopeChain"))); + v8::Handle<v8::Array> result = v8::Array::New(scopeChain->Length()); + for (uint32_t i = 0; i < scopeChain->Length(); i++) + result->Set(i, scopeChain->Get(i)); + return result; +} + +int JavaScriptCallFrame::scopeType(int scopeIndex) const +{ + v8::Handle<v8::Array> scopeType = v8::Handle<v8::Array>::Cast(m_callFrame.get()->Get(v8String("scopeType"))); + return scopeType->Get(scopeIndex)->Int32Value(); +} + +v8::Handle<v8::Value> JavaScriptCallFrame::thisObject() const +{ + return m_callFrame.get()->Get(v8String("thisObject")); +} + +v8::Handle<v8::Value> JavaScriptCallFrame::evaluate(const String& expression) +{ + v8::Handle<v8::Function> evalFunction = v8::Handle<v8::Function>::Cast(m_callFrame.get()->Get(v8String("evaluate"))); + v8::Handle<v8::Value> argv[] = { v8String(expression) }; + return evalFunction->Call(m_callFrame.get(), 1, argv); +} + +} // namespace WebCore + +#endif // ENABLE(JAVASCRIPT_DEBUGGER) diff --git a/WebCore/bindings/v8/JavaScriptCallFrame.h b/WebCore/bindings/v8/JavaScriptCallFrame.h new file mode 100644 index 0000000..95a0510 --- /dev/null +++ b/WebCore/bindings/v8/JavaScriptCallFrame.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2010, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JavaScriptCallFrame_h +#define JavaScriptCallFrame_h + +#if ENABLE(JAVASCRIPT_DEBUGGER) + +#include "OwnHandle.h" +#include "PlatformString.h" +#include <v8-debug.h> + +namespace WebCore { + +class JavaScriptCallFrame : public RefCounted<JavaScriptCallFrame> { +public: + static PassRefPtr<JavaScriptCallFrame> create(v8::Handle<v8::Context> debuggerContext, v8::Handle<v8::Object> callFrame) + { + return adoptRef(new JavaScriptCallFrame(debuggerContext, callFrame)); + } + ~JavaScriptCallFrame(); + + JavaScriptCallFrame* caller(); + + int sourceID() const; + int line() const; + String functionName() const; + + v8::Handle<v8::Value> scopeChain() const; + int scopeType(int scopeIndex) const; + v8::Handle<v8::Value> thisObject() const; + + v8::Handle<v8::Value> evaluate(const String& expression); + +private: + JavaScriptCallFrame(v8::Handle<v8::Context> debuggerContext, v8::Handle<v8::Object> callFrame); + + RefPtr<JavaScriptCallFrame> m_caller; + OwnHandle<v8::Context> m_debuggerContext; + OwnHandle<v8::Object> m_callFrame; +}; + +} // namespace WebCore + +#endif // ENABLE(JAVASCRIPT_DEBUGGER) + +#endif // JavaScriptCallFrame_h diff --git a/WebCore/bindings/v8/NPV8Object.cpp b/WebCore/bindings/v8/NPV8Object.cpp index 06243d4..56f9810 100644 --- a/WebCore/bindings/v8/NPV8Object.cpp +++ b/WebCore/bindings/v8/NPV8Object.cpp @@ -36,9 +36,9 @@ #include "ScriptController.h" #include "V8GCController.h" #include "V8Helpers.h" -#include "V8Index.h" #include "V8NPUtils.h" #include "V8Proxy.h" +#include "WrapperTypeInfo.h" #include "npruntime_impl.h" #include "npruntime_priv.h" @@ -55,10 +55,20 @@ using WebCore::npObjectInternalFieldCount; using WebCore::toV8Context; using WebCore::toV8Proxy; -using WebCore::V8ClassIndex; using WebCore::V8DOMWrapper; using WebCore::V8GCController; using WebCore::V8Proxy; +using WebCore::WrapperTypeInfo; + +namespace WebCore { + +WrapperTypeInfo* npObjectTypeInfo() +{ + static WrapperTypeInfo typeInfo = { 0, 0, false }; + return &typeInfo; +} + +} // FIXME: Comments on why use malloc and free. static NPObject* allocV8NPObject(NPP, NPClass*) @@ -115,8 +125,8 @@ NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, WebCore { // Check to see if this object is already wrapped. if (object->InternalFieldCount() == npObjectInternalFieldCount) { - v8::Local<v8::Value> typeIndex = object->GetInternalField(WebCore::v8DOMWrapperTypeIndex); - if (typeIndex->IsNumber() && typeIndex->Uint32Value() == V8ClassIndex::NPOBJECT) { + WrapperTypeInfo* typeInfo = static_cast<WrapperTypeInfo*>(object->GetPointerFromInternalField(WebCore::v8DOMWrapperTypeIndex)); + if (typeInfo == WebCore::npObjectTypeInfo()) { NPObject* returnValue = v8ObjectToNPObject(object); _NPN_RetainObject(returnValue); @@ -299,6 +309,9 @@ bool _NPN_GetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, NP v8::Handle<v8::Object> obj(object->v8Object); v8::Local<v8::Value> v8result = obj->Get(npIdentifierToV8Identifier(propertyName)); + + if (v8result.IsEmpty()) + return false; convertV8ObjectToNPVariant(v8result, npObject, result); return true; diff --git a/WebCore/bindings/v8/NPV8Object.h b/WebCore/bindings/v8/NPV8Object.h index e5550ee..b6fecce 100644 --- a/WebCore/bindings/v8/NPV8Object.h +++ b/WebCore/bindings/v8/NPV8Object.h @@ -30,7 +30,7 @@ #ifndef NPV8Object_h #define NPV8Object_h -#include "V8Index.h" +#include "V8DOMWrapper.h" #if PLATFORM(CHROMIUM) // FIXME: Chromium uses a different npruntime.h, which is in @@ -48,6 +48,8 @@ namespace WebCore { class DOMWindow; static const int npObjectInternalFieldCount = v8DefaultWrapperInternalFieldCount + 0; + + WrapperTypeInfo* npObjectTypeInfo(); } extern NPClass* npScriptObjectClass; diff --git a/WebCore/bindings/v8/ScopedDOMDataStore.cpp b/WebCore/bindings/v8/ScopedDOMDataStore.cpp index 19cd545..df4a63a 100644 --- a/WebCore/bindings/v8/ScopedDOMDataStore.cpp +++ b/WebCore/bindings/v8/ScopedDOMDataStore.cpp @@ -36,12 +36,12 @@ 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); + m_domNodeMap = new DOMWrapperMap<Node>(&DOMDataStore::weakNodeCallback); + m_domObjectMap = new DOMWrapperMap<void>(&DOMDataStore::weakDOMObjectCallback); + m_activeDomObjectMap = new DOMWrapperMap<void>(&DOMDataStore::weakActiveDOMObjectCallback); #if ENABLE(SVG) - m_domSvgElementInstanceMap = new InternalDOMWrapperMap<SVGElementInstance>(domData, &DOMDataStore::weakSVGElementInstanceCallback); - m_domSvgObjectWithContextMap = new InternalDOMWrapperMap<void>(domData, &DOMDataStore::weakSVGObjectWithContextCallback); + m_domSvgElementInstanceMap = new DOMWrapperMap<SVGElementInstance>(&DOMDataStore::weakSVGElementInstanceCallback); + m_domSvgObjectWithContextMap = new DOMWrapperMap<void>(&DOMDataStore::weakSVGObjectWithContextCallback); #endif } diff --git a/WebCore/bindings/v8/ScriptCallStack.cpp b/WebCore/bindings/v8/ScriptCallStack.cpp index 21063ed..45e7205 100644 --- a/WebCore/bindings/v8/ScriptCallStack.cpp +++ b/WebCore/bindings/v8/ScriptCallStack.cpp @@ -32,29 +32,33 @@ #include "ScriptCallStack.h" #include "ScriptController.h" +#include "ScriptDebugServer.h" #include <v8.h> #include "V8Binding.h" -#include "V8Proxy.h" namespace WebCore { ScriptCallStack* ScriptCallStack::create(const v8::Arguments& arguments, unsigned skipArgumentCount) { String sourceName; int sourceLineNumber; - if (!V8Proxy::sourceName(sourceName)) { - return 0; - } - if (!V8Proxy::sourceLineNumber(sourceLineNumber)) { - return 0; - } - sourceLineNumber += 1; - return new ScriptCallStack(arguments, skipArgumentCount, sourceName, sourceLineNumber); + String funcName; + if (!callLocation(&sourceName, &sourceLineNumber, &funcName)) + return 0; + return new ScriptCallStack(arguments, skipArgumentCount, sourceName, sourceLineNumber, funcName); } -ScriptCallStack::ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount, String sourceName, int sourceLineNumber) - : m_lastCaller(String(), sourceName, sourceLineNumber, arguments, skipArgumentCount) +bool ScriptCallStack::callLocation(String* sourceName, int* sourceLineNumber, String* functionName) +{ + if (!ScriptDebugServer::topStackFrame(*sourceName, *sourceLineNumber, *functionName)) + return false; + *sourceLineNumber += 1; + return true; +} + +ScriptCallStack::ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount, String sourceName, int sourceLineNumber, String functionName) + : m_lastCaller(functionName, sourceName, sourceLineNumber, arguments, skipArgumentCount) , m_scriptState(ScriptState::current()) { } diff --git a/WebCore/bindings/v8/ScriptCallStack.h b/WebCore/bindings/v8/ScriptCallStack.h index 8ac394c..2433bde 100644 --- a/WebCore/bindings/v8/ScriptCallStack.h +++ b/WebCore/bindings/v8/ScriptCallStack.h @@ -47,6 +47,8 @@ namespace WebCore { static ScriptCallStack* create(const v8::Arguments&, unsigned skipArgumentCount = 0); ~ScriptCallStack(); + static bool callLocation(String* sourceName, int* sourceLineNumber, String* functionName); + const ScriptCallFrame& at(unsigned) const; // FIXME: implement retrieving and storing call stack trace unsigned size() const { return 1; } @@ -55,7 +57,7 @@ namespace WebCore { ScriptState* globalState() const { return m_scriptState; } private: - ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount, String sourceName, int sourceLineNumber); + ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount, String sourceName, int sourceLineNumber, String funcName); ScriptCallFrame m_lastCaller; ScriptState* m_scriptState; diff --git a/WebCore/bindings/v8/ScriptController.cpp b/WebCore/bindings/v8/ScriptController.cpp index 40a71be..ee15eaa 100644 --- a/WebCore/bindings/v8/ScriptController.cpp +++ b/WebCore/bindings/v8/ScriptController.cpp @@ -33,7 +33,6 @@ #include "ScriptController.h" #include "PlatformBridge.h" -#include "CString.h" #include "Document.h" #include "DOMWindow.h" #include "Event.h" @@ -48,6 +47,7 @@ #include "NPV8Object.h" #include "ScriptSourceCode.h" #include "Settings.h" +#include "UserGestureIndicator.h" #include "V8Binding.h" #include "V8BindingState.h" #include "V8DOMWindow.h" @@ -59,6 +59,7 @@ #include "Widget.h" #include "XSSAuditor.h" #include <wtf/StdLibExtras.h> +#include <wtf/text/CString.h> namespace WebCore { @@ -153,9 +154,10 @@ void ScriptController::updatePlatformScriptObjects() bool ScriptController::processingUserGesture(DOMWrapperWorld*) const { Frame* activeFrame = V8Proxy::retrieveFrameForEnteredContext(); - // No script is running, so it must be run by users. + // No script is running, so it is user-initiated unless the gesture stack + // explicitly says it is not. if (!activeFrame) - return true; + return UserGestureIndicator::processingUserGesture(); V8Proxy* activeProxy = activeFrame->script()->proxy(); @@ -176,7 +178,7 @@ bool ScriptController::processingUserGesture(DOMWrapperWorld*) const // Based on code from kjs_bindings.cpp. // Note: This is more liberal than Firefox's implementation. if (event) { - if (event->createdByDOM()) + if (!UserGestureIndicator::processingUserGesture()) return false; const AtomicString& type = event->type(); @@ -190,7 +192,7 @@ bool ScriptController::processingUserGesture(DOMWrapperWorld*) const if (eventOk) return true; - } else if (activeProxy->inlineCode() && !activeProxy->timerCallback()) { + } else if (m_sourceURL && m_sourceURL->isNull() && !activeProxy->timerCallback()) { // This is the <a href="javascript:window.open('...')> case -> we let it through. return true; } @@ -219,7 +221,9 @@ void ScriptController::evaluateInIsolatedWorld(unsigned worldID, const Vector<Sc ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) { String sourceURL = sourceCode.url(); - + const String* savedSourceURL = m_sourceURL; + m_sourceURL = &sourceURL; + if (!m_XSSAuditor->canEvaluate(sourceCode.source())) { // This script is not safe to be evaluated. return ScriptValue(); @@ -237,9 +241,11 @@ ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode) v8::Local<v8::Value> object = m_proxy->evaluate(sourceCode, 0); // Evaluating the JavaScript could cause the frame to be deallocated - // so we starot the keep alive timer here. + // so we start the keep alive timer here. m_frame->keepAlive(); + m_sourceURL = savedSourceURL; + if (object.IsEmpty() || object->IsUndefined()) return ScriptValue(); @@ -402,7 +408,7 @@ NPObject* ScriptController::windowScriptNPObject() if (m_windowScriptNPObject) return m_windowScriptNPObject; - if (canExecuteScripts()) { + if (canExecuteScripts(NotAboutToExecuteScript)) { // JavaScript is enabled, so there is a JavaScript window object. // Return an NPObject bound to the window object. m_windowScriptNPObject = createScriptObject(m_frame); @@ -419,7 +425,7 @@ NPObject* ScriptController::windowScriptNPObject() NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement* plugin) { // Can't create NPObjects when JavaScript is disabled. - if (!canExecuteScripts()) + if (!canExecuteScripts(NotAboutToExecuteScript)) return createNoScriptObject(); v8::HandleScope handleScope; diff --git a/WebCore/bindings/v8/ScriptController.h b/WebCore/bindings/v8/ScriptController.h index b3995b2..7e13740 100644 --- a/WebCore/bindings/v8/ScriptController.h +++ b/WebCore/bindings/v8/ScriptController.h @@ -55,6 +55,11 @@ class String; class Widget; class XSSAuditor; +enum ReasonForCallingCanExecuteScripts { + AboutToExecuteScript, + NotAboutToExecuteScript +}; + class ScriptController { public: ScriptController(Frame*); @@ -113,7 +118,7 @@ public: // Check if the javascript engine has been initialized. bool haveInterpreter() const; - bool canExecuteScripts(); + bool canExecuteScripts(ReasonForCallingCanExecuteScripts); // FIXME: void* is a compile hack. void attachDebugger(void*); diff --git a/WebCore/bindings/v8/ScriptDebugServer.cpp b/WebCore/bindings/v8/ScriptDebugServer.cpp index 3fe8c34..54d7694 100644 --- a/WebCore/bindings/v8/ScriptDebugServer.cpp +++ b/WebCore/bindings/v8/ScriptDebugServer.cpp @@ -29,17 +29,379 @@ */ #include "config.h" - #include "ScriptDebugServer.h" +#if ENABLE(JAVASCRIPT_DEBUGGER) + +#include "Frame.h" +#include "JavaScriptCallFrame.h" +#include "Page.h" +#include "ScriptDebugListener.h" +#include "V8Binding.h" +#include "V8DOMWindow.h" +#include "V8Proxy.h" +#include <wtf/StdLibExtras.h> + namespace WebCore { -void ScriptDebugServer::recompileAllJSFunctions() +v8::Persistent<v8::Context> ScriptDebugServer::s_utilityContext; + +ScriptDebugServer::MessageLoopDispatchHandler ScriptDebugServer::s_messageLoopDispatchHandler = 0; + +ScriptDebugServer& ScriptDebugServer::shared() +{ + DEFINE_STATIC_LOCAL(ScriptDebugServer, server, ()); + return server; +} + +ScriptDebugServer::ScriptDebugServer() + : m_pauseOnExceptionsState(DontPauseOnExceptions) + , m_currentCallFrameState(0) +{ +} + +void ScriptDebugServer::setDebuggerScriptSource(const String& scriptSource) +{ + m_debuggerScriptSource = scriptSource; +} + +void ScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page) +{ +#if ENABLE(V8_SCRIPT_DEBUG_SERVER) + v8::HandleScope scope; + v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); + v8::Context::Scope contextScope(debuggerContext); + + if (!m_listenersMap.size()) { + ensureDebuggerScriptCompiled(); + ASSERT(!m_debuggerScript.get()->IsUndefined()); + v8::Debug::SetMessageHandler2(&ScriptDebugServer::onV8DebugMessage); + v8::Debug::SetHostDispatchHandler(&ScriptDebugServer::onV8DebugHostDispatch, 100 /* ms */); + } + m_listenersMap.set(page, listener); + V8Proxy* proxy = V8Proxy::retrieve(page->mainFrame()); + v8::Local<v8::Context> context = proxy->mainWorldContext(); + String contextData = toWebCoreStringWithNullCheck(context->GetData()); + m_contextDataMap.set(listener, contextData); + + v8::Handle<v8::Function> getScriptsFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("getScripts"))); + v8::Handle<v8::Value> value = v8::Debug::Call(getScriptsFunction); + if (value.IsEmpty()) + return; + ASSERT(!value->IsUndefined() && value->IsArray()); + v8::Handle<v8::Array> scriptsArray = v8::Handle<v8::Array>::Cast(value); + for (unsigned i = 0; i < scriptsArray->Length(); ++i) + dispatchDidParseSource(listener, v8::Handle<v8::Object>::Cast(scriptsArray->Get(v8::Integer::New(i)))); +#endif +} + +void ScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* page) +{ + if (!m_listenersMap.contains(page)) + return; + + m_listenersMap.remove(page); + + if (m_listenersMap.isEmpty()) { + v8::Debug::SetMessageHandler2(0); + v8::Debug::SetHostDispatchHandler(0); + } + // FIXME: Remove all breakpoints set by the agent. + // FIXME: Force continue if detach happened in nessted message loop while + // debugger was paused on a breakpoint(as long as there are other + // attached agents v8 will wait for explicit'continue' message). + // FIXME: send continue command to v8 if necessary; +} + +void ScriptDebugServer::setBreakpoint(const String& sourceID, unsigned lineNumber, ScriptBreakpoint breakpoint) +{ +#if ENABLE(V8_SCRIPT_DEBUG_SERVER) + v8::HandleScope scope; + v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); + v8::Context::Scope contextScope(debuggerContext); + + v8::Local<v8::Object> args = v8::Object::New(); + args->Set(v8::String::New("scriptId"), v8String(sourceID)); + args->Set(v8::String::New("lineNumber"), v8::Integer::New(lineNumber)); + args->Set(v8::String::New("condition"), v8String(breakpoint.condition)); + args->Set(v8::String::New("enabled"), v8::Boolean::New(breakpoint.enabled)); + + v8::Handle<v8::Function> setBreakpointFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("setBreakpoint"))); + v8::Debug::Call(setBreakpointFunction, args); +#endif +} + +void ScriptDebugServer::removeBreakpoint(const String& sourceID, unsigned lineNumber) +{ +#if ENABLE(V8_SCRIPT_DEBUG_SERVER) + v8::HandleScope scope; + v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); + v8::Context::Scope contextScope(debuggerContext); + + v8::Local<v8::Object> args = v8::Object::New(); + args->Set(v8::String::New("scriptId"), v8String(sourceID)); + args->Set(v8::String::New("lineNumber"), v8::Integer::New(lineNumber)); + + v8::Handle<v8::Function> removeBreakpointFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("removeBreakpoint"))); + v8::Debug::Call(removeBreakpointFunction, args); +#endif +} + +void ScriptDebugServer::clearBreakpoints() +{ +#if ENABLE(V8_SCRIPT_DEBUG_SERVER) + ensureDebuggerScriptCompiled(); + v8::HandleScope scope; + v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); + v8::Context::Scope contextScope(debuggerContext); + + v8::Handle<v8::Function> setBreakpointsActivated = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("clearBreakpoints"))); + v8::Debug::Call(setBreakpointsActivated); +#endif +} + +void ScriptDebugServer::setBreakpointsActivated(bool enabled) +{ +#if ENABLE(V8_SCRIPT_DEBUG_SERVER) + ensureDebuggerScriptCompiled(); + v8::HandleScope scope; + v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); + v8::Context::Scope contextScope(debuggerContext); + + v8::Local<v8::Object> args = v8::Object::New(); + args->Set(v8::String::New("enabled"), v8::Boolean::New(enabled)); + v8::Handle<v8::Function> setBreakpointsActivated = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("setBreakpointsActivated"))); + v8::Debug::Call(setBreakpointsActivated, args); +#endif +} + +void ScriptDebugServer::continueProgram() +{ +#if ENABLE(V8_SCRIPT_DEBUG_SERVER) + String cmd("{\"seq\":1,\"type\":\"request\",\"command\":\"continue\"}"); + v8::Debug::SendCommand(reinterpret_cast<const uint16_t*>(cmd.characters()), cmd.length(), new v8::Debug::ClientData()); + didResume(); +#endif +} + +void ScriptDebugServer::stepIntoStatement() +{ +#if ENABLE(V8_SCRIPT_DEBUG_SERVER) + String cmd("{\"seq\":1,\"type\":\"request\",\"command\":\"continue\",\"arguments\":{\"stepaction\":\"in\"}}"); + v8::Debug::SendCommand(reinterpret_cast<const uint16_t*>(cmd.characters()), cmd.length(), new v8::Debug::ClientData()); + didResume(); +#endif +} + +void ScriptDebugServer::stepOverStatement() { +#if ENABLE(V8_SCRIPT_DEBUG_SERVER) + String cmd("{\"seq\":1,\"type\":\"request\",\"command\":\"continue\",\"arguments\":{\"stepaction\":\"next\"}}"); + v8::Debug::SendCommand(reinterpret_cast<const uint16_t*>(cmd.characters()), cmd.length(), new v8::Debug::ClientData()); + didResume(); +#endif } -void ScriptDebugServer::recompileAllJSFunctionsSoon() +void ScriptDebugServer::stepOutOfFunction() { +#if ENABLE(V8_SCRIPT_DEBUG_SERVER) + String cmd("{\"seq\":1,\"type\":\"request\",\"command\":\"continue\",\"arguments\":{\"stepaction\":\"out\"}}"); + v8::Debug::SendCommand(reinterpret_cast<const uint16_t*>(cmd.characters()), cmd.length(), new v8::Debug::ClientData()); + didResume(); +#endif +} + +ScriptState* ScriptDebugServer::currentCallFrameState() +{ + return m_currentCallFrameState; +} + +v8::Handle<v8::Value> ScriptDebugServer::currentCallFrameV8() +{ +#if ENABLE(V8_SCRIPT_DEBUG_SERVER) + if (!m_currentCallFrame.get().IsEmpty()) + return m_currentCallFrame.get(); + + // Check on a bp. + v8::Handle<v8::Function> currentCallFrameFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("currentCallFrame"))); + v8::Handle<v8::Value> argv[] = { m_executionState.get() }; + v8::Handle<v8::Value> result = currentCallFrameFunction->Call(m_debuggerScript.get(), 1, argv); + m_currentCallFrame.set(result); + return result; +#else + return v8::Handle<v8::Value>(); +#endif +} + +PassRefPtr<JavaScriptCallFrame> ScriptDebugServer::currentCallFrame() +{ + return JavaScriptCallFrame::create(v8::Debug::GetDebugContext(), v8::Handle<v8::Object>::Cast(currentCallFrameV8())); +} + +void ScriptDebugServer::onV8DebugMessage(const v8::Debug::Message& message) +{ + ScriptDebugServer::shared().handleV8DebugMessage(message); +} + +void ScriptDebugServer::onV8DebugHostDispatch() +{ + ScriptDebugServer::shared().handleV8DebugHostDispatch(); +} + +void ScriptDebugServer::handleV8DebugHostDispatch() +{ + if (!s_messageLoopDispatchHandler) + return; + + Vector<WebCore::Page*> pages; + for (ListenersMap::iterator it = m_listenersMap.begin(); it != m_listenersMap.end(); ++it) + pages.append(it->first); + + s_messageLoopDispatchHandler(pages); +} + +void ScriptDebugServer::handleV8DebugMessage(const v8::Debug::Message& message) +{ + v8::HandleScope scope; + + if (!message.IsEvent()) + return; + + // Ignore unsupported event types. + if (message.GetEvent() != v8::AfterCompile && message.GetEvent() != v8::Break) + return; + + v8::Handle<v8::Context> context = message.GetEventContext(); + // If the context is from one of the inpected tabs it should have its context + // data. Skip events from unknown contexts. + if (context.IsEmpty()) + return; + + // Test that context has associated global dom window object. + v8::Handle<v8::Object> global = context->Global(); + if (global.IsEmpty()) + return; + + global = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), global); + if (global.IsEmpty()) + return; + + Frame* frame = V8Proxy::retrieveFrame(context); + if (frame) { + ScriptDebugListener* listener = m_listenersMap.get(frame->page()); + if (listener) { + if (message.GetEvent() == v8::AfterCompile) { + v8::Context::Scope contextScope(v8::Debug::GetDebugContext()); + v8::Local<v8::Object> args = v8::Object::New(); + args->Set(v8::String::New("eventData"), message.GetEventData()); + v8::Handle<v8::Function> onAfterCompileFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("getAfterCompileScript"))); + v8::Handle<v8::Value> argv[] = { message.GetExecutionState(), args }; + v8::Handle<v8::Value> value = onAfterCompileFunction->Call(m_debuggerScript.get(), 2, argv); + ASSERT(value->IsObject()); + v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); + dispatchDidParseSource(listener, object); + } else if (message.GetEvent() == v8::Break) { + m_executionState.set(message.GetExecutionState()); + m_currentCallFrameState = mainWorldScriptState(frame); + listener->didPause(); + m_currentCallFrameState = 0; + } + } + } +} + +void ScriptDebugServer::dispatchDidParseSource(ScriptDebugListener* listener, v8::Handle<v8::Object> object) +{ + String contextData = toWebCoreStringWithNullCheck(object->Get(v8::String::New("contextData"))); + if (contextData != m_contextDataMap.get(listener)) + return; + + listener->didParseSource( + toWebCoreStringWithNullCheck(object->Get(v8::String::New("id"))), + toWebCoreStringWithNullCheck(object->Get(v8::String::New("name"))), + toWebCoreStringWithNullCheck(object->Get(v8::String::New("source"))), + object->Get(v8::String::New("lineOffset"))->ToInteger()->Value()); +} + +void ScriptDebugServer::ensureDebuggerScriptCompiled() +{ + if (m_debuggerScript.get().IsEmpty()) { + v8::HandleScope scope; + v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); + v8::Context::Scope contextScope(debuggerContext); + m_debuggerScript.set(v8::Handle<v8::Object>::Cast(v8::Script::Compile(v8String(m_debuggerScriptSource))->Run())); + } +} + +void ScriptDebugServer::didResume() +{ + m_currentCallFrame.clear(); + m_executionState.clear(); +} + +// Create the utility context for holding JavaScript functions used internally +// which are not visible to JavaScript executing on the page. +void ScriptDebugServer::createUtilityContext() +{ + ASSERT(s_utilityContext.IsEmpty()); + + v8::HandleScope scope; + v8::Handle<v8::ObjectTemplate> globalTemplate = v8::ObjectTemplate::New(); + s_utilityContext = v8::Context::New(0, globalTemplate); + v8::Context::Scope contextScope(s_utilityContext); + + // Compile JavaScript function for retrieving the source line, the source + // name and the symbol name for the top JavaScript stack frame. + DEFINE_STATIC_LOCAL(const char*, topStackFrame, + ("function topStackFrame(exec_state) {" + " if (!exec_state.frameCount())" + " return undefined;" + " var frame = exec_state.frame(0);" + " var func = frame.func();" + " var scriptName;" + " if (func.resolved() && func.script())" + " scriptName = func.script().name();" + " return [scriptName, frame.sourceLine(), (func.name() || func.inferredName())];" + "}")); + v8::Script::Compile(v8::String::New(topStackFrame))->Run(); +} + +bool ScriptDebugServer::topStackFrame(String& sourceName, int& lineNumber, String& functionName) +{ + v8::HandleScope scope; + v8::Handle<v8::Context> v8UtilityContext = utilityContext(); + if (v8UtilityContext.IsEmpty()) + return false; + v8::Context::Scope contextScope(v8UtilityContext); + v8::Handle<v8::Function> topStackFrame; + topStackFrame = v8::Local<v8::Function>::Cast(v8UtilityContext->Global()->Get(v8::String::New("topStackFrame"))); + if (topStackFrame.IsEmpty()) + return false; + v8::Handle<v8::Value> value = v8::Debug::Call(topStackFrame); + if (value.IsEmpty()) + return false; + // If there is no top stack frame, we still return success, but fill the input params with defaults. + if (value->IsUndefined()) { + // Fallback to setting lineNumber to 0, and source and function name to "undefined". + sourceName = toWebCoreString(value); + lineNumber = 0; + functionName = toWebCoreString(value); + return true; + } + if (!value->IsArray()) + return false; + v8::Local<v8::Object> jsArray = value->ToObject(); + v8::Local<v8::Value> sourceNameValue = jsArray->Get(0); + v8::Local<v8::Value> lineNumberValue = jsArray->Get(1); + v8::Local<v8::Value> functionNameValue = jsArray->Get(2); + if (sourceNameValue.IsEmpty() || lineNumberValue.IsEmpty() || functionNameValue.IsEmpty()) + return false; + sourceName = toWebCoreString(sourceNameValue); + lineNumber = lineNumberValue->Int32Value(); + functionName = toWebCoreString(functionNameValue); + return true; } } // namespace WebCore + +#endif // ENABLE(JAVASCRIPT_DEBUGGER) diff --git a/WebCore/bindings/v8/ScriptDebugServer.h b/WebCore/bindings/v8/ScriptDebugServer.h index b37af2f..04857e4 100644 --- a/WebCore/bindings/v8/ScriptDebugServer.h +++ b/WebCore/bindings/v8/ScriptDebugServer.h @@ -31,16 +31,119 @@ #ifndef ScriptDebugServer_h #define ScriptDebugServer_h +#if ENABLE(JAVASCRIPT_DEBUGGER) + +#include "OwnHandle.h" +#include "PlatformString.h" +#include "ScriptBreakpoint.h" +#include "ScriptState.h" +#include "StringHash.h" +#include "Timer.h" +#include <v8-debug.h> +#include <wtf/HashMap.h> #include <wtf/Noncopyable.h> namespace WebCore { +class JavaScriptCallFrame; +class Page; +class ScriptDebugListener; + class ScriptDebugServer : public Noncopyable { public: - static void recompileAllJSFunctions(); - static void recompileAllJSFunctionsSoon(); + static ScriptDebugServer& shared(); + + // Function for retrieving the source name, line number and function name for the top + // JavaScript stack frame. + // + // It will return true if the caller information was successfully retrieved and written + // into the function parameters, otherwise the function will return false. It may + // fail due to a stack overflow in the underlying JavaScript implementation, handling + // of such exception is up to the caller. + static bool topStackFrame(String& sourceName, int& lineNumber, String& functionName); + + void addListener(ScriptDebugListener*, Page*); + void removeListener(ScriptDebugListener*, Page*); + + void setBreakpoint(const String& sourceID, unsigned lineNumber, ScriptBreakpoint breakpoint); + void removeBreakpoint(const String& sourceID, unsigned lineNumber); + void clearBreakpoints(); + void setBreakpointsActivated(bool activated); + + enum PauseOnExceptionsState { + DontPauseOnExceptions, + PauseOnAllExceptions, + PauseOnUncaughtExceptions + }; + PauseOnExceptionsState pauseOnExceptionsState() const { return m_pauseOnExceptionsState; } + void setPauseOnExceptionsState(PauseOnExceptionsState pauseOnExceptionsState) { m_pauseOnExceptionsState = pauseOnExceptionsState; } + + void pauseProgram() { } + void continueProgram(); + void stepIntoStatement(); + void stepOverStatement(); + void stepOutOfFunction(); + + void recompileAllJSFunctionsSoon() { } + void recompileAllJSFunctions(Timer<ScriptDebugServer>* = 0) { } + + ScriptState* currentCallFrameState(); + + void pageCreated(Page*) { } + + // v8-specific methods. + void setDebuggerScriptSource(const String& scriptSource); + + typedef void (*MessageLoopDispatchHandler)(const Vector<WebCore::Page*>&); + static void setMessageLoopDispatchHandler(MessageLoopDispatchHandler messageLoopDispatchHandler) { s_messageLoopDispatchHandler = messageLoopDispatchHandler; } + + v8::Handle<v8::Value> currentCallFrameV8(); + PassRefPtr<JavaScriptCallFrame> currentCallFrame(); + +private: + ScriptDebugServer(); + ~ScriptDebugServer() { } + + static void onV8DebugMessage(const v8::Debug::Message& message); + static void onV8DebugHostDispatch(); + + void handleV8DebugMessage(const v8::Debug::Message& message); + void handleV8DebugHostDispatch(); + + void dispatchDidParseSource(ScriptDebugListener* listener, v8::Handle<v8::Object> sourceObject); + + void ensureDebuggerScriptCompiled(); + void didResume(); + + static void createUtilityContext(); + + // Returns a local handle of the utility context. + static v8::Local<v8::Context> utilityContext() + { + if (s_utilityContext.IsEmpty()) + createUtilityContext(); + return v8::Local<v8::Context>::New(s_utilityContext); + } + + // Utility context holding JavaScript functions used internally. + static v8::Persistent<v8::Context> s_utilityContext; + + typedef HashMap<Page*, ScriptDebugListener*> ListenersMap; + ListenersMap m_listenersMap; + typedef HashMap<ScriptDebugListener*, String> ContextDataMap; + ContextDataMap m_contextDataMap; + String m_debuggerScriptSource; + PauseOnExceptionsState m_pauseOnExceptionsState; + OwnHandle<v8::Object> m_debuggerScript; + ScriptState* m_currentCallFrameState; + OwnHandle<v8::Value> m_currentCallFrame; + OwnHandle<v8::Object> m_executionState; + + static MessageLoopDispatchHandler s_messageLoopDispatchHandler; }; } // namespace WebCore +#endif // ENABLE(JAVASCRIPT_DEBUGGER) + #endif // ScriptDebugServer_h diff --git a/WebCore/bindings/v8/ScriptEventListener.cpp b/WebCore/bindings/v8/ScriptEventListener.cpp index b318d2e..fdb6076 100644 --- a/WebCore/bindings/v8/ScriptEventListener.cpp +++ b/WebCore/bindings/v8/ScriptEventListener.cpp @@ -56,7 +56,7 @@ PassRefPtr<V8LazyEventListener> createAttributeEventListener(Node* node, Attribu if (Frame* frame = node->document()->frame()) { ScriptController* scriptController = frame->script(); - if (!scriptController->canExecuteScripts()) + if (!scriptController->canExecuteScripts(AboutToExecuteScript)) return 0; if (!scriptController->xssAuditor()->canCreateInlineEventListener(attr->localName().string(), attr->value())) { @@ -89,7 +89,7 @@ PassRefPtr<V8LazyEventListener> createAttributeEventListener(Frame* frame, Attri String sourceURL; ScriptController* scriptController = frame->script(); - if (!scriptController->canExecuteScripts()) + if (!scriptController->canExecuteScripts(AboutToExecuteScript)) return 0; if (!scriptController->xssAuditor()->canCreateInlineEventListener(attr->localName().string(), attr->value())) { diff --git a/WebCore/bindings/v8/ScriptGCEvent.cpp b/WebCore/bindings/v8/ScriptGCEvent.cpp new file mode 100644 index 0000000..a58a0cd --- /dev/null +++ b/WebCore/bindings/v8/ScriptGCEvent.cpp @@ -0,0 +1,101 @@ +/* +* Copyright (C) 2010 Google Inc. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following disclaimer +* in the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Google Inc. nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "config.h" + +#if ENABLE(INSPECTOR) + +#include "ScriptGCEvent.h" +#include "ScriptGCEventListener.h" + +#include <wtf/CurrentTime.h> + +namespace WebCore { + +ScriptGCEvent::GCEventListeners ScriptGCEvent::s_eventListeners; +double ScriptGCEvent::s_startTime = 0.0; +size_t ScriptGCEvent::s_usedHeapSize = 0; + +void ScriptGCEvent::addEventListener(ScriptGCEventListener* eventListener) +{ + ASSERT(eventListener); + if (s_eventListeners.isEmpty()) { + v8::V8::AddGCPrologueCallback(ScriptGCEvent::gcPrologueCallback); + v8::V8::AddGCEpilogueCallback(ScriptGCEvent::gcEpilogueCallback); + } + s_eventListeners.append(eventListener); +} + +void ScriptGCEvent::removeEventListener(ScriptGCEventListener* eventListener) +{ + ASSERT(eventListener); + ASSERT(!s_eventListeners.isEmpty()); + size_t i = s_eventListeners.find(eventListener); + ASSERT(i != notFound); + s_eventListeners.remove(i); + if (s_eventListeners.isEmpty()) { + v8::V8::RemoveGCPrologueCallback(ScriptGCEvent::gcPrologueCallback); + v8::V8::RemoveGCEpilogueCallback(ScriptGCEvent::gcEpilogueCallback); + } +} + +void ScriptGCEvent::getHeapSize(size_t& usedHeapSize, size_t& totalHeapSize) +{ + v8::HeapStatistics heapStatistics; + v8::V8::GetHeapStatistics(&heapStatistics); + usedHeapSize = heapStatistics.used_heap_size(); + totalHeapSize = heapStatistics.total_heap_size(); +} + +size_t ScriptGCEvent::getUsedHeapSize() +{ + v8::HeapStatistics heapStatistics; + v8::V8::GetHeapStatistics(&heapStatistics); + return heapStatistics.used_heap_size(); +} + +void ScriptGCEvent::gcPrologueCallback(v8::GCType type, v8::GCCallbackFlags flags) +{ + s_startTime = WTF::currentTimeMS(); + s_usedHeapSize = getUsedHeapSize(); +} + +void ScriptGCEvent::gcEpilogueCallback(v8::GCType type, v8::GCCallbackFlags flags) +{ + double endTime = WTF::currentTimeMS(); + size_t collectedBytes = s_usedHeapSize - getUsedHeapSize(); + GCEventListeners listeners(s_eventListeners); + for (GCEventListeners::iterator i = listeners.begin(); i != listeners.end(); ++i) + (*i)->didGC(s_startTime, endTime, collectedBytes); +} + +} // namespace WebCore + +#endif // ENABLE(INSPECTOR) diff --git a/WebCore/bindings/v8/ScriptGCEvent.h b/WebCore/bindings/v8/ScriptGCEvent.h new file mode 100644 index 0000000..80a5a38 --- /dev/null +++ b/WebCore/bindings/v8/ScriptGCEvent.h @@ -0,0 +1,63 @@ +/* +* Copyright (C) 2010 Google Inc. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following disclaimer +* in the documentation and/or other materials provided with the +* distribution. +* * Neither the name of Google Inc. nor the names of its +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef ScriptGCEvent_h +#define ScriptGCEvent_h + +#if ENABLE(INSPECTOR) + +#include "v8.h" +#include <wtf/Vector.h> + +namespace WebCore { + +class ScriptGCEventListener; + +class ScriptGCEvent +{ +public: + static void addEventListener(ScriptGCEventListener*); + static void removeEventListener(ScriptGCEventListener*); + static void getHeapSize(size_t&, size_t&); +private: + typedef Vector<ScriptGCEventListener*> GCEventListeners; + static GCEventListeners s_eventListeners; + static double s_startTime; + static size_t s_usedHeapSize; + + static void gcEpilogueCallback(v8::GCType type, v8::GCCallbackFlags flags); + static void gcPrologueCallback(v8::GCType type, v8::GCCallbackFlags flags); + static size_t getUsedHeapSize(); +}; + +} // namespace WebCore + +#endif // !ENABLE(INSPECTOR) +#endif // !defined(ScriptGCEvent_h) diff --git a/WebCore/bindings/v8/custom/V8IDBRequestCustom.cpp b/WebCore/bindings/v8/ScriptProfile.cpp index ccf4d0e..beafea1 100644 --- a/WebCore/bindings/v8/custom/V8IDBRequestCustom.cpp +++ b/WebCore/bindings/v8/ScriptProfile.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (c) 2010, Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -30,24 +30,27 @@ #include "config.h" -#if ENABLE(INDEXED_DATABASE) -#include "V8IDBRequest.h" +#include "ScriptProfile.h" -#include "SerializedScriptValue.h" -#include "V8Proxy.h" +#include "V8Binding.h" + +#include <v8-profiler.h> namespace WebCore { -v8::Handle<v8::Value> V8IDBRequest::resultAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +String ScriptProfile::title() const { - IDBRequest* request = V8IDBRequest::toNative(info.Holder()); - SerializedScriptValue* result = request->result(); - if (!result) - return v8::Null(); + return toWebCoreString(m_profile->GetTitle()); +} - return result->deserialize(); +unsigned int ScriptProfile::uid() const +{ + return m_profile->GetUid(); } -} // namespace WebCore +PassRefPtr<ScriptProfileNode> ScriptProfile::head() const +{ + return ScriptProfileNode::create(m_profile->GetTopDownRoot()); +} -#endif +} // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptProfile.h b/WebCore/bindings/v8/ScriptProfile.h index 1a4d677..2f42ad2 100644 --- a/WebCore/bindings/v8/ScriptProfile.h +++ b/WebCore/bindings/v8/ScriptProfile.h @@ -32,29 +32,33 @@ #define ScriptProfile_h #include "PlatformString.h" +#include "ScriptProfileNode.h" + +namespace v8 { +class CpuProfile; +} namespace WebCore { class ScriptProfile : public RefCounted<ScriptProfile> { public: - static PassRefPtr<ScriptProfile> create(const String& title, unsigned uid) + static PassRefPtr<ScriptProfile> create(const v8::CpuProfile* profile) { - return adoptRef(new ScriptProfile(title, uid)); + return adoptRef(new ScriptProfile(profile)); } virtual ~ScriptProfile() {} - String title() const { return m_title; } - unsigned int uid() const { return m_uid; } + String title() const; + unsigned int uid() const; + PassRefPtr<ScriptProfileNode> head() const; protected: - ScriptProfile(const String& title, unsigned uid) - : m_title(title) - , m_uid(uid) + ScriptProfile(const v8::CpuProfile* profile) + : m_profile(profile) {} private: - String m_title; - unsigned int m_uid; + const v8::CpuProfile* m_profile; }; } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptProfileNode.cpp b/WebCore/bindings/v8/ScriptProfileNode.cpp new file mode 100644 index 0000000..3121128 --- /dev/null +++ b/WebCore/bindings/v8/ScriptProfileNode.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2010, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "ScriptProfile.h" + +#include "V8Binding.h" + +#include <v8-profiler.h> + +namespace WebCore { + +String ScriptProfileNode::functionName() const +{ + return toWebCoreString(m_profileNode->GetFunctionName()); +} + +String ScriptProfileNode::url() const +{ + return toWebCoreString(m_profileNode->GetScriptResourceName()); +} + +unsigned long ScriptProfileNode::lineNumber() const +{ + return m_profileNode->GetLineNumber(); +} + +double ScriptProfileNode::totalTime() const +{ + // FIXME: use GetTotalMilliseconds once it is implemented in V8. + return m_profileNode->GetTotalSamplesCount(); +} + +double ScriptProfileNode::selfTime() const +{ + // FIXME: use GetSelfMilliseconds once it is implemented in V8. + return m_profileNode->GetSelfSamplesCount(); +} + +unsigned long ScriptProfileNode::numberOfCalls() const +{ + return 0; +} + +ProfileNodesList ScriptProfileNode::children() const +{ + const int childrenCount = m_profileNode->GetChildrenCount(); + ProfileNodesList result(childrenCount); + for (int i = 0; i < childrenCount; ++i) + result[i] = ScriptProfileNode::create(m_profileNode->GetChild(i)); + return result; +} + +bool ScriptProfileNode::visible() const +{ + return true; +} + +unsigned long ScriptProfileNode::callUID() const +{ + return m_profileNode->GetCallUid(); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptProfileNode.h b/WebCore/bindings/v8/ScriptProfileNode.h new file mode 100644 index 0000000..5acf319 --- /dev/null +++ b/WebCore/bindings/v8/ScriptProfileNode.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2010, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ScriptProfileNode_h +#define ScriptProfileNode_h + +#include "PlatformString.h" + +namespace v8 { +class CpuProfileNode; +} + +namespace WebCore { + +class ScriptProfileNode; + +typedef Vector<RefPtr<ScriptProfileNode> > ProfileNodesList; + +class ScriptProfileNode : public RefCounted<ScriptProfileNode> { +public: + static PassRefPtr<ScriptProfileNode> create(const v8::CpuProfileNode* profileNode) + { + return adoptRef(new ScriptProfileNode(profileNode)); + } + virtual ~ScriptProfileNode() {} + + String functionName() const; + String url() const; + unsigned long lineNumber() const; + double totalTime() const; + double selfTime() const; + unsigned long numberOfCalls() const; + ProfileNodesList children() const; + bool visible() const; + unsigned long callUID() const; + +protected: + ScriptProfileNode(const v8::CpuProfileNode* profileNode) + : m_profileNode(profileNode) + {} + +private: + const v8::CpuProfileNode* m_profileNode; +}; + +} // namespace WebCore + +#endif // ScriptProfileNode_h diff --git a/WebCore/bindings/v8/ScriptProfiler.cpp b/WebCore/bindings/v8/ScriptProfiler.cpp index f238f6f..1f09420 100644 --- a/WebCore/bindings/v8/ScriptProfiler.cpp +++ b/WebCore/bindings/v8/ScriptProfiler.cpp @@ -31,20 +31,23 @@ #include "config.h" #include "ScriptProfiler.h" +#include "ScriptString.h" + +#include <v8-profiler.h> namespace WebCore { void ScriptProfiler::start(ScriptState* state, const String& title) { - v8::HandleScope scope; - v8::Context::Scope contextScope(v8::Context::GetCurrent()); - v8::V8::ResumeProfiler(); + v8::HandleScope hs; + v8::CpuProfiler::StartProfiling(v8String(title)); } PassRefPtr<ScriptProfile> ScriptProfiler::stop(ScriptState* state, const String& title) { - v8::V8::PauseProfiler(); - return 0; + v8::HandleScope hs; + const v8::CpuProfile* profile = v8::CpuProfiler::StopProfiling(v8String(title)); + return profile ? ScriptProfile::create(profile) : 0; } } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptState.h b/WebCore/bindings/v8/ScriptState.h index 5c5ce6c..ce350da 100644 --- a/WebCore/bindings/v8/ScriptState.h +++ b/WebCore/bindings/v8/ScriptState.h @@ -37,55 +37,77 @@ #include <wtf/RefCounted.h> namespace WebCore { - class DOMWrapperWorld; - class Frame; - class Node; - class Page; - - class ScriptState : public Noncopyable { - public: - bool hadException() { return !m_exception.IsEmpty(); } - void setException(v8::Local<v8::Value> exception) - { - m_exception = exception; +class DOMWrapperWorld; +class Frame; +class Node; +class Page; + +class ScriptState : public Noncopyable { +public: + bool hadException() { return !m_exception.IsEmpty(); } + void setException(v8::Local<v8::Value> exception) + { + m_exception = exception; + } + v8::Local<v8::Value> exception() { return m_exception; } + + v8::Local<v8::Context> context() const + { + return v8::Local<v8::Context>::New(m_context); + } + + static ScriptState* forContext(v8::Local<v8::Context>); + static ScriptState* current(); + +protected: + ScriptState() { } + ~ScriptState(); + +private: + friend ScriptState* mainWorldScriptState(Frame*); + explicit ScriptState(v8::Handle<v8::Context>); + + static void weakReferenceCallback(v8::Persistent<v8::Value> object, void* parameter); + + v8::Local<v8::Value> m_exception; + v8::Persistent<v8::Context> m_context; +}; + +class EmptyScriptState : public ScriptState { +public: + EmptyScriptState() : ScriptState() { } + ~EmptyScriptState() { } +}; + +class ScriptStateProtectedPtr : public Noncopyable { +public: + ScriptStateProtectedPtr() : m_scriptState(0) { } + ScriptStateProtectedPtr(ScriptState* scriptState) : m_scriptState(scriptState) + { + v8::HandleScope handleScope; + // Keep the context from being GC'ed. ScriptState is guaranteed to be live while the context is live. + m_context = v8::Persistent<v8::Context>::New(scriptState->context()); + } + ~ScriptStateProtectedPtr() + { + if (!m_context.IsEmpty()) { + m_context.Dispose(); + m_context.Clear(); } - v8::Local<v8::Value> exception() { return m_exception; } + } + ScriptState* get() { return m_scriptState; } +private: + ScriptState* m_scriptState; + v8::Persistent<v8::Context> m_context; +}; - v8::Local<v8::Context> context() const - { - return v8::Local<v8::Context>::New(m_context); - } - - static ScriptState* forContext(v8::Local<v8::Context>); - static ScriptState* current(); - - protected: - ScriptState() { } - ~ScriptState(); - - private: - friend ScriptState* mainWorldScriptState(Frame*); - explicit ScriptState(v8::Handle<v8::Context>); - - static void weakReferenceCallback(v8::Persistent<v8::Value> object, void* parameter); - - v8::Local<v8::Value> m_exception; - v8::Persistent<v8::Context> m_context; - }; - - class EmptyScriptState : public ScriptState { - public: - EmptyScriptState() : ScriptState() { } - ~EmptyScriptState() { } - }; - - ScriptState* mainWorldScriptState(Frame*); +ScriptState* mainWorldScriptState(Frame*); - ScriptState* scriptStateFromNode(DOMWrapperWorld*, Node*); - ScriptState* scriptStateFromPage(DOMWrapperWorld*, Page*); +ScriptState* scriptStateFromNode(DOMWrapperWorld*, Node*); +ScriptState* scriptStateFromPage(DOMWrapperWorld*, Page*); - inline DOMWrapperWorld* debuggerWorld() { return mainThreadNormalWorld(); } - inline DOMWrapperWorld* pluginWorld() { return mainThreadNormalWorld(); } +inline DOMWrapperWorld* debuggerWorld() { return mainThreadNormalWorld(); } +inline DOMWrapperWorld* pluginWorld() { return mainThreadNormalWorld(); } } diff --git a/WebCore/bindings/v8/ScriptValue.h b/WebCore/bindings/v8/ScriptValue.h index 1713f80..8241205 100644 --- a/WebCore/bindings/v8/ScriptValue.h +++ b/WebCore/bindings/v8/ScriptValue.h @@ -127,6 +127,8 @@ public: PassRefPtr<SerializedScriptValue> serialize(ScriptState*); static ScriptValue deserialize(ScriptState*, SerializedScriptValue*); + static ScriptValue undefined() { return ScriptValue(v8::Undefined()); } + void clear() { if (m_value.IsEmpty()) diff --git a/WebCore/bindings/v8/SerializedScriptValue.cpp b/WebCore/bindings/v8/SerializedScriptValue.cpp index bac7f20..50ac86b 100644 --- a/WebCore/bindings/v8/SerializedScriptValue.cpp +++ b/WebCore/bindings/v8/SerializedScriptValue.cpp @@ -31,7 +31,18 @@ #include "config.h" #include "SerializedScriptValue.h" +#include "Blob.h" +#include "ByteArray.h" +#include "CanvasPixelArray.h" +#include "File.h" +#include "FileList.h" +#include "ImageData.h" #include "SharedBuffer.h" +#include "V8Blob.h" +#include "V8File.h" +#include "V8FileList.h" +#include "V8ImageData.h" +#include "V8Proxy.h" #include <v8.h> #include <wtf/Assertions.h> @@ -40,7 +51,6 @@ // FIXME: // - catch V8 exceptions -// - be ready to get empty handles // - consider crashing in debug mode on deserialization errors namespace WebCore { @@ -60,19 +70,18 @@ enum SerializationTag { FalseTag = 'F', StringTag = 'S', Int32Tag = 'I', + Uint32Tag = 'U', + DateTag = 'D', NumberTag = 'N', - ObjectTag = '{', + BlobTag = 'b', + FileTag = 'f', + FileListTag = 'l', + ImageDataTag = '#', ArrayTag = '[', + ObjectTag = '{', + SparseArrayTag = '@', }; -// Helpers to do verbose handle casts. - -template <typename T, typename U> -static v8::Handle<T> handleCast(v8::Handle<U> handle) { return v8::Handle<T>::Cast(handle); } - -template <typename T, typename U> -static v8::Local<T> handleCast(v8::Local<U> handle) { return v8::Local<T>::Cast(handle); } - static bool shouldCheckForCycles(int depth) { ASSERT(depth >= 0); @@ -118,7 +127,8 @@ private: // information used to reconstruct composite types. class Writer : Noncopyable { public: - Writer() : m_position(0) + Writer() + : m_position(0) { } @@ -134,9 +144,17 @@ public: void writeString(const char* data, int length) { + ASSERT(length >= 0); append(StringTag); - doWriteUint32(static_cast<uint32_t>(length)); - append(data, length); + doWriteString(data, length); + } + + void writeWebCoreString(const String& string) + { + // Uses UTF8 encoding so we can read it back as either V8 or + // WebCore string. + append(StringTag); + doWriteWebCoreString(string); } void writeInt32(int32_t value) @@ -145,19 +163,71 @@ public: doWriteUint32(ZigZag::encode(static_cast<uint32_t>(value))); } + void writeUint32(uint32_t value) + { + append(Uint32Tag); + doWriteUint32(value); + } + + void writeDate(double numberValue) + { + append(DateTag); + doWriteNumber(numberValue); + } + void writeNumber(double number) { append(NumberTag); - append(reinterpret_cast<char*>(&number), sizeof(number)); + doWriteNumber(number); } - // Records that a composite object can be constructed by using - // |length| previously stored values. - void endComposite(SerializationTag tag, int32_t length) + void writeBlob(const String& path) { - ASSERT(tag == ObjectTag || tag == ArrayTag); - append(tag); - doWriteUint32(static_cast<uint32_t>(length)); + append(BlobTag); + doWriteWebCoreString(path); + } + + void writeFile(const String& path) + { + append(FileTag); + doWriteWebCoreString(path); + } + + void writeFileList(const FileList& fileList) + { + append(FileListTag); + uint32_t length = fileList.length(); + doWriteUint32(length); + for (unsigned i = 0; i < length; ++i) + doWriteWebCoreString(fileList.item(i)->path()); + } + + void writeImageData(uint32_t width, uint32_t height, const uint8_t* pixelData, uint32_t pixelDataLength) + { + append(ImageDataTag); + doWriteUint32(width); + doWriteUint32(height); + doWriteUint32(pixelDataLength); + append(pixelData, pixelDataLength); + } + + void writeArray(uint32_t length) + { + append(ArrayTag); + doWriteUint32(length); + } + + void writeObject(uint32_t numProperties) + { + append(ObjectTag); + doWriteUint32(numProperties); + } + + void writeSparseArray(uint32_t numProperties, uint32_t length) + { + append(SparseArrayTag); + doWriteUint32(numProperties); + doWriteUint32(length); } Vector<BufferValueType>& data() @@ -167,10 +237,22 @@ public: } private: + void doWriteString(const char* data, int length) + { + doWriteUint32(static_cast<uint32_t>(length)); + append(reinterpret_cast<const uint8_t*>(data), length); + } + + void doWriteWebCoreString(const String& string) + { + RefPtr<SharedBuffer> buffer = utf8Buffer(string); + doWriteString(buffer->data(), buffer->size()); + } + void doWriteUint32(uint32_t value) { while (true) { - char b = (value & varIntMask); + uint8_t b = (value & varIntMask); value >>= varIntShift; if (!value) { append(b); @@ -180,21 +262,26 @@ private: } } + void doWriteNumber(double number) + { + append(reinterpret_cast<uint8_t*>(&number), sizeof(number)); + } + void append(SerializationTag tag) { - append(static_cast<char>(tag)); + append(static_cast<uint8_t>(tag)); } - void append(char b) + void append(uint8_t b) { ensureSpace(1); - *charAt(m_position++) = b; + *byteAt(m_position++) = b; } - void append(const char* data, int length) + void append(const uint8_t* data, int length) { ensureSpace(length); - memcpy(charAt(m_position), data, length); + memcpy(byteAt(m_position), data, length); m_position += length; } @@ -210,41 +297,54 @@ private: // If the writer is at odd position in the buffer, then one of // the bytes in the last UChar is not initialized. if (m_position % 2) - *charAt(m_position) = static_cast<char>(PaddingTag); + *byteAt(m_position) = static_cast<uint8_t>(PaddingTag); } - char* charAt(int position) { return reinterpret_cast<char*>(m_buffer.data()) + position; } + uint8_t* byteAt(int position) { return reinterpret_cast<uint8_t*>(m_buffer.data()) + position; } Vector<BufferValueType> m_buffer; unsigned m_position; }; class Serializer { + class StateBase; public: explicit Serializer(Writer& writer) : m_writer(writer) - , m_state(0) , m_depth(0) + , m_hasError(false) { } bool serialize(v8::Handle<v8::Value> value) { v8::HandleScope scope; - StackCleaner cleaner(&m_state); - if (!doSerialize(value)) - return false; - while (top()) { - int length; - while (!top()->isDone(&length)) { - // Note that doSerialize() can change current top(). - if (!doSerialize(top()->advance())) - return false; - } - m_writer.endComposite(top()->tag(), length); - pop(); - } - return true; + StateBase* state = doSerialize(value, 0); + while (state) + state = state->advance(*this); + return !m_hasError; + } + + // Functions used by serialization states. + + StateBase* doSerialize(v8::Handle<v8::Value> value, StateBase* next); + + StateBase* writeArray(uint32_t length, StateBase* state) + { + m_writer.writeArray(length); + return pop(state); + } + + StateBase* writeObject(uint32_t numProperties, StateBase* state) + { + m_writer.writeObject(numProperties); + return pop(state); + } + + StateBase* writeSparseArray(uint32_t numProperties, uint32_t length, StateBase* state) + { + m_writer.writeSparseArray(numProperties, length); + return pop(state); } private: @@ -254,221 +354,308 @@ private: // Link to the next state to form a stack. StateBase* nextState() { return m_next; } - void setNextState(StateBase* next) { m_next = next; } // Composite object we're processing in this state. v8::Handle<v8::Value> composite() { return m_composite; } - // Serialization tag for the current composite. - virtual SerializationTag tag() const = 0; - - // Returns whether iteration over subobjects of the current - // composite object is done. If yes, |*length| is set to the - // number of subobjects. - virtual bool isDone(int* length) = 0; - - // Advances to the next subobject. - // Requires: !this->isDone(). - virtual v8::Local<v8::Value> advance() = 0; + // Serializes (a part of) the current composite and returns + // the next state to process or null when this is the final + // state. + virtual StateBase* advance(Serializer&) = 0; protected: - StateBase(v8::Handle<v8::Value> composite) - : m_next(0) - , m_composite(composite) + StateBase(v8::Handle<v8::Value> composite, StateBase* next) + : m_composite(composite) + , m_next(next) { } private: - StateBase* m_next; v8::Handle<v8::Value> m_composite; + StateBase* m_next; }; - template <typename T, SerializationTag compositeTag> - class State : public StateBase { + // Dummy state that is used to signal serialization errors. + class ErrorState : public StateBase { public: - v8::Handle<T> composite() { return handleCast<T>(StateBase::composite()); } + ErrorState() + : StateBase(v8::Handle<v8::Value>(), 0) + { + } - virtual SerializationTag tag() const { return compositeTag; } + virtual StateBase* advance(Serializer&) + { + delete this; + return 0; + } + }; + + template <typename T> + class State : public StateBase { + public: + v8::Handle<T> composite() { return v8::Handle<T>::Cast(StateBase::composite()); } protected: - explicit State(v8::Handle<T> composite) : StateBase(composite) + State(v8::Handle<T> composite, StateBase* next) + : StateBase(composite, next) { } }; - // Helper to clean up the state stack in case of errors. - class StackCleaner : Noncopyable { +#if 0 + // Currently unused, see comment in newArrayState. + class ArrayState : public State<v8::Array> { public: - explicit StackCleaner(StateBase** stack) : m_stack(stack) + ArrayState(v8::Handle<v8::Array> array, StateBase* next) + : State<v8::Array>(array, next) + , m_index(-1) { } - ~StackCleaner() + virtual StateBase* advance(Serializer& serializer) { - StateBase* state = *m_stack; - while (state) { - StateBase* tmp = state->nextState(); - delete state; - state = tmp; + ++m_index; + for (; m_index < composite()->Length(); ++m_index) { + if (StateBase* newState = serializer.doSerialize(composite()->Get(m_index), this)) + return newState; } - *m_stack = 0; + return serializer.writeArray(composite()->Length(), this); } private: - StateBase** m_stack; + unsigned m_index; }; +#endif - class ArrayState : public State<v8::Array, ArrayTag> { + class AbstractObjectState : public State<v8::Object> { public: - ArrayState(v8::Handle<v8::Array> array) - : State<v8::Array, ArrayTag>(array) - , m_index(0) + AbstractObjectState(v8::Handle<v8::Object> object, StateBase* next) + : State<v8::Object>(object, next) + , m_propertyNames(object->GetPropertyNames()) + , m_index(-1) + , m_numSerializedProperties(0) + , m_nameDone(false) { } - virtual bool isDone(int* length) + virtual StateBase* advance(Serializer& serializer) { - *length = composite()->Length(); - return static_cast<int>(m_index) >= *length; + ++m_index; + for (; m_index < m_propertyNames->Length(); ++m_index) { + if (m_propertyName.IsEmpty()) { + v8::Local<v8::Value> propertyName = m_propertyNames->Get(m_index); + if ((propertyName->IsString() && composite()->HasRealNamedProperty(propertyName.As<v8::String>())) + || (propertyName->IsUint32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value()))) { + m_propertyName = propertyName; + } else + continue; + } + ASSERT(!m_propertyName.IsEmpty()); + if (!m_nameDone) { + m_nameDone = true; + if (StateBase* newState = serializer.doSerialize(m_propertyName, this)) + return newState; + } + v8::Local<v8::Value> value = composite()->Get(m_propertyName); + m_nameDone = false; + m_propertyName.Clear(); + ++m_numSerializedProperties; + if (StateBase* newState = serializer.doSerialize(value, this)) + return newState; + } + return objectDone(m_numSerializedProperties, serializer); } - virtual v8::Local<v8::Value> advance() - { - ASSERT(m_index < composite()->Length()); - v8::HandleScope scope; - return scope.Close(composite()->Get(v8::Integer::New(m_index++))); - } + protected: + virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0; private: + v8::Local<v8::Array> m_propertyNames; + v8::Local<v8::Value> m_propertyName; unsigned m_index; + unsigned m_numSerializedProperties; + bool m_nameDone; }; - class ObjectState : public State<v8::Object, ObjectTag> { + class ObjectState : public AbstractObjectState { public: - ObjectState(v8::Handle<v8::Object> object) - : State<v8::Object, ObjectTag>(object) - , m_propertyNames(object->GetPropertyNames()) - , m_index(-1) - , m_length(0) + ObjectState(v8::Handle<v8::Object> object, StateBase* next) + : AbstractObjectState(object, next) { - nextProperty(); } - virtual bool isDone(int* length) + protected: + virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) { - *length = m_length; - return m_index >= 2 * m_propertyNames->Length(); + return serializer.writeObject(numProperties, this); } + }; - virtual v8::Local<v8::Value> advance() + class SparseArrayState : public AbstractObjectState { + public: + SparseArrayState(v8::Handle<v8::Array> array, StateBase* next) + : AbstractObjectState(array, next) { - ASSERT(m_index < 2 * m_propertyNames->Length()); - if (!(m_index % 2)) { - ++m_index; - return m_propertyName; - } - v8::Local<v8::Value> result = composite()->Get(m_propertyName); - nextProperty(); - return result; } - private: - void nextProperty() + protected: + virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) { - v8::HandleScope scope; - ++m_index; - ASSERT(!(m_index % 2)); - for (; m_index < 2 * m_propertyNames->Length(); m_index += 2) { - v8::Local<v8::Value> propertyName = m_propertyNames->Get(v8::Integer::New(m_index / 2)); - if ((propertyName->IsString() && composite()->HasRealNamedProperty(handleCast<v8::String>(propertyName))) - || (propertyName->IsInt32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value()))) { - m_propertyName = scope.Close(propertyName); - m_length += 2; - return; - } - } + return serializer.writeSparseArray(numProperties, composite().As<v8::Array>()->Length(), this); } - - v8::Local<v8::Array> m_propertyNames; - v8::Local<v8::Value> m_propertyName; - unsigned m_index; - unsigned m_length; }; - bool doSerialize(v8::Handle<v8::Value> value) - { - if (value->IsUndefined()) - m_writer.writeUndefined(); - else if (value->IsNull()) - m_writer.writeNull(); - else if (value->IsTrue()) - m_writer.writeTrue(); - else if (value->IsFalse()) - m_writer.writeFalse(); - else if (value->IsInt32()) - m_writer.writeInt32(value->Int32Value()); - else if (value->IsNumber()) - m_writer.writeNumber(handleCast<v8::Number>(value)->Value()); - else if (value->IsString()) { - v8::String::Utf8Value stringValue(value); - m_writer.writeString(*stringValue, stringValue.length()); - } else if (value->IsArray()) { - if (!checkComposite(value)) - return false; - push(new ArrayState(handleCast<v8::Array>(value))); - } else if (value->IsObject()) { - if (!checkComposite(value)) - return false; - push(new ObjectState(handleCast<v8::Object>(value))); - // FIXME: - // - check not a wrapper - // - support File, ImageData, etc. - } - return true; - } - - void push(StateBase* state) + StateBase* push(StateBase* state) { - state->setNextState(m_state); - m_state = state; + ASSERT(state); ++m_depth; + return checkComposite(state) ? state : handleError(state); } - StateBase* top() { return m_state; } - - void pop() + StateBase* pop(StateBase* state) { - if (!m_state) - return; - StateBase* top = m_state; - m_state = top->nextState(); - delete top; + ASSERT(state); --m_depth; + StateBase* next = state->nextState(); + delete state; + return next; + } + + StateBase* handleError(StateBase* state) + { + m_hasError = true; + while (state) { + StateBase* tmp = state->nextState(); + delete state; + state = tmp; + } + return new ErrorState; } - bool checkComposite(v8::Handle<v8::Value> composite) + bool checkComposite(StateBase* top) { + ASSERT(top); if (m_depth > maxDepth) return false; if (!shouldCheckForCycles(m_depth)) return true; - for (StateBase* state = top(); state; state = state->nextState()) { + v8::Handle<v8::Value> composite = top->composite(); + for (StateBase* state = top->nextState(); state; state = state->nextState()) { if (state->composite() == composite) return false; } return true; } + void writeString(v8::Handle<v8::Value> value) + { + v8::String::Utf8Value stringValue(value); + m_writer.writeString(*stringValue, stringValue.length()); + } + + void writeBlob(v8::Handle<v8::Value> value) + { + Blob* blob = V8Blob::toNative(value.As<v8::Object>()); + if (!blob) + return; + m_writer.writeBlob(blob->path()); + } + + void writeFile(v8::Handle<v8::Value> value) + { + File* file = V8File::toNative(value.As<v8::Object>()); + if (!file) + return; + m_writer.writeFile(file->path()); + } + + void writeFileList(v8::Handle<v8::Value> value) + { + FileList* fileList = V8FileList::toNative(value.As<v8::Object>()); + if (!fileList) + return; + m_writer.writeFileList(*fileList); + } + + void writeImageData(v8::Handle<v8::Value> value) + { + ImageData* imageData = V8ImageData::toNative(value.As<v8::Object>()); + if (!imageData) + return; + WTF::ByteArray* pixelArray = imageData->data()->data(); + m_writer.writeImageData(imageData->width(), imageData->height(), pixelArray->data(), pixelArray->length()); + } + + static StateBase* newArrayState(v8::Handle<v8::Array> array, StateBase* next) + { + // FIXME: use plain Array state when we can quickly check that + // an array is not sparse and has only indexed properties. + return new SparseArrayState(array, next); + } + + static StateBase* newObjectState(v8::Handle<v8::Object> object, StateBase* next) + { + // FIXME: + // - check not a wrapper + // - support File, etc. + return new ObjectState(object, next); + } + Writer& m_writer; - StateBase* m_state; int m_depth; + bool m_hasError; +}; + +Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, StateBase* next) +{ + if (value->IsUndefined()) + m_writer.writeUndefined(); + else if (value->IsNull()) + m_writer.writeNull(); + else if (value->IsTrue()) + m_writer.writeTrue(); + else if (value->IsFalse()) + m_writer.writeFalse(); + else if (value->IsInt32()) + m_writer.writeInt32(value->Int32Value()); + else if (value->IsUint32()) + m_writer.writeUint32(value->Uint32Value()); + else if (value->IsDate()) + m_writer.writeDate(value->NumberValue()); + else if (value->IsNumber()) + m_writer.writeNumber(value.As<v8::Number>()->Value()); + else if (value->IsString()) + writeString(value); + else if (value->IsArray()) + return push(newArrayState(value.As<v8::Array>(), next)); + else if (V8File::HasInstance(value)) + writeFile(value); + else if (V8Blob::HasInstance(value)) + writeBlob(value); + else if (V8FileList::HasInstance(value)) + writeFileList(value); + else if (V8ImageData::HasInstance(value)) + writeImageData(value); + else if (value->IsObject()) + return push(newObjectState(value.As<v8::Object>(), next)); + return 0; +} + +// Interface used by Reader to create objects of composite types. +class CompositeCreator { +public: + virtual ~CompositeCreator() { } + + virtual bool createArray(uint32_t length, v8::Handle<v8::Value>* value) = 0; + virtual bool createObject(uint32_t numProperties, v8::Handle<v8::Value>* value) = 0; + virtual bool createSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) = 0; }; // Reader is responsible for deserializing primitive types and // restoring information about saved objects of composite types. class Reader { public: - Reader(const char* buffer, int length) + Reader(const uint8_t* buffer, int length) : m_buffer(buffer) , m_length(length) , m_position(0) @@ -478,16 +665,16 @@ public: bool isEof() const { return m_position >= m_length; } - bool read(SerializationTag* tag, v8::Handle<v8::Value>* value, int* length) + bool read(v8::Handle<v8::Value>* value, CompositeCreator& creator) { - uint32_t rawLength; - if (!readTag(tag)) + SerializationTag tag; + if (!readTag(&tag)) return false; - switch (*tag) { + switch (tag) { case InvalidTag: return false; case PaddingTag: - break; + return true; case UndefinedTag: *value = v8::Undefined(); break; @@ -508,18 +695,65 @@ public: if (!readInt32(value)) return false; break; + case Uint32Tag: + if (!readUint32(value)) + return false; + break; + case DateTag: + if (!readDate(value)) + return false; + break; case NumberTag: if (!readNumber(value)) return false; break; - case ObjectTag: - case ArrayTag: - if (!doReadUint32(&rawLength)) + case BlobTag: + if (!readBlob(value)) + return false; + break; + case FileTag: + if (!readFile(value)) + return false; + break; + case FileListTag: + if (!readFileList(value)) + return false; + break; + case ImageDataTag: + if (!readImageData(value)) + return false; + break; + case ArrayTag: { + uint32_t length; + if (!doReadUint32(&length)) + return false; + if (!creator.createArray(length, value)) return false; - *length = rawLength; break; } - return true; + case ObjectTag: { + uint32_t numProperties; + if (!doReadUint32(&numProperties)) + return false; + if (!creator.createObject(numProperties, value)) + return false; + break; + } + case SparseArrayTag: { + uint32_t numProperties; + uint32_t length; + if (!doReadUint32(&numProperties)) + return false; + if (!doReadUint32(&length)) + return false; + if (!creator.createSparseArray(numProperties, length, value)) + return false; + break; + } + default: + return false; + } + return !value->IsEmpty(); } private: @@ -538,7 +772,19 @@ private: return false; if (m_position + length > m_length) return false; - *value = v8::String::New(m_buffer + m_position, length); + *value = v8::String::New(reinterpret_cast<const char*>(m_buffer + m_position), length); + m_position += length; + return true; + } + + bool readWebCoreString(String* string) + { + uint32_t length; + if (!doReadUint32(&length)) + return false; + if (m_position + length > m_length) + return false; + *string = String::fromUTF8(reinterpret_cast<const char*>(m_buffer + m_position), length); m_position += length; return true; } @@ -552,22 +798,96 @@ private: return true; } - bool readNumber(v8::Handle<v8::Value>* value) + bool readUint32(v8::Handle<v8::Value>* value) { - if (m_position + sizeof(double) > m_length) + uint32_t rawValue; + if (!doReadUint32(&rawValue)) + return false; + *value = v8::Integer::New(rawValue); + return true; + } + + bool readDate(v8::Handle<v8::Value>* value) + { + double numberValue; + if (!doReadNumber(&numberValue)) return false; + *value = v8::Date::New(numberValue); + return true; + } + + bool readNumber(v8::Handle<v8::Value>* value) + { double number; - char* numberAsByteArray = reinterpret_cast<char*>(&number); - for (unsigned i = 0; i < sizeof(double); ++i) - numberAsByteArray[i] = m_buffer[m_position++]; + if (!doReadNumber(&number)) + return false; *value = v8::Number::New(number); return true; } + bool readImageData(v8::Handle<v8::Value>* value) + { + uint32_t width; + uint32_t height; + uint32_t pixelDataLength; + if (!doReadUint32(&width)) + return false; + if (!doReadUint32(&height)) + return false; + if (!doReadUint32(&pixelDataLength)) + return false; + if (m_position + pixelDataLength > m_length) + return false; + PassRefPtr<ImageData> imageData = ImageData::create(width, height); + WTF::ByteArray* pixelArray = imageData->data()->data(); + ASSERT(pixelArray); + ASSERT(pixelArray->length() >= pixelDataLength); + memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength); + m_position += pixelDataLength; + *value = toV8(imageData); + return true; + } + + bool readBlob(v8::Handle<v8::Value>* value) + { + String path; + if (!readWebCoreString(&path)) + return false; + PassRefPtr<Blob> blob = Blob::create(path); + *value = toV8(blob); + return true; + } + + bool readFile(v8::Handle<v8::Value>* value) + { + String path; + if (!readWebCoreString(&path)) + return false; + PassRefPtr<File> file = File::create(path); + *value = toV8(file); + return true; + } + + bool readFileList(v8::Handle<v8::Value>* value) + { + uint32_t length; + if (!doReadUint32(&length)) + return false; + PassRefPtr<FileList> fileList = FileList::create(); + for (unsigned i = 0; i < length; ++i) { + String path; + if (!readWebCoreString(&path)) + return false; + fileList->append(File::create(path)); + } + *value = toV8(fileList); + return true; + } + bool doReadUint32(uint32_t* value) { *value = 0; - char currentByte; + uint8_t currentByte; int shift = 0; do { if (m_position >= m_length) @@ -579,64 +899,94 @@ private: return true; } - const char* m_buffer; + bool doReadNumber(double* number) + { + if (m_position + sizeof(double) > m_length) + return false; + uint8_t* numberAsByteArray = reinterpret_cast<uint8_t*>(number); + for (unsigned i = 0; i < sizeof(double); ++i) + numberAsByteArray[i] = m_buffer[m_position++]; + return true; + } + + const uint8_t* m_buffer; const unsigned m_length; unsigned m_position; }; -class Deserializer { +class Deserializer : public CompositeCreator { public: - explicit Deserializer(Reader& reader) : m_reader(reader) + explicit Deserializer(Reader& reader) + : m_reader(reader) { } - v8::Local<v8::Value> deserialize() + v8::Handle<v8::Value> deserialize() { v8::HandleScope scope; while (!m_reader.isEof()) { if (!doDeserialize()) - return v8::Local<v8::Value>(); + return v8::Null(); } if (stackDepth() != 1) - return v8::Local<v8::Value>(); + return v8::Null(); return scope.Close(element(0)); } + virtual bool createArray(uint32_t length, v8::Handle<v8::Value>* value) + { + if (length > stackDepth()) + return false; + v8::Local<v8::Array> array = v8::Array::New(length); + if (array.IsEmpty()) + return false; + const int depth = stackDepth() - length; + for (unsigned i = 0; i < length; ++i) + array->Set(i, element(depth + i)); + pop(length); + *value = array; + return true; + } + + virtual bool createObject(uint32_t numProperties, v8::Handle<v8::Value>* value) + { + v8::Local<v8::Object> object = v8::Object::New(); + if (object.IsEmpty()) + return false; + return initializeObject(object, numProperties, value); + } + + virtual bool createSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) + { + v8::Local<v8::Array> array = v8::Array::New(length); + if (array.IsEmpty()) + return false; + return initializeObject(array, numProperties, value); + } + private: + bool initializeObject(v8::Handle<v8::Object> object, uint32_t numProperties, v8::Handle<v8::Value>* value) + { + unsigned length = 2 * numProperties; + if (length > stackDepth()) + return false; + for (unsigned i = stackDepth() - length; i < stackDepth(); i += 2) { + v8::Local<v8::Value> propertyName = element(i); + v8::Local<v8::Value> propertyValue = element(i + 1); + object->Set(propertyName, propertyValue); + } + pop(length); + *value = object; + return true; + } + bool doDeserialize() { - SerializationTag tag; v8::Local<v8::Value> value; - int length = 0; - if (!m_reader.read(&tag, &value, &length)) + if (!m_reader.read(&value, *this)) return false; - if (!value.IsEmpty()) { + if (!value.IsEmpty()) push(value); - } else if (tag == ObjectTag) { - if (length > stackDepth()) - return false; - v8::Local<v8::Object> object = v8::Object::New(); - for (int i = stackDepth() - length; i < stackDepth(); i += 2) { - v8::Local<v8::Value> propertyName = element(i); - v8::Local<v8::Value> propertyValue = element(i + 1); - object->Set(propertyName, propertyValue); - } - pop(length); - push(object); - } else if (tag == ArrayTag) { - if (length > stackDepth()) - return false; - v8::Local<v8::Array> array = v8::Array::New(length); - const int depth = stackDepth() - length; - { - v8::HandleScope scope; - for (int i = 0; i < length; ++i) - array->Set(v8::Integer::New(i), element(depth + i)); - } - pop(length); - push(array); - } else if (tag != PaddingTag) - return false; return true; } @@ -648,7 +998,7 @@ private: m_stack.shrink(m_stack.size() - length); } - int stackDepth() const { return m_stack.size(); } + unsigned stackDepth() const { return m_stack.size(); } v8::Local<v8::Value> element(unsigned index) { @@ -662,12 +1012,14 @@ private: } // namespace -SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value) +SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, bool& didThrow) { + didThrow = false; Writer writer; Serializer serializer(writer); if (!serializer.serialize(value)) { - // FIXME: throw exception + throwError(NOT_SUPPORTED_ERR); + didThrow = true; return; } m_data = StringImpl::adopt(writer.data()); @@ -679,19 +1031,18 @@ SerializedScriptValue::SerializedScriptValue(String data, StringDataMode mode) m_data = data; else { ASSERT(mode == StringValue); - RefPtr<SharedBuffer> buffer = utf8Buffer(data); Writer writer; - writer.writeString(buffer->data(), buffer->size()); + writer.writeWebCoreString(data); m_data = StringImpl::adopt(writer.data()); } } -v8::Local<v8::Value> SerializedScriptValue::deserialize() +v8::Handle<v8::Value> SerializedScriptValue::deserialize() { if (!m_data.impl()) - return v8::Local<v8::Value>(); + return v8::Null(); COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes); - Reader reader(reinterpret_cast<const char*>(m_data.impl()->characters()), 2 * m_data.length()); + Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters()), 2 * m_data.length()); Deserializer deserializer(reader); return deserializer.deserialize(); } diff --git a/WebCore/bindings/v8/SerializedScriptValue.h b/WebCore/bindings/v8/SerializedScriptValue.h index 7eb8935..8205a42 100644 --- a/WebCore/bindings/v8/SerializedScriptValue.h +++ b/WebCore/bindings/v8/SerializedScriptValue.h @@ -40,10 +40,36 @@ namespace WebCore { class SerializedScriptValue : public RefCounted<SerializedScriptValue> { public: + // Deserializes the given value and sets it as a property on the + // object. + static void deserializeAndSetProperty(v8::Handle<v8::Object> object, + const char* propertyName, + v8::PropertyAttribute attribute, + SerializedScriptValue* value) + { + if (!value) + return; + v8::Handle<v8::Value> deserialized = value->deserialize(); + object->ForceSet(v8::String::NewSymbol(propertyName), deserialized, attribute); + } + // Creates a serialized representation of the given V8 value. static PassRefPtr<SerializedScriptValue> create(v8::Handle<v8::Value> value) { - return adoptRef(new SerializedScriptValue(value)); + bool didThrow; + return adoptRef(new SerializedScriptValue(value, didThrow)); + } + + // Creates a serialized representation of the given V8 value. + // + // If a serialization error occurs (e.g., cyclic input value) this + // function returns an empty representation, schedules a V8 exception to + // be thrown using v8::ThrowException(), and sets |didThrow|. In this case + // the caller must not invoke any V8 operations until control returns to + // V8. When serialization is successful, |didThrow| is false. + static PassRefPtr<SerializedScriptValue> create(v8::Handle<v8::Value> value, bool& didThrow) + { + return adoptRef(new SerializedScriptValue(value, didThrow)); } // Creates a serialized value with the given data obtained from a @@ -74,9 +100,9 @@ public: String toWireString() const { return m_data; } - // Deserializes the value (in the current context). Returns an - // empty handle in case of failure. - v8::Local<v8::Value> deserialize(); + // Deserializes the value (in the current context). Returns a null value in + // case of failure. + v8::Handle<v8::Value> deserialize(); private: enum StringDataMode { @@ -86,7 +112,7 @@ private: SerializedScriptValue() { } - explicit SerializedScriptValue(v8::Handle<v8::Value>); + SerializedScriptValue(v8::Handle<v8::Value>, bool& didThrow); SerializedScriptValue(String data, StringDataMode mode); diff --git a/WebCore/bindings/v8/StaticDOMDataStore.cpp b/WebCore/bindings/v8/StaticDOMDataStore.cpp index 722051b..0b0d531 100644 --- a/WebCore/bindings/v8/StaticDOMDataStore.cpp +++ b/WebCore/bindings/v8/StaticDOMDataStore.cpp @@ -36,11 +36,11 @@ namespace WebCore { StaticDOMDataStore::StaticDOMDataStore(DOMData* domData) : DOMDataStore(domData) , m_staticDomNodeMap(&DOMDataStore::weakNodeCallback) - , m_staticDomObjectMap(domData, &DOMDataStore::weakDOMObjectCallback) - , m_staticActiveDomObjectMap(domData, &DOMDataStore::weakActiveDOMObjectCallback) + , m_staticDomObjectMap(&DOMDataStore::weakDOMObjectCallback) + , m_staticActiveDomObjectMap(&DOMDataStore::weakActiveDOMObjectCallback) #if ENABLE(SVG) - , m_staticDomSvgElementInstanceMap(domData, &DOMDataStore::weakSVGElementInstanceCallback) - , m_staticDomSvgObjectWithContextMap(domData, &DOMDataStore::weakSVGObjectWithContextCallback) + , m_staticDomSvgElementInstanceMap(&DOMDataStore::weakSVGElementInstanceCallback) + , m_staticDomSvgObjectWithContextMap(&DOMDataStore::weakSVGObjectWithContextCallback) #endif { m_domNodeMap = &m_staticDomNodeMap; diff --git a/WebCore/bindings/v8/StaticDOMDataStore.h b/WebCore/bindings/v8/StaticDOMDataStore.h index 64a90e0..d1e5a30 100644 --- a/WebCore/bindings/v8/StaticDOMDataStore.h +++ b/WebCore/bindings/v8/StaticDOMDataStore.h @@ -49,11 +49,11 @@ public: private: IntrusiveDOMWrapperMap m_staticDomNodeMap; - InternalDOMWrapperMap<void> m_staticDomObjectMap; - InternalDOMWrapperMap<void> m_staticActiveDomObjectMap; + DOMWrapperMap<void> m_staticDomObjectMap; + DOMWrapperMap<void> m_staticActiveDomObjectMap; #if ENABLE(SVG) - InternalDOMWrapperMap<SVGElementInstance> m_staticDomSvgElementInstanceMap; - InternalDOMWrapperMap<void> m_staticDomSvgObjectWithContextMap; + DOMWrapperMap<SVGElementInstance> m_staticDomSvgElementInstanceMap; + DOMWrapperMap<void> m_staticDomSvgObjectWithContextMap; #endif }; diff --git a/WebCore/bindings/v8/V8AbstractEventListener.cpp b/WebCore/bindings/v8/V8AbstractEventListener.cpp index 944fd57..6dc2b29 100644 --- a/WebCore/bindings/v8/V8AbstractEventListener.cpp +++ b/WebCore/bindings/v8/V8AbstractEventListener.cpp @@ -88,8 +88,6 @@ void V8AbstractEventListener::handleEvent(ScriptExecutionContext* context, Event v8::Handle<v8::Value> jsEvent = toV8(event); invokeEventHandler(context, event, jsEvent); - - Document::updateStyleForAllDocuments(); } void V8AbstractEventListener::disposeListenerObject() @@ -147,11 +145,8 @@ void V8AbstractEventListener::invokeEventHandler(ScriptExecutionContext* context if (!tryCatch.CanContinue()) return; - // If an error occurs while handling the event, it should be reported. - if (tryCatch.HasCaught()) { - reportException(0, tryCatch); - tryCatch.Reset(); - } + // If an error occurs while handling the event, it should be reported in a regular way. + tryCatch.Reset(); // Restore the old event. This must be done for all exit paths through this method. if (savedEvent.IsEmpty()) diff --git a/WebCore/bindings/v8/V8Binding.cpp b/WebCore/bindings/v8/V8Binding.cpp index 34020be..e0904d7 100644 --- a/WebCore/bindings/v8/V8Binding.cpp +++ b/WebCore/bindings/v8/V8Binding.cpp @@ -32,7 +32,6 @@ #include "V8Binding.h" #include "AtomicString.h" -#include "CString.h" #include "Element.h" #include "MathExtras.h" #include "PlatformString.h" @@ -43,6 +42,7 @@ #include "Threading.h" #include "V8Element.h" #include "V8Proxy.h" +#include <wtf/text/CString.h> #include <v8.h> @@ -174,6 +174,53 @@ int toInt32(v8::Handle<v8::Value> value, bool& ok) return intValue->Value(); } +uint32_t toUInt32(v8::Handle<v8::Value> value, bool& ok) +{ + ok = true; + + // FIXME: there is currently no Value::IsUint32(). This code does + // some contortions to avoid silently converting out-of-range + // values to uint32_t. + + // Fast case. The value is already a 32-bit positive integer. + if (value->IsInt32()) { + int32_t result = value->Int32Value(); + if (result >= 0) + return result; + } + + // 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 unsigned integer? + v8::Local<v8::Uint32> uintValue = value->ToUint32(); + if (uintValue.IsEmpty()) { + ok = false; + return 0; + } + + // FIXME: v8::Uint32::Value is not defined! + // http://code.google.com/p/v8/issues/detail?id=624 + v8::Local<v8::Int32> intValue = value->ToInt32(); + if (intValue.IsEmpty()) { + ok = false; + return 0; + } + + return static_cast<uint32_t>(intValue->Value()); +} + String toWebCoreString(const v8::Arguments& args, int index) { return v8ValueToWebCoreString(args[index]); } diff --git a/WebCore/bindings/v8/V8Binding.h b/WebCore/bindings/v8/V8Binding.h index 0be0ebd..696cd1a 100644 --- a/WebCore/bindings/v8/V8Binding.h +++ b/WebCore/bindings/v8/V8Binding.h @@ -108,6 +108,17 @@ namespace WebCore { return toInt32(value, ok); } + // Convert a value to a 32-bit unsigned integer. The conversion fails if the + // value cannot be converted to an unsigned integer or converts to nan or to an infinity. + uint32_t toUInt32(v8::Handle<v8::Value> value, bool& ok); + + // Convert a value to a 32-bit unsigned integer assuming the conversion cannot fail. + inline uint32_t toUInt32(v8::Handle<v8::Value> value) + { + bool ok; + return toUInt32(value, ok); + } + inline float toFloat(v8::Local<v8::Value> value) { return static_cast<float>(value->NumberValue()); diff --git a/WebCore/bindings/v8/V8Collection.h b/WebCore/bindings/v8/V8Collection.h index 9611571..1757c85 100644 --- a/WebCore/bindings/v8/V8Collection.h +++ b/WebCore/bindings/v8/V8Collection.h @@ -34,6 +34,7 @@ #include "HTMLFormElement.h" #include "HTMLSelectElement.h" #include "V8Binding.h" +#include "V8Node.h" #include "V8Proxy.h" #include <v8.h> @@ -63,7 +64,7 @@ template<class Collection, class ItemType> static v8::Handle<v8::Value> getNamed { // FIXME: assert object is a collection type ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); - ASSERT(V8DOMWrapper::domWrapperType(object) != V8ClassIndex::NODE); + ASSERT(V8DOMWrapper::domWrapperType(object) != &V8Node::info); Collection* collection = toNativeCollection<Collection>(object); AtomicString propertyName = toAtomicWebCoreStringWithNullCheck(name); return getV8Object<ItemType>(collection->namedItem(propertyName)); @@ -89,7 +90,7 @@ template<class Collection, class ItemType> static v8::Handle<v8::Value> getIndex { // FIXME: Assert that object must be a collection type. ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); - ASSERT(V8DOMWrapper::domWrapperType(object) != V8ClassIndex::NODE); + ASSERT(V8DOMWrapper::domWrapperType(object) != &V8Node::info); Collection* collection = toNativeCollection<Collection>(object); return getV8Object<ItemType>(collection->item(index)); } @@ -154,17 +155,16 @@ template<class Collection> static v8::Handle<v8::Value> collectionStringIndexedP // Add indexed getter to the function template for a collection. -template<class Collection, class ItemType> static void setCollectionIndexedGetter(v8::Handle<v8::FunctionTemplate> desc, V8ClassIndex::V8WrapperType type) +template<class Collection, class ItemType> static void setCollectionIndexedGetter(v8::Handle<v8::FunctionTemplate> desc) { - desc->InstanceTemplate()->SetIndexedPropertyHandler(collectionIndexedPropertyGetter<Collection, ItemType>, 0, 0, 0, collectionIndexedPropertyEnumerator<Collection>, - v8::Integer::New(V8ClassIndex::ToInt(type))); + desc->InstanceTemplate()->SetIndexedPropertyHandler(collectionIndexedPropertyGetter<Collection, ItemType>, 0, 0, 0, collectionIndexedPropertyEnumerator<Collection>); } // Add named getter to the function template for a collection. -template<class Collection, class ItemType> static void setCollectionNamedGetter(v8::Handle<v8::FunctionTemplate> desc, V8ClassIndex::V8WrapperType type) +template<class Collection, class ItemType> static void setCollectionNamedGetter(v8::Handle<v8::FunctionTemplate> desc) { - desc->InstanceTemplate()->SetNamedPropertyHandler(collectionNamedPropertyGetter<Collection, ItemType>, 0, 0, 0, 0, v8::Integer::New(V8ClassIndex::ToInt(type))); + desc->InstanceTemplate()->SetNamedPropertyHandler(collectionNamedPropertyGetter<Collection, ItemType>, 0, 0, 0, 0); } // Add indexed getter returning a string or null to a function template for a collection. diff --git a/WebCore/bindings/v8/V8DOMMap.cpp b/WebCore/bindings/v8/V8DOMMap.cpp index fa2fba3..b478d06 100644 --- a/WebCore/bindings/v8/V8DOMMap.cpp +++ b/WebCore/bindings/v8/V8DOMMap.cpp @@ -33,7 +33,6 @@ #include "DOMData.h" #include "DOMDataStore.h" -#include "DOMObjectsInclude.h" #include "MainThreadDOMData.h" #include "ScopedDOMDataStore.h" @@ -95,13 +94,10 @@ DOMWrapperMap<void>& getDOMSVGObjectWithContextMap() #endif // ENABLE(SVG) -static void removeAllDOMObjectsInCurrentThreadHelper() +void removeAllDOMObjectsInCurrentThread() { v8::HandleScope scope; - // Deref all objects in the delayed queue. - DOMData::getCurrent()->derefDelayedObjects(); - // The DOM objects with the following types only exist on the main thread. if (WTF::isMainThread()) { // Remove all DOM nodes. @@ -123,17 +119,6 @@ static void removeAllDOMObjectsInCurrentThreadHelper() DOMData::removeObjectsFromWrapperMap<void>(getActiveDOMObjectMap()); } -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(); -} - - void visitDOMNodesInCurrentThread(DOMWrapperMap<Node>::Visitor* visitor) { v8::HandleScope scope; diff --git a/WebCore/bindings/v8/V8DOMWindowShell.cpp b/WebCore/bindings/v8/V8DOMWindowShell.cpp index cdf4393..6087479 100644 --- a/WebCore/bindings/v8/V8DOMWindowShell.cpp +++ b/WebCore/bindings/v8/V8DOMWindowShell.cpp @@ -31,12 +31,10 @@ #include "config.h" #include "V8DOMWindowShell.h" -#include "CString.h" #include "PlatformBridge.h" #include "CSSMutableStyleDeclaration.h" #include "DateExtension.h" #include "DocumentLoader.h" -#include "DOMObjectsInclude.h" #include "Frame.h" #include "FrameLoaderClient.h" #include "InspectorTimelineAgent.h" @@ -51,9 +49,9 @@ #include "V8DOMMap.h" #include "V8DOMWindow.h" #include "V8Document.h" +#include "V8GCForContextDispose.h" #include "V8HiddenPropertyName.h" #include "V8History.h" -#include "V8Index.h" #include "V8Location.h" #include "V8Proxy.h" #include "WorkerContextExecutionProxy.h" @@ -68,6 +66,7 @@ #include <wtf/StdLibExtras.h> #include <wtf/StringExtras.h> #include <wtf/UnusedParam.h> +#include <wtf/text/CString.h> #ifdef ANDROID_INSTRUMENT #include "TimeCounter.h" @@ -96,28 +95,20 @@ static void reportFatalErrorInV8(const char* location, const char* message) static Frame* getTargetFrame(v8::Local<v8::Object> host, v8::Local<v8::Value> data) { Frame* target = 0; - switch (V8ClassIndex::FromInt(data->Int32Value())) { - case V8ClassIndex::DOMWINDOW: { + WrapperTypeInfo* type = WrapperTypeInfo::unwrap(data); + if (V8DOMWindow::info.equals(type)) { v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), host); if (window.IsEmpty()) return target; DOMWindow* targetWindow = V8DOMWindow::toNative(window); target = targetWindow->frame(); - break; - } - case V8ClassIndex::LOCATION: { + } else if (V8History::info.equals(type)) { History* history = V8History::toNative(host); target = history->frame(); - break; - } - case V8ClassIndex::HISTORY: { + } else if (V8Location::info.equals(type)) { Location* location = V8Location::toNative(host); target = location->frame(); - break; - } - default: - break; } return target; } @@ -144,7 +135,6 @@ bool V8DOMWindowShell::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(); } @@ -154,15 +144,20 @@ void V8DOMWindowShell::disposeContextHandles() m_frame->loader()->client()->didDestroyScriptContextForFrame(); m_context.Dispose(); m_context.Clear(); + + // It's likely that disposing the context has created a lot of + // garbage. Notify V8 about this so it'll have a chance of cleaning + // it up when idle. + V8GCForContextDispose::instance().notifyContextDisposed(); } - if (!m_wrapperBoilerplates.IsEmpty()) { -#ifndef NDEBUG - V8GCController::unregisterGlobalHandle(this, m_wrapperBoilerplates); -#endif - m_wrapperBoilerplates.Dispose(); - m_wrapperBoilerplates.Clear(); + WrapperBoilerplateMap::iterator it = m_wrapperBoilerplates.begin(); + for (; it != m_wrapperBoilerplates.end(); ++it) { + v8::Persistent<v8::Object> wrapper = it->second; + wrapper.Dispose(); + wrapper.Clear(); } + m_wrapperBoilerplates.clear(); } void V8DOMWindowShell::destroyGlobal() @@ -299,19 +294,15 @@ void V8DOMWindowShell::initContextIfNeeded() #endif } - installHiddenObjectPrototype(v8Context); - m_wrapperBoilerplates = v8::Persistent<v8::Array>::New(v8::Array::New(V8ClassIndex::WRAPPER_TYPE_COUNT)); - // Bail out if allocation failed. - if (m_wrapperBoilerplates.IsEmpty()) { + if (!installHiddenObjectPrototype(v8Context)) { disposeContextHandles(); return; } -#ifndef NDEBUG - V8GCController::registerGlobalHandle(PROXY, this, m_wrapperBoilerplates); -#endif - if (!installDOMWindow(v8Context, m_frame->domWindow())) + if (!installDOMWindow(v8Context, m_frame->domWindow())) { disposeContextHandles(); + return; + } updateDocument(); @@ -357,7 +348,7 @@ v8::Persistent<v8::Context> V8DOMWindowShell::createNewContext(v8::Handle<v8::Ob // 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 (extensions[i].scheme.length() > 0 && (extensions[i].scheme != m_frame->loader()->activeDocumentLoader()->url().protocol() || extensions[i].scheme != m_frame->page()->mainFrame()->loader()->activeDocumentLoader()->url().protocol())) + if (extensions[i].scheme.length() > 0 && (extensions[i].scheme != m_frame->loader()->activeDocumentLoader()->url().protocol())) continue; extensionNames[index++] = extensions[i].extension->name(); @@ -369,6 +360,7 @@ v8::Persistent<v8::Context> V8DOMWindowShell::createNewContext(v8::Handle<v8::Ob } void V8DOMWindowShell::setContext(v8::Handle<v8::Context> context) +<<<<<<< HEAD { // if we already have a context, clear it before setting the new one. if (!m_context.IsEmpty()) { @@ -379,29 +371,37 @@ void V8DOMWindowShell::setContext(v8::Handle<v8::Context> context) } bool V8DOMWindowShell::installDOMWindow(v8::Handle<v8::Context> context, DOMWindow* window) +======= +>>>>>>> webkit.org at r58033 { - v8::Handle<v8::String> implicitProtoString = v8::String::New("__proto__"); - if (implicitProtoString.IsEmpty()) - return false; + // if we already have a context, clear it before setting the new one. + if (!m_context.IsEmpty()) { + m_context.Dispose(); + m_context.Clear(); + } + m_context = v8::Persistent<v8::Context>::New(context); +} +bool V8DOMWindowShell::installDOMWindow(v8::Handle<v8::Context> context, DOMWindow* window) +{ // 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::Handle<v8::Function> windowConstructor = V8DOMWrapper::getConstructor(&V8DOMWindow::info, 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); - V8DOMWrapper::setDOMWrapper(v8::Handle<v8::Object>::Cast(jsWindow->GetPrototype()), V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), window); + V8DOMWrapper::setDOMWrapper(jsWindow, &V8DOMWindow::info, window); + V8DOMWrapper::setDOMWrapper(v8::Handle<v8::Object>::Cast(jsWindow->GetPrototype()), &V8DOMWindow::info, 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(); - V8DOMWrapper::setDOMWrapper(v8::Handle<v8::Object>::Cast(v8Global->GetPrototype()), V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), window); - v8Global->Set(implicitProtoString, jsWindow); + v8::Handle<v8::Object> v8RealGlobal = v8::Handle<v8::Object>::Cast(context->Global()->GetPrototype()); + V8DOMWrapper::setDOMWrapper(v8RealGlobal, &V8DOMWindow::info, window); + v8RealGlobal->SetPrototype(jsWindow); return true; } @@ -533,31 +533,38 @@ v8::Handle<v8::Value> V8DOMWindowShell::getHiddenObjectPrototype(v8::Handle<v8:: return context->Global()->GetHiddenValue(V8HiddenPropertyName::objectPrototype()); } -void V8DOMWindowShell::installHiddenObjectPrototype(v8::Handle<v8::Context> context) +bool V8DOMWindowShell::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; + return false; v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(context->Global()->Get(objectString)); + // Bail out if fetching failed. + if (object.IsEmpty()) + return false; v8::Handle<v8::Value> objectPrototype = object->Get(prototypeString); + // Bail out if fetching failed. + if (objectPrototype.IsEmpty()) + return false; context->Global()->SetHiddenValue(hiddenObjectPrototypeString, objectPrototype); + + return true; } -v8::Local<v8::Object> V8DOMWindowShell::createWrapperFromCacheSlowCase(V8ClassIndex::V8WrapperType type) +v8::Local<v8::Object> V8DOMWindowShell::createWrapperFromCacheSlowCase(WrapperTypeInfo* type) { // Not in cache. - int classIndex = V8ClassIndex::ToInt(type); 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); + m_wrapperBoilerplates.set(type, v8::Persistent<v8::Object>::New(instance)); return instance->Clone(); } return notHandledByInterceptor(); diff --git a/WebCore/bindings/v8/V8DOMWindowShell.h b/WebCore/bindings/v8/V8DOMWindowShell.h index 6b8952d..f4eaff2 100644 --- a/WebCore/bindings/v8/V8DOMWindowShell.h +++ b/WebCore/bindings/v8/V8DOMWindowShell.h @@ -31,7 +31,8 @@ #ifndef V8DOMWindowShell_h #define V8DOMWindowShell_h -#include "V8Index.h" +#include "WrapperTypeInfo.h" +#include <wtf/HashMap.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> @@ -73,16 +74,15 @@ public: static v8::Handle<v8::Value> getHiddenObjectPrototype(v8::Handle<v8::Context>); // WARNING: Call |installHiddenObjectPrototype| only on fresh contexts! - static void installHiddenObjectPrototype(v8::Handle<v8::Context>); + static bool installHiddenObjectPrototype(v8::Handle<v8::Context>); // 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 type) + v8::Local<v8::Object> createWrapperFromCache(WrapperTypeInfo* type) { - int classIndex = V8ClassIndex::ToInt(type); - v8::Local<v8::Object> clone(m_wrapperBoilerplates->CloneElementAt(classIndex)); - return clone.IsEmpty() ? createWrapperFromCacheSlowCase(type) : clone; + v8::Persistent<v8::Object> boilerplate = m_wrapperBoilerplates.get(type); + return boilerplate.IsEmpty() ? createWrapperFromCacheSlowCase(type) : boilerplate->Clone(); } static void setLocation(DOMWindow*, const String& relativeURL); @@ -102,15 +102,14 @@ private: void updateDocumentWrapperCache(); void clearDocumentWrapperCache(); - v8::Local<v8::Object> createWrapperFromCacheSlowCase(V8ClassIndex::V8WrapperType); + v8::Local<v8::Object> createWrapperFromCacheSlowCase(WrapperTypeInfo*); Frame* m_frame; // 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; + // The boilerplate is used to create additional wrappers of the same type. + typedef WTF::HashMap<WrapperTypeInfo*, v8::Persistent<v8::Object> > WrapperBoilerplateMap; + WrapperBoilerplateMap m_wrapperBoilerplates; v8::Persistent<v8::Context> m_context; v8::Persistent<v8::Object> m_global; diff --git a/WebCore/bindings/v8/V8DOMWrapper.cpp b/WebCore/bindings/v8/V8DOMWrapper.cpp index cf11e6c..ac29170 100644 --- a/WebCore/bindings/v8/V8DOMWrapper.cpp +++ b/WebCore/bindings/v8/V8DOMWrapper.cpp @@ -1,10 +1,10 @@ /* * 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 @@ -14,7 +14,7 @@ * * 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 @@ -33,44 +33,50 @@ #include "CSSMutableStyleDeclaration.h" #include "DOMDataStore.h" -#include "DOMObjectsInclude.h" #include "DocumentLoader.h" #include "FrameLoaderClient.h" #include "Notification.h" -#include "SVGElementInstance.h" -#include "SVGPathSeg.h" #include "ScriptController.h" #include "V8AbstractEventListener.h" #include "V8Binding.h" #include "V8Collection.h" #include "V8CustomEventListener.h" +#include "V8DedicatedWorkerContext.h" #include "V8DOMApplicationCache.h" #include "V8DOMMap.h" #include "V8DOMWindow.h" #include "V8EventListenerList.h" +#include "V8EventSource.h" #include "V8HTMLCollection.h" #include "V8HTMLDocument.h" -#include "V8Index.h" #include "V8IsolatedContext.h" #include "V8Location.h" #include "V8MessageChannel.h" #include "V8NamedNodeMap.h" #include "V8Node.h" +#include "V8NodeFilterCondition.h" #include "V8NodeList.h" #include "V8Notification.h" #include "V8Proxy.h" -#include "V8SVGElementInstance.h" #include "V8SharedWorker.h" #include "V8SharedWorkerContext.h" #include "V8StyleSheet.h" #include "V8WebSocket.h" #include "V8Worker.h" #include "V8WorkerContext.h" +#include "V8WorkerContextEventListener.h" #include "V8XMLHttpRequest.h" #include "WebGLArray.h" #include "WebGLContextAttributes.h" #include "WebGLUniformLocation.h" #include "WorkerContextExecutionProxy.h" +#include "WrapperTypeInfo.h" + +#if ENABLE(SVG) +#include "SVGElementInstance.h" +#include "SVGPathSeg.h" +#include "V8SVGElementInstance.h" +#endif #include <algorithm> #include <utility> @@ -86,60 +92,11 @@ namespace WebCore { typedef HashMap<Node*, v8::Object*> DOMNodeMap; typedef HashMap<void*, v8::Object*> DOMObjectMap; -#if ENABLE(3D_CANVAS) -void V8DOMWrapper::setIndexedPropertiesToExternalArray(v8::Handle<v8::Object> wrapper, - int index, - void* address, - int length) -{ - v8::ExternalArrayType array_type = v8::kExternalByteArray; - V8ClassIndex::V8WrapperType classIndex = V8ClassIndex::FromInt(index); - switch (classIndex) { - case V8ClassIndex::WEBGLBYTEARRAY: - array_type = v8::kExternalByteArray; - break; - case V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY: - array_type = v8::kExternalUnsignedByteArray; - break; - case V8ClassIndex::WEBGLSHORTARRAY: - array_type = v8::kExternalShortArray; - break; - case V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY: - array_type = v8::kExternalUnsignedShortArray; - break; - case V8ClassIndex::WEBGLINTARRAY: - array_type = v8::kExternalIntArray; - break; - case V8ClassIndex::WEBGLUNSIGNEDINTARRAY: - array_type = v8::kExternalUnsignedIntArray; - break; - case V8ClassIndex::WEBGLFLOATARRAY: - array_type = v8::kExternalFloatArray; - break; - default: - ASSERT_NOT_REACHED(); - } - wrapper->SetIndexedPropertiesToExternalArrayData(address, - array_type, - length); -} -#endif - // 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 + ASSERT(!domWrapperType(wrapper)->toActiveDOMObjectFunction); getDOMObjectMap().set(object, wrapper); } @@ -147,16 +104,7 @@ void V8DOMWrapper::setJSWrapperForDOMObject(void* object, v8::Persistent<v8::Obj 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 + ASSERT(domWrapperType(wrapper)->toActiveDOMObjectFunction); getActiveDOMObjectMap().set(object, wrapper); } @@ -167,7 +115,7 @@ void V8DOMWrapper::setJSWrapperForDOMNode(Node* node, v8::Persistent<v8::Object> getDOMNodeMap().set(node, wrapper); } -v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> objectPrototype) +v8::Local<v8::Function> V8DOMWrapper::getConstructor(WrapperTypeInfo* 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 @@ -178,7 +126,7 @@ v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType // 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 = V8ClassIndex::getTemplate(type); + v8::Handle<v8::FunctionTemplate> functionTemplate = type->getTemplate(); // Getting the function might fail if we're running out of // stack or memory. v8::TryCatch tryCatch; @@ -187,11 +135,11 @@ v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType return v8::Local<v8::Function>(); // Hotmail fix, see comments above. if (!objectPrototype.IsEmpty()) - value->Set(v8::String::New("__proto__"), objectPrototype); + value->SetPrototype(objectPrototype); return value; } -v8::Local<v8::Function> V8DOMWrapper::getConstructorForContext(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Context> context) +v8::Local<v8::Function> V8DOMWrapper::getConstructorForContext(WrapperTypeInfo* type, v8::Handle<v8::Context> context) { // Enter the scope for this context to get the correct constructor. v8::Context::Scope scope(context); @@ -199,7 +147,7 @@ v8::Local<v8::Function> V8DOMWrapper::getConstructorForContext(V8ClassIndex::V8W return getConstructor(type, V8DOMWindowShell::getHiddenObjectPrototype(context)); } -v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, DOMWindow* window) +v8::Local<v8::Function> V8DOMWrapper::getConstructor(WrapperTypeInfo* type, DOMWindow* window) { Frame* frame = window->frame(); if (!frame) @@ -213,9 +161,14 @@ v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType } #if ENABLE(WORKERS) +<<<<<<< HEAD v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType type, WorkerContext*) +======= +v8::Local<v8::Function> V8DOMWrapper::getConstructor(WrapperTypeInfo* type, WorkerContext*) +>>>>>>> webkit.org at r58033 { - WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve(); + WorkerScriptController* controller = WorkerScriptController::controllerForContext(); + WorkerContextExecutionProxy* proxy = controller ? controller->proxy() : 0; if (!proxy) return v8::Local<v8::Function>(); @@ -226,8 +179,22 @@ v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType return getConstructorForContext(type, context); } #endif +<<<<<<< HEAD +======= -void V8DOMWrapper::setHiddenWindowReference(Frame* frame, const int internalIndex, v8::Handle<v8::Object> jsObject) +void V8DOMWrapper::setHiddenReference(v8::Handle<v8::Object> parent, v8::Handle<v8::Value> child) +{ + v8::Local<v8::Value> hiddenReferenceObject = parent->GetInternalField(v8DOMHiddenReferenceArrayIndex); + if (hiddenReferenceObject->IsNull() || hiddenReferenceObject->IsUndefined()) { + hiddenReferenceObject = v8::Array::New(); + parent->SetInternalField(v8DOMHiddenReferenceArrayIndex, hiddenReferenceObject); + } + v8::Local<v8::Array> hiddenReferenceArray = v8::Local<v8::Array>::Cast(hiddenReferenceObject); + hiddenReferenceArray->Set(v8::Integer::New(hiddenReferenceArray->Length()), child); +} +>>>>>>> webkit.org at r58033 + +void V8DOMWrapper::setHiddenWindowReference(Frame* frame, v8::Handle<v8::Value> jsObject) { // Get DOMWindow if (!frame) @@ -236,21 +203,18 @@ void V8DOMWrapper::setHiddenWindowReference(Frame* frame, const int internalInde if (context.IsEmpty()) return; - ASSERT(internalIndex < V8DOMWindow::internalFieldCount); - v8::Handle<v8::Object> global = context->Global(); // Look for real DOM wrapper. global = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), global); ASSERT(!global.IsEmpty()); - ASSERT(global->GetInternalField(internalIndex)->IsUndefined()); - global->SetInternalField(internalIndex, jsObject); + + setHiddenReference(global, jsObject); } -V8ClassIndex::V8WrapperType V8DOMWrapper::domWrapperType(v8::Handle<v8::Object> object) +WrapperTypeInfo* V8DOMWrapper::domWrapperType(v8::Handle<v8::Object> object) { ASSERT(V8DOMWrapper::maybeDOMWrapper(object)); - v8::Handle<v8::Value> type = object->GetInternalField(v8DOMWrapperTypeIndex); - return V8ClassIndex::FromInt(type->Int32Value()); + return static_cast<WrapperTypeInfo*>(object->GetPointerFromInternalField(v8DOMWrapperTypeIndex)); } PassRefPtr<NodeFilter> V8DOMWrapper::wrapNativeNodeFilter(v8::Handle<v8::Value> filter) @@ -275,15 +239,24 @@ static bool globalObjectPrototypeIsDOMWindow(v8::Handle<v8::Object> objectProtot #if ENABLE(SHARED_WORKERS) // We can identify what type of context the global object is wrapping by looking at the // internal field count of its prototype. This assumes WorkerContexts and DOMWindows have different numbers - // of internal fields, so a COMPILE_ASSERT is included to warn if this ever changes. DOMWindow has - // traditionally had far more internal fields than any other class. - COMPILE_ASSERT(V8DOMWindow::internalFieldCount != V8WorkerContext::internalFieldCount && V8DOMWindow::internalFieldCount != V8SharedWorkerContext::internalFieldCount, + // of internal fields, so a COMPILE_ASSERT is included to warn if this ever changes. +#if ENABLE(WORKERS) + COMPILE_ASSERT(V8DOMWindow::internalFieldCount != V8WorkerContext::internalFieldCount, DOMWindowAndWorkerContextHaveUnequalFieldCounts); +<<<<<<< HEAD +======= + COMPILE_ASSERT(V8DOMWindow::internalFieldCount != V8DedicatedWorkerContext::internalFieldCount, + DOMWindowAndDedicatedWorkerContextHaveUnequalFieldCounts); +#endif +#if ENABLE(SHARED_WORKERS) + COMPILE_ASSERT(V8DOMWindow::internalFieldCount != V8SharedWorkerContext::internalFieldCount, + DOMWindowAndSharedWorkerContextHaveUnequalFieldCounts); +>>>>>>> webkit.org at r58033 #endif return objectPrototype->InternalFieldCount() == V8DOMWindow::internalFieldCount; } -v8::Local<v8::Object> V8DOMWrapper::instantiateV8Object(V8Proxy* proxy, V8ClassIndex::V8WrapperType type, void* impl) +v8::Local<v8::Object> V8DOMWrapper::instantiateV8Object(V8Proxy* proxy, WrapperTypeInfo* type, void* impl) { WorkerContext* workerContext = 0; if (V8IsolatedContext::getEntered()) { @@ -316,12 +289,16 @@ v8::Local<v8::Object> V8DOMWrapper::instantiateV8Object(V8Proxy* proxy, V8ClassI function = getConstructor(type, workerContext); else #endif +<<<<<<< HEAD function = V8ClassIndex::getTemplate(type)->GetFunction(); +======= + function = type->getTemplate()->GetFunction(); +>>>>>>> webkit.org at r58033 instance = SafeAllocation::newInstance(function); } if (!instance.IsEmpty()) { // Avoid setting the DOM wrapper for failed allocations. - setDOMWrapper(instance, V8ClassIndex::ToInt(type), impl); + setDOMWrapper(instance, type, impl); } return instance; } @@ -338,10 +315,6 @@ bool V8DOMWrapper::maybeDOMWrapper(v8::Handle<v8::Value> value) ASSERT(object->InternalFieldCount() >= v8DefaultWrapperInternalFieldCount); - v8::Handle<v8::Value> type = object->GetInternalField(v8DOMWrapperTypeIndex); - ASSERT(type->IsInt32()); - ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() && type->Int32Value() < V8ClassIndex::CLASSINDEX_END); - v8::Handle<v8::Value> wrapper = object->GetInternalField(v8DOMWrapperObjectIndex); ASSERT(wrapper->IsNumber() || wrapper->IsExternal()); @@ -356,7 +329,7 @@ bool V8DOMWrapper::isValidDOMObject(v8::Handle<v8::Value> value) return v8::Handle<v8::Object>::Cast(value)->InternalFieldCount(); } -bool V8DOMWrapper::isWrapperOfType(v8::Handle<v8::Value> value, V8ClassIndex::V8WrapperType classType) +bool V8DOMWrapper::isWrapperOfType(v8::Handle<v8::Value> value, WrapperTypeInfo* type) { if (!isValidDOMObject(value)) return false; @@ -367,11 +340,8 @@ bool V8DOMWrapper::isWrapperOfType(v8::Handle<v8::Value> value, V8ClassIndex::V8 v8::Handle<v8::Value> wrapper = object->GetInternalField(v8DOMWrapperObjectIndex); ASSERT(wrapper->IsNumber() || wrapper->IsExternal()); - v8::Handle<v8::Value> type = object->GetInternalField(v8DOMWrapperTypeIndex); - ASSERT(type->IsInt32()); - ASSERT(V8ClassIndex::INVALID_CLASS_INDEX < type->Int32Value() && type->Int32Value() < V8ClassIndex::CLASSINDEX_END); - - return V8ClassIndex::FromInt(type->Int32Value()) == classType; + WrapperTypeInfo* typeInfo = static_cast<WrapperTypeInfo*>(object->GetPointerFromInternalField(v8DOMWrapperTypeIndex)); + return typeInfo == type; } v8::Handle<v8::Object> V8DOMWrapper::getWrapper(Node* node) @@ -440,9 +410,6 @@ v8::Handle<v8::Value> V8DOMWrapper::convertEventTargetToV8Object(EventTarget* ta return wrapper; } - if (XMLHttpRequest* xhr = target->toXMLHttpRequest()) - return toV8(xhr); - // MessagePort is created within its JS counterpart if (MessagePort* port = target->toMessagePort()) { v8::Handle<v8::Object> wrapper = getActiveDOMObjectMap().get(port); @@ -470,6 +437,7 @@ v8::Handle<v8::Value> V8DOMWrapper::convertEventTargetToV8Object(EventTarget* ta return notHandledByInterceptor(); } +<<<<<<< HEAD PassRefPtr<EventListener> V8DOMWrapper::getEventListener(Node* node, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) { return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); @@ -530,37 +498,23 @@ PassRefPtr<EventListener> V8DOMWrapper::getEventListener(XMLHttpRequestUpload* u #if ENABLE(EVENTSOURCE) PassRefPtr<EventListener> V8DOMWrapper::getEventListener(EventSource* eventSource, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) +======= +PassRefPtr<EventListener> V8DOMWrapper::getEventListener(v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) +>>>>>>> webkit.org at r58033 { - if (V8Proxy::retrieve(eventSource->scriptExecutionContext())) - return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); - + v8::Handle<v8::Context> context = v8::Context::GetCurrent(); + if (context.IsEmpty()) + return 0; + if (lookup == ListenerFindOnly) + return V8EventListenerList::findWrapper(value, isAttribute); + v8::Handle<v8::Object> globalPrototype = v8::Handle<v8::Object>::Cast(context->Global()->GetPrototype()); + if (globalObjectPrototypeIsDOMWindow(globalPrototype)) + return V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); #if ENABLE(WORKERS) - WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); - if (workerContextProxy) - return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly); -#endif - + return V8EventListenerList::findOrCreateWrapper<V8WorkerContextEventListener>(value, isAttribute); +#else return 0; -} #endif - -PassRefPtr<EventListener> V8DOMWrapper::getEventListener(EventTarget* eventTarget, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) -{ - if (V8Proxy::retrieve(eventTarget->scriptExecutionContext())) - return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); - -#if ENABLE(WORKERS) - WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve(); - if (workerContextProxy) - return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly); -#endif - - return 0; -} - -PassRefPtr<EventListener> V8DOMWrapper::getEventListener(V8Proxy* proxy, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) -{ - return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute); } } // namespace WebCore diff --git a/WebCore/bindings/v8/V8DOMWrapper.h b/WebCore/bindings/v8/V8DOMWrapper.h index 8a3fa3f..97e269a 100644 --- a/WebCore/bindings/v8/V8DOMWrapper.h +++ b/WebCore/bindings/v8/V8DOMWrapper.h @@ -39,62 +39,19 @@ #include "V8CustomXPathNSResolver.h" #include "V8DOMMap.h" #include "V8Event.h" -#include "V8Index.h" #include "V8Utilities.h" #include "V8XPathNSResolver.h" +#include "WrapperTypeInfo.h" #include "XPathNSResolver.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 V8Proxy; -#if ENABLE(WEB_SOCKETS) - class WebSocket; -#endif class WorkerContext; enum ListenerLookupType { @@ -110,11 +67,11 @@ namespace WebCore { #endif // Sets contents of a DOM wrapper. - static void setDOMWrapper(v8::Handle<v8::Object> object, int type, void* cptr) + static void setDOMWrapper(v8::Handle<v8::Object> object, WrapperTypeInfo* type, void* cptr) { ASSERT(object->InternalFieldCount() >= 2); object->SetPointerInInternalField(v8DOMWrapperObjectIndex, cptr); - object->SetInternalField(v8DOMWrapperTypeIndex, v8::Integer::New(type)); + object->SetPointerInInternalField(v8DOMWrapperTypeIndex, type); } static v8::Handle<v8::Object> lookupDOMWrapper(v8::Handle<v8::FunctionTemplate> functionTemplate, v8::Handle<v8::Object> object) @@ -122,7 +79,7 @@ namespace WebCore { return object.IsEmpty() ? object : object->FindInstanceInPrototypeChain(functionTemplate); } - static V8ClassIndex::V8WrapperType domWrapperType(v8::Handle<v8::Object>); + static WrapperTypeInfo* domWrapperType(v8::Handle<v8::Object>); static v8::Handle<v8::Value> convertEventTargetToV8Object(PassRefPtr<EventTarget> eventTarget) { @@ -131,27 +88,7 @@ namespace WebCore { static v8::Handle<v8::Value> convertEventTargetToV8Object(EventTarget*); - static PassRefPtr<EventListener> getEventListener(Node* node, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); - - static PassRefPtr<EventListener> getEventListener(SVGElementInstance* element, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); - - static PassRefPtr<EventListener> getEventListener(AbstractWorker* worker, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); - -#if ENABLE(NOTIFICATIONS) - static PassRefPtr<EventListener> getEventListener(Notification* notification, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); -#endif - - static PassRefPtr<EventListener> getEventListener(WorkerContext* workerContext, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); - - static PassRefPtr<EventListener> getEventListener(XMLHttpRequestUpload* upload, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); - -#if ENABLE(EVENTSOURCE) - static PassRefPtr<EventListener> getEventListener(EventSource* eventTarget, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); -#endif - - static PassRefPtr<EventListener> getEventListener(EventTarget* eventTarget, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); - - static PassRefPtr<EventListener> getEventListener(V8Proxy* proxy, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); + static PassRefPtr<EventListener> getEventListener(v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup); #if ENABLE(XPATH) // XPath-related utilities @@ -161,7 +98,7 @@ namespace WebCore { if (V8XPathNSResolver::HasInstance(value)) resolver = V8XPathNSResolver::toNative(v8::Handle<v8::Object>::Cast(value)); else if (value->IsObject()) - resolver = V8CustomXPathNSResolver::create(proxy, value->ToObject()); + resolver = V8CustomXPathNSResolver::create(value->ToObject()); return resolver; } #endif @@ -169,10 +106,12 @@ namespace WebCore { // Wrap JS node filter in C++. static PassRefPtr<NodeFilter> wrapNativeNodeFilter(v8::Handle<v8::Value>); - 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*); + static v8::Local<v8::Function> getConstructorForContext(WrapperTypeInfo*, v8::Handle<v8::Context>); + static v8::Local<v8::Function> getConstructor(WrapperTypeInfo*, v8::Handle<v8::Value> objectPrototype); + static v8::Local<v8::Function> getConstructor(WrapperTypeInfo*, DOMWindow*); +#if ENABLE(WORKERS) + static v8::Local<v8::Function> getConstructor(WrapperTypeInfo*, WorkerContext*); +#endif // Set JS wrapper of a DOM object, the caller in charge of increase ref. static void setJSWrapperForDOMObject(void*, v8::Persistent<v8::Object>); @@ -182,18 +121,14 @@ namespace WebCore { static bool isValidDOMObject(v8::Handle<v8::Value>); // Check whether a V8 value is a wrapper of type |classType|. - static bool isWrapperOfType(v8::Handle<v8::Value>, V8ClassIndex::V8WrapperType); + static bool isWrapperOfType(v8::Handle<v8::Value>, WrapperTypeInfo*); + + static void setHiddenReference(v8::Handle<v8::Object> parent, v8::Handle<v8::Value> child); -#if ENABLE(3D_CANVAS) - static void setIndexedPropertiesToExternalArray(v8::Handle<v8::Object>, - int, - void*, - int); -#endif // Set hidden references in a DOMWindow object of a frame. - static void setHiddenWindowReference(Frame*, const int internalIndex, v8::Handle<v8::Object>); + static void setHiddenWindowReference(Frame*, v8::Handle<v8::Value>); - static v8::Local<v8::Object> instantiateV8Object(V8Proxy* proxy, V8ClassIndex::V8WrapperType type, void* impl); + static v8::Local<v8::Object> instantiateV8Object(V8Proxy* proxy, WrapperTypeInfo*, void* impl); static v8::Handle<v8::Object> getWrapper(Node*); }; diff --git a/WebCore/bindings/v8/V8GCController.cpp b/WebCore/bindings/v8/V8GCController.cpp index b478636..61b2a88 100644 --- a/WebCore/bindings/v8/V8GCController.cpp +++ b/WebCore/bindings/v8/V8GCController.cpp @@ -31,11 +31,18 @@ #include "config.h" #include "V8GCController.h" +#include "ActiveDOMObject.h" +#include "Attr.h" #include "DOMDataStore.h" -#include "DOMObjectsInclude.h" +#include "Frame.h" +#include "HTMLImageElement.h" +#include "HTMLNames.h" +#include "MessagePort.h" +#include "SVGElement.h" #include "V8DOMMap.h" -#include "V8Index.h" +#include "V8MessagePort.h" #include "V8Proxy.h" +#include "WrapperTypeInfo.h" #include <algorithm> #include <utility> @@ -112,7 +119,7 @@ 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); + WrapperTypeInfo* type = V8DOMWrapper::domWrapperType(wrapper); void* object = it->first; UNUSED_PARAM(type); UNUSED_PARAM(object); @@ -123,7 +130,7 @@ class DOMObjectVisitor : public DOMWrapperMap<void>::Visitor { public: void visitDOMWrapper(void* object, v8::Persistent<v8::Object> wrapper) { - V8ClassIndex::V8WrapperType type = V8DOMWrapper::domWrapperType(wrapper); + WrapperTypeInfo* type = V8DOMWrapper::domWrapperType(wrapper); UNUSED_PARAM(type); UNUSED_PARAM(object); } @@ -181,36 +188,26 @@ 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 + WrapperTypeInfo* typeInfo = V8DOMWrapper::domWrapperType(wrapper); + + // 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 (V8MessagePort::info.equals(typeInfo)) { + // Mark each port as in-use if it's entangled. For simplicity's sake, we assume all ports are remotely entangled, + // since the Chromium port implementation can't tell the difference. + MessagePort* port1 = static_cast<MessagePort*>(object); + if (port1->isEntangled() || port1->hasPendingActivity()) + wrapper.ClearWeak(); + } else { + ActiveDOMObject* activeDOMObject = typeInfo->toActiveDOMObject(wrapper); + if (activeDOMObject && activeDOMObject->hasPendingActivity()) + wrapper.ClearWeak(); } - - // 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) { - // Mark each port as in-use if it's entangled. For simplicity's sake, we assume all ports are remotely entangled, - // since the Chromium port implementation can't tell the difference. - MessagePort* port1 = static_cast<MessagePort*>(object); - if (port1->isEntangled()) - wrapper.ClearWeak(); } -} }; class GrouperItem { @@ -369,30 +366,20 @@ 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) { + WrapperTypeInfo* typeInfo = V8DOMWrapper::domWrapperType(wrapper); + if (V8MessagePort::info.equals(typeInfo)) { MessagePort* port1 = static_cast<MessagePort*>(object); // 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). - if (!wrapper.IsWeak() && !wrapper.IsNearDeath()) + if ((!wrapper.IsWeak() && !wrapper.IsNearDeath()) || port1->hasPendingActivity()) wrapper.MakeWeak(port1, &DOMDataStore::weakActiveDOMObjectCallback); + } else { + ActiveDOMObject* activeDOMObject = typeInfo->toActiveDOMObject(wrapper); + if (activeDOMObject && activeDOMObject->hasPendingActivity()) { + ASSERT(!wrapper.IsWeak()); + wrapper.MakeWeak(activeDOMObject, &DOMDataStore::weakActiveDOMObjectCallback); + } } } }; diff --git a/WebCore/bindings/v8/V8GCForContextDispose.cpp b/WebCore/bindings/v8/V8GCForContextDispose.cpp new file mode 100644 index 0000000..06a0555 --- /dev/null +++ b/WebCore/bindings/v8/V8GCForContextDispose.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "V8GCForContextDispose.h" + +#include <wtf/StdLibExtras.h> + +namespace WebCore { + +V8GCForContextDispose::V8GCForContextDispose() + : m_pseudoIdleTimer(this, &V8GCForContextDispose::pseudoIdleTimerFired) +{ +} + +void V8GCForContextDispose::notifyContextDisposed() +{ + v8::V8::ContextDisposedNotification(); + if (!m_pseudoIdleTimer.isActive()) + m_pseudoIdleTimer.startOneShot(0.8); +} + +void V8GCForContextDispose::notifyIdleSooner(double maximumFireInterval) +{ + if (m_pseudoIdleTimer.isActive()) { + double nextFireInterval = m_pseudoIdleTimer.nextFireInterval(); + if (nextFireInterval > maximumFireInterval) { + m_pseudoIdleTimer.stop(); + m_pseudoIdleTimer.startOneShot(maximumFireInterval); + } + } +} + +V8GCForContextDispose& V8GCForContextDispose::instance() +{ + DEFINE_STATIC_LOCAL(V8GCForContextDispose, staticInstance, ()); + return staticInstance; +} + +void V8GCForContextDispose::pseudoIdleTimerFired(Timer<V8GCForContextDispose>*) +{ + v8::V8::IdleNotification(); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8DOMSelectionCustom.cpp b/WebCore/bindings/v8/V8GCForContextDispose.h index 0c9e745..b15c5af 100644 --- a/WebCore/bindings/v8/custom/V8DOMSelectionCustom.cpp +++ b/WebCore/bindings/v8/V8GCForContextDispose.h @@ -1,10 +1,10 @@ /* * Copyright (C) 2010 Google Inc. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: - * + * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above @@ -14,7 +14,7 @@ * * 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 @@ -28,24 +28,28 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#include "V8DOMSelection.h" +#ifndef V8GCForContextDispose_h +#define V8GCForContextDispose_h -#include "V8DOMWindow.h" -#include "V8DOMWrapper.h" +#include "Timer.h" +#include <v8.h> namespace WebCore { -v8::Handle<v8::Value> toV8(DOMSelection* impl) -{ - if (!impl) - return v8::Null(); - v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(impl); - if (wrapper.IsEmpty()) { - wrapper = V8DOMSelection::wrap(impl); - V8DOMWrapper::setHiddenWindowReference(impl->frame(), V8DOMWindow::domSelectionIndex, wrapper); - } - return wrapper; +class V8GCForContextDispose { +public: + void notifyContextDisposed(); + void notifyIdleSooner(double maximumFireInterval); + + static V8GCForContextDispose& instance(); + +private: + V8GCForContextDispose(); // Use instance() instead. + void pseudoIdleTimerFired(Timer<V8GCForContextDispose>*); + + Timer<V8GCForContextDispose> m_pseudoIdleTimer; +}; + } -} // namespace WebCore +#endif // V8GCForContextDispose_h diff --git a/WebCore/bindings/v8/V8Helpers.cpp b/WebCore/bindings/v8/V8Helpers.cpp index a690017..486bc48 100644 --- a/WebCore/bindings/v8/V8Helpers.cpp +++ b/WebCore/bindings/v8/V8Helpers.cpp @@ -33,16 +33,10 @@ #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); diff --git a/WebCore/bindings/v8/V8Helpers.h b/WebCore/bindings/v8/V8Helpers.h index 469833e..e90f5d6 100644 --- a/WebCore/bindings/v8/V8Helpers.h +++ b/WebCore/bindings/v8/V8Helpers.h @@ -37,9 +37,6 @@ 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*); diff --git a/WebCore/bindings/v8/V8IsolatedContext.h b/WebCore/bindings/v8/V8IsolatedContext.h index 70ca270..5cd9c65 100644 --- a/WebCore/bindings/v8/V8IsolatedContext.h +++ b/WebCore/bindings/v8/V8IsolatedContext.h @@ -34,7 +34,6 @@ #include "IsolatedWorld.h" #include "ScriptSourceCode.h" // for WebCore::ScriptSourceCode #include "V8DOMWindow.h" -#include "V8Index.h" #include "V8Proxy.h" #include "V8Utilities.h" #include <v8.h> diff --git a/WebCore/bindings/v8/V8LazyEventListener.h b/WebCore/bindings/v8/V8LazyEventListener.h index 078dcf1..f174d23 100644 --- a/WebCore/bindings/v8/V8LazyEventListener.h +++ b/WebCore/bindings/v8/V8LazyEventListener.h @@ -60,6 +60,12 @@ namespace WebCore { virtual v8::Local<v8::Value> callListenerFunction(ScriptExecutionContext*, v8::Handle<v8::Value> jsEvent, Event*); + // Needs to return true for all event handlers implemented in JavaScript so that + // the SVG code does not add the event handler in both + // SVGUseElement::buildShadowTree and again in + // SVGUseElement::transferEventListenersToShadowTree + virtual bool wasCreatedFromMarkup() const { return true; } + String m_functionName; bool m_isSVGEvent; String m_code; diff --git a/WebCore/bindings/v8/V8NPObject.cpp b/WebCore/bindings/v8/V8NPObject.cpp index b873d5f..1ea6487 100644 --- a/WebCore/bindings/v8/V8NPObject.cpp +++ b/WebCore/bindings/v8/V8NPObject.cpp @@ -375,7 +375,7 @@ v8::Local<v8::Object> createV8ObjectForNPObject(NPObject* object, NPObject* root if (value.IsEmpty()) return value; - wrapNPObject(value, object); + V8DOMWrapper::setDOMWrapper(value, npObjectTypeInfo(), object); // KJS retains the object as part of its wrapper (see Bindings::CInstance). _NPN_RetainObject(object); @@ -394,7 +394,7 @@ 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); + V8DOMWrapper::setDOMWrapper(handle, npObjectTypeInfo(), 0); staticNPObjectMap.forget(object); _NPN_ReleaseObject(object); } diff --git a/WebCore/bindings/v8/V8NodeFilterCondition.cpp b/WebCore/bindings/v8/V8NodeFilterCondition.cpp index a8868b5..2170698 100644 --- a/WebCore/bindings/v8/V8NodeFilterCondition.cpp +++ b/WebCore/bindings/v8/V8NodeFilterCondition.cpp @@ -72,10 +72,7 @@ short V8NodeFilterCondition::acceptNode(ScriptState* state, Node* node) const OwnArrayPtr<v8::Handle<v8::Value> > args(new v8::Handle<v8::Value>[1]); args[0] = toV8(node); - V8Proxy* proxy = V8Proxy::retrieve(); - ASSERT(proxy); - - v8::Handle<v8::Value> result = proxy->callFunction(callback, object, 1, args.get()); + v8::Handle<v8::Value> result = V8Proxy::callFunctionWithoutFrame(callback, object, 1, args.get()); if (exceptionCatcher.HasCaught()) { state->setException(exceptionCatcher.Exception()); diff --git a/WebCore/bindings/v8/V8Proxy.cpp b/WebCore/bindings/v8/V8Proxy.cpp index 85db554..878b86a 100644 --- a/WebCore/bindings/v8/V8Proxy.cpp +++ b/WebCore/bindings/v8/V8Proxy.cpp @@ -33,14 +33,16 @@ #include "CSSMutableStyleDeclaration.h" #include "DateExtension.h" -#include "DOMObjectsInclude.h" #include "DocumentLoader.h" +#include "Frame.h" #include "FrameLoaderClient.h" #include "InspectorTimelineAgent.h" #include "Page.h" #include "PageGroup.h" #include "PlatformBridge.h" +#include "SVGElement.h" #include "ScriptController.h" +#include "Settings.h" #include "StorageNamespace.h" #include "V8Binding.h" #include "V8BindingState.h" @@ -51,19 +53,21 @@ #include "V8DOMWindow.h" #include "V8EventException.h" #include "V8HiddenPropertyName.h" -#include "V8Index.h" #include "V8IsolatedContext.h" #include "V8RangeException.h" -#include "V8SVGException.h" #include "V8XMLHttpRequestException.h" #include "V8XPathException.h" +#include "WorkerContext.h" #include "WorkerContextExecutionProxy.h" +#if ENABLE(SVG) +#include "V8SVGException.h" +#endif + #include <algorithm> #include <stdio.h> #include <utility> #include <v8.h> -#include <v8-debug.h> #include <wtf/Assertions.h> #include <wtf/OwnArrayPtr.h> #include <wtf/StdLibExtras.h> @@ -80,8 +84,6 @@ namespace WebCore { -v8::Persistent<v8::Context> V8Proxy::m_utilityContext; - // Static list of registered extensions V8Extensions V8Proxy::m_extensions; @@ -501,9 +503,32 @@ v8::Local<v8::Value> V8Proxy::callFunction(v8::Handle<v8::Function> function, v8 // execution finishs before firing the timer. m_frame->keepAlive(); +#if ENABLE(INSPECTOR) + Page* inspectedPage = InspectorTimelineAgent::instanceCount() ? m_frame->page(): 0; + if (inspectedPage) + if (InspectorTimelineAgent* timelineAgent = inspectedPage->inspectorTimelineAgent()) { + v8::ScriptOrigin origin = function->GetScriptOrigin(); + String resourceName("undefined"); + int lineNumber = 1; + if (!origin.ResourceName().IsEmpty()) { + resourceName = toWebCoreString(origin.ResourceName()); + lineNumber = function->GetScriptLineNumber() + 1; + } + timelineAgent->willCallFunction(resourceName, lineNumber); + } else + inspectedPage = 0; +#endif // !ENABLE(INSPECTOR) + m_recursion++; result = function->Call(receiver, argc, args); m_recursion--; + +#if ENABLE(INSPECTOR) + if (inspectedPage) + if (InspectorTimelineAgent* timelineAgent = inspectedPage->inspectorTimelineAgent()) + timelineAgent->didCallFunction(); +#endif // !ENABLE(INSPECTOR) + } // Release the storage mutex if applicable. @@ -518,6 +543,17 @@ v8::Local<v8::Value> V8Proxy::callFunction(v8::Handle<v8::Function> function, v8 return result; } +v8::Local<v8::Value> V8Proxy::callFunctionWithoutFrame(v8::Handle<v8::Function> function, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> args[]) +{ + V8GCController::checkMemoryUsage(); + v8::Local<v8::Value> 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 @@ -594,7 +630,7 @@ V8Proxy* V8Proxy::retrieve(Frame* frame) { if (!frame) return 0; - return frame->script()->canExecuteScripts() ? frame->script()->proxy() : 0; + return frame->script()->canExecuteScripts(NotAboutToExecuteScript) ? frame->script()->proxy() : 0; } V8Proxy* V8Proxy::retrieve(ScriptExecutionContext* context) @@ -675,10 +711,12 @@ void V8Proxy::setDOMException(int exceptionCode) exception = toV8(XPathException::create(description)); break; #endif + default: + ASSERT_NOT_REACHED(); } - ASSERT(!exception.IsEmpty()); - v8::ThrowException(exception); + if (!exception.IsEmpty()) + v8::ThrowException(exception); } v8::Handle<v8::Value> V8Proxy::throwError(ErrorType type, const char* message) @@ -754,95 +792,11 @@ v8::Handle<v8::Value> V8Proxy::checkNewLegal(const v8::Arguments& args) 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(); -} - -bool V8Proxy::sourceLineNumber(int& result) -{ - v8::HandleScope scope; - v8::Handle<v8::Context> v8UtilityContext = V8Proxy::utilityContext(); - if (v8UtilityContext.IsEmpty()) - return false; - 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 false; - v8::Handle<v8::Value> value = v8::Debug::Call(frameSourceLine); - if (value.IsEmpty()) - return false; - result = value->Int32Value(); - return true; -} - -bool V8Proxy::sourceName(String& result) -{ - v8::HandleScope scope; - v8::Handle<v8::Context> v8UtilityContext = utilityContext(); - if (v8UtilityContext.IsEmpty()) - return false; - 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 false; - v8::Handle<v8::Value> value = v8::Debug::Call(frameSourceName); - if (value.IsEmpty()) - return false; - result = toWebCoreString(value); - return true; -} - void V8Proxy::registerExtensionWithV8(v8::Extension* extension) { // If the extension exists in our list, it was already registered with V8. diff --git a/WebCore/bindings/v8/V8Proxy.h b/WebCore/bindings/v8/V8Proxy.h index 44ed506..98bc902 100644 --- a/WebCore/bindings/v8/V8Proxy.h +++ b/WebCore/bindings/v8/V8Proxy.h @@ -39,7 +39,7 @@ #include "V8DOMWindowShell.h" #include "V8DOMWrapper.h" #include "V8GCController.h" -#include "V8Index.h" +#include "WrapperTypeInfo.h" #include <v8.h> #include <wtf/PassRefPtr.h> // so generated bindings don't have to #include <wtf/Vector.h> @@ -76,7 +76,7 @@ namespace WebCore { const char* const name; v8::AccessorGetter getter; v8::AccessorSetter setter; - V8ClassIndex::V8WrapperType data; + WrapperTypeInfo* data; v8::AccessControl settings; v8::PropertyAttribute attribute; bool onProto; @@ -89,7 +89,7 @@ namespace WebCore { (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)), + v8::External::Wrap(attribute.data), attribute.settings, attribute.attribute); } @@ -224,6 +224,9 @@ namespace WebCore { // 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 with the given receiver and arguments. + static v8::Local<v8::Value> callFunctionWithoutFrame(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[]); @@ -298,26 +301,12 @@ namespace WebCore { // 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&); + template <typename T> + static v8::Handle<v8::Value> constructDOMObject(const v8::Arguments&, WrapperTypeInfo*); // Process any pending JavaScript console messages. static void processConsoleMessages(); - // Function for retrieving the line number and source name for the top - // JavaScript stack frame. - // - // It will return true if the line number was successfully retrieved and written - // into the |result| parameter, otherwise the function will return false. It may - // fail due to a stck overflow in the underlying JavaScript implentation, handling - // of such exception is up to the caller. - static bool sourceLineNumber(int& result); - static bool sourceName(String& result); - v8::Local<v8::Context> context(); v8::Local<v8::Context> mainWorldContext(); @@ -368,23 +357,10 @@ namespace WebCore { 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); - } - Frame* m_frame; // For the moment, we have one of these. Soon we will have one per DOMWrapperWorld. RefPtr<V8DOMWindowShell> m_windowShell; - - // Utility context holding JavaScript functions used internally. - static v8::Persistent<v8::Context> m_utilityContext; int m_handlerLineNumber; @@ -418,8 +394,8 @@ namespace WebCore { IsolatedWorldMap m_isolatedWorlds; }; - template <int tag, typename T> - v8::Handle<v8::Value> V8Proxy::constructDOMObject(const v8::Arguments& args) + template <typename T> + v8::Handle<v8::Value> V8Proxy::constructDOMObject(const v8::Arguments& args, WrapperTypeInfo* type) { if (!args.IsConstructCall()) return throwError(V8Proxy::TypeError, "DOM object constructor cannot be called as a function."); @@ -427,7 +403,7 @@ namespace WebCore { // 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()); + V8DOMWrapper::setDOMWrapper(args.Holder(), type, obj.get()); obj->ref(); V8DOMWrapper::setJSWrapperForDOMObject(obj.get(), v8::Persistent<v8::Object>::New(args.Holder())); return args.Holder(); @@ -449,19 +425,22 @@ namespace WebCore { } inline v8::Handle<v8::Primitive> throwError(const char* message, V8Proxy::ErrorType type = V8Proxy::TypeError) { - V8Proxy::throwError(type, message); + if (!v8::V8::IsExecutionTerminating()) + V8Proxy::throwError(type, message); return v8::Undefined(); } inline v8::Handle<v8::Primitive> throwError(ExceptionCode ec) { - V8Proxy::setDOMException(ec); + if (!v8::V8::IsExecutionTerminating()) + V8Proxy::setDOMException(ec); return v8::Undefined(); } inline v8::Handle<v8::Primitive> throwError(v8::Local<v8::Value> exception) { - v8::ThrowException(exception); + if (!v8::V8::IsExecutionTerminating()) + v8::ThrowException(exception); return v8::Undefined(); } diff --git a/WebCore/bindings/v8/V8SVGPODTypeWrapper.h b/WebCore/bindings/v8/V8SVGPODTypeWrapper.h index d4cdcf8..c044a06 100644 --- a/WebCore/bindings/v8/V8SVGPODTypeWrapper.h +++ b/WebCore/bindings/v8/V8SVGPODTypeWrapper.h @@ -396,13 +396,13 @@ public: class V8SVGPODTypeUtil { public: template <class P> - static P toSVGPODType(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> object, bool& ok); + static P toSVGPODType(WrapperTypeInfo* info, v8::Handle<v8::Value> object, bool& ok); }; template <class P> -P V8SVGPODTypeUtil::toSVGPODType(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Value> object, bool& ok) +P V8SVGPODTypeUtil::toSVGPODType(WrapperTypeInfo* info, v8::Handle<v8::Value> object, bool& ok) { - if (!V8DOMWrapper::isWrapperOfType(object, type)) { + if (!V8DOMWrapper::isWrapperOfType(object, info)) { ok = false; return P(); } diff --git a/WebCore/bindings/v8/V8Utilities.cpp b/WebCore/bindings/v8/V8Utilities.cpp index c7314f1..ffccb06 100644 --- a/WebCore/bindings/v8/V8Utilities.cpp +++ b/WebCore/bindings/v8/V8Utilities.cpp @@ -125,54 +125,17 @@ void navigateIfAllowed(Frame* frame, const KURL& url, bool lockHistory, bool loc frame->redirectScheduler()->scheduleLocationChange(url.string(), callingFrame->loader()->outgoingReferrer(), lockHistory, lockBackForwardList, processingUserGesture()); } -ScriptExecutionContext* getScriptExecutionContext(ScriptState* scriptState) +ScriptExecutionContext* getScriptExecutionContext() { #if ENABLE(WORKERS) - WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve(); - if (proxy) - return proxy->workerContext()->scriptExecutionContext(); + if (WorkerScriptController* controller = WorkerScriptController::controllerForContext()) + return controller->workerContext(); #endif - Frame* frame; - if (scriptState) { - v8::HandleScope handleScope; - frame = V8Proxy::retrieveFrame(scriptState->context()); - } else - frame = V8Proxy::retrieveFrameForCurrentContext(); - - if (frame) + if (Frame* frame = V8Proxy::retrieveFrameForCurrentContext()) return frame->document()->scriptExecutionContext(); return 0; } -void reportException(ScriptState* scriptState, v8::TryCatch& exceptionCatcher) -{ - String errorMessage; - int lineNumber = 0; - String sourceURL; - - // There can be a situation that an exception is thrown without setting a message. - v8::Local<v8::Message> message = exceptionCatcher.Message(); - if (message.IsEmpty()) { - v8::Local<v8::String> exceptionString = exceptionCatcher.Exception()->ToString(); - // Conversion of the exception object to string can fail if an - // exception is thrown during conversion. - if (!exceptionString.IsEmpty()) - errorMessage = toWebCoreString(exceptionString); - } else { - errorMessage = toWebCoreString(message->Get()); - lineNumber = message->GetLineNumber(); - sourceURL = toWebCoreString(message->GetScriptResourceName()); - } - - // Do not report the exception if the current execution context is Document because we do not want to lead to duplicate error messages in the console. - // FIXME (31171): need better design to solve the duplicate error message reporting problem. - ScriptExecutionContext* context = getScriptExecutionContext(scriptState); - // During the frame teardown, there may not be a valid context. - if (context && !context->isDocument()) - context->reportException(errorMessage, lineNumber, sourceURL); - exceptionCatcher.Reset(); -} - } // namespace WebCore diff --git a/WebCore/bindings/v8/V8Utilities.h b/WebCore/bindings/v8/V8Utilities.h index 944823a..cbe7a7b 100644 --- a/WebCore/bindings/v8/V8Utilities.h +++ b/WebCore/bindings/v8/V8Utilities.h @@ -54,12 +54,7 @@ namespace WebCore { KURL completeURL(const String& relativeURL); void navigateIfAllowed(Frame*, const KURL&, bool lockHistory, bool lockBackForwardList); - ScriptExecutionContext* getScriptExecutionContext(ScriptState*); - inline ScriptExecutionContext* getScriptExecutionContext() { - return getScriptExecutionContext(0); - } - - void reportException(ScriptState*, v8::TryCatch&); + ScriptExecutionContext* getScriptExecutionContext(); class AllowAllocation { public: diff --git a/WebCore/bindings/v8/custom/V8BarInfoCustom.cpp b/WebCore/bindings/v8/V8WorkerContextErrorHandler.cpp index 44f0b62..5a75a40 100644 --- a/WebCore/bindings/v8/custom/V8BarInfoCustom.cpp +++ b/WebCore/bindings/v8/V8WorkerContextErrorHandler.cpp @@ -29,45 +29,38 @@ */ #include "config.h" -#include "V8BarInfo.h" -#include "V8DOMWindow.h" -#include "V8DOMWrapper.h" +#if ENABLE(WORKERS) + +#include "V8WorkerContextErrorHandler.h" + +#include "ErrorEvent.h" +#include "V8Binding.h" namespace WebCore { -v8::Handle<v8::Value> toV8(BarInfo* impl) +V8WorkerContextErrorHandler::V8WorkerContextErrorHandler(v8::Local<v8::Object> listener, bool isInline, const WorldContextHandle& worldContext) + : V8WorkerContextEventListener(listener, isInline, worldContext) +{ +} + +v8::Local<v8::Value> V8WorkerContextErrorHandler::callListenerFunction(ScriptExecutionContext* context, v8::Handle<v8::Value> jsEvent, Event* event) { - if (!impl) - return v8::Null(); - v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(impl); - if (wrapper.IsEmpty()) { - wrapper = V8BarInfo::wrap(impl); - if (!wrapper.IsEmpty()) { - Frame* frame = impl->frame(); - switch (impl->type()) { - case BarInfo::Locationbar: - V8DOMWrapper::setHiddenWindowReference(frame, V8DOMWindow::locationbarIndex, wrapper); - break; - case BarInfo::Menubar: - V8DOMWrapper::setHiddenWindowReference(frame, V8DOMWindow::menubarIndex, wrapper); - break; - case BarInfo::Personalbar: - V8DOMWrapper::setHiddenWindowReference(frame, V8DOMWindow::personalbarIndex, wrapper); - break; - case BarInfo::Scrollbars: - V8DOMWrapper::setHiddenWindowReference(frame, V8DOMWindow::scrollbarsIndex, wrapper); - break; - case BarInfo::Statusbar: - V8DOMWrapper::setHiddenWindowReference(frame, V8DOMWindow::statusbarIndex, wrapper); - break; - case BarInfo::Toolbar: - V8DOMWrapper::setHiddenWindowReference(frame, V8DOMWindow::toolbarIndex, wrapper); - break; - } - } + ASSERT(event->isErrorEvent()); + v8::Local<v8::Object> listener = getListenerObject(context); + v8::Local<v8::Value> returnValue; + if (!listener.IsEmpty() && listener->IsFunction()) { + ErrorEvent* errorEvent = static_cast<ErrorEvent*>(event); + v8::Local<v8::Function> callFunction = v8::Local<v8::Function>::Cast(listener); + v8::Local<v8::Object> thisValue = v8::Context::GetCurrent()->Global(); + v8::Handle<v8::Value> parameters[3] = { v8String(errorEvent->message()), v8String(errorEvent->filename()), v8::Integer::New(errorEvent->lineno()) }; + returnValue = callFunction->Call(thisValue, 3, parameters); + if (!returnValue.IsEmpty() && returnValue->IsBoolean() && !returnValue->BooleanValue()) + event->preventDefault(); } - return wrapper; + return returnValue; } } // namespace WebCore + +#endif // WORKERS diff --git a/WebCore/bindings/v8/V8WorkerContextErrorHandler.h b/WebCore/bindings/v8/V8WorkerContextErrorHandler.h new file mode 100644 index 0000000..cd1e0e6 --- /dev/null +++ b/WebCore/bindings/v8/V8WorkerContextErrorHandler.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef V8WorkerContextErrorHandler_h +#define V8WorkerContextErrorHandler_h + +#if ENABLE(WORKERS) + +#include "V8WorkerContextEventListener.h" +#include <v8.h> +#include <wtf/PassRefPtr.h> + +namespace WebCore { + +class V8WorkerContextErrorHandler : public V8WorkerContextEventListener { +public: + static PassRefPtr<V8WorkerContextErrorHandler> create(v8::Local<v8::Object> listener, bool isInline, const WorldContextHandle& worldContext) + { + return adoptRef(new V8WorkerContextErrorHandler(listener, isInline, worldContext)); + } + +private: + V8WorkerContextErrorHandler(v8::Local<v8::Object> listener, bool isInline, const WorldContextHandle& worldContext); + + virtual v8::Local<v8::Value> callListenerFunction(ScriptExecutionContext*, v8::Handle<v8::Value> jsEvent, Event*); +}; + +} // namespace WebCore + +#endif // WORKERS + +#endif // V8WorkerContextErrorHandler_h diff --git a/WebCore/bindings/v8/V8WorkerContextEventListener.cpp b/WebCore/bindings/v8/V8WorkerContextEventListener.cpp index fa89ae6..30b9865 100644 --- a/WebCore/bindings/v8/V8WorkerContextEventListener.cpp +++ b/WebCore/bindings/v8/V8WorkerContextEventListener.cpp @@ -82,56 +82,6 @@ void V8WorkerContextEventListener::handleEvent(ScriptExecutionContext* context, invokeEventHandler(context, event, jsEvent); } -bool V8WorkerContextEventListener::reportError(ScriptExecutionContext* context, const String& message, const String& url, int lineNumber) -{ - if (!context) - 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; - - WorkerContextExecutionProxy* proxy = workerProxy(context); - if (!proxy) - return false; - - v8::Handle<v8::Context> v8Context = proxy->context(); - if (v8Context.IsEmpty()) - return false; - - // Enter the V8 context in which to perform the event handling. - v8::Context::Scope scope(v8Context); - - v8::Local<v8::Object> listener = getListenerObject(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 (!listener.IsEmpty() && listener->IsFunction()) { - v8::Local<v8::Function> callFunction = v8::Local<v8::Function>::Cast(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(ScriptExecutionContext* context, v8::Handle<v8::Value> jsEvent, Event* event) { v8::Local<v8::Function> handlerFunction = getListenerFunction(context); diff --git a/WebCore/bindings/v8/V8WorkerContextEventListener.h b/WebCore/bindings/v8/V8WorkerContextEventListener.h index 4487497..1d0bfc8 100644 --- a/WebCore/bindings/v8/V8WorkerContextEventListener.h +++ b/WebCore/bindings/v8/V8WorkerContextEventListener.h @@ -50,11 +50,11 @@ namespace WebCore { } virtual void handleEvent(ScriptExecutionContext*, Event*); - virtual bool reportError(ScriptExecutionContext*, const String& message, const String& url, int lineNumber); - private: + protected: V8WorkerContextEventListener(v8::Local<v8::Object> listener, bool isInline, const WorldContextHandle& worldContext); + private: virtual v8::Local<v8::Value> callListenerFunction(ScriptExecutionContext*, v8::Handle<v8::Value> jsEvent, Event*); v8::Local<v8::Object> getReceiverObject(ScriptExecutionContext*, Event*); }; diff --git a/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp b/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp index e4b417e..16e0b41 100644 --- a/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp +++ b/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp @@ -35,33 +35,20 @@ #include "WorkerContextExecutionProxy.h" -#include "DOMCoreException.h" #include "DedicatedWorkerContext.h" #include "Event.h" -#include "EventSource.h" -#include "Notification.h" -#include "NotificationCenter.h" -#include "EventException.h" -#include "MessagePort.h" -#include "RangeException.h" #include "SharedWorker.h" #include "SharedWorkerContext.h" #include "V8Binding.h" +#include "V8ConsoleMessage.h" #include "V8DOMMap.h" -#include "V8Index.h" +#include "V8DedicatedWorkerContext.h" #include "V8Proxy.h" -#include "V8WorkerContext.h" -#include "V8WorkerContextEventListener.h" -#if ENABLE(WEB_SOCKETS) -#include "WebSocket.h" -#endif +#include "V8SharedWorkerContext.h" #include "Worker.h" #include "WorkerContext.h" -#include "WorkerLocation.h" -#include "WorkerNavigator.h" #include "WorkerScriptController.h" -#include "XMLHttpRequest.h" -#include "XMLHttpRequestException.h" +#include "WrapperTypeInfo.h" namespace WebCore { @@ -71,6 +58,26 @@ static void reportFatalErrorInV8(const char* location, const char* message) CRASH(); } +static void v8MessageHandler(v8::Handle<v8::Message> message, v8::Handle<v8::Value> data) +{ + static bool isReportingException = false; + // Exceptions that occur in error handler should be ignored since in that case + // WorkerContext::reportException will send the exception to the worker object. + if (isReportingException) + return; + isReportingException = true; + + // During the frame teardown, there may not be a valid context. + if (ScriptExecutionContext* context = getScriptExecutionContext()) { + String errorMessage = toWebCoreString(message->Get()); + int lineNumber = message->GetLineNumber(); + String sourceURL = toWebCoreString(message->GetScriptResourceName()); + context->reportException(errorMessage, lineNumber, sourceURL); + } + + isReportingException = false; +} + WorkerContextExecutionProxy::WorkerContextExecutionProxy(WorkerContext* workerContext) : m_workerContext(workerContext) , m_recursion(0) @@ -100,21 +107,6 @@ 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 = V8DOMWrapper::lookupDOMWrapper(V8WorkerContext::GetTemplate(), global); - // Return 0 if the current executing context is not the worker context. - if (global.IsEmpty()) - return 0; - WorkerContext* workerContext = V8WorkerContext::toNative(global); - return workerContext->script()->proxy(); -} - void WorkerContextExecutionProxy::initV8IfNeeded() { static bool v8Initialized = false; @@ -134,46 +126,53 @@ void WorkerContextExecutionProxy::initV8IfNeeded() v8Initialized = true; } -void WorkerContextExecutionProxy::initContextIfNeeded() +bool WorkerContextExecutionProxy::initContextIfNeeded() { // Bail out if the context has already been initialized. if (!m_context.IsEmpty()) - return; + return true; + + // Setup the security handlers and message listener. This only has + // to be done once. + static bool isV8Initialized = false; + if (!isV8Initialized) + v8::V8::AddMessageListener(&v8MessageHandler); // Create a new environment v8::Persistent<v8::ObjectTemplate> globalTemplate; m_context = v8::Context::New(0, globalTemplate); + if (m_context.IsEmpty()) + return false; // Starting from now, use local context only. v8::Local<v8::Context> context = v8::Local<v8::Context>::New(m_context); - v8::Context::Scope scope(context); - // Allocate strings used during initialization. - v8::Handle<v8::String> implicitProtoString = v8::String::New("__proto__"); + v8::Context::Scope scope(context); // Create a new JS object and use it as the prototype for the shadow global object. - V8ClassIndex::V8WrapperType contextType = V8ClassIndex::DEDICATEDWORKERCONTEXT; + WrapperTypeInfo* contextType = &V8DedicatedWorkerContext::info; #if ENABLE(SHARED_WORKERS) if (!m_workerContext->isDedicatedWorkerContext()) - contextType = V8ClassIndex::SHAREDWORKERCONTEXT; + contextType = &V8SharedWorkerContext::info; #endif v8::Handle<v8::Function> workerContextConstructor = V8DOMWrapper::getConstructorForContext(contextType, context); v8::Local<v8::Object> jsWorkerContext = SafeAllocation::newInstance(workerContextConstructor); // Bail out if allocation failed. if (jsWorkerContext.IsEmpty()) { dispose(); - return; + return false; } // Wrap the object. - V8DOMWrapper::setDOMWrapper(jsWorkerContext, V8ClassIndex::ToInt(contextType), m_workerContext); + V8DOMWrapper::setDOMWrapper(jsWorkerContext, contextType, m_workerContext); V8DOMWrapper::setJSWrapperForDOMObject(m_workerContext, v8::Persistent<v8::Object>::New(jsWorkerContext)); m_workerContext->ref(); // Insert the object instance as the prototype of the shadow object. - v8::Handle<v8::Object> globalObject = m_context->Global(); - globalObject->Set(implicitProtoString, jsWorkerContext); + v8::Handle<v8::Object> globalObject = v8::Handle<v8::Object>::Cast(m_context->Global()->GetPrototype()); + globalObject->SetPrototype(jsWorkerContext); + return true; } bool WorkerContextExecutionProxy::forgetV8EventObject(Event* event) @@ -189,7 +188,9 @@ ScriptValue WorkerContextExecutionProxy::evaluate(const String& script, const St { v8::HandleScope hs; - initContextIfNeeded(); + if (!initContextIfNeeded()) + return ScriptValue(); + v8::Context::Scope scope(m_context); v8::TryCatch exceptionCatcher; @@ -198,6 +199,9 @@ ScriptValue WorkerContextExecutionProxy::evaluate(const String& script, const St v8::Handle<v8::Script> compiledScript = V8Proxy::compileScript(scriptString, fileName, baseLine); v8::Local<v8::Value> result = runScript(compiledScript); + if (!exceptionCatcher.CanContinue()) + return ScriptValue(); + if (exceptionCatcher.HasCaught()) { v8::Local<v8::Message> message = exceptionCatcher.Message(); state->hadException = true; @@ -247,11 +251,6 @@ v8::Local<v8::Value> WorkerContextExecutionProxy::runScript(v8::Handle<v8::Scrip return result; } -PassRefPtr<V8EventListener> WorkerContextExecutionProxy::findOrCreateEventListener(v8::Local<v8::Value> object, bool isInline, bool findOnly) -{ - return findOnly ? V8EventListenerList::findWrapper(object, isInline) : V8EventListenerList::findOrCreateWrapper<V8WorkerContextEventListener>(object, isInline); -} - void WorkerContextExecutionProxy::trackEvent(Event* event) { m_events.append(event); diff --git a/WebCore/bindings/v8/WorkerContextExecutionProxy.h b/WebCore/bindings/v8/WorkerContextExecutionProxy.h index 67a472b..58824b9 100644 --- a/WebCore/bindings/v8/WorkerContextExecutionProxy.h +++ b/WebCore/bindings/v8/WorkerContextExecutionProxy.h @@ -35,8 +35,6 @@ #if ENABLE(WORKERS) #include "ScriptValue.h" -#include "V8EventListenerList.h" -#include "V8Index.h" #include <v8.h> #include <wtf/OwnPtr.h> #include <wtf/Vector.h> @@ -45,8 +43,6 @@ namespace WebCore { class Event; class EventTarget; - class V8EventListener; - class V8WorkerContextEventListener; class WorkerContext; struct WorkerContextExecutionState { @@ -64,9 +60,6 @@ namespace WebCore { WorkerContextExecutionProxy(WorkerContext*); ~WorkerContextExecutionProxy(); - // Finds/creates event listener wrappers. - PassRefPtr<V8EventListener> findOrCreateEventListener(v8::Local<v8::Value> listener, bool isInline, bool findOnly); - // 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 // events and releases references to their event targets: WorkerContext. @@ -78,15 +71,9 @@ namespace WebCore { // 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; } - - // 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(); - private: void initV8IfNeeded(); - void initContextIfNeeded(); + bool initContextIfNeeded(); void dispose(); // Run an already compiled script. diff --git a/WebCore/bindings/v8/WorkerScriptController.cpp b/WebCore/bindings/v8/WorkerScriptController.cpp index f2311bf..7db0d8d 100644 --- a/WebCore/bindings/v8/WorkerScriptController.cpp +++ b/WebCore/bindings/v8/WorkerScriptController.cpp @@ -41,6 +41,7 @@ #include "DOMTimer.h" #include "V8DOMMap.h" #include "V8Proxy.h" +#include "V8WorkerContext.h" #include "WorkerContext.h" #include "WorkerContextExecutionProxy.h" #include "WorkerObjectProxy.h" @@ -85,11 +86,13 @@ ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, return result; } -void WorkerScriptController::forbidExecution() +void WorkerScriptController::forbidExecution(ForbidExecutionOption option) { - // This function is called from another thread. + // This function may be called from another thread. MutexLocker lock(m_sharedDataMutex); m_executionForbidden = true; + if (option == TerminateRunningScript) + v8::V8::TerminateExecution(); } void WorkerScriptController::setException(ScriptValue exception) @@ -97,6 +100,21 @@ void WorkerScriptController::setException(ScriptValue exception) throwError(*exception.v8Value()); } +WorkerScriptController* WorkerScriptController::controllerForContext() +{ + // 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 = V8DOMWrapper::lookupDOMWrapper(V8WorkerContext::GetTemplate(), global); + // Return 0 if the current executing context is not the worker context. + if (global.IsEmpty()) + return 0; + WorkerContext* workerContext = V8WorkerContext::toNative(global); + return workerContext->script(); +} + } // namespace WebCore #endif // ENABLE(WORKERS) diff --git a/WebCore/bindings/v8/WorkerScriptController.h b/WebCore/bindings/v8/WorkerScriptController.h index 07e224c..616697a 100644 --- a/WebCore/bindings/v8/WorkerScriptController.h +++ b/WebCore/bindings/v8/WorkerScriptController.h @@ -48,14 +48,19 @@ namespace WebCore { WorkerScriptController(WorkerContext*); ~WorkerScriptController(); - WorkerContextExecutionProxy* proxy() { return m_proxy.get(); } + WorkerContextExecutionProxy* proxy() { return m_executionForbidden ? 0 : m_proxy.get(); } + WorkerContext* workerContext() { return m_workerContext; } ScriptValue evaluate(const ScriptSourceCode&); ScriptValue evaluate(const ScriptSourceCode&, ScriptValue* exception); void setException(ScriptValue); - void forbidExecution(); + enum ForbidExecutionOption { TerminateRunningScript, LetRunningScriptFinish }; + void forbidExecution(ForbidExecutionOption); + + // Returns WorkerScriptController for the currently executing context. 0 will be returned if the current executing context is not the worker context. + static WorkerScriptController* controllerForContext(); private: WorkerContext* m_workerContext; diff --git a/WebCore/bindings/v8/WrapperTypeInfo.h b/WebCore/bindings/v8/WrapperTypeInfo.h new file mode 100644 index 0000000..1d1cbfd --- /dev/null +++ b/WebCore/bindings/v8/WrapperTypeInfo.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WrapperTypeInfo_h +#define WrapperTypeInfo_h + +#include <v8.h> + +namespace WebCore { + + class ActiveDOMObject; + + static const int v8DOMWrapperTypeIndex = 0; + static const int v8DOMWrapperObjectIndex = 1; + static const int v8DOMHiddenReferenceArrayIndex = 2; + static const int v8DefaultWrapperInternalFieldCount = 3; + + typedef v8::Persistent<v8::FunctionTemplate> (*GetTemplateFunction)(); + typedef void (*DerefObjectFunction)(void*); + typedef ActiveDOMObject* (*ToActiveDOMObjectFunction)(v8::Handle<v8::Object>); + + // This struct provides a way to store a bunch of information that is helpful when unwrapping + // v8 objects. Each v8 bindings class has exactly one static WrapperTypeInfo member, so + // comparing pointers is a safe way to determine if types match. + struct WrapperTypeInfo { + + static WrapperTypeInfo* unwrap(v8::Handle<v8::Value> typeInfoWrapper) + { + return reinterpret_cast<WrapperTypeInfo*>(v8::External::Unwrap(typeInfoWrapper)); + } + + + bool equals(const WrapperTypeInfo* that) const + { + return this == that; + } + + v8::Persistent<v8::FunctionTemplate> getTemplate() { return getTemplateFunction(); } + + void derefObject(void* object) + { + if (derefObjectFunction) + derefObjectFunction(object); + } + + ActiveDOMObject* toActiveDOMObject(v8::Handle<v8::Object> object) + { + if (!toActiveDOMObjectFunction) + return 0; + return toActiveDOMObjectFunction(object); + } + + const GetTemplateFunction getTemplateFunction; + const DerefObjectFunction derefObjectFunction; + const ToActiveDOMObjectFunction toActiveDOMObjectFunction; + }; +} + +#endif // WrapperTypeInfo_h diff --git a/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp b/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp deleted file mode 100644 index e776438..0000000 --- a/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * 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 "V8AbstractWorker.h" - -#include "AbstractWorker.h" -#include "ExceptionCode.h" -#include "ScriptExecutionContext.h" -#include "V8Binding.h" -#include "V8Proxy.h" -#include "V8Utilities.h" -#include "WorkerContextExecutionProxy.h" - -namespace WebCore { - -v8::Handle<v8::Value> V8AbstractWorker::addEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS(L"DOM.AbstractWorker.addEventListener()"); - AbstractWorker* worker = V8AbstractWorker::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(worker, args[1], false, ListenerFindOrCreate); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - worker->addEventListener(type, listener, useCapture); - - createHiddenDependency(args.Holder(), args[1], cacheIndex); - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8AbstractWorker::removeEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS(L"DOM.AbstractWorker.removeEventListener()"); - AbstractWorker* worker = V8AbstractWorker::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(worker, args[1], false, ListenerFindOnly); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - worker->removeEventListener(type, listener.get(), useCapture); - - removeHiddenDependency(args.Holder(), args[1], cacheIndex); - } - - return v8::Undefined(); -} - -} // namespace WebCore - -#endif // ENABLE(WORKERS) diff --git a/WebCore/bindings/v8/custom/V8CSSStyleSheetCustom.cpp b/WebCore/bindings/v8/custom/V8CSSStyleSheetCustom.cpp index 5dcc966..9effca3 100644 --- a/WebCore/bindings/v8/custom/V8CSSStyleSheetCustom.cpp +++ b/WebCore/bindings/v8/custom/V8CSSStyleSheetCustom.cpp @@ -31,6 +31,7 @@ #include "config.h" #include "V8CSSStyleSheet.h" +#include "V8DOMWrapper.h" #include "V8Node.h" namespace WebCore { @@ -43,7 +44,7 @@ v8::Handle<v8::Value> toV8(CSSStyleSheet* impl) // Add a hidden reference from stylesheet object to its owner node. Node* ownerNode = impl->ownerNode(); if (ownerNode && !wrapper.IsEmpty()) - wrapper->SetInternalField(V8CSSStyleSheet::ownerNodeIndex, toV8(ownerNode)); + V8DOMWrapper::setHiddenReference(wrapper, toV8(ownerNode)); return wrapper; } diff --git a/WebCore/bindings/v8/custom/V8CSSValueCustom.cpp b/WebCore/bindings/v8/custom/V8CSSValueCustom.cpp index b06bc3c..601a62a 100644 --- a/WebCore/bindings/v8/custom/V8CSSValueCustom.cpp +++ b/WebCore/bindings/v8/custom/V8CSSValueCustom.cpp @@ -33,9 +33,12 @@ #include "V8CSSPrimitiveValue.h" #include "V8CSSValueList.h" +#include "V8WebKitCSSTransformValue.h" + +#if ENABLE(SVG) #include "V8SVGColor.h" #include "V8SVGPaint.h" -#include "V8WebKitCSSTransformValue.h" +#endif namespace WebCore { diff --git a/WebCore/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp b/WebCore/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp index 9a05d72..26fc626 100644 --- a/WebCore/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp +++ b/WebCore/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp @@ -98,362 +98,4 @@ void V8CanvasRenderingContext2D::fillStyleAccessorSetter(v8::Local<v8::String> n impl->setFillStyle(toCanvasStyle(value)); } -// TODO: SetStrokeColor and SetFillColor are similar except function names, -// consolidate them into one. -v8::Handle<v8::Value> V8CanvasRenderingContext2D::setStrokeColorCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.CanvasRenderingContext2D.setStrokeColor()"); - CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); - switch (args.Length()) { - case 1: - if (args[0]->IsString()) - 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])); - else - context->setStrokeColor(toFloat(args[0]), toFloat(args[1])); - break; - case 4: - context->setStrokeColor(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3])); - break; - case 5: - context->setStrokeColor(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])); - break; - default: - V8Proxy::throwError(V8Proxy::SyntaxError, "setStrokeColor: Invalid number of arguments"); - break; - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8CanvasRenderingContext2D::setFillColorCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.CanvasRenderingContext2D.setFillColor()"); - CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); - switch (args.Length()) { - case 1: - if (args[0]->IsString()) - 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])); - else - context->setFillColor(toFloat(args[0]), toFloat(args[1])); - break; - case 4: - context->setFillColor(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3])); - break; - case 5: - context->setFillColor(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])); - break; - default: - V8Proxy::throwError(V8Proxy::SyntaxError, "setFillColor: Invalid number of arguments"); - break; - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8CanvasRenderingContext2D::strokeRectCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.CanvasRenderingContext2D.strokeRect()"); - CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(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); - return notHandledByInterceptor(); - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8CanvasRenderingContext2D::setShadowCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.CanvasRenderingContext2D.setShadow()"); - CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); - - switch (args.Length()) { - case 3: - context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2])); - break; - case 4: - if (args[3]->IsString()) - 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])); - else - context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4])); - break; - case 7: - context->setShadow(toFloat(args[0]), toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), toFloat(args[5]), toFloat(args[6])); - break; - case 8: - 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::SyntaxError, "setShadow: Invalid number of arguments"); - break; - } - - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8CanvasRenderingContext2D::drawImageCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.CanvasRenderingContext2D.drawImage()"); - CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); - - v8::Handle<v8::Value> arg = args[0]; - - if (V8HTMLImageElement::HasInstance(arg)) { - ExceptionCode ec = 0; - HTMLImageElement* imageElement = V8HTMLImageElement::toNative(v8::Handle<v8::Object>::Cast(arg)); - switch (args.Length()) { - case 3: - context->drawImage(imageElement, toFloat(args[1]), toFloat(args[2])); - break; - case 5: - context->drawImage(imageElement, 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(imageElement, - 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(); - } - - // HTMLCanvasElement - if (V8HTMLCanvasElement::HasInstance(arg)) { - ExceptionCode ec = 0; - HTMLCanvasElement* canvasElement = V8HTMLCanvasElement::toNative(v8::Handle<v8::Object>::Cast(arg)); - switch (args.Length()) { - case 3: - context->drawImage(canvasElement, toFloat(args[1]), toFloat(args[2])); - break; - case 5: - context->drawImage(canvasElement, 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(canvasElement, - 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(); - } - -#if ENABLE(VIDEO) - // HTMLVideoElement - if (V8HTMLVideoElement::HasInstance(arg)) { - ExceptionCode ec = 0; - HTMLVideoElement* videoElement = V8HTMLVideoElement::toNative(v8::Handle<v8::Object>::Cast(arg)); - switch (args.Length()) { - case 3: - context->drawImage(videoElement, toFloat(args[1]), toFloat(args[2])); - break; - case 5: - context->drawImage(videoElement, 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(videoElement, - 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(); -} - - -v8::Handle<v8::Value> V8CanvasRenderingContext2D::drawImageFromRectCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.CanvasRenderingContext2D.drawImageFromRect()"); - CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); - - v8::Handle<v8::Value> arg = args[0]; - - if (V8HTMLImageElement::HasInstance(arg)) { - HTMLImageElement* imageElement = V8HTMLImageElement::toNative(v8::Handle<v8::Object>::Cast(arg)); - context->drawImageFromRect(imageElement, 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::TypeError, "drawImageFromRect: Invalid type of arguments"); - - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8CanvasRenderingContext2D::createPatternCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.CanvasRenderingContext2D.createPattern()"); - CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); - - v8::Handle<v8::Value> arg = args[0]; - - if (V8HTMLImageElement::HasInstance(arg)) { - HTMLImageElement* imageElement = V8HTMLImageElement::toNative(v8::Handle<v8::Object>::Cast(arg)); - ExceptionCode ec = 0; - RefPtr<CanvasPattern> pattern = context->createPattern(imageElement, toWebCoreStringWithNullCheck(args[1]), ec); - if (ec != 0) { - V8Proxy::setDOMException(ec); - return notHandledByInterceptor(); - } - return toV8(pattern.release()); - } - - if (V8HTMLCanvasElement::HasInstance(arg)) { - HTMLCanvasElement* canvasElement = V8HTMLCanvasElement::toNative(v8::Handle<v8::Object>::Cast(arg)); - ExceptionCode ec = 0; - RefPtr<CanvasPattern> pattern = context->createPattern(canvasElement, toWebCoreStringWithNullCheck(args[1]), ec); - if (ec != 0) { - V8Proxy::setDOMException(ec); - return notHandledByInterceptor(); - } - return toV8(pattern.release()); - } - - V8Proxy::setDOMException(TYPE_MISMATCH_ERR); - return notHandledByInterceptor(); -} - -v8::Handle<v8::Value> V8CanvasRenderingContext2D::fillTextCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.CanvasRenderingContext2D.fillText()"); - - CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); - - // Two forms: - // * fillText(text, x, y) - // * fillText(text, x, y, maxWidth) - if (args.Length() < 3 || args.Length() > 4) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - - String text = toWebCoreString(args[0]); - float x = toFloat(args[1]); - float y = toFloat(args[2]); - - if (args.Length() == 4) { - float maxWidth = toFloat(args[3]); - context->fillText(text, x, y, maxWidth); - } else - context->fillText(text, x, y); - - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8CanvasRenderingContext2D::strokeTextCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.CanvasRenderingContext2D.strokeText()"); - CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); - - // Two forms: - // * strokeText(text, x, y) - // * strokeText(text, x, y, maxWidth) - if (args.Length() < 3 || args.Length() > 4) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - - String text = toWebCoreString(args[0]); - float x = toFloat(args[1]); - float y = toFloat(args[2]); - - if (args.Length() == 4) { - float maxWidth = toFloat(args[3]); - context->strokeText(text, x, y, maxWidth); - } else - context->strokeText(text, x, y); - - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8CanvasRenderingContext2D::putImageDataCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.CanvasRenderingContext2D.putImageData()"); - - // Two froms: - // * putImageData(ImageData, x, y) - // * putImageData(ImageData, x, y, dirtyX, dirtyY, dirtyWidth, dirtyHeight) - if (args.Length() != 3 && args.Length() != 7) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - - CanvasRenderingContext2D* context = V8CanvasRenderingContext2D::toNative(args.Holder()); - - ImageData* imageData = 0; - - // Need to check that the argument is of the correct type, since - // toNative() 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 (V8DOMWrapper::isWrapperOfType(args[0], V8ClassIndex::IMAGEDATA)) - imageData = V8ImageData::toNative(v8::Handle<v8::Object>::Cast(args[0])); - - ExceptionCode ec = 0; - - if (args.Length() == 7) - context->putImageData(imageData, toFloat(args[1]), toFloat(args[2]), toFloat(args[3]), toFloat(args[4]), toFloat(args[5]), toFloat(args[6]), ec); - else - context->putImageData(imageData, toFloat(args[1]), toFloat(args[2]), ec); - - if (ec != 0) { - V8Proxy::setDOMException(ec); - return notHandledByInterceptor(); - } - - return v8::Undefined(); -} - } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp b/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp new file mode 100644 index 0000000..9026420 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "V8Console.h" + +#include "Console.h" +#include "ScriptProfile.h" +#include "V8Binding.h" +#include "V8Proxy.h" +#include "V8ScriptProfile.h" + +namespace WebCore { + +typedef Vector<RefPtr<ScriptProfile> > ProfilesArray; + +v8::Handle<v8::Value> V8Console::profilesAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.Console.profilesAccessorGetter"); + Console* imp = V8Console::toNative(info.Holder()); + const ProfilesArray& profiles = imp->profiles(); + v8::Handle<v8::Array> result = v8::Array::New(profiles.size()); + int index = 0; + ProfilesArray::const_iterator end = profiles.end(); + for (ProfilesArray::const_iterator iter = profiles.begin(); iter != end; ++iter) + result->Set(v8::Integer::New(index++), toV8(iter->get())); + return result; +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomBinding.h b/WebCore/bindings/v8/custom/V8CustomBinding.h deleted file mode 100644 index e69de29..0000000 --- a/WebCore/bindings/v8/custom/V8CustomBinding.h +++ /dev/null diff --git a/WebCore/bindings/v8/custom/V8CustomIDBCallbacks.h b/WebCore/bindings/v8/custom/V8CustomIDBCallbacks.h new file mode 100644 index 0000000..1517f15 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8CustomIDBCallbacks.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef V8CustomIDBCallbacks_h +#define V8CustomIDBCallbacks_h + +#include "Document.h" +#include "Frame.h" +#include "IDBDatabaseError.h" +#include "V8CustomVoidCallback.h" +#include "V8IDBDatabaseError.h" +#include "WorldContextHandle.h" +#include <v8.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> + +#if ENABLE(INDEXED_DATABASE) + +namespace WebCore { + +// FIXME: Maybe split common parts into a base class. +template <typename ResultType, typename ResultWrapperType> +class V8CustomIDBCallbacks : public IDBCallbacks<ResultType> { +public: + static PassRefPtr<V8CustomIDBCallbacks> create(v8::Local<v8::Value> onSuccess, v8::Local<v8::Value> onError, ScriptExecutionContext* scriptExecutionContext) + { + return adoptRef(new V8CustomIDBCallbacks(onSuccess, onError, scriptExecutionContext)); + } + + virtual ~V8CustomIDBCallbacks() + { + m_onSuccess.Dispose(); + m_onError.Dispose(); + } + + // FIXME: Handle suspend/resume correctly. + +private: + V8CustomIDBCallbacks(v8::Local<v8::Value> onSuccess, v8::Local<v8::Value> onError, ScriptExecutionContext* scriptExecutionContext) + : IDBCallbacks<ResultType>(scriptExecutionContext, this) + , m_onSuccess(onSuccess->IsObject() ? v8::Persistent<v8::Object>::New(onSuccess->ToObject()) : v8::Persistent<v8::Object>()) + , m_onError(onError->IsObject() ? v8::Persistent<v8::Object>::New(onError->ToObject()) : v8::Persistent<v8::Object>()) + , m_worldContext(UseCurrentWorld) + { + } + + template <typename Type> + void onEvent(v8::Persistent<v8::Object> callback, PassRefPtr<Type> value) + { + if (!ActiveDOMObject::scriptExecutionContext()) + return; + if (callback.IsEmpty()) + return; + + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = toV8Context(ActiveDOMObject::scriptExecutionContext(), m_worldContext); + if (context.IsEmpty()) + return; + + v8::Context::Scope scope(context); + v8::Handle<v8::Value> argv[] = { + toV8(value) + }; + + // FIXME: Make this work for workers. + ASSERT(ActiveDOMObject::scriptExecutionContext()->isDocument()); + RefPtr<Frame> protector(static_cast<Document*>(ActiveDOMObject::scriptExecutionContext())->frame()); + + bool callbackReturnValue = false; + // FIXME: Do we care if this thing returns true (i.e. it raised an exception)? + invokeCallback(callback, 1, argv, callbackReturnValue); + } + + virtual void onSuccessAsync(PassRefPtr<ResultType> result) + { + onEvent(m_onSuccess, ResultWrapperType::create(result)); + } + + virtual void onErrorAsync(PassRefPtr<IDBDatabaseError> error) + { + onEvent(m_onError, error); + } + + // FIXME: Use OwnHandles. + v8::Persistent<v8::Object> m_onSuccess; + v8::Persistent<v8::Object> m_onError; + + WorldContextHandle m_worldContext; +}; + +} + +#endif + +#endif // V8CustomIDBCallbacks_h diff --git a/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.cpp index d30b95a..df0cc53 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.cpp @@ -35,6 +35,7 @@ #include "V8CustomSQLStatementCallback.h" #include "Frame.h" +#include "ScriptExecutionContext.h" #include "V8CustomVoidCallback.h" #include "V8SQLResultSet.h" #include "V8SQLTransaction.h" @@ -44,6 +45,7 @@ namespace WebCore { V8CustomSQLStatementCallback::V8CustomSQLStatementCallback(v8::Local<v8::Object> callback, Frame* frame) : m_callback(v8::Persistent<v8::Object>::New(callback)) , m_frame(frame) + , m_worldContext(UseCurrentWorld) { } @@ -52,15 +54,15 @@ V8CustomSQLStatementCallback::~V8CustomSQLStatementCallback() m_callback.Dispose(); } -void V8CustomSQLStatementCallback::handleEvent(SQLTransaction* transaction, SQLResultSet* resultSet, bool& raisedException) +void V8CustomSQLStatementCallback::handleEvent(ScriptExecutionContext* context, SQLTransaction* transaction, SQLResultSet* resultSet, bool& raisedException) { v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); - if (context.IsEmpty()) + v8::Handle<v8::Context> v8Context = toV8Context(context, m_worldContext); + if (v8Context.IsEmpty()) return; - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); v8::Handle<v8::Value> argv[] = { toV8(transaction), @@ -77,4 +79,3 @@ void V8CustomSQLStatementCallback::handleEvent(SQLTransaction* transaction, SQLR } // namespace WebCore #endif - diff --git a/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.h b/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.h index 58ee943..31f53e4 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.h +++ b/WebCore/bindings/v8/custom/V8CustomSQLStatementCallback.h @@ -34,9 +34,9 @@ #if ENABLE(DATABASE) #include "SQLStatementCallback.h" +#include "WorldContextHandle.h" #include <v8.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> +#include <wtf/Forward.h> namespace WebCore { @@ -51,12 +51,13 @@ public: } virtual ~V8CustomSQLStatementCallback(); - virtual void handleEvent(SQLTransaction*, SQLResultSet*, bool& raisedException); + virtual void handleEvent(ScriptExecutionContext*, SQLTransaction*, SQLResultSet*, bool& raisedException); private: V8CustomSQLStatementCallback(v8::Local<v8::Object>, Frame*); v8::Persistent<v8::Object> m_callback; RefPtr<Frame> m_frame; + WorldContextHandle m_worldContext; }; } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp index f733ede..2545f24 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp @@ -35,6 +35,7 @@ #include "V8CustomSQLStatementErrorCallback.h" #include "Frame.h" +#include "ScriptExecutionContext.h" #include "V8CustomVoidCallback.h" #include "V8SQLError.h" #include "V8SQLTransaction.h" @@ -44,6 +45,7 @@ namespace WebCore { V8CustomSQLStatementErrorCallback::V8CustomSQLStatementErrorCallback(v8::Local<v8::Object> callback, Frame* frame) : m_callback(v8::Persistent<v8::Object>::New(callback)) , m_frame(frame) + , m_worldContext(UseCurrentWorld) { } @@ -52,15 +54,15 @@ V8CustomSQLStatementErrorCallback::~V8CustomSQLStatementErrorCallback() m_callback.Dispose(); } -bool V8CustomSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, SQLError* error) +bool V8CustomSQLStatementErrorCallback::handleEvent(ScriptExecutionContext* context, SQLTransaction* transaction, SQLError* error) { v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); - if (context.IsEmpty()) + v8::Handle<v8::Context> v8Context = toV8Context(context, m_worldContext); + if (v8Context.IsEmpty()) return true; - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); v8::Handle<v8::Value> argv[] = { toV8(transaction), @@ -75,7 +77,7 @@ bool V8CustomSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, // statement, if any, or onto the next overall step otherwise. Otherwise, // the error callback did not return false, or there was no error callback. // Jump to the last step in the overall steps. - return invokeCallbackTreatOnlyExplicitFalseAsFalse(m_callback, 2, argv, callbackReturnValue) || callbackReturnValue; + return invokeCallback(m_callback, 2, argv, callbackReturnValue) || callbackReturnValue; } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.h b/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.h index 685efc6..c3d7f79 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.h +++ b/WebCore/bindings/v8/custom/V8CustomSQLStatementErrorCallback.h @@ -34,8 +34,7 @@ #if ENABLE(DATABASE) #include "SQLStatementErrorCallback.h" - -#include "SQLStatementErrorCallback.h" +#include "WorldContextHandle.h" #include <v8.h> #include <wtf/PassRefPtr.h> #include <wtf/RefPtr.h> @@ -53,12 +52,13 @@ public: } virtual ~V8CustomSQLStatementErrorCallback(); - virtual bool handleEvent(SQLTransaction*, SQLError*); + virtual bool handleEvent(ScriptExecutionContext*, SQLTransaction*, SQLError*); private: V8CustomSQLStatementErrorCallback(v8::Local<v8::Object>, Frame*); v8::Persistent<v8::Object> m_callback; RefPtr<Frame> m_frame; + WorldContextHandle m_worldContext; }; } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.cpp index 68002d7..efe415c 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.cpp @@ -35,6 +35,7 @@ #include "V8CustomSQLTransactionCallback.h" #include "Frame.h" +#include "ScriptExecutionContext.h" #include "V8CustomVoidCallback.h" #include "V8SQLTransaction.h" @@ -43,6 +44,7 @@ namespace WebCore { V8CustomSQLTransactionCallback::V8CustomSQLTransactionCallback(v8::Local<v8::Object> callback, Frame* frame) : m_callback(v8::Persistent<v8::Object>::New(callback)) , m_frame(frame) + , m_worldContext(UseCurrentWorld) { } @@ -52,15 +54,15 @@ V8CustomSQLTransactionCallback::~V8CustomSQLTransactionCallback() } -void V8CustomSQLTransactionCallback::handleEvent(SQLTransaction* transaction, bool& raisedException) +void V8CustomSQLTransactionCallback::handleEvent(ScriptExecutionContext* context, SQLTransaction* transaction, bool& raisedException) { v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); - if (context.IsEmpty()) + v8::Handle<v8::Context> v8Context = toV8Context(context, m_worldContext); + if (v8Context.IsEmpty()) return; - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); v8::Handle<v8::Value> argv[] = { toV8(transaction) @@ -79,4 +81,3 @@ void V8CustomSQLTransactionCallback::handleEvent(SQLTransaction* transaction, bo } // namespace WebCore #endif - diff --git a/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.h b/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.h index 665404d..60ad529 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.h +++ b/WebCore/bindings/v8/custom/V8CustomSQLTransactionCallback.h @@ -34,9 +34,9 @@ #if ENABLE(DATABASE) #include "SQLTransactionCallback.h" +#include "WorldContextHandle.h" #include <v8.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> +#include <wtf/Forward.h> namespace WebCore { @@ -51,12 +51,13 @@ public: } virtual ~V8CustomSQLTransactionCallback(); - virtual void handleEvent(SQLTransaction*, bool& raisedException); + virtual void handleEvent(ScriptExecutionContext*, SQLTransaction*, bool& raisedException); private: V8CustomSQLTransactionCallback(v8::Local<v8::Object>, Frame*); v8::Persistent<v8::Object> m_callback; RefPtr<Frame> m_frame; + WorldContextHandle m_worldContext; }; } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp b/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp index cf5a0ef..1ef711a 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.cpp @@ -35,6 +35,7 @@ #include "V8CustomSQLTransactionErrorCallback.h" #include "Frame.h" +#include "ScriptExecutionContext.h" #include "V8CustomVoidCallback.h" #include "V8SQLError.h" @@ -43,6 +44,7 @@ namespace WebCore { V8CustomSQLTransactionErrorCallback::V8CustomSQLTransactionErrorCallback(v8::Local<v8::Object> callback, Frame* frame) : m_callback(v8::Persistent<v8::Object>::New(callback)) , m_frame(frame) + , m_worldContext(UseCurrentWorld) { } @@ -51,15 +53,15 @@ V8CustomSQLTransactionErrorCallback::~V8CustomSQLTransactionErrorCallback() m_callback.Dispose(); } -void V8CustomSQLTransactionErrorCallback::handleEvent(SQLError* error) +void V8CustomSQLTransactionErrorCallback::handleEvent(ScriptExecutionContext* context, SQLError* error) { v8::HandleScope handleScope; - v8::Handle<v8::Context> context = V8Proxy::context(m_frame.get()); - if (context.IsEmpty()) + v8::Handle<v8::Context> v8Context = toV8Context(context, m_worldContext); + if (v8Context.IsEmpty()) return; - v8::Context::Scope scope(context); + v8::Context::Scope scope(v8Context); v8::Handle<v8::Value> argv[] = { toV8(error) @@ -75,4 +77,3 @@ void V8CustomSQLTransactionErrorCallback::handleEvent(SQLError* error) } // namespace WebCore #endif - diff --git a/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.h b/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.h index 0387deb..72e9e7a 100644 --- a/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.h +++ b/WebCore/bindings/v8/custom/V8CustomSQLTransactionErrorCallback.h @@ -34,9 +34,9 @@ #if ENABLE(DATABASE) #include "SQLTransactionErrorCallback.h" +#include "WorldContextHandle.h" #include <v8.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> +#include <wtf/Forward.h> namespace WebCore { @@ -51,13 +51,14 @@ public: } virtual ~V8CustomSQLTransactionErrorCallback(); - virtual void handleEvent(SQLError*); + virtual void handleEvent(ScriptExecutionContext*, SQLError*); private: V8CustomSQLTransactionErrorCallback(v8::Local<v8::Object>, Frame*); v8::Persistent<v8::Object> m_callback; RefPtr<Frame> m_frame; + WorldContextHandle m_worldContext; }; } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp b/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp index 8c69e76..f4ea62a 100644 --- a/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp +++ b/WebCore/bindings/v8/custom/V8CustomVoidCallback.cpp @@ -29,10 +29,10 @@ */ #include "config.h" -#include "V8Binding.h" #include "V8CustomVoidCallback.h" #include "Frame.h" +#include "V8Binding.h" namespace WebCore { @@ -64,7 +64,7 @@ void V8CustomVoidCallback::handleEvent() invokeCallback(m_callback, 0, 0, callbackReturnValue); } -static bool invokeCallbackHelper(v8::Persistent<v8::Object> callback, int argc, v8::Handle<v8::Value> argv[], v8::Handle<v8::Value>& returnValue) +bool invokeCallback(v8::Persistent<v8::Object> callback, int argc, v8::Handle<v8::Value> argv[], bool& callbackReturnValue) { v8::TryCatch exceptionCatcher; @@ -73,9 +73,8 @@ static bool invokeCallbackHelper(v8::Persistent<v8::Object> callback, int argc, callbackFunction = v8::Local<v8::Function>::New(v8::Persistent<v8::Function>::Cast(callback)); } else if (callback->IsObject()) { v8::Local<v8::Value> handleEventFunction = callback->Get(v8::String::NewSymbol("handleEvent")); - if (handleEventFunction->IsFunction()) { + if (handleEventFunction->IsFunction()) callbackFunction = v8::Local<v8::Function>::Cast(handleEventFunction); - } } else return false; @@ -87,7 +86,8 @@ static bool invokeCallbackHelper(v8::Persistent<v8::Object> callback, int argc, V8Proxy* proxy = V8Proxy::retrieve(); ASSERT(proxy); - returnValue = proxy->callFunction(callbackFunction, thisObject, argc, argv); + v8::Handle<v8::Value> result = proxy->callFunction(callbackFunction, thisObject, argc, argv); + callbackReturnValue = !result.IsEmpty() && result->BooleanValue(); if (exceptionCatcher.HasCaught()) { v8::Local<v8::Message> message = exceptionCatcher.Message(); @@ -98,20 +98,4 @@ static bool invokeCallbackHelper(v8::Persistent<v8::Object> callback, int argc, return false; } -bool invokeCallback(v8::Persistent<v8::Object> callback, int argc, v8::Handle<v8::Value> argv[], bool& callbackReturnValue) -{ - v8::Handle<v8::Value> returnValue; - bool result = invokeCallbackHelper(callback, argc, argv, returnValue); - callbackReturnValue = !returnValue.IsEmpty() && returnValue->IsBoolean() && returnValue->BooleanValue(); - return result; -} - -bool invokeCallbackTreatOnlyExplicitFalseAsFalse(v8::Persistent<v8::Object> callback, int argc, v8::Handle<v8::Value> argv[], bool& callbackReturnValue) -{ - v8::Handle<v8::Value> returnValue; - bool result = invokeCallbackHelper(callback, argc, argv, returnValue); - callbackReturnValue = !returnValue.IsEmpty() && !returnValue->IsFalse(); - return result; -} - } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomVoidCallback.h b/WebCore/bindings/v8/custom/V8CustomVoidCallback.h index 6b7b3e8..586296b 100644 --- a/WebCore/bindings/v8/custom/V8CustomVoidCallback.h +++ b/WebCore/bindings/v8/custom/V8CustomVoidCallback.h @@ -60,7 +60,6 @@ private: // Returns false if callback failed (null, wrong type, or threw exception). bool invokeCallback(v8::Persistent<v8::Object> callback, int argc, v8::Handle<v8::Value> argv[], bool& callbackReturnValue); -bool invokeCallbackTreatOnlyExplicitFalseAsFalse(v8::Persistent<v8::Object> callback, int argc, v8::Handle<v8::Value> argv[], bool& callbackReturnValue); } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.cpp b/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.cpp index e45cba0..01448d9 100644 --- a/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.cpp +++ b/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.cpp @@ -38,14 +38,13 @@ namespace WebCore { -PassRefPtr<V8CustomXPathNSResolver> V8CustomXPathNSResolver::create(V8Proxy* proxy, v8::Handle<v8::Object> resolver) +PassRefPtr<V8CustomXPathNSResolver> V8CustomXPathNSResolver::create(v8::Handle<v8::Object> resolver) { - return adoptRef(new V8CustomXPathNSResolver(proxy, resolver)); + return adoptRef(new V8CustomXPathNSResolver(resolver)); } -V8CustomXPathNSResolver::V8CustomXPathNSResolver(V8Proxy* proxy, v8::Handle<v8::Object> resolver) - : m_proxy(proxy) - , m_resolver(resolver) +V8CustomXPathNSResolver::V8CustomXPathNSResolver(v8::Handle<v8::Object> resolver) + : m_resolver(resolver) { } @@ -55,14 +54,6 @@ V8CustomXPathNSResolver::~V8CustomXPathNSResolver() String V8CustomXPathNSResolver::lookupNamespaceURI(const String& prefix) { - V8Proxy* proxy = m_proxy; - - if (!proxy) { - proxy = V8Proxy::retrieve(); - if (!proxy) - return String(); - } - v8::Handle<v8::Function> lookupNamespaceURIFunc; v8::Handle<v8::String> lookupNamespaceURIName = v8::String::New("lookupNamespaceURI"); @@ -74,8 +65,10 @@ String V8CustomXPathNSResolver::lookupNamespaceURI(const String& prefix) } if (lookupNamespaceURIFunc.IsEmpty() && !m_resolver->IsFunction()) { - Frame* frame = proxy->frame(); - logInfo(frame, "XPathNSResolver does not have a lookupNamespaceURI method.", String()); + if (V8Proxy* proxy = V8Proxy::retrieve()) { + if (Frame* frame = proxy->frame()) + logInfo(frame, "XPathNSResolver does not have a lookupNamespaceURI method.", String()); + } return String(); } @@ -87,7 +80,7 @@ String V8CustomXPathNSResolver::lookupNamespaceURI(const String& prefix) v8::Handle<v8::Value> argv[argc] = { v8String(prefix) }; v8::Handle<v8::Function> function = lookupNamespaceURIFunc.IsEmpty() ? v8::Handle<v8::Function>::Cast(m_resolver) : lookupNamespaceURIFunc; - v8::Handle<v8::Value> retval = proxy->callFunction(function, m_resolver, argc, argv); + v8::Handle<v8::Value> retval = V8Proxy::callFunctionWithoutFrame(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()) diff --git a/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.h b/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.h index 15ac27d..cf84438 100644 --- a/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.h +++ b/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.h @@ -49,15 +49,14 @@ class V8Proxy; // must not exceed the lifetime of the passed handle. class V8CustomXPathNSResolver : public XPathNSResolver { public: - static PassRefPtr<V8CustomXPathNSResolver> create(V8Proxy* proxy, v8::Handle<v8::Object> resolver); + static PassRefPtr<V8CustomXPathNSResolver> create(v8::Handle<v8::Object> resolver); virtual ~V8CustomXPathNSResolver(); virtual String lookupNamespaceURI(const String& prefix); private: - V8CustomXPathNSResolver(V8Proxy* proxy, v8::Handle<v8::Object> resolver); + explicit V8CustomXPathNSResolver(v8::Handle<v8::Object> resolver); - V8Proxy* m_proxy; v8::Handle<v8::Object> m_resolver; // Handle to resolver object. }; diff --git a/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp b/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp deleted file mode 100644 index 61760b3..0000000 --- a/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * 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 "V8DOMApplicationCache.h" - -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - -#include "ApplicationCacheHost.h" -#include "DOMApplicationCache.h" -#include "V8Binding.h" -#include "V8Document.h" -#include "V8Proxy.h" -#include "V8Utilities.h" -#include "WorkerContextExecutionProxy.h" - -namespace WebCore { - -// Handles appcache.addEventListner(name, func, capture) method calls -v8::Handle<v8::Value> V8DOMApplicationCache::addEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOMApplicationCache.addEventListener()"); - DOMApplicationCache* appcache = V8DOMApplicationCache::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(appcache, args[1], false, ListenerFindOrCreate); - if (listener) { - createHiddenDependency(args.Holder(), args[1], cacheIndex); - String eventType = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - appcache->addEventListener(eventType, listener, useCapture); - } - return v8::Undefined(); -} - -// Handles appcache.removeEventListner(name, func, capture) method calls -v8::Handle<v8::Value> V8DOMApplicationCache::removeEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOMApplicationCache.removeEventListener()"); - DOMApplicationCache* appcache = V8DOMApplicationCache::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(appcache, args[1], false, ListenerFindOnly); - if (listener) { - removeHiddenDependency(args.Holder(), args[1], cacheIndex); - String eventType = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - appcache->removeEventListener(eventType, listener.get(), useCapture); - } - return v8::Undefined(); -} - -} // namespace WebCore - -#endif // ENABLE(OFFLINE_WEB_APPLICATIONS) diff --git a/WebCore/bindings/v8/custom/V8DOMFormDataCustom.cpp b/WebCore/bindings/v8/custom/V8DOMFormDataCustom.cpp new file mode 100644 index 0000000..8a39332 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8DOMFormDataCustom.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "V8DOMFormData.h" + +#include "DOMFormData.h" +#include "V8Binding.h" +#include "V8Blob.h" +#include "V8Proxy.h" +#include "V8Utilities.h" + +namespace WebCore { + +v8::Handle<v8::Value> V8DOMFormData::appendCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.FormData.append()"); + + if (args.Length() < 2) + return throwError("Not enough arguments", V8Proxy::SyntaxError); + + DOMFormData* domFormData = V8DOMFormData::toNative(args.Holder()); + + String name = toWebCoreStringWithNullCheck(args[0]); + + v8::Handle<v8::Value> arg = args[1]; + if (V8Blob::HasInstance(arg)) { + v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); + Blob* blob = V8Blob::toNative(object); + ASSERT(blob); + domFormData->append(name, blob); + } else + domFormData->append(name, toWebCoreStringWithNullCheck(arg)); + + return v8::Undefined(); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp b/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp index 9719837..6a53a1f 100644 --- a/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp @@ -31,7 +31,6 @@ #include "config.h" #include "V8DOMWindow.h" -#include "Base64.h" #include "Chrome.h" #include "Database.h" #include "DOMTimer.h" @@ -55,7 +54,13 @@ #include "V8BindingDOMWindow.h" #include "V8BindingState.h" #include "V8CustomEventListener.h" +#include "V8Database.h" +#include "V8DatabaseCallback.h" +#include "V8GCForContextDispose.h" +#include "V8HTMLAudioElementConstructor.h" #include "V8HTMLCollection.h" +#include "V8HTMLImageElementConstructor.h" +#include "V8HTMLOptionElementConstructor.h" #include "V8MessagePortCustom.h" #include "V8Node.h" #include "V8Proxy.h" @@ -135,38 +140,14 @@ v8::Handle<v8::Value> WindowSetTimeoutImpl(const v8::Arguments& args, bool singl id = DOMTimer::install(scriptContext, new ScheduledAction(V8Proxy::context(imp->frame()), functionString), timeout, singleShot); } - return v8::Integer::New(id); -} - -static bool isAscii(const String& str) -{ - for (size_t i = 0; i < str.length(); i++) { - if (str[i] > 0xFF) - return false; + // Try to do the idle notification before the timeout expires to get better + // use of any idle time. Aim for the middle of the interval for simplicity. + if (timeout > 0) { + double maximumFireInterval = static_cast<double>(timeout) / 1000 / 2; + V8GCForContextDispose::instance().notifyIdleSooner(maximumFireInterval); } - return true; -} -static v8::Handle<v8::Value> convertBase64(const String& str, bool encode) -{ - if (!isAscii(str)) { - V8Proxy::setDOMException(INVALID_CHARACTER_ERR); - return notHandledByInterceptor(); - } - - Vector<char> inputCharacters(str.length()); - for (size_t i = 0; i < str.length(); i++) - inputCharacters[i] = static_cast<char>(str[i]); - Vector<char> outputCharacters; - - if (encode) - base64Encode(inputCharacters, outputCharacters); - else { - if (!base64Decode(inputCharacters, outputCharacters)) - return throwError("Cannot decode base64", V8Proxy::GeneralError); - } - - return v8String(String(outputCharacters.data(), outputCharacters.size())); + return v8::Integer::New(id); } v8::Handle<v8::Value> V8DOMWindow::eventAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) @@ -250,7 +231,7 @@ void V8DOMWindow::openerAccessorSetter(v8::Local<v8::String> name, v8::Local<v8: v8::Handle<v8::Value> V8DOMWindow::AudioAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { DOMWindow* window = V8DOMWindow::toNative(info.Holder()); - return V8DOMWrapper::getConstructor(V8ClassIndex::AUDIO, window); + return V8DOMWrapper::getConstructor(&V8HTMLAudioElementConstructor::info, window); } #endif @@ -258,13 +239,13 @@ v8::Handle<v8::Value> V8DOMWindow::AudioAccessorGetter(v8::Local<v8::String> nam v8::Handle<v8::Value> V8DOMWindow::ImageAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { DOMWindow* window = V8DOMWindow::toNative(info.Holder()); - return V8DOMWrapper::getConstructor(V8ClassIndex::IMAGE, window); + return V8DOMWrapper::getConstructor(&V8HTMLImageElementConstructor::info, window); } v8::Handle<v8::Value> V8DOMWindow::OptionAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { DOMWindow* window = V8DOMWindow::toNative(info.Holder()); - return V8DOMWrapper::getConstructor(V8ClassIndex::OPTION, window); + return V8DOMWrapper::getConstructor(&V8HTMLOptionElementConstructor::info, window); } v8::Handle<v8::Value> V8DOMWindow::addEventListenerCallback(const v8::Arguments& args) @@ -289,11 +270,11 @@ v8::Handle<v8::Value> V8DOMWindow::addEventListenerCallback(const v8::Arguments& if (!proxy) return v8::Undefined(); - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(proxy, args[1], false, ListenerFindOrCreate); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(args[1], false, ListenerFindOrCreate); if (listener) { imp->addEventListener(eventType, listener, useCapture); - createHiddenDependency(args.Holder(), args[1], cacheIndex); + createHiddenDependency(args.Holder(), args[1], eventListenerCacheIndex); } return v8::Undefined(); @@ -321,11 +302,11 @@ v8::Handle<v8::Value> V8DOMWindow::removeEventListenerCallback(const v8::Argumen if (!proxy) return v8::Undefined(); - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(proxy, args[1], false, ListenerFindOnly); + RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(args[1], false, ListenerFindOnly); if (listener) { imp->removeEventListener(eventType, listener.get(), useCapture); - removeHiddenDependency(args.Holder(), args[1], cacheIndex); + removeHiddenDependency(args.Holder(), args[1], eventListenerCacheIndex); } return v8::Undefined(); @@ -339,8 +320,11 @@ v8::Handle<v8::Value> V8DOMWindow::postMessageCallback(const v8::Arguments& args DOMWindow* source = V8Proxy::retrieveFrameForCallingContext()->domWindow(); ASSERT(source->frame()); - v8::TryCatch tryCatch; - RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0]); + bool didThrow = false; + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0], didThrow); + if (didThrow) + return v8::Undefined(); + MessagePortArray portArray; String targetOrigin; @@ -348,6 +332,7 @@ v8::Handle<v8::Value> V8DOMWindow::postMessageCallback(const v8::Arguments& args // postMessage(message, port, targetOrigin); // or // postMessage(message, targetOrigin); + v8::TryCatch tryCatch; if (args.Length() > 2) { if (!getMessagePortArray(args[1], portArray)) return v8::Undefined(); @@ -364,44 +349,6 @@ v8::Handle<v8::Value> V8DOMWindow::postMessageCallback(const v8::Arguments& args return throwError(ec); } -v8::Handle<v8::Value> V8DOMWindow::atobCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.DOMWindow.atob()"); - - if (args[0]->IsNull()) - return v8String(""); - String str = toWebCoreString(args[0]); - - DOMWindow* imp = V8DOMWindow::toNative(args.Holder()); - - if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) - return v8::Undefined(); - - if (args.Length() < 1) - return throwError("Not enough arguments", V8Proxy::SyntaxError); - - return convertBase64(str, false); -} - -v8::Handle<v8::Value> V8DOMWindow::btoaCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.DOMWindow.btoa()"); - - if (args[0]->IsNull()) - return v8String(""); - String str = toWebCoreString(args[0]); - - DOMWindow* imp = V8DOMWindow::toNative(args.Holder()); - - if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) - return v8::Undefined(); - - if (args.Length() < 1) - return throwError("Not enough arguments", V8Proxy::SyntaxError); - - return convertBase64(str, true); -} - // FIXME(fqian): returning string is cheating, and we should // fix this by calling toString function on the receiver. // However, V8 implements toString in JavaScript, which requires @@ -768,39 +715,33 @@ v8::Handle<v8::Value> V8DOMWindow::setIntervalCallback(const v8::Arguments& args return WindowSetTimeoutImpl(args, false); } - -void ClearTimeoutImpl(const v8::Arguments& args) +v8::Handle<v8::Value> V8DOMWindow::openDatabaseCallback(const v8::Arguments& args) { - int handle = toInt32(args[0]); + INC_STATS("DOM.DOMWindow.openDatabase"); + if (args.Length() < 4) + return v8::Undefined(); - v8::Handle<v8::Object> holder = args.Holder(); - DOMWindow* imp = V8DOMWindow::toNative(holder); + DOMWindow* imp = V8DOMWindow::toNative(args.Holder()); if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) - return; - ScriptExecutionContext* context = static_cast<ScriptExecutionContext*>(imp->document()); - if (!context) - return; - DOMTimer::removeById(context, handle); -} + return v8::Undefined(); + ExceptionCode ec = 0; + String name = toWebCoreString(args[0]); + String version = toWebCoreString(args[1]); + String displayName = toWebCoreString(args[2]); + unsigned long estimatedSize = args[3]->IntegerValue(); + RefPtr<DatabaseCallback> creationCallback; + if ((args.Length() >= 5) && args[4]->IsObject()) + creationCallback = V8DatabaseCallback::create(args[4], imp->frame()); -v8::Handle<v8::Value> V8DOMWindow::clearTimeoutCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.DOMWindow.clearTimeout"); - ClearTimeoutImpl(args); - return v8::Undefined(); -} + v8::Handle<v8::Value> result = toV8(imp->openDatabase(name, version, displayName, estimatedSize, creationCallback.release(), ec)); -v8::Handle<v8::Value> V8DOMWindow::clearIntervalCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.DOMWindow.clearInterval"); - ClearTimeoutImpl(args); - return v8::Undefined(); + V8Proxy::setDOMException(ec); + return result; } -bool V8DOMWindow::namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value> data) +bool V8DOMWindow::namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value>) { - ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::DOMWINDOW); v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), host); if (window.IsEmpty()) return false; // the frame is gone. @@ -824,9 +765,8 @@ bool V8DOMWindow::namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::V return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), target, false); } -bool V8DOMWindow::indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value> data) +bool V8DOMWindow::indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value>) { - ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::DOMWINDOW); v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), host); if (window.IsEmpty()) return false; diff --git a/WebCore/bindings/v8/custom/V8DatabaseCallback.cpp b/WebCore/bindings/v8/custom/V8DatabaseCallback.cpp new file mode 100644 index 0000000..088d89f --- /dev/null +++ b/WebCore/bindings/v8/custom/V8DatabaseCallback.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2010, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(DATABASE) + +#include "V8DatabaseCallback.h" + +#include "Frame.h" +#include "ScriptExecutionContext.h" +#include "V8CustomVoidCallback.h" +#include "V8Database.h" + +namespace WebCore { + +V8DatabaseCallback::V8DatabaseCallback(v8::Local<v8::Object> callback, Frame* frame) + : m_callback(v8::Persistent<v8::Object>::New(callback)) + , m_frame(frame) + , m_worldContext(UseCurrentWorld) +{ +} + +V8DatabaseCallback::~V8DatabaseCallback() +{ + m_callback.Dispose(); +} + +void V8DatabaseCallback::handleEvent(ScriptExecutionContext* context, Database* database) +{ + v8::HandleScope handleScope; + + v8::Handle<v8::Context> v8Context = toV8Context(context, m_worldContext); + if (v8Context.IsEmpty()) + return; + + v8::Context::Scope scope(v8Context); + + v8::Handle<v8::Value> argv[] = { + toV8(database) + }; + + // Protect the frame until the callback returns. + RefPtr<Frame> protector(m_frame); + + bool callbackReturnValue = false; + invokeCallback(m_callback, 1, argv, callbackReturnValue); +} + +} // namespace WebCore + +#endif diff --git a/WebCore/bindings/v8/custom/V8DatabaseCallback.h b/WebCore/bindings/v8/custom/V8DatabaseCallback.h new file mode 100644 index 0000000..064a9a7 --- /dev/null +++ b/WebCore/bindings/v8/custom/V8DatabaseCallback.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef V8DatabaseCallback_h +#define V8DatabaseCallback_h + +#if ENABLE(DATABASE) + +#include "DatabaseCallback.h" +#include "WorldContextHandle.h" +#include <v8.h> +#include <wtf/Forward.h> + +namespace WebCore { + +class Frame; + +class V8DatabaseCallback : public DatabaseCallback { +public: + static PassRefPtr<V8DatabaseCallback> create(v8::Local<v8::Value> value, Frame* frame) + { + ASSERT(value->IsObject()); + return adoptRef(new V8DatabaseCallback(value->ToObject(), frame)); + } + virtual ~V8DatabaseCallback(); + + virtual void handleEvent(ScriptExecutionContext*, Database*); + +private: + V8DatabaseCallback(v8::Local<v8::Object>, Frame*); + + v8::Persistent<v8::Object> m_callback; + RefPtr<Frame> m_frame; + WorldContextHandle m_worldContext; +}; + +} // namespace WebCore + +#endif + +#endif // V8DatabaseCallback_h diff --git a/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp b/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp index 4486dbe..8fcf9a8 100644 --- a/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp @@ -46,7 +46,10 @@ v8::Handle<v8::Value> V8DedicatedWorkerContext::postMessageCallback(const v8::Ar { INC_STATS(L"DOM.DedicatedWorkerContext.postMessage"); DedicatedWorkerContext* workerContext = V8DedicatedWorkerContext::toNative(args.Holder()); - RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0]); + bool didThrow = false; + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0], didThrow); + if (didThrow) + return v8::Undefined(); MessagePortArray portArray; if (args.Length() > 1) { if (!getMessagePortArray(args[1], portArray)) diff --git a/WebCore/bindings/v8/custom/V8DocumentCustom.cpp b/WebCore/bindings/v8/custom/V8DocumentCustom.cpp index 8968707..9fa9f80 100644 --- a/WebCore/bindings/v8/custom/V8DocumentCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DocumentCustom.cpp @@ -46,11 +46,16 @@ #include "V8IsolatedContext.h" #include "V8Node.h" #include "V8Proxy.h" -#include "V8SVGDocument.h" +#if ENABLE(3D_CANVAS) #include "V8WebGLRenderingContext.h" +#endif #include "V8XPathNSResolver.h" #include "V8XPathResult.h" +#if ENABLE(SVG) +#include "V8SVGDocument.h" +#endif + #include <wtf/RefPtr.h> namespace WebCore { @@ -67,7 +72,7 @@ v8::Handle<v8::Value> V8Document::evaluateCallback(const v8::Arguments& args) if (V8Node::HasInstance(args[1])) contextNode = V8Node::toNative(v8::Handle<v8::Object>::Cast(args[1])); - RefPtr<XPathNSResolver> resolver = V8DOMWrapper::getXPathNSResolver(args[2], V8Proxy::retrieve(V8Proxy::retrieveFrameForCallingContext())); + RefPtr<XPathNSResolver> resolver = V8DOMWrapper::getXPathNSResolver(args[2]); if (!resolver && !args[2]->IsNull() && !args[2]->IsUndefined()) return throwError(TYPE_MISMATCH_ERR); diff --git a/WebCore/bindings/v8/custom/V8ElementCustom.cpp b/WebCore/bindings/v8/custom/V8ElementCustom.cpp index 86f134e..8256110 100644 --- a/WebCore/bindings/v8/custom/V8ElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8ElementCustom.cpp @@ -45,7 +45,10 @@ #include "V8BindingState.h" #include "V8HTMLElement.h" #include "V8Proxy.h" + +#if ENABLE(SVG) #include "V8SVGElement.h" +#endif #include <wtf/RefPtr.h> diff --git a/WebCore/bindings/v8/custom/V8EventCustom.cpp b/WebCore/bindings/v8/custom/V8EventCustom.cpp index 79bddc0..b2728ec 100644 --- a/WebCore/bindings/v8/custom/V8EventCustom.cpp +++ b/WebCore/bindings/v8/custom/V8EventCustom.cpp @@ -33,11 +33,13 @@ #include "Clipboard.h" #include "ClipboardEvent.h" +#include "CustomEvent.h" #include "Event.h" #include "V8BeforeLoadEvent.h" #include "V8Binding.h" #include "V8Clipboard.h" #include "V8CompositionEvent.h" +#include "V8CustomEvent.h" #include "V8ErrorEvent.h" #include "V8KeyboardEvent.h" #include "V8MessageEvent.h" @@ -48,7 +50,6 @@ #include "V8PopStateEvent.h" #include "V8ProgressEvent.h" #include "V8Proxy.h" -#include "V8SVGZoomEvent.h" #include "V8StorageEvent.h" #include "V8TextEvent.h" #include "V8TouchEvent.h" @@ -58,6 +59,10 @@ #include "V8WheelEvent.h" #include "V8XMLHttpRequestProgressEvent.h" +#if ENABLE(SVG) +#include "V8SVGZoomEvent.h" +#endif + namespace WebCore { void V8Event::valueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) @@ -140,6 +145,8 @@ v8::Handle<v8::Value> toV8(Event* impl) #endif if (impl->isBeforeLoadEvent()) return toV8(static_cast<BeforeLoadEvent*>(impl)); + if (impl->isCustomEvent()) + return toV8(static_cast<CustomEvent*>(impl)); return V8Event::wrap(impl); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8EventSourceConstructor.cpp b/WebCore/bindings/v8/custom/V8EventSourceConstructor.cpp index 793ffb6..01e9c44 100644 --- a/WebCore/bindings/v8/custom/V8EventSourceConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8EventSourceConstructor.cpp @@ -56,17 +56,17 @@ v8::Handle<v8::Value> V8EventSource::constructorCallback(const v8::Arguments& ar if (!context) return throwError("EventSource constructor's associated context is not available", V8Proxy::ReferenceError); if (args.Length() != 1) - return throwError("EventSource constructor wrong number of parameters", V8Proxy::TypeError); + return throwError("Not enough arguments", V8Proxy::SyntaxError); ExceptionCode ec = 0; String url = toWebCoreString(args[0]); RefPtr<EventSource> eventSource = EventSource::create(url, context, ec); - + if (ec) return throwError(ec); - V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::EVENTSOURCE), eventSource.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), &info, eventSource.get()); // Add object to the wrapper map. eventSource->ref(); diff --git a/WebCore/bindings/v8/custom/V8EventSourceCustom.cpp b/WebCore/bindings/v8/custom/V8EventSourceCustom.cpp deleted file mode 100644 index a7f79db..0000000 --- a/WebCore/bindings/v8/custom/V8EventSourceCustom.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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(EVENTSOURCE) -#include "V8EventSource.h" - -#include "EventSource.h" - -#include "V8Binding.h" -#include "V8Proxy.h" - -namespace WebCore { - -v8::Handle<v8::Value> V8EventSource::addEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.EventSource.addEventListener()"); - EventSource* eventSource = V8EventSource::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(eventSource, args[1], false, ListenerFindOrCreate); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - eventSource->addEventListener(type, listener, useCapture); - - createHiddenDependency(args.Holder(), args[1], cacheIndex); - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8EventSource::removeEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.EventSource.removeEventListener()"); - EventSource* eventSource = V8EventSource::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(eventSource, args[1], false, ListenerFindOnly); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - eventSource->removeEventListener(type, listener.get(), useCapture); - - removeHiddenDependency(args.Holder(), args[1], cacheIndex); - } - - return v8::Undefined(); -} - -} // namespace WebCore - -#endif // ENABLE(EVENTSOURCE) diff --git a/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp index 9b75db8..df16501 100644 --- a/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp @@ -44,6 +44,8 @@ namespace WebCore { +WrapperTypeInfo V8HTMLAudioElementConstructor::info = { V8HTMLAudioElementConstructor::GetTemplate, 0, false }; + static v8::Handle<v8::Value> v8HTMLAudioElementConstructorCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLAudioElement.Contructor"); @@ -69,7 +71,7 @@ static v8::Handle<v8::Value> v8HTMLAudioElementConstructorCallback(const v8::Arg src = toWebCoreString(args[0]); RefPtr<HTMLAudioElement> audio = HTMLAudioElement::createForJSConstructor(document, src); - V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::AUDIO), audio.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), &V8HTMLAudioElementConstructor::info, audio.get()); audio->ref(); V8DOMWrapper::setJSWrapperForDOMNode(audio.get(), v8::Persistent<v8::Object>::New(args.Holder())); return args.Holder(); diff --git a/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.h b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.h index 711f539..8bc5f2c 100755 --- a/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.h +++ b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.h @@ -31,6 +31,8 @@ #ifndef V8HTMLAudioElementConstructor_h #define V8HTMLAudioElementConstructor_h +#include "WrapperTypeInfo.h" + #include <v8.h> namespace WebCore { @@ -38,6 +40,7 @@ namespace WebCore { class V8HTMLAudioElementConstructor { public: static v8::Persistent<v8::FunctionTemplate> GetTemplate(); + static WrapperTypeInfo info; }; } diff --git a/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp index 54a003c..67ba38b 100644 --- a/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp @@ -39,7 +39,9 @@ #include "V8CanvasRenderingContext2D.h" #include "V8Node.h" #include "V8Proxy.h" +#if ENABLE(3D_CANVAS) #include "V8WebGLRenderingContext.h" +#endif namespace WebCore { @@ -54,7 +56,7 @@ v8::Handle<v8::Value> V8HTMLCanvasElement::getContextCallback(const v8::Argument if (contextId == "experimental-webgl" || contextId == "webkit-3d") { attrs = WebGLContextAttributes::create(); WebGLContextAttributes* webGLAttrs = static_cast<WebGLContextAttributes*>(attrs.get()); - if (args.Length() > 1 && args[0]->IsObject()) { + if (args.Length() > 1 && args[1]->IsObject()) { v8::Handle<v8::Object> jsAttrs = args[1]->ToObject(); v8::Handle<v8::String> alpha = v8::String::New("alpha"); if (jsAttrs->Has(alpha)) diff --git a/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp index 29b4813..4751224 100644 --- a/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp @@ -44,6 +44,8 @@ namespace WebCore { +WrapperTypeInfo V8HTMLImageElementConstructor::info = { V8HTMLImageElementConstructor::GetTemplate, 0, false }; + static v8::Handle<v8::Value> v8HTMLImageElementConstructorCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLImageElement.Contructor"); @@ -80,7 +82,7 @@ static v8::Handle<v8::Value> v8HTMLImageElementConstructorCallback(const v8::Arg } RefPtr<HTMLImageElement> image = HTMLImageElement::createForJSConstructor(document, optionalWidth, optionalHeight); - V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::IMAGE), image.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), &V8HTMLImageElementConstructor::info, image.get()); image->ref(); V8DOMWrapper::setJSWrapperForDOMNode(image.get(), v8::Persistent<v8::Object>::New(args.Holder())); return args.Holder(); diff --git a/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.h b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.h index 19ee944..5db4946 100755 --- a/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.h +++ b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.h @@ -31,6 +31,8 @@ #ifndef V8HTMLImageElementConstructor_h #define V8HTMLImageElementConstructor_h +#include "WrapperTypeInfo.h" + #include <v8.h> namespace WebCore { @@ -38,6 +40,7 @@ namespace WebCore { class V8HTMLImageElementConstructor { public: static v8::Persistent<v8::FunctionTemplate> GetTemplate(); + static WrapperTypeInfo info; }; } diff --git a/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp index 1ff1d2e..6b84856 100644 --- a/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp @@ -44,6 +44,8 @@ namespace WebCore { +WrapperTypeInfo V8HTMLOptionElementConstructor::info = { V8HTMLOptionElementConstructor::GetTemplate, 0, false }; + static v8::Handle<v8::Value> v8HTMLOptionElementConstructorCallback(const v8::Arguments& args) { INC_STATS("DOM.HTMLOptionElement.Contructor"); @@ -78,7 +80,7 @@ static v8::Handle<v8::Value> v8HTMLOptionElementConstructorCallback(const v8::Ar if (ec) throwError(ec); - V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::OPTION), option.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), &V8HTMLOptionElementConstructor::info, option.get()); option->ref(); V8DOMWrapper::setJSWrapperForDOMNode(option.get(), v8::Persistent<v8::Object>::New(args.Holder())); return args.Holder(); diff --git a/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.h b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.h index 905a745..2adf0fe 100755 --- a/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.h +++ b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.h @@ -31,6 +31,8 @@ #ifndef V8HTMLOptionElementConstructor_h #define V8HTMLOptionElementConstructor_h +#include "WrapperTypeInfo.h" + #include <v8.h> namespace WebCore { @@ -38,6 +40,7 @@ namespace WebCore { class V8HTMLOptionElementConstructor { public: static v8::Persistent<v8::FunctionTemplate> GetTemplate(); + static WrapperTypeInfo info; }; } diff --git a/WebCore/bindings/v8/custom/V8HistoryCustom.cpp b/WebCore/bindings/v8/custom/V8HistoryCustom.cpp index 6075ec5..ad2b9a9 100644 --- a/WebCore/bindings/v8/custom/V8HistoryCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HistoryCustom.cpp @@ -43,7 +43,10 @@ namespace WebCore { v8::Handle<v8::Value> V8History::pushStateCallback(const v8::Arguments& args) { - RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(args[0]); + bool didThrow = false; + RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(args[0], didThrow); + if (didThrow) + return v8::Undefined(); v8::TryCatch tryCatch; String title = toWebCoreStringWithNullOrUndefinedCheck(args[1]); @@ -64,7 +67,10 @@ v8::Handle<v8::Value> V8History::pushStateCallback(const v8::Arguments& args) v8::Handle<v8::Value> V8History::replaceStateCallback(const v8::Arguments& args) { - RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(args[0]); + bool didThrow = false; + RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(args[0], didThrow); + if (didThrow) + return v8::Undefined(); v8::TryCatch tryCatch; String title = toWebCoreStringWithNullOrUndefinedCheck(args[1]); @@ -83,33 +89,18 @@ v8::Handle<v8::Value> V8History::replaceStateCallback(const v8::Arguments& args) return throwError(ec); } -bool V8History::indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value> data) +bool V8History::indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value>) { - ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::HISTORY); // Only allow same origin access. History* history = V8History::toNative(host); return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), history->frame(), false); } -bool V8History::namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value> data) +bool V8History::namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value>) { - ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::HISTORY); // Only allow same origin access. History* history = V8History::toNative(host); return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), history->frame(), false); } -v8::Handle<v8::Value> toV8(History* impl) -{ - if (!impl) - return v8::Null(); - v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(impl); - if (wrapper.IsEmpty()) { - wrapper = V8History::wrap(impl); - if (!wrapper.IsEmpty()) - V8DOMWrapper::setHiddenWindowReference(impl->frame(), V8DOMWindow::historyIndex, wrapper); - } - return wrapper; -} - } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8IndexedDatabaseRequestCustom.cpp b/WebCore/bindings/v8/custom/V8IndexedDatabaseRequestCustom.cpp index 0fd182c..e8c2b68 100644 --- a/WebCore/bindings/v8/custom/V8IndexedDatabaseRequestCustom.cpp +++ b/WebCore/bindings/v8/custom/V8IndexedDatabaseRequestCustom.cpp @@ -33,7 +33,12 @@ #if ENABLE(INDEXED_DATABASE) #include "V8IndexedDatabaseRequest.h" +#include "IDBDatabaseError.h" +#include "IDBDatabaseRequest.h" #include "V8Binding.h" +#include "V8CustomIDBCallbacks.h" +#include "V8IDBDatabaseError.h" +#include "V8IDBDatabaseRequest.h" #include "V8Proxy.h" namespace WebCore { @@ -45,12 +50,32 @@ v8::Handle<v8::Value> V8IndexedDatabaseRequest::openCallback(const v8::Arguments return throwError(V8Proxy::TypeError); V8Parameter<> name = args[0]; V8Parameter<> description = args[1]; + bool modifyDatabase = true; - if (args.Length() > 2) + if (args.Length() > 2 && !args[2]->IsUndefined() && !args[2]->IsNull()) modifyDatabase = args[2]->BooleanValue(); + v8::Local<v8::Value> onError; + v8::Local<v8::Value> onSuccess; + if (args.Length() > 3 && !args[3]->IsUndefined() && !args[3]->IsNull()) { + if (!args[3]->IsObject()) + return throwError("onerror callback was not the proper type"); + onError = args[3]; + } + if (args.Length() > 4 && !args[4]->IsUndefined() && !args[4]->IsNull()) { + if (!args[4]->IsObject()) + return throwError("onsuccess callback was not the proper type"); + onSuccess = args[4]; + } + if (!onError->IsObject() && !onSuccess->IsObject()) + return throwError("Neither the onerror nor the onsuccess callbacks were set."); + + Frame* frame = V8Proxy::retrieveFrameForCurrentContext(); + RefPtr<V8CustomIDBCallbacks<IDBDatabase, IDBDatabaseRequest> > callbacks = + V8CustomIDBCallbacks<IDBDatabase, IDBDatabaseRequest>::create(onSuccess, onError, frame->document()); + ExceptionCode ec = 0; - imp->open(name, description, modifyDatabase, ec); + imp->open(name, description, modifyDatabase, callbacks, ec); if (ec) return throwError(ec); return v8::Handle<v8::Value>(); diff --git a/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp b/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp index 054f9ba..4c091c8 100644 --- a/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp +++ b/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp @@ -39,10 +39,14 @@ #include "InspectorController.h" #include "Node.h" #include "Page.h" +#include "ScriptDebugServer.h" #include "SerializedScriptValue.h" #include "V8Binding.h" +#include "V8BindingState.h" +#include "V8DOMWindow.h" #include "V8Database.h" +#include "V8JavaScriptCallFrame.h" #include "V8Node.h" #include "V8Proxy.h" #include "V8Storage.h" @@ -59,7 +63,6 @@ static void WeakReferenceCallback(v8::Persistent<v8::Value> object, void* parame static v8::Local<v8::Object> createInjectedScriptHostV8Wrapper(InjectedScriptHost* host) { - V8ClassIndex::V8WrapperType descriptorType = V8ClassIndex::INJECTEDSCRIPTHOST; v8::Local<v8::Function> function = V8InjectedScriptHost::GetTemplate()->GetFunction(); if (function.IsEmpty()) { // Return if allocation failed. @@ -70,7 +73,7 @@ static v8::Local<v8::Object> createInjectedScriptHostV8Wrapper(InjectedScriptHos // Avoid setting the wrapper if allocation failed. return v8::Local<v8::Object>(); } - V8DOMWrapper::setDOMWrapper(instance, V8ClassIndex::ToInt(descriptorType), host); + V8DOMWrapper::setDOMWrapper(instance, &V8InjectedScriptHost::info, host); // Create a weak reference to the v8 wrapper of InspectorBackend to deref // InspectorBackend when the wrapper is garbage collected. host->ref(); @@ -79,7 +82,7 @@ static v8::Local<v8::Object> createInjectedScriptHostV8Wrapper(InjectedScriptHos return instance; } -static ScriptObject createInjectedScript(const String& scriptSource, InjectedScriptHost* injectedScriptHost, ScriptState* inspectedScriptState, long id) +ScriptObject InjectedScriptHost::createInjectedScript(const String& scriptSource, ScriptState* inspectedScriptState, long id) { v8::HandleScope scope; @@ -90,7 +93,7 @@ static ScriptObject createInjectedScript(const String& scriptSource, InjectedScr // instead of calling toV8() that would create the // wrapper in the current context. // FIXME: make it possible to use generic bindings factory for InjectedScriptHost. - v8::Local<v8::Object> scriptHostWrapper = createInjectedScriptHostV8Wrapper(injectedScriptHost); + v8::Local<v8::Object> scriptHostWrapper = createInjectedScriptHostV8Wrapper(this); if (scriptHostWrapper.IsEmpty()) return ScriptObject(); @@ -109,9 +112,10 @@ static ScriptObject createInjectedScript(const String& scriptSource, InjectedScr v8::Handle<v8::Value> args[] = { scriptHostWrapper, windowGlobal, - v8::Number::New(id) + v8::Number::New(id), + v8::String::New("v8") }; - v8::Local<v8::Value> injectedScriptValue = v8::Function::Cast(*v)->Call(windowGlobal, 3, args); + v8::Local<v8::Value> injectedScriptValue = v8::Function::Cast(*v)->Call(windowGlobal, 4, args); v8::Local<v8::Object> injectedScript(v8::Object::Cast(*injectedScriptValue)); return ScriptObject(inspectedScriptState, injectedScript); } @@ -151,6 +155,20 @@ v8::Handle<v8::Value> V8InjectedScriptHost::pushNodePathToFrontendCallback(const return v8::Undefined(); } +#if ENABLE(JAVASCRIPT_DEBUGGER) +v8::Handle<v8::Value> V8InjectedScriptHost::currentCallFrameCallback(const v8::Arguments& args) +{ + INC_STATS("InjectedScriptHost.currentCallFrame()"); + return toV8(ScriptDebugServer::shared().currentCallFrame()); +} + +v8::Handle<v8::Value> V8InjectedScriptHost::isActivationCallback(const v8::Arguments& args) +{ + INC_STATS("InjectedScriptHost.isActivation()"); + return v8::Boolean::New(true); +} +#endif + #if ENABLE(DATABASE) v8::Handle<v8::Value> V8InjectedScriptHost::databaseForIdCallback(const v8::Arguments& args) { @@ -226,12 +244,27 @@ InjectedScript InjectedScriptHost::injectedScriptFor(ScriptState* inspectedScrip return InjectedScript(ScriptObject(inspectedScriptState, v8::Local<v8::Object>::Cast(val))); ASSERT(!m_injectedScriptSource.isEmpty()); - ScriptObject injectedScriptObject = createInjectedScript(m_injectedScriptSource, this, inspectedScriptState, m_nextInjectedScriptId); - InjectedScript result(injectedScriptObject); - m_idToInjectedScript.set(m_nextInjectedScriptId, result); - ++m_nextInjectedScriptId; - global->SetHiddenValue(key, injectedScriptObject.v8Object()); + pair<long, ScriptObject> injectedScript = injectScript(m_injectedScriptSource, inspectedScriptState); + InjectedScript result(injectedScript.second); + m_idToInjectedScript.set(injectedScript.first, result); + global->SetHiddenValue(key, injectedScript.second.v8Object()); return result; } +bool InjectedScriptHost::canAccessInspectedWindow(ScriptState* scriptState) +{ + v8::HandleScope handleScope; + v8::Local<v8::Context> context = scriptState->context(); + v8::Local<v8::Object> global = context->Global(); + if (global.IsEmpty()) + return false; + v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), global); + if (holder.IsEmpty()) + return false; + Frame* frame = V8DOMWindow::toNative(holder)->frame(); + + v8::Context::Scope contextScope(context); + return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), frame, false); +} + } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp b/WebCore/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp index b823034..7f4ccf7 100644 --- a/WebCore/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp +++ b/WebCore/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp @@ -35,12 +35,65 @@ #include "InspectorFrontendHost.h" #include "V8Binding.h" +#include "V8MouseEvent.h" #include "V8Proxy.h" namespace WebCore { +v8::Handle<v8::Value> V8InspectorFrontendHost::platformCallback(const v8::Arguments&) +{ +#if defined(OS_MACOSX) + return v8String("mac"); +#elif defined(OS_LINUX) + return v8String("linux"); +#elif defined(OS_WIN) + return v8String("windows"); +#else + return v8String("unknown"); +#endif +} + +v8::Handle<v8::Value> V8InspectorFrontendHost::portCallback(const v8::Arguments&) +{ + return v8::Undefined(); +} + v8::Handle<v8::Value> V8InspectorFrontendHost::showContextMenuCallback(const v8::Arguments& args) { + if (args.Length() < 2) + return v8::Undefined(); + + v8::Local<v8::Object> eventWrapper = v8::Local<v8::Object>::Cast(args[0]); + if (!V8MouseEvent::info.equals(V8DOMWrapper::domWrapperType(eventWrapper))) + return v8::Undefined(); + + Event* event = V8Event::toNative(eventWrapper); + if (!args[1]->IsArray()) + return v8::Undefined(); + + v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(args[1]); + Vector<ContextMenuItem*> items; + + for (size_t i = 0; i < array->Length(); ++i) { + v8::Local<v8::Object> item = v8::Local<v8::Object>::Cast(array->Get(v8::Integer::New(i))); + v8::Local<v8::Value> label = item->Get(v8::String::New("label")); + v8::Local<v8::Value> id = item->Get(v8::String::New("id")); + if (label->IsUndefined() || id->IsUndefined()) { + items.append(new ContextMenuItem(SeparatorType, + ContextMenuItemTagNoAction, + String())); + } else { + ContextMenuAction typedId = static_cast<ContextMenuAction>( + ContextMenuItemBaseCustomTag + id->ToInt32()->Value()); + items.append(new ContextMenuItem(ActionType, + typedId, + toWebCoreStringWithNullCheck(label))); + } + } + + InspectorFrontendHost* frontendHost = V8InspectorFrontendHost::toNative(args.Holder()); + frontendHost->showContextMenu(event, items); + return v8::Undefined(); } diff --git a/WebCore/bindings/v8/custom/V8JavaScriptCallFrameCustom.cpp b/WebCore/bindings/v8/custom/V8JavaScriptCallFrameCustom.cpp new file mode 100644 index 0000000..e2a691d --- /dev/null +++ b/WebCore/bindings/v8/custom/V8JavaScriptCallFrameCustom.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "V8JavaScriptCallFrame.h" + +#if ENABLE(JAVASCRIPT_DEBUGGER) + +#include "V8Binding.h" +#include "V8Proxy.h" + +namespace WebCore { + +v8::Handle<v8::Value> V8JavaScriptCallFrame::evaluateCallback(const v8::Arguments& args) +{ + INC_STATS("V8JavaScriptCallFrame.evaluateCallback()"); + JavaScriptCallFrame* impl = V8JavaScriptCallFrame::toNative(args.Holder()); + String expression = toWebCoreStringWithNullOrUndefinedCheck(args[0]); + return impl->evaluate(expression); +} + +v8::Handle<v8::Value> V8JavaScriptCallFrame::scopeChainAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("V8JavaScriptCallFrame.scopeChainAccessorGetter()"); + JavaScriptCallFrame* impl = V8JavaScriptCallFrame::toNative(info.Holder()); + return impl->scopeChain(); +} + +v8::Handle<v8::Value> V8JavaScriptCallFrame::scopeTypeCallback(const v8::Arguments& args) +{ + INC_STATS("V8JavaScriptCallFrame.scopeTypeCallback()"); + JavaScriptCallFrame* impl = V8JavaScriptCallFrame::toNative(args.Holder()); + int scopeIndex = args[0]->Int32Value(); + return v8::Int32::New(impl->scopeType(scopeIndex)); +} + +v8::Handle<v8::Value> V8JavaScriptCallFrame::thisObjectAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("V8JavaScriptCallFrame.thisObjectAccessorGetter()"); + JavaScriptCallFrame* impl = V8JavaScriptCallFrame::toNative(info.Holder()); + return impl->thisObject(); +} + +v8::Handle<v8::Value> V8JavaScriptCallFrame::typeAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("V8JavaScriptCallFrame.typeAccessorGetter()"); + return v8String("function"); +} + +} // namespace WebCore + +#endif // ENABLE(JAVASCRIPT_DEBUGGER) diff --git a/WebCore/bindings/v8/custom/V8LocationCustom.cpp b/WebCore/bindings/v8/custom/V8LocationCustom.cpp index b5df601..ac305c9 100644 --- a/WebCore/bindings/v8/custom/V8LocationCustom.cpp +++ b/WebCore/bindings/v8/custom/V8LocationCustom.cpp @@ -75,9 +75,14 @@ void V8Location::hashAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Va if (hash.startsWith("#")) hash = hash.substring(1); - if (oldRef == hash || (oldRef.isNull() && hash.isEmpty())) - return; + + // Note that by parsing the URL and *then* comparing fragments, we are + // comparing fragments post-canonicalization, and so this handles the + // cases where fragment identifiers are ignored or invalid. url.setFragmentIdentifier(hash); + String newRef = url.fragmentIdentifier(); + if (oldRef == newRef || (oldRef.isNull() && newRef.isEmpty())) + return; navigateIfAllowed(frame, url, false, false); } @@ -185,7 +190,10 @@ void V8Location::protocolAccessorSetter(v8::Local<v8::String> name, v8::Local<v8 return; KURL url = frame->loader()->url(); - url.setProtocol(protocol); + if (!url.setProtocol(protocol)) { + throwError("Can't set protocol", V8Proxy::SyntaxError); + return; + } navigateIfAllowed(frame, url, false, false); } @@ -342,17 +350,15 @@ v8::Handle<v8::Value> V8Location::toStringCallback(const v8::Arguments& args) return v8String(result); } -bool V8Location::indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value> data) +bool V8Location::indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value>) { - ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::LOCATION); // Only allow same origin access Location* imp = V8Location::toNative(host); return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false); } -bool V8Location::namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value> data) +bool V8Location::namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value>) { - ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::LOCATION); // Only allow same origin access Location* imp = V8Location::toNative(host); return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), false); @@ -366,7 +372,7 @@ v8::Handle<v8::Value> toV8(Location* impl) if (wrapper.IsEmpty()) { wrapper = V8Location::wrap(impl); if (!wrapper.IsEmpty()) - V8DOMWrapper::setHiddenWindowReference(impl->frame(), V8DOMWindow::locationIndex, wrapper); + V8DOMWrapper::setHiddenWindowReference(impl->frame(), wrapper); } return wrapper; } diff --git a/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp b/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp index 4fb82ba..b966e42 100644 --- a/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp @@ -67,11 +67,11 @@ v8::Handle<v8::Value> V8MessageChannel::constructorCallback(const v8::Arguments& // 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(V8MessageChannel::port1Index, toV8(obj->port1())); - messageChannel->SetInternalField(V8MessageChannel::port2Index, toV8(obj->port2())); + V8DOMWrapper::setHiddenReference(messageChannel, toV8(obj->port1())); + V8DOMWrapper::setHiddenReference(messageChannel, toV8(obj->port2())); // Setup the standard wrapper object internal fields. - V8DOMWrapper::setDOMWrapper(messageChannel, V8ClassIndex::MESSAGECHANNEL, obj.get()); + V8DOMWrapper::setDOMWrapper(messageChannel, &info, obj.get()); return toV8(obj.release(), messageChannel); } diff --git a/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp b/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp index d41a785..cca4a24 100644 --- a/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp +++ b/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp @@ -84,6 +84,8 @@ v8::Handle<v8::Value> V8MessageEvent::initMessageEventCallback(const v8::Argumen return v8::Undefined(); } event->initMessageEvent(typeArg, canBubbleArg, cancelableArg, dataArg.release(), originArg, lastEventIdArg, sourceArg, portArray.release()); + v8::PropertyAttribute dataAttr = static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly); + SerializedScriptValue::deserializeAndSetProperty(args.Holder(), "data", dataAttr, event->data()); return v8::Undefined(); } diff --git a/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp b/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp index 9890668..c41ed38 100644 --- a/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp +++ b/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp @@ -42,42 +42,14 @@ namespace WebCore { -v8::Handle<v8::Value> V8MessagePort::addEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.MessagePort.addEventListener()"); - MessagePort* messagePort = V8MessagePort::toNative(args.Holder()); - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(messagePort, args[1], false, ListenerFindOrCreate); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - messagePort->addEventListener(type, listener, useCapture); - - createHiddenDependency(args.Holder(), args[1], cacheIndex); - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8MessagePort::removeEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.MessagePort.removeEventListener()"); - MessagePort* messagePort = V8MessagePort::toNative(args.Holder()); - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(messagePort, args[1], false, ListenerFindOnly); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - messagePort->removeEventListener(type, listener.get(), useCapture); - - removeHiddenDependency(args.Holder(), args[1], cacheIndex); - } - - return v8::Undefined(); -} - v8::Handle<v8::Value> V8MessagePort::postMessageCallback(const v8::Arguments& args) { INC_STATS("DOM.MessagePort.postMessage"); MessagePort* messagePort = V8MessagePort::toNative(args.Holder()); - RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0]); + bool didThrow = false; + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0], didThrow); + if (didThrow) + return v8::Undefined(); MessagePortArray portArray; if (args.Length() > 1) { if (!getMessagePortArray(args[1], portArray)) diff --git a/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp b/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp index 611ab94..4e1dd21 100644 --- a/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NamedNodeMapCustom.cpp @@ -32,7 +32,9 @@ #include "V8NamedNodeMap.h" #include "NamedNodeMap.h" +#include "V8Attr.h" #include "V8Binding.h" +#include "V8BindingState.h" #include "V8Element.h" #include "V8Node.h" #include "V8Proxy.h" @@ -73,6 +75,48 @@ v8::Handle<v8::Value> V8NamedNodeMap::namedPropertyGetter(v8::Local<v8::String> return toV8(result.release()); } +v8::Handle<v8::Value> V8NamedNodeMap::setNamedItemNSCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.NamedNodeMap.setNamedItemNS"); + NamedNodeMap* imp = V8NamedNodeMap::toNative(args.Holder()); + Node* newNode = V8Node::HasInstance(args[0]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; + + if (newNode && newNode->nodeType() == Node::ATTRIBUTE_NODE && imp->element()) { + if (!V8BindingSecurity::allowSettingSrcToJavascriptURL(V8BindingState::Only(), imp->element(), newNode->nodeName(), newNode->nodeValue())) + return v8::Handle<v8::Value>(); + } + + ExceptionCode ec = 0; + RefPtr<Node> result = imp->setNamedItemNS(newNode, ec); + if (UNLIKELY(ec)) { + throwError(ec); + return v8::Handle<v8::Value>(); + } + + return toV8(result.release()); +} + +v8::Handle<v8::Value> V8NamedNodeMap::setNamedItemCallback(const v8::Arguments & args) +{ + INC_STATS("DOM.NamedNodeMap.setNamedItem"); + NamedNodeMap* imp = V8NamedNodeMap::toNative(args.Holder()); + Node* newNode = V8Node::HasInstance(args[0]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; + + if (newNode && newNode->nodeType() == Node::ATTRIBUTE_NODE && imp->element()) { + if (!V8BindingSecurity::allowSettingSrcToJavascriptURL(V8BindingState::Only(), imp->element(), newNode->nodeName(), newNode->nodeValue())) + return v8::Handle<v8::Value>(); + } + + ExceptionCode ec = 0; + RefPtr<Node> result = imp->setNamedItem(newNode, ec); + if (UNLIKELY(ec)) { + throwError(ec); + return v8::Handle<v8::Value>(); + } + + return toV8(result.release()); +} + v8::Handle<v8::Value> toV8(NamedNodeMap* impl) { if (!impl) @@ -80,10 +124,8 @@ v8::Handle<v8::Value> toV8(NamedNodeMap* impl) v8::Handle<v8::Object> wrapper = V8NamedNodeMap::wrap(impl); // Add a hidden reference from named node map to its owner node. Element* element = impl->element(); - if (!wrapper.IsEmpty() && element) { - v8::Handle<v8::Value> owner = toV8(element); - wrapper->SetInternalField(V8NamedNodeMap::ownerNodeIndex, owner); - } + if (!wrapper.IsEmpty() && element) + V8DOMWrapper::setHiddenReference(wrapper, toV8(element)); return wrapper; } diff --git a/WebCore/bindings/v8/custom/V8NodeCustom.cpp b/WebCore/bindings/v8/custom/V8NodeCustom.cpp index 7907283..0a7198a 100644 --- a/WebCore/bindings/v8/custom/V8NodeCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NodeCustom.cpp @@ -37,6 +37,7 @@ #include "V8AbstractEventListener.h" #include "V8Attr.h" #include "V8Binding.h" +#include "V8BindingState.h" #include "V8CDATASection.h" #include "V8Comment.h" #include "V8CustomEventListener.h" @@ -56,38 +57,43 @@ namespace WebCore { -v8::Handle<v8::Value> V8Node::addEventListenerCallback(const v8::Arguments& args) +static inline bool isFrameSrc(Element *element, const String& name) { - INC_STATS("DOM.Node.addEventListener()"); - Node* node = V8Node::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(node, args[1], false, ListenerFindOrCreate); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - node->addEventListener(type, listener, useCapture); - createHiddenDependency(args.Holder(), args[1], cacheIndex); + return element && (element->hasTagName(HTMLNames::iframeTag) || element->hasTagName(HTMLNames::frameTag)) && equalIgnoringCase(name, "src"); +} + +void V8Node::textContentAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + Node* imp = V8Node::toNative(info.Holder()); + String nodeValue = toWebCoreStringWithNullCheck(value); + + if (imp->nodeType() == Node::ATTRIBUTE_NODE) { + Element * ownerElement = V8Attr::toNative(info.Holder())->ownerElement(); + if (ownerElement && !V8BindingSecurity::allowSettingSrcToJavascriptURL(V8BindingState::Only(), ownerElement, imp->nodeName(), nodeValue)) + return; } - return v8::Undefined(); + + ExceptionCode ec = 0; + imp->setTextContent(nodeValue, ec); + if (ec) + throwError(ec); } -v8::Handle<v8::Value> V8Node::removeEventListenerCallback(const v8::Arguments& args) +void V8Node::nodeValueAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { - INC_STATS("DOM.Node.removeEventListener()"); - Node* node = V8Node::toNative(args.Holder()); - - // It is possbile that the owner document of the node is detached - // from the frame. - // See issue http://b/878909 - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(node, args[1], false, ListenerFindOnly); - if (listener) { - AtomicString type = v8ValueToAtomicWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - node->removeEventListener(type, listener.get(), useCapture); - removeHiddenDependency(args.Holder(), args[1], cacheIndex); + Node* imp = V8Node::toNative(info.Holder()); + String nodeValue = toWebCoreStringWithNullCheck(value); + + if (imp->nodeType() == Node::ATTRIBUTE_NODE) { + Element * ownerElement = V8Attr::toNative(info.Holder())->ownerElement(); + if (ownerElement && !V8BindingSecurity::allowSettingSrcToJavascriptURL(V8BindingState::Only(), ownerElement, imp->nodeName(), nodeValue)) + return; } - return v8::Undefined(); + ExceptionCode ec = 0; + imp->setNodeValue(nodeValue, ec); + if (ec) + throwError(ec); } // This function is customized to take advantage of the optional 4th argument: shouldLazyAttach @@ -96,6 +102,12 @@ v8::Handle<v8::Value> V8Node::insertBeforeCallback(const v8::Arguments& args) INC_STATS("DOM.Node.insertBefore"); v8::Handle<v8::Object> holder = args.Holder(); Node* imp = V8Node::toNative(holder); + + if (imp->nodeType() == Node::ATTRIBUTE_NODE && isFrameSrc(V8Attr::toNative(holder)->ownerElement(), imp->nodeName())) { + V8Proxy::setDOMException(NOT_SUPPORTED_ERR); + return v8::Handle<v8::Value>(); + } + ExceptionCode ec = 0; Node* newChild = V8Node::HasInstance(args[0]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; Node* refChild = V8Node::HasInstance(args[1]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[1])) : 0; @@ -115,6 +127,12 @@ v8::Handle<v8::Value> V8Node::replaceChildCallback(const v8::Arguments& args) INC_STATS("DOM.Node.replaceChild"); v8::Handle<v8::Object> holder = args.Holder(); Node* imp = V8Node::toNative(holder); + + if (imp->nodeType() == Node::ATTRIBUTE_NODE && isFrameSrc(V8Attr::toNative(holder)->ownerElement(), imp->nodeName())) { + V8Proxy::setDOMException(NOT_SUPPORTED_ERR); + return v8::Handle<v8::Value>(); + } + ExceptionCode ec = 0; Node* newChild = V8Node::HasInstance(args[0]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; Node* oldChild = V8Node::HasInstance(args[1]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[1])) : 0; @@ -133,6 +151,12 @@ v8::Handle<v8::Value> V8Node::removeChildCallback(const v8::Arguments& args) INC_STATS("DOM.Node.removeChild"); v8::Handle<v8::Object> holder = args.Holder(); Node* imp = V8Node::toNative(holder); + + if (imp->nodeType() == Node::ATTRIBUTE_NODE && isFrameSrc(V8Attr::toNative(holder)->ownerElement(), imp->nodeName())) { + V8Proxy::setDOMException(NOT_SUPPORTED_ERR); + return v8::Handle<v8::Value>(); + } + ExceptionCode ec = 0; Node* oldChild = V8Node::HasInstance(args[0]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; bool success = imp->removeChild(oldChild, ec); @@ -151,6 +175,12 @@ v8::Handle<v8::Value> V8Node::appendChildCallback(const v8::Arguments& args) INC_STATS("DOM.Node.appendChild"); v8::Handle<v8::Object> holder = args.Holder(); Node* imp = V8Node::toNative(holder); + + if (imp->nodeType() == Node::ATTRIBUTE_NODE && isFrameSrc(V8Attr::toNative(holder)->ownerElement(), imp->nodeName())) { + V8Proxy::setDOMException(NOT_SUPPORTED_ERR); + return v8::Handle<v8::Value>(); + } + ExceptionCode ec = 0; Node* newChild = V8Node::HasInstance(args[0]) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; bool success = imp->appendChild(newChild, ec, true ); diff --git a/WebCore/bindings/v8/custom/V8NotificationCenterCustom.cpp b/WebCore/bindings/v8/custom/V8NotificationCenterCustom.cpp index 9c3ab45..30773e3 100644 --- a/WebCore/bindings/v8/custom/V8NotificationCenterCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NotificationCenterCustom.cpp @@ -46,38 +46,6 @@ namespace WebCore { -v8::Handle<v8::Value> V8Notification::addEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.Notification.addEventListener()"); - Notification* notification = V8Notification::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(notification, args[1], false, ListenerFindOrCreate); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - notification->addEventListener(type, listener, useCapture); - createHiddenDependency(args.Holder(), args[1], cacheIndex); - } - - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8Notification::removeEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.Notification.removeEventListener()"); - Notification* notification = V8Notification::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(notification, args[1], false, ListenerFindOnly); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - notification->removeEventListener(type, listener.get(), useCapture); - removeHiddenDependency(args.Holder(), args[1], cacheIndex); - } - - return v8::Undefined(); -} - v8::Handle<v8::Value> V8NotificationCenter::createHTMLNotificationCallback(const v8::Arguments& args) { INC_STATS(L"DOM.NotificationCenter.CreateHTMLNotification()"); diff --git a/WebCore/bindings/v8/custom/V8PopStateEventCustom.cpp b/WebCore/bindings/v8/custom/V8PopStateEventCustom.cpp index 46e9929..cdb160d 100644 --- a/WebCore/bindings/v8/custom/V8PopStateEventCustom.cpp +++ b/WebCore/bindings/v8/custom/V8PopStateEventCustom.cpp @@ -35,6 +35,8 @@ #include "SerializedScriptValue.h" #include "V8Proxy.h" +#include <v8.h> + namespace WebCore { v8::Handle<v8::Value> V8PopStateEvent::initPopStateEventCallback(const v8::Arguments& args) @@ -44,7 +46,11 @@ v8::Handle<v8::Value> V8PopStateEvent::initPopStateEventCallback(const v8::Argum String typeArg = v8ValueToWebCoreString(args[0]); bool canBubbleArg = args[1]->BooleanValue(); bool cancelableArg = args[2]->BooleanValue(); - RefPtr<SerializedScriptValue> stateArg = SerializedScriptValue::create(args[3]); + + bool didThrow = false; + RefPtr<SerializedScriptValue> stateArg = SerializedScriptValue::create(args[3], didThrow); + if (didThrow) + return v8::Undefined(); PopStateEvent* event = V8PopStateEvent::toNative(args.Holder()); event->initPopStateEvent(typeArg, canBubbleArg, cancelableArg, stateArg.release()); diff --git a/WebCore/bindings/v8/custom/V8SVGDocumentCustom.cpp b/WebCore/bindings/v8/custom/V8SVGDocumentCustom.cpp index 558c03b..8dce61b 100644 --- a/WebCore/bindings/v8/custom/V8SVGDocumentCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SVGDocumentCustom.cpp @@ -29,6 +29,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "V8SVGDocument.h" #include "V8IsolatedContext.h" @@ -51,3 +53,5 @@ v8::Handle<v8::Value> toV8(SVGDocument* impl, bool forceNewObject) } } // namespace WebCore + +#endif diff --git a/WebCore/bindings/v8/custom/V8SVGElementCustom.cpp b/WebCore/bindings/v8/custom/V8SVGElementCustom.cpp index 0ce48ce..7ad5f41 100644 --- a/WebCore/bindings/v8/custom/V8SVGElementCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SVGElementCustom.cpp @@ -29,10 +29,10 @@ */ #include "config.h" -#include "V8SVGElement.h" #if ENABLE(SVG) +#include "V8SVGElement.h" #include "V8SVGElementWrapperFactory.h" namespace WebCore { diff --git a/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp b/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp deleted file mode 100644 index 56c37bd..0000000 --- a/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * 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(SVG) -#include "V8SVGElementInstance.h" - -#include "EventListener.h" -#include "SVGElementInstance.h" - -#include "V8Binding.h" -#include "V8CustomEventListener.h" -#include "V8SVGPODTypeWrapper.h" -#include "V8Proxy.h" - -namespace WebCore { - -v8::Handle<v8::Value> V8SVGElementInstance::addEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.SVGElementInstance.AddEventListener()"); - SVGElementInstance* instance = V8SVGElementInstance::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(instance, args[1], false, ListenerFindOrCreate); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - instance->addEventListener(type, listener, useCapture); - createHiddenDependency(args.Holder(), args[1], cacheIndex); - } - - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8SVGElementInstance::removeEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.SVGElementInstance.RemoveEventListener()"); - SVGElementInstance* instance = V8SVGElementInstance::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(instance, args[1], false, ListenerFindOnly); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - instance->removeEventListener(type, listener.get(), useCapture); - removeHiddenDependency(args.Holder(), args[1], cacheIndex); - } - - return v8::Undefined(); -} - -} // namespace WebCore - -#endif diff --git a/WebCore/bindings/v8/custom/V8SVGPathSegCustom.cpp b/WebCore/bindings/v8/custom/V8SVGPathSegCustom.cpp index a96d55e..5544f83 100644 --- a/WebCore/bindings/v8/custom/V8SVGPathSegCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SVGPathSegCustom.cpp @@ -29,6 +29,8 @@ */ #include "config.h" + +#if ENABLE(SVG) #include "V8SVGPathSeg.h" #include "V8DOMWindow.h" @@ -104,3 +106,5 @@ v8::Handle<v8::Value> toV8(SVGPathSeg* impl) } } // namespace WebCore + +#endif diff --git a/WebCore/bindings/v8/custom/V8ScreenCustom.cpp b/WebCore/bindings/v8/custom/V8ScriptProfileCustom.cpp index 98d9dd7..ddaabb0 100644 --- a/WebCore/bindings/v8/custom/V8ScreenCustom.cpp +++ b/WebCore/bindings/v8/custom/V8ScriptProfileCustom.cpp @@ -29,24 +29,33 @@ */ #include "config.h" -#include "V8Screen.h" +#include "V8ScriptProfile.h" -#include "V8DOMWindow.h" -#include "V8DOMWrapper.h" +#include "ScriptProfile.h" +#include "V8Binding.h" +#include "V8Proxy.h" + +#include <v8-profiler.h> namespace WebCore { -v8::Handle<v8::Value> toV8(Screen* impl) +v8::Handle<v8::Value> toV8(ScriptProfile* impl) { if (!impl) return v8::Null(); - v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(impl); - if (wrapper.IsEmpty()) { - wrapper = V8Screen::wrap(impl); - if (!wrapper.IsEmpty()) - V8DOMWrapper::setHiddenWindowReference(impl->frame(), V8DOMWindow::screenIndex, wrapper); + v8::Local<v8::Function> function = V8ScriptProfile::GetTemplate()->GetFunction(); + if (function.IsEmpty()) { + // Return if allocation failed. + return v8::Local<v8::Object>(); + } + v8::Local<v8::Object> instance = SafeAllocation::newInstance(function); + if (instance.IsEmpty()) { + // Avoid setting the wrapper if allocation failed. + return v8::Local<v8::Object>(); } - return wrapper; + impl->ref(); + V8DOMWrapper::setDOMWrapper(instance, &V8ScriptProfile::info, impl); + return instance; } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8ScriptProfileNodeCustom.cpp b/WebCore/bindings/v8/custom/V8ScriptProfileNodeCustom.cpp new file mode 100644 index 0000000..a4deeeb --- /dev/null +++ b/WebCore/bindings/v8/custom/V8ScriptProfileNodeCustom.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "V8ScriptProfileNode.h" + +#include "ScriptProfileNode.h" +#include "V8Binding.h" +#include "V8Proxy.h" + +#include <v8-profiler.h> + +namespace WebCore { + +v8::Handle<v8::Value> V8ScriptProfileNode::childrenAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.ScriptProfileNode.childrenAccessorGetter"); + ScriptProfileNode* imp = V8ScriptProfileNode::toNative(info.Holder()); + const ProfileNodesList& children = imp->children(); + v8::Handle<v8::Array> result = v8::Array::New(children.size()); + int index = 0; + ProfileNodesList::const_iterator end = children.end(); + for (ProfileNodesList::const_iterator iter = children.begin(); iter != end; ++iter) + result->Set(v8::Integer::New(index++), toV8(iter->get())); + return result; +} + +v8::Handle<v8::Value> V8ScriptProfileNode::callUIDAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.ScriptProfileNode.callUIDAccessorGetter"); + ScriptProfileNode* imp = V8ScriptProfileNode::toNative(info.Holder()); + return v8::Number::New(imp->callUID()); +} + +v8::Handle<v8::Value> toV8(ScriptProfileNode* impl) +{ + if (!impl) + return v8::Null(); + v8::Local<v8::Function> function = V8ScriptProfileNode::GetTemplate()->GetFunction(); + if (function.IsEmpty()) { + // Return if allocation failed. + return v8::Local<v8::Object>(); + } + v8::Local<v8::Object> instance = SafeAllocation::newInstance(function); + if (instance.IsEmpty()) { + // Avoid setting the wrapper if allocation failed. + return v8::Local<v8::Object>(); + } + impl->ref(); + V8DOMWrapper::setDOMWrapper(instance, &V8ScriptProfileNode::info, impl); + return instance; +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp b/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp index f69675a..2d72c37 100644 --- a/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp @@ -80,7 +80,7 @@ v8::Handle<v8::Value> V8SharedWorker::constructorCallback(const v8::Arguments& a // Setup the standard wrapper object internal fields. v8::Handle<v8::Object> wrapperObject = args.Holder(); - V8DOMWrapper::setDOMWrapper(wrapperObject, V8ClassIndex::SHAREDWORKER, obj.get()); + V8DOMWrapper::setDOMWrapper(wrapperObject, &info, obj.get()); obj->ref(); V8DOMWrapper::setJSWrapperForActiveDOMObject(obj.get(), v8::Persistent<v8::Object>::New(wrapperObject)); diff --git a/WebCore/bindings/v8/custom/V8StyleSheetCustom.cpp b/WebCore/bindings/v8/custom/V8StyleSheetCustom.cpp index b062cdc..b3f6ff7 100644 --- a/WebCore/bindings/v8/custom/V8StyleSheetCustom.cpp +++ b/WebCore/bindings/v8/custom/V8StyleSheetCustom.cpp @@ -31,6 +31,7 @@ #include "config.h" #include "V8StyleSheet.h" +#include "V8DOMWrapper.h" #include "V8CSSStyleSheet.h" #include "V8Node.h" @@ -45,10 +46,8 @@ v8::Handle<v8::Value> toV8(StyleSheet* impl) v8::Handle<v8::Object> wrapper = V8StyleSheet::wrap(impl); // Add a hidden reference from stylesheet object to its owner node. Node* ownerNode = impl->ownerNode(); - if (ownerNode && !wrapper.IsEmpty()) { - v8::Handle<v8::Object> owner = v8::Handle<v8::Object>::Cast(toV8(ownerNode)); - wrapper->SetInternalField(V8StyleSheet::ownerNodeIndex, owner); - } + if (ownerNode && !wrapper.IsEmpty()) + V8DOMWrapper::setHiddenReference(wrapper, toV8(ownerNode)); return wrapper; } diff --git a/WebCore/bindings/v8/custom/V8WebGLArrayBufferCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLArrayBufferCustom.cpp index 5b54563..d3e6cb5 100644 --- a/WebCore/bindings/v8/custom/V8WebGLArrayBufferCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLArrayBufferCustom.cpp @@ -72,9 +72,13 @@ v8::Handle<v8::Value> V8WebGLArrayBuffer::constructorCallback(const v8::Argument len = toInt32(args[0]); } - RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(len); + RefPtr<WebGLArrayBuffer> buffer = WebGLArrayBuffer::create(len, 1); + if (!buffer.get()) { + V8Proxy::setDOMException(INDEX_SIZE_ERR); + return v8::Undefined(); + } // Transform the holder into a wrapper object for the array. - V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::WEBGLARRAYBUFFER), buffer.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), &info, buffer.get()); return toV8(buffer.release(), args.Holder()); } diff --git a/WebCore/bindings/v8/custom/V8WebGLArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLArrayCustom.cpp index a92e4f2..e15fa11 100644 --- a/WebCore/bindings/v8/custom/V8WebGLArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLArrayCustom.cpp @@ -33,6 +33,8 @@ #if ENABLE(3D_CANVAS) #include "V8WebGLArray.h" +#include "V8Binding.h" +#include "V8Proxy.h" #include "V8WebGLByteArray.h" #include "V8WebGLFloatArray.h" #include "V8WebGLIntArray.h" @@ -64,6 +66,30 @@ v8::Handle<v8::Value> toV8(WebGLArray* impl) return v8::Handle<v8::Value>(); } +v8::Handle<v8::Value> V8WebGLArray::sliceCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.WebGLArray.slice"); + // Forms: + // * slice(long start, long end); + + WebGLArray* imp = V8WebGLArray::toNative(args.Holder()); + int start, end; + switch (args.Length()) { + case 0: + start = 0; + end = imp->length(); + break; + case 1: + start = toInt32(args[0]); + end = imp->length(); + break; + default: + start = toInt32(args[0]); + end = toInt32(args[1]); + } + return toV8(imp->slice(start, end)); +} + } // namespace WebCore #endif // ENABLE(3D_CANVAS) diff --git a/WebCore/bindings/v8/custom/V8WebGLArrayCustom.h b/WebCore/bindings/v8/custom/V8WebGLArrayCustom.h index beea8e6..02bce9c 100644 --- a/WebCore/bindings/v8/custom/V8WebGLArrayCustom.h +++ b/WebCore/bindings/v8/custom/V8WebGLArrayCustom.h @@ -41,9 +41,8 @@ namespace WebCore { // Template function used by the WebGLArray*Constructor callbacks. -template<class ArrayClass> -v8::Handle<v8::Value> constructWebGLArray(const v8::Arguments& args, - int classIndex) +template<class ArrayClass, class ElementType> +v8::Handle<v8::Value> constructWebGLArray(const v8::Arguments& args, WrapperTypeInfo* type, v8::ExternalArrayType arrayType) { if (!args.IsConstructCall()) return throwError("DOM object constructor cannot be called as a function."); @@ -71,96 +70,64 @@ v8::Handle<v8::Value> constructWebGLArray(const v8::Arguments& args, // See whether the first argument is a WebGLArrayBuffer. if (V8WebGLArrayBuffer::HasInstance(args[0])) { - if (argLen > 3) - return throwError("Wrong number of arguments to new WebGL<T>Array(WebGLArrayBuffer, int, int)"); - WebGLArrayBuffer* buf = V8WebGLArrayBuffer::toNative(args[0]->ToObject()); - if (buf == NULL) + if (!buf) return throwError("Could not convert argument 0 to a WebGLArrayBuffer"); bool ok; - int offset = 0; + uint32_t offset = 0; if (argLen > 1) { - offset = toInt32(args[1], ok); + offset = toUInt32(args[1], ok); if (!ok) - return throwError("Could not convert argument 1 to an integer"); + return throwError("Could not convert argument 1 to a number"); } - int length = buf->byteLength() - offset; + uint32_t length = (buf->byteLength() - offset) / sizeof(ElementType); if (argLen > 2) { - length = toInt32(args[2], ok); + length = toUInt32(args[2], ok); if (!ok) - return throwError("Could not convert argument 2 to an integer"); + return throwError("Could not convert argument 2 to a number"); } - if (length < 0) - return throwError("Length / offset out of range"); RefPtr<ArrayClass> array = ArrayClass::create(buf, offset, length); - if (array == NULL) - return throwError("Invalid arguments to new WebGL<T>Array(WebGLArrayBuffer, int, int)"); + if (!array) + return throwError("Out-of-range offset and/or length"); // Transform the holder into a wrapper object for the array. - V8DOMWrapper::setDOMWrapper(args.Holder(), classIndex, array.get()); - V8DOMWrapper::setIndexedPropertiesToExternalArray(args.Holder(), - classIndex, - array.get()->baseAddress(), - array.get()->length()); + V8DOMWrapper::setDOMWrapper(args.Holder(), type, array.get()); + args.Holder()->SetIndexedPropertiesToExternalArrayData(array.get()->baseAddress(), arrayType, array.get()->length()); return toV8(array.release(), args.Holder()); } - int len = 0; + uint32_t len = 0; v8::Handle<v8::Object> srcArray; - if (argLen != 1) - return throwError("Wrong number of arguments to new WebGL<T>Array(int / array)"); if (args[0]->IsInt32()) { - len = toInt32(args[0]); + len = toUInt32(args[0]); } else if (args[0]->IsObject()) { srcArray = args[0]->ToObject(); if (srcArray.IsEmpty()) - return throwError("Could not convert argument 0 to an object"); - len = toInt32(srcArray->Get(v8::String::New("length"))); + return throwError("Could not convert argument 0 to an array"); + len = toUInt32(srcArray->Get(v8::String::New("length"))); } else - return throwError("Could not convert argument 0 to either an int32 or an object"); + return throwError("Could not convert argument 0 to either a number or an array"); RefPtr<ArrayClass> array = ArrayClass::create(len); + if (!array.get()) { + V8Proxy::setDOMException(INDEX_SIZE_ERR); + return v8::Undefined(); + } if (!srcArray.IsEmpty()) { // Need to copy the incoming array into the newly created WebGLArray. - for (int i = 0; i < len; i++) { - v8::Local<v8::Value> val = srcArray->Get(v8::Integer::New(i)); + for (unsigned i = 0; i < len; i++) { + v8::Local<v8::Value> val = srcArray->Get(v8::Integer::NewFromUnsigned(i)); array->set(i, val->NumberValue()); } } // Transform the holder into a wrapper object for the array. - V8DOMWrapper::setDOMWrapper(args.Holder(), classIndex, array.get()); - V8DOMWrapper::setIndexedPropertiesToExternalArray(args.Holder(), - classIndex, - array.get()->baseAddress(), - array.get()->length()); + V8DOMWrapper::setDOMWrapper(args.Holder(), type, array.get()); + args.Holder()->SetIndexedPropertiesToExternalArrayData(array.get()->baseAddress(), arrayType, array.get()->length()); return toV8(array.release(), args.Holder()); } -template <class T, typename ElementType> -v8::Handle<v8::Value> getWebGLArrayElement(const v8::Arguments& args, - V8ClassIndex::V8WrapperType wrapperType) -{ - if (args.Length() != 1) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - bool ok; - uint32_t index = toInt32(args[0], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } - T* array = reinterpret_cast<T*>(args.Holder()->GetPointerFromInternalField(v8DOMWrapperObjectIndex)); - if (index >= array->length()) - return v8::Undefined(); - ElementType result; - if (!array->get(index, result)) - return v8::Undefined(); - return v8::Number::New(result); -} - template <class T> v8::Handle<v8::Value> setWebGLArrayFromArray(T* webGLArray, const v8::Arguments& args) { @@ -169,21 +136,23 @@ v8::Handle<v8::Value> setWebGLArrayFromArray(T* webGLArray, const v8::Arguments& v8::Local<v8::Object> array = args[0]->ToObject(); uint32_t offset = 0; if (args.Length() == 2) - offset = toInt32(args[1]); - uint32_t length = toInt32(array->Get(v8::String::New("length"))); - if (offset + length > webGLArray->length()) + offset = toUInt32(args[1]); + uint32_t length = toUInt32(array->Get(v8::String::New("length"))); + if (offset > webGLArray->length() || + offset + length > webGLArray->length() || + offset + length < offset) + // Out of range offset or overflow V8Proxy::setDOMException(INDEX_SIZE_ERR); else for (uint32_t i = 0; i < length; i++) - webGLArray->set(offset + i, array->Get(v8::Integer::New(i))->NumberValue()); + webGLArray->set(offset + i, array->Get(v8::Integer::NewFromUnsigned(i))->NumberValue()); } return v8::Undefined(); } template <class CPlusPlusArrayType, class JavaScriptWrapperArrayType> -v8::Handle<v8::Value> setWebGLArray(const v8::Arguments& args, - V8ClassIndex::V8WrapperType wrapperType) +v8::Handle<v8::Value> setWebGLArray(const v8::Arguments& args) { if (args.Length() < 1 || args.Length() > 2) { V8Proxy::setDOMException(SYNTAX_ERR); @@ -192,9 +161,10 @@ v8::Handle<v8::Value> setWebGLArray(const v8::Arguments& args, CPlusPlusArrayType* array = JavaScriptWrapperArrayType::toNative(args.Holder()); + // FIXME: change to IsUInt32() when available if (args.Length() == 2 && args[0]->IsInt32()) { // void set(in unsigned long index, in {long|float} value); - uint32_t index = toInt32(args[0]); + uint32_t index = toUInt32(args[0]); array->set(index, args[1]->NumberValue()); return v8::Undefined(); } @@ -204,7 +174,7 @@ v8::Handle<v8::Value> setWebGLArray(const v8::Arguments& args, CPlusPlusArrayType* src = JavaScriptWrapperArrayType::toNative(args[0]->ToObject()); uint32_t offset = 0; if (args.Length() == 2) - offset = toInt32(args[1]); + offset = toUInt32(args[1]); ExceptionCode ec = 0; array->set(src, offset, ec); V8Proxy::setDOMException(ec); diff --git a/WebCore/bindings/v8/custom/V8WebGLByteArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLByteArrayCustom.cpp index dd6163a..8487ace 100644 --- a/WebCore/bindings/v8/custom/V8WebGLByteArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLByteArrayCustom.cpp @@ -47,19 +47,13 @@ v8::Handle<v8::Value> V8WebGLByteArray::constructorCallback(const v8::Arguments& { INC_STATS("DOM.WebGLByteArray.Contructor"); - return constructWebGLArray<WebGLByteArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLBYTEARRAY)); -} - -v8::Handle<v8::Value> V8WebGLByteArray::getCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.WebGLByteArray.get()"); - return getWebGLArrayElement<WebGLByteArray, signed char>(args, V8ClassIndex::WEBGLBYTEARRAY); + return constructWebGLArray<WebGLByteArray, signed char>(args, &info, v8::kExternalByteArray); } v8::Handle<v8::Value> V8WebGLByteArray::setCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLByteArray.set()"); - return setWebGLArray<WebGLByteArray, V8WebGLByteArray>(args, V8ClassIndex::WEBGLBYTEARRAY); + return setWebGLArray<WebGLByteArray, V8WebGLByteArray>(args); } v8::Handle<v8::Value> toV8(WebGLByteArray* impl) diff --git a/WebCore/bindings/v8/custom/V8WebGLFloatArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLFloatArrayCustom.cpp index 3fb8865..77223ea 100644 --- a/WebCore/bindings/v8/custom/V8WebGLFloatArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLFloatArrayCustom.cpp @@ -47,19 +47,13 @@ v8::Handle<v8::Value> V8WebGLFloatArray::constructorCallback(const v8::Arguments { INC_STATS("DOM.WebGLFloatArray.Contructor"); - return constructWebGLArray<WebGLFloatArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLFLOATARRAY)); -} - -v8::Handle<v8::Value> V8WebGLFloatArray::getCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.WebGLFloatArray.get()"); - return getWebGLArrayElement<WebGLFloatArray, float>(args, V8ClassIndex::WEBGLFLOATARRAY); + return constructWebGLArray<WebGLFloatArray, float>(args, &info, v8::kExternalFloatArray); } v8::Handle<v8::Value> V8WebGLFloatArray::setCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLFloatArray.set()"); - return setWebGLArray<WebGLFloatArray, V8WebGLFloatArray>(args, V8ClassIndex::WEBGLFLOATARRAY); + return setWebGLArray<WebGLFloatArray, V8WebGLFloatArray>(args); } v8::Handle<v8::Value> toV8(WebGLFloatArray* impl) diff --git a/WebCore/bindings/v8/custom/V8WebGLIntArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLIntArrayCustom.cpp index 0141a0b..532bdef 100644 --- a/WebCore/bindings/v8/custom/V8WebGLIntArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLIntArrayCustom.cpp @@ -47,19 +47,13 @@ v8::Handle<v8::Value> V8WebGLIntArray::constructorCallback(const v8::Arguments& { INC_STATS("DOM.WebGLIntArray.Contructor"); - return constructWebGLArray<WebGLIntArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLINTARRAY)); -} - -v8::Handle<v8::Value> V8WebGLIntArray::getCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.WebGLIntArray.get()"); - return getWebGLArrayElement<WebGLIntArray, int>(args, V8ClassIndex::WEBGLINTARRAY); + return constructWebGLArray<WebGLIntArray, int>(args, &info, v8::kExternalIntArray); } v8::Handle<v8::Value> V8WebGLIntArray::setCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLIntArray.set()"); - return setWebGLArray<WebGLIntArray, V8WebGLIntArray>(args, V8ClassIndex::WEBGLINTARRAY); + return setWebGLArray<WebGLIntArray, V8WebGLIntArray>(args); } v8::Handle<v8::Value> toV8(WebGLIntArray* impl) diff --git a/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp index 78de5e6..1b8936d 100644 --- a/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp @@ -2,7 +2,7 @@ * 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 areV8ClassIndex::WEBGL + * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright @@ -429,10 +429,6 @@ v8::Handle<v8::Value> V8WebGLRenderingContext::getUniformCallback(const v8::Argu bool ok = false; WebGLUniformLocation* location = toWebGLUniformLocation(args[1], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } WebGLGetInfo info = context->getUniform(program, location, ec); if (ec) { V8Proxy::setDOMException(ec); @@ -786,10 +782,6 @@ static v8::Handle<v8::Value> vertexAttribAndUniformHelperf(const v8::Arguments& WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } if (V8WebGLFloatArray::HasInstance(args[1])) { WebGLFloatArray* array = V8WebGLFloatArray::toNative(args[1]->ToObject()); ASSERT(array != NULL); @@ -862,10 +854,6 @@ static v8::Handle<v8::Value> uniformHelperi(const v8::Arguments& args, bool ok = false; WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } if (V8WebGLIntArray::HasInstance(args[1])) { WebGLIntArray* array = V8WebGLIntArray::toNative(args[1]->ToObject()); ASSERT(array != NULL); @@ -979,10 +967,6 @@ static v8::Handle<v8::Value> uniformMatrixHelper(const v8::Arguments& args, bool ok = false; WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok); - if (!ok) { - V8Proxy::setDOMException(SYNTAX_ERR); - return notHandledByInterceptor(); - } bool transpose = args[1]->BooleanValue(); if (V8WebGLFloatArray::HasInstance(args[2])) { WebGLFloatArray* array = V8WebGLFloatArray::toNative(args[2]->ToObject()); diff --git a/WebCore/bindings/v8/custom/V8WebGLShortArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLShortArrayCustom.cpp index 5a2408e..328f227 100644 --- a/WebCore/bindings/v8/custom/V8WebGLShortArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLShortArrayCustom.cpp @@ -47,19 +47,13 @@ v8::Handle<v8::Value> V8WebGLShortArray::constructorCallback(const v8::Arguments { INC_STATS("DOM.WebGLShortArray.Contructor"); - return constructWebGLArray<WebGLShortArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLSHORTARRAY)); -} - -v8::Handle<v8::Value> V8WebGLShortArray::getCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.WebGLShortArray.get()"); - return getWebGLArrayElement<WebGLShortArray, short>(args, V8ClassIndex::WEBGLSHORTARRAY); + return constructWebGLArray<WebGLShortArray, short>(args, &info, v8::kExternalShortArray); } v8::Handle<v8::Value> V8WebGLShortArray::setCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLShortArray.set()"); - return setWebGLArray<WebGLShortArray, V8WebGLShortArray>(args, V8ClassIndex::WEBGLSHORTARRAY); + return setWebGLArray<WebGLShortArray, V8WebGLShortArray>(args); } v8::Handle<v8::Value> toV8(WebGLShortArray* impl) diff --git a/WebCore/bindings/v8/custom/V8WebGLUnsignedByteArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLUnsignedByteArrayCustom.cpp index 5a30ace..5185298 100644 --- a/WebCore/bindings/v8/custom/V8WebGLUnsignedByteArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLUnsignedByteArrayCustom.cpp @@ -47,19 +47,13 @@ v8::Handle<v8::Value> V8WebGLUnsignedByteArray::constructorCallback(const v8::Ar { INC_STATS("DOM.WebGLUnsignedByteArray.Contructor"); - return constructWebGLArray<WebGLUnsignedByteArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY)); -} - -v8::Handle<v8::Value> V8WebGLUnsignedByteArray::getCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.WebGLUnsignedByteArray.get()"); - return getWebGLArrayElement<WebGLUnsignedByteArray, unsigned char>(args, V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY); + return constructWebGLArray<WebGLUnsignedByteArray, unsigned char>(args, &info, v8::kExternalUnsignedByteArray); } v8::Handle<v8::Value> V8WebGLUnsignedByteArray::setCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLUnsignedByteArray.set()"); - return setWebGLArray<WebGLUnsignedByteArray, V8WebGLUnsignedByteArray>(args, V8ClassIndex::WEBGLUNSIGNEDBYTEARRAY); + return setWebGLArray<WebGLUnsignedByteArray, V8WebGLUnsignedByteArray>(args); } v8::Handle<v8::Value> toV8(WebGLUnsignedByteArray* impl) diff --git a/WebCore/bindings/v8/custom/V8WebGLUnsignedIntArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLUnsignedIntArrayCustom.cpp index cefc60e..14aa1bb 100644 --- a/WebCore/bindings/v8/custom/V8WebGLUnsignedIntArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLUnsignedIntArrayCustom.cpp @@ -47,19 +47,13 @@ v8::Handle<v8::Value> V8WebGLUnsignedIntArray::constructorCallback(const v8::Arg { INC_STATS("DOM.WebGLUnsignedIntArray.Contructor"); - return constructWebGLArray<WebGLUnsignedIntArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLUNSIGNEDINTARRAY)); -} - -v8::Handle<v8::Value> V8WebGLUnsignedIntArray::getCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.WebGLUnsignedIntArray.get()"); - return getWebGLArrayElement<WebGLUnsignedIntArray, unsigned int>(args, V8ClassIndex::WEBGLUNSIGNEDINTARRAY); + return constructWebGLArray<WebGLUnsignedIntArray, unsigned int>(args, &info, v8::kExternalUnsignedIntArray); } v8::Handle<v8::Value> V8WebGLUnsignedIntArray::setCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLUnsignedIntArray.set()"); - return setWebGLArray<WebGLUnsignedIntArray, V8WebGLUnsignedIntArray>(args, V8ClassIndex::WEBGLUNSIGNEDINTARRAY); + return setWebGLArray<WebGLUnsignedIntArray, V8WebGLUnsignedIntArray>(args); } v8::Handle<v8::Value> toV8(WebGLUnsignedIntArray* impl) diff --git a/WebCore/bindings/v8/custom/V8WebGLUnsignedShortArrayCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLUnsignedShortArrayCustom.cpp index 56e34b8..e9ebb4f 100644 --- a/WebCore/bindings/v8/custom/V8WebGLUnsignedShortArrayCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLUnsignedShortArrayCustom.cpp @@ -47,19 +47,13 @@ v8::Handle<v8::Value> V8WebGLUnsignedShortArray::constructorCallback(const v8::A { INC_STATS("DOM.WebGLUnsignedShortArray.Contructor"); - return constructWebGLArray<WebGLUnsignedShortArray>(args, V8ClassIndex::ToInt(V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY)); -} - -v8::Handle<v8::Value> V8WebGLUnsignedShortArray::getCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.WebGLUnsignedShortArray.get()"); - return getWebGLArrayElement<WebGLUnsignedShortArray, unsigned short>(args, V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY); + return constructWebGLArray<WebGLUnsignedShortArray, unsigned short>(args, &info, v8::kExternalUnsignedShortArray); } v8::Handle<v8::Value> V8WebGLUnsignedShortArray::setCallback(const v8::Arguments& args) { INC_STATS("DOM.WebGLUnsignedShortArray.set()"); - return setWebGLArray<WebGLUnsignedShortArray, V8WebGLUnsignedShortArray>(args, V8ClassIndex::WEBGLUNSIGNEDSHORTARRAY); + return setWebGLArray<WebGLUnsignedShortArray, V8WebGLUnsignedShortArray>(args); } v8::Handle<v8::Value> toV8(WebGLUnsignedShortArray* impl) diff --git a/WebCore/bindings/v8/custom/V8WebKitCSSMatrixConstructor.cpp b/WebCore/bindings/v8/custom/V8WebKitCSSMatrixConstructor.cpp index 55518d2..b97d0e8 100644 --- a/WebCore/bindings/v8/custom/V8WebKitCSSMatrixConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8WebKitCSSMatrixConstructor.cpp @@ -63,7 +63,7 @@ v8::Handle<v8::Value> V8WebKitCSSMatrix::constructorCallback(const v8::Arguments throwError(ec); // Transform the holder into a wrapper object for the matrix. - V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::WEBKITCSSMATRIX), matrix.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), &info, 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 1959454..cb29f82 100755 --- a/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp @@ -33,8 +33,8 @@ #include "V8Binding.h" #include "V8DOMWrapper.h" -#include "V8Index.h" #include "V8Proxy.h" +#include "WrapperTypeInfo.h" #include <wtf/MathExtras.h> @@ -63,7 +63,7 @@ v8::Handle<v8::Value> V8WebKitPoint::constructorCallback(const v8::Arguments& ar } PassRefPtr<WebKitPoint> point = WebKitPoint::create(x, y); point->ref(); - V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::WEBKITPOINT, point.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), &info, point.get()); return args.Holder(); } diff --git a/WebCore/bindings/v8/custom/V8WebSocketCustom.cpp b/WebCore/bindings/v8/custom/V8WebSocketCustom.cpp index 2451b90..b931053 100644 --- a/WebCore/bindings/v8/custom/V8WebSocketCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebSocketCustom.cpp @@ -45,37 +45,6 @@ namespace WebCore { -v8::Handle<v8::Value> V8WebSocket::addEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.WebSocket.addEventListener()"); - WebSocket* webSocket = V8WebSocket::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(webSocket, args[1], false, ListenerFindOrCreate); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - webSocket->addEventListener(type, listener, useCapture); - - createHiddenDependency(args.Holder(), args[1], cacheIndex); - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8WebSocket::removeEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.WebSocket.removeEventListener()"); - WebSocket* webSocket = V8WebSocket::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(webSocket, args[1], false, ListenerFindOnly); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - webSocket->removeEventListener(type, listener.get(), useCapture); - removeHiddenDependency(args.Holder(), args[1], cacheIndex); - } - return v8::Undefined(); -} - v8::Handle<v8::Value> V8WebSocket::constructorCallback(const v8::Arguments& args) { INC_STATS("DOM.WebSocket.Constructor"); @@ -115,7 +84,7 @@ v8::Handle<v8::Value> V8WebSocket::constructorCallback(const v8::Arguments& args return throwError(ec); // Setup the standard wrapper object internal fields. - V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::WEBSOCKET), webSocket.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), &info, webSocket.get()); // Add object to the wrapper map. webSocket->ref(); diff --git a/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp b/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp index 7677e27..46bd966 100755 --- a/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp @@ -58,7 +58,11 @@ v8::Handle<v8::Value> SetTimeoutOrInterval(const v8::Arguments& args, bool singl int32_t timeout = argumentCount >= 2 ? args[1]->Int32Value() : 0; int timerId; - v8::Handle<v8::Context> v8Context = workerContext->script()->proxy()->context(); + WorkerContextExecutionProxy* proxy = workerContext->script()->proxy(); + if (!proxy) + return v8::Undefined(); + + v8::Handle<v8::Context> v8Context = proxy->context(); if (function->IsString()) { WebCore::String stringFunction = toWebCoreString(function); timerId = DOMTimer::install(workerContext, new ScheduledAction(v8Context, stringFunction, workerContext->url()), timeout, singleShot); @@ -86,14 +90,6 @@ v8::Handle<v8::Value> V8WorkerContext::importScriptsCallback(const v8::Arguments if (!args.Length()) return v8::Undefined(); - String callerURL; - if (!V8Proxy::sourceName(callerURL)) - return v8::Undefined(); - int callerLine; - if (!V8Proxy::sourceLineNumber(callerLine)) - return v8::Undefined(); - callerLine += 1; - Vector<String> urls; for (int i = 0; i < args.Length(); i++) { v8::TryCatch tryCatch; @@ -106,7 +102,7 @@ v8::Handle<v8::Value> V8WorkerContext::importScriptsCallback(const v8::Arguments WorkerContext* workerContext = V8WorkerContext::toNative(args.Holder()); ExceptionCode ec = 0; - workerContext->importScripts(urls, callerURL, callerLine, ec); + workerContext->importScripts(urls, ec); if (ec) return throwError(ec); @@ -126,44 +122,16 @@ v8::Handle<v8::Value> V8WorkerContext::setIntervalCallback(const v8::Arguments& return SetTimeoutOrInterval(args, false); } -v8::Handle<v8::Value> V8WorkerContext::addEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS(L"DOM.WorkerContext.addEventListener()"); - WorkerContext* workerContext = V8WorkerContext::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(workerContext, args[1], false, ListenerFindOrCreate); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - workerContext->addEventListener(type, listener, useCapture); - - createHiddenDependency(args.Holder(), args[1], cacheIndex); - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8WorkerContext::removeEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS(L"DOM.WorkerContext.removeEventListener()"); - WorkerContext* workerContext = V8WorkerContext::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(workerContext, args[1], false, ListenerFindOnly); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - workerContext->removeEventListener(type, listener.get(), useCapture); - - removeHiddenDependency(args.Holder(), args[1], cacheIndex); - } - return v8::Undefined(); -} - v8::Handle<v8::Value> toV8(WorkerContext* impl) { if (!impl) return v8::Null(); - v8::Handle<v8::Object> global = impl->script()->proxy()->context()->Global(); + WorkerContextExecutionProxy* proxy = impl->script()->proxy(); + if (!proxy) + return v8::Null(); + + v8::Handle<v8::Object> global = proxy->context()->Global(); ASSERT(!global.IsEmpty()); return global; } diff --git a/WebCore/bindings/v8/custom/V8WorkerCustom.cpp b/WebCore/bindings/v8/custom/V8WorkerCustom.cpp index 6b41246..fdc6815 100755 --- a/WebCore/bindings/v8/custom/V8WorkerCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WorkerCustom.cpp @@ -79,7 +79,7 @@ v8::Handle<v8::Value> V8Worker::constructorCallback(const v8::Arguments& args) // Setup the standard wrapper object internal fields. v8::Handle<v8::Object> wrapperObject = args.Holder(); - V8DOMWrapper::setDOMWrapper(wrapperObject, V8ClassIndex::WORKER, obj.get()); + V8DOMWrapper::setDOMWrapper(wrapperObject, &info, obj.get()); obj->ref(); V8DOMWrapper::setJSWrapperForActiveDOMObject(obj.get(), v8::Persistent<v8::Object>::New(wrapperObject)); @@ -91,7 +91,10 @@ v8::Handle<v8::Value> V8Worker::postMessageCallback(const v8::Arguments& args) { INC_STATS("DOM.Worker.postMessage"); Worker* worker = V8Worker::toNative(args.Holder()); - RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0]); + bool didThrow = false; + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0], didThrow); + if (didThrow) + return v8::Undefined(); MessagePortArray portArray; if (args.Length() > 1) { if (!getMessagePortArray(args[1], portArray)) diff --git a/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp b/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp index f50248b..6b5b64f 100644 --- a/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp +++ b/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp @@ -53,7 +53,7 @@ v8::Handle<v8::Value> V8XMLHttpRequest::constructorCallback(const v8::Arguments& if (!context) return throwError("XMLHttpRequest constructor's associated context is not available", V8Proxy::ReferenceError); RefPtr<XMLHttpRequest> xmlHttpRequest = XMLHttpRequest::create(context); - V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::XMLHTTPREQUEST), xmlHttpRequest.get()); + V8DOMWrapper::setDOMWrapper(args.Holder(), &info, xmlHttpRequest.get()); // Add object to the wrapper map. xmlHttpRequest->ref(); diff --git a/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp b/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp index d10c418..4e9c715 100644 --- a/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp +++ b/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009 Google Inc. All rights reserved. + * Copyright (C) 2008, 2009, 2010 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -34,6 +34,7 @@ #include "Frame.h" #include "V8Binding.h" #include "V8Blob.h" +#include "V8DOMFormData.h" #include "V8Document.h" #include "V8HTMLDocument.h" #include "V8Proxy.h" @@ -51,39 +52,6 @@ v8::Handle<v8::Value> V8XMLHttpRequest::responseTextAccessorGetter(v8::Local<v8: return xmlHttpRequest->responseText().v8StringOrNull(); } -v8::Handle<v8::Value> V8XMLHttpRequest::addEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.XMLHttpRequest.addEventListener()"); - XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(xmlHttpRequest, args[1], false, ListenerFindOrCreate); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - xmlHttpRequest->addEventListener(type, listener, useCapture); - - createHiddenDependency(args.Holder(), args[1], cacheIndex); - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8XMLHttpRequest::removeEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.XMLHttpRequest.removeEventListener()"); - XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toNative(args.Holder()); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(xmlHttpRequest, args[1], false, ListenerFindOnly); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - xmlHttpRequest->removeEventListener(type, listener.get(), useCapture); - - removeHiddenDependency(args.Holder(), args[1], cacheIndex); - } - - return v8::Undefined(); -} - v8::Handle<v8::Value> V8XMLHttpRequest::openCallback(const v8::Arguments& args) { INC_STATS("DOM.XMLHttpRequest.open()"); @@ -106,20 +74,23 @@ v8::Handle<v8::Value> V8XMLHttpRequest::openCallback(const v8::Arguments& args) KURL url = context->completeURL(urlstring); - bool async = (args.Length() < 3) ? true : args[2]->BooleanValue(); - ExceptionCode ec = 0; - String user, passwd; - if (args.Length() >= 4 && !args[3]->IsUndefined()) { - user = toWebCoreStringWithNullCheck(args[3]); - if (args.Length() >= 5 && !args[4]->IsUndefined()) { - passwd = toWebCoreStringWithNullCheck(args[4]); - xmlHttpRequest->open(method, url, async, user, passwd, ec); + if (args.Length() >= 3) { + bool async = args[2]->BooleanValue(); + + if (args.Length() >= 4 && !args[3]->IsUndefined()) { + String user = toWebCoreStringWithNullCheck(args[3]); + + if (args.Length() >= 5 && !args[4]->IsUndefined()) { + String passwd = toWebCoreStringWithNullCheck(args[4]); + xmlHttpRequest->open(method, url, async, user, passwd, ec); + } else + xmlHttpRequest->open(method, url, async, user, ec); } else - xmlHttpRequest->open(method, url, async, user, ec); + xmlHttpRequest->open(method, url, async, ec); } else - xmlHttpRequest->open(method, url, async, ec); + xmlHttpRequest->open(method, url, ec); if (ec) return throwError(ec); @@ -127,7 +98,7 @@ v8::Handle<v8::Value> V8XMLHttpRequest::openCallback(const v8::Arguments& args) return v8::Undefined(); } -static bool IsDocumentType(v8::Handle<v8::Value> value) +static bool isDocumentType(v8::Handle<v8::Value> value) { // FIXME: add other document types. return V8Document::HasInstance(value) || V8HTMLDocument::HasInstance(value); @@ -143,7 +114,9 @@ v8::Handle<v8::Value> V8XMLHttpRequest::sendCallback(const v8::Arguments& args) xmlHttpRequest->send(ec); else { v8::Handle<v8::Value> arg = args[0]; - if (IsDocumentType(arg)) { + if (isUndefinedOrNull(arg)) + xmlHttpRequest->send(ec); + else if (isDocumentType(arg)) { v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); Document* document = V8Document::toNative(object); ASSERT(document); @@ -153,6 +126,11 @@ v8::Handle<v8::Value> V8XMLHttpRequest::sendCallback(const v8::Arguments& args) Blob* blob = V8Blob::toNative(object); ASSERT(blob); xmlHttpRequest->send(blob, ec); + } else if (V8DOMFormData::HasInstance(arg)) { + v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); + DOMFormData* domFormData = V8DOMFormData::toNative(object); + ASSERT(domFormData); + xmlHttpRequest->send(domFormData, ec); } else xmlHttpRequest->send(toWebCoreStringWithNullCheck(arg), ec); } @@ -206,10 +184,4 @@ v8::Handle<v8::Value> V8XMLHttpRequest::overrideMimeTypeCallback(const v8::Argum return v8::Undefined(); } -v8::Handle<v8::Value> V8XMLHttpRequest::dispatchEventCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.XMLHttpRequest.dispatchEvent()"); - return v8::Undefined(); -} - } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp b/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp deleted file mode 100644 index c6c31bf..0000000 --- a/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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 "V8XMLHttpRequestUpload.h" - -#include "ExceptionCode.h" -#include "V8Binding.h" -#include "V8Proxy.h" -#include "V8Utilities.h" -#include "XMLHttpRequest.h" -#include "XMLHttpRequestUpload.h" - -#include <wtf/Assertions.h> - -namespace WebCore { - -v8::Handle<v8::Value> V8XMLHttpRequestUpload::addEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.XMLHttpRequestUpload.addEventListener()"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8XMLHttpRequestUpload::toNative(args.Holder()); - - XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest(); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(xmlHttpRequest, args[1], false, ListenerFindOrCreate); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - xmlHttpRequestUpload->addEventListener(type, listener, useCapture); - - createHiddenDependency(args.Holder(), args[1], cacheIndex); - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8XMLHttpRequestUpload::removeEventListenerCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.XMLHttpRequestUpload.removeEventListener()"); - XMLHttpRequestUpload* xmlHttpRequestUpload = V8XMLHttpRequestUpload::toNative(args.Holder()); - - XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest(); - - RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(xmlHttpRequest, args[1], false, ListenerFindOnly); - if (listener) { - String type = toWebCoreString(args[0]); - bool useCapture = args[2]->BooleanValue(); - xmlHttpRequestUpload->removeEventListener(type, listener.get(), useCapture); - - removeHiddenDependency(args.Holder(), args[1], cacheIndex); - } - - return v8::Undefined(); -} - -v8::Handle<v8::Value> V8XMLHttpRequestUpload::dispatchEventCallback(const v8::Arguments& args) -{ - INC_STATS("DOM.XMLHttpRequestUpload.dispatchEvent()"); - return throwError(NOT_SUPPORTED_ERR); -} - -} // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8XSLTProcessorCustom.cpp b/WebCore/bindings/v8/custom/V8XSLTProcessorCustom.cpp index 89f804c..b624fcf 100644 --- a/WebCore/bindings/v8/custom/V8XSLTProcessorCustom.cpp +++ b/WebCore/bindings/v8/custom/V8XSLTProcessorCustom.cpp @@ -49,7 +49,7 @@ namespace WebCore { v8::Handle<v8::Value> V8XSLTProcessor::constructorCallback(const v8::Arguments& args) { INC_STATS("DOM.XSLTProcessor.Constructor"); - return V8Proxy::constructDOMObject<V8ClassIndex::XSLTPROCESSOR, XSLTProcessor>(args); + return V8Proxy::constructDOMObject<XSLTProcessor>(args, &info); } diff --git a/WebCore/bindings/v8/test/TestObj.idl b/WebCore/bindings/v8/test/TestObj.idl new file mode 100644 index 0000000..662ac64 --- /dev/null +++ b/WebCore/bindings/v8/test/TestObj.idl @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary formstrArg, 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIEstrArg, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS 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 IDL file is for testing the V8 generator and for tracking changes +// in its ouput. +module test { + interface TestObj { + // Attributes + readonly attribute long readOnlyIntAttr; + readonly attribute DOMString readOnlyStringAttr; + readonly attribute TestObj readOnlyTestObjAttr; + attribute long intAttr; + attribute DOMString stringAttr; + attribute TestObj testObjAttr; + + // Methods + void voidMethod(); + void voidMethodWithArgs(in long intArg, in DOMString strArg, in TestObj objArg); + long intMethod(); + long intMethodWithArgs(in long intArg, in DOMString strArg, in TestObj objArg); + TestObj objMethod(); + TestObj objMethodWithArgs(in long intArg, in DOMString strArg, in TestObj objArg); + + // Exceptions + void methodWithException() raises(DOMException); + attribute long attrWithException raises(DOMException); + attribute long attrWithSetterException getraises(DOMException); + attribute long attrWithGetterException setraises(DOMException); + + // 'Custom' extended attribute + attribute [Custom] long customAttr; + [Custom] void customMethod(); + [Custom] void customMethodWithArgs(in long intArg, in DOMString strArg, in TestObj objArg); + + // 'Optional' extended attribute + void methodWithOptionalArg(in [Optional] long opt); + void methodWithNonOptionalArgAndOptionalArg(in long nonOpt, in [Optional] long opt); + void methodWithNonOptionalArgAndTwoOptionalArgs(in long nonOpt, in [Optional] long opt1, in long opt2); + + // Overloads + void overloadedMethod(in TestObj objArg, in DOMString strArg); + void overloadedMethod(in TestObj objArg, in [Optional] long intArg); + void overloadedMethod(in DOMString strArg); + void overloadedMethod(in long intArg); + }; +} diff --git a/WebCore/bindings/v8/test/V8TestObj.cpp b/WebCore/bindings/v8/test/V8TestObj.cpp new file mode 100644 index 0000000..d51884e --- /dev/null +++ b/WebCore/bindings/v8/test/V8TestObj.cpp @@ -0,0 +1,459 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "config.h" +#include "V8TestObj.h" + +#include "ExceptionCode.h" +#include "RuntimeEnabledFeatures.h" +#include "V8Binding.h" +#include "V8BindingState.h" +#include "V8DOMWrapper.h" +#include "V8IsolatedContext.h" +#include "V8Proxy.h" +#include <wtf/GetPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +WrapperTypeInfo V8TestObj::info = { V8TestObj::GetTemplate, V8TestObj::derefObject, 0 }; + +namespace TestObjInternal { + +template <typename T> void V8_USE(T) { } + +static v8::Handle<v8::Value> readOnlyIntAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.readOnlyIntAttr._get"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + return v8::Integer::New(imp->readOnlyIntAttr()); +} + +static v8::Handle<v8::Value> readOnlyStringAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.readOnlyStringAttr._get"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + return v8String(imp->readOnlyStringAttr()); +} + +static v8::Handle<v8::Value> readOnlyTestObjAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.readOnlyTestObjAttr._get"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + RefPtr<TestObj> result = imp->readOnlyTestObjAttr(); + v8::Handle<v8::Value> wrapper = result.get() ? getDOMObjectMap().get(result.get()) : v8::Handle<v8::Value>(); + if (wrapper.IsEmpty()) { + wrapper = toV8(result.get()); + if (!wrapper.IsEmpty()) + V8DOMWrapper::setHiddenReference(info.Holder(), wrapper); + } + return wrapper; +} + +static v8::Handle<v8::Value> intAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.intAttr._get"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + return v8::Integer::New(imp->intAttr()); +} + +static void intAttrAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.intAttr._set"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + int v = toInt32(value); + imp->setIntAttr(v); + return; +} + +static v8::Handle<v8::Value> stringAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.stringAttr._get"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + return v8String(imp->stringAttr()); +} + +static void stringAttrAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.stringAttr._set"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + V8Parameter<> v = value; + imp->setStringAttr(v); + return; +} + +static v8::Handle<v8::Value> testObjAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.testObjAttr._get"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + return toV8(imp->testObjAttr()); +} + +static void testObjAttrAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.testObjAttr._set"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + TestObj* v = V8TestObj::HasInstance(value) ? V8TestObj::toNative(v8::Handle<v8::Object>::Cast(value)) : 0; + imp->setTestObjAttr(WTF::getPtr(v)); + return; +} + +static v8::Handle<v8::Value> attrWithExceptionAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.attrWithException._get"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + return v8::Integer::New(imp->attrWithException()); +} + +static void attrWithExceptionAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.attrWithException._set"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + int v = toInt32(value); + imp->setAttrWithException(v); + return; +} + +static v8::Handle<v8::Value> attrWithSetterExceptionAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.attrWithSetterException._get"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + return v8::Integer::New(imp->attrWithSetterException()); +} + +static void attrWithSetterExceptionAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.attrWithSetterException._set"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + int v = toInt32(value); + imp->setAttrWithSetterException(v); + return; +} + +static v8::Handle<v8::Value> attrWithGetterExceptionAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.attrWithGetterException._get"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + return v8::Integer::New(imp->attrWithGetterException()); +} + +static void attrWithGetterExceptionAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.TestObj.attrWithGetterException._set"); + TestObj* imp = V8TestObj::toNative(info.Holder()); + int v = toInt32(value); + imp->setAttrWithGetterException(v); + return; +} + +static v8::Handle<v8::Value> voidMethodCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.voidMethod"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + imp->voidMethod(); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> voidMethodWithArgsCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.voidMethodWithArgs"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + int intArg = toInt32(args[0]); + V8Parameter<> strArg = args[1]; + TestObj* objArg = V8TestObj::HasInstance(args[2]) ? V8TestObj::toNative(v8::Handle<v8::Object>::Cast(args[2])) : 0; + imp->voidMethodWithArgs(intArg, strArg, objArg); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> intMethodCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.intMethod"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + return v8::Integer::New(imp->intMethod()); +} + +static v8::Handle<v8::Value> intMethodWithArgsCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.intMethodWithArgs"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + int intArg = toInt32(args[0]); + V8Parameter<> strArg = args[1]; + TestObj* objArg = V8TestObj::HasInstance(args[2]) ? V8TestObj::toNative(v8::Handle<v8::Object>::Cast(args[2])) : 0; + return v8::Integer::New(imp->intMethodWithArgs(intArg, strArg, objArg)); +} + +static v8::Handle<v8::Value> objMethodCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.objMethod"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + return toV8(imp->objMethod()); +} + +static v8::Handle<v8::Value> objMethodWithArgsCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.objMethodWithArgs"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + int intArg = toInt32(args[0]); + V8Parameter<> strArg = args[1]; + TestObj* objArg = V8TestObj::HasInstance(args[2]) ? V8TestObj::toNative(v8::Handle<v8::Object>::Cast(args[2])) : 0; + return toV8(imp->objMethodWithArgs(intArg, strArg, objArg)); +} + +static v8::Handle<v8::Value> methodWithExceptionCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.methodWithException"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + ExceptionCode ec = 0; + { + imp->methodWithException(ec); + if (UNLIKELY(ec)) + goto fail; + return v8::Handle<v8::Value>(); + } + fail: + V8Proxy::setDOMException(ec); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> methodWithOptionalArgCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.methodWithOptionalArg"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + if (args.Length() <= 0) { + imp->methodWithOptionalArg(); + return v8::Handle<v8::Value>(); + } + int opt = toInt32(args[0]); + imp->methodWithOptionalArg(opt); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> methodWithNonOptionalArgAndOptionalArgCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.methodWithNonOptionalArgAndOptionalArg"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + int nonOpt = toInt32(args[0]); + if (args.Length() <= 1) { + imp->methodWithNonOptionalArgAndOptionalArg(nonOpt); + return v8::Handle<v8::Value>(); + } + int opt = toInt32(args[1]); + imp->methodWithNonOptionalArgAndOptionalArg(nonOpt, opt); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> methodWithNonOptionalArgAndTwoOptionalArgsCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.methodWithNonOptionalArgAndTwoOptionalArgs"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + int nonOpt = toInt32(args[0]); + if (args.Length() <= 1) { + imp->methodWithNonOptionalArgAndTwoOptionalArgs(nonOpt); + return v8::Handle<v8::Value>(); + } + int opt1 = toInt32(args[1]); + int opt2 = toInt32(args[2]); + imp->methodWithNonOptionalArgAndTwoOptionalArgs(nonOpt, opt1, opt2); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> overloadedMethod1Callback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.overloadedMethod1"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + TestObj* objArg = V8TestObj::HasInstance(args[0]) ? V8TestObj::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; + V8Parameter<> strArg = args[1]; + imp->overloadedMethod(objArg, strArg); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> overloadedMethod2Callback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.overloadedMethod2"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + TestObj* objArg = V8TestObj::HasInstance(args[0]) ? V8TestObj::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; + if (args.Length() <= 1) { + imp->overloadedMethod(objArg); + return v8::Handle<v8::Value>(); + } + int intArg = toInt32(args[1]); + imp->overloadedMethod(objArg, intArg); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> overloadedMethod3Callback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.overloadedMethod3"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + V8Parameter<> strArg = args[0]; + imp->overloadedMethod(strArg); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> overloadedMethod4Callback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.overloadedMethod4"); + TestObj* imp = V8TestObj::toNative(args.Holder()); + int intArg = toInt32(args[0]); + imp->overloadedMethod(intArg); + return v8::Handle<v8::Value>(); +} + +static v8::Handle<v8::Value> overloadedMethodCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.TestObj.overloadedMethod"); + if ((args.Length() == 2 && (args[0]->IsNull() || V8TestObj::HasInstance(args[0])) && (args[1]->IsNull() || args[1]->IsUndefined() || args[1]->IsString() || args[1]->IsObject()))) + return overloadedMethod1Callback(args); + if ((args.Length() == 1 && (args[0]->IsNull() || V8TestObj::HasInstance(args[0]))) || (args.Length() == 2 && (args[0]->IsNull() || V8TestObj::HasInstance(args[0])))) + return overloadedMethod2Callback(args); + if ((args.Length() == 1 && (args[0]->IsNull() || args[0]->IsUndefined() || args[0]->IsString() || args[0]->IsObject()))) + return overloadedMethod3Callback(args); + if (args.Length() == 1) + return overloadedMethod4Callback(args); + V8Proxy::setDOMException(SYNTAX_ERR); + return notHandledByInterceptor(); +} + +} // namespace TestObjInternal + +static const BatchedAttribute TestObjAttrs[] = { + // Attribute 'readOnlyIntAttr' (Type: 'readonly attribute' ExtAttr: '') + {"readOnlyIntAttr", TestObjInternal::readOnlyIntAttrAttrGetter, 0, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, + // Attribute 'readOnlyStringAttr' (Type: 'readonly attribute' ExtAttr: '') + {"readOnlyStringAttr", TestObjInternal::readOnlyStringAttrAttrGetter, 0, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, + // Attribute 'readOnlyTestObjAttr' (Type: 'readonly attribute' ExtAttr: '') + {"readOnlyTestObjAttr", TestObjInternal::readOnlyTestObjAttrAttrGetter, 0, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, + // Attribute 'intAttr' (Type: 'attribute' ExtAttr: '') + {"intAttr", TestObjInternal::intAttrAttrGetter, TestObjInternal::intAttrAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, + // Attribute 'stringAttr' (Type: 'attribute' ExtAttr: '') + {"stringAttr", TestObjInternal::stringAttrAttrGetter, TestObjInternal::stringAttrAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, + // Attribute 'testObjAttr' (Type: 'attribute' ExtAttr: '') + {"testObjAttr", TestObjInternal::testObjAttrAttrGetter, TestObjInternal::testObjAttrAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, + // Attribute 'attrWithException' (Type: 'attribute' ExtAttr: '') + {"attrWithException", TestObjInternal::attrWithExceptionAttrGetter, TestObjInternal::attrWithExceptionAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, + // Attribute 'attrWithSetterException' (Type: 'attribute' ExtAttr: '') + {"attrWithSetterException", TestObjInternal::attrWithSetterExceptionAttrGetter, TestObjInternal::attrWithSetterExceptionAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, + // Attribute 'attrWithGetterException' (Type: 'attribute' ExtAttr: '') + {"attrWithGetterException", TestObjInternal::attrWithGetterExceptionAttrGetter, TestObjInternal::attrWithGetterExceptionAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, + // Attribute 'customAttr' (Type: 'attribute' ExtAttr: 'Custom') + {"customAttr", V8TestObj::customAttrAccessorGetter, V8TestObj::customAttrAccessorSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, +}; +static const BatchedCallback TestObjCallbacks[] = { + {"voidMethod", TestObjInternal::voidMethodCallback}, + {"intMethod", TestObjInternal::intMethodCallback}, + {"objMethod", TestObjInternal::objMethodCallback}, + {"methodWithException", TestObjInternal::methodWithExceptionCallback}, + {"customMethod", V8TestObj::customMethodCallback}, + {"customMethodWithArgs", V8TestObj::customMethodWithArgsCallback}, + {"methodWithOptionalArg", TestObjInternal::methodWithOptionalArgCallback}, + {"methodWithNonOptionalArgAndOptionalArg", TestObjInternal::methodWithNonOptionalArgAndOptionalArgCallback}, + {"methodWithNonOptionalArgAndTwoOptionalArgs", TestObjInternal::methodWithNonOptionalArgAndTwoOptionalArgsCallback}, + {"overloadedMethod", TestObjInternal::overloadedMethodCallback}, +}; +static v8::Persistent<v8::FunctionTemplate> ConfigureV8TestObjTemplate(v8::Persistent<v8::FunctionTemplate> desc) +{ + v8::Local<v8::Signature> defaultSignature = configureTemplate(desc, "TestObj", v8::Persistent<v8::FunctionTemplate>(), V8TestObj::internalFieldCount, + TestObjAttrs, sizeof(TestObjAttrs) / sizeof(*TestObjAttrs), + TestObjCallbacks, sizeof(TestObjCallbacks) / sizeof(*TestObjCallbacks)); + v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate(); + v8::Local<v8::ObjectTemplate> proto = desc->PrototypeTemplate(); + + + // Custom Signature 'voidMethodWithArgs' + const int voidMethodWithArgsArgc = 3; + v8::Handle<v8::FunctionTemplate> voidMethodWithArgsArgv[voidMethodWithArgsArgc] = { v8::Handle<v8::FunctionTemplate>(), v8::Handle<v8::FunctionTemplate>(), V8TestObj::GetRawTemplate() }; + v8::Handle<v8::Signature> voidMethodWithArgsSignature = v8::Signature::New(desc, voidMethodWithArgsArgc, voidMethodWithArgsArgv); + proto->Set(v8::String::New("voidMethodWithArgs"), v8::FunctionTemplate::New(TestObjInternal::voidMethodWithArgsCallback, v8::Handle<v8::Value>(), voidMethodWithArgsSignature)); + + // Custom Signature 'intMethodWithArgs' + const int intMethodWithArgsArgc = 3; + v8::Handle<v8::FunctionTemplate> intMethodWithArgsArgv[intMethodWithArgsArgc] = { v8::Handle<v8::FunctionTemplate>(), v8::Handle<v8::FunctionTemplate>(), V8TestObj::GetRawTemplate() }; + v8::Handle<v8::Signature> intMethodWithArgsSignature = v8::Signature::New(desc, intMethodWithArgsArgc, intMethodWithArgsArgv); + proto->Set(v8::String::New("intMethodWithArgs"), v8::FunctionTemplate::New(TestObjInternal::intMethodWithArgsCallback, v8::Handle<v8::Value>(), intMethodWithArgsSignature)); + + // Custom Signature 'objMethodWithArgs' + const int objMethodWithArgsArgc = 3; + v8::Handle<v8::FunctionTemplate> objMethodWithArgsArgv[objMethodWithArgsArgc] = { v8::Handle<v8::FunctionTemplate>(), v8::Handle<v8::FunctionTemplate>(), V8TestObj::GetRawTemplate() }; + v8::Handle<v8::Signature> objMethodWithArgsSignature = v8::Signature::New(desc, objMethodWithArgsArgc, objMethodWithArgsArgv); + proto->Set(v8::String::New("objMethodWithArgs"), v8::FunctionTemplate::New(TestObjInternal::objMethodWithArgsCallback, v8::Handle<v8::Value>(), objMethodWithArgsSignature)); + + // Custom toString template + desc->Set(getToStringName(), getToStringTemplate()); + return desc; +} + +v8::Persistent<v8::FunctionTemplate> V8TestObj::GetRawTemplate() +{ + static v8::Persistent<v8::FunctionTemplate> V8TestObjRawCache = createRawTemplate(); + return V8TestObjRawCache; +} + +v8::Persistent<v8::FunctionTemplate> V8TestObj::GetTemplate() +{ + static v8::Persistent<v8::FunctionTemplate> V8TestObjCache = ConfigureV8TestObjTemplate(GetRawTemplate()); + return V8TestObjCache; +} + +TestObj* V8TestObj::toNative(v8::Handle<v8::Object> object) +{ + return reinterpret_cast<TestObj*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex)); +} + +bool V8TestObj::HasInstance(v8::Handle<v8::Value> value) +{ + return GetRawTemplate()->HasInstance(value); +} + + +v8::Handle<v8::Object> V8TestObj::wrap(TestObj* impl) +{ + v8::Handle<v8::Object> wrapper; + V8Proxy* proxy = 0; + wrapper = getDOMObjectMap().get(impl); + if (!wrapper.IsEmpty()) + return wrapper; + wrapper = V8DOMWrapper::instantiateV8Object(proxy, &info, impl); + if (wrapper.IsEmpty()) + return wrapper; + + impl->ref(); + getDOMObjectMap().set(impl, v8::Persistent<v8::Object>::New(wrapper)); + return wrapper; +} + +v8::Handle<v8::Value> toV8(PassRefPtr<TestObj > impl) +{ + return toV8(impl.get()); +} + +v8::Handle<v8::Value> toV8(TestObj* impl) +{ + if (!impl) + return v8::Null(); + return V8TestObj::wrap(impl); +} + +void V8TestObj::derefObject(void* object) +{ + static_cast<TestObj*>(object)->deref(); +} + +} // namespace WebCore diff --git a/WebCore/bindings/v8/test/V8TestObj.h b/WebCore/bindings/v8/test/V8TestObj.h new file mode 100644 index 0000000..5d6770a --- /dev/null +++ b/WebCore/bindings/v8/test/V8TestObj.h @@ -0,0 +1,53 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef V8TestObj_h +#define V8TestObj_h + +#include "StringHash.h" +#include "TestObj.h" +#include "WrapperTypeInfo.h" +#include <v8.h> +#include <wtf/HashMap.h> + +namespace WebCore { + +class V8TestObj { + +public: + static bool HasInstance(v8::Handle<v8::Value> value); + static v8::Persistent<v8::FunctionTemplate> GetRawTemplate(); + static v8::Persistent<v8::FunctionTemplate> GetTemplate(); + static TestObj* toNative(v8::Handle<v8::Object>); + static v8::Handle<v8::Object> wrap(TestObj*); + static void derefObject(void*); + static WrapperTypeInfo info; + static v8::Handle<v8::Value> customMethodCallback(const v8::Arguments&); + static v8::Handle<v8::Value> customMethodWithArgsCallback(const v8::Arguments&); + static v8::Handle<v8::Value> customAttrAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info); + static void customAttrAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info); + static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + 0; +}; + +v8::Handle<v8::Value> toV8(TestObj*); +v8::Handle<v8::Value> toV8(PassRefPtr<TestObj >); +} + +#endif // V8TestObj_h diff --git a/WebCore/bindings/v8/test/run_tests.py b/WebCore/bindings/v8/test/run_tests.py new file mode 100644 index 0000000..e27d559 --- /dev/null +++ b/WebCore/bindings/v8/test/run_tests.py @@ -0,0 +1,58 @@ +#!/usr/bin/python +# +# Copyright (C) 2010 Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 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. +# + +# This script generates h and cpp file for TestObj.idl using the V8 code +# generator. Please execute the script whenever changes are made to +# CodeGeneratorV8.pm, and submit the changes in V8TestObj.h/cpp in the same +# patch. This makes it easier to track and review changes in generated code. +# To execute, invoke: 'python run_tests.py' + +import os +import sys + + +def test(idlFilePath): + cmd = ['perl', '-w', + '-I../../scripts', + '../../scripts/generate-bindings.pl', + # idl include directories (path relative to generate-bindings.pl) + '--include .', + # place holder for defines (generate-bindings.pl requires it) + '--defines xxx', + '--generator V8', + '--outputDir .', + idlFilePath] + os.system(' '.join(cmd)) + + +def main(argv): + scriptDir = os.path.dirname(__file__) + os.chdir(scriptDir) + test('TestObj.idl') + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) |