{"ast":null,"code":"'use strict';\n\nvar utils = require('../../utils/iframe'),\n    random = require('../../utils/random'),\n    browser = require('../../utils/browser'),\n    urlUtils = require('../../utils/url'),\n    inherits = require('inherits'),\n    EventEmitter = require('events').EventEmitter;\n\nvar debug = function () {};\n\nif (process.env.NODE_ENV !== 'production') {\n  debug = require('debug')('sockjs-client:receiver:jsonp');\n}\n\nfunction JsonpReceiver(url) {\n  debug(url);\n  var self = this;\n  EventEmitter.call(this);\n  utils.polluteGlobalNamespace();\n  this.id = 'a' + random.string(6);\n  var urlWithId = urlUtils.addQuery(url, 'c=' + encodeURIComponent(utils.WPrefix + '.' + this.id));\n  global[utils.WPrefix][this.id] = this._callback.bind(this);\n\n  this._createScript(urlWithId); // Fallback mostly for Konqueror - stupid timer, 35 seconds shall be plenty.\n\n\n  this.timeoutId = setTimeout(function () {\n    debug('timeout');\n\n    self._abort(new Error('JSONP script loaded abnormally (timeout)'));\n  }, JsonpReceiver.timeout);\n}\n\ninherits(JsonpReceiver, EventEmitter);\n\nJsonpReceiver.prototype.abort = function () {\n  debug('abort');\n\n  if (global[utils.WPrefix][this.id]) {\n    var err = new Error('JSONP user aborted read');\n    err.code = 1000;\n\n    this._abort(err);\n  }\n};\n\nJsonpReceiver.timeout = 35000;\nJsonpReceiver.scriptErrorTimeout = 1000;\n\nJsonpReceiver.prototype._callback = function (data) {\n  debug('_callback', data);\n\n  this._cleanup();\n\n  if (this.aborting) {\n    return;\n  }\n\n  if (data) {\n    debug('message', data);\n    this.emit('message', data);\n  }\n\n  this.emit('close', null, 'network');\n  this.removeAllListeners();\n};\n\nJsonpReceiver.prototype._abort = function (err) {\n  debug('_abort', err);\n\n  this._cleanup();\n\n  this.aborting = true;\n  this.emit('close', err.code, err.message);\n  this.removeAllListeners();\n};\n\nJsonpReceiver.prototype._cleanup = function () {\n  debug('_cleanup');\n  clearTimeout(this.timeoutId);\n\n  if (this.script2) {\n    this.script2.parentNode.removeChild(this.script2);\n    this.script2 = null;\n  }\n\n  if (this.script) {\n    var script = this.script; // Unfortunately, you can't really abort script loading of\n    // the script.\n\n    script.parentNode.removeChild(script);\n    script.onreadystatechange = script.onerror = script.onload = script.onclick = null;\n    this.script = null;\n  }\n\n  delete global[utils.WPrefix][this.id];\n};\n\nJsonpReceiver.prototype._scriptError = function () {\n  debug('_scriptError');\n  var self = this;\n\n  if (this.errorTimer) {\n    return;\n  }\n\n  this.errorTimer = setTimeout(function () {\n    if (!self.loadedOkay) {\n      self._abort(new Error('JSONP script loaded abnormally (onerror)'));\n    }\n  }, JsonpReceiver.scriptErrorTimeout);\n};\n\nJsonpReceiver.prototype._createScript = function (url) {\n  debug('_createScript', url);\n  var self = this;\n  var script = this.script = global.document.createElement('script');\n  var script2; // Opera synchronous load trick.\n\n  script.id = 'a' + random.string(8);\n  script.src = url;\n  script.type = 'text/javascript';\n  script.charset = 'UTF-8';\n  script.onerror = this._scriptError.bind(this);\n\n  script.onload = function () {\n    debug('onload');\n\n    self._abort(new Error('JSONP script loaded abnormally (onload)'));\n  }; // IE9 fires 'error' event after onreadystatechange or before, in random order.\n  // Use loadedOkay to determine if actually errored\n\n\n  script.onreadystatechange = function () {\n    debug('onreadystatechange', script.readyState);\n\n    if (/loaded|closed/.test(script.readyState)) {\n      if (script && script.htmlFor && script.onclick) {\n        self.loadedOkay = true;\n\n        try {\n          // In IE, actually execute the script.\n          script.onclick();\n        } catch (x) {// intentionally empty\n        }\n      }\n\n      if (script) {\n        self._abort(new Error('JSONP script loaded abnormally (onreadystatechange)'));\n      }\n    }\n  }; // IE: event/htmlFor/onclick trick.\n  // One can't rely on proper order for onreadystatechange. In order to\n  // make sure, set a 'htmlFor' and 'event' properties, so that\n  // script code will be installed as 'onclick' handler for the\n  // script object. Later, onreadystatechange, manually execute this\n  // code. FF and Chrome doesn't work with 'event' and 'htmlFor'\n  // set. For reference see:\n  //   http://jaubourg.net/2010/07/loading-script-as-onclick-handler-of.html\n  // Also, read on that about script ordering:\n  //   http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order\n\n\n  if (typeof script.async === 'undefined' && global.document.attachEvent) {\n    // According to mozilla docs, in recent browsers script.async defaults\n    // to 'true', so we may use it to detect a good browser:\n    // https://developer.mozilla.org/en/HTML/Element/script\n    if (!browser.isOpera()) {\n      // Naively assume we're in IE\n      try {\n        script.htmlFor = script.id;\n        script.event = 'onclick';\n      } catch (x) {// intentionally empty\n      }\n\n      script.async = true;\n    } else {\n      // Opera, second sync script hack\n      script2 = this.script2 = global.document.createElement('script');\n      script2.text = \"try{var a = document.getElementById('\" + script.id + \"'); if(a)a.onerror();}catch(x){};\";\n      script.async = script2.async = false;\n    }\n  }\n\n  if (typeof script.async !== 'undefined') {\n    script.async = true;\n  }\n\n  var head = global.document.getElementsByTagName('head')[0];\n  head.insertBefore(script, head.firstChild);\n\n  if (script2) {\n    head.insertBefore(script2, head.firstChild);\n  }\n};\n\nmodule.exports = JsonpReceiver;","map":null,"metadata":{},"sourceType":"script"}