This source file includes following definitions.
- m_position
- toObjectWrapper
- callListenerFunction
- V8LazyEventListenerToString
- prepareListenerObject
#include "config.h"
#include "bindings/v8/V8LazyEventListener.h"
#include "V8Document.h"
#include "V8HTMLFormElement.h"
#include "V8Node.h"
#include "bindings/v8/ScriptController.h"
#include "bindings/v8/ScriptSourceCode.h"
#include "bindings/v8/V8Binding.h"
#include "bindings/v8/V8DOMWrapper.h"
#include "bindings/v8/V8HiddenValue.h"
#include "bindings/v8/V8ScriptRunner.h"
#include "core/dom/Document.h"
#include "core/dom/Node.h"
#include "core/html/HTMLElement.h"
#include "core/html/HTMLFormElement.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/csp/ContentSecurityPolicy.h"
#include "wtf/StdLibExtras.h"
namespace WebCore {
V8LazyEventListener::V8LazyEventListener(const AtomicString& functionName, const AtomicString& eventParameterName, const String& code, const String sourceURL, const TextPosition& position, Node* node, v8::Isolate* isolate)
: V8AbstractEventListener(true, DOMWrapperWorld::mainWorld(), isolate)
, m_functionName(functionName)
, m_eventParameterName(eventParameterName)
, m_code(code)
, m_sourceURL(sourceURL)
, m_node(node)
, m_position(position)
{
}
template<typename T>
v8::Handle<v8::Object> toObjectWrapper(T* domObject, v8::Isolate* isolate)
{
if (!domObject)
return v8::Object::New(isolate);
v8::Handle<v8::Value> value = toV8(domObject, v8::Handle<v8::Object>(), isolate);
if (value.IsEmpty())
return v8::Object::New(isolate);
return v8::Local<v8::Object>::New(isolate, value.As<v8::Object>());
}
v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(ExecutionContext* 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(context, event);
if (handlerFunction.IsEmpty() || receiver.IsEmpty())
return v8::Local<v8::Value>();
if (!context)
return v8::Local<v8::Value>();
if (!context->isDocument())
return v8::Local<v8::Value>();
LocalFrame* frame = toDocument(context)->frame();
if (!frame)
return v8::Local<v8::Value>();
if (!frame->script().canExecuteScripts(AboutToExecuteScript))
return v8::Local<v8::Value>();
v8::Handle<v8::Value> parameters[1] = { jsEvent };
return frame->script().callFunction(handlerFunction, receiver, WTF_ARRAY_LENGTH(parameters), parameters);
}
static void V8LazyEventListenerToString(const v8::FunctionCallbackInfo<v8::Value>& info)
{
v8SetReturnValue(info, V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::toStringString(info.GetIsolate())));
}
void V8LazyEventListener::prepareListenerObject(ExecutionContext* context)
{
if (context->isDocument() && !toDocument(context)->allowInlineEventHandlers(m_node, this, m_sourceURL, m_position.m_line)) {
clearListenerObject();
return;
}
if (hasExistingListenerObject())
return;
ASSERT(context->isDocument());
v8::Isolate* isolate = toIsolate(context);
v8::HandleScope handleScope(isolate);
v8::Local<v8::Context> v8Context = toV8Context(context, world());
if (v8Context.IsEmpty())
return;
v8::Context::Scope scope(v8Context);
String listenerSource = InspectorInstrumentation::preprocessEventListener(toDocument(context)->frame(), m_code, m_sourceURL, m_functionName);
String code = "(function() {"
"with (this[2]) {"
"with (this[1]) {"
"with (this[0]) {"
"return function(" + m_eventParameterName + ") {" +
listenerSource + "\n"
"};"
"}}}})";
v8::Handle<v8::String> codeExternalString = v8String(isolate, code);
v8::Local<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(codeExternalString, isolate, m_sourceURL, m_position);
if (result.IsEmpty())
return;
ASSERT(result->IsFunction());
v8::Local<v8::Function> intermediateFunction = result.As<v8::Function>();
HTMLFormElement* formElement = 0;
if (m_node && m_node->isHTMLElement())
formElement = toHTMLElement(m_node)->formOwner();
v8::Handle<v8::Object> nodeWrapper = toObjectWrapper<Node>(m_node, isolate);
v8::Handle<v8::Object> formWrapper = toObjectWrapper<HTMLFormElement>(formElement, isolate);
v8::Handle<v8::Object> documentWrapper = toObjectWrapper<Document>(m_node ? m_node->ownerDocument() : 0, isolate);
v8::Local<v8::Object> thisObject = v8::Object::New(isolate);
if (thisObject.IsEmpty())
return;
if (!thisObject->ForceSet(v8::Integer::New(isolate, 0), nodeWrapper))
return;
if (!thisObject->ForceSet(v8::Integer::New(isolate, 1), formWrapper))
return;
if (!thisObject->ForceSet(v8::Integer::New(isolate, 2), documentWrapper))
return;
v8::Local<v8::Value> innerValue = V8ScriptRunner::callInternalFunction(intermediateFunction, thisObject, 0, 0, isolate);
if (innerValue.IsEmpty() || !innerValue->IsFunction())
return;
v8::Local<v8::Function> wrappedFunction = innerValue.As<v8::Function>();
v8::Local<v8::Function> toStringFunction = v8::Function::New(isolate, V8LazyEventListenerToString);
ASSERT(!toStringFunction.IsEmpty());
String toStringString = "function " + m_functionName + "(" + m_eventParameterName + ") {\n " + m_code + "\n}";
V8HiddenValue::setHiddenValue(isolate, wrappedFunction, V8HiddenValue::toStringString(isolate), v8String(isolate, toStringString));
wrappedFunction->Set(v8AtomicString(isolate, "toString"), toStringFunction);
wrappedFunction->SetName(v8String(isolate, m_functionName));
setListenerObject(wrappedFunction);
}
}