OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2006, 2007, 2008, 2009 Google Inc. All rights reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2009 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 #include "core/html/HTMLFormElement.h" | 46 #include "core/html/HTMLFormElement.h" |
47 #include "core/inspector/InspectorInstrumentation.h" | 47 #include "core/inspector/InspectorInstrumentation.h" |
48 #include "core/frame/LocalFrame.h" | 48 #include "core/frame/LocalFrame.h" |
49 #include "core/frame/csp/ContentSecurityPolicy.h" | 49 #include "core/frame/csp/ContentSecurityPolicy.h" |
50 | 50 |
51 #include "wtf/StdLibExtras.h" | 51 #include "wtf/StdLibExtras.h" |
52 | 52 |
53 namespace WebCore { | 53 namespace WebCore { |
54 | 54 |
55 V8LazyEventListener::V8LazyEventListener(const AtomicString& functionName, const
AtomicString& eventParameterName, const String& code, const String sourceURL, c
onst TextPosition& position, Node* node, v8::Isolate* isolate) | 55 V8LazyEventListener::V8LazyEventListener(const AtomicString& functionName, const
AtomicString& eventParameterName, const String& code, const String sourceURL, c
onst TextPosition& position, Node* node, v8::Isolate* isolate) |
56 : V8AbstractEventListener(true, DOMWrapperWorld::mainWorld(), isolate) | 56 : V8AbstractEventListener(true, isolate) |
57 , m_functionName(functionName) | 57 , m_functionName(functionName) |
58 , m_eventParameterName(eventParameterName) | 58 , m_eventParameterName(eventParameterName) |
59 , m_code(code) | 59 , m_code(code) |
60 , m_sourceURL(sourceURL) | 60 , m_sourceURL(sourceURL) |
61 , m_node(node) | 61 , m_node(node) |
62 , m_position(position) | 62 , m_position(position) |
63 { | 63 { |
64 } | 64 } |
65 | 65 |
66 template<typename T> | 66 template<typename T> |
67 v8::Handle<v8::Object> toObjectWrapper(T* domObject, v8::Isolate* isolate) | 67 v8::Handle<v8::Object> toObjectWrapper(T* domObject, ScriptState* scriptState) |
68 { | 68 { |
69 if (!domObject) | 69 if (!domObject) |
70 return v8::Object::New(isolate); | 70 return v8::Object::New(scriptState->isolate()); |
71 v8::Handle<v8::Value> value = toV8(domObject, v8::Handle<v8::Object>(), isol
ate); | 71 v8::Handle<v8::Value> value = toV8(domObject, scriptState->context()->Global
(), scriptState->isolate()); |
72 if (value.IsEmpty()) | 72 if (value.IsEmpty()) |
73 return v8::Object::New(isolate); | 73 return v8::Object::New(scriptState->isolate()); |
74 return v8::Local<v8::Object>::New(isolate, value.As<v8::Object>()); | 74 return v8::Local<v8::Object>::New(scriptState->isolate(), value.As<v8::Objec
t>()); |
75 } | 75 } |
76 | 76 |
77 v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(ExecutionContext*
context, v8::Handle<v8::Value> jsEvent, Event* event) | 77 v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(ExecutionContext*
context, v8::Handle<v8::Value> jsEvent, Event* event) |
78 { | 78 { |
79 v8::Local<v8::Object> listenerObject = getListenerObject(context); | 79 v8::Local<v8::Object> listenerObject = getListenerObject(context); |
80 if (listenerObject.IsEmpty()) | 80 if (listenerObject.IsEmpty()) |
81 return v8::Local<v8::Value>(); | 81 return v8::Local<v8::Value>(); |
82 | 82 |
83 v8::Local<v8::Function> handlerFunction = listenerObject.As<v8::Function>(); | 83 v8::Local<v8::Function> handlerFunction = listenerObject.As<v8::Function>(); |
84 v8::Local<v8::Object> receiver = getReceiverObject(context, event); | 84 v8::Local<v8::Object> receiver = getReceiverObject(event); |
85 if (handlerFunction.IsEmpty() || receiver.IsEmpty()) | 85 if (handlerFunction.IsEmpty() || receiver.IsEmpty()) |
86 return v8::Local<v8::Value>(); | 86 return v8::Local<v8::Value>(); |
87 | 87 |
88 // FIXME: Can |context| be 0 here? | 88 if (!scriptState()->executionContext()->isDocument()) |
89 if (!context) | |
90 return v8::Local<v8::Value>(); | 89 return v8::Local<v8::Value>(); |
91 | 90 |
92 if (!context->isDocument()) | 91 LocalFrame* frame = toDocument(scriptState()->executionContext())->frame(); |
93 return v8::Local<v8::Value>(); | |
94 | |
95 LocalFrame* frame = toDocument(context)->frame(); | |
96 if (!frame) | 92 if (!frame) |
97 return v8::Local<v8::Value>(); | 93 return v8::Local<v8::Value>(); |
98 | 94 |
99 if (!frame->script().canExecuteScripts(AboutToExecuteScript)) | 95 if (!frame->script().canExecuteScripts(AboutToExecuteScript)) |
100 return v8::Local<v8::Value>(); | 96 return v8::Local<v8::Value>(); |
101 | 97 |
102 v8::Handle<v8::Value> parameters[1] = { jsEvent }; | 98 v8::Handle<v8::Value> parameters[1] = { jsEvent }; |
103 return frame->script().callFunction(handlerFunction, receiver, WTF_ARRAY_LEN
GTH(parameters), parameters); | 99 return frame->script().callFunction(handlerFunction, receiver, WTF_ARRAY_LEN
GTH(parameters), parameters); |
104 } | 100 } |
105 | 101 |
106 static void V8LazyEventListenerToString(const v8::FunctionCallbackInfo<v8::Value
>& info) | 102 static void V8LazyEventListenerToString(const v8::FunctionCallbackInfo<v8::Value
>& info) |
107 { | 103 { |
108 v8SetReturnValue(info, V8HiddenValue::getHiddenValue(info.GetIsolate(), info
.Holder(), V8HiddenValue::toStringString(info.GetIsolate()))); | 104 v8SetReturnValue(info, V8HiddenValue::getHiddenValue(info.GetIsolate(), info
.Holder(), V8HiddenValue::toStringString(info.GetIsolate()))); |
109 } | 105 } |
110 | 106 |
| 107 void V8LazyEventListener::handleEvent(ExecutionContext* context, Event* event) |
| 108 { |
| 109 v8::HandleScope handleScope(toIsolate(context)); |
| 110 // V8LazyEventListener doesn't know the associated context when created. |
| 111 // Thus we lazily get the associated context and set a ScriptState on V8Abst
ractEventListener. |
| 112 v8::Local<v8::Context> v8Context = toV8Context(context, world()); |
| 113 if (v8Context.IsEmpty()) |
| 114 return; |
| 115 setScriptState(ScriptState::from(v8Context)); |
| 116 |
| 117 V8AbstractEventListener::handleEvent(context, event); |
| 118 } |
| 119 |
111 void V8LazyEventListener::prepareListenerObject(ExecutionContext* context) | 120 void V8LazyEventListener::prepareListenerObject(ExecutionContext* context) |
112 { | 121 { |
| 122 v8::HandleScope handleScope(toIsolate(context)); |
| 123 // V8LazyEventListener doesn't know the associated context when created. |
| 124 // Thus we lazily get the associated context and set a ScriptState on V8Abst
ractEventListener. |
| 125 v8::Local<v8::Context> v8Context = toV8Context(context, world()); |
| 126 if (v8Context.IsEmpty()) |
| 127 return; |
| 128 setScriptState(ScriptState::from(v8Context)); |
| 129 |
113 if (context->isDocument() && !toDocument(context)->allowInlineEventHandlers(
m_node, this, m_sourceURL, m_position.m_line)) { | 130 if (context->isDocument() && !toDocument(context)->allowInlineEventHandlers(
m_node, this, m_sourceURL, m_position.m_line)) { |
114 clearListenerObject(); | 131 clearListenerObject(); |
115 return; | 132 return; |
116 } | 133 } |
117 | 134 |
118 if (hasExistingListenerObject()) | 135 if (hasExistingListenerObject()) |
119 return; | 136 return; |
120 | 137 |
121 ASSERT(context->isDocument()); | 138 ASSERT(context->isDocument()); |
122 | 139 |
123 v8::Isolate* isolate = toIsolate(context); | 140 ScriptState::Scope scope(scriptState()); |
124 v8::HandleScope handleScope(isolate); | |
125 | |
126 // Use the outer scope to hold context. | |
127 v8::Local<v8::Context> v8Context = toV8Context(context, world()); | |
128 // Bail out if we cannot get the context. | |
129 if (v8Context.IsEmpty()) | |
130 return; | |
131 | |
132 v8::Context::Scope scope(v8Context); | |
133 | |
134 String listenerSource = InspectorInstrumentation::preprocessEventListener(t
oDocument(context)->frame(), m_code, m_sourceURL, m_functionName); | 141 String listenerSource = InspectorInstrumentation::preprocessEventListener(t
oDocument(context)->frame(), m_code, m_sourceURL, m_functionName); |
135 | 142 |
136 // FIXME: Remove the following 'with' hack. | 143 // FIXME: Remove the following 'with' hack. |
137 // | 144 // |
138 // Nodes other than the document object, when executing inline event | 145 // Nodes other than the document object, when executing inline event |
139 // handlers push document, form owner, and the target node on the scope chai
n. | 146 // handlers push document, form owner, and the target node on the scope chai
n. |
140 // We do this by using 'with' statement. | 147 // We do this by using 'with' statement. |
141 // See chrome/fast/forms/form-action.html | 148 // See chrome/fast/forms/form-action.html |
142 // chrome/fast/forms/selected-index-value.html | 149 // chrome/fast/forms/selected-index-value.html |
143 // base/fast/overflow/onscroll-layer-self-destruct.html | 150 // base/fast/overflow/onscroll-layer-self-destruct.html |
144 // | 151 // |
145 // Don't use new lines so that lines in the modified handler | 152 // Don't use new lines so that lines in the modified handler |
146 // have the same numbers as in the original code. | 153 // have the same numbers as in the original code. |
147 // FIXME: V8 does not allow us to programmatically create object environment
s so | 154 // FIXME: V8 does not allow us to programmatically create object environment
s so |
148 // we have to do this hack! What if m_code escapes to run arbitrary s
cript? | 155 // we have to do this hack! What if m_code escapes to run arbitrary s
cript? |
149 // | 156 // |
150 // Call with 4 arguments instead of 3, pass additional null as the last para
meter. | 157 // Call with 4 arguments instead of 3, pass additional null as the last para
meter. |
151 // By calling the function with 4 arguments, we create a setter on arguments
object | 158 // By calling the function with 4 arguments, we create a setter on arguments
object |
152 // which would shadow property "3" on the prototype. | 159 // which would shadow property "3" on the prototype. |
153 String code = "(function() {" | 160 String code = "(function() {" |
154 "with (this[2]) {" | 161 "with (this[2]) {" |
155 "with (this[1]) {" | 162 "with (this[1]) {" |
156 "with (this[0]) {" | 163 "with (this[0]) {" |
157 "return function(" + m_eventParameterName + ") {" + | 164 "return function(" + m_eventParameterName + ") {" + |
158 listenerSource + "\n" // Insert '\n' otherwise //-style comments
could break the handler. | 165 listenerSource + "\n" // Insert '\n' otherwise //-style comments
could break the handler. |
159 "};" | 166 "};" |
160 "}}}})"; | 167 "}}}})"; |
161 | 168 |
162 v8::Handle<v8::String> codeExternalString = v8String(isolate, code); | 169 v8::Handle<v8::String> codeExternalString = v8String(isolate(), code); |
163 | 170 |
164 v8::Local<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(co
deExternalString, isolate, m_sourceURL, m_position); | 171 v8::Local<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(co
deExternalString, isolate(), m_sourceURL, m_position); |
165 if (result.IsEmpty()) | 172 if (result.IsEmpty()) |
166 return; | 173 return; |
167 | 174 |
168 // Call the outer function to get the inner function. | 175 // Call the outer function to get the inner function. |
169 ASSERT(result->IsFunction()); | 176 ASSERT(result->IsFunction()); |
170 v8::Local<v8::Function> intermediateFunction = result.As<v8::Function>(); | 177 v8::Local<v8::Function> intermediateFunction = result.As<v8::Function>(); |
171 | 178 |
172 HTMLFormElement* formElement = 0; | 179 HTMLFormElement* formElement = 0; |
173 if (m_node && m_node->isHTMLElement()) | 180 if (m_node && m_node->isHTMLElement()) |
174 formElement = toHTMLElement(m_node)->formOwner(); | 181 formElement = toHTMLElement(m_node)->formOwner(); |
175 | 182 |
176 v8::Handle<v8::Object> nodeWrapper = toObjectWrapper<Node>(m_node, isolate); | 183 v8::Handle<v8::Object> nodeWrapper = toObjectWrapper<Node>(m_node, scriptSta
te()); |
177 v8::Handle<v8::Object> formWrapper = toObjectWrapper<HTMLFormElement>(formEl
ement, isolate); | 184 v8::Handle<v8::Object> formWrapper = toObjectWrapper<HTMLFormElement>(formEl
ement, scriptState()); |
178 v8::Handle<v8::Object> documentWrapper = toObjectWrapper<Document>(m_node ?
m_node->ownerDocument() : 0, isolate); | 185 v8::Handle<v8::Object> documentWrapper = toObjectWrapper<Document>(m_node ?
m_node->ownerDocument() : 0, scriptState()); |
179 | 186 |
180 v8::Local<v8::Object> thisObject = v8::Object::New(isolate); | 187 v8::Local<v8::Object> thisObject = v8::Object::New(isolate()); |
181 if (thisObject.IsEmpty()) | 188 if (thisObject.IsEmpty()) |
182 return; | 189 return; |
183 if (!thisObject->ForceSet(v8::Integer::New(isolate, 0), nodeWrapper)) | 190 if (!thisObject->ForceSet(v8::Integer::New(isolate(), 0), nodeWrapper)) |
184 return; | 191 return; |
185 if (!thisObject->ForceSet(v8::Integer::New(isolate, 1), formWrapper)) | 192 if (!thisObject->ForceSet(v8::Integer::New(isolate(), 1), formWrapper)) |
186 return; | 193 return; |
187 if (!thisObject->ForceSet(v8::Integer::New(isolate, 2), documentWrapper)) | 194 if (!thisObject->ForceSet(v8::Integer::New(isolate(), 2), documentWrapper)) |
188 return; | 195 return; |
189 | 196 |
190 // FIXME: Remove this code when we stop doing the 'with' hack above. | 197 // FIXME: Remove this code when we stop doing the 'with' hack above. |
191 v8::Local<v8::Value> innerValue = V8ScriptRunner::callInternalFunction(inter
mediateFunction, thisObject, 0, 0, isolate); | 198 v8::Local<v8::Value> innerValue = V8ScriptRunner::callInternalFunction(inter
mediateFunction, thisObject, 0, 0, isolate()); |
192 if (innerValue.IsEmpty() || !innerValue->IsFunction()) | 199 if (innerValue.IsEmpty() || !innerValue->IsFunction()) |
193 return; | 200 return; |
194 | 201 |
195 v8::Local<v8::Function> wrappedFunction = innerValue.As<v8::Function>(); | 202 v8::Local<v8::Function> wrappedFunction = innerValue.As<v8::Function>(); |
196 | 203 |
197 // Change the toString function on the wrapper function to avoid it | 204 // Change the toString function on the wrapper function to avoid it |
198 // returning the source for the actual wrapper function. Instead it | 205 // returning the source for the actual wrapper function. Instead it |
199 // returns source for a clean wrapper function with the event | 206 // returns source for a clean wrapper function with the event |
200 // argument wrapping the event source code. The reason for this is | 207 // argument wrapping the event source code. The reason for this is |
201 // that some web sites use toString on event functions and eval the | 208 // that some web sites use toString on event functions and eval the |
202 // source returned (sometimes a RegExp is applied as well) for some | 209 // source returned (sometimes a RegExp is applied as well) for some |
203 // other use. That fails miserably if the actual wrapper source is | 210 // other use. That fails miserably if the actual wrapper source is |
204 // returned. | 211 // returned. |
205 v8::Local<v8::Function> toStringFunction = v8::Function::New(isolate, V8Lazy
EventListenerToString); | 212 v8::Local<v8::Function> toStringFunction = v8::Function::New(isolate(), V8La
zyEventListenerToString); |
206 ASSERT(!toStringFunction.IsEmpty()); | 213 ASSERT(!toStringFunction.IsEmpty()); |
207 String toStringString = "function " + m_functionName + "(" + m_eventParamete
rName + ") {\n " + m_code + "\n}"; | 214 String toStringString = "function " + m_functionName + "(" + m_eventParamete
rName + ") {\n " + m_code + "\n}"; |
208 V8HiddenValue::setHiddenValue(isolate, wrappedFunction, V8HiddenValue::toStr
ingString(isolate), v8String(isolate, toStringString)); | 215 V8HiddenValue::setHiddenValue(isolate(), wrappedFunction, V8HiddenValue::toS
tringString(isolate()), v8String(isolate(), toStringString)); |
209 wrappedFunction->Set(v8AtomicString(isolate, "toString"), toStringFunction); | 216 wrappedFunction->Set(v8AtomicString(isolate(), "toString"), toStringFunction
); |
210 wrappedFunction->SetName(v8String(isolate, m_functionName)); | 217 wrappedFunction->SetName(v8String(isolate(), m_functionName)); |
211 | 218 |
212 // FIXME: Remove the following comment-outs. | 219 // FIXME: Remove the following comment-outs. |
213 // See https://bugs.webkit.org/show_bug.cgi?id=85152 for more details. | 220 // See https://bugs.webkit.org/show_bug.cgi?id=85152 for more details. |
214 // | 221 // |
215 // For the time being, we comment out the following code since the | 222 // For the time being, we comment out the following code since the |
216 // second parsing can happen. | 223 // second parsing can happen. |
217 // // Since we only parse once, there's no need to keep data used for parsin
g around anymore. | 224 // // Since we only parse once, there's no need to keep data used for parsin
g around anymore. |
218 // m_functionName = String(); | 225 // m_functionName = String(); |
219 // m_code = String(); | 226 // m_code = String(); |
220 // m_eventParameterName = String(); | 227 // m_eventParameterName = String(); |
221 // m_sourceURL = String(); | 228 // m_sourceURL = String(); |
222 | 229 |
223 setListenerObject(wrappedFunction); | 230 setListenerObject(wrappedFunction); |
224 } | 231 } |
225 | 232 |
226 } // namespace WebCore | 233 } // namespace WebCore |
OLD | NEW |