diff options
Diffstat (limited to 'WebCore/bindings/v8')
-rw-r--r-- | WebCore/bindings/v8/ScriptDebugServer.cpp | 85 | ||||
-rw-r--r-- | WebCore/bindings/v8/ScriptDebugServer.h | 7 | ||||
-rw-r--r-- | WebCore/bindings/v8/ScriptProfiler.cpp | 5 | ||||
-rw-r--r-- | WebCore/bindings/v8/ScriptProfiler.h | 1 | ||||
-rw-r--r-- | WebCore/bindings/v8/V8DOMWrapper.cpp | 6 | ||||
-rw-r--r-- | WebCore/bindings/v8/V8HiddenPropertyName.h | 2 | ||||
-rw-r--r-- | WebCore/bindings/v8/V8NodeFilterCondition.cpp | 15 | ||||
-rw-r--r-- | WebCore/bindings/v8/V8Proxy.cpp | 22 | ||||
-rw-r--r-- | WebCore/bindings/v8/V8Proxy.h | 4 | ||||
-rw-r--r-- | WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp | 18 | ||||
-rw-r--r-- | WebCore/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp | 29 | ||||
-rw-r--r-- | WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp | 35 |
12 files changed, 186 insertions, 43 deletions
diff --git a/WebCore/bindings/v8/ScriptDebugServer.cpp b/WebCore/bindings/v8/ScriptDebugServer.cpp index 0c24678..3f1a0c5 100644 --- a/WebCore/bindings/v8/ScriptDebugServer.cpp +++ b/WebCore/bindings/v8/ScriptDebugServer.cpp @@ -84,6 +84,7 @@ ScriptDebugServer::ScriptDebugServer() : m_pauseOnExceptionsState(DontPauseOnExceptions) , m_pausedPage(0) , m_enabled(true) + , m_breakpointsActivated(true) { } @@ -186,7 +187,7 @@ void ScriptDebugServer::clearBreakpoints() v8::Debug::Call(clearBreakpoints); } -void ScriptDebugServer::setBreakpointsActivated(bool enabled) +void ScriptDebugServer::setBreakpointsActivated(bool activated) { ensureDebuggerScriptCompiled(); v8::HandleScope scope; @@ -194,9 +195,11 @@ void ScriptDebugServer::setBreakpointsActivated(bool enabled) v8::Context::Scope contextScope(debuggerContext); v8::Local<v8::Object> args = v8::Object::New(); - args->Set(v8::String::New("enabled"), v8::Boolean::New(enabled)); + args->Set(v8::String::New("enabled"), v8::Boolean::New(activated)); v8::Handle<v8::Function> setBreakpointsActivated = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("setBreakpointsActivated"))); v8::Debug::Call(setBreakpointsActivated, args); + + m_breakpointsActivated = activated; } ScriptDebugServer::PauseOnExceptionsState ScriptDebugServer::pauseOnExceptionsState() @@ -228,6 +231,31 @@ void ScriptDebugServer::pause() v8::Debug::DebugBreak(); } +void ScriptDebugServer::breakProgram() +{ + DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, callbackTemplate, ()); + + if (!m_breakpointsActivated) + return; + + if (!v8::Context::InContext()) + return; + + if (callbackTemplate.IsEmpty()) { + callbackTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New()); + callbackTemplate->SetCallHandler(&ScriptDebugServer::breakProgramCallback); + } + + v8::Handle<v8::Context> context = v8::Context::GetCurrent(); + if (context.IsEmpty()) + return; + + m_pausedPageContext = *context; + v8::Handle<v8::Function> breakProgramFunction = callbackTemplate->GetFunction(); + v8::Debug::Call(breakProgramFunction); + m_pausedPageContext.Clear(); +} + void ScriptDebugServer::continueProgram() { if (m_pausedPage) @@ -323,6 +351,41 @@ void ScriptDebugServer::runPendingTasks() v8::Debug::ProcessDebugMessages(); } +v8::Handle<v8::Value> ScriptDebugServer::breakProgramCallback(const v8::Arguments& args) +{ + ASSERT(2 == args.Length()); + ScriptDebugServer::shared().breakProgram(v8::Handle<v8::Object>::Cast(args[0])); + return v8::Undefined(); +} + +void ScriptDebugServer::breakProgram(v8::Handle<v8::Object> executionState) +{ + // Don't allow nested breaks. + if (m_pausedPage) + return; + + Frame* frame = retrieveFrame(m_pausedPageContext); + if (!frame) + return; + + ScriptDebugListener* listener = m_listenersMap.get(frame->page()); + if (!listener) + return; + + m_executionState.set(executionState); + m_pausedPage = frame->page(); + ScriptState* currentCallFrameState = ScriptState::forContext(m_pausedPageContext); + listener->didPause(currentCallFrameState); + + // Wait for continue or step command. + m_clientMessageLoop->run(m_pausedPage); + ASSERT(!m_pausedPage); + + // The listener may have been removed in the nested loop. + if (ScriptDebugListener* listener = m_listenersMap.get(frame->page())) + listener->didContinue(); +} + void ScriptDebugServer::v8DebugEventCallback(const v8::Debug::EventDetails& eventDetails) { ScriptDebugServer::shared().handleV8DebugEvent(eventDetails); @@ -365,21 +428,9 @@ void ScriptDebugServer::handleV8DebugEvent(const v8::Debug::EventDetails& eventD return; } - // Don't allow nested breaks. - if (m_pausedPage) - return; - m_executionState.set(eventDetails.GetExecutionState()); - m_pausedPage = frame->page(); - ScriptState* currentCallFrameState = mainWorldScriptState(frame); - listener->didPause(currentCallFrameState); - - // Wait for continue or step command. - m_clientMessageLoop->run(m_pausedPage); - ASSERT(!m_pausedPage); - - // The listener may have been removed in the nested loop. - if (ScriptDebugListener* listener = m_listenersMap.get(frame->page())) - listener->didContinue(); + m_pausedPageContext = *eventContext; + breakProgram(eventDetails.GetExecutionState()); + m_pausedPageContext.Clear(); } } } diff --git a/WebCore/bindings/v8/ScriptDebugServer.h b/WebCore/bindings/v8/ScriptDebugServer.h index a1e0a47..d1fd71f 100644 --- a/WebCore/bindings/v8/ScriptDebugServer.h +++ b/WebCore/bindings/v8/ScriptDebugServer.h @@ -71,6 +71,7 @@ public: void setPauseOnExceptionsState(PauseOnExceptionsState pauseOnExceptionsState); void pause(); + void breakProgram(); void continueProgram(); void stepIntoStatement(); void stepOverStatement(); @@ -111,6 +112,9 @@ private: ScriptDebugServer(); ~ScriptDebugServer() { } + static v8::Handle<v8::Value> breakProgramCallback(const v8::Arguments& args); + void breakProgram(v8::Handle<v8::Object> executionState); + static void v8DebugEventCallback(const v8::Debug::EventDetails& eventDetails); void handleV8DebugEvent(const v8::Debug::EventDetails& eventDetails); @@ -128,7 +132,10 @@ private: OwnHandle<v8::Object> m_executionState; OwnPtr<ClientMessageLoop> m_clientMessageLoop; Page* m_pausedPage; + v8::Local<v8::Context> m_pausedPageContext; bool m_enabled; + + bool m_breakpointsActivated; }; } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptProfiler.cpp b/WebCore/bindings/v8/ScriptProfiler.cpp index 9213774..0de4a24 100644 --- a/WebCore/bindings/v8/ScriptProfiler.cpp +++ b/WebCore/bindings/v8/ScriptProfiler.cpp @@ -69,4 +69,9 @@ long ScriptProfiler::getProfilerLogLines(long position, String* data) return position; } +bool ScriptProfiler::isProfilerAlwaysEnabled() +{ + return true; +} + } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptProfiler.h b/WebCore/bindings/v8/ScriptProfiler.h index 5c1054b..b1ab3b1 100644 --- a/WebCore/bindings/v8/ScriptProfiler.h +++ b/WebCore/bindings/v8/ScriptProfiler.h @@ -45,6 +45,7 @@ public: static PassRefPtr<ScriptProfile> stop(ScriptState* state, const String& title); static void takeHeapSnapshot(); static long getProfilerLogLines(long position, String* data); + static bool isProfilerAlwaysEnabled(); }; } // namespace WebCore diff --git a/WebCore/bindings/v8/V8DOMWrapper.cpp b/WebCore/bindings/v8/V8DOMWrapper.cpp index 8a72a3a..921f957 100644 --- a/WebCore/bindings/v8/V8DOMWrapper.cpp +++ b/WebCore/bindings/v8/V8DOMWrapper.cpp @@ -51,6 +51,7 @@ #include "V8HTMLCollection.h" #include "V8HTMLDocument.h" #include "V8IDBRequest.h" +#include "V8IDBTransaction.h" #include "V8IsolatedContext.h" #include "V8Location.h" #include "V8MessageChannel.h" @@ -221,9 +222,6 @@ PassRefPtr<NodeFilter> V8DOMWrapper::wrapNativeNodeFilter(v8::Handle<v8::Value> // to NodeFilter. NodeFilter has a ref counted pointer to NodeFilterCondition. // In NodeFilterCondition, filter object is persisted in its constructor, // and disposed in its destructor. - if (!filter->IsFunction()) - return 0; - return NodeFilter::create(V8NodeFilterCondition::create(filter)); } @@ -382,6 +380,8 @@ v8::Handle<v8::Value> V8DOMWrapper::convertEventTargetToV8Object(EventTarget* ta #if ENABLE(INDEXED_DATABASE) if (IDBRequest* idbRequest = target->toIDBRequest()) return toV8(idbRequest); + if (IDBTransaction* idbTransaction = target->toIDBTransaction()) + return toV8(idbTransaction); #endif #if ENABLE(WEB_SOCKETS) diff --git a/WebCore/bindings/v8/V8HiddenPropertyName.h b/WebCore/bindings/v8/V8HiddenPropertyName.h index 2d0e8d6..7867b36 100644 --- a/WebCore/bindings/v8/V8HiddenPropertyName.h +++ b/WebCore/bindings/v8/V8HiddenPropertyName.h @@ -40,10 +40,12 @@ namespace WebCore { V(listener) \ V(attributeListener) \ V(scriptState) \ + V(devtoolsInjectedScript) \ V(sleepFunction) \ V(toStringString) \ V(event) + class V8HiddenPropertyName { public: #define V8_DECLARE_PROPERTY(name) static v8::Handle<v8::String> name(); diff --git a/WebCore/bindings/v8/V8NodeFilterCondition.cpp b/WebCore/bindings/v8/V8NodeFilterCondition.cpp index 2170698..4e0240d 100644 --- a/WebCore/bindings/v8/V8NodeFilterCondition.cpp +++ b/WebCore/bindings/v8/V8NodeFilterCondition.cpp @@ -62,13 +62,24 @@ short V8NodeFilterCondition::acceptNode(ScriptState* state, Node* node) const { ASSERT(v8::Context::InContext()); - if (!m_filter->IsFunction()) + if (!m_filter->IsObject()) return NodeFilter::FILTER_ACCEPT; v8::TryCatch exceptionCatcher; + v8::Handle<v8::Function> callback; + if (m_filter->IsFunction()) + callback = v8::Handle<v8::Function>::Cast(m_filter); + else { + v8::Local<v8::Value> value = m_filter->ToObject()->Get(v8::String::New("acceptNode")); + if (!value->IsFunction()) { + V8Proxy::throwError(V8Proxy::TypeError, "NodeFilter object does not have an acceptNode function"); + return NodeFilter::FILTER_REJECT; + } + callback = v8::Handle<v8::Function>::Cast(value); + } + v8::Handle<v8::Object> object = v8::Context::GetCurrent()->Global(); - v8::Handle<v8::Function> callback = v8::Handle<v8::Function>::Cast(m_filter); OwnArrayPtr<v8::Handle<v8::Value> > args(new v8::Handle<v8::Value>[1]); args[0] = toV8(node); diff --git a/WebCore/bindings/v8/V8Proxy.cpp b/WebCore/bindings/v8/V8Proxy.cpp index 50e9fdc..5d3eeb8 100644 --- a/WebCore/bindings/v8/V8Proxy.cpp +++ b/WebCore/bindings/v8/V8Proxy.cpp @@ -37,6 +37,8 @@ #include "DocumentLoader.h" #include "Frame.h" #include "FrameLoaderClient.h" +#include "IDBFactoryBackendInterface.h" +#include "IDBPendingTransactionMonitor.h" #include "InspectorTimelineAgent.h" #include "Page.h" #include "PageGroup.h" @@ -487,7 +489,7 @@ v8::Local<v8::Value> V8Proxy::runScriptInternal(v8::Handle<v8::Script> script, b } // Release the storage mutex if applicable. - releaseStorageMutex(); + didLeaveScriptContext(); if (handleOutOfMemory()) ASSERT(result.IsEmpty()); @@ -563,7 +565,7 @@ v8::Local<v8::Value> V8Proxy::callFunction(v8::Handle<v8::Function> function, v8 } // Release the storage mutex if applicable. - releaseStorageMutex(); + didLeaveScriptContext(); if (v8::V8::IsDead()) handleFatalErrorInV8(); @@ -675,16 +677,24 @@ void V8Proxy::disconnectFrame() { } -void V8Proxy::releaseStorageMutex() +void V8Proxy::didLeaveScriptContext() { + Page* page = m_frame->page(); + if (!page) + return; + // If we've just left a script context and indexed database has been + // instantiated, we must let its transaction coordinator know so it can terminate + // any not-yet-started transactions. + if (IDBPendingTransactionMonitor::hasPendingTransactions()) { + ASSERT(page->group().hasIDBFactory()); + page->group().idbFactory()->abortPendingTransactions(IDBPendingTransactionMonitor::pendingTransactions()); + IDBPendingTransactionMonitor::clearPendingTransactions(); + } // If we've just left a top level script context and local storage has been // instantiated, we must ensure that any storage locks have been freed. // Per http://dev.w3.org/html5/spec/Overview.html#storage-mutex if (m_recursion != 0) return; - Page* page = m_frame->page(); - if (!page) - return; if (page->group().hasLocalStorage()) page->group().localStorage()->unlock(); } diff --git a/WebCore/bindings/v8/V8Proxy.h b/WebCore/bindings/v8/V8Proxy.h index 94ff17c..ca3920b 100644 --- a/WebCore/bindings/v8/V8Proxy.h +++ b/WebCore/bindings/v8/V8Proxy.h @@ -346,9 +346,7 @@ namespace WebCore { static void reportUnsafeAccessTo(Frame* target, DelayReporting delay); private: - // If m_recursionCount is 0, let LocalStorage know so we can release - // the storage mutex. - void releaseStorageMutex(); + void didLeaveScriptContext(); void resetIsolatedWorlds(); diff --git a/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp b/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp index 1b069cf..b3007a4 100644 --- a/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp +++ b/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp @@ -46,6 +46,7 @@ #include "V8BindingState.h" #include "V8DOMWindow.h" #include "V8Database.h" +#include "V8HiddenPropertyName.h" #include "V8JavaScriptCallFrame.h" #include "V8Node.h" #include "V8Proxy.h" @@ -120,6 +121,21 @@ ScriptObject InjectedScriptHost::createInjectedScript(const String& scriptSource return ScriptObject(inspectedScriptState, injectedScript); } +void InjectedScriptHost::discardInjectedScript(ScriptState* inspectedScriptState) +{ + v8::HandleScope handleScope; + v8::Local<v8::Context> context = inspectedScriptState->context(); + v8::Context::Scope contextScope(context); + + v8::Local<v8::Object> global = context->Global(); + // Skip proxy object. The proxy object will survive page navigation while we need + // an object whose lifetime consides with that of the inspected context. + global = v8::Local<v8::Object>::Cast(global->GetPrototype()); + + v8::Handle<v8::String> key = V8HiddenPropertyName::devtoolsInjectedScript(); + global->DeleteHiddenValue(key); +} + v8::Handle<v8::Value> V8InjectedScriptHost::nodeForIdCallback(const v8::Arguments& args) { INC_STATS("InjectedScriptHost.nodeForId()"); @@ -206,7 +222,7 @@ InjectedScript InjectedScriptHost::injectedScriptFor(ScriptState* inspectedScrip // an object whose lifetime consides with that of the inspected context. global = v8::Local<v8::Object>::Cast(global->GetPrototype()); - v8::Local<v8::String> key = v8::String::New("Devtools_InjectedScript"); + v8::Handle<v8::String> key = V8HiddenPropertyName::devtoolsInjectedScript(); v8::Local<v8::Value> val = global->GetHiddenValue(key); if (!val.IsEmpty() && val->IsObject()) return InjectedScript(ScriptObject(inspectedScriptState, v8::Local<v8::Object>::Cast(val))); diff --git a/WebCore/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp b/WebCore/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp index 7733a70..25b9010 100644 --- a/WebCore/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp +++ b/WebCore/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp @@ -33,6 +33,7 @@ #include "InspectorController.h" #include "InspectorFrontendHost.h" +#include "PlatformString.h" #include "V8Binding.h" #include "V8MouseEvent.h" @@ -76,18 +77,26 @@ v8::Handle<v8::Value> V8InspectorFrontendHost::showContextMenuCallback(const v8: for (size_t i = 0; i < array->Length(); ++i) { v8::Local<v8::Object> item = v8::Local<v8::Object>::Cast(array->Get(v8::Integer::New(i))); - v8::Local<v8::Value> label = item->Get(v8::String::New("label")); + v8::Local<v8::Value> type = item->Get(v8::String::New("type")); v8::Local<v8::Value> id = item->Get(v8::String::New("id")); - if (label->IsUndefined() || id->IsUndefined()) { - items.append(new ContextMenuItem(SeparatorType, - ContextMenuItemCustomTagNoAction, - String())); + v8::Local<v8::Value> label = item->Get(v8::String::New("label")); + v8::Local<v8::Value> enabled = item->Get(v8::String::New("enabled")); + v8::Local<v8::Value> checked = item->Get(v8::String::New("checked")); + if (!type->IsString()) + continue; + String typeString = toWebCoreStringWithNullCheck(type); + if (typeString == "separator") { + items.append(new ContextMenuItem(SeparatorType, + ContextMenuItemCustomTagNoAction, + String())); } else { - ContextMenuAction typedId = static_cast<ContextMenuAction>( - ContextMenuItemBaseCustomTag + id->ToInt32()->Value()); - items.append(new ContextMenuItem(ActionType, - typedId, - toWebCoreStringWithNullCheck(label))); + ContextMenuAction typedId = static_cast<ContextMenuAction>(ContextMenuItemBaseCustomTag + id->ToInt32()->Value()); + ContextMenuItem* menuItem = new ContextMenuItem((typeString == "checkbox" ? CheckableActionType : ActionType), typedId, toWebCoreStringWithNullCheck(label)); + if (checked->IsBoolean()) + menuItem->setChecked(checked->ToBoolean()->Value()); + if (enabled->IsBoolean()) + menuItem->setEnabled(enabled->ToBoolean()->Value()); + items.append(menuItem); } } diff --git a/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp b/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp index fd6e120..9346a05 100644 --- a/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp +++ b/WebCore/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp @@ -227,6 +227,10 @@ v8::Handle<v8::Value> V8WebGLRenderingContext::getAttachedShadersCallback(const ExceptionCode ec = 0; WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); + if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLProgram::HasInstance(args[0])) { + V8Proxy::throwTypeError(); + return notHandledByInterceptor(); + } WebGLProgram* program = V8WebGLProgram::HasInstance(args[0]) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; Vector<WebGLShader*> shaders; bool succeed = context->getAttachedShaders(program, shaders, ec); @@ -319,6 +323,10 @@ v8::Handle<v8::Value> V8WebGLRenderingContext::getProgramParameterCallback(const ExceptionCode ec = 0; WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); + if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLProgram::HasInstance(args[0])) { + V8Proxy::throwTypeError(); + return notHandledByInterceptor(); + } WebGLProgram* program = V8WebGLProgram::HasInstance(args[0]) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; bool ok; unsigned pname = toInt32(args[1], ok); @@ -351,6 +359,10 @@ v8::Handle<v8::Value> V8WebGLRenderingContext::getShaderParameterCallback(const ExceptionCode ec = 0; WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); + if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLShader::HasInstance(args[0])) { + V8Proxy::throwTypeError(); + return notHandledByInterceptor(); + } WebGLShader* shader = V8WebGLShader::HasInstance(args[0]) ? V8WebGLShader::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; bool ok; unsigned pname = toInt32(args[1], ok); @@ -383,8 +395,16 @@ v8::Handle<v8::Value> V8WebGLRenderingContext::getUniformCallback(const v8::Argu ExceptionCode ec = 0; WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); + if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLProgram::HasInstance(args[0])) { + V8Proxy::throwTypeError(); + return notHandledByInterceptor(); + } WebGLProgram* program = V8WebGLProgram::HasInstance(args[0]) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; + if (args.Length() > 1 && !isUndefinedOrNull(args[1]) && !V8WebGLUniformLocation::HasInstance(args[1])) { + V8Proxy::throwTypeError(); + return notHandledByInterceptor(); + } bool ok = false; WebGLUniformLocation* location = toWebGLUniformLocation(args[1], ok); @@ -452,8 +472,13 @@ static v8::Handle<v8::Value> vertexAttribAndUniformHelperf(const v8::Arguments& if (isFunctionToCallForAttribute(functionToCall)) index = toInt32(args[0], ok); - else + else { + if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLUniformLocation::HasInstance(args[0])) { + V8Proxy::throwTypeError(); + return notHandledByInterceptor(); + } location = toWebGLUniformLocation(args[0], ok); + } WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); @@ -526,6 +551,10 @@ static v8::Handle<v8::Value> uniformHelperi(const v8::Arguments& args, } WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); + if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLUniformLocation::HasInstance(args[0])) { + V8Proxy::throwTypeError(); + return notHandledByInterceptor(); + } bool ok = false; WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok); @@ -639,6 +668,10 @@ static v8::Handle<v8::Value> uniformMatrixHelper(const v8::Arguments& args, WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(args.Holder()); + if (args.Length() > 0 && !isUndefinedOrNull(args[0]) && !V8WebGLUniformLocation::HasInstance(args[0])) { + V8Proxy::throwTypeError(); + return notHandledByInterceptor(); + } bool ok = false; WebGLUniformLocation* location = toWebGLUniformLocation(args[0], ok); |