diff options
Diffstat (limited to 'WebCore/bindings/v8')
23 files changed, 380 insertions, 219 deletions
diff --git a/WebCore/bindings/v8/DOMData.h b/WebCore/bindings/v8/DOMData.h index 4d7331b..c8b4a41 100644 --- a/WebCore/bindings/v8/DOMData.h +++ b/WebCore/bindings/v8/DOMData.h @@ -79,14 +79,25 @@ namespace WebCore { template<typename T> void DOMData::handleWeakObject(DOMDataStore::DOMWrapperMapType mapType, v8::Persistent<v8::Object> v8Object, T* domObject) { + WrapperTypeInfo* type = V8DOMWrapper::domWrapperType(v8Object); DOMDataList& list = DOMDataStore::allStores(); + bool found = false; for (size_t i = 0; i < list.size(); ++i) { DOMDataStore* store = list[i]; ASSERT(store->domData()->owningThread() == WTF::currentThread()); DOMWrapperMap<T>* domMap = static_cast<DOMWrapperMap<T>*>(store->getDOMWrapperMap(mapType)); - if (domMap->removeIfPresent(domObject, v8Object)) - store->domData()->derefObject(V8DOMWrapper::domWrapperType(v8Object), domObject); + if (domMap->removeIfPresent(domObject, v8Object)) { + derefObject(type, domObject); + found = true; + } + } + + // If not found, it means map for the wrapper has been already destroyed, just dispose the + // handle and deref the object to fight memory leak. + if (!found) { + v8Object.Dispose(); + derefObject(type, domObject); } } diff --git a/WebCore/bindings/v8/DOMDataStore.cpp b/WebCore/bindings/v8/DOMDataStore.cpp index 5d609d8..0b06a69 100644 --- a/WebCore/bindings/v8/DOMDataStore.cpp +++ b/WebCore/bindings/v8/DOMDataStore.cpp @@ -163,10 +163,15 @@ void DOMDataStore::weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* do DOMDataStore* store = list[i]; if (store->domNodeMap().removeIfPresent(node, v8Object)) { ASSERT(store->domData()->owningThread() == WTF::currentThread()); - node->deref(); // Nobody overrides Node::deref so it's safe - break; // There might be at most one wrapper for the node in world's maps + node->deref(); // Nobody overrides Node::deref so it's safe + return; // There might be at most one wrapper for the node in world's maps } } + + // If not found, it means map for the wrapper has been already destroyed, just dispose the + // handle and deref the object to fight memory leak. + v8Object.Dispose(); + node->deref(); // Nobody overrides Node::deref so it's safe } bool DOMDataStore::IntrusiveDOMWrapperMap::removeIfPresent(Node* obj, v8::Persistent<v8::Data> value) diff --git a/WebCore/bindings/v8/ScriptArray.cpp b/WebCore/bindings/v8/ScriptArray.cpp index a199a6c..7119b27 100644 --- a/WebCore/bindings/v8/ScriptArray.cpp +++ b/WebCore/bindings/v8/ScriptArray.cpp @@ -31,11 +31,11 @@ #include "config.h" #include "ScriptArray.h" -#include "ScriptScope.h" -#include "ScriptState.h" - #include "Document.h" #include "Frame.h" +#include "ScriptScope.h" +#include "ScriptState.h" +#include "SerializedScriptValue.h" #include "V8Binding.h" #include "V8Proxy.h" @@ -57,6 +57,19 @@ bool ScriptArray::set(unsigned index, const ScriptObject& value) return scope.success(); } +bool ScriptArray::set(unsigned index, SerializedScriptValue* value) +{ + ScriptValue scriptValue = ScriptValue::deserialize(m_scriptState, value); + if (scriptValue.hasNoValue()) { + ASSERT_NOT_REACHED(); + return false; + } + + ScriptScope scope(m_scriptState); + v8Object()->Set(v8::Integer::New(index), scriptValue.v8Value()); + return scope.success(); +} + bool ScriptArray::set(unsigned index, const String& value) { ScriptScope scope(m_scriptState); diff --git a/WebCore/bindings/v8/ScriptArray.h b/WebCore/bindings/v8/ScriptArray.h index 9f40fbf..9aa8764 100644 --- a/WebCore/bindings/v8/ScriptArray.h +++ b/WebCore/bindings/v8/ScriptArray.h @@ -36,24 +36,26 @@ #include <v8.h> namespace WebCore { - class ScriptState; - - class ScriptArray : public ScriptObject { - public: - ScriptArray(ScriptState* scriptState, v8::Handle<v8::Array>); - ScriptArray() {}; - virtual ~ScriptArray() {} - - bool set(unsigned index, const ScriptObject&); - bool set(unsigned index, const String&); - bool set(unsigned index, double); - bool set(unsigned index, long long); - bool set(unsigned index, int); - bool set(unsigned index, bool); - unsigned length(); - - static ScriptArray createNew(ScriptState*); - }; +class ScriptState; +class SerializedScriptValue; + +class ScriptArray : public ScriptObject { +public: + ScriptArray(ScriptState* scriptState, v8::Handle<v8::Array>); + ScriptArray() {}; + virtual ~ScriptArray() {} + + bool set(unsigned index, const ScriptObject&); + bool set(unsigned index, SerializedScriptValue*); + bool set(unsigned index, const String&); + bool set(unsigned index, double); + bool set(unsigned index, long long); + bool set(unsigned index, int); + bool set(unsigned index, bool); + unsigned length(); + + static ScriptArray createNew(ScriptState*); +}; } #endif // ScriptArray_h diff --git a/WebCore/bindings/v8/ScriptCallFrame.cpp b/WebCore/bindings/v8/ScriptCallFrame.cpp index 4c29814..9554f67 100644 --- a/WebCore/bindings/v8/ScriptCallFrame.cpp +++ b/WebCore/bindings/v8/ScriptCallFrame.cpp @@ -45,10 +45,17 @@ ScriptCallFrame::ScriptCallFrame(const String& functionName, const String& urlSt , m_sourceURL(ParsedURLString, urlString) , m_lineNumber(lineNumber) { - for (int i = 0; i < arguments.Length(); ++i) + for (int i = skipArgumentCount; i < arguments.Length(); ++i) m_arguments.append(ScriptValue(arguments[i])); } +ScriptCallFrame::ScriptCallFrame(const String& functionName, const String& urlString, int lineNumber) + : m_functionName(functionName) + , m_sourceURL(ParsedURLString, urlString) + , m_lineNumber(lineNumber) +{ +} + ScriptCallFrame::~ScriptCallFrame() { } diff --git a/WebCore/bindings/v8/ScriptCallFrame.h b/WebCore/bindings/v8/ScriptCallFrame.h index 50357cf..8d1972f 100644 --- a/WebCore/bindings/v8/ScriptCallFrame.h +++ b/WebCore/bindings/v8/ScriptCallFrame.h @@ -50,6 +50,7 @@ namespace WebCore { class ScriptCallFrame { public: ScriptCallFrame(const String& functionName, const String& urlString, int lineNumber, const v8::Arguments&, unsigned skipArgumentCount); + ScriptCallFrame(const String& functionName, const String& urlString, int lineNumber); ~ScriptCallFrame(); const ScriptString& functionName() const { return m_functionName; } diff --git a/WebCore/bindings/v8/ScriptCallStack.cpp b/WebCore/bindings/v8/ScriptCallStack.cpp index d62175a..98ddb90 100644 --- a/WebCore/bindings/v8/ScriptCallStack.cpp +++ b/WebCore/bindings/v8/ScriptCallStack.cpp @@ -32,68 +32,122 @@ #include "ScriptCallStack.h" #include "InspectorValues.h" -#include "ScriptScope.h" #include "ScriptController.h" #include "ScriptDebugServer.h" +#include "ScriptScope.h" #include "V8Binding.h" #include <v8-debug.h> namespace WebCore { -ScriptCallStack* ScriptCallStack::create(const v8::Arguments& arguments, unsigned skipArgumentCount) { - String sourceName; - int sourceLineNumber; - String funcName; - if (!callLocation(&sourceName, &sourceLineNumber, &funcName)) - return 0; - return new ScriptCallStack(arguments, skipArgumentCount, sourceName, sourceLineNumber, funcName); -} - -bool ScriptCallStack::callLocation(String* sourceName, int* sourceLineNumber, String* functionName) +static void getFrameLocation(v8::Handle<v8::StackFrame> frame, String* sourceName, int* sourceLineNumber, String* functionName) { - v8::HandleScope scope; - v8::Context::Scope contextScope(v8::Context::GetCurrent()); - v8::Handle<v8::StackTrace> stackTrace(v8::StackTrace::CurrentStackTrace(1)); - if (stackTrace.IsEmpty()) - return false; - if (stackTrace->GetFrameCount() <= 0) { - // Successfully grabbed stack trace, but there are no frames. - // Fallback to setting lineNumber to 0, and source and function name to "undefined". - *sourceName = toWebCoreString(v8::Undefined()); - *sourceLineNumber = 0; - *functionName = toWebCoreString(v8::Undefined()); - return true; - } - v8::Handle<v8::StackFrame> frame = stackTrace->GetFrame(0); - // There must be at least one valid frame. ASSERT(!frame.IsEmpty()); v8::Local<v8::String> sourceNameValue(frame->GetScriptName()); v8::Local<v8::String> functionNameValue(frame->GetFunctionName()); *sourceName = sourceNameValue.IsEmpty() ? "" : toWebCoreString(sourceNameValue); *functionName = functionNameValue.IsEmpty() ? "" : toWebCoreString(functionNameValue); *sourceLineNumber = frame->GetLineNumber(); - return true; } -ScriptCallStack::ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount, String sourceName, int sourceLineNumber, String functionName) - : m_lastCaller(functionName, sourceName, sourceLineNumber, arguments, skipArgumentCount) - , m_scriptState(ScriptState::current()) +static void getTopFrameLocation(v8::Handle<v8::StackTrace> stackTrace, String* sourceName, int* sourceLineNumber, String* functionName) +{ + if (stackTrace->GetFrameCount() <= 0) { + // Successfully grabbed stack trace, but there are no frames. It may happen in case of a syntax error for example. + // Fallback to setting lineNumber to 0, and source and function name to "undefined". + *sourceName = "undefined"; + *sourceLineNumber = 0; + *functionName = "undefined"; + } else { + v8::Handle<v8::StackFrame> frame = stackTrace->GetFrame(0); + getFrameLocation(frame, sourceName, sourceLineNumber, functionName); + } +} + +static PassOwnPtr<ScriptCallFrame> toScriptCallFrame(v8::Handle<v8::StackFrame> frame) +{ + String sourceName; + int sourceLineNumber; + String functionName; + getFrameLocation(frame, &sourceName, &sourceLineNumber, &functionName); + return new ScriptCallFrame(functionName, sourceName, sourceLineNumber); +} + +static void toScriptCallFramesVector(v8::Local<v8::Context> context, v8::Handle<v8::StackTrace> stackTrace, Vector<OwnPtr<ScriptCallFrame> >& scriptCallFrames) +{ + v8::Context::Scope contextScope(context); + int frameCount = stackTrace->GetFrameCount(); + for (int i = 0; i < frameCount; i++) { + v8::Local<v8::StackFrame> stackFrame = stackTrace->GetFrame(i); + scriptCallFrames.append(toScriptCallFrame(stackFrame)); + } +} + +const int ScriptCallStack::maxCallStackSizeToCapture = 200; + +PassOwnPtr<ScriptCallStack> ScriptCallStack::create(const v8::Arguments& arguments, unsigned skipArgumentCount, int framCountLimit) +{ + v8::HandleScope scope; + v8::Local<v8::Context> context = v8::Context::GetCurrent(); + v8::Context::Scope contextScope(context); + v8::Handle<v8::StackTrace> stackTrace(v8::StackTrace::CurrentStackTrace(framCountLimit)); + + if (stackTrace.IsEmpty()) + return 0; + + String sourceName; + int sourceLineNumber; + String functionName; + getTopFrameLocation(stackTrace, &sourceName, &sourceLineNumber, &functionName); + + Vector<OwnPtr<ScriptCallFrame> > scriptCallFrames; + if (framCountLimit > 1) + toScriptCallFramesVector(context, stackTrace, scriptCallFrames); + + return new ScriptCallStack(ScriptState::forContext(context), new ScriptCallFrame(functionName, sourceName, sourceLineNumber, arguments, skipArgumentCount), scriptCallFrames); +} + +PassOwnPtr<ScriptCallStack> ScriptCallStack::create(ScriptState* state, v8::Handle<v8::StackTrace> stackTrace) +{ + v8::HandleScope scope; + Vector<OwnPtr<ScriptCallFrame> > scriptCallFrames; + toScriptCallFramesVector(state->context(), stackTrace, scriptCallFrames); + + String sourceName; + int sourceLineNumber; + String functionName; + getTopFrameLocation(stackTrace, &sourceName, &sourceLineNumber, &functionName); + + return new ScriptCallStack(state, new ScriptCallFrame(functionName, sourceName, sourceLineNumber), scriptCallFrames); +} + +ScriptCallStack::ScriptCallStack(ScriptState* scriptState, PassOwnPtr<ScriptCallFrame> topFrame, Vector<OwnPtr<ScriptCallFrame> >& scriptCallFrames) + : m_topFrame(topFrame) + , m_scriptState(scriptState) { + m_scriptCallFrames.swap(scriptCallFrames); } ScriptCallStack::~ScriptCallStack() { } -const ScriptCallFrame& ScriptCallStack::at(unsigned index) const +const ScriptCallFrame& ScriptCallStack::at(unsigned index) { - // Currently, only one ScriptCallFrame is supported. When we can get - // a full stack trace from V8, we can do this right. - ASSERT(index == 0); - return m_lastCaller; + if (!index && m_topFrame) + return *m_topFrame; + return *m_scriptCallFrames.at(index); } +unsigned ScriptCallStack::size() +{ + if (m_scriptCallFrames.isEmpty()) + return 1; + return m_scriptCallFrames.size(); +} + + bool ScriptCallStack::stackTrace(int frameLimit, const RefPtr<InspectorArray>& stackTrace) { #if ENABLE(INSPECTOR) diff --git a/WebCore/bindings/v8/ScriptCallStack.h b/WebCore/bindings/v8/ScriptCallStack.h index 80d5f76..b608563 100644 --- a/WebCore/bindings/v8/ScriptCallStack.h +++ b/WebCore/bindings/v8/ScriptCallStack.h @@ -48,7 +48,10 @@ class InspectorArray; class ScriptCallStack : public Noncopyable { public: - static ScriptCallStack* create(const v8::Arguments&, unsigned skipArgumentCount = 0); + static const int maxCallStackSizeToCapture; + + static PassOwnPtr<ScriptCallStack> create(const v8::Arguments&, unsigned skipArgumentCount = 0, int framCountLimit = 1); + static PassOwnPtr<ScriptCallStack> create(ScriptState*, v8::Handle<v8::StackTrace>); ~ScriptCallStack(); // Returns false if there is no running JavaScript or if fetching the stack failed. @@ -62,20 +65,19 @@ public: // } static bool stackTrace(int frameLimit, const RefPtr<InspectorArray>& stackTrace); - const ScriptCallFrame& at(unsigned) const; - // FIXME: implement retrieving and storing call stack trace - unsigned size() const { return 1; } + const ScriptCallFrame& at(unsigned); + unsigned size(); ScriptState* state() const { return m_scriptState; } ScriptState* globalState() const { return m_scriptState; } private: - ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount, String sourceName, int sourceLineNumber, String funcName); - - static bool callLocation(String* sourceName, int* sourceLineNumber, String* functionName); + ScriptCallStack(ScriptState* scriptState, PassOwnPtr<ScriptCallFrame> topFrame, Vector<OwnPtr<ScriptCallFrame> >& scriptCallFrames); + ScriptCallStack(ScriptState* scriptState, v8::Handle<v8::StackTrace> stackTrace); - ScriptCallFrame m_lastCaller; + OwnPtr<ScriptCallFrame> m_topFrame; ScriptState* m_scriptState; + Vector<OwnPtr<ScriptCallFrame> > m_scriptCallFrames; }; } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptController.cpp b/WebCore/bindings/v8/ScriptController.cpp index 2396de0..a27c5cf 100644 --- a/WebCore/bindings/v8/ScriptController.cpp +++ b/WebCore/bindings/v8/ScriptController.cpp @@ -34,6 +34,7 @@ #include "PlatformBridge.h" #include "Document.h" +#include "ScriptCallStack.h" #include "ScriptableDocumentParser.h" #include "DOMWindow.h" #include "Event.h" @@ -464,6 +465,13 @@ void ScriptController::clearWindowShell(bool) m_proxy->clearForNavigation(); } +#if ENABLE(INSPECTOR) +void ScriptController::setCaptureCallStackForUncaughtExceptions(bool) +{ + v8::V8::SetCaptureStackTraceForUncaughtExceptions(true, ScriptCallStack::maxCallStackSizeToCapture); +} +#endif + void ScriptController::attachDebugger(void*) { notImplemented(); @@ -476,12 +484,10 @@ void ScriptController::updateDocument() void ScriptController::namedItemAdded(HTMLDocument* doc, const AtomicString& name) { - m_proxy->windowShell()->namedItemAdded(doc, name); } void ScriptController::namedItemRemoved(HTMLDocument* doc, const AtomicString& name) { - m_proxy->windowShell()->namedItemRemoved(doc, name); } } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptController.h b/WebCore/bindings/v8/ScriptController.h index 75ae0bf..04a15f6 100644 --- a/WebCore/bindings/v8/ScriptController.h +++ b/WebCore/bindings/v8/ScriptController.h @@ -116,6 +116,10 @@ public: static bool canAccessFromCurrentOrigin(Frame*); +#if ENABLE(INSPECTOR) + static void setCaptureCallStackForUncaughtExceptions(bool); +#endif + bool canExecuteScripts(ReasonForCallingCanExecuteScripts); // FIXME: void* is a compile hack. diff --git a/WebCore/bindings/v8/ScriptDebugServer.cpp b/WebCore/bindings/v8/ScriptDebugServer.cpp index 138237b..0a432b7 100644 --- a/WebCore/bindings/v8/ScriptDebugServer.cpp +++ b/WebCore/bindings/v8/ScriptDebugServer.cpp @@ -44,7 +44,6 @@ namespace WebCore { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) static Frame* retrieveFrame(v8::Handle<v8::Context> context) { if (context.IsEmpty()) @@ -61,7 +60,6 @@ static Frame* retrieveFrame(v8::Handle<v8::Context> context) return V8Proxy::retrieveFrame(context); } -#endif ScriptDebugServer& ScriptDebugServer::shared() { @@ -83,9 +81,13 @@ void ScriptDebugServer::setDebuggerScriptSource(const String& scriptSource) void ScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page) { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) if (!m_enabled) return; + + V8Proxy* proxy = V8Proxy::retrieve(page->mainFrame()); + if (!proxy) + return; + v8::HandleScope scope; v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); v8::Context::Scope contextScope(debuggerContext); @@ -96,7 +98,7 @@ void ScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page) v8::Debug::SetDebugEventListener2(&ScriptDebugServer::v8DebugEventCallback); } m_listenersMap.set(page, listener); - V8Proxy* proxy = V8Proxy::retrieve(page->mainFrame()); + v8::Local<v8::Context> context = proxy->mainWorldContext(); v8::Handle<v8::Function> getScriptsFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("getScripts"))); @@ -108,7 +110,6 @@ void ScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page) v8::Handle<v8::Array> scriptsArray = v8::Handle<v8::Array>::Cast(value); for (unsigned i = 0; i < scriptsArray->Length(); ++i) dispatchDidParseSource(listener, v8::Handle<v8::Object>::Cast(scriptsArray->Get(v8::Integer::New(i)))); -#endif } void ScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* page) @@ -128,7 +129,6 @@ void ScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* page bool ScriptDebugServer::setBreakpoint(const String& sourceID, ScriptBreakpoint breakpoint, unsigned lineNumber, unsigned* actualLineNumber) { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) v8::HandleScope scope; v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); v8::Context::Scope contextScope(debuggerContext); @@ -146,14 +146,10 @@ bool ScriptDebugServer::setBreakpoint(const String& sourceID, ScriptBreakpoint b ASSERT(result->Int32Value() >= 0); *actualLineNumber = result->Int32Value(); return true; -#else - return false; -#endif } void ScriptDebugServer::removeBreakpoint(const String& sourceID, unsigned lineNumber) { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) v8::HandleScope scope; v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); v8::Context::Scope contextScope(debuggerContext); @@ -164,12 +160,10 @@ void ScriptDebugServer::removeBreakpoint(const String& sourceID, unsigned lineNu v8::Handle<v8::Function> removeBreakpointFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("removeBreakpoint"))); v8::Debug::Call(removeBreakpointFunction, args); -#endif } void ScriptDebugServer::clearBreakpoints() { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) ensureDebuggerScriptCompiled(); v8::HandleScope scope; v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); @@ -177,12 +171,10 @@ void ScriptDebugServer::clearBreakpoints() v8::Handle<v8::Function> clearBreakpoints = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("clearBreakpoints"))); v8::Debug::Call(clearBreakpoints); -#endif } void ScriptDebugServer::setBreakpointsActivated(bool enabled) { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) ensureDebuggerScriptCompiled(); v8::HandleScope scope; v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); @@ -192,12 +184,10 @@ void ScriptDebugServer::setBreakpointsActivated(bool enabled) args->Set(v8::String::New("enabled"), v8::Boolean::New(enabled)); v8::Handle<v8::Function> setBreakpointsActivated = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("setBreakpointsActivated"))); v8::Debug::Call(setBreakpointsActivated, args); -#endif } ScriptDebugServer::PauseOnExceptionsState ScriptDebugServer::pauseOnExceptionsState() { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) ensureDebuggerScriptCompiled(); v8::HandleScope scope; v8::Context::Scope contextScope(v8::Debug::GetDebugContext()); @@ -206,14 +196,10 @@ ScriptDebugServer::PauseOnExceptionsState ScriptDebugServer::pauseOnExceptionsSt v8::Handle<v8::Value> argv[] = { v8::Handle<v8::Value>() }; v8::Handle<v8::Value> result = function->Call(m_debuggerScript.get(), 0, argv); return static_cast<ScriptDebugServer::PauseOnExceptionsState>(result->Int32Value()); -#else - return DontPauseOnExceptions; -#endif } void ScriptDebugServer::setPauseOnExceptionsState(PauseOnExceptionsState pauseOnExceptionsState) { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) ensureDebuggerScriptCompiled(); v8::HandleScope scope; v8::Context::Scope contextScope(v8::Debug::GetDebugContext()); @@ -221,54 +207,44 @@ void ScriptDebugServer::setPauseOnExceptionsState(PauseOnExceptionsState pauseOn 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); -#endif } void ScriptDebugServer::continueProgram() { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) if (m_pausedPage) m_clientMessageLoop->quitNow(); didResume(); -#endif } void ScriptDebugServer::stepIntoStatement() { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) ASSERT(m_pausedPage); 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); continueProgram(); -#endif } void ScriptDebugServer::stepOverStatement() { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) ASSERT(m_pausedPage); 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); continueProgram(); -#endif } void ScriptDebugServer::stepOutOfFunction() { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) ASSERT(m_pausedPage); 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); continueProgram(); -#endif } bool ScriptDebugServer::editScriptSource(const String& sourceID, const String& newContent, String& newSourceOrErrorMessage) { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) ensureDebuggerScriptCompiled(); v8::HandleScope scope; @@ -295,9 +271,6 @@ bool ScriptDebugServer::editScriptSource(const String& sourceID, const String& n if (m_currentCallFrame) m_currentCallFrame.clear(); return true; -#else - return false; -#endif } PassRefPtr<JavaScriptCallFrame> ScriptDebugServer::currentCallFrame() @@ -321,7 +294,6 @@ bool ScriptDebugServer::isDebuggerAlwaysEnabled() return m_enabled; } -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) void ScriptDebugServer::v8DebugEventCallback(const v8::Debug::EventDetails& eventDetails) { ScriptDebugServer::shared().handleV8DebugEvent(eventDetails); @@ -376,7 +348,6 @@ void ScriptDebugServer::handleV8DebugEvent(const v8::Debug::EventDetails& eventD } } } -#endif void ScriptDebugServer::dispatchDidParseSource(ScriptDebugListener* listener, v8::Handle<v8::Object> object) { diff --git a/WebCore/bindings/v8/ScriptDebugServer.h b/WebCore/bindings/v8/ScriptDebugServer.h index 26ca785..a55388f 100644 --- a/WebCore/bindings/v8/ScriptDebugServer.h +++ b/WebCore/bindings/v8/ScriptDebugServer.h @@ -59,6 +59,8 @@ public: void removeBreakpoint(const String& sourceID, unsigned lineNumber); void clearBreakpoints(); void setBreakpointsActivated(bool activated); + void activateBreakpoints() { setBreakpointsActivated(true); } + void deactivateBreakpoints() { setBreakpointsActivated(false); } enum PauseOnExceptionsState { DontPauseOnExceptions, @@ -68,7 +70,7 @@ public: PauseOnExceptionsState pauseOnExceptionsState(); void setPauseOnExceptionsState(PauseOnExceptionsState pauseOnExceptionsState); - void pauseProgram() { } + void pause() { } void continueProgram(); void stepIntoStatement(); void stepOverStatement(); @@ -101,10 +103,8 @@ private: ScriptDebugServer(); ~ScriptDebugServer() { } -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) static void v8DebugEventCallback(const v8::Debug::EventDetails& eventDetails); void handleV8DebugEvent(const v8::Debug::EventDetails& eventDetails); -#endif void dispatchDidParseSource(ScriptDebugListener* listener, v8::Handle<v8::Object> sourceObject); diff --git a/WebCore/bindings/v8/ScriptSourceCode.h b/WebCore/bindings/v8/ScriptSourceCode.h index 485daea..dbc9d5e 100644 --- a/WebCore/bindings/v8/ScriptSourceCode.h +++ b/WebCore/bindings/v8/ScriptSourceCode.h @@ -46,14 +46,6 @@ public: , m_url(url) , m_startLine(startLine) { - // FIXME: Copying the source to strip BOMs isn't strictly necessary - // because V8 treats BOMs as whitespace. However, it is here because it - // must be in sync with CachedScript::script() which strips the BOMs. We - // should investigate the performance implications. - if (m_source.length()) { - bool scratch = false; - m_source = String(source.impl()->copyStringWithoutBOMs(false, scratch)); - } } // We lose the encoding information from CachedScript. diff --git a/WebCore/bindings/v8/V8ConsoleMessage.cpp b/WebCore/bindings/v8/V8ConsoleMessage.cpp index d9fe069..8b6bb17 100644 --- a/WebCore/bindings/v8/V8ConsoleMessage.cpp +++ b/WebCore/bindings/v8/V8ConsoleMessage.cpp @@ -36,6 +36,7 @@ #include "Frame.h" #include "OwnPtr.h" #include "Page.h" +#include "ScriptCallStack.h" #include "V8Binding.h" #include "V8Proxy.h" @@ -52,14 +53,7 @@ V8ConsoleMessage::V8ConsoleMessage(const String& string, const String& sourceID, void V8ConsoleMessage::dispatchNow(Page* page) { - ASSERT(page); - - // Process any delayed messages to make sure that messages - // appear in the right order in the console. - processDelayed(); - - Console* console = page->mainFrame()->domWindow()->console(); - console->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, m_string, m_lineNumber, m_sourceID); + dispatchNow(page, 0); } void V8ConsoleMessage::dispatchLater() @@ -118,11 +112,33 @@ void V8ConsoleMessage::handler(v8::Handle<v8::Message> message, v8::Handle<v8::V ASSERT(!errorMessageString.IsEmpty()); String errorMessage = toWebCoreString(errorMessageString); + v8::Handle<v8::StackTrace> stackTrace = message->GetStackTrace(); + OwnPtr<ScriptCallStack> callStack; + // Currently stack trace is only collected when inspector is open. + if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0) { + v8::Local<v8::Context> context = v8::Context::GetEntered(); + ScriptState* scriptState = ScriptState::forContext(context); + callStack = ScriptCallStack::create(scriptState, stackTrace); + } + v8::Handle<v8::Value> resourceName = message->GetScriptResourceName(); bool useURL = resourceName.IsEmpty() || !resourceName->IsString(); String resourceNameString = useURL ? frame->document()->url() : toWebCoreString(resourceName); V8ConsoleMessage consoleMessage(errorMessage, resourceNameString, message->GetLineNumber()); - consoleMessage.dispatchNow(page); + consoleMessage.dispatchNow(page, callStack.get()); +} + +void V8ConsoleMessage::dispatchNow(Page* page, ScriptCallStack* callStack) +{ + ASSERT(page); + + // Process any delayed messages to make sure that messages + // appear in the right order in the console. + processDelayed(); + + Console* console = page->mainFrame()->domWindow()->console(); + MessageType messageType = callStack ? UncaughtExceptionMessageType : LogMessageType; + console->addMessage(JSMessageSource, messageType, ErrorMessageLevel, m_string, m_lineNumber, m_sourceID, callStack); } } // namespace WebCore diff --git a/WebCore/bindings/v8/V8ConsoleMessage.h b/WebCore/bindings/v8/V8ConsoleMessage.h index a8f75ee..387b5ee 100644 --- a/WebCore/bindings/v8/V8ConsoleMessage.h +++ b/WebCore/bindings/v8/V8ConsoleMessage.h @@ -36,8 +36,9 @@ #include <wtf/Vector.h> namespace WebCore { - + class Page; + class ScriptCallStack; // V8ConsoleMessage encapsulates everything needed to // log messages originating from JavaScript to the console. @@ -80,6 +81,8 @@ namespace WebCore { const String m_sourceID; const unsigned m_lineNumber; + void dispatchNow(Page*, ScriptCallStack*); + // All delayed messages are stored in this vector. If the vector // is 0, there are no delayed messages. static Vector<V8ConsoleMessage>* m_delayedMessages; diff --git a/WebCore/bindings/v8/V8DOMMap.h b/WebCore/bindings/v8/V8DOMMap.h index a7e03a0..d8d5c04 100644 --- a/WebCore/bindings/v8/V8DOMMap.h +++ b/WebCore/bindings/v8/V8DOMMap.h @@ -74,13 +74,7 @@ namespace WebCore { public: typedef AbstractWeakReferenceMap<KeyType, ValueType> Parent; WeakReferenceMap(v8::WeakReferenceCallback callback) : Parent(callback) { } - virtual ~WeakReferenceMap() - { - #ifndef NDEBUG - if (m_map.size() > 0) - fprintf(stderr, "Leak %d JS wrappers.\n", m_map.size()); - #endif - } + virtual ~WeakReferenceMap() { } // Get the JS wrapper object of an object. virtual v8::Persistent<ValueType> get(KeyType* obj) @@ -135,7 +129,6 @@ namespace WebCore { protected: HashMap<KeyType*, ValueType*> m_map; - v8::WeakReferenceCallback m_weakReferenceCallback; }; template <class KeyType> class DOMWrapperMap : public WeakReferenceMap<KeyType, v8::Object> { diff --git a/WebCore/bindings/v8/V8DOMWindowShell.cpp b/WebCore/bindings/v8/V8DOMWindowShell.cpp index 99fea4c..c7c77d3 100644 --- a/WebCore/bindings/v8/V8DOMWindowShell.cpp +++ b/WebCore/bindings/v8/V8DOMWindowShell.cpp @@ -50,7 +50,6 @@ #include "V8DOMWindow.h" #include "V8Document.h" #include "V8GCForContextDispose.h" -#include "V8HTMLDocument.h" #include "V8HiddenPropertyName.h" #include "V8History.h" #include "V8Location.h" @@ -415,12 +414,6 @@ void V8DOMWindowShell::clearDocumentWrapper() } } -static void checkDocumentWrapper(v8::Handle<v8::Object> wrapper, Document* document) -{ - ASSERT(V8Document::toNative(wrapper) == document); - ASSERT(!document->isHTMLDocument() || (V8Document::toNative(v8::Handle<v8::Object>::Cast(wrapper->GetPrototype())) == document)); -} - void V8DOMWindowShell::updateDocumentWrapperCache() { v8::HandleScope handleScope; @@ -439,10 +432,6 @@ void V8DOMWindowShell::updateDocumentWrapperCache() } v8::Handle<v8::Value> documentWrapper = toV8(m_frame->document()); - ASSERT(documentWrapper == m_document || m_document.IsEmpty()); - if (m_document.IsEmpty()) - updateDocumentWrapper(v8::Handle<v8::Object>::Cast(documentWrapper)); - checkDocumentWrapper(m_document, m_frame->document()); // If instantiation of the document wrapper fails, clear the cache // and let the DOMWindow accessor handle access to the document. @@ -520,39 +509,6 @@ void V8DOMWindowShell::updateDocument() updateSecurityOrigin(); } -v8::Handle<v8::Value> getter(v8::Local<v8::String> property, const v8::AccessorInfo& info) -{ - // FIXME(antonm): consider passing AtomicStringImpl directly. - AtomicString name = v8StringToAtomicWebCoreString(property); - HTMLDocument* htmlDocument = V8HTMLDocument::toNative(info.Holder()); - ASSERT(htmlDocument); - return V8HTMLDocument::GetNamedProperty(htmlDocument, name); -} - -void V8DOMWindowShell::namedItemAdded(HTMLDocument* doc, const AtomicString& name) -{ - initContextIfNeeded(); - - v8::HandleScope handleScope; - v8::Context::Scope contextScope(m_context); - - ASSERT(!m_document.IsEmpty()); - checkDocumentWrapper(m_document, doc); - m_document->SetAccessor(v8String(name), getter); -} - -void V8DOMWindowShell::namedItemRemoved(HTMLDocument* doc, const AtomicString& name) -{ - initContextIfNeeded(); - - v8::HandleScope handleScope; - v8::Context::Scope contextScope(m_context); - - ASSERT(!m_document.IsEmpty()); - checkDocumentWrapper(m_document, doc); - m_document->Delete(v8String(name)); -} - void V8DOMWindowShell::updateSecurityOrigin() { v8::HandleScope scope; diff --git a/WebCore/bindings/v8/V8DOMWindowShell.h b/WebCore/bindings/v8/V8DOMWindowShell.h index 3cf1b52..f4eaff2 100644 --- a/WebCore/bindings/v8/V8DOMWindowShell.h +++ b/WebCore/bindings/v8/V8DOMWindowShell.h @@ -31,7 +31,6 @@ #ifndef V8DOMWindowShell_h #define V8DOMWindowShell_h -#include "AtomicString.h" #include "WrapperTypeInfo.h" #include <wtf/HashMap.h> #include <wtf/PassRefPtr.h> @@ -42,7 +41,6 @@ namespace WebCore { class DOMWindow; class Frame; -class HTMLDocument; class String; // V8WindowShell represents all the per-global object state for a Frame that @@ -56,9 +54,6 @@ public: // Update document object of the frame. void updateDocument(); - void namedItemAdded(HTMLDocument*, const AtomicString&); - void namedItemRemoved(HTMLDocument*, const AtomicString&); - // Update the security origin of a document // (e.g., after setting docoument.domain). void updateSecurityOrigin(); diff --git a/WebCore/bindings/v8/V8DOMWrapper.cpp b/WebCore/bindings/v8/V8DOMWrapper.cpp index b5703d2..4a09c34 100644 --- a/WebCore/bindings/v8/V8DOMWrapper.cpp +++ b/WebCore/bindings/v8/V8DOMWrapper.cpp @@ -284,8 +284,6 @@ v8::Local<v8::Object> V8DOMWrapper::instantiateV8Object(V8Proxy* proxy, WrapperT if (!instance.IsEmpty()) { // Avoid setting the DOM wrapper for failed allocations. setDOMWrapper(instance, type, impl); - if (type == &V8HTMLDocument::info) - instance = V8HTMLDocument::WrapInShadowObject(instance, static_cast<Node*>(impl)); } return instance; } diff --git a/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp b/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp index 62838a0..baffbd4 100644 --- a/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp +++ b/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp @@ -33,10 +33,9 @@ #include "V8Console.h" #include "Console.h" -#include "MemoryInfo.h" +#include "ScriptCallStack.h" #include "ScriptProfile.h" #include "V8Binding.h" -#include "V8MemoryInfo.h" #include "V8Proxy.h" #include "V8ScriptProfile.h" @@ -59,10 +58,26 @@ v8::Handle<v8::Value> V8Console::profilesAccessorGetter(v8::Local<v8::String> na } #endif -v8::Handle<v8::Value> V8Console::memoryAccessorGetter(v8::Local<v8::String>, const v8::AccessorInfo&) +v8::Handle<v8::Value> V8Console::traceCallback(const v8::Arguments& args) { - INC_STATS("DOM.Console.memoryAccessorGetter"); - return toV8(MemoryInfo::create()); + INC_STATS("DOM.Console.traceCallback"); + Console* imp = V8Console::toNative(args.Holder()); + v8::HandleScope handleScope; + ScriptState* scriptState = ScriptState::current(); + v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(ScriptCallStack::maxCallStackSizeToCapture); + OwnPtr<ScriptCallStack> callStack(ScriptCallStack::create(scriptState, stackTrace)); + imp->trace(callStack.get()); + return v8::Handle<v8::Value>(); +} + +v8::Handle<v8::Value> V8Console::assertCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.Console.assertCallback"); + Console* imp = V8Console::toNative(args.Holder()); + OwnPtr<ScriptCallStack> callStack(ScriptCallStack::create(args, 1, ScriptCallStack::maxCallStackSizeToCapture)); + bool condition = args[0]->BooleanValue(); + imp->assertCondition(condition, callStack.get()); + return v8::Handle<v8::Value>(); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8DeviceOrientationEventCustom.cpp b/WebCore/bindings/v8/custom/V8DeviceOrientationEventCustom.cpp new file mode 100644 index 0000000..26cc6cc --- /dev/null +++ b/WebCore/bindings/v8/custom/V8DeviceOrientationEventCustom.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "V8DeviceOrientationEvent.h" + +#if ENABLE(DEVICE_ORIENTATION) + +#include "DeviceOrientation.h" +#include "V8Binding.h" +#include "V8Proxy.h" + +#include <v8.h> + +namespace WebCore { + +v8::Handle<v8::Value> V8DeviceOrientationEvent::alphaAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.DeviceOrientationEvent.alpha._get"); + v8::Handle<v8::Object> holder = info.Holder(); + DeviceOrientationEvent* imp = V8DeviceOrientationEvent::toNative(holder); + if (!imp->orientation()->canProvideAlpha()) + return v8::Null(); + return v8::Number::New(imp->orientation()->alpha()); +} + +v8::Handle<v8::Value> V8DeviceOrientationEvent::betaAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.DeviceOrientationEvent.beta._get"); + v8::Handle<v8::Object> holder = info.Holder(); + DeviceOrientationEvent* imp = V8DeviceOrientationEvent::toNative(holder); + if (!imp->orientation()->canProvideBeta()) + return v8::Null(); + return v8::Number::New(imp->orientation()->beta()); +} + +v8::Handle<v8::Value> V8DeviceOrientationEvent::gammaAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.DeviceOrientationEvent.gamma._get"); + v8::Handle<v8::Object> holder = info.Holder(); + DeviceOrientationEvent* imp = V8DeviceOrientationEvent::toNative(holder); + if (!imp->orientation()->canProvideGamma()) + return v8::Null(); + return v8::Number::New(imp->orientation()->gamma()); +} + +v8::Handle<v8::Value> V8DeviceOrientationEvent::initDeviceOrientationEventCallback(const v8::Arguments& args) +{ + DeviceOrientationEvent* imp = V8DeviceOrientationEvent::toNative(args.Holder()); + V8Parameter<> type = args[0]; + bool bubbles = args[1]->BooleanValue(); + bool cancelable = args[2]->BooleanValue(); + // If alpha, beta or gamma are null or undefined, mark them as not provided. + // Otherwise, use the standard JavaScript conversion. + bool alphaProvided = !isUndefinedOrNull(args[3]); + double alpha = static_cast<double>(args[3]->NumberValue()); + bool betaProvided = !isUndefinedOrNull(args[4]); + double beta = static_cast<double>(args[4]->NumberValue()); + bool gammaProvided = !isUndefinedOrNull(args[5]); + double gamma = static_cast<double>(args[5]->NumberValue()); + RefPtr<DeviceOrientation> orientation = DeviceOrientation::create(alphaProvided, alpha, betaProvided, beta, gammaProvided, gamma); + imp->initDeviceOrientationEvent(type, bubbles, cancelable, orientation.get()); + return v8::Handle<v8::Value>(); +} + +} // namespace WebCore + +#endif // ENABLE(DEVICE_ORIENTATION) diff --git a/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp index 09f0a6f..86f2eb5 100644 --- a/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp @@ -49,37 +49,48 @@ namespace WebCore { -v8::Local<v8::Object> V8HTMLDocument::WrapInShadowObject(v8::Local<v8::Object> wrapper, Node* impl) +v8::Handle<v8::Boolean> V8HTMLDocument::namedPropertyDeleter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { - DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, shadowTemplate, ()); - if (shadowTemplate.IsEmpty()) { - shadowTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New()); - if (shadowTemplate.IsEmpty()) - return v8::Local<v8::Object>(); - shadowTemplate->SetClassName(v8::String::New("HTMLDocument")); - shadowTemplate->Inherit(V8HTMLDocument::GetTemplate()); - shadowTemplate->InstanceTemplate()->SetInternalFieldCount(V8HTMLDocument::internalFieldCount); - } - - v8::Local<v8::Function> shadowConstructor = shadowTemplate->GetFunction(); - if (shadowConstructor.IsEmpty()) - return v8::Local<v8::Object>(); - - v8::Local<v8::Object> shadow = shadowConstructor->NewInstance(); - if (shadow.IsEmpty()) - return v8::Local<v8::Object>(); - V8DOMWrapper::setDOMWrapper(shadow, &V8HTMLDocument::info, impl); - shadow->SetPrototype(wrapper); - return shadow; + // Only handle document.all. Insert the marker object into the + // shadow internal field to signal that document.all is no longer + // shadowed. + AtomicString key = v8StringToAtomicWebCoreString(name); + DEFINE_STATIC_LOCAL(const AtomicString, all, ("all")); + if (key != all) + return deletionNotHandledByInterceptor(); + + ASSERT(info.Holder()->InternalFieldCount() == V8HTMLDocument::internalFieldCount); + v8::Local<v8::Value> marker = info.Holder()->GetInternalField(V8HTMLDocument::markerIndex); + info.Holder()->SetInternalField(V8HTMLDocument::shadowIndex, marker); + return v8::True(); } -v8::Handle<v8::Value> V8HTMLDocument::GetNamedProperty(HTMLDocument* htmlDocument, const AtomicString& key) +v8::Handle<v8::Value> V8HTMLDocument::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { - ASSERT(htmlDocument->hasNamedItem(key.impl()) || htmlDocument->hasExtraNamedItem(key.impl())); + INC_STATS("DOM.HTMLDocument.NamedPropertyGetter"); + AtomicString key = v8StringToAtomicWebCoreString(name); + + // Special case for document.all. If the value in the shadow + // internal field is not the marker object, then document.all has + // been temporarily shadowed and we return the value. + DEFINE_STATIC_LOCAL(const AtomicString, all, ("all")); + if (key == all) { + ASSERT(info.Holder()->InternalFieldCount() == V8HTMLDocument::internalFieldCount); + v8::Local<v8::Value> marker = info.Holder()->GetInternalField(V8HTMLDocument::markerIndex); + v8::Local<v8::Value> value = info.Holder()->GetInternalField(V8HTMLDocument::shadowIndex); + if (marker != value) + return value; + } + + HTMLDocument* htmlDocument = V8HTMLDocument::toNative(info.Holder()); + + // Fast case for named elements that are not there. + if (!htmlDocument->hasNamedItem(key.impl()) && !htmlDocument->hasExtraNamedItem(key.impl())) + return v8::Handle<v8::Value>(); RefPtr<HTMLCollection> items = htmlDocument->documentNamedItems(key); if (!items->length()) - return v8::Handle<v8::Value>(); + return notHandledByInterceptor(); if (items->length() == 1) { Node* node = items->firstItem(); @@ -93,6 +104,13 @@ v8::Handle<v8::Value> V8HTMLDocument::GetNamedProperty(HTMLDocument* htmlDocumen return toV8(items.release()); } +v8::Handle<v8::Value> V8HTMLDocument::indexedPropertyGetter(uint32_t index, const v8::AccessorInfo &info) +{ + INC_STATS("DOM.HTMLDocument.IndexedPropertyGetter"); + v8::Local<v8::Integer> indexV8 = v8::Integer::NewFromUnsigned(index); + return namedPropertyGetter(indexV8->ToString(), info); +} + // HTMLDocument ---------------------------------------------------------------- // Concatenates "args" to a string. If args is empty, returns empty string. @@ -175,8 +193,10 @@ v8::Handle<v8::Value> V8HTMLDocument::allAccessorGetter(v8::Local<v8::String> na void V8HTMLDocument::allAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { - // Just emulate a normal JS behaviour---install a property on this. - info.This()->ForceSet(name, value); + INC_STATS("DOM.HTMLDocument.all._set"); + v8::Handle<v8::Object> holder = info.Holder(); + ASSERT(info.Holder()->InternalFieldCount() == V8HTMLDocument::internalFieldCount); + info.Holder()->SetInternalField(V8HTMLDocument::shadowIndex, value); } v8::Handle<v8::Value> toV8(HTMLDocument* impl, bool forceNewObject) @@ -190,6 +210,12 @@ v8::Handle<v8::Value> toV8(HTMLDocument* impl, bool forceNewObject) if (V8Proxy* proxy = V8Proxy::retrieve(impl->frame())) proxy->windowShell()->updateDocumentWrapper(wrapper); } + // Create marker object and insert it in two internal fields. + // This is used to implement temporary shadowing of document.all. + ASSERT(wrapper->InternalFieldCount() == V8HTMLDocument::internalFieldCount); + v8::Local<v8::Object> marker = v8::Object::New(); + wrapper->SetInternalField(V8HTMLDocument::markerIndex, marker); + wrapper->SetInternalField(V8HTMLDocument::shadowIndex, marker); return wrapper; } diff --git a/WebCore/bindings/v8/custom/V8SQLTransactionSyncCustom.cpp b/WebCore/bindings/v8/custom/V8SQLTransactionSyncCustom.cpp index 8ef11ce..495a8e4 100644 --- a/WebCore/bindings/v8/custom/V8SQLTransactionSyncCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SQLTransactionSyncCustom.cpp @@ -41,6 +41,7 @@ #include "V8Binding.h" #include "V8BindingMacros.h" #include "V8Proxy.h" +#include "V8SQLResultSet.h" #include <wtf/Vector.h> using namespace WTF; @@ -90,10 +91,10 @@ v8::Handle<v8::Value> V8SQLTransactionSync::executeSqlCallback(const v8::Argumen SQLTransactionSync* transaction = V8SQLTransactionSync::toNative(args.Holder()); ExceptionCode ec = 0; - transaction->executeSQL(statement, sqlValues, ec); + v8::Handle<v8::Value> result = toV8(transaction->executeSQL(statement, sqlValues, ec)); V8Proxy::setDOMException(ec); - return v8::Undefined(); + return result; } } // namespace WebCore |