| 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 |