summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/bindings/v8
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-25 19:08:45 +0100
committerSteve Block <steveblock@google.com>2011-06-08 13:51:31 +0100
commit2bde8e466a4451c7319e3a072d118917957d6554 (patch)
tree28f4a1b869a513e565c7760d0e6a06e7cf1fe95a /Source/WebCore/bindings/v8
parent6939c99b71d9372d14a0c74a772108052e8c48c8 (diff)
downloadexternal_webkit-2bde8e466a4451c7319e3a072d118917957d6554.zip
external_webkit-2bde8e466a4451c7319e3a072d118917957d6554.tar.gz
external_webkit-2bde8e466a4451c7319e3a072d118917957d6554.tar.bz2
Merge WebKit at r82507: Initial merge by git
Change-Id: I60ce9d780725b58b45e54165733a8ffee23b683e
Diffstat (limited to 'Source/WebCore/bindings/v8')
-rw-r--r--Source/WebCore/bindings/v8/DebuggerScript.js1
-rwxr-xr-xSource/WebCore/bindings/v8/PageScriptDebugServer.cpp165
-rwxr-xr-xSource/WebCore/bindings/v8/PageScriptDebugServer.h81
-rw-r--r--Source/WebCore/bindings/v8/RetainedDOMInfo.cpp85
-rw-r--r--Source/WebCore/bindings/v8/RetainedDOMInfo.h60
-rw-r--r--Source/WebCore/bindings/v8/RetainedObjectInfo.h45
-rw-r--r--Source/WebCore/bindings/v8/ScriptCachedFrameData.cpp6
-rw-r--r--Source/WebCore/bindings/v8/ScriptDebugServer.cpp203
-rw-r--r--Source/WebCore/bindings/v8/ScriptDebugServer.h37
-rw-r--r--Source/WebCore/bindings/v8/ScriptHeapSnapshot.cpp11
-rw-r--r--Source/WebCore/bindings/v8/ScriptHeapSnapshot.h3
-rw-r--r--Source/WebCore/bindings/v8/ScriptProfile.cpp5
-rw-r--r--Source/WebCore/bindings/v8/ScriptProfile.h2
-rw-r--r--Source/WebCore/bindings/v8/ScriptProfiler.cpp27
-rw-r--r--Source/WebCore/bindings/v8/ScriptProfiler.h2
-rw-r--r--Source/WebCore/bindings/v8/SerializedScriptValue.h2
-rw-r--r--Source/WebCore/bindings/v8/V8DOMWindowShell.cpp3
-rw-r--r--Source/WebCore/bindings/v8/V8GCController.cpp401
-rw-r--r--Source/WebCore/bindings/v8/V8LazyEventListener.cpp4
-rwxr-xr-xSource/WebCore/bindings/v8/WorkerScriptDebugServer.cpp55
-rwxr-xr-xSource/WebCore/bindings/v8/WorkerScriptDebugServer.h61
-rw-r--r--Source/WebCore/bindings/v8/WrapperTypeInfo.h15
-rw-r--r--Source/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp3
-rw-r--r--Source/WebCore/bindings/v8/custom/V8IDBAnyCustom.cpp4
-rw-r--r--Source/WebCore/bindings/v8/custom/V8IDBKeyCustom.cpp4
-rw-r--r--Source/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp139
-rw-r--r--Source/WebCore/bindings/v8/custom/V8InjectedScriptManager.cpp170
-rw-r--r--Source/WebCore/bindings/v8/custom/V8WebKitAnimationCustom.cpp50
28 files changed, 1117 insertions, 527 deletions
diff --git a/Source/WebCore/bindings/v8/DebuggerScript.js b/Source/WebCore/bindings/v8/DebuggerScript.js
index 0bed33d..fe6e8ab 100644
--- a/Source/WebCore/bindings/v8/DebuggerScript.js
+++ b/Source/WebCore/bindings/v8/DebuggerScript.js
@@ -262,5 +262,4 @@ DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror, callerFrame)
}
return DebuggerScript;
-
})();
diff --git a/Source/WebCore/bindings/v8/PageScriptDebugServer.cpp b/Source/WebCore/bindings/v8/PageScriptDebugServer.cpp
new file mode 100755
index 0000000..f149d8f
--- /dev/null
+++ b/Source/WebCore/bindings/v8/PageScriptDebugServer.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2011 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 "PageScriptDebugServer.h"
+
+#if ENABLE(JAVASCRIPT_DEBUGGER)
+
+#include "Frame.h"
+#include "Page.h"
+#include "ScriptDebugListener.h"
+#include "V8Binding.h"
+#include "V8DOMWindow.h"
+#include "V8Proxy.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/StdLibExtras.h>
+
+namespace WebCore {
+
+static Frame* retrieveFrame(v8::Handle<v8::Context> context)
+{
+ if (context.IsEmpty())
+ return 0;
+
+ // Test that context has associated global dom window object.
+ v8::Handle<v8::Object> global = context->Global();
+ if (global.IsEmpty())
+ return 0;
+
+ global = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), global);
+ if (global.IsEmpty())
+ return 0;
+
+ return V8Proxy::retrieveFrame(context);
+}
+
+PageScriptDebugServer& PageScriptDebugServer::shared()
+{
+ DEFINE_STATIC_LOCAL(PageScriptDebugServer, server, ());
+ return server;
+}
+
+PageScriptDebugServer::PageScriptDebugServer()
+ : ScriptDebugServer()
+ , m_pausedPage(0)
+ , m_enabled(true)
+{
+}
+
+void PageScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page)
+{
+ if (!m_enabled)
+ return;
+
+ V8Proxy* proxy = V8Proxy::retrieve(page->mainFrame());
+ if (!proxy)
+ return;
+
+ 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::SetDebugEventListener2(&PageScriptDebugServer::v8DebugEventCallback, v8::External::New(this));
+ }
+ m_listenersMap.set(page, listener);
+
+ V8DOMWindowShell* shell = proxy->windowShell();
+ if (!shell->isContextInitialized())
+ return;
+ v8::Handle<v8::Context> context = shell->context();
+ v8::Handle<v8::Function> getScriptsFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("getScripts")));
+ v8::Handle<v8::Value> argv[] = { context->GetData() };
+ v8::Handle<v8::Value> value = getScriptsFunction->Call(m_debuggerScript.get(), 1, argv);
+ 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))));
+}
+
+void PageScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* page)
+{
+ if (!m_listenersMap.contains(page))
+ return;
+
+ if (m_pausedPage == page)
+ continueProgram();
+
+ m_listenersMap.remove(page);
+
+ if (m_listenersMap.isEmpty())
+ v8::Debug::SetDebugEventListener(0);
+ // FIXME: Remove all breakpoints set by the agent.
+}
+
+void PageScriptDebugServer::setClientMessageLoop(PassOwnPtr<ClientMessageLoop> clientMessageLoop)
+{
+ m_clientMessageLoop = clientMessageLoop;
+}
+
+ScriptDebugListener* PageScriptDebugServer::getDebugListenerForContext(v8::Handle<v8::Context> context)
+{
+ v8::HandleScope scope;
+ Frame* frame = retrieveFrame(context);
+ if (!frame)
+ return 0;
+ return m_listenersMap.get(frame->page());
+}
+
+void PageScriptDebugServer::runMessageLoopOnPause(v8::Handle<v8::Context> context)
+{
+ v8::HandleScope scope;
+ Frame* frame = retrieveFrame(context);
+ m_pausedPage = frame->page();
+
+ // Wait for continue or step command.
+ m_clientMessageLoop->run(m_pausedPage);
+
+ // The listener may have been removed in the nested loop.
+ if (ScriptDebugListener* listener = m_listenersMap.get(m_pausedPage))
+ listener->didContinue();
+
+ m_pausedPage = 0;
+}
+
+void PageScriptDebugServer::quitMessageLoopOnPause()
+{
+ m_clientMessageLoop->quitNow();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(JAVASCRIPT_DEBUGGER)
diff --git a/Source/WebCore/bindings/v8/PageScriptDebugServer.h b/Source/WebCore/bindings/v8/PageScriptDebugServer.h
new file mode 100755
index 0000000..4b134c1
--- /dev/null
+++ b/Source/WebCore/bindings/v8/PageScriptDebugServer.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2011 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 PageScriptDebugServer_h
+#define PageScriptDebugServer_h
+
+#if ENABLE(JAVASCRIPT_DEBUGGER)
+
+#include "ScriptDebugServer.h"
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class Page;
+
+class PageScriptDebugServer : public ScriptDebugServer {
+ WTF_MAKE_NONCOPYABLE(PageScriptDebugServer);
+public:
+ static PageScriptDebugServer& shared();
+
+ void addListener(ScriptDebugListener*, Page*);
+ void removeListener(ScriptDebugListener*, Page*);
+
+ // v8-specific methods.
+ void setEnabled(bool value) { m_enabled = value; }
+
+ class ClientMessageLoop {
+ public:
+ virtual ~ClientMessageLoop() { }
+ virtual void run(Page*) = 0;
+ virtual void quitNow() = 0;
+ };
+ void setClientMessageLoop(PassOwnPtr<ClientMessageLoop>);
+
+private:
+ PageScriptDebugServer();
+ virtual ~PageScriptDebugServer() { }
+
+ virtual ScriptDebugListener* getDebugListenerForContext(v8::Handle<v8::Context>);
+ virtual void runMessageLoopOnPause(v8::Handle<v8::Context>);
+ virtual void quitMessageLoopOnPause();
+
+ typedef HashMap<Page*, ScriptDebugListener*> ListenersMap;
+ ListenersMap m_listenersMap;
+ OwnPtr<ClientMessageLoop> m_clientMessageLoop;
+ Page* m_pausedPage;
+ bool m_enabled;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(JAVASCRIPT_DEBUGGER)
+
+#endif // PageScriptDebugServer_h
diff --git a/Source/WebCore/bindings/v8/RetainedDOMInfo.cpp b/Source/WebCore/bindings/v8/RetainedDOMInfo.cpp
new file mode 100644
index 0000000..ba64263
--- /dev/null
+++ b/Source/WebCore/bindings/v8/RetainedDOMInfo.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2011 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 "RetainedDOMInfo.h"
+
+#include "Node.h"
+
+namespace WebCore {
+
+RetainedDOMInfo::RetainedDOMInfo(Node* root)
+ : m_root(root)
+{
+ ASSERT(m_root);
+}
+
+RetainedDOMInfo::~RetainedDOMInfo()
+{
+}
+
+void RetainedDOMInfo::Dispose()
+{
+ delete this;
+}
+
+bool RetainedDOMInfo::IsEquivalent(v8::RetainedObjectInfo* other)
+{
+ ASSERT(other);
+ return other == this || static_cast<WebCore::RetainedObjectInfo*>(other)->GetEquivalenceClass() == this->GetEquivalenceClass();
+}
+
+intptr_t RetainedDOMInfo::GetHash()
+{
+ return reinterpret_cast<intptr_t>(m_root);
+}
+
+const char* RetainedDOMInfo::GetLabel()
+{
+ return m_root->inDocument() ? "Document DOM tree" : "Detached DOM tree";
+}
+
+intptr_t RetainedDOMInfo::GetElementCount()
+{
+ intptr_t count = 1;
+ Node* current = m_root;
+ while (current) {
+ current = current->traverseNextNode(m_root);
+ ++count;
+ }
+ return count;
+}
+
+intptr_t RetainedDOMInfo::GetEquivalenceClass()
+{
+ return reinterpret_cast<intptr_t>(m_root);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/v8/RetainedDOMInfo.h b/Source/WebCore/bindings/v8/RetainedDOMInfo.h
new file mode 100644
index 0000000..6767f75
--- /dev/null
+++ b/Source/WebCore/bindings/v8/RetainedDOMInfo.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011 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 RetainedDOMInfo_h
+#define RetainedDOMInfo_h
+
+#include "RetainedObjectInfo.h"
+
+namespace WebCore {
+
+class Node;
+
+// Implements v8::RetainedObjectInfo.
+class RetainedDOMInfo : public RetainedObjectInfo {
+public:
+ explicit RetainedDOMInfo(Node* root);
+ virtual ~RetainedDOMInfo();
+ virtual void Dispose();
+ virtual bool IsEquivalent(v8::RetainedObjectInfo* other);
+ virtual intptr_t GetHash();
+ virtual const char* GetLabel();
+ virtual intptr_t GetElementCount();
+ virtual intptr_t GetEquivalenceClass();
+
+private:
+ // V8 guarantees to keep RetainedObjectInfos alive only during a GC or heap snapshotting round, when renderer
+ // doesn't get control. This allows us to use raw pointers.
+ Node* m_root;
+};
+
+} // namespace WebCore
+
+#endif // RetainedDOMInfo_h
diff --git a/Source/WebCore/bindings/v8/RetainedObjectInfo.h b/Source/WebCore/bindings/v8/RetainedObjectInfo.h
new file mode 100644
index 0000000..0368fb1
--- /dev/null
+++ b/Source/WebCore/bindings/v8/RetainedObjectInfo.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 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 RetainedObjectInfo_h
+#define RetainedObjectInfo_h
+
+#include <v8-profiler.h>
+
+namespace WebCore {
+
+class RetainedObjectInfo : public v8::RetainedObjectInfo {
+public:
+ virtual intptr_t GetEquivalenceClass() = 0;
+};
+
+} // namespace WebCore
+
+#endif // RetainedObjectInfo_h
diff --git a/Source/WebCore/bindings/v8/ScriptCachedFrameData.cpp b/Source/WebCore/bindings/v8/ScriptCachedFrameData.cpp
index dc28f32..9e15d1c 100644
--- a/Source/WebCore/bindings/v8/ScriptCachedFrameData.cpp
+++ b/Source/WebCore/bindings/v8/ScriptCachedFrameData.cpp
@@ -26,6 +26,10 @@
#include "config.h"
#include "ScriptCachedFrameData.h"
+#if PLATFORM(ANDROID) || PLATFORM(QT)
+// FIXME: the right guard should be ENABLE(PAGE_CACHE). Replace with the right guard, once
+// https://bugs.webkit.org/show_bug.cgi?id=35061 is fixed.
+
#include "Frame.h"
#include "ScriptController.h"
#include "V8DOMWindow.h"
@@ -72,3 +76,5 @@ void ScriptCachedFrameData::clear()
}
} // namespace WebCore
+
+#endif // PLATFORM(ANDROID) || PLATFORM(QT)
diff --git a/Source/WebCore/bindings/v8/ScriptDebugServer.cpp b/Source/WebCore/bindings/v8/ScriptDebugServer.cpp
index cc7fba8..5758639 100644
--- a/Source/WebCore/bindings/v8/ScriptDebugServer.cpp
+++ b/Source/WebCore/bindings/v8/ScriptDebugServer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Google Inc. All rights reserved.
+ * Copyright (c) 2010-2011 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -33,13 +33,10 @@
#if ENABLE(JAVASCRIPT_DEBUGGER)
-#include "Frame.h"
+#include "DebuggerScriptSource.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 {
@@ -57,92 +54,12 @@ private:
}
-static Frame* retrieveFrame(v8::Handle<v8::Context> context)
-{
- if (context.IsEmpty())
- return 0;
-
- // Test that context has associated global dom window object.
- v8::Handle<v8::Object> global = context->Global();
- if (global.IsEmpty())
- return 0;
-
- global = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), global);
- if (global.IsEmpty())
- return 0;
-
- return V8Proxy::retrieveFrame(context);
-}
-
-ScriptDebugServer& ScriptDebugServer::shared()
-{
- DEFINE_STATIC_LOCAL(ScriptDebugServer, server, ());
- return server;
-}
-
ScriptDebugServer::ScriptDebugServer()
: m_pauseOnExceptionsState(DontPauseOnExceptions)
- , m_pausedPage(0)
- , m_enabled(true)
, m_breakpointsActivated(true)
{
}
-void ScriptDebugServer::setDebuggerScriptSource(const String& scriptSource)
-{
- m_debuggerScriptSource = scriptSource;
-}
-
-void ScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page)
-{
- if (!m_enabled)
- return;
-
- V8Proxy* proxy = V8Proxy::retrieve(page->mainFrame());
- if (!proxy)
- return;
-
- 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::SetDebugEventListener2(&ScriptDebugServer::v8DebugEventCallback);
- }
- m_listenersMap.set(page, listener);
-
- V8DOMWindowShell* shell = proxy->windowShell();
- if (!shell->isContextInitialized())
- return;
- v8::Handle<v8::Context> context = shell->context();
- v8::Handle<v8::Function> getScriptsFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("getScripts")));
- v8::Handle<v8::Value> argv[] = { context->GetData() };
- v8::Handle<v8::Value> value = getScriptsFunction->Call(m_debuggerScript.get(), 1, argv);
- 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))));
-}
-
-void ScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* page)
-{
- if (!m_listenersMap.contains(page))
- return;
-
- if (m_pausedPage == page)
- continueProgram();
-
- m_listenersMap.remove(page);
-
- if (m_listenersMap.isEmpty())
- v8::Debug::SetDebugEventListener(0);
- // FIXME: Remove all breakpoints set by the agent.
-}
-
String ScriptDebugServer::setBreakpoint(const String& sourceID, const ScriptBreakpoint& scriptBreakpoint, int* actualLineNumber, int* actualColumnNumber)
{
v8::HandleScope scope;
@@ -229,7 +146,7 @@ void ScriptDebugServer::setPauseOnExceptionsState(PauseOnExceptionsState pauseOn
void ScriptDebugServer::setPauseOnNextStatement(bool pause)
{
- if (m_pausedPage)
+ if (isPaused())
return;
if (pause)
v8::Debug::DebugBreak();
@@ -239,17 +156,15 @@ void ScriptDebugServer::setPauseOnNextStatement(bool pause)
void ScriptDebugServer::breakProgram()
{
- DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, callbackTemplate, ());
-
if (!m_breakpointsActivated)
return;
if (!v8::Context::InContext())
return;
- if (callbackTemplate.IsEmpty()) {
- callbackTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New());
- callbackTemplate->SetCallHandler(&ScriptDebugServer::breakProgramCallback);
+ if (m_breakProgramCallbackTemplate.get().IsEmpty()) {
+ m_breakProgramCallbackTemplate.set(v8::FunctionTemplate::New());
+ m_breakProgramCallbackTemplate.get()->SetCallHandler(&ScriptDebugServer::breakProgramCallback, v8::External::New(this));
}
v8::Handle<v8::Context> context = v8::Context::GetCurrent();
@@ -257,21 +172,22 @@ void ScriptDebugServer::breakProgram()
return;
m_pausedPageContext = *context;
- v8::Handle<v8::Function> breakProgramFunction = callbackTemplate->GetFunction();
+ v8::Handle<v8::Function> breakProgramFunction = m_breakProgramCallbackTemplate.get()->GetFunction();
v8::Debug::Call(breakProgramFunction);
m_pausedPageContext.Clear();
}
void ScriptDebugServer::continueProgram()
{
- if (m_pausedPage)
- m_clientMessageLoop->quitNow();
- didResume();
+ if (isPaused())
+ quitMessageLoopOnPause();
+ m_currentCallFrame.clear();
+ m_executionState.clear();
}
void ScriptDebugServer::stepIntoStatement()
{
- ASSERT(m_pausedPage);
+ ASSERT(isPaused());
v8::Handle<v8::Function> function = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("stepIntoStatement")));
v8::Handle<v8::Value> argv[] = { m_executionState.get() };
function->Call(m_debuggerScript.get(), 1, argv);
@@ -280,7 +196,7 @@ void ScriptDebugServer::stepIntoStatement()
void ScriptDebugServer::stepOverStatement()
{
- ASSERT(m_pausedPage);
+ ASSERT(isPaused());
v8::Handle<v8::Function> function = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("stepOverStatement")));
v8::Handle<v8::Value> argv[] = { m_executionState.get() };
function->Call(m_debuggerScript.get(), 1, argv);
@@ -289,7 +205,7 @@ void ScriptDebugServer::stepOverStatement()
void ScriptDebugServer::stepOutOfFunction()
{
- ASSERT(m_pausedPage);
+ ASSERT(isPaused());
v8::Handle<v8::Function> function = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("stepOutOfFunction")));
v8::Handle<v8::Value> argv[] = { m_executionState.get() };
function->Call(m_debuggerScript.get(), 1, argv);
@@ -302,7 +218,7 @@ bool ScriptDebugServer::editScriptSource(const String& sourceID, const String& n
v8::HandleScope scope;
OwnPtr<v8::Context::Scope> contextScope;
- if (!m_pausedPage)
+ if (!isPaused())
contextScope.set(new v8::Context::Scope(v8::Debug::GetDebugContext()));
v8::Handle<v8::Function> function = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("editScriptSource")));
@@ -337,11 +253,6 @@ PassRefPtr<JavaScriptCallFrame> ScriptDebugServer::currentCallFrame()
return m_currentCallFrame;
}
-void ScriptDebugServer::setEnabled(bool value)
-{
- m_enabled = value;
-}
-
void ScriptDebugServer::interruptAndRun(PassOwnPtr<Task> task)
{
v8::Debug::DebugBreakForCommand(new ClientDataImpl(task));
@@ -352,44 +263,42 @@ void ScriptDebugServer::runPendingTasks()
v8::Debug::ProcessDebugMessages();
}
+static ScriptDebugServer* toScriptDebugServer(v8::Handle<v8::Value> data)
+{
+ void* p = v8::Handle<v8::External>::Cast(data)->Value();
+ return static_cast<ScriptDebugServer*>(p);
+}
+
v8::Handle<v8::Value> ScriptDebugServer::breakProgramCallback(const v8::Arguments& args)
{
ASSERT(2 == args.Length());
- ScriptDebugServer::shared().breakProgram(v8::Handle<v8::Object>::Cast(args[0]));
+
+ ScriptDebugServer* thisPtr = toScriptDebugServer(args.Data());
+ thisPtr->breakProgram(v8::Handle<v8::Object>::Cast(args[0]));
return v8::Undefined();
}
void ScriptDebugServer::breakProgram(v8::Handle<v8::Object> executionState)
{
// Don't allow nested breaks.
- if (m_pausedPage)
- return;
-
- Frame* frame = retrieveFrame(m_pausedPageContext);
- if (!frame)
+ if (isPaused())
return;
- ScriptDebugListener* listener = m_listenersMap.get(frame->page());
+ ScriptDebugListener* listener = getDebugListenerForContext(m_pausedPageContext);
if (!listener)
return;
m_executionState.set(executionState);
- m_pausedPage = frame->page();
ScriptState* currentCallFrameState = ScriptState::forContext(m_pausedPageContext);
listener->didPause(currentCallFrameState);
- // Wait for continue or step command.
- m_clientMessageLoop->run(m_pausedPage);
- ASSERT(!m_pausedPage);
-
- // The listener may have been removed in the nested loop.
- if (ScriptDebugListener* listener = m_listenersMap.get(frame->page()))
- listener->didContinue();
+ runMessageLoopOnPause(m_pausedPageContext);
}
void ScriptDebugServer::v8DebugEventCallback(const v8::Debug::EventDetails& eventDetails)
{
- ScriptDebugServer::shared().handleV8DebugEvent(eventDetails);
+ ScriptDebugServer* thisPtr = toScriptDebugServer(eventDetails.GetCallbackData());
+ thisPtr->handleV8DebugEvent(eventDetails);
}
void ScriptDebugServer::handleV8DebugEvent(const v8::Debug::EventDetails& eventDetails)
@@ -408,31 +317,28 @@ void ScriptDebugServer::handleV8DebugEvent(const v8::Debug::EventDetails& eventD
v8::Handle<v8::Context> eventContext = eventDetails.GetEventContext();
ASSERT(!eventContext.IsEmpty());
- Frame* frame = retrieveFrame(eventContext);
- if (frame) {
- ScriptDebugListener* listener = m_listenersMap.get(frame->page());
- if (listener) {
- v8::HandleScope scope;
- if (event == v8::AfterCompile) {
- v8::Context::Scope contextScope(v8::Debug::GetDebugContext());
- v8::Handle<v8::Function> onAfterCompileFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("getAfterCompileScript")));
- v8::Handle<v8::Value> argv[] = { eventDetails.GetEventData() };
- v8::Handle<v8::Value> value = onAfterCompileFunction->Call(m_debuggerScript.get(), 1, argv);
- ASSERT(value->IsObject());
- v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value);
- dispatchDidParseSource(listener, object);
- } else if (event == v8::Break || event == v8::Exception) {
- if (event == v8::Exception) {
- v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(1);
- // Stack trace is empty in case of syntax error. Silently continue execution in such cases.
- if (!stackTrace->GetFrameCount())
- return;
- }
-
- m_pausedPageContext = *eventContext;
- breakProgram(eventDetails.GetExecutionState());
- m_pausedPageContext.Clear();
+ ScriptDebugListener* listener = getDebugListenerForContext(eventContext);
+ if (listener) {
+ v8::HandleScope scope;
+ if (event == v8::AfterCompile) {
+ v8::Context::Scope contextScope(v8::Debug::GetDebugContext());
+ v8::Handle<v8::Function> onAfterCompileFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("getAfterCompileScript")));
+ v8::Handle<v8::Value> argv[] = { eventDetails.GetEventData() };
+ v8::Handle<v8::Value> value = onAfterCompileFunction->Call(m_debuggerScript.get(), 1, argv);
+ ASSERT(value->IsObject());
+ v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value);
+ dispatchDidParseSource(listener, object);
+ } else if (event == v8::Break || event == v8::Exception) {
+ if (event == v8::Exception) {
+ v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(1);
+ // Stack trace is empty in case of syntax error. Silently continue execution in such cases.
+ if (!stackTrace->GetFrameCount())
+ return;
}
+
+ m_pausedPageContext = *eventContext;
+ breakProgram(eventDetails.GetExecutionState());
+ m_pausedPageContext.Clear();
}
}
}
@@ -454,15 +360,14 @@ void ScriptDebugServer::ensureDebuggerScriptCompiled()
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()));
+ String debuggerScriptSource(reinterpret_cast<const char*>(DebuggerScriptSource_js), sizeof(DebuggerScriptSource_js));
+ m_debuggerScript.set(v8::Handle<v8::Object>::Cast(v8::Script::Compile(v8String(debuggerScriptSource))->Run()));
}
}
-void ScriptDebugServer::didResume()
+bool ScriptDebugServer::isPaused()
{
- m_currentCallFrame.clear();
- m_executionState.clear();
- m_pausedPage = 0;
+ return !m_executionState.get().IsEmpty();
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/v8/ScriptDebugServer.h b/Source/WebCore/bindings/v8/ScriptDebugServer.h
index af3d2ab..15004ea 100644
--- a/Source/WebCore/bindings/v8/ScriptDebugServer.h
+++ b/Source/WebCore/bindings/v8/ScriptDebugServer.h
@@ -45,17 +45,11 @@
namespace WebCore {
-class Page;
class ScriptDebugListener;
class ScriptDebugServer {
WTF_MAKE_NONCOPYABLE(ScriptDebugServer);
public:
- static ScriptDebugServer& shared();
-
- void addListener(ScriptDebugListener*, Page*);
- void removeListener(ScriptDebugListener*, Page*);
-
String setBreakpoint(const String& sourceID, const ScriptBreakpoint&, int* actualLineNumber, int* actualColumnNumber);
void removeBreakpoint(const String& breakpointId);
void clearBreakpoints();
@@ -83,23 +77,8 @@ public:
void recompileAllJSFunctionsSoon() { }
void recompileAllJSFunctions(Timer<ScriptDebugServer>* = 0) { }
- void pageCreated(Page*) { }
-
- // v8-specific methods.
- void setDebuggerScriptSource(const String& scriptSource);
-
- class ClientMessageLoop {
- public:
- virtual ~ClientMessageLoop() { }
- virtual void run(Page*) = 0;
- virtual void quitNow() = 0;
- };
- void setClientMessageLoop(PassOwnPtr<ClientMessageLoop> clientMessageLoop) { m_clientMessageLoop = clientMessageLoop; }
-
PassRefPtr<JavaScriptCallFrame> currentCallFrame();
- void setEnabled(bool);
-
class Task {
public:
virtual ~Task() { }
@@ -108,9 +87,13 @@ public:
static void interruptAndRun(PassOwnPtr<Task>);
void runPendingTasks();
-private:
+protected:
ScriptDebugServer();
~ScriptDebugServer() { }
+
+ virtual ScriptDebugListener* getDebugListenerForContext(v8::Handle<v8::Context>) = 0;
+ virtual void runMessageLoopOnPause(v8::Handle<v8::Context>) = 0;
+ virtual void quitMessageLoopOnPause() = 0;
static v8::Handle<v8::Value> breakProgramCallback(const v8::Arguments& args);
void breakProgram(v8::Handle<v8::Object> executionState);
@@ -121,21 +104,17 @@ private:
void dispatchDidParseSource(ScriptDebugListener* listener, v8::Handle<v8::Object> sourceObject);
void ensureDebuggerScriptCompiled();
- void didResume();
+
+ bool isPaused();
- typedef HashMap<Page*, ScriptDebugListener*> ListenersMap;
- ListenersMap m_listenersMap;
- String m_debuggerScriptSource;
PauseOnExceptionsState m_pauseOnExceptionsState;
OwnHandle<v8::Object> m_debuggerScript;
RefPtr<JavaScriptCallFrame> m_currentCallFrame;
OwnHandle<v8::Object> m_executionState;
- OwnPtr<ClientMessageLoop> m_clientMessageLoop;
- Page* m_pausedPage;
v8::Local<v8::Context> m_pausedPageContext;
- bool m_enabled;
bool m_breakpointsActivated;
+ OwnHandle<v8::FunctionTemplate> m_breakProgramCallbackTemplate;
};
} // namespace WebCore
diff --git a/Source/WebCore/bindings/v8/ScriptHeapSnapshot.cpp b/Source/WebCore/bindings/v8/ScriptHeapSnapshot.cpp
index 09e1e54..68ed8da 100644
--- a/Source/WebCore/bindings/v8/ScriptHeapSnapshot.cpp
+++ b/Source/WebCore/bindings/v8/ScriptHeapSnapshot.cpp
@@ -40,6 +40,11 @@
namespace WebCore {
+ScriptHeapSnapshot::~ScriptHeapSnapshot()
+{
+ const_cast<v8::HeapSnapshot*>(m_snapshot)->Delete();
+}
+
String ScriptHeapSnapshot::title() const
{
v8::HandleScope scope;
@@ -76,10 +81,4 @@ void ScriptHeapSnapshot::writeJSON(ScriptHeapSnapshot::OutputStream* stream)
m_snapshot->Serialize(&outputStream, v8::HeapSnapshot::kJSON);
}
-int ScriptHeapSnapshot::exactRetainedSize(uint64_t nodeId)
-{
- const v8::HeapGraphNode* node = m_snapshot->GetNodeById(nodeId);
- return node ? node->GetRetainedSize(true) : -1;
-}
-
} // namespace WebCore
diff --git a/Source/WebCore/bindings/v8/ScriptHeapSnapshot.h b/Source/WebCore/bindings/v8/ScriptHeapSnapshot.h
index 6cfd76d..4093fa7 100644
--- a/Source/WebCore/bindings/v8/ScriptHeapSnapshot.h
+++ b/Source/WebCore/bindings/v8/ScriptHeapSnapshot.h
@@ -54,12 +54,11 @@ public:
{
return adoptRef(new ScriptHeapSnapshot(snapshot));
}
- virtual ~ScriptHeapSnapshot() {}
+ virtual ~ScriptHeapSnapshot();
String title() const;
unsigned int uid() const;
void writeJSON(OutputStream* stream);
- int exactRetainedSize(uint64_t nodeId);
private:
ScriptHeapSnapshot(const v8::HeapSnapshot* snapshot)
diff --git a/Source/WebCore/bindings/v8/ScriptProfile.cpp b/Source/WebCore/bindings/v8/ScriptProfile.cpp
index c5a6dbf..2c9f0f5 100644
--- a/Source/WebCore/bindings/v8/ScriptProfile.cpp
+++ b/Source/WebCore/bindings/v8/ScriptProfile.cpp
@@ -39,6 +39,11 @@
namespace WebCore {
+ScriptProfile::~ScriptProfile()
+{
+ const_cast<v8::CpuProfile*>(m_profile)->Delete();
+}
+
String ScriptProfile::title() const
{
v8::HandleScope scope;
diff --git a/Source/WebCore/bindings/v8/ScriptProfile.h b/Source/WebCore/bindings/v8/ScriptProfile.h
index 0182669..d8196a4 100644
--- a/Source/WebCore/bindings/v8/ScriptProfile.h
+++ b/Source/WebCore/bindings/v8/ScriptProfile.h
@@ -48,7 +48,7 @@ public:
{
return adoptRef(new ScriptProfile(profile));
}
- virtual ~ScriptProfile() {}
+ virtual ~ScriptProfile();
String title() const;
unsigned int uid() const;
diff --git a/Source/WebCore/bindings/v8/ScriptProfiler.cpp b/Source/WebCore/bindings/v8/ScriptProfiler.cpp
index 615dcfc..3fe45a8 100644
--- a/Source/WebCore/bindings/v8/ScriptProfiler.cpp
+++ b/Source/WebCore/bindings/v8/ScriptProfiler.cpp
@@ -32,9 +32,11 @@
#include "ScriptProfiler.h"
#include "InspectorValues.h"
+#include "RetainedDOMInfo.h"
+#include "V8Binding.h"
+#include "V8Node.h"
#include <v8-profiler.h>
-#include <V8Binding.h>
namespace WebCore {
@@ -53,6 +55,14 @@ PassRefPtr<ScriptProfile> ScriptProfiler::stop(ScriptState* state, const String&
return profile ? ScriptProfile::create(profile) : 0;
}
+void ScriptProfiler::collectGarbage()
+{
+ // NOTE : There is currently no direct way to collect memory from the v8 C++ API
+ // but notifying low-memory forces a mark-compact, which is exactly what we want
+ // in this case.
+ v8::V8::LowMemoryNotification();
+}
+
namespace {
class ActivityControlAdapter : public v8::ActivityControl {
@@ -90,4 +100,19 @@ PassRefPtr<ScriptHeapSnapshot> ScriptProfiler::takeHeapSnapshot(const String& ti
return snapshot ? ScriptHeapSnapshot::create(snapshot) : 0;
}
+static v8::RetainedObjectInfo* retainedDOMInfo(uint16_t classId, v8::Handle<v8::Value> wrapper)
+{
+ ASSERT(classId == v8DOMSubtreeClassId);
+ if (!wrapper->IsObject())
+ return 0;
+ Node* node = V8Node::toNative(wrapper.As<v8::Object>());
+ return node ? new RetainedDOMInfo(node) : 0;
+}
+
+void ScriptProfiler::initialize()
+{
+ v8::HeapProfiler::DefineWrapperClass(v8DOMSubtreeClassId, &retainedDOMInfo);
+}
+
+
} // namespace WebCore
diff --git a/Source/WebCore/bindings/v8/ScriptProfiler.h b/Source/WebCore/bindings/v8/ScriptProfiler.h
index 9016668..92a980b 100644
--- a/Source/WebCore/bindings/v8/ScriptProfiler.h
+++ b/Source/WebCore/bindings/v8/ScriptProfiler.h
@@ -53,9 +53,11 @@ public:
virtual bool isCanceled() = 0;
};
+ static void collectGarbage();
static void start(ScriptState* state, const String& title);
static PassRefPtr<ScriptProfile> stop(ScriptState* state, const String& title);
static PassRefPtr<ScriptHeapSnapshot> takeHeapSnapshot(const String& title, HeapSnapshotProgress*);
+ static void initialize();
};
} // namespace WebCore
diff --git a/Source/WebCore/bindings/v8/SerializedScriptValue.h b/Source/WebCore/bindings/v8/SerializedScriptValue.h
index c0e9109..212be66 100644
--- a/Source/WebCore/bindings/v8/SerializedScriptValue.h
+++ b/Source/WebCore/bindings/v8/SerializedScriptValue.h
@@ -37,7 +37,7 @@
namespace WebCore {
-class SerializedScriptValue : public ThreadSafeShared<SerializedScriptValue> {
+class SerializedScriptValue : public ThreadSafeRefCounted<SerializedScriptValue> {
public:
static void deserializeAndSetProperty(v8::Handle<v8::Object>, const char* propertyName,
v8::PropertyAttribute, SerializedScriptValue*);
diff --git a/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp b/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp
index d88d8a6..e025008 100644
--- a/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp
+++ b/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp
@@ -43,6 +43,7 @@
#include "ScriptCallStack.h"
#include "ScriptCallStackFactory.h"
#include "ScriptController.h"
+#include "ScriptProfiler.h"
#include "StorageNamespace.h"
#include "V8Binding.h"
#include "V8BindingState.h"
@@ -305,6 +306,8 @@ bool V8DOMWindowShell::initContextIfNeeded()
v8::V8::SetFailedAccessCheckCallbackFunction(reportUnsafeJavaScriptAccess);
+ ScriptProfiler::initialize();
+
isV8Initialized = true;
}
diff --git a/Source/WebCore/bindings/v8/V8GCController.cpp b/Source/WebCore/bindings/v8/V8GCController.cpp
index cda9f3d..82c9ca4 100644
--- a/Source/WebCore/bindings/v8/V8GCController.cpp
+++ b/Source/WebCore/bindings/v8/V8GCController.cpp
@@ -34,27 +34,20 @@
#include "ActiveDOMObject.h"
#include "Attr.h"
#include "DOMDataStore.h"
-#include "Frame.h"
+#include "DOMImplementation.h"
#include "HTMLImageElement.h"
#include "HTMLNames.h"
#include "MessagePort.h"
#include "PlatformBridge.h"
-#include "SVGElement.h"
+#include "RetainedDOMInfo.h"
+#include "RetainedObjectInfo.h"
#include "V8Binding.h"
-#include "V8CSSCharsetRule.h"
-#include "V8CSSFontFaceRule.h"
-#include "V8CSSImportRule.h"
-#include "V8CSSMediaRule.h"
+#include "V8CSSRule.h"
#include "V8CSSRuleList.h"
#include "V8CSSStyleDeclaration.h"
-#include "V8CSSStyleRule.h"
-#include "V8CSSStyleSheet.h"
-#include "V8DOMMap.h"
-#include "V8HTMLLinkElement.h"
-#include "V8HTMLStyleElement.h"
+#include "V8DOMImplementation.h"
#include "V8MessagePort.h"
-#include "V8ProcessingInstruction.h"
-#include "V8Proxy.h"
+#include "V8StyleSheet.h"
#include "V8StyleSheetList.h"
#include "WrapperTypeInfo.h"
@@ -175,19 +168,86 @@ public:
}
};
-class GrouperItem {
+// Implements v8::RetainedObjectInfo.
+class UnspecifiedGroup : public RetainedObjectInfo {
public:
- GrouperItem(uintptr_t groupId, v8::Persistent<v8::Object> wrapper)
- : m_groupId(groupId)
- , m_wrapper(wrapper)
- {
- }
+ explicit UnspecifiedGroup(void* object)
+ : m_object(object)
+ {
+ ASSERT(m_object);
+ }
+
+ virtual void Dispose() { delete this; }
+
+ virtual bool IsEquivalent(v8::RetainedObjectInfo* other)
+ {
+ ASSERT(other);
+ return other == this || static_cast<WebCore::RetainedObjectInfo*>(other)->GetEquivalenceClass() == this->GetEquivalenceClass();
+ }
+ virtual intptr_t GetHash()
+ {
+ return reinterpret_cast<intptr_t>(m_object);
+ }
+
+ virtual const char* GetLabel()
+ {
+ return "Object group";
+ }
+
+ virtual intptr_t GetEquivalenceClass()
+ {
+ return reinterpret_cast<intptr_t>(m_object);
+ }
+
+private:
+ void* m_object;
+};
+
+class GroupId {
+public:
+ GroupId() : m_type(NullType), m_groupId(0) {}
+ GroupId(Node* node) : m_type(NodeType), m_node(node) {}
+ GroupId(void* other) : m_type(OtherType), m_other(other) {}
+ bool operator!() const { return m_type == NullType; }
uintptr_t groupId() const { return m_groupId; }
+ RetainedObjectInfo* createRetainedObjectInfo() const
+ {
+ switch (m_type) {
+ case NullType:
+ return 0;
+ case NodeType:
+ return new RetainedDOMInfo(m_node);
+ case OtherType:
+ return new UnspecifiedGroup(m_other);
+ default:
+ return 0;
+ }
+ }
+
+private:
+ enum Type {
+ NullType,
+ NodeType,
+ OtherType
+ };
+ Type m_type;
+ union {
+ uintptr_t m_groupId;
+ Node* m_node;
+ void* m_other;
+ };
+};
+
+class GrouperItem {
+public:
+ GrouperItem(GroupId groupId, v8::Persistent<v8::Object> wrapper) : m_groupId(groupId), m_wrapper(wrapper) {}
+ uintptr_t groupId() const { return m_groupId.groupId(); }
+ RetainedObjectInfo* createRetainedObjectInfo() const { return m_groupId.createRetainedObjectInfo(); }
v8::Persistent<v8::Object> wrapper() const { return m_wrapper; }
private:
- uintptr_t m_groupId;
+ GroupId m_groupId;
v8::Persistent<v8::Object> m_wrapper;
};
@@ -198,215 +258,160 @@ bool operator<(const GrouperItem& a, const GrouperItem& b)
typedef Vector<GrouperItem> GrouperList;
-void makeV8ObjectGroups(GrouperList& grouper)
+// If the node is in document, put it in the ownerDocument's object group.
+//
+// If an image element was created by JavaScript "new Image",
+// it is not in a document. However, if the load event has not
+// been fired (still onloading), it is treated as in the document.
+//
+// Otherwise, the node is put in an object group identified by the root
+// element of the tree to which it belongs.
+static GroupId calculateGroupId(Node* node)
{
- // Group by sorting by the group id.
- std::sort(grouper.begin(), grouper.end());
-
- // FIXME Should probably work in iterators here, but indexes were easier for my simple mind.
- for (size_t i = 0; i < grouper.size(); ) {
- // Seek to the next key (or the end of the list).
- size_t nextKeyIndex = grouper.size();
- for (size_t j = i; j < grouper.size(); ++j) {
- if (grouper[i].groupId() != grouper[j].groupId()) {
- nextKeyIndex = j;
- break;
- }
- }
+ if (node->inDocument() || (node->hasTagName(HTMLNames::imgTag) && !static_cast<HTMLImageElement*>(node)->haveFiredLoadEvent()))
+ return GroupId(node->document());
+
+ Node* root = node;
+ if (node->isAttributeNode()) {
+ root = static_cast<Attr*>(node)->ownerElement();
+ // If the attribute has no element, no need to put it in the group,
+ // because it'll always be a group of 1.
+ if (!root)
+ return GroupId();
+ } else {
+ while (Node* parent = root->parentNode())
+ root = parent;
+ }
- ASSERT(nextKeyIndex > i);
+ return GroupId(root);
+}
- // We only care about a group if it has more than one object. If it only
- // has one object, it has nothing else that needs to be kept alive.
- if (nextKeyIndex - i <= 1) {
- i = nextKeyIndex;
- continue;
+static GroupId calculateGroupId(StyleBase* styleBase)
+{
+ ASSERT(styleBase);
+ StyleBase* current = styleBase;
+ StyleSheet* styleSheet = 0;
+ while (true) {
+ // Special case: CSSStyleDeclarations might be either inline and in this case
+ // we need to group them with their node or regular ones.
+ if (current->isMutableStyleDeclaration()) {
+ CSSMutableStyleDeclaration* cssMutableStyleDeclaration = static_cast<CSSMutableStyleDeclaration*>(current);
+ if (cssMutableStyleDeclaration->isInlineStyleDeclaration()) {
+ ASSERT(cssMutableStyleDeclaration->parent()->isStyleSheet());
+ return calculateGroupId(cssMutableStyleDeclaration->node());
+ }
+ // Either we have no parent, or this parent is a CSSRule.
+ ASSERT(cssMutableStyleDeclaration->parent() == cssMutableStyleDeclaration->parentRule());
}
- Vector<v8::Persistent<v8::Value> > group;
- group.reserveCapacity(nextKeyIndex - i);
- for (; i < nextKeyIndex; ++i) {
- v8::Persistent<v8::Value> wrapper = grouper[i].wrapper();
- if (!wrapper.IsEmpty())
- group.append(wrapper);
- }
+ if (current->isStyleSheet())
+ styleSheet = static_cast<StyleSheet*>(current);
- if (group.size() > 1)
- v8::V8::AddObjectGroup(&group[0], group.size());
+ StyleBase* parent = current->parent();
+ if (!parent)
+ break;
+ current = parent;
+ }
- ASSERT(i == nextKeyIndex);
+ if (styleSheet) {
+ if (Node* ownerNode = styleSheet->ownerNode())
+ return calculateGroupId(ownerNode);
+ return GroupId(styleSheet);
}
+
+ return GroupId(current);
}
-class NodeGrouperVisitor : public DOMWrapperMap<Node>::Visitor {
+class GrouperVisitor : public DOMWrapperMap<Node>::Visitor, public DOMWrapperMap<void>::Visitor {
public:
- NodeGrouperVisitor()
- {
- // FIXME: grouper_.reserveCapacity(node_map.size()); ?
- }
-
void visitDOMWrapper(DOMDataStore* store, Node* node, v8::Persistent<v8::Object> wrapper)
{
- // If the node is in document, put it in the ownerDocument's object group.
- //
- // If an image element was created by JavaScript "new Image",
- // it is not in a document. However, if the load event has not
- // been fired (still onloading), it is treated as in the document.
- //
- // Otherwise, the node is put in an object group identified by the root
- // element of the tree to which it belongs.
- uintptr_t groupId;
- if (node->inDocument() || (node->hasTagName(HTMLNames::imgTag) && !static_cast<HTMLImageElement*>(node)->haveFiredLoadEvent()))
- groupId = reinterpret_cast<uintptr_t>(node->document());
- else {
- Node* root = node;
- if (node->isAttributeNode()) {
- root = static_cast<Attr*>(node)->ownerElement();
- // If the attribute has no element, no need to put it in the group,
- // because it'll always be a group of 1.
- if (!root)
- return;
- } else {
- while (root->parentNode())
- root = root->parentNode();
-
- // If the node is alone in its DOM tree (doesn't have a parent or any
- // children) then the group will be filtered out later anyway.
- if (root == node && !node->hasChildNodes() && !node->hasAttributes())
- return;
- }
- groupId = reinterpret_cast<uintptr_t>(root);
- }
+ GroupId groupId = calculateGroupId(node);
+ if (!groupId)
+ return;
m_grouper.append(GrouperItem(groupId, wrapper));
+ }
- // If the node is styled and there is a wrapper for the inline
- // style declaration, we need to keep that style declaration
- // wrapper alive as well, so we add it to the object group.
- if (node->isStyledElement()) {
- StyledElement* element = reinterpret_cast<StyledElement*>(node);
- addDOMObjectToGroup(store, groupId, element->inlineStyleDecl());
- }
-
- if (node->isDocumentNode()) {
- Document* document = reinterpret_cast<Document*>(node);
- addDOMObjectToGroup(store, groupId, document->styleSheets());
- addDOMObjectToGroup(store, groupId, document->implementation());
- }
-
+ void visitDOMWrapper(DOMDataStore* store, void* object, v8::Persistent<v8::Object> wrapper)
+ {
WrapperTypeInfo* typeInfo = V8DOMWrapper::domWrapperType(wrapper);
- if (V8HTMLLinkElement::info.equals(typeInfo)) {
- HTMLLinkElement* htmlLinkElement = static_cast<HTMLLinkElement*>(node);
- addDOMObjectToGroup(store, groupId, htmlLinkElement->sheet());
- }
+ if (typeInfo->isSubclass(&V8StyleSheetList::info)) {
+ StyleSheetList* styleSheetList = static_cast<StyleSheetList*>(object);
+ GroupId groupId(styleSheetList);
+ if (Document* document = styleSheetList->document())
+ groupId = GroupId(document);
+ m_grouper.append(GrouperItem(groupId, wrapper));
- if (V8HTMLStyleElement::info.equals(typeInfo)) {
- HTMLStyleElement* htmlStyleElement = static_cast<HTMLStyleElement*>(node);
- addDOMObjectToGroup(store, groupId, htmlStyleElement->sheet());
- }
+ } else if (typeInfo->isSubclass(&V8DOMImplementation::info)) {
+ DOMImplementation* domImplementation = static_cast<DOMImplementation*>(object);
+ GroupId groupId(domImplementation);
+ if (Document* document = domImplementation->ownerDocument())
+ groupId = GroupId(document);
+ m_grouper.append(GrouperItem(groupId, wrapper));
- if (V8ProcessingInstruction::info.equals(typeInfo)) {
- ProcessingInstruction* processingInstruction = static_cast<ProcessingInstruction*>(node);
- addDOMObjectToGroup(store, groupId, processingInstruction->sheet());
- }
- }
+ } else if (typeInfo->isSubclass(&V8StyleSheet::info) || typeInfo->isSubclass(&V8CSSRule::info)) {
+ m_grouper.append(GrouperItem(calculateGroupId(static_cast<StyleBase*>(object)), wrapper));
- void applyGrouping()
- {
- makeV8ObjectGroups(m_grouper);
- }
-
-private:
- GrouperList m_grouper;
+ } else if (typeInfo->isSubclass(&V8CSSStyleDeclaration::info)) {
+ CSSStyleDeclaration* cssStyleDeclaration = static_cast<CSSStyleDeclaration*>(object);
- void addDOMObjectToGroup(DOMDataStore* store, uintptr_t groupId, void* object)
- {
- if (!object)
- return;
- v8::Persistent<v8::Object> wrapper = store->domObjectMap().get(object);
- if (!wrapper.IsEmpty())
+ GroupId groupId = calculateGroupId(cssStyleDeclaration);
m_grouper.append(GrouperItem(groupId, wrapper));
- }
-};
-class DOMObjectGrouperVisitor : public DOMWrapperMap<void>::Visitor {
-public:
- DOMObjectGrouperVisitor()
- {
+ } else if (typeInfo->isSubclass(&V8CSSRuleList::info)) {
+ CSSRuleList* cssRuleList = static_cast<CSSRuleList*>(object);
+ GroupId groupId(cssRuleList);
+ StyleList* styleList = cssRuleList->styleList();
+ if (styleList)
+ groupId = calculateGroupId(styleList);
+ m_grouper.append(GrouperItem(groupId, wrapper));
+ }
}
- void startMap()
+ void applyGrouping()
{
- m_grouper.shrink(0);
- }
+ // Group by sorting by the group id.
+ std::sort(m_grouper.begin(), m_grouper.end());
+
+ for (size_t i = 0; i < m_grouper.size(); ) {
+ // Seek to the next key (or the end of the list).
+ size_t nextKeyIndex = m_grouper.size();
+ for (size_t j = i; j < m_grouper.size(); ++j) {
+ if (m_grouper[i].groupId() != m_grouper[j].groupId()) {
+ nextKeyIndex = j;
+ break;
+ }
+ }
- void endMap()
- {
- makeV8ObjectGroups(m_grouper);
- }
+ ASSERT(nextKeyIndex > i);
- void visitDOMWrapper(DOMDataStore* store, void* object, v8::Persistent<v8::Object> wrapper)
- {
- WrapperTypeInfo* typeInfo = V8DOMWrapper::domWrapperType(wrapper);
- // FIXME: extend WrapperTypeInfo with isStyle to simplify the check below or consider
- // adding a virtual method to WrapperTypeInfo which would know how to group objects.
- // FIXME: check if there are other StyleBase wrappers we should care of.
- if (V8CSSStyleSheet::info.equals(typeInfo)
- || V8CSSStyleDeclaration::info.equals(typeInfo)
- || V8CSSCharsetRule::info.equals(typeInfo)
- || V8CSSFontFaceRule::info.equals(typeInfo)
- || V8CSSStyleRule::info.equals(typeInfo)
- || V8CSSImportRule::info.equals(typeInfo)
- || V8CSSMediaRule::info.equals(typeInfo)) {
- StyleBase* styleBase = static_cast<StyleBase*>(object);
-
- // We put the whole tree of style elements into a single object group.
- // To achieve that we group elements by the roots of their trees.
- StyleBase* root = styleBase;
- ASSERT(root);
- while (true) {
- StyleBase* parent = root->parent();
- if (!parent)
- break;
- root = parent;
+ // We only care about a group if it has more than one object. If it only
+ // has one object, it has nothing else that needs to be kept alive.
+ if (nextKeyIndex - i <= 1) {
+ i = nextKeyIndex;
+ continue;
}
- // Group id is an address of the root.
- uintptr_t groupId = reinterpret_cast<uintptr_t>(root);
- m_grouper.append(GrouperItem(groupId, wrapper));
- if (V8CSSStyleDeclaration::info.equals(typeInfo)) {
- CSSStyleDeclaration* cssStyleDeclaration = static_cast<CSSStyleDeclaration*>(styleBase);
- if (cssStyleDeclaration->isMutableStyleDeclaration()) {
- CSSMutableStyleDeclaration* cssMutableStyleDeclaration = static_cast<CSSMutableStyleDeclaration*>(cssStyleDeclaration);
- CSSMutableStyleDeclaration::const_iterator end = cssMutableStyleDeclaration->end();
- for (CSSMutableStyleDeclaration::const_iterator it = cssMutableStyleDeclaration->begin(); it != end; ++it) {
- wrapper = store->domObjectMap().get(it->value());
- if (!wrapper.IsEmpty())
- m_grouper.append(GrouperItem(groupId, wrapper));
- }
- }
+ size_t rootIndex = i;
+
+ Vector<v8::Persistent<v8::Value> > group;
+ group.reserveCapacity(nextKeyIndex - i);
+ for (; i < nextKeyIndex; ++i) {
+ v8::Persistent<v8::Value> wrapper = m_grouper[i].wrapper();
+ if (!wrapper.IsEmpty())
+ group.append(wrapper);
}
- } else if (V8StyleSheetList::info.equals(typeInfo)) {
- addAllItems(store, static_cast<StyleSheetList*>(object), wrapper);
- } else if (V8CSSRuleList::info.equals(typeInfo)) {
- addAllItems(store, static_cast<CSSRuleList*>(object), wrapper);
+
+ if (group.size() > 1)
+ v8::V8::AddObjectGroup(&group[0], group.size(), m_grouper[rootIndex].createRetainedObjectInfo());
+
+ ASSERT(i == nextKeyIndex);
}
}
private:
GrouperList m_grouper;
-
- template <class C>
- void addAllItems(DOMDataStore* store, C* collection, v8::Persistent<v8::Object> wrapper)
- {
- uintptr_t groupId = reinterpret_cast<uintptr_t>(collection);
- m_grouper.append(GrouperItem(groupId, wrapper));
- for (unsigned i = 0; i < collection->length(); i++) {
- wrapper = store->domObjectMap().get(collection->item(i));
- if (!wrapper.IsEmpty())
- m_grouper.append(GrouperItem(groupId, wrapper));
- }
- }
};
// Create object groups for DOM tree nodes.
@@ -425,12 +430,10 @@ void V8GCController::gcPrologue()
visitActiveDOMObjectsInCurrentThread(&prologueVisitor);
// Create object groups.
- NodeGrouperVisitor nodeGrouperVisitor;
- visitDOMNodesInCurrentThread(&nodeGrouperVisitor);
- nodeGrouperVisitor.applyGrouping();
-
- DOMObjectGrouperVisitor domObjectGrouperVisitor;
- visitDOMObjectsInCurrentThread(&domObjectGrouperVisitor);
+ GrouperVisitor grouperVisitor;
+ visitDOMNodesInCurrentThread(&grouperVisitor);
+ visitDOMObjectsInCurrentThread(&grouperVisitor);
+ grouperVisitor.applyGrouping();
// Clean single element cache for string conversions.
lastStringImpl = 0;
diff --git a/Source/WebCore/bindings/v8/V8LazyEventListener.cpp b/Source/WebCore/bindings/v8/V8LazyEventListener.cpp
index 7f46333..0e2c368 100644
--- a/Source/WebCore/bindings/v8/V8LazyEventListener.cpp
+++ b/Source/WebCore/bindings/v8/V8LazyEventListener.cpp
@@ -31,6 +31,7 @@
#include "config.h"
#include "V8LazyEventListener.h"
+#include "ContentSecurityPolicy.h"
#include "Frame.h"
#include "V8Binding.h"
#include "V8HiddenPropertyName.h"
@@ -80,6 +81,9 @@ void V8LazyEventListener::prepareListenerObject(ScriptExecutionContext* context)
if (hasExistingListenerObject())
return;
+ if (context->isDocument() && !static_cast<Document*>(context)->contentSecurityPolicy()->allowInlineEventHandlers())
+ return;
+
v8::HandleScope handleScope;
V8Proxy* proxy = V8Proxy::retrieve(context);
diff --git a/Source/WebCore/bindings/v8/WorkerScriptDebugServer.cpp b/Source/WebCore/bindings/v8/WorkerScriptDebugServer.cpp
new file mode 100755
index 0000000..5e2acd2
--- /dev/null
+++ b/Source/WebCore/bindings/v8/WorkerScriptDebugServer.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011 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 "WorkerScriptDebugServer.h"
+
+#if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(WORKERS)
+
+#include "WorkerContext.h"
+
+namespace WebCore {
+
+WorkerScriptDebugServer::WorkerScriptDebugServer()
+ : ScriptDebugServer()
+{
+}
+
+void WorkerScriptDebugServer::addListener(ScriptDebugListener*, WorkerContext*)
+{
+}
+
+void WorkerScriptDebugServer::removeListener(ScriptDebugListener*, WorkerContext*)
+{
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(WORKERS)
diff --git a/Source/WebCore/bindings/v8/WorkerScriptDebugServer.h b/Source/WebCore/bindings/v8/WorkerScriptDebugServer.h
new file mode 100755
index 0000000..fdc47ac
--- /dev/null
+++ b/Source/WebCore/bindings/v8/WorkerScriptDebugServer.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2011 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 WorkerScriptDebugServer_h
+#define WorkerScriptDebugServer_h
+
+#if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(WORKERS)
+
+#include "ScriptDebugServer.h"
+
+namespace WebCore {
+
+class WorkerContext;
+
+class WorkerScriptDebugServer : public ScriptDebugServer {
+ WTF_MAKE_NONCOPYABLE(WorkerScriptDebugServer);
+public:
+ WorkerScriptDebugServer();
+ ~WorkerScriptDebugServer() { }
+
+ void addListener(ScriptDebugListener*, WorkerContext*);
+ void removeListener(ScriptDebugListener*, WorkerContext*);
+
+private:
+ virtual ScriptDebugListener* getDebugListenerForContext(v8::Handle<v8::Context>) { return 0; }
+ virtual void runMessageLoopOnPause(v8::Handle<v8::Context>) { }
+ virtual void quitMessageLoopOnPause() { }
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(WORKERS)
+
+#endif // WorkerScriptDebugServer_h
diff --git a/Source/WebCore/bindings/v8/WrapperTypeInfo.h b/Source/WebCore/bindings/v8/WrapperTypeInfo.h
index 1d1cbfd..166d642 100644
--- a/Source/WebCore/bindings/v8/WrapperTypeInfo.h
+++ b/Source/WebCore/bindings/v8/WrapperTypeInfo.h
@@ -41,7 +41,9 @@ namespace WebCore {
static const int v8DOMWrapperObjectIndex = 1;
static const int v8DOMHiddenReferenceArrayIndex = 2;
static const int v8DefaultWrapperInternalFieldCount = 3;
-
+
+ static const uint16_t v8DOMSubtreeClassId = 1;
+
typedef v8::Persistent<v8::FunctionTemplate> (*GetTemplateFunction)();
typedef void (*DerefObjectFunction)(void*);
typedef ActiveDOMObject* (*ToActiveDOMObjectFunction)(v8::Handle<v8::Object>);
@@ -61,6 +63,16 @@ namespace WebCore {
{
return this == that;
}
+
+ bool isSubclass(const WrapperTypeInfo* that) const
+ {
+ for (const WrapperTypeInfo* current = this; current; current = current->parentClass) {
+ if (current == that)
+ return true;
+ }
+
+ return false;
+ }
v8::Persistent<v8::FunctionTemplate> getTemplate() { return getTemplateFunction(); }
@@ -80,6 +92,7 @@ namespace WebCore {
const GetTemplateFunction getTemplateFunction;
const DerefObjectFunction derefObjectFunction;
const ToActiveDOMObjectFunction toActiveDOMObjectFunction;
+ const WrapperTypeInfo* parentClass;
};
}
diff --git a/Source/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp b/Source/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp
index 8fd2d62..52465b6 100644
--- a/Source/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp
+++ b/Source/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp
@@ -76,6 +76,9 @@ v8::Handle<v8::Value> V8HTMLCanvasElement::getContextCallback(const v8::Argument
v8::Handle<v8::String> premultipliedAlpha = v8::String::New("premultipliedAlpha");
if (jsAttrs->Has(premultipliedAlpha))
webGLAttrs->setPremultipliedAlpha(jsAttrs->Get(premultipliedAlpha)->BooleanValue());
+ v8::Handle<v8::String> preserveDrawingBuffer = v8::String::New("preserveDrawingBuffer");
+ if (jsAttrs->Has(preserveDrawingBuffer))
+ webGLAttrs->setPreserveDrawingBuffer(jsAttrs->Get(preserveDrawingBuffer)->BooleanValue());
}
}
#endif
diff --git a/Source/WebCore/bindings/v8/custom/V8IDBAnyCustom.cpp b/Source/WebCore/bindings/v8/custom/V8IDBAnyCustom.cpp
index ccd6fb2..a1a8636 100644
--- a/Source/WebCore/bindings/v8/custom/V8IDBAnyCustom.cpp
+++ b/Source/WebCore/bindings/v8/custom/V8IDBAnyCustom.cpp
@@ -77,6 +77,6 @@ v8::Handle<v8::Value> toV8(IDBAny* impl)
return v8::Undefined();
}
-#endif // ENABLE(INDEXED_DATABASE)
-
} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
diff --git a/Source/WebCore/bindings/v8/custom/V8IDBKeyCustom.cpp b/Source/WebCore/bindings/v8/custom/V8IDBKeyCustom.cpp
index 3805dca..b8fa6bb 100644
--- a/Source/WebCore/bindings/v8/custom/V8IDBKeyCustom.cpp
+++ b/Source/WebCore/bindings/v8/custom/V8IDBKeyCustom.cpp
@@ -56,6 +56,6 @@ v8::Handle<v8::Value> toV8(IDBKey* key)
return v8::Undefined();
}
-#endif // ENABLE(INDEXED_DATABASE)
-
} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
diff --git a/Source/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp b/Source/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp
index 7a33ed0..3dbacb2 100644
--- a/Source/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp
+++ b/Source/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2009 Google Inc. All rights reserved.
+ * Copyright (C) 2007-2011 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
@@ -31,27 +31,21 @@
#include "config.h"
#include "V8InjectedScriptHost.h"
-#include "DOMWindow.h"
#include "Database.h"
-#include "Frame.h"
#include "InjectedScript.h"
#include "InjectedScriptHost.h"
+#include "InspectorDebuggerAgent.h"
#include "InspectorValues.h"
-#include "Node.h"
-#include "Page.h"
#include "ScriptDebugServer.h"
#include "ScriptValue.h"
-
#include "V8Binding.h"
#include "V8BindingState.h"
-#include "V8DOMWindow.h"
#include "V8Database.h"
#include "V8HiddenPropertyName.h"
#include "V8JavaScriptCallFrame.h"
#include "V8Node.h"
#include "V8Proxy.h"
#include "V8Storage.h"
-#include <wtf/RefPtr.h>
namespace WebCore {
@@ -71,86 +65,6 @@ ScriptValue InjectedScriptHost::nodeAsScriptValue(ScriptState* state, Node* node
return ScriptValue(toV8(node));
}
-static void WeakReferenceCallback(v8::Persistent<v8::Value> object, void* parameter)
-{
- InjectedScriptHost* nativeObject = static_cast<InjectedScriptHost*>(parameter);
- nativeObject->deref();
- object.Dispose();
-}
-
-static v8::Local<v8::Object> createInjectedScriptHostV8Wrapper(InjectedScriptHost* host)
-{
- v8::Local<v8::Function> function = V8InjectedScriptHost::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>();
- }
- 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();
- v8::Persistent<v8::Object> weakHandle = v8::Persistent<v8::Object>::New(instance);
- weakHandle.MakeWeak(host, &WeakReferenceCallback);
- return instance;
-}
-
-ScriptObject InjectedScriptHost::createInjectedScript(const String& scriptSource, ScriptState* inspectedScriptState, long id)
-{
- v8::HandleScope scope;
-
- v8::Local<v8::Context> inspectedContext = inspectedScriptState->context();
- v8::Context::Scope contextScope(inspectedContext);
-
- // Call custom code to create InjectedScripHost wrapper specific for the context
- // 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(this);
- if (scriptHostWrapper.IsEmpty())
- return ScriptObject();
-
- v8::Local<v8::Object> windowGlobal = inspectedContext->Global();
-
- // Inject javascript into the context. The compiled script is supposed to evaluate into
- // a single anonymous function(it's anonymous to avoid cluttering the global object with
- // inspector's stuff) the function is called a few lines below with InjectedScriptHost wrapper,
- // injected script id and explicit reference to the inspected global object. The function is expected
- // to create and configure InjectedScript instance that is going to be used by the inspector.
- v8::Local<v8::Script> script = v8::Script::Compile(v8String(scriptSource));
- v8::Local<v8::Value> v = script->Run();
- ASSERT(!v.IsEmpty());
- ASSERT(v->IsFunction());
-
- v8::Handle<v8::Value> args[] = {
- scriptHostWrapper,
- windowGlobal,
- v8::Number::New(id),
- };
- v8::Local<v8::Value> injectedScriptValue = v8::Function::Cast(*v)->Call(windowGlobal, 3, args);
- v8::Local<v8::Object> injectedScript(v8::Object::Cast(*injectedScriptValue));
- return ScriptObject(inspectedScriptState, injectedScript);
-}
-
-void InjectedScriptHost::discardInjectedScript(ScriptState* inspectedScriptState)
-{
- v8::HandleScope handleScope;
- v8::Local<v8::Context> context = inspectedScriptState->context();
- v8::Context::Scope contextScope(context);
-
- v8::Local<v8::Object> global = context->Global();
- // Skip proxy object. The proxy object will survive page navigation while we need
- // an object whose lifetime consides with that of the inspected context.
- global = v8::Local<v8::Object>::Cast(global->GetPrototype());
-
- v8::Handle<v8::String> key = V8HiddenPropertyName::devtoolsInjectedScript();
- global->DeleteHiddenValue(key);
-}
-
v8::Handle<v8::Value> V8InjectedScriptHost::inspectedNodeCallback(const v8::Arguments& args)
{
INC_STATS("InjectedScriptHost.inspectedNode()");
@@ -185,9 +99,9 @@ v8::Handle<v8::Value> V8InjectedScriptHost::inspectCallback(const v8::Arguments&
return v8::Undefined();
InjectedScriptHost* host = V8InjectedScriptHost::toNative(args.Holder());
- ScriptValue objectId(args[0]);
+ ScriptValue object(args[0]);
ScriptValue hints(args[1]);
- host->inspectImpl(objectId.toInspectorValue(ScriptState::current()), hints.toInspectorValue(ScriptState::current()));
+ host->inspectImpl(object.toInspectorValue(ScriptState::current()), hints.toInspectorValue(ScriptState::current()));
return v8::Undefined();
}
@@ -196,7 +110,8 @@ v8::Handle<v8::Value> V8InjectedScriptHost::currentCallFrameCallback(const v8::A
{
#if ENABLE(JAVASCRIPT_DEBUGGER)
INC_STATS("InjectedScriptHost.currentCallFrame()");
- return toV8(ScriptDebugServer::shared().currentCallFrame());
+ InjectedScriptHost* host = V8InjectedScriptHost::toNative(args.Holder());
+ return toV8(host->debuggerAgent()->scriptDebugServer().currentCallFrame());
#else
UNUSED_PARAM(args);
return v8::Undefined();
@@ -231,46 +146,4 @@ v8::Handle<v8::Value> V8InjectedScriptHost::storageIdCallback(const v8::Argument
return v8::Undefined();
}
-InjectedScript InjectedScriptHost::injectedScriptFor(ScriptState* inspectedScriptState)
-{
- v8::HandleScope handleScope;
- v8::Local<v8::Context> context = inspectedScriptState->context();
- v8::Context::Scope contextScope(context);
-
- v8::Local<v8::Object> global = context->Global();
- // Skip proxy object. The proxy object will survive page navigation while we need
- // an object whose lifetime consides with that of the inspected context.
- global = v8::Local<v8::Object>::Cast(global->GetPrototype());
-
- v8::Handle<v8::String> key = V8HiddenPropertyName::devtoolsInjectedScript();
- v8::Local<v8::Value> val = global->GetHiddenValue(key);
- if (!val.IsEmpty() && val->IsObject())
- return InjectedScript(ScriptObject(inspectedScriptState, v8::Local<v8::Object>::Cast(val)));
-
- if (!canAccessInspectedWindow(inspectedScriptState))
- return InjectedScript();
-
- pair<long, ScriptObject> injectedScript = injectScript(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/Source/WebCore/bindings/v8/custom/V8InjectedScriptManager.cpp b/Source/WebCore/bindings/v8/custom/V8InjectedScriptManager.cpp
new file mode 100644
index 0000000..f4006b8
--- /dev/null
+++ b/Source/WebCore/bindings/v8/custom/V8InjectedScriptManager.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2007-2011 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 "InjectedScriptManager.h"
+
+#include "DOMWindow.h"
+#include "InjectedScript.h"
+#include "InjectedScriptHost.h"
+#include "ScriptValue.h"
+#include "V8Binding.h"
+#include "V8BindingState.h"
+#include "V8DOMWindow.h"
+#include "V8HiddenPropertyName.h"
+#include "V8InjectedScriptHost.h"
+#include "V8Proxy.h"
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+static void WeakReferenceCallback(v8::Persistent<v8::Value> object, void* parameter)
+{
+ InjectedScriptHost* nativeObject = static_cast<InjectedScriptHost*>(parameter);
+ nativeObject->deref();
+ object.Dispose();
+}
+
+static v8::Local<v8::Object> createInjectedScriptHostV8Wrapper(InjectedScriptHost* host)
+{
+ v8::Local<v8::Function> function = V8InjectedScriptHost::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>();
+ }
+ 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();
+ v8::Persistent<v8::Object> weakHandle = v8::Persistent<v8::Object>::New(instance);
+ weakHandle.MakeWeak(host, &WeakReferenceCallback);
+ return instance;
+}
+
+ScriptObject InjectedScriptManager::createInjectedScript(const String& scriptSource, ScriptState* inspectedScriptState, long id)
+{
+ v8::HandleScope scope;
+
+ v8::Local<v8::Context> inspectedContext = inspectedScriptState->context();
+ v8::Context::Scope contextScope(inspectedContext);
+
+ // Call custom code to create InjectedScripHost wrapper specific for the context
+ // 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(m_injectedScriptHost.get());
+ if (scriptHostWrapper.IsEmpty())
+ return ScriptObject();
+
+ v8::Local<v8::Object> windowGlobal = inspectedContext->Global();
+
+ // Inject javascript into the context. The compiled script is supposed to evaluate into
+ // a single anonymous function(it's anonymous to avoid cluttering the global object with
+ // inspector's stuff) the function is called a few lines below with InjectedScriptHost wrapper,
+ // injected script id and explicit reference to the inspected global object. The function is expected
+ // to create and configure InjectedScript instance that is going to be used by the inspector.
+ v8::Local<v8::Script> script = v8::Script::Compile(v8String(scriptSource));
+ v8::Local<v8::Value> v = script->Run();
+ ASSERT(!v.IsEmpty());
+ ASSERT(v->IsFunction());
+
+ v8::Handle<v8::Value> args[] = {
+ scriptHostWrapper,
+ windowGlobal,
+ v8::Number::New(id),
+ };
+ v8::Local<v8::Value> injectedScriptValue = v8::Function::Cast(*v)->Call(windowGlobal, 3, args);
+ v8::Local<v8::Object> injectedScript(v8::Object::Cast(*injectedScriptValue));
+ return ScriptObject(inspectedScriptState, injectedScript);
+}
+
+void InjectedScriptManager::discardInjectedScript(ScriptState* inspectedScriptState)
+{
+ v8::HandleScope handleScope;
+ v8::Local<v8::Context> context = inspectedScriptState->context();
+ v8::Context::Scope contextScope(context);
+
+ v8::Local<v8::Object> global = context->Global();
+ // Skip proxy object. The proxy object will survive page navigation while we need
+ // an object whose lifetime consides with that of the inspected context.
+ global = v8::Local<v8::Object>::Cast(global->GetPrototype());
+
+ v8::Handle<v8::String> key = V8HiddenPropertyName::devtoolsInjectedScript();
+ global->DeleteHiddenValue(key);
+}
+
+InjectedScript InjectedScriptManager::injectedScriptFor(ScriptState* inspectedScriptState)
+{
+ v8::HandleScope handleScope;
+ v8::Local<v8::Context> context = inspectedScriptState->context();
+ v8::Context::Scope contextScope(context);
+
+ v8::Local<v8::Object> global = context->Global();
+ // Skip proxy object. The proxy object will survive page navigation while we need
+ // an object whose lifetime consides with that of the inspected context.
+ global = v8::Local<v8::Object>::Cast(global->GetPrototype());
+
+ v8::Handle<v8::String> key = V8HiddenPropertyName::devtoolsInjectedScript();
+ v8::Local<v8::Value> val = global->GetHiddenValue(key);
+ if (!val.IsEmpty() && val->IsObject())
+ return InjectedScript(ScriptObject(inspectedScriptState, v8::Local<v8::Object>::Cast(val)));
+
+ if (!canAccessInspectedWindow(inspectedScriptState))
+ return InjectedScript();
+
+ pair<long, ScriptObject> injectedScript = injectScript(injectedScriptSource(), inspectedScriptState);
+ InjectedScript result(injectedScript.second);
+ m_idToInjectedScript.set(injectedScript.first, result);
+ global->SetHiddenValue(key, injectedScript.second.v8Object());
+ return result;
+}
+
+bool InjectedScriptManager::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/Source/WebCore/bindings/v8/custom/V8WebKitAnimationCustom.cpp b/Source/WebCore/bindings/v8/custom/V8WebKitAnimationCustom.cpp
new file mode 100644
index 0000000..c0949ae
--- /dev/null
+++ b/Source/WebCore/bindings/v8/custom/V8WebKitAnimationCustom.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * 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"
+#include "V8WebKitAnimation.h"
+
+#include "V8Binding.h"
+#include "V8BindingMacros.h"
+#include "V8Proxy.h"
+#include "WebKitAnimation.h"
+
+#include <v8.h>
+
+namespace WebCore {
+
+v8::Handle<v8::Value> V8WebKitAnimation::iterationCountAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
+{
+ INC_STATS("DOM.WebKitAnimation.iterationCount._get");
+ v8::Handle<v8::Object> holder = info.Holder();
+ WebKitAnimation* imp = V8WebKitAnimation::toNative(holder);
+ int count = imp->iterationCount();
+ if (count == Animation::IterationCountInfinite)
+ return v8::Number::New(std::numeric_limits<float>::infinity());
+ return v8::Number::New(count);
+}
+
+} // namespace WebCore
+