684 lines
21 KiB
JavaScript
684 lines
21 KiB
JavaScript
/** @license
|
|
* eventsource.js
|
|
* Available under MIT License (MIT)
|
|
* https://github.com/Yaffle/EventSource/
|
|
*/
|
|
|
|
/*jslint indent: 2, vars: true, plusplus: true */
|
|
/*global setTimeout, clearTimeout */
|
|
|
|
(function (global) {
|
|
"use strict";
|
|
|
|
var setTimeout = global.setTimeout;
|
|
var clearTimeout = global.clearTimeout;
|
|
|
|
var k = function () {
|
|
};
|
|
|
|
function XHRTransport(xhr, onStartCallback, onProgressCallback, onFinishCallback, thisArg) {
|
|
this._internal = new XHRTransportInternal(xhr, onStartCallback, onProgressCallback, onFinishCallback, thisArg);
|
|
}
|
|
|
|
XHRTransport.prototype.open = function (url, withCredentials) {
|
|
this._internal.open(url, withCredentials);
|
|
};
|
|
|
|
XHRTransport.prototype.cancel = function () {
|
|
this._internal.cancel();
|
|
};
|
|
|
|
function XHRTransportInternal(xhr, onStartCallback, onProgressCallback, onFinishCallback, thisArg) {
|
|
this.onStartCallback = onStartCallback;
|
|
this.onProgressCallback = onProgressCallback;
|
|
this.onFinishCallback = onFinishCallback;
|
|
this.thisArg = thisArg;
|
|
this.xhr = xhr;
|
|
this.state = 0;
|
|
this.charOffset = 0;
|
|
this.offset = 0;
|
|
this.url = "";
|
|
this.withCredentials = false;
|
|
this.timeout = 0;
|
|
}
|
|
|
|
XHRTransportInternal.prototype.onStart = function () {
|
|
if (this.state === 1) {
|
|
this.state = 2;
|
|
var status = 0;
|
|
var statusText = "";
|
|
var contentType = undefined;
|
|
if (!("contentType" in this.xhr)) {
|
|
try {
|
|
status = this.xhr.status;
|
|
statusText = this.xhr.statusText;
|
|
contentType = this.xhr.getResponseHeader("Content-Type");
|
|
} catch (error) {
|
|
// https://bugs.webkit.org/show_bug.cgi?id=29121
|
|
status = 0;
|
|
statusText = "";
|
|
contentType = undefined;
|
|
// FF < 14, WebKit
|
|
// https://bugs.webkit.org/show_bug.cgi?id=29658
|
|
// https://bugs.webkit.org/show_bug.cgi?id=77854
|
|
}
|
|
} else {
|
|
status = 200;
|
|
statusText = "OK";
|
|
contentType = this.xhr.contentType;
|
|
}
|
|
if (contentType == undefined) {
|
|
contentType = "";
|
|
}
|
|
this.onStartCallback.call(this.thisArg, status, statusText, contentType);
|
|
}
|
|
};
|
|
XHRTransportInternal.prototype.onProgress = function () {
|
|
this.onStart();
|
|
if (this.state === 2 || this.state === 3) {
|
|
this.state = 3;
|
|
var responseText = "";
|
|
try {
|
|
responseText = this.xhr.responseText;
|
|
} catch (error) {
|
|
// IE 8 - 9 with XMLHttpRequest
|
|
}
|
|
var chunkStart = this.charOffset;
|
|
var length = responseText.length;
|
|
for (var i = this.offset; i < length; i += 1) {
|
|
var c = responseText.charCodeAt(i);
|
|
if (c === "\n".charCodeAt(0) || c === "\r".charCodeAt(0)) {
|
|
this.charOffset = i + 1;
|
|
}
|
|
}
|
|
this.offset = length;
|
|
var chunk = responseText.slice(chunkStart, this.charOffset);
|
|
this.onProgressCallback.call(this.thisArg, chunk);
|
|
}
|
|
};
|
|
XHRTransportInternal.prototype.onFinish = function () {
|
|
// IE 8 fires "onload" without "onprogress
|
|
this.onProgress();
|
|
if (this.state === 3) {
|
|
this.state = 4;
|
|
if (this.timeout !== 0) {
|
|
clearTimeout(this.timeout);
|
|
this.timeout = 0;
|
|
}
|
|
this.onFinishCallback.call(this.thisArg);
|
|
}
|
|
};
|
|
XHRTransportInternal.prototype.onReadyStateChange = function () {
|
|
if (this.xhr != undefined) { // Opera 12
|
|
if (this.xhr.readyState === 4) {
|
|
if (this.xhr.status === 0) {
|
|
this.onFinish();
|
|
} else {
|
|
this.onFinish();
|
|
}
|
|
} else if (this.xhr.readyState === 3) {
|
|
this.onProgress();
|
|
} else if (this.xhr.readyState === 2) {
|
|
// Opera 10.63 throws exception for `this.xhr.status`
|
|
// this.onStart();
|
|
}
|
|
}
|
|
};
|
|
XHRTransportInternal.prototype.onTimeout2 = function () {
|
|
this.timeout = 0;
|
|
var tmp = (/^data\:([^,]*?)(base64)?,([\S]*)$/).exec(this.url);
|
|
var contentType = tmp[1];
|
|
var data = tmp[2] === "base64" ? global.atob(tmp[3]) : decodeURIComponent(tmp[3]);
|
|
if (this.state === 1) {
|
|
this.state = 2;
|
|
this.onStartCallback.call(this.thisArg, 200, "OK", contentType);
|
|
}
|
|
if (this.state === 2 || this.state === 3) {
|
|
this.state = 3;
|
|
this.onProgressCallback.call(this.thisArg, data);
|
|
}
|
|
if (this.state === 3) {
|
|
this.state = 4;
|
|
this.onFinishCallback.call(this.thisArg);
|
|
}
|
|
};
|
|
XHRTransportInternal.prototype.onTimeout1 = function () {
|
|
this.timeout = 0;
|
|
this.open(this.url, this.withCredentials);
|
|
};
|
|
XHRTransportInternal.prototype.onTimeout0 = function () {
|
|
var that = this;
|
|
this.timeout = setTimeout(function () {
|
|
that.onTimeout0();
|
|
}, 500);
|
|
if (this.xhr.readyState === 3) {
|
|
this.onProgress();
|
|
}
|
|
};
|
|
XHRTransportInternal.prototype.handleEvent = function (event) {
|
|
if (event.type === "load") {
|
|
this.onFinish();
|
|
} else if (event.type === "error") {
|
|
this.onFinish();
|
|
} else if (event.type === "abort") {
|
|
// improper fix to match Firefox behaviour, but it is better than just ignore abort
|
|
// see https://bugzilla.mozilla.org/show_bug.cgi?id=768596
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=880200
|
|
// https://code.google.com/p/chromium/issues/detail?id=153570
|
|
// IE 8 fires "onload" without "onprogress
|
|
this.onFinish();
|
|
} else if (event.type === "progress") {
|
|
this.onProgress();
|
|
} else if (event.type === "readystatechange") {
|
|
this.onReadyStateChange();
|
|
}
|
|
};
|
|
XHRTransportInternal.prototype.open = function (url, withCredentials) {
|
|
this.cancel();
|
|
|
|
this.url = url;
|
|
this.withCredentials = withCredentials;
|
|
|
|
this.state = 1;
|
|
this.charOffset = 0;
|
|
this.offset = 0;
|
|
|
|
var that = this;
|
|
|
|
var tmp = (/^data\:([^,]*?)(?:;base64)?,[\S]*$/).exec(url);
|
|
if (tmp != undefined) {
|
|
this.timeout = setTimeout(function () {
|
|
that.onTimeout2();
|
|
}, 0);
|
|
return;
|
|
}
|
|
|
|
// loading indicator in Safari, Chrome < 14
|
|
// loading indicator in Firefox
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=736723
|
|
if ((!("ontimeout" in this.xhr) || ("sendAsBinary" in this.xhr) || ("mozAnon" in this.xhr)) && global.document != undefined && global.document.readyState != undefined && global.document.readyState !== "complete") {
|
|
this.timeout = setTimeout(function () {
|
|
that.onTimeout1();
|
|
}, 4);
|
|
return;
|
|
}
|
|
|
|
// XDomainRequest#abort removes onprogress, onerror, onload
|
|
this.xhr.onload = function (event) {
|
|
that.handleEvent({type: "load"});
|
|
};
|
|
this.xhr.onerror = function () {
|
|
that.handleEvent({type: "error"});
|
|
};
|
|
this.xhr.onabort = function () {
|
|
that.handleEvent({type: "abort"});
|
|
};
|
|
this.xhr.onprogress = function () {
|
|
that.handleEvent({type: "progress"});
|
|
};
|
|
// IE 8-9 (XMLHTTPRequest)
|
|
// Firefox 3.5 - 3.6 - ? < 9.0
|
|
// onprogress is not fired sometimes or delayed
|
|
// see also #64
|
|
this.xhr.onreadystatechange = function () {
|
|
that.handleEvent({type: "readystatechange"});
|
|
};
|
|
|
|
this.xhr.open("GET", url, true);
|
|
|
|
// withCredentials should be set after "open" for Safari and Chrome (< 19 ?)
|
|
this.xhr.withCredentials = withCredentials;
|
|
|
|
this.xhr.responseType = "text";
|
|
|
|
if ("setRequestHeader" in this.xhr) {
|
|
// Request header field Cache-Control is not allowed by Access-Control-Allow-Headers.
|
|
// "Cache-control: no-cache" are not honored in Chrome and Firefox
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=428916
|
|
//this.xhr.setRequestHeader("Cache-Control", "no-cache");
|
|
this.xhr.setRequestHeader("Accept", "text/event-stream");
|
|
// Request header field Last-Event-ID is not allowed by Access-Control-Allow-Headers.
|
|
//this.xhr.setRequestHeader("Last-Event-ID", this.lastEventId);
|
|
}
|
|
|
|
try {
|
|
this.xhr.send(undefined);
|
|
} catch (error1) {
|
|
// Safari 5.1.7, Opera 12
|
|
throw error1;
|
|
}
|
|
|
|
if (("readyState" in this.xhr) && global.opera != undefined) {
|
|
// workaround for Opera issue with "progress" events
|
|
this.timeout = setTimeout(function () {
|
|
that.onTimeout0();
|
|
}, 0);
|
|
}
|
|
};
|
|
XHRTransportInternal.prototype.cancel = function () {
|
|
if (this.state !== 0 && this.state !== 4) {
|
|
this.state = 4;
|
|
this.xhr.onload = k;
|
|
this.xhr.onerror = k;
|
|
this.xhr.onabort = k;
|
|
this.xhr.onprogress = k;
|
|
this.xhr.onreadystatechange = k;
|
|
this.xhr.abort();
|
|
if (this.timeout !== 0) {
|
|
clearTimeout(this.timeout);
|
|
this.timeout = 0;
|
|
}
|
|
this.onFinishCallback.call(this.thisArg);
|
|
}
|
|
this.state = 0;
|
|
};
|
|
|
|
function Map() {
|
|
this._data = {};
|
|
}
|
|
|
|
Map.prototype.get = function (key) {
|
|
return this._data[key + "~"];
|
|
};
|
|
Map.prototype.set = function (key, value) {
|
|
this._data[key + "~"] = value;
|
|
};
|
|
Map.prototype["delete"] = function (key) {
|
|
delete this._data[key + "~"];
|
|
};
|
|
|
|
function EventTarget() {
|
|
this._listeners = new Map();
|
|
}
|
|
|
|
function throwError(e) {
|
|
setTimeout(function () {
|
|
throw e;
|
|
}, 0);
|
|
}
|
|
|
|
EventTarget.prototype.dispatchEvent = function (event) {
|
|
event.target = this;
|
|
var type = event.type.toString();
|
|
var listeners = this._listeners;
|
|
var typeListeners = listeners.get(type);
|
|
if (typeListeners == undefined) {
|
|
return;
|
|
}
|
|
var length = typeListeners.length;
|
|
var listener = undefined;
|
|
for (var i = 0; i < length; i += 1) {
|
|
listener = typeListeners[i];
|
|
try {
|
|
if (typeof listener.handleEvent === "function") {
|
|
listener.handleEvent(event);
|
|
} else {
|
|
listener.call(this, event);
|
|
}
|
|
} catch (e) {
|
|
throwError(e);
|
|
}
|
|
}
|
|
};
|
|
EventTarget.prototype.addEventListener = function (type, callback) {
|
|
type = type.toString();
|
|
var listeners = this._listeners;
|
|
var typeListeners = listeners.get(type);
|
|
if (typeListeners == undefined) {
|
|
typeListeners = [];
|
|
listeners.set(type, typeListeners);
|
|
}
|
|
for (var i = typeListeners.length; i >= 0; i -= 1) {
|
|
if (typeListeners[i] === callback) {
|
|
return;
|
|
}
|
|
}
|
|
typeListeners.push(callback);
|
|
};
|
|
EventTarget.prototype.removeEventListener = function (type, callback) {
|
|
type = type.toString();
|
|
var listeners = this._listeners;
|
|
var typeListeners = listeners.get(type);
|
|
if (typeListeners == undefined) {
|
|
return;
|
|
}
|
|
var length = typeListeners.length;
|
|
var filtered = [];
|
|
for (var i = 0; i < length; i += 1) {
|
|
if (typeListeners[i] !== callback) {
|
|
filtered.push(typeListeners[i]);
|
|
}
|
|
}
|
|
if (filtered.length === 0) {
|
|
listeners["delete"](type);
|
|
} else {
|
|
listeners.set(type, filtered);
|
|
}
|
|
};
|
|
|
|
function Event(type) {
|
|
this.type = type;
|
|
this.target = undefined;
|
|
}
|
|
|
|
function MessageEvent(type, options) {
|
|
Event.call(this, type);
|
|
this.data = options.data;
|
|
this.lastEventId = options.lastEventId;
|
|
}
|
|
|
|
MessageEvent.prototype = Event.prototype;
|
|
|
|
var XHR = global.XMLHttpRequest;
|
|
var XDR = global.XDomainRequest;
|
|
var isCORSSupported = XHR != undefined && (new XHR()).withCredentials != undefined;
|
|
var Transport = isCORSSupported || (XHR != undefined && XDR == undefined) ? XHR : XDR;
|
|
|
|
var WAITING = -1;
|
|
var CONNECTING = 0;
|
|
var OPEN = 1;
|
|
var CLOSED = 2;
|
|
var AFTER_CR = 3;
|
|
var FIELD_START = 4;
|
|
var FIELD = 5;
|
|
var VALUE_START = 6;
|
|
var VALUE = 7;
|
|
var contentTypeRegExp = /^text\/event\-stream;?(\s*charset\=utf\-8)?$/i;
|
|
|
|
var MINIMUM_DURATION = 1000;
|
|
var MAXIMUM_DURATION = 18000000;
|
|
|
|
var getDuration = function (value, def) {
|
|
var n = value;
|
|
if (n !== n) {
|
|
n = def;
|
|
}
|
|
return (n < MINIMUM_DURATION ? MINIMUM_DURATION : (n > MAXIMUM_DURATION ? MAXIMUM_DURATION : n));
|
|
};
|
|
|
|
var fire = function (that, f, event) {
|
|
try {
|
|
if (typeof f === "function") {
|
|
f.call(that, event);
|
|
}
|
|
} catch (e) {
|
|
throwError(e);
|
|
}
|
|
};
|
|
|
|
function EventSource(url, options) {
|
|
EventTarget.call(this);
|
|
|
|
this.onopen = undefined;
|
|
this.onmessage = undefined;
|
|
this.onerror = undefined;
|
|
|
|
this.url = "";
|
|
this.readyState = CONNECTING;
|
|
this.withCredentials = false;
|
|
|
|
this._internal = new EventSourceInternal(this, url, options);
|
|
}
|
|
|
|
function EventSourceInternal(es, url, options) {
|
|
this.url = url.toString();
|
|
this.readyState = CONNECTING;
|
|
this.withCredentials = isCORSSupported && options != undefined && Boolean(options.withCredentials);
|
|
|
|
this.es = es;
|
|
this.initialRetry = getDuration(1000, 0);
|
|
this.heartbeatTimeout = getDuration(45000, 0);
|
|
|
|
this.lastEventId = "";
|
|
this.retry = this.initialRetry;
|
|
this.wasActivity = false;
|
|
var CurrentTransport = options != undefined && options.Transport != undefined ? options.Transport : Transport;
|
|
var xhr = new CurrentTransport();
|
|
this.transport = new XHRTransport(xhr, this.onStart, this.onProgress, this.onFinish, this);
|
|
this.timeout = 0;
|
|
this.currentState = WAITING;
|
|
this.dataBuffer = [];
|
|
this.lastEventIdBuffer = "";
|
|
this.eventTypeBuffer = "";
|
|
|
|
this.state = FIELD_START;
|
|
this.fieldStart = 0;
|
|
this.valueStart = 0;
|
|
|
|
this.es.url = this.url;
|
|
this.es.readyState = this.readyState;
|
|
this.es.withCredentials = this.withCredentials;
|
|
|
|
this.onTimeout();
|
|
}
|
|
|
|
EventSourceInternal.prototype.onStart = function (status, statusText, contentType) {
|
|
if (this.currentState === CONNECTING) {
|
|
if (contentType == undefined) {
|
|
contentType = "";
|
|
}
|
|
if (status === 200 && contentTypeRegExp.test(contentType)) {
|
|
this.currentState = OPEN;
|
|
this.wasActivity = true;
|
|
this.retry = this.initialRetry;
|
|
this.readyState = OPEN;
|
|
this.es.readyState = OPEN;
|
|
var event = new Event("open");
|
|
this.es.dispatchEvent(event);
|
|
fire(this.es, this.es.onopen, event);
|
|
} else if (status !== 0) {
|
|
var message = "";
|
|
if (status !== 200) {
|
|
message = "EventSource's response has a status " + status + " " + statusText.replace(/\s+/g, " ") + " that is not 200. Aborting the connection.";
|
|
} else {
|
|
message = "EventSource's response has a Content-Type specifying an unsupported type: " + contentType.replace(/\s+/g, " ") + ". Aborting the connection.";
|
|
}
|
|
throwError(new Error(message));
|
|
this.close();
|
|
var event = new Event("error");
|
|
this.es.dispatchEvent(event);
|
|
fire(this.es, this.es.onerror, event);
|
|
}
|
|
}
|
|
};
|
|
|
|
EventSourceInternal.prototype.onProgress = function (chunk) {
|
|
if (this.currentState === OPEN) {
|
|
var length = chunk.length;
|
|
if (length !== 0) {
|
|
this.wasActivity = true;
|
|
}
|
|
for (var position = 0; position < length; position += 1) {
|
|
var c = chunk.charCodeAt(position);
|
|
if (this.state === AFTER_CR && c === "\n".charCodeAt(0)) {
|
|
this.state = FIELD_START;
|
|
} else {
|
|
if (this.state === AFTER_CR) {
|
|
this.state = FIELD_START;
|
|
}
|
|
if (c === "\r".charCodeAt(0) || c === "\n".charCodeAt(0)) {
|
|
if (this.state !== FIELD_START) {
|
|
if (this.state === FIELD) {
|
|
this.valueStart = position + 1;
|
|
}
|
|
var field = chunk.slice(this.fieldStart, this.valueStart - 1);
|
|
var value = chunk.slice(this.valueStart + (this.valueStart < position && chunk.charCodeAt(this.valueStart) === " ".charCodeAt(0) ? 1 : 0), position);
|
|
if (field === "data") {
|
|
this.dataBuffer.push(value);
|
|
} else if (field === "id") {
|
|
this.lastEventIdBuffer = value;
|
|
} else if (field === "event") {
|
|
this.eventTypeBuffer = value;
|
|
} else if (field === "retry") {
|
|
this.initialRetry = getDuration(Number(value), this.initialRetry);
|
|
this.retry = this.initialRetry;
|
|
} else if (field === "heartbeatTimeout") {
|
|
this.heartbeatTimeout = getDuration(Number(value), this.heartbeatTimeout);
|
|
if (this.timeout !== 0) {
|
|
clearTimeout(this.timeout);
|
|
var that = this;
|
|
this.timeout = setTimeout(function () {
|
|
that.onTimeout();
|
|
}, this.heartbeatTimeout);
|
|
}
|
|
}
|
|
}
|
|
if (this.state === FIELD_START) {
|
|
if (this.dataBuffer.length !== 0) {
|
|
this.lastEventId = this.lastEventIdBuffer;
|
|
if (this.eventTypeBuffer === "") {
|
|
this.eventTypeBuffer = "message";
|
|
}
|
|
var event = new MessageEvent(this.eventTypeBuffer, {
|
|
data: this.dataBuffer.join("\n"),
|
|
lastEventId: this.lastEventIdBuffer
|
|
});
|
|
this.es.dispatchEvent(event);
|
|
if (this.eventTypeBuffer === "message") {
|
|
fire(this.es, this.es.onmessage, event);
|
|
}
|
|
if (this.currentState === CLOSED) {
|
|
return;
|
|
}
|
|
}
|
|
this.dataBuffer.length = 0;
|
|
this.eventTypeBuffer = "";
|
|
}
|
|
this.state = c === "\r".charCodeAt(0) ? AFTER_CR : FIELD_START;
|
|
} else {
|
|
if (this.state === FIELD_START) {
|
|
this.fieldStart = position;
|
|
this.state = FIELD;
|
|
}
|
|
if (this.state === FIELD) {
|
|
if (c === ":".charCodeAt(0)) {
|
|
this.valueStart = position + 1;
|
|
this.state = VALUE_START;
|
|
}
|
|
} else if (this.state === VALUE_START) {
|
|
this.state = VALUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
EventSourceInternal.prototype.onFinish = function () {
|
|
if (this.currentState === OPEN || this.currentState === CONNECTING) {
|
|
this.currentState = WAITING;
|
|
if (this.timeout !== 0) {
|
|
clearTimeout(this.timeout);
|
|
this.timeout = 0;
|
|
}
|
|
if (this.retry > this.initialRetry * 16) {
|
|
this.retry = this.initialRetry * 16;
|
|
}
|
|
if (this.retry > MAXIMUM_DURATION) {
|
|
this.retry = MAXIMUM_DURATION;
|
|
}
|
|
var that = this;
|
|
this.timeout = setTimeout(function () {
|
|
that.onTimeout();
|
|
}, this.retry);
|
|
this.retry = this.retry * 2 + 1;
|
|
|
|
this.readyState = CONNECTING;
|
|
this.es.readyState = CONNECTING;
|
|
var event = new Event("error");
|
|
this.es.dispatchEvent(event);
|
|
fire(this.es, this.es.onerror, event);
|
|
}
|
|
};
|
|
|
|
EventSourceInternal.prototype.onTimeout = function () {
|
|
this.timeout = 0;
|
|
if (this.currentState !== WAITING) {
|
|
if (!this.wasActivity) {
|
|
throwError(new Error("No activity within " + this.heartbeatTimeout + " milliseconds. Reconnecting."));
|
|
this.transport.cancel();
|
|
} else {
|
|
this.wasActivity = false;
|
|
var that = this;
|
|
this.timeout = setTimeout(function () {
|
|
that.onTimeout();
|
|
}, this.heartbeatTimeout);
|
|
}
|
|
return;
|
|
}
|
|
|
|
this.wasActivity = false;
|
|
var that = this;
|
|
this.timeout = setTimeout(function () {
|
|
that.onTimeout();
|
|
}, this.heartbeatTimeout);
|
|
|
|
this.currentState = CONNECTING;
|
|
this.dataBuffer.length = 0;
|
|
this.eventTypeBuffer = "";
|
|
this.lastEventIdBuffer = this.lastEventId;
|
|
this.fieldStart = 0;
|
|
this.valueStart = 0;
|
|
this.state = FIELD_START;
|
|
|
|
var s = this.url.slice(0, 5);
|
|
if (s !== "data:" && s !== "blob:") {
|
|
s = this.url + ((this.url.indexOf("?", 0) === -1 ? "?" : "&") + "lastEventId=" + encodeURIComponent(this.lastEventId) + "&r=" + (Math.random() + 1).toString().slice(2));
|
|
} else {
|
|
s = this.url;
|
|
}
|
|
try {
|
|
this.transport.open(s, this.withCredentials);
|
|
} catch (error) {
|
|
this.close();
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
EventSourceInternal.prototype.close = function () {
|
|
this.currentState = CLOSED;
|
|
this.transport.cancel();
|
|
if (this.timeout !== 0) {
|
|
clearTimeout(this.timeout);
|
|
this.timeout = 0;
|
|
}
|
|
this.readyState = CLOSED;
|
|
this.es.readyState = CLOSED;
|
|
};
|
|
|
|
function F() {
|
|
this.CONNECTING = CONNECTING;
|
|
this.OPEN = OPEN;
|
|
this.CLOSED = CLOSED;
|
|
}
|
|
F.prototype = EventTarget.prototype;
|
|
|
|
EventSource.prototype = new F();
|
|
|
|
EventSource.prototype.close = function () {
|
|
this._internal.close();
|
|
};
|
|
|
|
F.call(EventSource);
|
|
if (isCORSSupported) {
|
|
EventSource.prototype.withCredentials = undefined;
|
|
}
|
|
|
|
var isEventSourceSupported = function () {
|
|
// Opera 12 fails this test, but this is fine.
|
|
return global.EventSource != undefined && ("withCredentials" in global.EventSource.prototype);
|
|
};
|
|
|
|
if (Transport != undefined && (global.EventSource == undefined || (isCORSSupported && !isEventSourceSupported()))) {
|
|
// Why replace a native EventSource ?
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=444328
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=831392
|
|
// https://code.google.com/p/chromium/issues/detail?id=260144
|
|
// https://code.google.com/p/chromium/issues/detail?id=225654
|
|
// ...
|
|
global.NativeEventSource = global.EventSource;
|
|
global.EventSource = EventSource;
|
|
}
|
|
|
|
}(typeof window !== 'undefined' ? window : this));
|