v8::Local<v8::Value> V8ErrorHandler::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event) { if (!event->hasInterface(EventNames::ErrorEvent)) return V8EventListener::callListenerFunction(jsEvent, event); ErrorEvent* errorEvent = static_cast<ErrorEvent*>(event); if (errorEvent->world() && errorEvent->world() != &world()) return v8::Null(isolate()); v8::Local<v8::Object> listener = getListenerObject(scriptState()->executionContext()); v8::Local<v8::Value> returnValue; if (!listener.IsEmpty() && listener->IsFunction()) { v8::Local<v8::Function> callFunction = v8::Local<v8::Function>::Cast(listener); v8::Local<v8::Object> thisValue = scriptState()->context()->Global(); v8::Local<v8::Value> error = V8HiddenValue::getHiddenValue(isolate(), jsEvent->ToObject(), V8HiddenValue::error(isolate())); if (error.IsEmpty()) error = v8::Null(isolate()); v8::Handle<v8::Value> parameters[5] = { v8String(isolate(), errorEvent->message()), v8String(isolate(), errorEvent->filename()), v8::Integer::New(isolate(), errorEvent->lineno()), v8::Integer::New(isolate(), errorEvent->colno()), error }; v8::TryCatch tryCatch; tryCatch.SetVerbose(true); returnValue = ScriptController::callFunction(scriptState()->executionContext(), callFunction, thisValue, WTF_ARRAY_LENGTH(parameters), parameters, isolate()); } return returnValue; }
v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(ScriptState* scriptState, v8::Local<v8::Value> jsEvent, Event* event) { ASSERT(!jsEvent.IsEmpty()); v8::Local<v8::Object> listenerObject = getListenerObject(scriptState->executionContext()); if (listenerObject.IsEmpty()) return v8::Local<v8::Value>(); v8::Local<v8::Function> handlerFunction = listenerObject.As<v8::Function>(); v8::Local<v8::Object> receiver = getReceiverObject(scriptState, event); if (handlerFunction.IsEmpty() || receiver.IsEmpty()) return v8::Local<v8::Value>(); if (!scriptState->executionContext()->isDocument()) return v8::Local<v8::Value>(); LocalFrame* frame = toDocument(scriptState->executionContext())->frame(); if (!frame) return v8::Local<v8::Value>(); if (!frame->script().canExecuteScripts(AboutToExecuteScript)) return v8::Local<v8::Value>(); v8::Local<v8::Value> parameters[1] = { jsEvent }; v8::Local<v8::Value> result; if (!frame->script().callFunction(handlerFunction, receiver, WTF_ARRAY_LENGTH(parameters), parameters).ToLocal(&result)) return v8::Local<v8::Value>(); return result; }
v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(ScriptExecutionContext* context, v8::Handle<v8::Value> jsEvent, Event* event) { v8::Local<v8::Object> listenerObject = getListenerObject(context); if (listenerObject.IsEmpty()) return v8::Local<v8::Value>(); v8::Local<v8::Function> handlerFunction = listenerObject.As<v8::Function>(); v8::Local<v8::Object> receiver = getReceiverObject(event); if (handlerFunction.IsEmpty() || receiver.IsEmpty()) return v8::Local<v8::Value>(); v8::Handle<v8::Value> parameters[1] = { jsEvent }; // FIXME: Can |context| be 0 here? if (!context) return v8::Local<v8::Value>(); if (!context->isDocument()) return v8::Local<v8::Value>(); Frame* frame = static_cast<Document*>(context)->frame(); if (!frame) return v8::Local<v8::Value>(); if (!frame->script()->canExecuteScripts(AboutToExecuteScript)) return v8::Local<v8::Value>(); return frame->script()->callFunction(handlerFunction, receiver, 1, parameters); }
v8::Local<v8::Value> V8ErrorHandler::callListenerFunction( ScriptState* scriptState, v8::Local<v8::Value> jsEvent, Event* event) { ASSERT(!jsEvent.IsEmpty()); if (!event->hasInterface(EventNames::ErrorEvent)) return V8EventListener::callListenerFunction(scriptState, jsEvent, event); ErrorEvent* errorEvent = static_cast<ErrorEvent*>(event); if (errorEvent->world() && errorEvent->world() != &world()) return v8::Null(isolate()); v8::Local<v8::Object> listener = getListenerObject(scriptState->getExecutionContext()); if (listener.IsEmpty() || !listener->IsFunction()) return v8::Null(isolate()); v8::Local<v8::Function> callFunction = v8::Local<v8::Function>::Cast(listener); v8::Local<v8::Object> thisValue = scriptState->context()->Global(); v8::Local<v8::Object> eventObject; if (!jsEvent->ToObject(scriptState->context()).ToLocal(&eventObject)) return v8::Null(isolate()); auto privateError = V8PrivateProperty::getErrorEventError(isolate()); v8::Local<v8::Value> error = privateError.getOrUndefined(scriptState->context(), eventObject); if (error->IsUndefined()) error = v8::Null(isolate()); v8::Local<v8::Value> parameters[5] = { v8String(isolate(), errorEvent->message()), v8String(isolate(), errorEvent->filename()), v8::Integer::New(isolate(), errorEvent->lineno()), v8::Integer::New(isolate(), errorEvent->colno()), error}; v8::TryCatch tryCatch(isolate()); tryCatch.SetVerbose(true); v8::MaybeLocal<v8::Value> result; if (scriptState->getExecutionContext()->isWorkerGlobalScope()) { result = V8ScriptRunner::callFunction( callFunction, scriptState->getExecutionContext(), thisValue, WTF_ARRAY_LENGTH(parameters), parameters, isolate()); } else { result = V8ScriptRunner::callFunction( callFunction, scriptState->getExecutionContext(), thisValue, WTF_ARRAY_LENGTH(parameters), parameters, isolate()); } v8::Local<v8::Value> returnValue; if (!result.ToLocal(&returnValue)) return v8::Null(isolate()); return returnValue; }
v8::Local<v8::Object> V8WorkerContextEventListener::getReceiverObject(ScriptExecutionContext* context, Event* event) { v8::Local<v8::Object> listener = getListenerObject(context); if (!listener.IsEmpty() && !listener->IsFunction()) return listener; EventTarget* target = event->currentTarget(); v8::Handle<v8::Value> value = V8DOMWrapper::convertEventTargetToV8Object(target); if (value.IsEmpty()) return v8::Local<v8::Object>(); return v8::Local<v8::Object>::New(v8::Handle<v8::Object>::Cast(value)); }
// FIXME: Remove getReceiverObject(). // This is almost identical to V8AbstractEventListener::getReceiverObject(). v8::Local<v8::Object> V8WorkerGlobalScopeEventListener::getReceiverObject(ScriptState* scriptState, Event* event) { v8::Local<v8::Object> listener = getListenerObject(scriptState->executionContext()); if (!listener.IsEmpty() && !listener->IsFunction()) return listener; EventTarget* target = event->currentTarget(); v8::Local<v8::Value> value = toV8(target, scriptState->context()->Global(), isolate()); if (value.IsEmpty()) return v8::Local<v8::Object>(); return v8::Local<v8::Object>::New(isolate(), v8::Local<v8::Object>::Cast(value)); }
v8::Local<v8::Value> V8WorkerContextErrorHandler::callListenerFunction(ScriptExecutionContext* context, v8::Handle<v8::Value> jsEvent, Event* event) { ASSERT(event->isErrorEvent()); v8::Local<v8::Object> listener = getListenerObject(context); v8::Local<v8::Value> returnValue; if (!listener.IsEmpty() && listener->IsFunction()) { ErrorEvent* errorEvent = static_cast<ErrorEvent*>(event); v8::Local<v8::Function> callFunction = v8::Local<v8::Function>::Cast(listener); v8::Local<v8::Object> thisValue = v8::Context::GetCurrent()->Global(); v8::Handle<v8::Value> parameters[3] = { v8String(errorEvent->message()), v8String(errorEvent->filename()), v8::Integer::New(errorEvent->lineno()) }; returnValue = callFunction->Call(thisValue, 3, parameters); } return returnValue; }
v8::Local<v8::Object> V8WorkerGlobalScopeEventListener::getReceiverObject(ExecutionContext* context, Event* event) { v8::Local<v8::Object> listener = getListenerObject(context); if (!listener.IsEmpty() && !listener->IsFunction()) return listener; EventTarget* target = event->currentTarget(); v8::Isolate* isolate = toIsolate(context); v8::Handle<v8::Value> value = toV8(target, v8::Handle<v8::Object>(), isolate); if (value.IsEmpty()) return v8::Local<v8::Object>(); return v8::Local<v8::Object>::New(isolate, v8::Handle<v8::Object>::Cast(value)); }
bool V8WorkerContextEventListener::reportError(const String& message, const String& url, int lineNumber) { // Is the EventListener disconnected? if (disconnected()) return false; // The callback function can clear the event listener and destroy 'this' object. Keep a local reference to it. RefPtr<V8AbstractEventListener> protect(this); v8::HandleScope handleScope; v8::Handle<v8::Context> context = m_proxy->context(); if (context.IsEmpty()) return false; // Enter the V8 context in which to perform the event handling. v8::Context::Scope scope(context); v8::Local<v8::Object> listener = getListenerObject(); v8::Local<v8::Value> returnValue; { // Catch exceptions thrown in calling the function so they do not propagate to javascript code that caused the event to fire. v8::TryCatch tryCatch; tryCatch.SetVerbose(true); // Call the function. if (!listener.IsEmpty() && listener->IsFunction()) { v8::Local<v8::Function> callFunction = v8::Local<v8::Function>::Cast(listener); v8::Local<v8::Object> thisValue = v8::Context::GetCurrent()->Global(); v8::Handle<v8::Value> parameters[3] = { v8String(message), v8String(url), v8::Integer::New(lineNumber) }; returnValue = callFunction->Call(thisValue, 3, parameters); } // If an error occurs while handling the script error, it should be bubbled up. if (tryCatch.HasCaught()) { tryCatch.Reset(); return false; } } // If the function returns false, then the error is handled. Otherwise, the error is not handled. bool errorHandled = returnValue->IsBoolean() && !returnValue->BooleanValue(); return errorHandled; }
v8::Local<v8::Value> V8WindowErrorHandler::callListenerFunction(ScriptExecutionContext* context, v8::Handle<v8::Value> jsEvent, Event* event) { if (!event->hasInterface(eventNames().interfaceForErrorEvent)) return V8EventListener::callListenerFunction(context, jsEvent, event); ErrorEvent* errorEvent = static_cast<ErrorEvent*>(event); v8::Local<v8::Object> listener = getListenerObject(context); v8::Local<v8::Value> returnValue; if (!listener.IsEmpty() && listener->IsFunction()) { v8::Local<v8::Function> callFunction = v8::Local<v8::Function>::Cast(listener); v8::Local<v8::Object> thisValue = v8::Context::GetCurrent()->Global(); v8::Handle<v8::Value> parameters[3] = { v8String(errorEvent->message()), v8String(errorEvent->filename()), v8Integer(errorEvent->lineno()) }; v8::TryCatch tryCatch; tryCatch.SetVerbose(true); returnValue = V8Proxy::instrumentedCallFunction(0 /* frame */, callFunction, thisValue, 3, parameters); } return returnValue; }
v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(ScriptExecutionContext* context, v8::Handle<v8::Value> jsEvent, Event* event) { v8::Local<v8::Object> listenerObject = getListenerObject(context); if (listenerObject.IsEmpty()) return v8::Local<v8::Value>(); v8::Local<v8::Function> handlerFunction = v8::Local<v8::Function>::Cast(listenerObject); v8::Local<v8::Object> receiver = getReceiverObject(event); if (handlerFunction.IsEmpty() || receiver.IsEmpty()) return v8::Local<v8::Value>(); v8::Handle<v8::Value> parameters[1] = { jsEvent }; if (V8Proxy* proxy = V8Proxy::retrieve(context)) return proxy->callFunction(handlerFunction, receiver, 1, parameters); return v8::Local<v8::Value>(); }
v8::Local<v8::Function> V8EventListener::getListenerFunction(ScriptExecutionContext* context) { v8::Local<v8::Object> listener = getListenerObject(context); // Has the listener been disposed? if (listener.IsEmpty()) return v8::Local<v8::Function>(); if (listener->IsFunction()) return v8::Local<v8::Function>::Cast(listener); if (listener->IsObject()) { v8::Local<v8::Value> property = listener->Get(v8::String::NewSymbol("handleEvent")); if (property->IsFunction()) return v8::Local<v8::Function>::Cast(property); } return v8::Local<v8::Function>(); }
v8::Local<v8::Function> V8EventListener::getListenerFunction(ScriptExecutionContext* context) { v8::Local<v8::Object> listener = getListenerObject(context); // Has the listener been disposed? if (listener.IsEmpty()) return v8::Local<v8::Function>(); if (listener->IsFunction()) return v8::Local<v8::Function>::Cast(listener); if (listener->IsObject()) { v8::Local<v8::Value> property = listener->Get(v8::String::NewSymbol("handleEvent")); // Check that no exceptions were thrown when getting the // handleEvent property and that the value is a function. if (!property.IsEmpty() && property->IsFunction()) return v8::Local<v8::Function>::Cast(property); } return v8::Local<v8::Function>(); }
v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(ScriptExecutionContext* context, v8::Handle<v8::Value> jsEvent, Event* event) { v8::Local<v8::Object> listenerObject = getListenerObject(context); if (listenerObject.IsEmpty()) return v8::Local<v8::Value>(); v8::Local<v8::Function> handlerFunction = listenerObject.As<v8::Function>(); v8::Local<v8::Object> receiver = getReceiverObject(event); if (handlerFunction.IsEmpty() || receiver.IsEmpty()) return v8::Local<v8::Value>(); v8::Handle<v8::Value> parameters[1] = { jsEvent }; if (V8Proxy* proxy = V8Proxy::retrieve(context)) { Frame* frame = static_cast<Document*>(context)->frame(); if (frame->script()->canExecuteScripts(AboutToExecuteScript)) return proxy->callFunction(handlerFunction, receiver, 1, parameters); } return v8::Local<v8::Value>(); }
v8::Local<v8::Function> V8EventListener::getListenerFunction( ScriptState* scriptState) { v8::Local<v8::Object> listener = getListenerObject(scriptState->getExecutionContext()); // Has the listener been disposed? if (listener.IsEmpty()) return v8::Local<v8::Function>(); if (listener->IsFunction()) return v8::Local<v8::Function>::Cast(listener); // The EventHandler callback function type (used for event handler // attributes in HTML) has [TreatNonObjectAsNull], which implies that // non-function objects should be treated as no-op functions that return // undefined. if (isAttribute()) return v8::Local<v8::Function>(); // Getting the handleEvent property can runs script in the getter. if (ScriptForbiddenScope::isScriptForbidden()) { V8ThrowException::throwError(isolate(), "Script execution is forbidden."); return v8::Local<v8::Function>(); } if (listener->IsObject()) { // Check that no exceptions were thrown when getting the // handleEvent property and that the value is a function. v8::Local<v8::Value> property; if (listener ->Get(scriptState->context(), v8AtomicString(isolate(), "handleEvent")) .ToLocal(&property) && property->IsFunction()) return v8::Local<v8::Function>::Cast(property); } return v8::Local<v8::Function>(); }
v8::Local<v8::Function> V8EventListener::getListenerFunction(ScriptState* scriptState) { v8::Local<v8::Object> listener = getListenerObject(scriptState->executionContext()); // Has the listener been disposed? if (listener.IsEmpty()) return v8::Local<v8::Function>(); if (listener->IsFunction()) return v8::Local<v8::Function>::Cast(listener); if (listener->IsObject()) { ASSERT_WITH_MESSAGE(!isAttribute(), "EventHandler attributes should only accept JS Functions as input."); v8::Local<v8::Value> property = listener->Get(v8AtomicString(isolate(), "handleEvent")); // Check that no exceptions were thrown when getting the // handleEvent property and that the value is a function. if (!property.IsEmpty() && property->IsFunction()) return v8::Local<v8::Function>::Cast(property); } return v8::Local<v8::Function>(); }