diff options
Diffstat (limited to 'Source/WebCore/bindings/v8')
28 files changed, 322 insertions, 642 deletions
diff --git a/Source/WebCore/bindings/v8/JavaScriptCallFrame.h b/Source/WebCore/bindings/v8/JavaScriptCallFrame.h index 021616e56..21a1d6d54 100644 --- a/Source/WebCore/bindings/v8/JavaScriptCallFrame.h +++ b/Source/WebCore/bindings/v8/JavaScriptCallFrame.h @@ -33,8 +33,8 @@ #if ENABLE(JAVASCRIPT_DEBUGGER) -#include "OwnHandle.h" #include "PlatformString.h" +#include "ScopedPersistent.h" #include <v8-debug.h> #include <wtf/RefCounted.h> @@ -66,8 +66,8 @@ private: JavaScriptCallFrame(v8::Handle<v8::Context> debuggerContext, v8::Handle<v8::Object> callFrame); RefPtr<JavaScriptCallFrame> m_caller; - OwnHandle<v8::Context> m_debuggerContext; - OwnHandle<v8::Object> m_callFrame; + ScopedPersistent<v8::Context> m_debuggerContext; + ScopedPersistent<v8::Object> m_callFrame; }; } // namespace WebCore diff --git a/Source/WebCore/bindings/v8/ScheduledAction.cpp b/Source/WebCore/bindings/v8/ScheduledAction.cpp index 2a5f89d2d..40ab33dfa 100644 --- a/Source/WebCore/bindings/v8/ScheduledAction.cpp +++ b/Source/WebCore/bindings/v8/ScheduledAction.cpp @@ -49,49 +49,20 @@ namespace WebCore { -ScheduledAction::ScheduledAction(v8::Handle<v8::Context> context, v8::Handle<v8::Function> func, int argc, v8::Handle<v8::Value> argv[]) +ScheduledAction::ScheduledAction(v8::Handle<v8::Context> context, v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[]) : m_context(context) + , m_function(function) , m_code(String(), KURL(), TextPosition::belowRangePosition()) { - m_function = v8::Persistent<v8::Function>::New(func); - -#ifndef NDEBUG - V8GCController::registerGlobalHandle(SCHEDULED_ACTION, this, m_function); -#endif - - m_argc = argc; - if (argc > 0) { - m_argv = new v8::Persistent<v8::Value>[argc]; - for (int i = 0; i < argc; i++) { - m_argv[i] = v8::Persistent<v8::Value>::New(argv[i]); - -#ifndef NDEBUG - V8GCController::registerGlobalHandle(SCHEDULED_ACTION, this, m_argv[i]); -#endif - } - } else - m_argv = 0; + m_args.reserveCapacity(argc); + for (int i = 0; i < argc; ++i) + m_args.append(v8::Persistent<v8::Value>::New(argv[i])); } ScheduledAction::~ScheduledAction() { - if (m_function.IsEmpty()) - return; - -#ifndef NDEBUG - V8GCController::unregisterGlobalHandle(this, m_function); -#endif - m_function.Dispose(); - - for (int i = 0; i < m_argc; i++) { -#ifndef NDEBUG - V8GCController::unregisterGlobalHandle(this, m_argv[i]); -#endif - m_argv[i].Dispose(); - } - - if (m_argc > 0) - delete[] m_argv; + for (size_t i = 0; i < m_args.size(); ++i) + m_args[i].Dispose(); } void ScheduledAction::execute(ScriptExecutionContext* context) @@ -102,7 +73,7 @@ void ScheduledAction::execute(ScriptExecutionContext* context) return; if (!frame->script()->canExecuteScripts(AboutToExecuteScript)) return; - execute(frame->script()); + execute(frame); } #if ENABLE(WORKERS) else { @@ -112,47 +83,46 @@ void ScheduledAction::execute(ScriptExecutionContext* context) #endif } -void ScheduledAction::execute(ScriptController* script) +void ScheduledAction::execute(Frame* frame) { - ASSERT(script->proxy()); - v8::HandleScope handleScope; - v8::Handle<v8::Context> v8Context = v8::Local<v8::Context>::New(m_context.get()); - if (v8Context.IsEmpty()) - return; // JS may not be enabled. + + v8::Handle<v8::Context> context = v8::Local<v8::Context>::New(m_context.get()); + if (context.IsEmpty()) + return; + v8::Context::Scope scope(context); #if PLATFORM(CHROMIUM) TRACE_EVENT0("v8", "ScheduledAction::execute"); #endif - v8::Context::Scope scope(v8Context); - - // FIXME: Need to implement timeouts for preempting a long-running script. - if (!m_function.IsEmpty() && m_function->IsFunction()) - script->callFunction(v8::Persistent<v8::Function>::Cast(m_function), v8Context->Global(), m_argc, m_argv); + v8::Handle<v8::Function> function = m_function.get(); + if (!function.IsEmpty()) + frame->script()->callFunction(function, context->Global(), m_args.size(), m_args.data()); else - script->compileAndRunScript(m_code); + frame->script()->compileAndRunScript(m_code); - // The 'proxy' may be invalid at this point since JS could have released the owning Frame. + // The frame might be invalid at this point because JavaScript could have released it. } #if ENABLE(WORKERS) -void ScheduledAction::execute(WorkerContext* workerContext) +void ScheduledAction::execute(WorkerContext* worker) { - // In a Worker, the execution should always happen on a worker thread. - ASSERT(workerContext->thread()->threadID() == currentThread()); + ASSERT(worker->thread()->threadID() == currentThread()); - V8RecursionScope recursionScope(workerContext); - WorkerScriptController* scriptController = workerContext->script(); + V8RecursionScope recursionScope(worker); - if (!m_function.IsEmpty() && m_function->IsFunction()) { + v8::Handle<v8::Function> function = m_function.get(); + if (!function.IsEmpty()) { v8::HandleScope handleScope; - v8::Handle<v8::Context> v8Context = v8::Local<v8::Context>::New(m_context.get()); - ASSERT(!v8Context.IsEmpty()); - v8::Context::Scope scope(v8Context); - m_function->Call(v8Context->Global(), m_argc, m_argv); + + v8::Handle<v8::Context> context = v8::Local<v8::Context>::New(m_context.get()); + ASSERT(!context.IsEmpty()); + v8::Context::Scope scope(context); + + function->Call(context->Global(), m_args.size(), m_args.data()); } else - scriptController->evaluate(m_code); + worker->script()->evaluate(m_code); } #endif diff --git a/Source/WebCore/bindings/v8/ScheduledAction.h b/Source/WebCore/bindings/v8/ScheduledAction.h index e3f3bb440..17ca7b41a 100644 --- a/Source/WebCore/bindings/v8/ScheduledAction.h +++ b/Source/WebCore/bindings/v8/ScheduledAction.h @@ -31,45 +31,42 @@ #ifndef ScheduledAction_h #define ScheduledAction_h -#include "OwnHandle.h" +#include "ScopedPersistent.h" #include "ScriptSourceCode.h" -#include "V8GCController.h" -#include <wtf/Forward.h> - #include <v8.h> +#include <wtf/Forward.h> +#include <wtf/Vector.h> namespace WebCore { - class ScriptController; - class ScriptExecutionContext; - class WorkerContext; +class Frame; +class ScriptExecutionContext; +class WorkerContext; + +class ScheduledAction { +public: + ScheduledAction(v8::Handle<v8::Context>, v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[]); - class ScheduledAction { - public: - ScheduledAction(v8::Handle<v8::Context>, v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[]); - explicit ScheduledAction(v8::Handle<v8::Context> context, const WTF::String& code, const KURL& url = KURL()) - : m_context(context) - , m_argc(0) - , m_argv(0) - , m_code(code, url) - { - } + ScheduledAction(v8::Handle<v8::Context> context, const String& code, const KURL& url = KURL()) + : m_context(context) + , m_code(code, url) + { + } - virtual ~ScheduledAction(); - virtual void execute(ScriptExecutionContext*); + ~ScheduledAction(); + void execute(ScriptExecutionContext*); - private: - void execute(ScriptController*); +private: + void execute(Frame*); #if ENABLE(WORKERS) - void execute(WorkerContext*); + void execute(WorkerContext*); #endif - OwnHandle<v8::Context> m_context; - v8::Persistent<v8::Function> m_function; - int m_argc; - v8::Persistent<v8::Value>* m_argv; - ScriptSourceCode m_code; - }; + ScopedPersistent<v8::Context> m_context; + ScopedPersistent<v8::Function> m_function; + Vector<v8::Persistent<v8::Value> > m_args; + ScriptSourceCode m_code; +}; } // namespace WebCore diff --git a/Source/WebCore/bindings/v8/OwnHandle.h b/Source/WebCore/bindings/v8/ScopedPersistent.h index 668f5d414..f5d696ccc 100644 --- a/Source/WebCore/bindings/v8/OwnHandle.h +++ b/Source/WebCore/bindings/v8/ScopedPersistent.h @@ -28,29 +28,31 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef OwnHandle_h -#define OwnHandle_h +#ifndef ScopedPersistent_h +#define ScopedPersistent_h #include <v8.h> +#include <wtf/Noncopyable.h> namespace WebCore { template<typename T> -class OwnHandle { +class ScopedPersistent { + WTF_MAKE_NONCOPYABLE(ScopedPersistent); public: - OwnHandle() { } + ScopedPersistent() { } - explicit OwnHandle(v8::Handle<T> handle) + explicit ScopedPersistent(v8::Handle<T> handle) : m_handle(v8::Persistent<T>::New(handle)) { } - ~OwnHandle() + ~ScopedPersistent() { clear(); } - v8::Handle<T> get() const { return m_handle; } + v8::Persistent<T> get() const { return m_handle; } void set(v8::Handle<T> handle) { @@ -58,6 +60,12 @@ public: m_handle = v8::Persistent<T>::New(handle); } + void adopt(v8::Persistent<T> handle) + { + clear(); + m_handle = handle; + } + // Note: This is clear in the OwnPtr sense, not the v8::Handle sense. void clear() { @@ -73,4 +81,4 @@ private: } // namespace WebCore -#endif // OwnHandle_h +#endif // ScopedPersistent_h diff --git a/Source/WebCore/bindings/v8/ScriptController.cpp b/Source/WebCore/bindings/v8/ScriptController.cpp index 1fb36b374..4672570e6 100644 --- a/Source/WebCore/bindings/v8/ScriptController.cpp +++ b/Source/WebCore/bindings/v8/ScriptController.cpp @@ -59,6 +59,7 @@ #include "V8Binding.h" #include "V8DOMWindow.h" #include "V8Event.h" +#include "V8GCController.h" #include "V8HiddenPropertyName.h" #include "V8HTMLEmbedElement.h" #include "V8IsolatedContext.h" @@ -111,7 +112,6 @@ ScriptController::ScriptController(Frame* frame) , m_sourceURL(0) , m_windowShell(V8DOMWindowShell::create(frame)) , m_paused(false) - , m_proxy(adoptPtr(new V8Proxy(frame))) #if ENABLE(NETSCAPE_PLUGIN_API) , m_wrappedWindowScriptNPObject(0) #endif @@ -120,6 +120,7 @@ ScriptController::ScriptController(Frame* frame) ScriptController::~ScriptController() { + windowShell()->destroyGlobal(); clearForClose(); } @@ -193,7 +194,7 @@ bool ScriptController::processingUserGesture() v8::Local<v8::Value> ScriptController::callFunction(v8::Handle<v8::Function> function, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> args[]) { - // Keep Frame (and therefore ScriptController and V8Proxy) alive. + // Keep Frame (and therefore ScriptController) alive. RefPtr<Frame> protect(m_frame); return ScriptController::callFunctionWithInstrumentation(m_frame ? m_frame->document() : 0, function, receiver, argc, args); } @@ -647,7 +648,7 @@ NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement void ScriptController::clearWindowShell(DOMWindow*, bool) { // V8 binding expects ScriptController::clearWindowShell only be called - // when a frame is loading a new page. V8Proxy::clearForNavigation + // when a frame is loading a new page. ScriptController::clearForNavigation // creates a new context for the new page. clearForNavigation(); } diff --git a/Source/WebCore/bindings/v8/ScriptController.h b/Source/WebCore/bindings/v8/ScriptController.h index ca59838ac..ad9bf7116 100644 --- a/Source/WebCore/bindings/v8/ScriptController.h +++ b/Source/WebCore/bindings/v8/ScriptController.h @@ -31,18 +31,17 @@ #ifndef ScriptController_h #define ScriptController_h +#include "FrameLoaderTypes.h" #include "ScriptControllerBase.h" #include "ScriptInstance.h" #include "ScriptValue.h" -#include "V8Proxy.h" - #include <v8.h> - #include <wtf/Forward.h> #include <wtf/HashMap.h> #include <wtf/RefCounted.h> #include <wtf/Vector.h> +#include <wtf/text/TextPosition.h> struct NPObject; @@ -53,12 +52,25 @@ class Event; class Frame; class HTMLDocument; class HTMLPlugInElement; -class PagePopupClient; +class KURL; class ScriptSourceCode; class ScriptState; +class SecurityOrigin; class V8DOMWindowShell; +class V8IsolatedContext; class Widget; +// Note: although the pointer is raw, the instance is kept alive by a strong +// reference to the v8 context it contains, which is not made weak until we +// call world->destroy(). +// +// FIXME: We want to eventually be holding window shells instead of the +// IsolatedContext directly. +// https://bugs.webkit.org/show_bug.cgi?id=94875 +typedef HashMap<int, V8IsolatedContext*> IsolatedWorldMap; + +typedef HashMap<int, RefPtr<SecurityOrigin> > IsolatedWorldSecurityOriginMap; + typedef WTF::Vector<v8::Extension*> V8Extensions; class ScriptController { @@ -66,9 +78,8 @@ public: ScriptController(Frame*); ~ScriptController(); - // FIXME: V8Proxy should either be folded into ScriptController - // or this accessor should be made JSProxy* - V8Proxy* proxy() { return m_proxy.get(); } + // FIXME: This should eventually take DOMWrapperWorld argument. + // https://bugs.webkit.org/show_bug.cgi?id=94875 V8DOMWindowShell* windowShell() const { return m_windowShell.get(); } ScriptValue executeScript(const ScriptSourceCode&); @@ -150,11 +161,9 @@ public: // --- and there is only one VM instance. --- // Returns the frame for the entered context. See comments in - // V8Proxy::retrieveFrameForEnteredContext() for more information. static Frame* retrieveFrameForEnteredContext(); // Returns the frame for the current context. See comments in - // V8Proxy::retrieveFrameForEnteredContext() for more information. static Frame* retrieveFrameForCurrentContext(); // Returns V8 Context. If none exists, creates a new context. @@ -227,7 +236,6 @@ private: bool m_paused; - OwnPtr<V8Proxy> m_proxy; typedef HashMap<Widget*, NPObject*> PluginObjectMap; // A mapping between Widgets and their corresponding script object. diff --git a/Source/WebCore/bindings/v8/ScriptDebugServer.cpp b/Source/WebCore/bindings/v8/ScriptDebugServer.cpp index 1455aaec4..ef1691eec 100644 --- a/Source/WebCore/bindings/v8/ScriptDebugServer.cpp +++ b/Source/WebCore/bindings/v8/ScriptDebugServer.cpp @@ -441,7 +441,7 @@ void ScriptDebugServer::compileScript(ScriptState* state, const String& expressi return; *scriptId = toWebCoreStringWithNullOrUndefinedCheck(script->Id()); - m_compiledScripts.set(*scriptId, adoptPtr(new OwnHandle<v8::Script>(script))); + m_compiledScripts.set(*scriptId, adoptPtr(new ScopedPersistent<v8::Script>(script))); } void ScriptDebugServer::clearCompiledScripts() @@ -454,8 +454,8 @@ void ScriptDebugServer::runScript(ScriptState* state, const String& scriptId, Sc if (!m_compiledScripts.contains(scriptId)) return; v8::HandleScope handleScope; - OwnHandle<v8::Script>* scriptOwnHandle = m_compiledScripts.get(scriptId); - v8::Local<v8::Script> script = v8::Local<v8::Script>::New(scriptOwnHandle->get()); + ScopedPersistent<v8::Script>* scriptHandle = m_compiledScripts.get(scriptId); + v8::Local<v8::Script> script = v8::Local<v8::Script>::New(scriptHandle->get()); m_compiledScripts.remove(scriptId); if (script.IsEmpty()) return; diff --git a/Source/WebCore/bindings/v8/ScriptDebugServer.h b/Source/WebCore/bindings/v8/ScriptDebugServer.h index 4d1e65e09..244d28577 100644 --- a/Source/WebCore/bindings/v8/ScriptDebugServer.h +++ b/Source/WebCore/bindings/v8/ScriptDebugServer.h @@ -33,8 +33,8 @@ #if ENABLE(JAVASCRIPT_DEBUGGER) -#include "OwnHandle.h" #include "PlatformString.h" +#include "ScopedPersistent.h" #include "ScriptBreakpoint.h" #include "Timer.h" #include <v8-debug.h> @@ -125,13 +125,13 @@ protected: 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; + ScopedPersistent<v8::Object> m_debuggerScript; + ScopedPersistent<v8::Object> m_executionState; v8::Local<v8::Context> m_pausedContext; bool m_breakpointsActivated; - OwnHandle<v8::FunctionTemplate> m_breakProgramCallbackTemplate; - HashMap<String, OwnPtr<OwnHandle<v8::Script> > > m_compiledScripts; + ScopedPersistent<v8::FunctionTemplate> m_breakProgramCallbackTemplate; + HashMap<String, OwnPtr<ScopedPersistent<v8::Script> > > m_compiledScripts; }; } // namespace WebCore diff --git a/Source/WebCore/bindings/v8/ScriptInstance.cpp b/Source/WebCore/bindings/v8/ScriptInstance.cpp index 1f407d0f5..e62fb7d7a 100644 --- a/Source/WebCore/bindings/v8/ScriptInstance.cpp +++ b/Source/WebCore/bindings/v8/ScriptInstance.cpp @@ -31,51 +31,11 @@ #include "config.h" #include "ScriptInstance.h" -#include "V8GCController.h" -#include <wtf/Assertions.h> - namespace WebCore { -V8ScriptInstance::V8ScriptInstance() -{ -} - V8ScriptInstance::V8ScriptInstance(v8::Handle<v8::Object> instance) + : m_instance(instance) { - set(instance); -} - -V8ScriptInstance::~V8ScriptInstance() -{ - clear(); -} - -v8::Persistent<v8::Object> V8ScriptInstance::instance() -{ - return m_instance; -} - -void V8ScriptInstance::clear() -{ - if (m_instance.IsEmpty()) - return; -#ifndef NDEBUG - V8GCController::unregisterGlobalHandle(this, m_instance); -#endif - m_instance.Dispose(); - m_instance.Clear(); -} - -void V8ScriptInstance::set(v8::Handle<v8::Object> instance) -{ - clear(); - if (instance.IsEmpty()) - return; - - m_instance = v8::Persistent<v8::Object>::New(instance); -#ifndef NDEBUG - V8GCController::registerGlobalHandle(SCRIPTINSTANCE, this, m_instance); -#endif } } // namespace WebCore diff --git a/Source/WebCore/bindings/v8/ScriptInstance.h b/Source/WebCore/bindings/v8/ScriptInstance.h index 2fe37364f..7f6438799 100644 --- a/Source/WebCore/bindings/v8/ScriptInstance.h +++ b/Source/WebCore/bindings/v8/ScriptInstance.h @@ -31,8 +31,8 @@ #ifndef ScriptInstance_h #define ScriptInstance_h +#include "ScopedPersistent.h" #include <v8.h> - #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> @@ -41,19 +41,14 @@ namespace WebCore { class V8ScriptInstance : public RefCounted<V8ScriptInstance> { public: - static PassRefPtr<V8ScriptInstance> create(v8::Handle<v8::Object> instance) - { - return adoptRef(new V8ScriptInstance(instance)); - } - V8ScriptInstance(); - V8ScriptInstance(v8::Handle<v8::Object>); - ~V8ScriptInstance(); - v8::Persistent<v8::Object> instance(); + static PassRefPtr<V8ScriptInstance> create(v8::Handle<v8::Object> instance) { return adoptRef(new V8ScriptInstance(instance)); } + + v8::Persistent<v8::Object> instance() { return m_instance.get(); } private: - void clear(); - void set(v8::Handle<v8::Object>); - mutable v8::Persistent<v8::Object> m_instance; + explicit V8ScriptInstance(v8::Handle<v8::Object>); + + ScopedPersistent<v8::Object> m_instance; }; typedef RefPtr<V8ScriptInstance> ScriptInstance; diff --git a/Source/WebCore/bindings/v8/ScriptState.cpp b/Source/WebCore/bindings/v8/ScriptState.cpp index a975b14c5..8a0580bcd 100644 --- a/Source/WebCore/bindings/v8/ScriptState.cpp +++ b/Source/WebCore/bindings/v8/ScriptState.cpp @@ -41,76 +41,53 @@ #include "WorkerContext.h" #include "WorkerContextExecutionProxy.h" #include "WorkerScriptController.h" - #include <v8.h> #include <wtf/Assertions.h> namespace WebCore { ScriptState::ScriptState(v8::Handle<v8::Context> context) - : m_context(v8::Persistent<v8::Context>::New(context)) + : m_context(context) { - m_context.MakeWeak(this, &ScriptState::weakReferenceCallback); + m_context.get().MakeWeak(this, &ScriptState::weakReferenceCallback); } ScriptState::~ScriptState() { - m_context.Dispose(); - m_context.Clear(); } DOMWindow* ScriptState::domWindow() const { v8::HandleScope handleScope; - v8::Handle<v8::Object> v8RealGlobal = v8::Handle<v8::Object>::Cast(m_context->Global()->GetPrototype()); - if (!V8DOMWrapper::isWrapperOfType(v8RealGlobal, &V8DOMWindow::info)) - return 0; - return V8DOMWindow::toNative(v8RealGlobal); + return toDOMWindow(m_context.get()); } ScriptExecutionContext* ScriptState::scriptExecutionContext() const { v8::HandleScope handleScope; - - v8::Handle<v8::Object> global = m_context->Global(); - v8::Handle<v8::Object> v8RealGlobal = v8::Handle<v8::Object>::Cast(global->GetPrototype()); - if (V8DOMWrapper::isWrapperOfType(v8RealGlobal, &V8DOMWindow::info)) - return V8DOMWindow::toNative(v8RealGlobal)->scriptExecutionContext(); -#if ENABLE(WORKERS) - global = V8DOMWrapper::lookupDOMWrapper(V8WorkerContext::GetTemplate(), global); - if (!global.IsEmpty()) - return V8WorkerContext::toNative(global)->scriptExecutionContext(); -#endif - return 0; + return toScriptExecutionContext(m_context.get()); } ScriptState* ScriptState::forContext(v8::Local<v8::Context> 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 coincides with that of the inspected context. - global = v8::Local<v8::Object>::Cast(global->GetPrototype()); + v8::Local<v8::Object> innerGlobal = v8::Local<v8::Object>::Cast(context->Global()->GetPrototype()); - v8::Handle<v8::String> key = V8HiddenPropertyName::scriptState(); - v8::Local<v8::Value> val = global->GetHiddenValue(key); - if (!val.IsEmpty() && val->IsExternal()) - return static_cast<ScriptState*>(v8::External::Cast(*val)->Value()); + v8::Local<v8::Value> scriptStateWrapper = innerGlobal->GetHiddenValue(V8HiddenPropertyName::scriptState()); + if (!scriptStateWrapper.IsEmpty() && scriptStateWrapper->IsExternal()) + return static_cast<ScriptState*>(v8::External::Cast(*scriptStateWrapper)->Value()); - ScriptState* state = new ScriptState(context); - global->SetHiddenValue(key, v8::External::New(state)); - return state; + ScriptState* scriptState = new ScriptState(context); + innerGlobal->SetHiddenValue(V8HiddenPropertyName::scriptState(), v8::External::New(scriptState)); + return scriptState; } ScriptState* ScriptState::current() { v8::HandleScope handleScope; v8::Local<v8::Context> context = v8::Context::GetCurrent(); - if (context.IsEmpty()) { - ASSERT_NOT_REACHED(); - return 0; - } + ASSERT(!context.IsEmpty()); return ScriptState::forContext(context); } diff --git a/Source/WebCore/bindings/v8/ScriptState.h b/Source/WebCore/bindings/v8/ScriptState.h index 009886a17..f59aa8da0 100644 --- a/Source/WebCore/bindings/v8/ScriptState.h +++ b/Source/WebCore/bindings/v8/ScriptState.h @@ -32,11 +32,13 @@ #define ScriptState_h #include "DOMWrapperWorld.h" +#include "ScopedPersistent.h" #include <v8.h> #include <wtf/Noncopyable.h> #include <wtf/RefCounted.h> namespace WebCore { + class DOMWindow; class DOMWrapperWorld; class Frame; @@ -57,7 +59,7 @@ public: v8::Local<v8::Context> context() const { - return v8::Local<v8::Context>::New(m_context); + return v8::Local<v8::Context>::New(m_context.get()); } DOMWindow* domWindow() const; @@ -77,7 +79,7 @@ private: static void weakReferenceCallback(v8::Persistent<v8::Value> object, void* parameter); v8::Local<v8::Value> m_exception; - v8::Persistent<v8::Context> m_context; + ScopedPersistent<v8::Context> m_context; }; class EmptyScriptState : public ScriptState { @@ -89,24 +91,24 @@ public: class ScriptStateProtectedPtr { WTF_MAKE_NONCOPYABLE(ScriptStateProtectedPtr); public: - ScriptStateProtectedPtr() : m_scriptState(0) { } - ScriptStateProtectedPtr(ScriptState* scriptState) : m_scriptState(scriptState) + ScriptStateProtectedPtr() + : m_scriptState(0) { - v8::HandleScope handleScope; - // Keep the context from being GC'ed. ScriptState is guaranteed to be live while the context is live. - m_context = v8::Persistent<v8::Context>::New(scriptState->context()); } - ~ScriptStateProtectedPtr() + + ScriptStateProtectedPtr(ScriptState* scriptState) + : m_scriptState(scriptState) { - if (!m_context.IsEmpty()) { - m_context.Dispose(); - m_context.Clear(); - } + v8::HandleScope handleScope; + // Keep the context from being GC'ed. ScriptState is guaranteed to be live while the context is live. + m_context.set(scriptState->context()); } + ScriptState* get() const { return m_scriptState; } + private: ScriptState* m_scriptState; - v8::Persistent<v8::Context> m_context; + ScopedPersistent<v8::Context> m_context; }; DOMWindow* domWindowFromScriptState(ScriptState*); diff --git a/Source/WebCore/bindings/v8/ScriptValue.cpp b/Source/WebCore/bindings/v8/ScriptValue.cpp index 31bcd23ee..1c48fdfc6 100644 --- a/Source/WebCore/bindings/v8/ScriptValue.cpp +++ b/Source/WebCore/bindings/v8/ScriptValue.cpp @@ -40,14 +40,17 @@ namespace WebCore { +ScriptValue::~ScriptValue() +{ +} + PassRefPtr<SerializedScriptValue> ScriptValue::serialize(ScriptState* scriptState) { ScriptScope scope(scriptState); return SerializedScriptValue::create(v8Value()); } -PassRefPtr<SerializedScriptValue> ScriptValue::serialize(ScriptState* scriptState, - MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, bool& didThrow) +PassRefPtr<SerializedScriptValue> ScriptValue::serialize(ScriptState* scriptState, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, bool& didThrow) { ScriptScope scope(scriptState); return SerializedScriptValue::create(v8Value(), messagePorts, arrayBuffers, didThrow); @@ -61,24 +64,23 @@ ScriptValue ScriptValue::deserialize(ScriptState* scriptState, SerializedScriptV bool ScriptValue::getString(String& result) const { - if (m_value.IsEmpty()) + if (m_value.get().IsEmpty()) return false; - if (!m_value->IsString()) + if (!m_value.get()->IsString()) return false; - result = toWebCoreString(m_value); + result = toWebCoreString(m_value.get()); return true; } String ScriptValue::toString(ScriptState*) const { v8::TryCatch block; - v8::Handle<v8::String> s = m_value->ToString(); - // Handle the case where an exception is thrown as part of invoking toString on the object. + v8::Handle<v8::String> string = m_value.get()->ToString(); if (block.HasCaught()) return String(); - return v8StringToWebCoreString<String>(s, DoNotExternalize); + return v8StringToWebCoreString<String>(string, DoNotExternalize); } #if ENABLE(INSPECTOR) @@ -140,7 +142,7 @@ PassRefPtr<InspectorValue> ScriptValue::toInspectorValue(ScriptState* scriptStat v8::HandleScope handleScope; // v8::Object::GetPropertyNames() expects current context to be not null. v8::Context::Scope contextScope(scriptState->context()); - return v8ToInspectorValue(m_value, InspectorValue::maxDepth); + return v8ToInspectorValue(m_value.get(), InspectorValue::maxDepth); } #endif diff --git a/Source/WebCore/bindings/v8/ScriptValue.h b/Source/WebCore/bindings/v8/ScriptValue.h index 0f489afbe..70dbff0dd 100644 --- a/Source/WebCore/bindings/v8/ScriptValue.h +++ b/Source/WebCore/bindings/v8/ScriptValue.h @@ -31,17 +31,17 @@ #ifndef ScriptValue_h #define ScriptValue_h -#include "PlatformString.h" +#include "ScopedPersistent.h" #include "ScriptState.h" - #include <v8.h> #include <wtf/PassRefPtr.h> #include <wtf/RefPtr.h> #include <wtf/Vector.h> +#include <wtf/text/WTFString.h> -#ifndef NDEBUG -#include "V8GCController.h" -#endif +#ifndef NDEBUG +#include "V8GCController.h" +#endif namespace WTF { class ArrayBuffer; @@ -57,28 +57,21 @@ typedef Vector<RefPtr<WTF::ArrayBuffer>, 1> ArrayBufferArray; class ScriptValue { public: - ScriptValue() {} + ScriptValue() { } + virtual ~ScriptValue(); ScriptValue(v8::Handle<v8::Value> value) { if (value.IsEmpty()) return; - - m_value = v8::Persistent<v8::Value>::New(value); -#ifndef NDEBUG - V8GCController::registerGlobalHandle(SCRIPTVALUE, this, m_value); -#endif + m_value.set(value); } ScriptValue(const ScriptValue& value) { - if (value.m_value.IsEmpty()) + if (value.hasNoValue()) return; - - m_value = v8::Persistent<v8::Value>::New(value.m_value); -#ifndef NDEBUG - V8GCController::registerGlobalHandle(SCRIPTVALUE, this, m_value); -#endif + m_value.set(value.m_value.get()); } ScriptValue& operator=(const ScriptValue& value) @@ -86,32 +79,28 @@ public: if (this == &value) return *this; - clear(); + m_value.clear(); - if (value.m_value.IsEmpty()) + if (value.hasNoValue()) return *this; - m_value = v8::Persistent<v8::Value>::New(value.m_value); -#ifndef NDEBUG - V8GCController::registerGlobalHandle(SCRIPTVALUE, this, m_value); -#endif - + m_value.set(value.m_value.get()); return *this; } bool operator==(const ScriptValue& value) const { - return m_value == value.m_value; + return m_value.get() == value.m_value.get(); } bool isEqual(ScriptState*, const ScriptValue& value) const { - return m_value == value.m_value; + return m_value.get() == value.m_value.get(); } bool isFunction() const { - return m_value->IsFunction(); + return m_value.get()->IsFunction(); } bool operator!=(const ScriptValue& value) const @@ -121,22 +110,22 @@ public: bool isNull() const { - return m_value->IsNull(); + return m_value.get()->IsNull(); } bool isUndefined() const { - return m_value->IsUndefined(); + return m_value.get()->IsUndefined(); } bool isObject() const { - return m_value->IsObject(); + return m_value.get()->IsObject(); } bool hasNoValue() const { - return m_value.IsEmpty(); + return m_value.get().IsEmpty(); } PassRefPtr<SerializedScriptValue> serialize(ScriptState*); @@ -145,22 +134,11 @@ public: void clear() { - if (m_value.IsEmpty()) - return; - -#ifndef NDEBUG - V8GCController::unregisterGlobalHandle(this, m_value); -#endif - m_value.Dispose(); - m_value.Clear(); + m_value.clear(); } - virtual ~ScriptValue() - { - clear(); - } + v8::Handle<v8::Value> v8Value() const { return m_value.get(); } - v8::Handle<v8::Value> v8Value() const { return m_value; } bool getString(ScriptState*, String& result) const { return getString(result); } bool getString(String& result) const; String toString(ScriptState*) const; @@ -168,7 +146,7 @@ public: PassRefPtr<InspectorValue> toInspectorValue(ScriptState*) const; private: - mutable v8::Persistent<v8::Value> m_value; + ScopedPersistent<v8::Value> m_value; }; } // namespace WebCore diff --git a/Source/WebCore/bindings/v8/V8AbstractEventListener.cpp b/Source/WebCore/bindings/v8/V8AbstractEventListener.cpp index 04f399163..0d2115276 100644 --- a/Source/WebCore/bindings/v8/V8AbstractEventListener.cpp +++ b/Source/WebCore/bindings/v8/V8AbstractEventListener.cpp @@ -47,10 +47,10 @@ namespace WebCore { -static void weakEventListenerCallback(v8::Persistent<v8::Value>, void* parameter) +void V8AbstractEventListener::weakEventListenerCallback(v8::Persistent<v8::Value>, void* parameter) { V8AbstractEventListener* listener = static_cast<V8AbstractEventListener*>(parameter); - listener->disposeListenerObject(); + listener->m_listener.clear(); } V8AbstractEventListener::V8AbstractEventListener(bool isAttribute, const WorldContextHandle& worldContext) @@ -65,12 +65,10 @@ V8AbstractEventListener::V8AbstractEventListener(bool isAttribute, const WorldCo V8AbstractEventListener::~V8AbstractEventListener() { - if (!m_listener.IsEmpty()) { + if (!m_listener.get().IsEmpty()) { v8::HandleScope scope; - v8::Local<v8::Object> listener = v8::Local<v8::Object>::New(m_listener); - V8EventListenerList::clearWrapper(listener, m_isAttribute); + V8EventListenerList::clearWrapper(v8::Local<v8::Object>::New(m_listener.get()), m_isAttribute); } - disposeListenerObject(); #if ENABLE(INSPECTOR) ThreadLocalInspectorCounters::current().decrementCounter(ThreadLocalInspectorCounters::JSEventListenerCounter); #endif @@ -104,25 +102,10 @@ void V8AbstractEventListener::handleEvent(ScriptExecutionContext* context, Event invokeEventHandler(context, event, jsEvent); } -void V8AbstractEventListener::disposeListenerObject() -{ - if (!m_listener.IsEmpty()) { -#ifndef NDEBUG - V8GCController::unregisterGlobalHandle(this, m_listener); -#endif - m_listener.Dispose(); - m_listener.Clear(); - } -} - void V8AbstractEventListener::setListenerObject(v8::Handle<v8::Object> listener) { - disposeListenerObject(); - m_listener = v8::Persistent<v8::Object>::New(listener); -#ifndef NDEBUG - V8GCController::registerGlobalHandle(EVENT_LISTENER, this, m_listener); -#endif - m_listener.MakeWeak(this, &weakEventListenerCallback); + m_listener.set(listener); + m_listener.get().MakeWeak(this, &V8AbstractEventListener::weakEventListenerCallback); } void V8AbstractEventListener::invokeEventHandler(ScriptExecutionContext* context, Event* event, v8::Handle<v8::Value> jsEvent) @@ -201,8 +184,8 @@ bool V8AbstractEventListener::shouldPreventDefault(v8::Local<v8::Value> returnVa v8::Local<v8::Object> V8AbstractEventListener::getReceiverObject(Event* event) { - if (!m_listener.IsEmpty() && !m_listener->IsFunction()) - return v8::Local<v8::Object>::New(m_listener); + if (!m_listener.get().IsEmpty() && !m_listener.get()->IsFunction()) + return v8::Local<v8::Object>::New(m_listener.get()); EventTarget* target = event->currentTarget(); v8::Handle<v8::Value> value = V8DOMWrapper::convertEventTargetToV8Object(target); diff --git a/Source/WebCore/bindings/v8/V8AbstractEventListener.h b/Source/WebCore/bindings/v8/V8AbstractEventListener.h index 672ba6dba..19a37e0a7 100644 --- a/Source/WebCore/bindings/v8/V8AbstractEventListener.h +++ b/Source/WebCore/bindings/v8/V8AbstractEventListener.h @@ -32,8 +32,8 @@ #define V8AbstractEventListener_h #include "EventListener.h" +#include "ScopedPersistent.h" #include "WorldContextHandle.h" - #include <v8.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> @@ -41,8 +41,6 @@ namespace WebCore { class Event; - class Frame; - class V8Proxy; // There are two kinds of event listeners: HTML or non-HMTL. onload, // onfocus, etc (attributes) are always HTML event handler type; Event @@ -80,29 +78,26 @@ namespace WebCore { v8::Local<v8::Object> getListenerObject(ScriptExecutionContext* context) { prepareListenerObject(context); - return v8::Local<v8::Object>::New(m_listener); + return v8::Local<v8::Object>::New(m_listener.get()); } v8::Local<v8::Object> getExistingListenerObject() { - return v8::Local<v8::Object>::New(m_listener); + return v8::Local<v8::Object>::New(m_listener.get()); } // Provides access to the underlying handle for GC. Returned // value is a weak handle and so not guaranteed to stay alive. v8::Persistent<v8::Object> existingListenerObjectPersistentHandle() { - return m_listener; + return m_listener.get(); } bool hasExistingListenerObject() { - return !m_listener.IsEmpty(); + return !m_listener.get().IsEmpty(); } - // Dispose listener object and clear the handle. - void disposeListenerObject(); - const WorldContextHandle& worldContext() const { return m_worldContext; } protected: @@ -118,6 +113,8 @@ namespace WebCore { v8::Local<v8::Object> getReceiverObject(Event*); private: + static void weakEventListenerCallback(v8::Persistent<v8::Value>, void* parameter); + // Implementation of EventListener function. virtual bool virtualisAttribute() const { return m_isAttribute; } @@ -125,7 +122,7 @@ namespace WebCore { virtual bool shouldPreventDefault(v8::Local<v8::Value> returnValue); - v8::Persistent<v8::Object> m_listener; + ScopedPersistent<v8::Object> m_listener; // Indicates if this is an HTML type listener. bool m_isAttribute; diff --git a/Source/WebCore/bindings/v8/V8Binding.cpp b/Source/WebCore/bindings/v8/V8Binding.cpp index bf57f8286..acd043aa5 100644 --- a/Source/WebCore/bindings/v8/V8Binding.cpp +++ b/Source/WebCore/bindings/v8/V8Binding.cpp @@ -37,17 +37,19 @@ #include "Frame.h" #include "MemoryInstrumentation.h" #include "PlatformString.h" +#include "PlatformSupport.h" #include "QualifiedName.h" #include "Settings.h" #include "V8DOMStringList.h" #include "V8DOMWindow.h" #include "V8Element.h" #include "V8ObjectConstructor.h" +#include "V8WorkerContext.h" #include "V8XPathNSResolver.h" #include "WorkerContext.h" #include "WorkerContextExecutionProxy.h" +#include "WorldContextHandle.h" #include "XPathNSResolver.h" - #include <wtf/MathExtras.h> #include <wtf/MainThread.h> #include <wtf/StdLibExtras.h> @@ -261,6 +263,21 @@ DOMWindow* toDOMWindow(v8::Handle<v8::Context> context) return V8DOMWindow::toNative(global); } +ScriptExecutionContext* toScriptExecutionContext(v8::Handle<v8::Context> context) +{ + v8::Handle<v8::Object> global = context->Global(); + v8::Handle<v8::Object> windowWrapper = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), global); + if (!windowWrapper.IsEmpty()) + return V8DOMWindow::toNative(windowWrapper)->scriptExecutionContext(); +#if ENABLE(WORKERS) + v8::Handle<v8::Object> workerWrapper = V8DOMWrapper::lookupDOMWrapper(V8WorkerContext::GetTemplate(), global); + if (!workerWrapper.IsEmpty()) + return V8WorkerContext::toNative(workerWrapper)->scriptExecutionContext(); +#endif + // FIXME: Is this line of code reachable? + return 0; +} + Frame* toFrameIfNotDetached(v8::Handle<v8::Context> context) { DOMWindow* window = toDOMWindow(context); diff --git a/Source/WebCore/bindings/v8/V8Binding.h b/Source/WebCore/bindings/v8/V8Binding.h index 2333cede0..c8f31b28c 100644 --- a/Source/WebCore/bindings/v8/V8Binding.h +++ b/Source/WebCore/bindings/v8/V8Binding.h @@ -353,8 +353,8 @@ namespace WebCore { PassRefPtr<DOMStringList> toDOMStringList(v8::Handle<v8::Value>); PassRefPtr<XPathNSResolver> toXPathNSResolver(v8::Handle<v8::Value>); - // Returns the window object associated with a context. DOMWindow* toDOMWindow(v8::Handle<v8::Context>); + ScriptExecutionContext* toScriptExecutionContext(v8::Handle<v8::Context>); // Returns the context associated with a ScriptExecutionContext. v8::Local<v8::Context> toV8Context(ScriptExecutionContext*, const WorldContextHandle&); diff --git a/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp b/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp index 3e6a78e24..4d87e72e1 100644 --- a/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp +++ b/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp @@ -54,6 +54,7 @@ #include "V8DOMMap.h" #include "V8DOMWindow.h" #include "V8Document.h" +#include "V8GCController.h" #include "V8GCForContextDispose.h" #include "V8HTMLDocument.h" #include "V8HiddenPropertyName.h" @@ -93,7 +94,7 @@ static void reportFatalErrorInV8(const char* location, const char* message) { // V8 is shutdown, we cannot use V8 api. // The only thing we can do is to disable JavaScript. - // FIXME: clean up V8Proxy and disable JavaScript. + // FIXME: clean up ScriptController and disable JavaScript. int memoryUsageMB = -1; #if PLATFORM(CHROMIUM) memoryUsageMB = MemoryUsageSupport::actualMemoryUsageMB(); @@ -158,6 +159,31 @@ static void reportUnsafeJavaScriptAccess(v8::Local<v8::Object> host, v8::AccessT targetWindow->printErrorMessage(targetWindow->crossDomainAccessErrorMessage(activeDOMWindow(BindingState::instance()))); } +static void initializeV8IfNeeded() +{ + ASSERT(isMainThread()); + + static bool initialized = false; + if (initialized) + return; + initialized = true; + + v8::V8::IgnoreOutOfMemoryException(); + v8::V8::SetFatalErrorHandler(reportFatalErrorInV8); + v8::V8::SetGlobalGCPrologueCallback(&V8GCController::gcPrologue); + v8::V8::SetGlobalGCEpilogueCallback(&V8GCController::gcEpilogue); + v8::V8::AddMessageListener(&v8UncaughtExceptionHandler); + v8::V8::SetFailedAccessCheckCallbackFunction(reportUnsafeJavaScriptAccess); +#if ENABLE(JAVASCRIPT_DEBUGGER) + ScriptProfiler::initialize(); +#endif + V8PerIsolateData::ensureInitialized(v8::Isolate::GetCurrent()); + + // FIXME: Remove the following 2 lines when V8 default has changed. + const char es5ReadonlyFlag[] = "--es5_readonly"; + v8::V8::SetFlagsFromString(es5ReadonlyFlag, sizeof(es5ReadonlyFlag)); +} + PassRefPtr<V8DOMWindowShell> V8DOMWindowShell::create(Frame* frame) { return adoptRef(new V8DOMWindowShell(frame)); @@ -172,16 +198,15 @@ bool V8DOMWindowShell::isContextInitialized() { // m_context, m_global, and m_wrapperBoilerplates should // all be non-empty if if m_context is non-empty. - ASSERT(m_context.IsEmpty() || !m_global.IsEmpty()); - return !m_context.IsEmpty(); + ASSERT(m_context.get().IsEmpty() || !m_global.get().IsEmpty()); + return !m_context.get().IsEmpty(); } void V8DOMWindowShell::disposeContextHandles() { - if (!m_context.IsEmpty()) { - m_frame->loader()->client()->willReleaseScriptContext(m_context, 0); - m_context.Dispose(); - m_context.Clear(); + if (!m_context.get().IsEmpty()) { + m_frame->loader()->client()->willReleaseScriptContext(m_context.get(), 0); + m_context.clear(); // It's likely that disposing the context has created a lot of // garbage. Notify V8 about this so it'll have a chance of cleaning @@ -195,48 +220,40 @@ void V8DOMWindowShell::disposeContextHandles() void V8DOMWindowShell::destroyGlobal() { - if (!m_global.IsEmpty()) { -#ifndef NDEBUG - V8GCController::unregisterGlobalHandle(this, m_global); -#endif - m_global.Dispose(); - m_global.Clear(); - } + m_global.clear(); } void V8DOMWindowShell::clearForClose() { - if (!m_context.IsEmpty()) { - v8::HandleScope handleScope; + if (m_context.get().IsEmpty()) + return; - clearDocumentWrapper(); - disposeContextHandles(); - } + v8::HandleScope handleScope; + clearDocumentWrapper(); + disposeContextHandles(); } void V8DOMWindowShell::clearForNavigation() { - if (!m_context.IsEmpty()) { - v8::HandleScope handle; - clearDocumentWrapper(); - - v8::Context::Scope contextScope(m_context); + if (m_context.get().IsEmpty()) + return; - // Clear the document wrapper cache before turning on access checks on - // the old DOMWindow wrapper. This way, access to the document wrapper - // will be protected by the security checks on the DOMWindow wrapper. - clearDocumentWrapperCache(); + v8::HandleScope handleScope; + clearDocumentWrapper(); - // Turn on access check on the old DOMWindow wrapper. - v8::Handle<v8::Object> wrapper = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), m_global); - ASSERT(!wrapper.IsEmpty()); - wrapper->TurnOnAccessCheck(); + // FIXME: Should we create a new Local handle here? + v8::Context::Scope contextScope(m_context.get()); - // Separate the context from its global object. - m_context->DetachGlobal(); + // Clear the document wrapper cache before turning on access checks on + // the old DOMWindow wrapper. This way, access to the document wrapper + // will be protected by the security checks on the DOMWindow wrapper. + clearDocumentWrapperCache(); - disposeContextHandles(); - } + v8::Handle<v8::Object> windowWrapper = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), m_global.get()); + ASSERT(!windowWrapper.IsEmpty()); + windowWrapper->TurnOnAccessCheck(); + m_context.get()->DetachGlobal(); + disposeContextHandles(); } // Create a new environment and setup the global object. @@ -276,67 +293,35 @@ void V8DOMWindowShell::clearForNavigation() // it won't be able to reach the outer window via its global object. bool V8DOMWindowShell::initContextIfNeeded() { - // Bail out if the context has already been initialized. - if (!m_context.IsEmpty()) + if (!m_context.get().IsEmpty()) return true; - // Create a handle scope for all local handles. v8::HandleScope handleScope; - // Setup the security handlers and message listener. This only has - // to be done once. - static bool isV8Initialized = false; - if (!isV8Initialized) { - // Tells V8 not to call the default OOM handler, binding code - // will handle it. - v8::V8::IgnoreOutOfMemoryException(); - v8::V8::SetFatalErrorHandler(reportFatalErrorInV8); - - v8::V8::SetGlobalGCPrologueCallback(&V8GCController::gcPrologue); - v8::V8::SetGlobalGCEpilogueCallback(&V8GCController::gcEpilogue); - - v8::V8::AddMessageListener(&v8UncaughtExceptionHandler); - - v8::V8::SetFailedAccessCheckCallbackFunction(reportUnsafeJavaScriptAccess); -#if ENABLE(JAVASCRIPT_DEBUGGER) - ScriptProfiler::initialize(); -#endif - V8PerIsolateData::ensureInitialized(v8::Isolate::GetCurrent()); - - // FIXME: Remove the following 2 lines when V8 default has changed. - const char es5ReadonlyFlag[] = "--es5_readonly"; - v8::V8::SetFlagsFromString(es5ReadonlyFlag, sizeof(es5ReadonlyFlag)); + initializeV8IfNeeded(); - isV8Initialized = true; - } - - m_context = createNewContext(m_global, 0, 0); - if (m_context.IsEmpty()) + m_context.adopt(createNewContext(m_global.get(), 0, 0)); + if (m_context.get().IsEmpty()) return false; - v8::Local<v8::Context> v8Context = v8::Local<v8::Context>::New(m_context); - v8::Context::Scope contextScope(v8Context); + v8::Local<v8::Context> context = v8::Local<v8::Context>::New(m_context.get()); + v8::Context::Scope contextScope(context); - // Store the first global object created so we can reuse it. - if (m_global.IsEmpty()) { - m_global = v8::Persistent<v8::Object>::New(v8Context->Global()); - // Bail out if allocation of the first global objects fails. - if (m_global.IsEmpty()) { + if (m_global.get().IsEmpty()) { + m_global.set(context->Global()); + if (m_global.get().IsEmpty()) { disposeContextHandles(); return false; } -#ifndef NDEBUG - V8GCController::registerGlobalHandle(PROXY, this, m_global); -#endif } - m_perContextData = V8PerContextData::create(m_context); + m_perContextData = V8PerContextData::create(m_context.get()); if (!m_perContextData->init()) { disposeContextHandles(); return false; } - if (!installDOMWindow(v8Context, m_frame->document()->domWindow())) { + if (!installDOMWindow(context, m_frame->document()->domWindow())) { disposeContextHandles(); return false; } @@ -346,9 +331,9 @@ bool V8DOMWindowShell::initContextIfNeeded() setSecurityToken(); if (m_frame->document()) - v8Context->AllowCodeGenerationFromStrings(m_frame->document()->contentSecurityPolicy()->allowEval(0, ContentSecurityPolicy::SuppressReport)); + context->AllowCodeGenerationFromStrings(m_frame->document()->contentSecurityPolicy()->allowEval(0, ContentSecurityPolicy::SuppressReport)); - m_frame->loader()->client()->didCreateScriptContext(m_context, 0, 0); + m_frame->loader()->client()->didCreateScriptContext(m_context.get(), 0, 0); // FIXME: This is wrong. We should actually do this for the proper world once // we do isolated worlds the WebCore way. @@ -400,12 +385,7 @@ v8::Persistent<v8::Context> V8DOMWindowShell::createNewContext(v8::Handle<v8::Ob void V8DOMWindowShell::setContext(v8::Handle<v8::Context> context) { - // if we already have a context, clear it before setting the new one. - if (!m_context.IsEmpty()) { - m_context.Dispose(); - m_context.Clear(); - } - m_context = v8::Persistent<v8::Context>::New(context); + m_context.set(context); } bool V8DOMWindowShell::installDOMWindow(v8::Handle<v8::Context> context, DOMWindow* window) @@ -435,22 +415,13 @@ void V8DOMWindowShell::updateDocumentWrapper(v8::Handle<v8::Object> wrapper) { clearDocumentWrapper(); - ASSERT(m_document.IsEmpty()); - m_document = v8::Persistent<v8::Object>::New(wrapper); -#ifndef NDEBUG - V8GCController::registerGlobalHandle(PROXY, this, m_document); -#endif + ASSERT(m_document.get().IsEmpty()); + m_document.set(wrapper); } void V8DOMWindowShell::clearDocumentWrapper() { - if (!m_document.IsEmpty()) { -#ifndef NDEBUG - V8GCController::unregisterGlobalHandle(this, m_document); -#endif - m_document.Dispose(); - m_document.Clear(); - } + m_document.clear(); } static void checkDocumentWrapper(v8::Handle<v8::Object> wrapper, Document* document) @@ -462,7 +433,8 @@ static void checkDocumentWrapper(v8::Handle<v8::Object> wrapper, Document* docum void V8DOMWindowShell::updateDocumentWrapperCache() { v8::HandleScope handleScope; - v8::Context::Scope contextScope(m_context); + // FIXME: Should we use a new Local handle here? + v8::Context::Scope contextScope(m_context.get()); // If the document has no frame, NodeToV8Object might get the // document wrapper for a document that is about to be deleted. @@ -471,16 +443,17 @@ void V8DOMWindowShell::updateDocumentWrapperCache() // wrapper cleared. Using the cleared global handle will lead to // crashes. In this case we clear the cache and let the DOMWindow // accessor handle access to the document. + // FIXME: This should not be possible anymore. if (!m_frame->document()->frame()) { clearDocumentWrapperCache(); return; } v8::Handle<v8::Value> documentWrapper = toV8(m_frame->document()); - ASSERT(documentWrapper == m_document || m_document.IsEmpty()); - if (m_document.IsEmpty()) + ASSERT(documentWrapper == m_document.get() || m_document.get().IsEmpty()); + if (m_document.get().IsEmpty()) updateDocumentWrapper(v8::Handle<v8::Object>::Cast(documentWrapper)); - checkDocumentWrapper(m_document, m_frame->document()); + checkDocumentWrapper(m_document.get(), m_frame->document()); // If instantiation of the document wrapper fails, clear the cache // and let the DOMWindow accessor handle access to the document. @@ -489,27 +462,28 @@ void V8DOMWindowShell::updateDocumentWrapperCache() return; } ASSERT(documentWrapper->IsObject()); - m_context->Global()->ForceSet(v8::String::New("document"), documentWrapper, static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete)); + m_context.get()->Global()->ForceSet(v8::String::New("document"), documentWrapper, static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete)); // We also stash a reference to the document on the real global object so that // DOMWindow objects we obtain from JavaScript references are guaranteed to have // live Document objects. - v8::Handle<v8::Object> v8RealGlobal = v8::Handle<v8::Object>::Cast(m_context->Global()->GetPrototype()); + v8::Handle<v8::Object> v8RealGlobal = v8::Handle<v8::Object>::Cast(m_context.get()->Global()->GetPrototype()); v8RealGlobal->SetHiddenValue(V8HiddenPropertyName::document(), documentWrapper); } void V8DOMWindowShell::clearDocumentWrapperCache() { - ASSERT(!m_context.IsEmpty()); - m_context->Global()->ForceDelete(v8::String::New("document")); + ASSERT(!m_context.get().IsEmpty()); + m_context.get()->Global()->ForceDelete(v8::String::New("document")); } void V8DOMWindowShell::setSecurityToken() { Document* document = m_frame->document(); - // Setup security origin and security token. + + // FIXME: This shouldn't be possible anymore. if (!document) { - m_context->UseDefaultSecurityToken(); + m_context.get()->UseDefaultSecurityToken(); return; } @@ -529,22 +503,23 @@ void V8DOMWindowShell::setSecurityToken() // case, we use the global object as the security token to avoid // calling canAccess when a script accesses its own objects. if (token.isEmpty() || token == "null") { - m_context->UseDefaultSecurityToken(); + m_context.get()->UseDefaultSecurityToken(); return; } CString utf8Token = token.utf8(); // NOTE: V8 does identity comparison in fast path, must use a symbol // as the security token. - m_context->SetSecurityToken(v8::String::NewSymbol(utf8Token.data(), utf8Token.length())); + m_context.get()->SetSecurityToken(v8::String::NewSymbol(utf8Token.data(), utf8Token.length())); } void V8DOMWindowShell::updateDocument() { + // FIXME: This shouldn't be possible anymore. if (!m_frame->document()) return; - if (m_global.IsEmpty()) + if (m_global.get().IsEmpty()) return; // There is an existing JavaScript wrapper for the global object @@ -561,9 +536,9 @@ void V8DOMWindowShell::updateDocument() updateSecurityOrigin(); } -v8::Handle<v8::Value> getter(v8::Local<v8::String> property, const v8::AccessorInfo& info) +static v8::Handle<v8::Value> getter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { - // FIXME(antonm): consider passing AtomicStringImpl directly. + // FIXME: Consider passing AtomicStringImpl directly. AtomicString name = toWebCoreAtomicString(property); HTMLDocument* htmlDocument = V8HTMLDocument::toNative(info.Holder()); ASSERT(htmlDocument); @@ -576,40 +551,40 @@ v8::Handle<v8::Value> getter(v8::Local<v8::String> property, const v8::AccessorI return v8::Undefined(); } -void V8DOMWindowShell::namedItemAdded(HTMLDocument* doc, const AtomicString& name) +void V8DOMWindowShell::namedItemAdded(HTMLDocument* document, const AtomicString& name) { if (!initContextIfNeeded()) return; v8::HandleScope handleScope; - v8::Context::Scope contextScope(m_context); + v8::Context::Scope contextScope(m_context.get()); - ASSERT(!m_document.IsEmpty()); - checkDocumentWrapper(m_document, doc); - m_document->SetAccessor(v8String(name), getter); + ASSERT(!m_document.get().IsEmpty()); + checkDocumentWrapper(m_document.get(), document); + m_document.get()->SetAccessor(v8String(name), getter); } -void V8DOMWindowShell::namedItemRemoved(HTMLDocument* doc, const AtomicString& name) +void V8DOMWindowShell::namedItemRemoved(HTMLDocument* document, const AtomicString& name) { - if (doc->hasNamedItem(name.impl()) || doc->hasExtraNamedItem(name.impl())) + if (document->hasNamedItem(name.impl()) || document->hasExtraNamedItem(name.impl())) return; if (!initContextIfNeeded()) return; v8::HandleScope handleScope; - v8::Context::Scope contextScope(m_context); + v8::Context::Scope contextScope(m_context.get()); - ASSERT(!m_document.IsEmpty()); - checkDocumentWrapper(m_document, doc); - m_document->Delete(v8String(name)); + ASSERT(!m_document.get().IsEmpty()); + checkDocumentWrapper(m_document.get(), document); + m_document.get()->Delete(v8String(name)); } void V8DOMWindowShell::updateSecurityOrigin() { - if (m_context.IsEmpty()) + if (m_context.get().IsEmpty()) return; - v8::HandleScope scope; + v8::HandleScope handleScope; setSecurityToken(); } diff --git a/Source/WebCore/bindings/v8/V8DOMWindowShell.h b/Source/WebCore/bindings/v8/V8DOMWindowShell.h index b25bbfc48..e2ff81937 100644 --- a/Source/WebCore/bindings/v8/V8DOMWindowShell.h +++ b/Source/WebCore/bindings/v8/V8DOMWindowShell.h @@ -31,6 +31,7 @@ #ifndef V8DOMWindowShell_h #define V8DOMWindowShell_h +#include "ScopedPersistent.h" #include "V8PerContextData.h" #include "WrapperTypeInfo.h" #include <wtf/Forward.h> @@ -52,7 +53,7 @@ class V8DOMWindowShell : public RefCounted<V8DOMWindowShell> { public: static PassRefPtr<V8DOMWindowShell> create(Frame*); - v8::Handle<v8::Context> context() const { return m_context; } + v8::Handle<v8::Context> context() const { return m_context.get(); } // Update document object of the frame. void updateDocument(); @@ -99,9 +100,9 @@ private: OwnPtr<V8PerContextData> m_perContextData; - v8::Persistent<v8::Context> m_context; - v8::Persistent<v8::Object> m_global; - v8::Persistent<v8::Object> m_document; + ScopedPersistent<v8::Context> m_context; + ScopedPersistent<v8::Object> m_global; + ScopedPersistent<v8::Object> m_document; }; } // namespace WebCore diff --git a/Source/WebCore/bindings/v8/V8DOMWrapper.h b/Source/WebCore/bindings/v8/V8DOMWrapper.h index f66e89e49..25c14d694 100644 --- a/Source/WebCore/bindings/v8/V8DOMWrapper.h +++ b/Source/WebCore/bindings/v8/V8DOMWrapper.h @@ -53,9 +53,7 @@ namespace WebCore { class Frame; class Node; class V8PerContextData; - class V8Proxy; class WorkerContext; - class XPathResolver; enum ListenerLookupType { ListenerFindOnly, diff --git a/Source/WebCore/bindings/v8/V8ObjectConstructor.cpp b/Source/WebCore/bindings/v8/V8ObjectConstructor.cpp index f7877450a..d390185ca 100644 --- a/Source/WebCore/bindings/v8/V8ObjectConstructor.cpp +++ b/Source/WebCore/bindings/v8/V8ObjectConstructor.cpp @@ -74,8 +74,7 @@ v8::Local<v8::Object> V8ObjectConstructor::newInstanceInDocument(v8::Handle<v8:: TRACE_EVENT0("v8", "v8.newInstance"); #endif - // No artificial limitations on the depth of recursion, see comment in - // V8Proxy::callFunction. + // No artificial limitations on the depth of recursion. V8RecursionScope recursionScope(document); v8::Local<v8::Object> result = function->NewInstance(argc, argv); crashIfV8IsDead(); diff --git a/Source/WebCore/bindings/v8/V8PerContextData.h b/Source/WebCore/bindings/v8/V8PerContextData.h index c8cd6a5c6..20e910c16 100644 --- a/Source/WebCore/bindings/v8/V8PerContextData.h +++ b/Source/WebCore/bindings/v8/V8PerContextData.h @@ -31,7 +31,7 @@ #ifndef V8PerContextData_h #define V8PerContextData_h -#include "OwnHandle.h" +#include "ScopedPersistent.h" #include "WrapperTypeInfo.h" #include <v8.h> #include <wtf/HashMap.h> @@ -90,8 +90,8 @@ private: ConstructorMap m_constructorMap; v8::Handle<v8::Context> m_context; - OwnHandle<v8::Value> m_errorPrototype; - OwnHandle<v8::Value> m_objectPrototype; + ScopedPersistent<v8::Value> m_errorPrototype; + ScopedPersistent<v8::Value> m_objectPrototype; }; } // namespace WebCore diff --git a/Source/WebCore/bindings/v8/V8Proxy.cpp b/Source/WebCore/bindings/v8/V8Proxy.cpp deleted file mode 100644 index ed36d8675..000000000 --- a/Source/WebCore/bindings/v8/V8Proxy.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2008, 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "V8Proxy.h" - -#include "BindingState.h" -#include "CachedMetadata.h" -#include "DateExtension.h" -#include "Document.h" -#include "DocumentLoader.h" -#include "ExceptionHeaders.h" -#include "ExceptionInterfaces.h" -#include "Frame.h" -#include "FrameLoaderClient.h" -#include "IDBFactoryBackendInterface.h" -#include "InspectorInstrumentation.h" -#include "PlatformSupport.h" -#include "ScriptCallStack.h" -#include "ScriptCallStackFactory.h" -#include "ScriptRunner.h" -#include "ScriptSourceCode.h" -#include "SecurityOrigin.h" -#include "Settings.h" -#include "StylePropertySet.h" -#include "V8Binding.h" -#include "V8Collection.h" -#include "V8DOMCoreException.h" -#include "V8DOMMap.h" -#include "V8DOMWindow.h" -#include "V8HiddenPropertyName.h" -#include "V8IsolatedContext.h" -#include "V8RecursionScope.h" -#include "WorkerContext.h" -#include "WorkerContextExecutionProxy.h" - -#include <algorithm> -#include <stdio.h> -#include <utility> -#include <wtf/Assertions.h> -#include <wtf/OwnArrayPtr.h> -#include <wtf/OwnPtr.h> -#include <wtf/StdLibExtras.h> -#include <wtf/StringExtras.h> -#include <wtf/UnusedParam.h> -#include <wtf/text/WTFString.h> - -#if PLATFORM(CHROMIUM) -#include "TraceEvent.h" -#endif - -namespace WebCore { - -V8Proxy::V8Proxy(Frame* frame) - : m_frame(frame) -{ -} - -V8Proxy::~V8Proxy() -{ - windowShell()->destroyGlobal(); -} - -V8DOMWindowShell* V8Proxy::windowShell() const -{ - return frame()->script()->windowShell(); -} - -} // namespace WebCore diff --git a/Source/WebCore/bindings/v8/V8Proxy.h b/Source/WebCore/bindings/v8/V8Proxy.h deleted file mode 100644 index 07a7781e2..000000000 --- a/Source/WebCore/bindings/v8/V8Proxy.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef V8Proxy_h -#define V8Proxy_h - -#include "PlatformSupport.h" -#include "SharedPersistent.h" -#include "StatsCounter.h" -#include "V8AbstractEventListener.h" -#include "V8DOMWrapper.h" -#include "V8GCController.h" -#include "V8Utilities.h" -#include "WrapperTypeInfo.h" -#include <v8.h> -#include <wtf/Forward.h> -#include <wtf/HashMap.h> -#include <wtf/PassRefPtr.h> // so generated bindings don't have to -#include <wtf/Vector.h> -#include <wtf/text/TextPosition.h> - -namespace WebCore { - - class CachedScript; - class DOMWindow; - class Frame; - class Node; - class ScriptExecutionContext; - class ScriptSourceCode; - class SecurityOrigin; - class V8DOMWindowShell; - class V8EventListener; - class V8IsolatedContext; - class V8PerContextData; - class WorldContextHandle; - - // Note: although the pointer is raw, the instance is kept alive by a strong - // reference to the v8 context it contains, which is not made weak until we - // call world->destroy(). - // - // FIXME: We want to eventually be holding window shells instead of the - // IsolatedContext directly. - typedef HashMap<int, V8IsolatedContext*> IsolatedWorldMap; - - typedef HashMap<int, RefPtr<SecurityOrigin> > IsolatedWorldSecurityOriginMap; - - class V8Proxy { - public: - explicit V8Proxy(Frame*); - - ~V8Proxy(); - - Frame* frame() const { return m_frame; } - - // FIXME: This should eventually take DOMWrapperWorld argument! - // FIXME: This method will be soon removed, as all methods that access windowShell() - // will be moved to ScriptController. - V8DOMWindowShell* windowShell() const; - private: - Frame* m_frame; - }; -} - -#endif // V8Proxy_h diff --git a/Source/WebCore/bindings/v8/V8RecursionScope.h b/Source/WebCore/bindings/v8/V8RecursionScope.h index 78b3f2b75..64c6c8aed 100644 --- a/Source/WebCore/bindings/v8/V8RecursionScope.h +++ b/Source/WebCore/bindings/v8/V8RecursionScope.h @@ -46,7 +46,7 @@ namespace WebCore { // // Debug-time checking of this is enforced via this class. // -// Calls of type (1) should generally go through V8Proxy, as inspector +// Calls of type (1) should generally go through ScriptController, 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::MicrotaskSuppression -- this diff --git a/Source/WebCore/bindings/v8/V8Utilities.cpp b/Source/WebCore/bindings/v8/V8Utilities.cpp index 0a45dddf0..4621818e6 100644 --- a/Source/WebCore/bindings/v8/V8Utilities.cpp +++ b/Source/WebCore/bindings/v8/V8Utilities.cpp @@ -38,6 +38,7 @@ #include "MessagePort.h" #include "ScriptExecutionContext.h" #include "ScriptState.h" +#include "V8AbstractEventListener.h" #include "V8ArrayBuffer.h" #include "V8Binding.h" #include "V8MessagePort.h" diff --git a/Source/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.h b/Source/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.h index 72260e4b8..03f07e926 100644 --- a/Source/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.h +++ b/Source/WebCore/bindings/v8/custom/V8CustomXPathNSResolver.h @@ -39,8 +39,6 @@ namespace WebCore { -class V8Proxy; - // V8CustomXPathNSResolver does not create a persistent handle to the // given resolver object. So the lifetime of V8CustomXPathNSResolver // must not exceed the lifetime of the passed handle. |