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 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 if (!toDocument(executionContext)->allowInlineEventHandlers(m_node, this, m_
sourceURL, m_position.m_line)) { | 125 if (!toDocument(executionContext)->allowInlineEventHandlers(m_node, this, m_
sourceURL, m_position.m_line)) { |
126 clearListenerObject(); | 126 clearListenerObject(); |
127 return; | 127 return; |
128 } | 128 } |
129 | 129 |
130 if (hasExistingListenerObject()) | 130 if (hasExistingListenerObject()) |
131 return; | 131 return; |
132 | 132 |
133 ScriptState::Scope scope(scriptState); | 133 ScriptState::Scope scope(scriptState); |
134 | 134 |
135 // FIXME: Remove the following 'with' hack. | |
136 // | |
137 // Nodes other than the document object, when executing inline event | 135 // Nodes other than the document object, when executing inline event |
138 // handlers push document, form owner, and the target node on the scope chai
n. | 136 // handlers push document, form owner, and the target node on the scope chai
n. |
139 // We do this by using 'with' statement. | 137 // We do this by using 'with' statement. |
140 // See chrome/fast/forms/form-action.html | 138 // See fast/forms/form-action.html |
141 // chrome/fast/forms/selected-index-value.html | 139 // fast/forms/selected-index-value.html |
142 // base/fast/overflow/onscroll-layer-self-destruct.html | 140 // fast/overflow/onscroll-layer-self-destruct.html |
143 // | |
144 // Don't use new lines so that lines in the modified handler | |
145 // have the same numbers as in the original code. | |
146 // FIXME: V8 does not allow us to programmatically create object environment
s so | |
147 // we have to do this hack! What if m_code escapes to run arbitrary s
cript? | |
148 // | |
149 // Call with 4 arguments instead of 3, pass additional null as the last para
meter. | |
150 // By calling the function with 4 arguments, we create a setter on arguments
object | |
151 // which would shadow property "3" on the prototype. | |
152 String code = "(function() {" | |
153 "with (this[2]) {" | |
154 "with (this[1]) {" | |
155 "with (this[0]) {" | |
156 "return function(" + m_eventParameterName + ") {" + | |
157 m_code + "\n" // Insert '\n' otherwise //-style comments could b
reak the handler. | |
158 "};" | |
159 "}}}})"; | |
160 | |
161 v8::Handle<v8::String> codeExternalString = v8String(isolate(), code); | |
162 | |
163 v8::Local<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(co
deExternalString, isolate(), m_sourceURL, m_position); | |
164 if (result.IsEmpty()) | |
165 return; | |
166 | |
167 // Call the outer function to get the inner function. | |
168 if (!result->IsFunction()) | |
169 return; | |
170 v8::Local<v8::Function> intermediateFunction = result.As<v8::Function>(); | |
171 | |
172 HTMLFormElement* formElement = 0; | 141 HTMLFormElement* formElement = 0; |
173 if (m_node && m_node->isHTMLElement()) | 142 if (m_node && m_node->isHTMLElement()) |
174 formElement = toHTMLElement(m_node)->formOwner(); | 143 formElement = toHTMLElement(m_node)->formOwner(); |
175 | 144 |
176 v8::Handle<v8::Object> nodeWrapper = toObjectWrapper<Node>(m_node, scriptSta
te); | 145 v8::Local<v8::Object> scopes[3]; |
177 v8::Handle<v8::Object> formWrapper = toObjectWrapper<HTMLFormElement>(formEl
ement, scriptState); | 146 scopes[2] = toObjectWrapper<Node>(m_node, scriptState); |
178 v8::Handle<v8::Object> documentWrapper = toObjectWrapper<Document>(m_node ?
m_node->ownerDocument() : 0, scriptState); | 147 scopes[1] = toObjectWrapper<HTMLFormElement>(formElement, scriptState); |
| 148 scopes[0] = toObjectWrapper<Document>(m_node ? m_node->ownerDocument() : 0,
scriptState); |
179 | 149 |
180 v8::Local<v8::Object> thisObject = v8::Object::New(isolate()); | 150 v8::Local<v8::String> parameterName = v8String(isolate(), m_eventParameterNa
me); |
181 if (thisObject.IsEmpty()) | 151 v8::ScriptCompiler::Source source(v8String(isolate(), m_code)); |
| 152 |
| 153 v8::Local<v8::Function> wrappedFunction = v8::ScriptCompiler::CompileFunctio
nInContext(isolate(), &source, v8Context, 1, ¶meterName, 3, scopes); |
| 154 |
| 155 if (wrappedFunction.IsEmpty()) |
182 return; | 156 return; |
183 if (!thisObject->ForceSet(v8::Integer::New(isolate(), 0), nodeWrapper)) | |
184 return; | |
185 if (!thisObject->ForceSet(v8::Integer::New(isolate(), 1), formWrapper)) | |
186 return; | |
187 if (!thisObject->ForceSet(v8::Integer::New(isolate(), 2), documentWrapper)) | |
188 return; | |
189 | |
190 // 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()); | |
192 if (innerValue.IsEmpty() || !innerValue->IsFunction()) | |
193 return; | |
194 | |
195 v8::Local<v8::Function> wrappedFunction = innerValue.As<v8::Function>(); | |
196 | 157 |
197 // Change the toString function on the wrapper function to avoid it | 158 // Change the toString function on the wrapper function to avoid it |
198 // returning the source for the actual wrapper function. Instead it | 159 // returning the source for the actual wrapper function. Instead it |
199 // returns source for a clean wrapper function with the event | 160 // returns source for a clean wrapper function with the event |
200 // argument wrapping the event source code. The reason for this is | 161 // argument wrapping the event source code. The reason for this is |
201 // that some web sites use toString on event functions and eval the | 162 // that some web sites use toString on event functions and eval the |
202 // source returned (sometimes a RegExp is applied as well) for some | 163 // source returned (sometimes a RegExp is applied as well) for some |
203 // other use. That fails miserably if the actual wrapper source is | 164 // other use. That fails miserably if the actual wrapper source is |
204 // returned. | 165 // returned. |
205 v8::Local<v8::Function> toStringFunction = v8::Function::New(isolate(), V8La
zyEventListenerToString); | 166 v8::Local<v8::Function> toStringFunction = v8::Function::New(isolate(), V8La
zyEventListenerToString); |
(...skipping 12 matching lines...) Expand all Loading... |
218 // // Since we only parse once, there's no need to keep data used for parsin
g around anymore. | 179 // // Since we only parse once, there's no need to keep data used for parsin
g around anymore. |
219 // m_functionName = String(); | 180 // m_functionName = String(); |
220 // m_code = String(); | 181 // m_code = String(); |
221 // m_eventParameterName = String(); | 182 // m_eventParameterName = String(); |
222 // m_sourceURL = String(); | 183 // m_sourceURL = String(); |
223 | 184 |
224 setListenerObject(wrappedFunction); | 185 setListenerObject(wrappedFunction); |
225 } | 186 } |
226 | 187 |
227 } // namespace blink | 188 } // namespace blink |
OLD | NEW |