I can't seem to reply to the source of a MessageEvent in this script using IE8. I can't figure out why I get a "evt.source is null or undefined" error as it works normally when I do window.addEvent("onmessage", function(evt){print(evt.source)}) and outputs "[object Window]".
Am I doing something wrong that would make evt.source be null or undefined? If so, please tell me what it is that I am doing wrong.
The script works in every Gecko 1.9.x browser, Safari 4, Google Chrome 2, and Opera 9.6+.
Code:
(function() {
var alwaysTrustedOrigins = [ // always trusted origins, can be exact strings or regular expressions
];
if (typeof window.opera != "undefined") { // Opera 9.x postMessage fix (only for http :, not https :)
if (parseInt(window.opera.version()) == 9) Event.prototype.__defineGetter__("origin", function() {
/*WTF ProgrammingTalk, since when was http :// is an external URL?!*/
return "http"+"://" + this.domain;
})
}
function pmxdrRequestHandler(evt) {
var alwaysTrusted = false, data = JSON.parse(evt.data), headers = [];
if (data.pmxdr == true) { // only handle pmxdr requests
for (var i=0; i<alwaysTrustedOrigins.length; i++) {
if (alwaysTrustedOrigins[i] instanceof RegExp)
alwaysTrusted = alwaysTrustedOrigins[i].test(evt.origin);
else if (typeof alwaysTrustedOrigins[i] == "string")
alwaysTrusted = (origin === alwaysTrustedOrigins[i]);
}
if (typeof data.method == "string") data.method = data.method.toUpperCase();
var req = new XMLHttpRequest();
req.open(data.method, data.uri, true);
if (data.headers)
for (var header in data.headers)
if (data.headers.hasOwnProperty(header)) {
req.setRequestHeader(header, data.headers[header]);
headers.push(header.toLowerCase());
}
if (typeof data.data == "string") req.send(data.data)
else req.send(null);
function err(errorCode) {
var errorResponse = {
pmxdr : true,
error : errorCode,
status : req.status,
statusText : req.statusText,
id : data.id
};
evt.source.postMessage(JSON.stringify(errorResponse), evt.origin);
}
req.onreadystatechange = function() {
if(this.readyState == 4) {
if(this.status == 200) {
function getResponseHeader(header) {
return req.getResponseHeader(header)
}
var ac = { // access controls
origin : (getResponseHeader("Access-Control-Allow-Origin")||"").replace(/\s/g, ""),
methods: (getResponseHeader("Access-Control-Allow-Methods")||"").replace(/\s/g, "")
//,headers: (getResponseHeader("Access-Control-Allow-Headers")||"").replace(/\s/g, "")
};
if ( // determine if origin is trusted
alwaysTrusted == true
|| ac.origin == "*"
|| ac.origin.indexOf(evt.origin) != -1 )
{
if ( // determine if request method was allowed
!ac.methods
|| ac.methods == "*"
|| (typeof ac.methods == "string" && ac.methods.indexOf(data.method) != -1) )
{
var response = {
pmxdr : true, // signify that this is the response of a pmxdr request
data : this.responseText,
headers : {}, // populated with headers below
status : this.status,
statusText : this.statusText
}; if (typeof data.id != "undefined") response.id = data.id;
var responseHeaders = this.getAllResponseHeaders().split(/\r?\n/);
for (var i=0; i<responseHeaders.length; i++) {
var header = responseHeaders[i].split(": ");
response.headers[header[0].toLowerCase()] = header[1];
}
return evt.source.postMessage(JSON.stringify(response), evt.origin)
} else return err("DISALLOWED_REQUEST_METHOD"); // The request method was not allowed
} else return err("DISALLOWED_ORIGIN"); // The host was not allowed to request the resource
} else return err("LOAD_ERROR"); // Error loading the requested resource
}
}
}
}
if (window.addEventListener) window.addEventListener("message", pmxdrRequestHandler, false); // normal browsers
else if (window.attachEvent) window.attachEvent("onmessage", pmxdrRequestHandler); // IE
})();
You probably got that error because the event object is very short lived. (On can get similar problems when for example trying to debug event handlers using Firebug in Firefox.) The browser thinks the event handler is done with its thing so the event object is deleted because the browser misses the event object reference, which has not yet been executed.
About that ProgrammingTalk comment in your code: It might have been the link filter which caught you because you don't have enough posts yet, I think it classifies all links as invalid (external) if they start with http://. What was the error message you got?