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 // FIXME: Can |context| be 0 here? |
89 if (!context) | 89 if (!context) |
90 return v8::Local<v8::Value>(); | 90 return v8::Local<v8::Value>(); |
91 | 91 |
92 if (!context->isDocument()) | 92 if (!context->isDocument()) |
93 return v8::Local<v8::Value>(); | 93 return v8::Local<v8::Value>(); |
94 | 94 |
95 LocalFrame* frame = toDocument(context)->frame(); | 95 LocalFrame* frame = toDocument(context)->frame(); |
96 if (!frame) | 96 if (!frame) |
97 return v8::Local<v8::Value>(); | 97 return v8::Local<v8::Value>(); |
98 | 98 |
99 if (!frame->script().canExecuteScripts(AboutToExecuteScript)) | 99 if (!frame->script().canExecuteScripts(AboutToExecuteScript)) |
100 return v8::Local<v8::Value>(); | 100 return v8::Local<v8::Value>(); |
101 | 101 |
102 v8::Handle<v8::Value> parameters[1] = { jsEvent }; | 102 v8::Handle<v8::Value> parameters[1] = { jsEvent }; |
103 return frame->script().callFunction(handlerFunction, receiver, WTF_ARRAY_LEN
GTH(parameters), parameters); | 103 return frame->script().callFunction(handlerFunction, receiver, WTF_ARRAY_LEN
GTH(parameters), parameters); |
104 } | 104 } |
105 | 105 |
106 static void V8LazyEventListenerToString(const v8::FunctionCallbackInfo<v8::Value
>& info) | 106 static void V8LazyEventListenerToString(const v8::FunctionCallbackInfo<v8::Value
>& info) |
107 { | 107 { |
108 v8SetReturnValue(info, V8HiddenValue::getHiddenValue(info.GetIsolate(), info
.Holder(), V8HiddenValue::toStringString(info.GetIsolate()))); | 108 v8SetReturnValue(info, V8HiddenValue::getHiddenValue(info.GetIsolate(), info
.Holder(), V8HiddenValue::toStringString(info.GetIsolate()))); |
109 } | 109 } |
110 | 110 |
| 111 void V8LazyEventListener::handleEvent(ExecutionContext* context, Event* event) |
| 112 { |
| 113 v8::HandleScope handleScope(toIsolate(context)); |
| 114 // V8LazyEventListener doesn't know the associated context when created. |
| 115 // Thus we lazily get the associated context and set a ScriptState on V8Abst
ractEventListener. |
| 116 v8::Local<v8::Context> v8Context = toV8Context(context, world()); |
| 117 if (v8Context.IsEmpty()) |
| 118 return; |
| 119 setScriptState(ScriptState::from(v8Context)); |
| 120 |
| 121 V8AbstractEventListener::handleEvent(context, event); |
| 122 } |
| 123 |
111 void V8LazyEventListener::prepareListenerObject(ExecutionContext* context) | 124 void V8LazyEventListener::prepareListenerObject(ExecutionContext* context) |
112 { | 125 { |
113 if (context->isDocument() && !toDocument(context)->allowInlineEventHandlers(
m_node, this, m_sourceURL, m_position.m_line)) { | 126 if (context->isDocument() && !toDocument(context)->allowInlineEventHandlers(
m_node, this, m_sourceURL, m_position.m_line)) { |
114 clearListenerObject(); | 127 clearListenerObject(); |
115 return; | 128 return; |
116 } | 129 } |
117 | 130 |
118 if (hasExistingListenerObject()) | 131 if (hasExistingListenerObject()) |
119 return; | 132 return; |
120 | 133 |
121 ASSERT(context->isDocument()); | 134 ASSERT(context->isDocument()); |
122 | 135 |
123 v8::Isolate* isolate = toIsolate(context); | 136 v8::HandleScope handleScope(toIsolate(context)); |
124 v8::HandleScope handleScope(isolate); | 137 // V8LazyEventListener doesn't know the associated context when created. |
125 | 138 // Thus we lazily get the associated context and set a ScriptState on V8Abst
ractEventListener. |
126 // Use the outer scope to hold context. | |
127 v8::Local<v8::Context> v8Context = toV8Context(context, world()); | 139 v8::Local<v8::Context> v8Context = toV8Context(context, world()); |
128 // Bail out if we cannot get the context. | |
129 if (v8Context.IsEmpty()) | 140 if (v8Context.IsEmpty()) |
130 return; | 141 return; |
| 142 setScriptState(ScriptState::from(v8Context)); |
131 | 143 |
132 v8::Context::Scope scope(v8Context); | 144 ScriptState::Scope scope(scriptState()); |
133 | |
134 String listenerSource = InspectorInstrumentation::preprocessEventListener(t
oDocument(context)->frame(), m_code, m_sourceURL, m_functionName); | 145 String listenerSource = InspectorInstrumentation::preprocessEventListener(t
oDocument(context)->frame(), m_code, m_sourceURL, m_functionName); |
135 | 146 |
136 // FIXME: Remove the following 'with' hack. | 147 // FIXME: Remove the following 'with' hack. |
137 // | 148 // |
138 // Nodes other than the document object, when executing inline event | 149 // 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. | 150 // handlers push document, form owner, and the target node on the scope chai
n. |
140 // We do this by using 'with' statement. | 151 // We do this by using 'with' statement. |
141 // See chrome/fast/forms/form-action.html | 152 // See chrome/fast/forms/form-action.html |
142 // chrome/fast/forms/selected-index-value.html | 153 // chrome/fast/forms/selected-index-value.html |
143 // base/fast/overflow/onscroll-layer-self-destruct.html | 154 // base/fast/overflow/onscroll-layer-self-destruct.html |
144 // | 155 // |
145 // Don't use new lines so that lines in the modified handler | 156 // Don't use new lines so that lines in the modified handler |
146 // have the same numbers as in the original code. | 157 // have the same numbers as in the original code. |
147 // FIXME: V8 does not allow us to programmatically create object environment
s so | 158 // 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? | 159 // we have to do this hack! What if m_code escapes to run arbitrary s
cript? |
149 // | 160 // |
150 // Call with 4 arguments instead of 3, pass additional null as the last para
meter. | 161 // 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 | 162 // By calling the function with 4 arguments, we create a setter on arguments
object |
152 // which would shadow property "3" on the prototype. | 163 // which would shadow property "3" on the prototype. |
153 String code = "(function() {" | 164 String code = "(function() {" |
154 "with (this[2]) {" | 165 "with (this[2]) {" |
155 "with (this[1]) {" | 166 "with (this[1]) {" |
156 "with (this[0]) {" | 167 "with (this[0]) {" |
157 "return function(" + m_eventParameterName + ") {" + | 168 "return function(" + m_eventParameterName + ") {" + |
158 listenerSource + "\n" // Insert '\n' otherwise //-style comments
could break the handler. | 169 listenerSource + "\n" // Insert '\n' otherwise //-style comments
could break the handler. |
159 "};" | 170 "};" |
160 "}}}})"; | 171 "}}}})"; |
161 | 172 |
162 v8::Handle<v8::String> codeExternalString = v8String(isolate, code); | 173 v8::Handle<v8::String> codeExternalString = v8String(isolate(), code); |
163 | 174 |
164 v8::Local<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(co
deExternalString, isolate, m_sourceURL, m_position); | 175 v8::Local<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(co
deExternalString, isolate(), m_sourceURL, m_position); |
165 if (result.IsEmpty()) | 176 if (result.IsEmpty()) |
166 return; | 177 return; |
167 | 178 |
168 // Call the outer function to get the inner function. | 179 // Call the outer function to get the inner function. |
169 ASSERT(result->IsFunction()); | 180 ASSERT(result->IsFunction()); |
170 v8::Local<v8::Function> intermediateFunction = result.As<v8::Function>(); | 181 v8::Local<v8::Function> intermediateFunction = result.As<v8::Function>(); |
171 | 182 |
172 HTMLFormElement* formElement = 0; | 183 HTMLFormElement* formElement = 0; |
173 if (m_node && m_node->isHTMLElement()) | 184 if (m_node && m_node->isHTMLElement()) |
174 formElement = toHTMLElement(m_node)->formOwner(); | 185 formElement = toHTMLElement(m_node)->formOwner(); |
175 | 186 |
176 v8::Handle<v8::Object> nodeWrapper = toObjectWrapper<Node>(m_node, isolate); | 187 v8::Handle<v8::Object> nodeWrapper = toObjectWrapper<Node>(m_node, scriptSta
te()); |
177 v8::Handle<v8::Object> formWrapper = toObjectWrapper<HTMLFormElement>(formEl
ement, isolate); | 188 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); | 189 v8::Handle<v8::Object> documentWrapper = toObjectWrapper<Document>(m_node ?
m_node->ownerDocument() : 0, scriptState()); |
179 | 190 |
180 v8::Local<v8::Object> thisObject = v8::Object::New(isolate); | 191 v8::Local<v8::Object> thisObject = v8::Object::New(isolate()); |
181 if (thisObject.IsEmpty()) | 192 if (thisObject.IsEmpty()) |
182 return; | 193 return; |
183 if (!thisObject->ForceSet(v8::Integer::New(isolate, 0), nodeWrapper)) | 194 if (!thisObject->ForceSet(v8::Integer::New(isolate(), 0), nodeWrapper)) |
184 return; | 195 return; |
185 if (!thisObject->ForceSet(v8::Integer::New(isolate, 1), formWrapper)) | 196 if (!thisObject->ForceSet(v8::Integer::New(isolate(), 1), formWrapper)) |
186 return; | 197 return; |
187 if (!thisObject->ForceSet(v8::Integer::New(isolate, 2), documentWrapper)) | 198 if (!thisObject->ForceSet(v8::Integer::New(isolate(), 2), documentWrapper)) |
188 return; | 199 return; |
189 | 200 |
190 // FIXME: Remove this code when we stop doing the 'with' hack above. | 201 // 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); | 202 v8::Local<v8::Value> innerValue = V8ScriptRunner::callInternalFunction(inter
mediateFunction, thisObject, 0, 0, isolate()); |
192 if (innerValue.IsEmpty() || !innerValue->IsFunction()) | 203 if (innerValue.IsEmpty() || !innerValue->IsFunction()) |
193 return; | 204 return; |
194 | 205 |
195 v8::Local<v8::Function> wrappedFunction = innerValue.As<v8::Function>(); | 206 v8::Local<v8::Function> wrappedFunction = innerValue.As<v8::Function>(); |
196 | 207 |
197 // Change the toString function on the wrapper function to avoid it | 208 // Change the toString function on the wrapper function to avoid it |
198 // returning the source for the actual wrapper function. Instead it | 209 // returning the source for the actual wrapper function. Instead it |
199 // returns source for a clean wrapper function with the event | 210 // returns source for a clean wrapper function with the event |
200 // argument wrapping the event source code. The reason for this is | 211 // argument wrapping the event source code. The reason for this is |
201 // that some web sites use toString on event functions and eval the | 212 // that some web sites use toString on event functions and eval the |
202 // source returned (sometimes a RegExp is applied as well) for some | 213 // source returned (sometimes a RegExp is applied as well) for some |
203 // other use. That fails miserably if the actual wrapper source is | 214 // other use. That fails miserably if the actual wrapper source is |
204 // returned. | 215 // returned. |
205 v8::Local<v8::Function> toStringFunction = v8::Function::New(isolate, V8Lazy
EventListenerToString); | 216 v8::Local<v8::Function> toStringFunction = v8::Function::New(isolate(), V8La
zyEventListenerToString); |
206 ASSERT(!toStringFunction.IsEmpty()); | 217 ASSERT(!toStringFunction.IsEmpty()); |
207 String toStringString = "function " + m_functionName + "(" + m_eventParamete
rName + ") {\n " + m_code + "\n}"; | 218 String toStringString = "function " + m_functionName + "(" + m_eventParamete
rName + ") {\n " + m_code + "\n}"; |
208 V8HiddenValue::setHiddenValue(isolate, wrappedFunction, V8HiddenValue::toStr
ingString(isolate), v8String(isolate, toStringString)); | 219 V8HiddenValue::setHiddenValue(isolate(), wrappedFunction, V8HiddenValue::toS
tringString(isolate()), v8String(isolate(), toStringString)); |
209 wrappedFunction->Set(v8AtomicString(isolate, "toString"), toStringFunction); | 220 wrappedFunction->Set(v8AtomicString(isolate(), "toString"), toStringFunction
); |
210 wrappedFunction->SetName(v8String(isolate, m_functionName)); | 221 wrappedFunction->SetName(v8String(isolate(), m_functionName)); |
211 | 222 |
212 // FIXME: Remove the following comment-outs. | 223 // FIXME: Remove the following comment-outs. |
213 // See https://bugs.webkit.org/show_bug.cgi?id=85152 for more details. | 224 // See https://bugs.webkit.org/show_bug.cgi?id=85152 for more details. |
214 // | 225 // |
215 // For the time being, we comment out the following code since the | 226 // For the time being, we comment out the following code since the |
216 // second parsing can happen. | 227 // second parsing can happen. |
217 // // Since we only parse once, there's no need to keep data used for parsin
g around anymore. | 228 // // Since we only parse once, there's no need to keep data used for parsin
g around anymore. |
218 // m_functionName = String(); | 229 // m_functionName = String(); |
219 // m_code = String(); | 230 // m_code = String(); |
220 // m_eventParameterName = String(); | 231 // m_eventParameterName = String(); |
221 // m_sourceURL = String(); | 232 // m_sourceURL = String(); |
222 | 233 |
223 setListenerObject(wrappedFunction); | 234 setListenerObject(wrappedFunction); |
224 } | 235 } |
225 | 236 |
226 } // namespace WebCore | 237 } // namespace WebCore |
OLD | NEW |