Commit 9b999edb authored by ap@apple.com's avatar ap@apple.com

Reverting r48767, as it broke Windows build in a non-trivial way.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@48778 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent fe5c8a64
2009-09-25 Alexey Proskuryakov <ap@apple.com>
Reverting r48767, as it broke Windows build in a non-trivial way.
* fast/events/attribute-listener-cloned-from-frameless-doc-context-2-expected.txt: Removed.
* fast/events/attribute-listener-cloned-from-frameless-doc-context-2.html: Removed.
* fast/events/attribute-listener-cloned-from-frameless-doc-context-expected.txt: Removed.
* fast/events/attribute-listener-cloned-from-frameless-doc-context.html: Removed.
* fast/events/attribute-listener-cloned-from-frameless-doc-expected.txt: Removed.
* fast/events/attribute-listener-cloned-from-frameless-doc.xhtml: Removed.
* fast/events/attribute-listener-extracted-from-frameless-doc-context-2-expected.txt: Removed.
* fast/events/attribute-listener-extracted-from-frameless-doc-context-2.html: Removed.
* fast/events/attribute-listener-extracted-from-frameless-doc-context-expected.txt: Removed.
* fast/events/attribute-listener-extracted-from-frameless-doc-context.html: Removed.
2009-09-25 Simon Fraser <simon.fraser@apple.com>
Reviewed by Darin Adler.
......
<html>
<body onload="test()">
<iframe src='data:text/html,<a id="a" href="#" onclick="document.write(window != top ? &apos;<p>FAIL</p>&apos; : &apos;<p>PASS</p>&apos;); return false">link</a>'></iframe>
<script>
if (window.layoutTestController) {
layoutTestController.dumpAsText();
layoutTestController.waitUntilDone();
}
function test()
{
var doc = frames[0].document;
var range=doc.createRange();
range.selectNodeContents(doc.body);
var frag=range.cloneContents();
document.body.appendChild(frag);
frames[0].location = "data:text/html,";
frames[0].frameElement.onload = test2;
}
function test2()
{
var event = top.document.createEvent('MouseEvent');
event.initEvent('click', true, true);
top.document.getElementsByTagName('a')[0].dispatchEvent(event);
if (window.layoutTestController)
layoutTestController.notifyDone();
}
</script>
</body>
</html>
<html>
<body onload="test()">
<iframe src='data:text/html,<a id="a" href="#" onclick="document.write(window != top ? &apos;<p>FAIL</p>&apos; : &apos;<p>PASS</p>&apos;); return false">link</a>'></iframe>
<script>
if (window.layoutTestController) {
layoutTestController.dumpAsText();
layoutTestController.waitUntilDone();
}
function test()
{
var doc = frames[0].document;
var range=doc.createRange();
range.selectNodeContents(doc.body);
var frag=range.cloneContents();
document.body.appendChild(frag);
var event = top.document.createEvent('MouseEvent');
event.initEvent('click', true, true);
top.document.getElementsByTagName('a')[0].dispatchEvent(event);
if (window.layoutTestController)
layoutTestController.notifyDone();
}
</script>
</body>
</html>
ALERT: SUCCESS
Test that an element that was imported from a frameless document has functional attribute event listeners. Should alert "SUCCESS".
Link (clicked automatically).Element.onclick result is correct.
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<p>Test that an element that was imported from a frameless document has functional attribute event listeners. Should alert "SUCCESS".</p>
<script>
<![CDATA[
if (window.layoutTestController)
layoutTestController.dumpAsText();
var doc = (new DOMParser).parseFromString('<html xmlns="http://www.w3.org/1999/xhtml"><a id="a" href="javascript:alert(\'FAIL\')" onclick="alert(\'SUCCESS\'); return false">Link (clicked automatically).</a></html>', "application/xhtml+xml");
var a = doc.documentElement.firstChild.cloneNode(true);
document.getElementsByTagName("body")[0].appendChild(a);
var event = document.createEvent('MouseEvent');
event.initEvent('click', true, true);
document.getElementsByTagName('a')[0].dispatchEvent(event);
if (0 == document.getElementsByTagName('a')[0].onclick.toString().indexOf("function onclick"))
document.body.appendChild(document.createTextNode("Element.onclick result is correct."));
]]>
</script>
</body>
</html>
<html>
<body onload="test()">
<iframe src='data:text/html,<a id="a" href="#" onclick="document.write(window != top ? &apos;<p>FAIL</p>&apos; : &apos;<p>PASS</p>&apos;); return false">link</a>'></iframe>
<script>
if (window.layoutTestController) {
layoutTestController.dumpAsText();
layoutTestController.waitUntilDone();
}
function test()
{
var doc = frames[0].document;
var range=doc.createRange();
range.selectNodeContents(doc.body);
var frag=range.extractContents();
document.body.appendChild(frag);
frames[0].location = "data:text/html,";
frames[0].frameElement.onload = test2;
}
function test2()
{
var event = top.document.createEvent('MouseEvent');
event.initEvent('click', true, true);
top.document.getElementsByTagName('a')[0].dispatchEvent(event);
if (window.layoutTestController)
layoutTestController.notifyDone();
}
</script>
</body>
</html>
<html>
<body onload="test()">
<iframe src='data:text/html,<a id="a" href="#" onclick="document.write(window != top ? &apos;<p>FAIL</p>&apos; : &apos;<p>PASS</p>&apos;); return false">link</a>'></iframe>
<script>
if (window.layoutTestController) {
layoutTestController.dumpAsText();
layoutTestController.waitUntilDone();
}
function test()
{
var doc = frames[0].document;
var range=doc.createRange();
range.selectNodeContents(doc.body);
var frag=range.extractContents();
document.body.appendChild(frag);
var event = top.document.createEvent('MouseEvent');
event.initEvent('click', true, true);
top.document.getElementsByTagName('a')[0].dispatchEvent(event);
if (window.layoutTestController)
layoutTestController.notifyDone();
}
</script>
</body>
</html>
This diff is collapsed.
......@@ -54,7 +54,7 @@ JSValue JSAbstractWorker::addEventListener(ExecState* exec, const ArgList& args)
if (!listener.isObject())
return jsUndefined();
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec));
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false), args.at(2).toBoolean(exec));
return jsUndefined();
}
......@@ -68,7 +68,7 @@ JSValue JSAbstractWorker::removeEventListener(ExecState* exec, const ArgList& ar
if (!listener.isObject())
return jsUndefined();
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec));
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
......
......@@ -95,7 +95,7 @@ JSValue JSDOMApplicationCache::addEventListener(ExecState* exec, const ArgList&
if (!listener.isObject())
return jsUndefined();
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec));
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false), args.at(2).toBoolean(exec));
return jsUndefined();
}
......@@ -109,7 +109,7 @@ JSValue JSDOMApplicationCache::removeEventListener(ExecState* exec, const ArgLis
if (!listener.isObject())
return jsUndefined();
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec));
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
......
......@@ -68,7 +68,7 @@ PassRefPtr<JSEventListener> JSDOMGlobalObject::createJSAttributeEventListener(JS
if (!val.isObject())
return 0;
return JSEventListener::create(asObject(val), true).get();
return JSEventListener::create(asObject(val), this, true).get();
}
void JSDOMGlobalObject::setCurrentEvent(Event* evt)
......
......@@ -1034,7 +1034,7 @@ JSValue JSDOMWindow::addEventListener(ExecState* exec, const ArgList& args)
if (!listener.isObject())
return jsUndefined();
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec));
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false), args.at(2).toBoolean(exec));
return jsUndefined();
}
......@@ -1048,7 +1048,7 @@ JSValue JSDOMWindow::removeEventListener(ExecState* exec, const ArgList& args)
if (!listener.isObject())
return jsUndefined();
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec));
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
......
......@@ -31,18 +31,20 @@ using namespace JSC;
namespace WebCore {
JSEventListener::JSEventListener(JSObject* function, bool isAttribute)
JSEventListener::JSEventListener(JSObject* function, JSDOMGlobalObject* globalObject, bool isAttribute)
: EventListener(JSEventListenerType)
, m_jsFunction(function)
, m_globalObject(globalObject)
, m_isAttribute(isAttribute)
{
ASSERT(m_globalObject);
}
JSEventListener::~JSEventListener()
{
}
JSObject* JSEventListener::jsFunction(ScriptExecutionContext*) const
JSObject* JSEventListener::jsFunction() const
{
return m_jsFunction;
}
......@@ -51,22 +53,20 @@ void JSEventListener::markJSFunction(MarkStack& markStack)
{
if (m_jsFunction)
markStack.append(m_jsFunction);
markStack.append(m_globalObject);
}
void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event)
void JSEventListener::handleEvent(Event* event)
{
ASSERT(scriptExecutionContext);
if (!scriptExecutionContext)
return;
JSLock lock(SilenceAssertionsOnly);
JSObject* jsFunction = this->jsFunction(scriptExecutionContext);
JSObject* jsFunction = this->jsFunction();
if (!jsFunction)
return;
JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext);
if (!globalObject)
JSDOMGlobalObject* globalObject = m_globalObject;
ScriptExecutionContext* scriptExecutionContext = globalObject->scriptExecutionContext();
if (!scriptExecutionContext)
return;
if (scriptExecutionContext->isDocument()) {
......@@ -132,15 +132,15 @@ void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext
}
}
bool JSEventListener::reportError(ScriptExecutionContext* context, const String& message, const String& url, int lineNumber)
bool JSEventListener::reportError(const String& message, const String& url, int lineNumber)
{
JSLock lock(SilenceAssertionsOnly);
JSObject* jsFunction = this->jsFunction(context);
JSObject* jsFunction = this->jsFunction();
if (!jsFunction)
return false;
JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context);
JSDOMGlobalObject* globalObject = m_globalObject;
ExecState* exec = globalObject->globalExec();
CallData callData;
......
......@@ -30,9 +30,9 @@ namespace WebCore {
class JSEventListener : public EventListener {
public:
static PassRefPtr<JSEventListener> create(JSC::JSObject* listener, bool isAttribute)
static PassRefPtr<JSEventListener> create(JSC::JSObject* listener, JSDOMGlobalObject* globalObject, bool isAttribute)
{
return adoptRef(new JSEventListener(listener, isAttribute));
return adoptRef(new JSEventListener(listener, globalObject, isAttribute));
}
static const JSEventListener* cast(const EventListener* listener)
......@@ -49,19 +49,20 @@ namespace WebCore {
// Returns true if this event listener was created for an event handler attribute, like "onload" or "onclick".
bool isAttribute() const { return m_isAttribute; }
virtual JSC::JSObject* jsFunction(ScriptExecutionContext*) const;
virtual JSC::JSObject* jsFunction() const;
private:
virtual void markJSFunction(JSC::MarkStack&);
virtual void handleEvent(ScriptExecutionContext*, Event*);
virtual bool reportError(ScriptExecutionContext*, const String& message, const String& url, int lineNumber);
virtual void handleEvent(Event*);
virtual bool reportError(const String& message, const String& url, int lineNumber);
virtual bool virtualisAttribute() const;
void clearJSFunctionInline();
protected:
JSEventListener(JSC::JSObject* function, bool isAttribute);
JSEventListener(JSC::JSObject* function, JSDOMGlobalObject*, bool isAttribute);
mutable JSC::JSObject* m_jsFunction;
JSDOMGlobalObject* m_globalObject;
bool m_isAttribute;
};
......
......@@ -53,7 +53,7 @@ JSValue JSEventSource::addEventListener(ExecState* exec, const ArgList& args)
if (!listener.isObject())
return jsUndefined();
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec));
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
......@@ -67,7 +67,7 @@ JSValue JSEventSource::removeEventListener(ExecState* exec, const ArgList& args)
if (!listener.isObject())
return jsUndefined();
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec));
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
......
......@@ -35,13 +35,12 @@ namespace WebCore {
static WTF::RefCountedLeakCounter eventListenerCounter("JSLazyEventListener");
#endif
JSLazyEventListener::JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, Node* node, const String& sourceURL, int lineNumber)
: JSEventListener(0, true)
JSLazyEventListener::JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, JSDOMGlobalObject* globalObject, Node* node, int lineNumber)
: JSEventListener(0, globalObject, true)
, m_functionName(functionName)
, m_eventParameterName(eventParameterName)
, m_code(code)
, m_parsed(false)
, m_sourceURL(sourceURL)
, m_lineNumber(lineNumber)
, m_originalNode(node)
{
......@@ -68,43 +67,23 @@ JSLazyEventListener::~JSLazyEventListener()
#endif
}
JSObject* JSLazyEventListener::jsFunction(ScriptExecutionContext* executionContext) const
JSObject* JSLazyEventListener::jsFunction() const
{
parseCode(executionContext);
parseCode();
return m_jsFunction;
}
void JSLazyEventListener::parseCode(ScriptExecutionContext* executionContext) const
void JSLazyEventListener::parseCode() const
{
ASSERT(executionContext);
ASSERT(executionContext->isDocument());
if (!executionContext)
return;
if (m_parsed)
return;
Frame* frame = static_cast<Document*>(executionContext)->frame();
if (!frame)
return;
ScriptController* scriptController = frame->script();
if (!scriptController->isEnabled())
return;
JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(executionContext);
if (!globalObject)
ScriptExecutionContext* executionContext = m_globalObject->scriptExecutionContext();
ASSERT(executionContext);
if (!executionContext)
return;
// Ensure that 'node' has a JavaScript wrapper to mark the event listener we're creating.
if (m_originalNode) {
JSLock lock(SilenceAssertionsOnly);
// FIXME: Should pass the global object associated with the node
toJS(globalObject->globalExec(), globalObject, m_originalNode);
}
if (executionContext->isDocument()) {
JSDOMWindow* window = static_cast<JSDOMWindow*>(globalObject);
JSDOMWindow* window = static_cast<JSDOMWindow*>(m_globalObject);
Frame* frame = window->impl()->frame();
if (!frame)
return;
......@@ -116,13 +95,16 @@ void JSLazyEventListener::parseCode(ScriptExecutionContext* executionContext) co
m_parsed = true;
ExecState* exec = globalObject->globalExec();
ExecState* exec = m_globalObject->globalExec();
MarkedArgumentBuffer args;
UString sourceURL(executionContext->url().string());
args.append(jsNontrivialString(exec, m_eventParameterName));
args.append(jsString(exec, m_code));
m_jsFunction = constructFunction(exec, args, Identifier(exec, m_functionName), m_sourceURL, m_lineNumber); // FIXME: is globalExec ok?
// FIXME: Passing the document's URL to construct is not always correct, since this event listener might
// have been added with setAttribute from a script, and we should pass String() in that case.
m_jsFunction = constructFunction(exec, args, Identifier(exec, m_functionName), sourceURL, m_lineNumber); // FIXME: is globalExec ok?
JSFunction* listenerAsFunction = static_cast<JSFunction*>(m_jsFunction);
......@@ -136,7 +118,7 @@ void JSLazyEventListener::parseCode(ScriptExecutionContext* executionContext) co
// (and the document, and the form - see JSHTMLElement::eventHandlerScope)
ScopeChain scope = listenerAsFunction->scope();
JSValue thisObj = toJS(exec, globalObject, m_originalNode);
JSValue thisObj = toJS(exec, m_globalObject, m_originalNode);
if (thisObj.isObject()) {
static_cast<JSNode*>(asObject(thisObj))->pushEventHandlerScope(exec, scope);
listenerAsFunction->setScope(scope);
......@@ -147,7 +129,6 @@ void JSLazyEventListener::parseCode(ScriptExecutionContext* executionContext) co
m_functionName = String();
m_code = String();
m_eventParameterName = String();
m_sourceURL = String();
}
} // namespace WebCore
......@@ -29,25 +29,24 @@ namespace WebCore {
class JSLazyEventListener : public JSEventListener {
public:
static PassRefPtr<JSLazyEventListener> create(const String& functionName, const String& eventParameterName, const String& code, Node* node, const String& sourceURL, int lineNumber)
static PassRefPtr<JSLazyEventListener> create(const String& functionName, const String& eventParameterName, const String& code, JSDOMGlobalObject* globalObject, Node* node, int lineNumber)
{
return adoptRef(new JSLazyEventListener(functionName, eventParameterName, code, node, sourceURL, lineNumber));
return adoptRef(new JSLazyEventListener(functionName, eventParameterName, code, globalObject, node, lineNumber));
}
virtual ~JSLazyEventListener();
private:
JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, Node*, const String& sourceURL, int lineNumber);
JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, JSDOMGlobalObject*, Node*, int lineNumber);
virtual JSC::JSObject* jsFunction(ScriptExecutionContext*) const;
virtual JSC::JSObject* jsFunction() const;
virtual bool wasCreatedFromMarkup() const { return true; }
void parseCode(ScriptExecutionContext*) const;
void parseCode() const;
mutable String m_functionName;
mutable String m_eventParameterName;
mutable String m_code;
mutable bool m_parsed;
mutable String m_sourceURL;
int m_lineNumber;
Node* m_originalNode;
};
......
......@@ -65,7 +65,7 @@ JSValue JSMessagePort::addEventListener(ExecState* exec, const ArgList& args)
if (!listener.isObject())
return jsUndefined();
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec));
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
......@@ -79,7 +79,7 @@ JSValue JSMessagePort::removeEventListener(ExecState* exec, const ArgList& args)
if (!listener.isObject())
return jsUndefined();
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec));
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
......
......@@ -122,7 +122,7 @@ JSValue JSNode::addEventListener(ExecState* exec, const ArgList& args)
if (!listener.isObject())
return jsUndefined();
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec));
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false), args.at(2).toBoolean(exec));
return jsUndefined();
}
......@@ -140,7 +140,7 @@ JSValue JSNode::removeEventListener(ExecState* exec, const ArgList& args)
if (!listener.isObject())
return jsUndefined();
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec));
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
......
......@@ -58,7 +58,7 @@ JSValue JSSVGElementInstance::addEventListener(ExecState* exec, const ArgList& a
if (!listener.isObject())
return jsUndefined();
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec));
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false), args.at(2).toBoolean(exec));
return jsUndefined();
}
......@@ -72,7 +72,7 @@ JSValue JSSVGElementInstance::removeEventListener(ExecState* exec, const ArgList
if (!listener.isObject())
return jsUndefined();
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec));
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
......
......@@ -122,7 +122,7 @@ JSValue JSWorkerContext::addEventListener(ExecState* exec, const ArgList& args)
if (!listener.isObject())
return jsUndefined();
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec));
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false), args.at(2).toBoolean(exec));
return jsUndefined();
}
......@@ -132,7 +132,7 @@ JSValue JSWorkerContext::removeEventListener(ExecState* exec, const ArgList& arg
if (!listener.isObject())
return jsUndefined();
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec));
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
......
......@@ -160,7 +160,7 @@ JSValue JSXMLHttpRequest::addEventListener(ExecState* exec, const ArgList& args)
if (!listener.isObject())
return jsUndefined();
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec));
impl()->addEventListener(args.at(0).