WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-79131-20120327165613.patch (text/plain), 46.29 KB, created by
Rafael Weinstein
on 2012-03-27 16:56:14 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Rafael Weinstein
Created:
2012-03-27 16:56:14 PDT
Size:
46.29 KB
patch
obsolete
>Subversion Revision: 112329 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 3c5b5ac938f18c3da603ed0473a44b0bdfef063d..e73fc11ce67c627cc6baca64722cdec3b54557eb 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,85 @@ >+2012-03-26 Rafael Weinstein <rafaelw@chromium.org> >+ >+ Use V8 completion callback API to assert that V8RecursionScope is on the stack whenever invoking script >+ https://bugs.webkit.org/show_bug.cgi?id=79131 >+ >+ End-of-microtask work (cancelling outstanding IDB transactions, >+ delivering DOM mutations) depend on V8RecursionScope being on the >+ stack whenever a call is made into script. V8 provides a completion >+ callback API that could be used to hook these "end-of-microtask" >+ events, but it turns out that WebKit calls into script for various >+ reasons besides running script from the page. For example, constructing >+ wrapper objects from function templates counts as "running script", >+ yet it's not appropriate to run this callback every time a JS wrapper >+ is constructed. >+ >+ Instead, this patch makes use of the V8 completion callback mechanism >+ only in debug mode, to assert that either a V8RecursionScope (when >+ calling author script) or a V8RecursionScope::BypassMicrotaskCheckpoint >+ (when calling non-author script) is on the stack when V8 thinks it's >+ finished executing script. This requires dropping BypassMicrotaskCheckpoint >+ objects in a bunch of places, most notably the Inspector. >+ Note that in release mode, this class does nothing and thus should be >+ optimized away. >+ >+ No new tests; existing tests cover this code (when run in debug mode). >+ >+ * Target.pri: >+ * WebCore.gypi: >+ * bindings/v8/DateExtension.cpp: >+ (WebCore::DateExtension::setAllowSleep): >+ * bindings/v8/PageScriptDebugServer.cpp: >+ (WebCore::PageScriptDebugServer::addListener): >+ * bindings/v8/SafeAllocation.h: Added. >+ (WebCore): >+ (SafeAllocation): >+ (WebCore::SafeAllocation::newInstance): >+ * bindings/v8/ScriptController.cpp: >+ (WebCore::ScriptController::collectGarbage): >+ * bindings/v8/ScriptDebugServer.cpp: >+ (WebCore::ScriptDebugServer::callDebuggerMethod): >+ (WebCore): >+ (WebCore::ScriptDebugServer::pauseOnExceptionsState): >+ (WebCore::ScriptDebugServer::setPauseOnExceptionsState): >+ (WebCore::ScriptDebugServer::stepIntoStatement): >+ (WebCore::ScriptDebugServer::stepOverStatement): >+ (WebCore::ScriptDebugServer::stepOutOfFunction): >+ (WebCore::ScriptDebugServer::setScriptSource): >+ (WebCore::ScriptDebugServer::currentCallFrame): >+ (WebCore::ScriptDebugServer::handleV8DebugEvent): >+ (WebCore::ScriptDebugServer::ensureDebuggerScriptCompiled): >+ * bindings/v8/ScriptDebugServer.h: >+ (ScriptDebugServer): >+ * bindings/v8/ScriptFunctionCall.cpp: >+ (WebCore::ScriptFunctionCall::call): >+ * bindings/v8/V8Binding.cpp: >+ (WebCore::V8BindingPerIsolateData::V8BindingPerIsolateData): >+ * bindings/v8/V8Binding.h: >+ (V8BindingPerIsolateData): >+ (WebCore::V8BindingPerIsolateData::internalScriptRecursionLevel): >+ (WebCore::V8BindingPerIsolateData::incrementInternalScriptRecursionLevel): >+ (WebCore::V8BindingPerIsolateData::decrementInternalScriptRecursionLevel): >+ * bindings/v8/V8DOMWindowShell.cpp: >+ * bindings/v8/V8DOMWrapper.cpp: >+ * bindings/v8/V8LazyEventListener.cpp: >+ (WebCore::V8LazyEventListener::prepareListenerObject): >+ * bindings/v8/V8NPObject.cpp: >+ * bindings/v8/V8RecursionScope.h: >+ (WebCore): >+ (WebCore::V8RecursionScope::recursionLevel): >+ (V8RecursionScope): >+ (WebCore::V8RecursionScope::properlyUsed): >+ (BypassFinalizationPhase): >+ (WebCore::V8RecursionScope::BypassFinalizationPhase::BypassFinalizationPhase): >+ (WebCore::V8RecursionScope::BypassFinalizationPhase::~BypassFinalizationPhase): >+ * bindings/v8/WorkerContextExecutionProxy.cpp: >+ * bindings/v8/custom/V8HTMLDocumentCustom.cpp: >+ (WebCore::V8HTMLDocument::WrapInShadowObject): >+ * bindings/v8/custom/V8InjectedScriptManager.cpp: >+ (WebCore::InjectedScriptManager::createInjectedScript): >+ * bindings/v8/custom/V8ScriptProfileCustom.cpp: >+ * bindings/v8/custom/V8ScriptProfileNodeCustom.cpp: >+ > 2012-03-27 Dirk Pranke <dpranke@chromium.org> > > Re-land r112277; reverting it doesn't seem to have fixed anything. >diff --git a/Source/WebKit/chromium/ChangeLog b/Source/WebKit/chromium/ChangeLog >index 98fff94eab31f0b02af8e682855c522fccdf52e3..eb236be21afd09d3457508b4b864d84807a991ad 100644 >--- a/Source/WebKit/chromium/ChangeLog >+++ b/Source/WebKit/chromium/ChangeLog >@@ -1,3 +1,37 @@ >+2012-03-26 Rafael Weinstein <rafaelw@chromium.org> >+ >+ Use V8 completion callback API to assert that V8RecursionScope is on the stack whenever invoking script >+ https://bugs.webkit.org/show_bug.cgi?id=79131 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * WebKit.gyp: >+ * public/WebFrame.h: >+ (v8): >+ (WebFrame): >+ * public/platform/WebScriptScope.h: Copied from Source/WebCore/bindings/v8/V8RecursionScope.h. >+ (WebKit): >+ (WebScriptScope): >+ (BypassFinalizationPhase): >+ * src/WebFrameImpl.cpp: >+ (WebKit): >+ (WebKit::WebFrameImpl::callFunctionAndReturnValue): >+ * src/WebFrameImpl.h: >+ (WebFrameImpl): >+ * src/WebKit.cpp: >+ (WebKit): >+ (WebKit::assertV8RecursionScope): >+ (WebKit::initialize): >+ (WebKit::shutdown): >+ * src/WebScriptScope.cpp: Copied from Source/WebCore/bindings/v8/V8RecursionScope.h. >+ (WebKit): >+ (WebScriptScope): >+ (BypassFinalizationPhase::Impl): >+ (WebKit::WebScriptScope::BypassFinalizationPhase::Impl::Impl): >+ (WebKit::WebScriptScope::BypassFinalizationPhase::Impl::~Impl): >+ (WebKit::WebScriptScope::BypassFinalizationPhase::BypassFinalizationPhase): >+ (WebKit::WebScriptScope::BypassFinalizationPhase::~BypassFinalizationPhase): >+ > 2012-03-27 Dana Jansens <danakj@chromium.org> > > [chromium] Rename opaqueContentsRegion() to visibleContentOpaqueRegion() >diff --git a/Source/WebCore/Target.pri b/Source/WebCore/Target.pri >index 513dc98443969a50695face6662f87e93202a92d..9473003753501fa1f20a096e32bc96426deb5d12 100644 >--- a/Source/WebCore/Target.pri >+++ b/Source/WebCore/Target.pri >@@ -1405,6 +1405,7 @@ v8 { > bindings/v8/PageScriptDebugServer.h \ > bindings/v8/RetainedDOMInfo.h \ > bindings/v8/RetainedObjectInfo.h \ >+ bindings/v8/SafeAllocation.h \ > bindings/v8/ScheduledAction.h \ > bindings/v8/ScopedDOMDataStore.h \ > bindings/v8/ScriptCachedFrameData.h \ >diff --git a/Source/WebCore/WebCore.gypi b/Source/WebCore/WebCore.gypi >index dd1421e47928eeb0f812160ca0edee2c7ce87a2f..5b45acd6321aaa3b694349c8c2f93ec7269839ea 100644 >--- a/Source/WebCore/WebCore.gypi >+++ b/Source/WebCore/WebCore.gypi >@@ -2064,6 +2064,7 @@ > 'bindings/v8/RetainedDOMInfo.cpp', > 'bindings/v8/RetainedDOMInfo.h', > 'bindings/v8/RetainedObjectInfo.h', >+ 'bindings/v8/SafeAllocation.h', > 'bindings/v8/ScheduledAction.cpp', > 'bindings/v8/ScheduledAction.h', > 'bindings/v8/ScopedDOMDataStore.cpp', >diff --git a/Source/WebCore/bindings/v8/DateExtension.cpp b/Source/WebCore/bindings/v8/DateExtension.cpp >index 332828b22a378d49ead0ade723fa7b84bb944eb8..b72ddebd0ec5759435914bee2222efd614d9a157 100644 >--- a/Source/WebCore/bindings/v8/DateExtension.cpp >+++ b/Source/WebCore/bindings/v8/DateExtension.cpp >@@ -31,8 +31,9 @@ > #include "config.h" > #include "DateExtension.h" > >-#include "V8Proxy.h" > #include "V8HiddenPropertyName.h" >+#include "V8Proxy.h" >+#include "V8RecursionScope.h" > > namespace WebCore { > >@@ -89,6 +90,7 @@ void DateExtension::setAllowSleep(bool allow) > > v8::Handle<v8::Value> argv[1]; > argv[0] = v8::Boolean::New(!allow); >+ V8RecursionScope::BypassMicrotaskCheckpoint scope; > v8::Handle<v8::Function>::Cast(sleepFunctionHandle)->Call(v8::Object::New(), 1, argv); > } > >diff --git a/Source/WebCore/bindings/v8/PageScriptDebugServer.cpp b/Source/WebCore/bindings/v8/PageScriptDebugServer.cpp >index 18f7df7ee4254010c1d716197a4bb4a6bf7c5096..be417e4c27a0da3f95e2f2b30084365a8b365df2 100755 >--- a/Source/WebCore/bindings/v8/PageScriptDebugServer.cpp >+++ b/Source/WebCore/bindings/v8/PageScriptDebugServer.cpp >@@ -39,6 +39,7 @@ > #include "V8Binding.h" > #include "V8DOMWindow.h" > #include "V8Proxy.h" >+#include "V8RecursionScope.h" > #include <wtf/OwnPtr.h> > #include <wtf/PassOwnPtr.h> > #include <wtf/StdLibExtras.h> >@@ -100,7 +101,11 @@ void PageScriptDebugServer::addListener(ScriptDebugListener* listener, Page* pag > 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); >+ v8::Handle<v8::Value> value; >+ { >+ V8RecursionScope::BypassMicrotaskCheckpoint scope; >+ value = getScriptsFunction->Call(m_debuggerScript.get(), 1, argv); >+ } > if (value.IsEmpty()) > return; > ASSERT(!value->IsUndefined() && value->IsArray()); >diff --git a/Source/WebCore/bindings/v8/SafeAllocation.h b/Source/WebCore/bindings/v8/SafeAllocation.h >new file mode 100644 >index 0000000000000000000000000000000000000000..4c7005d8ff92da3e716f4cc944bedc0d5cc702f8 >--- /dev/null >+++ b/Source/WebCore/bindings/v8/SafeAllocation.h >@@ -0,0 +1,77 @@ >+/* >+* Copyright (C) 2012 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 SafeAllocation_h >+#define SafeAllocation_h >+ >+#include "V8Binding.h" >+#include "V8RecursionScope.h" >+ >+#include <v8.h> >+ >+namespace WebCore { >+ >+class SafeAllocation { >+public: >+ static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::Function>); >+ static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::ObjectTemplate>); >+ static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[]); >+}; >+ >+v8::Local<v8::Object> SafeAllocation::newInstance(v8::Handle<v8::Function> function) >+{ >+ if (function.IsEmpty()) >+ return v8::Local<v8::Object>(); >+ ConstructorMode constructorMode; >+ V8RecursionScope::BypassMicrotaskCheckpoint scope; >+ return function->NewInstance(); >+} >+ >+v8::Local<v8::Object> SafeAllocation::newInstance(v8::Handle<v8::ObjectTemplate> objectTemplate) >+{ >+ if (objectTemplate.IsEmpty()) >+ return v8::Local<v8::Object>(); >+ ConstructorMode constructorMode; >+ V8RecursionScope::BypassMicrotaskCheckpoint scope; >+ return objectTemplate->NewInstance(); >+} >+ >+v8::Local<v8::Object> SafeAllocation::newInstance(v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[]) >+{ >+ if (function.IsEmpty()) >+ return v8::Local<v8::Object>(); >+ ConstructorMode constructorMode; >+ V8RecursionScope::BypassMicrotaskCheckpoint scope; >+ return function->NewInstance(argc, argv); >+} >+ >+} // namespace WebCore >+ >+#endif // SafeAllocation_h >diff --git a/Source/WebCore/bindings/v8/ScriptController.cpp b/Source/WebCore/bindings/v8/ScriptController.cpp >index 8de95537ad7f2cfd1af64f82e9dadfa8d27dc9dc..a0e3ef515f4d2a865b7d63b9528264516454df6a 100644 >--- a/Source/WebCore/bindings/v8/ScriptController.cpp >+++ b/Source/WebCore/bindings/v8/ScriptController.cpp >@@ -62,6 +62,7 @@ > #include "V8IsolatedContext.h" > #include "V8NPObject.h" > #include "V8Proxy.h" >+#include "V8RecursionScope.h" > #include "Widget.h" > #include <wtf/StdLibExtras.h> > #include <wtf/text/CString.h> >@@ -161,6 +162,15 @@ bool ScriptController::processingUserGesture() > return UserGestureIndicator::processingUserGesture(); > } > >+ScriptValue ScriptController::callFunction(v8::Handle<v8::Function> function, >+ v8::Handle<v8::Object> receiver, >+ int argc, >+ v8::Handle<v8::Value> argv[]) >+{ >+ // FIXME: This should probably perform the same checks to canExecuteScripts & isPaused that happen in ScriptController::executeScript. >+ return ScriptValue(m_proxy->callFunction(function, receiver, argc, argv)); >+} >+ > void ScriptController::evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>& sources) > { > m_proxy->evaluateInIsolatedWorld(worldID, sources, 0); >@@ -245,8 +255,10 @@ void ScriptController::collectGarbage() > v8::Local<v8::String> source = v8::String::New("if (gc) gc();"); > v8::Local<v8::String> name = v8::String::New("gc"); > v8::Handle<v8::Script> script = v8::Script::Compile(source, name); >- if (!script.IsEmpty()) >+ if (!script.IsEmpty()) { >+ V8RecursionScope::BypassMicrotaskCheckpoint scope; > script->Run(); >+ } > } > v8Context.Dispose(); > } >diff --git a/Source/WebCore/bindings/v8/ScriptController.h b/Source/WebCore/bindings/v8/ScriptController.h >index 9d2efdeb18edc52661ae98c8c680856f74c55d0a..fbe79b1acf9ffbb47f99e1d36bfd9531891cbe43 100644 >--- a/Source/WebCore/bindings/v8/ScriptController.h >+++ b/Source/WebCore/bindings/v8/ScriptController.h >@@ -73,6 +73,7 @@ public: > > ScriptValue executeScript(const ScriptSourceCode&); > ScriptValue executeScript(const String& script, bool forceUserGesture = false); >+ ScriptValue callFunction(v8::Handle<v8::Function>, v8::Handle<v8::Object>, int argc, v8::Handle<v8::Value> argv[]); > > // Returns true if argument is a JavaScript URL. > bool executeIfJavaScriptURL(const KURL&, ShouldReplaceDocumentIfJavaScriptURL shouldReplaceDocumentIfJavaScriptURL = ReplaceDocumentIfJavaScriptURL); >diff --git a/Source/WebCore/bindings/v8/ScriptDebugServer.cpp b/Source/WebCore/bindings/v8/ScriptDebugServer.cpp >index b705523b71f58b99f032f39b6a6504c810f0e5b5..5b7ece4d4a87ecf47e1fbb0e7a65f7ac817390e6 100644 >--- a/Source/WebCore/bindings/v8/ScriptDebugServer.cpp >+++ b/Source/WebCore/bindings/v8/ScriptDebugServer.cpp >@@ -39,6 +39,7 @@ > #include "ScriptObject.h" > #include "V8Binding.h" > #include "V8JavaScriptCallFrame.h" >+#include "V8RecursionScope.h" > #include <wtf/StdLibExtras.h> > #include <wtf/Vector.h> > >@@ -57,6 +58,13 @@ private: > > } > >+v8::Local<v8::Value> ScriptDebugServer::callDebuggerMethod(const char* functionName, int argc, v8::Handle<v8::Value> argv[]) >+{ >+ v8::Handle<v8::Function> function = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New(functionName))); >+ V8RecursionScope::BypassMicrotaskCheckpoint scope; >+ return function->Call(m_debuggerScript.get(), argc, argv); >+} >+ > ScriptDebugServer::ScriptDebugServer() > : m_pauseOnExceptionsState(DontPauseOnExceptions) > , m_breakpointsActivated(true) >@@ -129,9 +137,8 @@ ScriptDebugServer::PauseOnExceptionsState ScriptDebugServer::pauseOnExceptionsSt > v8::HandleScope scope; > v8::Context::Scope contextScope(v8::Debug::GetDebugContext()); > >- v8::Handle<v8::Function> function = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("pauseOnExceptionsState"))); > v8::Handle<v8::Value> argv[] = { v8::Handle<v8::Value>() }; >- v8::Handle<v8::Value> result = function->Call(m_debuggerScript.get(), 0, argv); >+ v8::Handle<v8::Value> result = callDebuggerMethod("pauseOnExceptionsState", 0, argv); > return static_cast<ScriptDebugServer::PauseOnExceptionsState>(result->Int32Value()); > } > >@@ -141,9 +148,8 @@ void ScriptDebugServer::setPauseOnExceptionsState(PauseOnExceptionsState pauseOn > v8::HandleScope scope; > v8::Context::Scope contextScope(v8::Debug::GetDebugContext()); > >- v8::Handle<v8::Function> setPauseOnExceptionsFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("setPauseOnExceptionsState"))); > v8::Handle<v8::Value> argv[] = { v8::Int32::New(pauseOnExceptionsState) }; >- setPauseOnExceptionsFunction->Call(m_debuggerScript.get(), 1, argv); >+ callDebuggerMethod("setPauseOnExceptionsState", 1, argv); > } > > void ScriptDebugServer::setPauseOnNextStatement(bool pause) >@@ -190,27 +196,24 @@ void ScriptDebugServer::continueProgram() > void ScriptDebugServer::stepIntoStatement() > { > 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); >+ callDebuggerMethod("stepIntoStatement", 1, argv); > continueProgram(); > } > > void ScriptDebugServer::stepOverStatement() > { > 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); >+ callDebuggerMethod("stepOverStatement", 1, argv); > continueProgram(); > } > > void ScriptDebugServer::stepOutOfFunction() > { > 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); >+ callDebuggerMethod("stepOutOfFunction", 1, argv); > continueProgram(); > } > >@@ -228,12 +231,11 @@ bool ScriptDebugServer::setScriptSource(const String& sourceID, const String& ne > if (!isPaused()) > contextScope = adoptPtr(new v8::Context::Scope(v8::Debug::GetDebugContext())); > >- v8::Handle<v8::Function> function = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("setScriptSource"))); > v8::Handle<v8::Value> argv[] = { v8String(sourceID), v8String(newContent), v8Boolean(preview) }; > > v8::TryCatch tryCatch; > tryCatch.SetVerbose(false); >- v8::Handle<v8::Value> v8result = function->Call(m_debuggerScript.get(), 3, argv); >+ v8::Local<v8::Value> v8result = callDebuggerMethod("setScriptSource", 3, argv); > if (tryCatch.HasCaught()) { > v8::Local<v8::Message> message = tryCatch.Message(); > if (!message.IsEmpty()) >@@ -255,9 +257,8 @@ bool ScriptDebugServer::setScriptSource(const String& sourceID, const String& ne > ScriptValue ScriptDebugServer::currentCallFrame() > { > ASSERT(isPaused()); >- 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> currentCallFrameV8 = currentCallFrameFunction->Call(m_debuggerScript.get(), 1, argv); >+ v8::Handle<v8::Value> currentCallFrameV8 = callDebuggerMethod("currentCallFrame", 1, argv); > > ASSERT(!currentCallFrameV8.IsEmpty()); > if (!currentCallFrameV8->IsObject()) >@@ -355,6 +356,7 @@ void ScriptDebugServer::handleV8DebugEvent(const v8::Debug::EventDetails& eventD > v8::Handle<v8::Value> exceptionGetterValue = eventData->Get(v8::String::New("exception")); > ASSERT(!exceptionGetterValue.IsEmpty() && exceptionGetterValue->IsFunction()); > v8::Handle<v8::Value> argv[] = { v8::Handle<v8::Value>() }; >+ V8RecursionScope::BypassMicrotaskCheckpoint scope; > exception = v8::Handle<v8::Function>::Cast(exceptionGetterValue)->Call(eventData, 0, argv); > } > >@@ -389,6 +391,7 @@ void ScriptDebugServer::ensureDebuggerScriptCompiled() > v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); > v8::Context::Scope contextScope(debuggerContext); > String debuggerScriptSource(reinterpret_cast<const char*>(DebuggerScriptSource_js), sizeof(DebuggerScriptSource_js)); >+ V8RecursionScope::BypassMicrotaskCheckpoint recursionScope; > m_debuggerScript.set(v8::Handle<v8::Object>::Cast(v8::Script::Compile(v8String(debuggerScriptSource))->Run())); > } > } >diff --git a/Source/WebCore/bindings/v8/ScriptDebugServer.h b/Source/WebCore/bindings/v8/ScriptDebugServer.h >index de846514011e1751fd77d20f9d74a25a0836be7c..a4fb6129de0e40befabb0187a8a78545180b708f 100644 >--- a/Source/WebCore/bindings/v8/ScriptDebugServer.h >+++ b/Source/WebCore/bindings/v8/ScriptDebugServer.h >@@ -113,7 +113,9 @@ protected: > void dispatchDidParseSource(ScriptDebugListener* listener, v8::Handle<v8::Object> sourceObject); > > void ensureDebuggerScriptCompiled(); >- >+ >+ v8::Local<v8::Value> callDebuggerMethod(const char* functionName, int argc, v8::Handle<v8::Value> argv[]); >+ > PauseOnExceptionsState m_pauseOnExceptionsState; > OwnHandle<v8::Object> m_debuggerScript; > OwnHandle<v8::Object> m_executionState; >diff --git a/Source/WebCore/bindings/v8/ScriptFunctionCall.cpp b/Source/WebCore/bindings/v8/ScriptFunctionCall.cpp >index 5c96b564e134209cd5ca2d5db4ebe9f9c506153c..f5110870a62b9194d2e2c3a47aba1c9aec6bd259 100644 >--- a/Source/WebCore/bindings/v8/ScriptFunctionCall.cpp >+++ b/Source/WebCore/bindings/v8/ScriptFunctionCall.cpp >@@ -31,12 +31,13 @@ > #include "config.h" > #include "ScriptFunctionCall.h" > >+#include "SafeAllocation.h" > #include "ScriptScope.h" > #include "ScriptState.h" > #include "ScriptValue.h" >- > #include "V8Binding.h" > #include "V8Proxy.h" >+#include "V8RecursionScope.h" > #include "V8Utilities.h" > > #include <v8.h> >@@ -130,7 +131,11 @@ ScriptValue ScriptFunctionCall::call(bool& hadException, bool reportExceptions) > for (size_t i = 0; i < m_arguments.size(); ++i) > args[i] = m_arguments[i].v8Value(); > >- v8::Local<v8::Value> result = function->Call(thisObject, m_arguments.size(), args.get()); >+ v8::Local<v8::Value> result; >+ { >+ V8RecursionScope recursionScope(getScriptExecutionContext()); >+ result = function->Call(thisObject, m_arguments.size(), args.get()); >+ } > if (!scope.success()) { > hadException = true; > return ScriptValue(); >diff --git a/Source/WebCore/bindings/v8/V8Binding.cpp b/Source/WebCore/bindings/v8/V8Binding.cpp >index 798676e1ee69e85a738b453252494813d5c268e7..f7dbe05918efc83e27759f913c1ffd457766cf4f 100644 >--- a/Source/WebCore/bindings/v8/V8Binding.cpp >+++ b/Source/WebCore/bindings/v8/V8Binding.cpp >@@ -56,6 +56,9 @@ V8BindingPerIsolateData::V8BindingPerIsolateData(v8::Isolate* isolate) > : m_domDataStore(0) > , m_constructorMode(ConstructorMode::CreateNewObject) > , m_recursionLevel(0) >+#ifndef NDEBUG >+ , m_internalScriptRecursionLevel(0) >+#endif > { > } > >diff --git a/Source/WebCore/bindings/v8/V8Binding.h b/Source/WebCore/bindings/v8/V8Binding.h >index bacd7e9aa26f3f7486ce78bd18c0458e87a069f5..e59cdd64f7675a43d6dc9ad408c24aa254ba7ae2 100644 >--- a/Source/WebCore/bindings/v8/V8Binding.h >+++ b/Source/WebCore/bindings/v8/V8Binding.h >@@ -153,6 +153,10 @@ namespace WebCore { > > #ifndef NDEBUG > GlobalHandleMap& globalHandleMap() { return m_globalHandleMap; } >+ >+ int internalScriptRecursionLevel() const { return m_internalScriptRecursionLevel; } >+ int incrementInternalScriptRecursionLevel() { return ++m_internalScriptRecursionLevel; } >+ int decrementInternalScriptRecursionLevel() { return --m_internalScriptRecursionLevel; } > #endif > > private: >@@ -179,6 +183,7 @@ namespace WebCore { > > #ifndef NDEBUG > GlobalHandleMap m_globalHandleMap; >+ int m_internalScriptRecursionLevel; > #endif > }; > >@@ -208,38 +213,6 @@ namespace WebCore { > bool m_previous; > }; > >- class SafeAllocation { >- public: >- static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::Function>); >- static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::ObjectTemplate>); >- static inline v8::Local<v8::Object> newInstance(v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[]); >- }; >- >- v8::Local<v8::Object> SafeAllocation::newInstance(v8::Handle<v8::Function> function) >- { >- if (function.IsEmpty()) >- return v8::Local<v8::Object>(); >- ConstructorMode constructorMode; >- return function->NewInstance(); >- } >- >- v8::Local<v8::Object> SafeAllocation::newInstance(v8::Handle<v8::ObjectTemplate> objectTemplate) >- { >- if (objectTemplate.IsEmpty()) >- return v8::Local<v8::Object>(); >- ConstructorMode constructorMode; >- return objectTemplate->NewInstance(); >- } >- >- v8::Local<v8::Object> SafeAllocation::newInstance(v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[]) >- { >- if (function.IsEmpty()) >- return v8::Local<v8::Object>(); >- ConstructorMode constructorMode; >- return function->NewInstance(argc, argv); >- } >- >- > > enum ExternalMode { > Externalize, >diff --git a/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp b/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp >index c4c60540ab9b68a693cdb6fc1e77ff094c4341a5..b7e3ad49c5deb0d3b4689e9acd4a63e4284a9a0c 100644 >--- a/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp >+++ b/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp >@@ -39,6 +39,7 @@ > #include "Page.h" > #include "PageGroup.h" > #include "RuntimeEnabledFeatures.h" >+#include "SafeAllocation.h" > #include "ScriptCallStack.h" > #include "ScriptCallStackFactory.h" > #include "ScriptProfiler.h" >diff --git a/Source/WebCore/bindings/v8/V8DOMWrapper.cpp b/Source/WebCore/bindings/v8/V8DOMWrapper.cpp >index 05dc181b95e71377084982780e0023bac52a9dfb..22f225c2318abd326d3939fce4b38aed6173e5f6 100644 >--- a/Source/WebCore/bindings/v8/V8DOMWrapper.cpp >+++ b/Source/WebCore/bindings/v8/V8DOMWrapper.cpp >@@ -37,6 +37,7 @@ > #include "EventTargetInterfaces.h" > #include "FrameLoaderClient.h" > #include "SVGElementInstance.h" >+#include "SafeAllocation.h" > #include "StylePropertySet.h" > #include "V8AbstractEventListener.h" > #include "V8Binding.h" >diff --git a/Source/WebCore/bindings/v8/V8LazyEventListener.cpp b/Source/WebCore/bindings/v8/V8LazyEventListener.cpp >index 6163eaa9587e3f9b1aaacb8aa9c9c0caccf0cf3a..de4992cfb66a2f147c0cda5fa337d0c9d4636a85 100644 >--- a/Source/WebCore/bindings/v8/V8LazyEventListener.cpp >+++ b/Source/WebCore/bindings/v8/V8LazyEventListener.cpp >@@ -44,6 +44,7 @@ > #include "V8HiddenPropertyName.h" > #include "V8Node.h" > #include "V8Proxy.h" >+#include "V8RecursionScope.h" > #include "WorldContextHandle.h" > > #include <wtf/StdLibExtras.h> >@@ -155,9 +156,12 @@ void V8LazyEventListener::prepareListenerObject(ScriptExecutionContext* context) > if (script.IsEmpty()) > return; > >- // Call v8::Script::Run() directly to avoid an erroneous call to V8RecursionScope::didLeaveScriptContext(). > // FIXME: Remove this code when we stop doing the 'with' hack above. >- v8::Local<v8::Value> value = script->Run(); >+ v8::Local<v8::Value> value; >+ { >+ V8RecursionScope::BypassMicrotaskCheckpoint scope; >+ value = script->Run(); >+ } > if (value.IsEmpty()) > return; > >@@ -174,10 +178,12 @@ void V8LazyEventListener::prepareListenerObject(ScriptExecutionContext* context) > > v8::Handle<v8::Value> parameters[3] = { nodeWrapper, formWrapper, documentWrapper }; > >- // Use Call directly to avoid an erroneous call to V8RecursionScope::didLeaveScriptContext(). > // FIXME: Remove this code when we stop doing the 'with' hack above. >- v8::Local<v8::Value> innerValue = intermediateFunction->Call(v8Context->Global(), 3, parameters); >- >+ v8::Local<v8::Value> innerValue; >+ { >+ V8RecursionScope::BypassMicrotaskCheckpoint scope; >+ innerValue = intermediateFunction->Call(v8Context->Global(), 3, parameters); >+ } > if (innerValue.IsEmpty() || !innerValue->IsFunction()) > return; > >diff --git a/Source/WebCore/bindings/v8/V8NPObject.cpp b/Source/WebCore/bindings/v8/V8NPObject.cpp >index e43d27e6409dee25a8aee726970a47e526005d34..f6dd1f8f36f4f788c11d99520dbab3c2e4038d06 100644 >--- a/Source/WebCore/bindings/v8/V8NPObject.cpp >+++ b/Source/WebCore/bindings/v8/V8NPObject.cpp >@@ -34,6 +34,7 @@ > > #include "HTMLPlugInElement.h" > #include "NPV8Object.h" >+#include "SafeAllocation.h" > #include "V8Binding.h" > #include "V8DOMMap.h" > #include "V8HTMLAppletElement.h" >diff --git a/Source/WebCore/bindings/v8/V8RecursionScope.h b/Source/WebCore/bindings/v8/V8RecursionScope.h >index 3b9ad6ec11d084e7b10fe954e5cc52f5687f2f88..5d8237c061f75f80f5fa224d4cfb33a81efd2983 100644 >--- a/Source/WebCore/bindings/v8/V8RecursionScope.h >+++ b/Source/WebCore/bindings/v8/V8RecursionScope.h >@@ -33,9 +33,27 @@ > > #include "ScriptExecutionContext.h" > #include "V8Binding.h" >+#include <wtf/Noncopyable.h> > > namespace WebCore { > >+// C++ Calls into script contexts which are "owned" by WebKit (initialized in >+// WebKit.cpp) must declare their type: >+// >+// 1. Calls into page/author script from a frame >+// 2. Calls into page/author script from a worker >+// 3. Calls into internal script (typically setup/teardown work) >+// >+// Debug-time checking of this is enforced via this class. >+// >+// Calls of type (1) should generally go through V8Proxy, as inspector >+// instrumentation is needed. Calls of type (2) should always stack-allocate a >+// V8RecursionScope in the same block as the call into script. Calls of type (3) >+// should stack allocate a V8RecursionScope::BypassMicrotaskCheckpoint -- this >+// skips work that is spec'd to happen at the end of the outer-most script stack >+// frame of calls into page script: >+// >+// http://www.whatwg.org/specs/web-apps/current-work/#perform-a-microtask-checkpoint > class V8RecursionScope { > WTF_MAKE_NONCOPYABLE(V8RecursionScope); > public: >@@ -51,7 +69,34 @@ public: > didLeaveScriptContext(); > } > >- static int recursionLevel() { return V8BindingPerIsolateData::current()->recursionLevel(); } >+ static int recursionLevel() >+ { >+ return V8BindingPerIsolateData::current()->recursionLevel(); >+ } >+ >+#ifndef NDEBUG >+ static bool properlyUsed() >+ { >+ return recursionLevel() > 0 || V8BindingPerIsolateData::current()->internalScriptRecursionLevel() > 0; >+ } >+#endif >+ >+ class BypassMicrotaskCheckpoint { >+ public: >+ BypassMicrotaskCheckpoint() >+ { >+#ifndef NDEBUG >+ V8BindingPerIsolateData::current()->incrementInternalScriptRecursionLevel(); >+#endif >+ } >+ >+ ~BypassMicrotaskCheckpoint() >+ { >+#ifndef NDEBUG >+ V8BindingPerIsolateData::current()->decrementInternalScriptRecursionLevel(); >+#endif >+ } >+ }; > > private: > void didLeaveScriptContext(); >diff --git a/Source/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp b/Source/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp >index bf8d2b339cc15d16384e05a579757608a6e63a09..f82bdd07f9ec10fa3cac2b296e2d835291f8dd7e 100644 >--- a/Source/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp >+++ b/Source/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp >@@ -37,6 +37,7 @@ > > #include "DedicatedWorkerContext.h" > #include "Event.h" >+#include "SafeAllocation.h" > #include "ScriptCallStack.h" > #include "SharedWorker.h" > #include "SharedWorkerContext.h" >diff --git a/Source/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp b/Source/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp >index 41ae0717155e517d090609c91c954161d6b3e647..cae668970029adc7cccf69f727f2d9d239969f01 100644 >--- a/Source/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp >+++ b/Source/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp >@@ -44,6 +44,7 @@ > #include "V8IsolatedContext.h" > #include "V8Node.h" > #include "V8Proxy.h" >+#include "V8RecursionScope.h" > #include <wtf/OwnArrayPtr.h> > #include <wtf/RefPtr.h> > #include <wtf/StdLibExtras.h> >@@ -66,7 +67,11 @@ v8::Local<v8::Object> V8HTMLDocument::WrapInShadowObject(v8::Local<v8::Object> w > if (shadowConstructor.IsEmpty()) > return v8::Local<v8::Object>(); > >- v8::Local<v8::Object> shadow = shadowConstructor->NewInstance(); >+ v8::Local<v8::Object> shadow; >+ { >+ V8RecursionScope::BypassMicrotaskCheckpoint scope; >+ shadow = shadowConstructor->NewInstance(); >+ } > if (shadow.IsEmpty()) > return v8::Local<v8::Object>(); > V8DOMWrapper::setDOMWrapper(shadow, &V8HTMLDocument::info, impl); >diff --git a/Source/WebCore/bindings/v8/custom/V8InjectedScriptManager.cpp b/Source/WebCore/bindings/v8/custom/V8InjectedScriptManager.cpp >index 8bb4281e3882b2420bce13fedf614779f765c8a3..ad5fb9d01bbb62ba8d569f5a6b8bc819bc1e9564 100644 >--- a/Source/WebCore/bindings/v8/custom/V8InjectedScriptManager.cpp >+++ b/Source/WebCore/bindings/v8/custom/V8InjectedScriptManager.cpp >@@ -34,6 +34,7 @@ > #include "DOMWindow.h" > #include "InjectedScript.h" > #include "InjectedScriptHost.h" >+#include "SafeAllocation.h" > #include "ScriptValue.h" > #include "V8Binding.h" > #include "V8BindingState.h" >@@ -41,6 +42,7 @@ > #include "V8HiddenPropertyName.h" > #include "V8InjectedScriptHost.h" > #include "V8Proxy.h" >+#include "V8RecursionScope.h" > #include <wtf/RefPtr.h> > > namespace WebCore { >@@ -96,6 +98,7 @@ ScriptObject InjectedScriptManager::createInjectedScript(const String& scriptSou > // 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)); >+ V8RecursionScope::BypassMicrotaskCheckpoint recursionScope; > v8::Local<v8::Value> v = script->Run(); > ASSERT(!v.IsEmpty()); > ASSERT(v->IsFunction()); >diff --git a/Source/WebCore/bindings/v8/custom/V8ScriptProfileCustom.cpp b/Source/WebCore/bindings/v8/custom/V8ScriptProfileCustom.cpp >index 32d87268cab7ecbc3e370326b9393ef96045932a..642185501626fd2e9cf7d32ac2bfe3afbb3f613b 100644 >--- a/Source/WebCore/bindings/v8/custom/V8ScriptProfileCustom.cpp >+++ b/Source/WebCore/bindings/v8/custom/V8ScriptProfileCustom.cpp >@@ -32,6 +32,7 @@ > #if ENABLE(JAVASCRIPT_DEBUGGER) > #include "V8ScriptProfile.h" > >+#include "SafeAllocation.h" > #include "ScriptProfile.h" > #include "V8Binding.h" > #include "V8Proxy.h" >diff --git a/Source/WebCore/bindings/v8/custom/V8ScriptProfileNodeCustom.cpp b/Source/WebCore/bindings/v8/custom/V8ScriptProfileNodeCustom.cpp >index c13400efe2fb32697ad23d936e38389724456d78..78d9210bd1e259ecc01661843f600568653380f4 100644 >--- a/Source/WebCore/bindings/v8/custom/V8ScriptProfileNodeCustom.cpp >+++ b/Source/WebCore/bindings/v8/custom/V8ScriptProfileNodeCustom.cpp >@@ -32,6 +32,7 @@ > #if ENABLE(JAVASCRIPT_DEBUGGER) > #include "V8ScriptProfileNode.h" > >+#include "SafeAllocation.h" > #include "ScriptProfileNode.h" > #include "V8Binding.h" > #include "V8Proxy.h" >diff --git a/Source/WebKit/chromium/WebKit.gyp b/Source/WebKit/chromium/WebKit.gyp >index b4db3e4ab5238674f0fcb1d7c59edfcaac784a06..adcdf552103d6ff17885ae694c156a24944e00b5 100644 >--- a/Source/WebKit/chromium/WebKit.gyp >+++ b/Source/WebKit/chromium/WebKit.gyp >@@ -240,6 +240,7 @@ > 'public/WebScopedUserGesture.h', > 'public/WebScreenInfo.h', > 'public/WebScriptController.h', >+ 'public/WebScriptInvocation.h', > 'public/WebScriptSource.h', > 'public/WebScrollbar.h', > 'public/WebScrollbarClient.h', >@@ -644,6 +645,7 @@ > 'src/WebRuntimeFeatures.cpp', > 'src/WebScopedUserGesture.cpp', > 'src/WebScriptController.cpp', >+ 'src/WebScriptInvocation.cpp', > 'src/WebScrollbarImpl.cpp', > 'src/WebScrollbarImpl.h', > 'src/WebSearchableFormData.cpp', >diff --git a/Source/WebKit/chromium/public/WebFrame.h b/Source/WebKit/chromium/public/WebFrame.h >index 0d5406d520682c9501546b4082532850955f6be5..b496beef52288384a3dae1b63cf6c5ec4aa93f7a 100644 >--- a/Source/WebKit/chromium/public/WebFrame.h >+++ b/Source/WebKit/chromium/public/WebFrame.h >@@ -44,6 +44,8 @@ struct NPObject; > #if WEBKIT_USING_V8 > namespace v8 { > class Context; >+class Function; >+class Object; > class Value; > template <class T> class Handle; > template <class T> class Local; >@@ -274,6 +276,13 @@ public: > virtual v8::Handle<v8::Value> executeScriptAndReturnValue( > const WebScriptSource&) = 0; > >+ // Call the function with the given receiver and arguments. >+ virtual v8::Handle<v8::Value> callFunctionAndReturnValue( >+ v8::Handle<v8::Function>, >+ v8::Handle<v8::Object>, >+ int argc, >+ v8::Handle<v8::Value> argv[]) = 0; >+ > // Returns the V8 context for this frame, or an empty handle if there > // is none. > virtual v8::Local<v8::Context> mainWorldScriptContext() const = 0; >diff --git a/Source/WebKit/chromium/public/WebScriptInvocation.h b/Source/WebKit/chromium/public/WebScriptInvocation.h >new file mode 100644 >index 0000000000000000000000000000000000000000..f34d1c48e42de6bfca28d5d1aa37e3a9d3353370 >--- /dev/null >+++ b/Source/WebKit/chromium/public/WebScriptInvocation.h >@@ -0,0 +1,54 @@ >+/* >+ * Copyright (C) 2009 Google Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions are >+ * met: >+ * >+ * * Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * * Redistributions in binary form must reproduce the above >+ * copyright notice, this list of conditions and the following disclaimer >+ * in the documentation and/or other materials provided with the >+ * distribution. >+ * * Neither the name of Google Inc. nor the names of its >+ * contributors may be used to endorse or promote products derived from >+ * this software without specific prior written permission. >+ * >+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS >+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT >+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR >+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT >+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, >+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT >+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, >+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY >+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#ifndef WebScriptInvocation_h >+#define WebScriptInvocation_h >+ >+namespace WebKit { >+ >+namespace WebScriptInvocation { >+ >+class BypassMicrotaskCheckpoint { >+public: >+ BypassMicrotaskCheckpoint(); >+ ~BypassMicrotaskCheckpoint(); >+ >+private: >+#ifndef NDEBUG >+ class Impl; >+ Impl* m_impl; >+#endif >+}; >+ >+} >+ >+} // WebKit >+ >+#endif >diff --git a/Source/WebKit/chromium/src/WebFrameImpl.cpp b/Source/WebKit/chromium/src/WebFrameImpl.cpp >index 39897c82362a832cbe2f1c9c12538daaa2a768b1..e7f7f9c8e0f824ed3c827459eb0988323768a371 100644 >--- a/Source/WebKit/chromium/src/WebFrameImpl.cpp >+++ b/Source/WebKit/chromium/src/WebFrameImpl.cpp >@@ -894,6 +894,15 @@ v8::Handle<v8::Value> WebFrameImpl::executeScriptAndReturnValue(const WebScriptS > return m_frame->script()->executeScript(ScriptSourceCode(source.code, source.url, position)).v8Value(); > } > >+// Call the function with the given receiver and arguments. >+v8::Handle<v8::Value> WebFrameImpl::callFunctionAndReturnValue(v8::Handle<v8::Function> function, >+ v8::Handle<v8::Object> receiver, >+ int argc, >+ v8::Handle<v8::Value> argv[]) >+{ >+ return m_frame->script()->callFunction(function, receiver, argc, argv).v8Value(); >+} >+ > // Returns the V8 context for this frame, or an empty handle if there is none. > v8::Local<v8::Context> WebFrameImpl::mainWorldScriptContext() const > { >diff --git a/Source/WebKit/chromium/src/WebFrameImpl.h b/Source/WebKit/chromium/src/WebFrameImpl.h >index 700f6ea4037e7b28b90bdc8f94994c8aee9a31f2..01de74f0593df93d9bdf9438a59c13458e8a8a2b 100644 >--- a/Source/WebKit/chromium/src/WebFrameImpl.h >+++ b/Source/WebKit/chromium/src/WebFrameImpl.h >@@ -110,6 +110,11 @@ public: > #if WEBKIT_USING_V8 > virtual v8::Handle<v8::Value> executeScriptAndReturnValue( > const WebScriptSource&); >+ virtual v8::Handle<v8::Value> callFunctionAndReturnValue( >+ v8::Handle<v8::Function>, >+ v8::Handle<v8::Object>, >+ int argc, >+ v8::Handle<v8::Value> argv[]); > virtual v8::Local<v8::Context> mainWorldScriptContext() const; > virtual v8::Handle<v8::Value> createFileSystem(WebFileSystem::Type, > const WebString& name, >diff --git a/Source/WebKit/chromium/src/WebKit.cpp b/Source/WebKit/chromium/src/WebKit.cpp >index 77858c4e7b9701a7f92d94a2c0a3abfb46f0ee25..2476c79ced95f21ec9a2fe1b66733cb8293645df 100644 >--- a/Source/WebKit/chromium/src/WebKit.cpp >+++ b/Source/WebKit/chromium/src/WebKit.cpp >@@ -37,6 +37,7 @@ > #include "Settings.h" > #include "TextEncoding.h" > #include "V8Binding.h" >+#include "V8RecursionScope.h" > #include "WebKitMutationObserver.h" > #include "platform/WebKitPlatformSupport.h" > #include "WebMediaPlayerClientImpl.h" >@@ -88,6 +89,14 @@ static bool generateEntropy(unsigned char* buffer, size_t length) > return false; > } > >+#ifndef NDEBUG >+static void assertV8RecursionScope() >+{ >+ // FIXME: Enable when chromium usage of WebScriptInvocation has landed. >+ // ASSERT(!isMainThread() || WebCore::V8RecursionScope::properlyUsed()); >+} >+#endif >+ > void initialize(WebKitPlatformSupport* webKitPlatformSupport) > { > initializeWithoutV8(webKitPlatformSupport); >@@ -97,6 +106,10 @@ void initialize(WebKitPlatformSupport* webKitPlatformSupport) > WebCore::V8BindingPerIsolateData::ensureInitialized(v8::Isolate::GetCurrent()); > > #if ENABLE(MUTATION_OBSERVERS) >+#ifndef NDEBUG >+ v8::V8::AddCallCompletedCallback(&assertV8RecursionScope); >+#endif >+ > // currentThread will always be non-null in production, but can be null in Chromium unit tests. > if (WebThread* currentThread = webKitPlatformSupport->currentThread()) { > ASSERT(!s_endOfTaskRunner); >@@ -137,6 +150,10 @@ void initializeWithoutV8(WebKitPlatformSupport* webKitPlatformSupport) > void shutdown() > { > #if ENABLE(MUTATION_OBSERVERS) >+#ifndef NDEBUG >+ v8::V8::RemoveCallCompletedCallback(&assertV8RecursionScope); >+#endif >+ > if (s_endOfTaskRunner) { > ASSERT(s_webKitPlatformSupport->currentThread()); > s_webKitPlatformSupport->currentThread()->removeTaskObserver(s_endOfTaskRunner); >diff --git a/Source/WebKit/chromium/src/WebScriptInvocation.cpp b/Source/WebKit/chromium/src/WebScriptInvocation.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..6877f4f3e679eecbc43193b054fcca53e9394353 >--- /dev/null >+++ b/Source/WebKit/chromium/src/WebScriptInvocation.cpp >@@ -0,0 +1,66 @@ >+/* >+ * 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 "WebScriptInvocation.h" >+ >+#include "V8RecursionScope.h" >+#include <wtf/OwnPtr.h> >+ >+namespace WebKit { >+ >+namespace WebScriptInvocation { >+ >+#ifndef NDEBUG >+class BypassMicrotaskCheckpoint::Impl { >+public: >+ Impl() { } >+ ~Impl() { } >+ WebCore::V8RecursionScope::BypassMicrotaskCheckpoint m_scope; >+}; >+#endif >+ >+BypassMicrotaskCheckpoint::BypassMicrotaskCheckpoint() >+{ >+#ifndef NDEBUG >+ m_impl = new BypassMicrotaskCheckpoint::Impl(); >+#endif >+} >+ >+BypassMicrotaskCheckpoint::~BypassMicrotaskCheckpoint() >+{ >+#ifndef NDEBUG >+ delete m_impl; >+#endif >+} >+ >+} >+ >+} // namespace WebKit
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 79131
:
128004
|
128778
|
133957
|
134169
|
134466
|
134467
|
134475
|
134611
|
134858
|
134876
|
134877
|
135368