UNPKG

remotedev

Version:

Remote debugging for any flux implementation.

1,741 lines (1,454 loc) 154 kB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define([], factory); else if(typeof exports === 'object') exports["RemoteDev"] = factory(); else root["RemoteDev"] = factory(); })(this, function() { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ exports: {}, /******/ id: moduleId, /******/ loaded: false /******/ }; /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ // Flag the module as loaded /******/ module.loaded = true; /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ // Load entry module and return exports /******/ return __webpack_require__(0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; module.exports = __webpack_require__(9); /***/ }, /* 1 */ /***/ function(module, exports, __webpack_require__) { var Emitter = __webpack_require__(11); if (!Object.create) { Object.create = __webpack_require__(23); } var SCEmitter = function () { Emitter.call(this); }; SCEmitter.prototype = Object.create(Emitter.prototype); SCEmitter.prototype.emit = function (event) { if (event == 'error' && this.domain) { // Emit the error on the domain if it has one. // See https://github.com/joyent/node/blob/ef4344311e19a4f73c031508252b21712b22fe8a/lib/events.js#L78-85 var err = arguments[1]; if (!err) { err = new Error('Uncaught, unspecified "error" event.'); } err.domainEmitter = this; err.domain = this.domain; err.domainThrown = false; this.domain.emit('error', err); } Emitter.prototype.emit.apply(this, arguments); }; module.exports.SCEmitter = SCEmitter; /***/ }, /* 2 */ /***/ function(module, exports, __webpack_require__) { var cycle = __webpack_require__(12); var isStrict = (function () { return !this; })(); function AuthTokenExpiredError(message, expiry) { if (Error.captureStackTrace && !isStrict) { Error.captureStackTrace(this, arguments.callee); } else { this.stack = (new Error()).stack; } this.name = 'AuthTokenExpiredError'; this.message = message; this.expiry = expiry; }; AuthTokenExpiredError.prototype = Object.create(Error.prototype); function AuthTokenInvalidError(message) { if (Error.captureStackTrace && !isStrict) { Error.captureStackTrace(this, arguments.callee); } else { this.stack = (new Error()).stack; } this.name = 'AuthTokenInvalidError'; this.message = message; }; AuthTokenInvalidError.prototype = Object.create(Error.prototype); function SilentMiddlewareBlockedError(message, type) { if (Error.captureStackTrace && !isStrict) { Error.captureStackTrace(this, arguments.callee); } else { this.stack = (new Error()).stack; } this.name = 'SilentMiddlewareBlockedError'; this.message = message; this.type = type; }; SilentMiddlewareBlockedError.prototype = Object.create(Error.prototype); function InvalidActionError(message) { if (Error.captureStackTrace && !isStrict) { Error.captureStackTrace(this, arguments.callee); } else { this.stack = (new Error()).stack; } this.name = 'InvalidActionError'; this.message = message; }; InvalidActionError.prototype = Object.create(Error.prototype); function InvalidArgumentsError(message) { if (Error.captureStackTrace && !isStrict) { Error.captureStackTrace(this, arguments.callee); } else { this.stack = (new Error()).stack; } this.name = 'InvalidArgumentsError'; this.message = message; }; InvalidArgumentsError.prototype = Object.create(Error.prototype); function InvalidOptionsError(message) { if (Error.captureStackTrace && !isStrict) { Error.captureStackTrace(this, arguments.callee); } else { this.stack = (new Error()).stack; } this.name = 'InvalidOptionsError'; this.message = message; }; InvalidOptionsError.prototype = Object.create(Error.prototype); function InvalidMessageError(message) { if (Error.captureStackTrace && !isStrict) { Error.captureStackTrace(this, arguments.callee); } else { this.stack = (new Error()).stack; } this.name = 'InvalidMessageError'; this.message = message; }; InvalidMessageError.prototype = Object.create(Error.prototype); function SocketProtocolError(message, code) { if (Error.captureStackTrace && !isStrict) { Error.captureStackTrace(this, arguments.callee); } else { this.stack = (new Error()).stack; } this.name = 'SocketProtocolError'; this.message = message; this.code = code; }; SocketProtocolError.prototype = Object.create(Error.prototype); function ServerProtocolError(message) { if (Error.captureStackTrace && !isStrict) { Error.captureStackTrace(this, arguments.callee); } else { this.stack = (new Error()).stack; } this.name = 'ServerProtocolError'; this.message = message; }; ServerProtocolError.prototype = Object.create(Error.prototype); function HTTPServerError(message) { if (Error.captureStackTrace && !isStrict) { Error.captureStackTrace(this, arguments.callee); } else { this.stack = (new Error()).stack; } this.name = 'HTTPServerError'; this.message = message; }; HTTPServerError.prototype = Object.create(Error.prototype); function ResourceLimitError(message) { if (Error.captureStackTrace && !isStrict) { Error.captureStackTrace(this, arguments.callee); } else { this.stack = (new Error()).stack; } this.name = 'ResourceLimitError'; this.message = message; }; ResourceLimitError.prototype = Object.create(Error.prototype); function TimeoutError(message) { if (Error.captureStackTrace && !isStrict) { Error.captureStackTrace(this, arguments.callee); } else { this.stack = (new Error()).stack; } this.name = 'TimeoutError'; this.message = message; }; TimeoutError.prototype = Object.create(Error.prototype); function BrokerError(message) { if (Error.captureStackTrace && !isStrict) { Error.captureStackTrace(this, arguments.callee); } else { this.stack = (new Error()).stack; } this.name = 'BrokerError'; this.message = message; }; BrokerError.prototype = Object.create(Error.prototype); function ProcessExitError(message, code) { if (Error.captureStackTrace && !isStrict) { Error.captureStackTrace(this, arguments.callee); } else { this.stack = (new Error()).stack; } this.name = 'ProcessExitError'; this.message = message; this.code = code; }; ProcessExitError.prototype = Object.create(Error.prototype); function UnknownError(message) { if (Error.captureStackTrace && !isStrict) { Error.captureStackTrace(this, arguments.callee); } else { this.stack = (new Error()).stack; } this.name = 'UnknownError'; this.message = message; }; UnknownError.prototype = Object.create(Error.prototype); // Expose all error types module.exports = { AuthTokenExpiredError: AuthTokenExpiredError, AuthTokenInvalidError: AuthTokenInvalidError, SilentMiddlewareBlockedError: SilentMiddlewareBlockedError, InvalidActionError: InvalidActionError, InvalidArgumentsError: InvalidArgumentsError, InvalidOptionsError: InvalidOptionsError, InvalidMessageError: InvalidMessageError, SocketProtocolError: SocketProtocolError, ServerProtocolError: ServerProtocolError, HTTPServerError: HTTPServerError, ResourceLimitError: ResourceLimitError, TimeoutError: TimeoutError, BrokerError: BrokerError, ProcessExitError: ProcessExitError, UnknownError: UnknownError }; module.exports.socketProtocolErrorStatuses = { 1001: 'Socket was disconnected', 1002: 'A WebSocket protocol error was encountered', 1003: 'Server terminated socket because it received invalid data', 1005: 'Socket closed without status code', 1006: 'Socket hung up', 1007: 'Message format was incorrect', 1008: 'Encountered a policy violation', 1009: 'Message was too big to process', 1010: 'Client ended the connection because the server did not comply with extension requirements', 1011: 'Server encountered an unexpected fatal condition', 4000: 'Server ping timed out', 4001: 'Client pong timed out', 4002: 'Server failed to sign auth token', 4003: 'Failed to complete handshake', 4004: 'Client failed to save auth token', 4005: 'Did not receive #handshake from client before timeout', 4006: 'Failed to bind socket to message broker', 4007: 'Client connection establishment timed out' }; module.exports.socketProtocolIgnoreStatuses = { 1000: 'Socket closed normally', 1001: 'Socket hung up' }; // Properties related to error domains cannot be serialized. var unserializableErrorProperties = { domain: 1, domainEmitter: 1, domainThrown: 1 }; module.exports.dehydrateError = function (error, includeStackTrace) { var dehydratedError; if (typeof error == 'string') { dehydratedError = error; } else { dehydratedError = { message: error.message }; if (includeStackTrace) { dehydratedError.stack = error.stack; } for (var i in error) { if (!unserializableErrorProperties[i]) { dehydratedError[i] = error[i]; } } } return cycle.decycle(dehydratedError); }; module.exports.hydrateError = function (error) { var hydratedError = null; if (error != null) { if (typeof error == 'string') { hydratedError = error; } else { hydratedError = new Error(error.message); for (var i in error) { if (error.hasOwnProperty(i)) { hydratedError[i] = error[i]; } } } } return hydratedError; }; /***/ }, /* 3 */ /***/ function(module, exports) { module.exports = pathGetter; function pathGetter(obj, path) { if (path !== '$') { var paths = getPaths(path); for (var i = 0; i < paths.length; i++) { path = paths[i].toString().replace(/\\"/g, '"'); obj = obj[path]; } } return obj; } function getPaths(pathString) { var regex = /(?:\.(\w+))|(?:\[(\d+)\])|(?:\["((?:[^\\"]|\\.)*)"\])/g; var matches = []; var match; while (match = regex.exec(pathString)) { matches.push( match[1] || match[2] || match[3] ); } return matches; } /***/ }, /* 4 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; exports.decode = exports.parse = __webpack_require__(19); exports.encode = exports.stringify = __webpack_require__(20); /***/ }, /* 5 */ /***/ function(module, exports, __webpack_require__) { var scErrors = __webpack_require__(2); var InvalidActionError = scErrors.InvalidActionError; var Response = function (socket, id) { this.socket = socket; this.id = id; this.sent = false; }; Response.prototype._respond = function (responseData) { if (this.sent) { throw new InvalidActionError('Response ' + this.id + ' has already been sent'); } else { this.sent = true; this.socket.send(this.socket.stringify(responseData)); } }; Response.prototype.end = function (data) { if (this.id) { var responseData = { rid: this.id }; if (data !== undefined) { responseData.data = data; } this._respond(responseData); } }; Response.prototype.error = function (error, data) { if (this.id) { var err = scErrors.dehydrateError(error); var responseData = { rid: this.id, error: err }; if (data !== undefined) { responseData.data = data; } this._respond(responseData); } }; Response.prototype.callback = function (error, data) { if (error) { this.error(error, data); } else { this.end(data); } }; module.exports.Response = Response; /***/ }, /* 6 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(global, Buffer) {var SCEmitter = __webpack_require__(1).SCEmitter; var SCChannel = __webpack_require__(22).SCChannel; var Response = __webpack_require__(5).Response; var AuthEngine = __webpack_require__(26).AuthEngine; var SCTransport = __webpack_require__(28).SCTransport; var querystring = __webpack_require__(4); var LinkedList = __webpack_require__(18); var base64 = __webpack_require__(10); var scErrors = __webpack_require__(2); var InvalidArgumentsError = scErrors.InvalidArgumentsError; var InvalidMessageError = scErrors.InvalidMessageError; var SocketProtocolError = scErrors.SocketProtocolError; var TimeoutError = scErrors.TimeoutError; var isBrowser = typeof window != 'undefined'; var SCSocket = function (opts) { var self = this; SCEmitter.call(this); this.id = null; this.state = this.CLOSED; this.authState = this.PENDING; this.signedAuthToken = null; this.authToken = null; this.pendingReconnect = false; this.pendingReconnectTimeout = null; this.pendingConnectCallback = false; this.connectTimeout = opts.connectTimeout; this.ackTimeout = opts.ackTimeout; this.channelPrefix = opts.channelPrefix || null; // pingTimeout will be ackTimeout at the start, but it will // be updated with values provided by the 'connect' event this.pingTimeout = this.ackTimeout; var maxTimeout = Math.pow(2, 31) - 1; var verifyDuration = function (propertyName) { if (self[propertyName] > maxTimeout) { throw new InvalidArgumentsError('The ' + propertyName + ' value provided exceeded the maximum amount allowed'); } }; verifyDuration('connectTimeout'); verifyDuration('ackTimeout'); verifyDuration('pingTimeout'); this._localEvents = { 'connect': 1, 'connectAbort': 1, 'disconnect': 1, 'message': 1, 'error': 1, 'raw': 1, 'fail': 1, 'kickOut': 1, 'subscribe': 1, 'unsubscribe': 1, 'subscribeStateChange': 1, 'authStateChange': 1, 'authenticate': 1, 'deauthenticate': 1, 'removeAuthToken': 1, 'subscribeRequest': 1 }; this.connectAttempts = 0; this._emitBuffer = new LinkedList(); this._channels = {}; this.options = opts; this._cid = 1; this.options.callIdGenerator = function () { return self._callIdGenerator(); }; if (this.options.autoReconnect) { if (this.options.autoReconnectOptions == null) { this.options.autoReconnectOptions = {}; } // Add properties to the this.options.autoReconnectOptions object. // We assign the reference to a reconnectOptions variable to avoid repetition. var reconnectOptions = this.options.autoReconnectOptions; if (reconnectOptions.initialDelay == null) { reconnectOptions.initialDelay = 10000; } if (reconnectOptions.randomness == null) { reconnectOptions.randomness = 10000; } if (reconnectOptions.multiplier == null) { reconnectOptions.multiplier = 1.5; } if (reconnectOptions.maxDelay == null) { reconnectOptions.maxDelay = 60000; } } if (this.options.subscriptionRetryOptions == null) { this.options.subscriptionRetryOptions = {}; } if (this.options.authEngine) { this.auth = this.options.authEngine; } else { this.auth = new AuthEngine(); } this.options.path = this.options.path.replace(/\/$/, '') + '/'; this.options.query = opts.query || {}; if (typeof this.options.query == 'string') { this.options.query = querystring.parse(this.options.query); } this.connect(); this._channelEmitter = new SCEmitter(); if (isBrowser) { var unloadHandler = function () { self.disconnect(); }; if (global.attachEvent) { global.attachEvent('onunload', unloadHandler); } else if (global.addEventListener) { global.addEventListener('beforeunload', unloadHandler, false); } } }; SCSocket.prototype = Object.create(SCEmitter.prototype); SCSocket.CONNECTING = SCSocket.prototype.CONNECTING = SCTransport.prototype.CONNECTING; SCSocket.OPEN = SCSocket.prototype.OPEN = SCTransport.prototype.OPEN; SCSocket.CLOSED = SCSocket.prototype.CLOSED = SCTransport.prototype.CLOSED; SCSocket.AUTHENTICATED = SCSocket.prototype.AUTHENTICATED = 'authenticated'; SCSocket.UNAUTHENTICATED = SCSocket.prototype.UNAUTHENTICATED = 'unauthenticated'; SCSocket.PENDING = SCSocket.prototype.PENDING = 'pending'; SCSocket.ignoreStatuses = scErrors.socketProtocolIgnoreStatuses; SCSocket.errorStatuses = scErrors.socketProtocolErrorStatuses; SCSocket.prototype._privateEventHandlerMap = { '#publish': function (data) { var undecoratedChannelName = this._undecorateChannelName(data.channel); var isSubscribed = this.isSubscribed(undecoratedChannelName, true); if (isSubscribed) { this._channelEmitter.emit(undecoratedChannelName, data.data); } }, '#kickOut': function (data) { var undecoratedChannelName = this._undecorateChannelName(data.channel); var channel = this._channels[undecoratedChannelName]; if (channel) { SCEmitter.prototype.emit.call(this, 'kickOut', data.message, undecoratedChannelName); channel.emit('kickOut', data.message, undecoratedChannelName); this._triggerChannelUnsubscribe(channel); } }, '#setAuthToken': function (data, response) { var self = this; if (data) { var triggerAuthenticate = function (err) { if (err) { // This is a non-fatal error, we don't want to close the connection // because of this but we do want to notify the server and throw an error // on the client. response.error(err); self._onSCError(err); } else { self._changeToAuthenticatedState(data.token); response.end(); } }; this.auth.saveToken(this.options.authTokenName, data.token, {}, triggerAuthenticate); } else { response.error(new InvalidMessageError('No token data provided by #setAuthToken event')); } }, '#removeAuthToken': function (data, response) { var self = this; this.auth.removeToken(this.options.authTokenName, function (err, oldToken) { if (err) { // Non-fatal error - Do not close the connection response.error(err); self._onSCError(err); } else { SCEmitter.prototype.emit.call(self, 'removeAuthToken', oldToken); self._changeToUnauthenticatedState(); response.end(); } }); }, '#disconnect': function (data) { this.transport.close(data.code, data.data); } }; SCSocket.prototype._callIdGenerator = function () { return this._cid++; }; SCSocket.prototype.getState = function () { return this.state; }; SCSocket.prototype.getBytesReceived = function () { return this.transport.getBytesReceived(); }; SCSocket.prototype.deauthenticate = function (callback) { var self = this; this.auth.removeToken(this.options.authTokenName, function (err, oldToken) { self.emit('#removeAuthToken'); callback && callback(err); if (err) { // Non-fatal error - Do not close the connection self._onSCError(err); } else { SCEmitter.prototype.emit.call(self, 'removeAuthToken', oldToken); self._changeToUnauthenticatedState(); } }); }; SCSocket.prototype.connect = SCSocket.prototype.open = function () { var self = this; if (this.state == this.CLOSED) { this.pendingReconnect = false; this.pendingReconnectTimeout = null; clearTimeout(this._reconnectTimeoutRef); this.state = this.CONNECTING; this._changeToPendingAuthState(); if (this.transport) { this.transport.off(); } this.transport = new SCTransport(this.auth, this.options); this.transport.on('open', function (status) { self.state = self.OPEN; self._onSCOpen(status); }); this.transport.on('error', function (err) { self._onSCError(err); }); this.transport.on('close', function (code, data) { self.state = self.CLOSED; self._onSCClose(code, data); }); this.transport.on('openAbort', function (code, data) { self.state = self.CLOSED; self._onSCClose(code, data, true); }); this.transport.on('event', function (event, data, res) { self._onSCEvent(event, data, res); }); } }; SCSocket.prototype.reconnect = function () { this.disconnect(); this.connect(); }; SCSocket.prototype.disconnect = function (code, data) { code = code || 1000; if (this.state == this.OPEN) { var packet = { code: code, data: data }; this.transport.emit('#disconnect', packet); this.transport.close(code, data); } else if (this.state == this.CONNECTING) { this.transport.close(code, data); } else { this.pendingReconnect = false; this.pendingReconnectTimeout = null; clearTimeout(this._reconnectTimeoutRef); } }; SCSocket.prototype._changeToPendingAuthState = function () { if (this.authState != this.PENDING) { var oldState = this.authState; this.authState = this.PENDING; var stateChangeData = { oldState: oldState, newState: this.authState }; SCEmitter.prototype.emit.call(this, 'authStateChange', stateChangeData); } }; SCSocket.prototype._changeToUnauthenticatedState = function () { if (this.authState != this.UNAUTHENTICATED) { var oldState = this.authState; this.authState = this.UNAUTHENTICATED; this.signedAuthToken = null; this.authToken = null; var stateChangeData = { oldState: oldState, newState: this.authState }; SCEmitter.prototype.emit.call(this, 'authStateChange', stateChangeData); if (oldState == this.AUTHENTICATED) { SCEmitter.prototype.emit.call(this, 'deauthenticate'); } SCEmitter.prototype.emit.call(this, 'authTokenChange', this.signedAuthToken); } }; SCSocket.prototype._changeToAuthenticatedState = function (signedAuthToken) { this.signedAuthToken = signedAuthToken; this.authToken = this._extractAuthTokenData(signedAuthToken); if (this.authState != this.AUTHENTICATED) { var oldState = this.authState; this.authState = this.AUTHENTICATED; var stateChangeData = { oldState: oldState, newState: this.authState, signedAuthToken: signedAuthToken, authToken: this.authToken }; this.processPendingSubscriptions(); SCEmitter.prototype.emit.call(this, 'authStateChange', stateChangeData); SCEmitter.prototype.emit.call(this, 'authenticate', signedAuthToken); } SCEmitter.prototype.emit.call(this, 'authTokenChange', signedAuthToken); }; SCSocket.prototype.decodeBase64 = function (encodedString) { var decodedString; if (typeof Buffer == 'undefined') { if (global.atob) { decodedString = global.atob(encodedString); } else { decodedString = base64.decode(encodedString); } } else { var buffer = new Buffer(encodedString, 'base64'); decodedString = buffer.toString('utf8'); } return decodedString; }; SCSocket.prototype.encodeBase64 = function (decodedString) { var encodedString; if (typeof Buffer == 'undefined') { if (global.btoa) { encodedString = global.btoa(decodedString); } else { encodedString = base64.encode(decodedString); } } else { var buffer = new Buffer(decodedString, 'utf8'); encodedString = buffer.toString('base64'); } return encodedString; }; SCSocket.prototype._extractAuthTokenData = function (signedAuthToken) { var tokenParts = (signedAuthToken || '').split('.'); var encodedTokenData = tokenParts[1]; if (encodedTokenData != null) { var tokenData = encodedTokenData; try { tokenData = this.decodeBase64(tokenData); return JSON.parse(tokenData); } catch (e) { return tokenData; } } return null; }; SCSocket.prototype.getAuthToken = function () { return this.authToken; }; SCSocket.prototype.getSignedAuthToken = function () { return this.signedAuthToken; }; // Perform client-initiated authentication by providing an encrypted token string SCSocket.prototype.authenticate = function (signedAuthToken, callback) { var self = this; this._changeToPendingAuthState(); this.emit('#authenticate', signedAuthToken, function (err, authStatus) { if (authStatus && authStatus.authError) { authStatus.authError = scErrors.hydrateError(authStatus.authError); } if (err) { self._changeToUnauthenticatedState(); callback && callback(err, authStatus); } else { self.auth.saveToken(self.options.authTokenName, signedAuthToken, {}, function (err) { callback && callback(err, authStatus); if (err) { self._changeToUnauthenticatedState(); self._onSCError(err); } else { if (authStatus.isAuthenticated) { self._changeToAuthenticatedState(signedAuthToken); } else { self._changeToUnauthenticatedState(); } } }); } }); }; SCSocket.prototype._tryReconnect = function (initialDelay) { var self = this; var exponent = this.connectAttempts++; var reconnectOptions = this.options.autoReconnectOptions; var timeout; if (initialDelay == null || exponent > 0) { var initialTimeout = Math.round(reconnectOptions.initialDelay + (reconnectOptions.randomness || 0) * Math.random()); timeout = Math.round(initialTimeout * Math.pow(reconnectOptions.multiplier, exponent)); } else { timeout = initialDelay; } if (timeout > reconnectOptions.maxDelay) { timeout = reconnectOptions.maxDelay; } clearTimeout(this._reconnectTimeoutRef); this.pendingReconnect = true; this.pendingReconnectTimeout = timeout; this._reconnectTimeoutRef = setTimeout(function () { self.connect(); }, timeout); }; SCSocket.prototype._onSCOpen = function (status) { var self = this; if (status) { this.id = status.id; this.pingTimeout = status.pingTimeout; this.transport.pingTimeout = this.pingTimeout; if (status.isAuthenticated) { this._changeToAuthenticatedState(status.authToken); } else { this._changeToUnauthenticatedState(); } } else { this._changeToUnauthenticatedState(); } this.connectAttempts = 0; if (this.options.autoProcessSubscriptions) { this.processPendingSubscriptions(); } else { this.pendingConnectCallback = true; } // If the user invokes the callback while in autoProcessSubscriptions mode, it // won't break anything - The processPendingSubscriptions() call will be a no-op. SCEmitter.prototype.emit.call(this, 'connect', status, function () { self.processPendingSubscriptions(); }); this._flushEmitBuffer(); }; SCSocket.prototype._onSCError = function (err) { var self = this; // Throw error in different stack frame so that error handling // cannot interfere with a reconnect action. setTimeout(function () { if (self.listeners('error').length < 1) { throw err; } else { SCEmitter.prototype.emit.call(self, 'error', err); } }, 0); }; SCSocket.prototype._suspendSubscriptions = function () { var channel, newState; for (var channelName in this._channels) { if (this._channels.hasOwnProperty(channelName)) { channel = this._channels[channelName]; if (channel.state == channel.SUBSCRIBED || channel.state == channel.PENDING) { newState = channel.PENDING; } else { newState = channel.UNSUBSCRIBED; } this._triggerChannelUnsubscribe(channel, newState); } } }; SCSocket.prototype._onSCClose = function (code, data, openAbort) { var self = this; this.id = null; if (this.transport) { this.transport.off(); } this.pendingReconnect = false; this.pendingReconnectTimeout = null; clearTimeout(this._reconnectTimeoutRef); this._changeToPendingAuthState(); this._suspendSubscriptions(); // Try to reconnect // on server ping timeout (4000) // or on client pong timeout (4001) // or on close without status (1005) // or on handshake failure (4003) // or on socket hung up (1006) if (this.options.autoReconnect) { if (code == 4000 || code == 4001 || code == 1005) { // If there is a ping or pong timeout or socket closes without // status, don't wait before trying to reconnect - These could happen // if the client wakes up after a period of inactivity and in this case we // want to re-establish the connection as soon as possible. this._tryReconnect(0); // Codes 4500 and above will be treated as permanent disconnects. // Socket will not try to auto-reconnect. } else if (code != 1000 && code < 4500) { this._tryReconnect(); } } if (openAbort) { SCEmitter.prototype.emit.call(self, 'connectAbort', code, data); } else { SCEmitter.prototype.emit.call(self, 'disconnect', code, data); } if (!SCSocket.ignoreStatuses[code]) { var failureMessage; if (data) { failureMessage = 'Socket connection failed: ' + data; } else { failureMessage = 'Socket connection failed for unknown reasons'; } var err = new SocketProtocolError(SCSocket.errorStatuses[code] || failureMessage, code); this._onSCError(err); } }; SCSocket.prototype._onSCEvent = function (event, data, res) { var handler = this._privateEventHandlerMap[event]; if (handler) { handler.call(this, data, res); } else { SCEmitter.prototype.emit.call(this, event, data, function () { res && res.callback.apply(res, arguments); }); } }; SCSocket.prototype.parse = function (message) { return this.transport.parse(message); }; SCSocket.prototype.stringify = function (object) { return this.transport.stringify(object); }; SCSocket.prototype._flushEmitBuffer = function () { var currentNode = this._emitBuffer.head; var nextNode; while (currentNode) { nextNode = currentNode.next; var eventObject = currentNode.data; currentNode.detach(); this.transport.emitRaw(eventObject); currentNode = nextNode; } }; SCSocket.prototype._handleEventAckTimeout = function (eventObject, eventNode) { if (eventNode) { eventNode.detach(); } var error = new TimeoutError("Event response for '" + eventObject.event + "' timed out"); var callback = eventObject.callback; if (callback) { delete eventObject.callback; callback.call(eventObject, error, eventObject); } }; SCSocket.prototype._emit = function (event, data, callback) { var self = this; if (this.state == this.CLOSED) { this.connect(); } var eventObject = { event: event, data: data, callback: callback }; var eventNode = new LinkedList.Item(); eventNode.data = eventObject; eventObject.timeout = setTimeout(function () { self._handleEventAckTimeout(eventObject, eventNode); }, this.ackTimeout); this._emitBuffer.append(eventNode); if (this.state == this.OPEN) { this._flushEmitBuffer(); } }; SCSocket.prototype.send = function (data) { this.transport.send(data); }; SCSocket.prototype.emit = function (event, data, callback) { if (this._localEvents[event] == null) { this._emit(event, data, callback); } else { SCEmitter.prototype.emit.call(this, event, data); } }; SCSocket.prototype.publish = function (channelName, data, callback) { var pubData = { channel: this._decorateChannelName(channelName), data: data }; this.emit('#publish', pubData, callback); }; SCSocket.prototype._triggerChannelSubscribe = function (channel, subscriptionOptions) { var channelName = channel.name; if (channel.state != channel.SUBSCRIBED) { var oldState = channel.state; channel.state = channel.SUBSCRIBED; var stateChangeData = { channel: channelName, oldState: oldState, newState: channel.state, subscriptionOptions: subscriptionOptions }; channel.emit('subscribeStateChange', stateChangeData); channel.emit('subscribe', channelName, subscriptionOptions); SCEmitter.prototype.emit.call(this, 'subscribeStateChange', stateChangeData); SCEmitter.prototype.emit.call(this, 'subscribe', channelName, subscriptionOptions); } }; SCSocket.prototype._triggerChannelSubscribeFail = function (err, channel, subscriptionOptions) { var channelName = channel.name; var meetsAuthRequirements = !channel.waitForAuth || this.authState == this.AUTHENTICATED; if (channel.state != channel.UNSUBSCRIBED && meetsAuthRequirements) { channel.state = channel.UNSUBSCRIBED; channel.emit('subscribeFail', err, channelName, subscriptionOptions); SCEmitter.prototype.emit.call(this, 'subscribeFail', err, channelName, subscriptionOptions); } }; // Cancel any pending subscribe callback SCSocket.prototype._cancelPendingSubscribeCallback = function (channel) { if (channel._pendingSubscriptionCid != null) { this.transport.cancelPendingResponse(channel._pendingSubscriptionCid); delete channel._pendingSubscriptionCid; } }; SCSocket.prototype._decorateChannelName = function (channelName) { if (this.channelPrefix) { channelName = this.channelPrefix + channelName; } return channelName; }; SCSocket.prototype._undecorateChannelName = function (decoratedChannelName) { if (this.channelPrefix && decoratedChannelName.indexOf(this.channelPrefix) == 0) { return decoratedChannelName.replace(this.channelPrefix, ''); } return decoratedChannelName; }; SCSocket.prototype._trySubscribe = function (channel) { var self = this; var meetsAuthRequirements = !channel.waitForAuth || this.authState == this.AUTHENTICATED; // We can only ever have one pending subscribe action at any given time on a channel if (this.state == this.OPEN && !this.pendingConnectCallback && channel._pendingSubscriptionCid == null && meetsAuthRequirements) { var options = { noTimeout: true }; var subscriptionOptions = { channel: this._decorateChannelName(channel.name) }; if (channel.waitForAuth) { options.waitForAuth = true; subscriptionOptions.waitForAuth = options.waitForAuth; } if (channel.data) { subscriptionOptions.data = channel.data; } channel._pendingSubscriptionCid = this.transport.emit( '#subscribe', subscriptionOptions, options, function (err) { delete channel._pendingSubscriptionCid; if (err) { self._triggerChannelSubscribeFail(err, channel, subscriptionOptions); } else { self._triggerChannelSubscribe(channel, subscriptionOptions); } } ); SCEmitter.prototype.emit.call(this, 'subscribeRequest', channel.name, subscriptionOptions); } }; SCSocket.prototype.subscribe = function (channelName, options) { var channel = this._channels[channelName]; if (!channel) { channel = new SCChannel(channelName, this, options); this._channels[channelName] = channel; } else if (options) { channel.setOptions(options); } if (channel.state == channel.UNSUBSCRIBED) { channel.state = channel.PENDING; this._trySubscribe(channel); } return channel; }; SCSocket.prototype._triggerChannelUnsubscribe = function (channel, newState) { var channelName = channel.name; var oldState = channel.state; if (newState) { channel.state = newState; } else { channel.state = channel.UNSUBSCRIBED; } this._cancelPendingSubscribeCallback(channel); if (oldState == channel.SUBSCRIBED) { var stateChangeData = { channel: channelName, oldState: oldState, newState: channel.state }; channel.emit('subscribeStateChange', stateChangeData); channel.emit('unsubscribe', channelName); SCEmitter.prototype.emit.call(this, 'subscribeStateChange', stateChangeData); SCEmitter.prototype.emit.call(this, 'unsubscribe', channelName); } }; SCSocket.prototype._tryUnsubscribe = function (channel) { var self = this; if (this.state == this.OPEN) { var options = { noTimeout: true }; // If there is a pending subscribe action, cancel the callback this._cancelPendingSubscribeCallback(channel); // This operation cannot fail because the TCP protocol guarantees delivery // so long as the connection remains open. If the connection closes, // the server will automatically unsubscribe the socket and thus complete // the operation on the server side. var decoratedChannelName = this._decorateChannelName(channel.name); this.transport.emit('#unsubscribe', decoratedChannelName, options); } }; SCSocket.prototype.unsubscribe = function (channelName) { var channel = this._channels[channelName]; if (channel) { if (channel.state != channel.UNSUBSCRIBED) { this._triggerChannelUnsubscribe(channel); this._tryUnsubscribe(channel); } } }; SCSocket.prototype.channel = function (channelName, options) { var currentChannel = this._channels[channelName]; if (!currentChannel) { currentChannel = new SCChannel(channelName, this, options); this._channels[channelName] = currentChannel; } return currentChannel; }; SCSocket.prototype.destroyChannel = function (channelName) { var channel = this._channels[channelName]; channel.unwatch(); channel.unsubscribe(); delete this._channels[channelName]; }; SCSocket.prototype.subscriptions = function (includePending) { var subs = []; var channel, includeChannel; for (var channelName in this._channels) { if (this._channels.hasOwnProperty(channelName)) { channel = this._channels[channelName]; if (includePending) { includeChannel = channel && (channel.state == channel.SUBSCRIBED || channel.state == channel.PENDING); } else { includeChannel = channel && channel.state == channel.SUBSCRIBED; } if (includeChannel) { subs.push(channelName); } } } return subs; }; SCSocket.prototype.isSubscribed = function (channelName, includePending) { var channel = this._channels[channelName]; if (includePending) { return !!channel && (channel.state == channel.SUBSCRIBED || channel.state == channel.PENDING); } return !!channel && channel.state == channel.SUBSCRIBED; }; SCSocket.prototype.processPendingSubscriptions = function () { var self = this; this.pendingConnectCallback = false; for (var i in this._channels) { if (this._channels.hasOwnProperty(i)) { (function (channel) { if (channel.state == channel.PENDING) { self._trySubscribe(channel); } })(this._channels[i]); } } }; SCSocket.prototype.watch = function (channelName, handler) { if (typeof handler != 'function') { throw new InvalidArgumentsError('No handler function was provided'); } this._channelEmitter.on(channelName, handler); }; SCSocket.prototype.unwatch = function (channelName, handler) { if (handler) { this._channelEmitter.removeListener(channelName, handler); } else { this._channelEmitter.removeAllListeners(channelName); } }; SCSocket.prototype.watchers = function (channelName) { return this._channelEmitter.listeners(channelName); }; module.exports = SCSocket; /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __webpack_require__(7).Buffer)) /***/ }, /* 7 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(Buffer, global) {/*! * The buffer module from node.js, for the browser. * * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org> * @license MIT */ /* eslint-disable no-proto */ 'use strict' var base64 = __webpack_require__(31) var ieee754 = __webpack_require__(32) var isArray = __webpack_require__(33) exports.Buffer = Buffer exports.SlowBuffer = SlowBuffer exports.INSPECT_MAX_BYTES = 50 Buffer.poolSize = 8192 // not used by this implementation var rootParent = {} /** * If `Buffer.TYPED_ARRAY_SUPPORT`: * === true Use Uint8Array implementation (fastest) * === false Use Object implementation (most compatible, even IE6) * * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, * Opera 11.6+, iOS 4.2+. * * Due to various browser bugs, sometimes the Object implementation will be used even * when the browser supports typed arrays. * * Note: * * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances, * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. * * - Safari 5-7 lacks support for changing the `Object.prototype.constructor` property * on objects. * * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. * * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of * incorrect length in some situations. * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they * get the Object implementation, which is slower but behaves correctly. */ Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined ? global.TYPED_ARRAY_SUPPORT : typedArraySupport() function typedArraySupport () { function Bar () {} try { var arr = new Uint8Array(1) arr.foo = function () { return 42 } arr.constructor = Bar return arr.foo() === 42 && // typed array instances can be augmented arr.constructor === Bar && // constructor can be set typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` } catch (e) { return false } } function kMaxLength () { return Buffer.TYPED_ARRAY_SUPPORT ? 0x7fffffff : 0x3fffffff } /** * Class: Buffer * ============= * * The Buffer constructor returns instances of `Uint8Array` that are augmented * with function properties for all the node `Buffer` API functions. We use * `Uint8Array` so that square bracket notation works as expected -- it returns * a single octet. * * By augmenting the instances, we can avoid modifying the `Uint8Array` * prototype. */ function Buffer (arg) { if (!(this instanceof Buffer)) { // Avoid going through an ArgumentsAdaptorTrampoline in the common case. if (arguments.length > 1) return new Buffer(arg, arguments[1]) return new Buffer(arg) } if (!Buffer.TYPED_ARRAY_SUPPORT) { this.length = 0 this.parent = undefined } // Common case. if (typeof arg === 'number') { return fromNumber(this, arg) } // Slightly less common case. if (typeof arg === 'string') { return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8') } // Unusual. return fromObject(this, arg) } function fromNumber (that, length) { that = allocate(that, length < 0 ? 0 : checked(length) | 0) if (!Buffer.TYPED_ARRAY_SUPPORT) { for (var i = 0; i < length; i++) { that[i] = 0 } } return that } function fromString (that, string, encoding) { if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8' // Assumption: byteLength() return value is always < kMaxLength. var length = byteLength(string, encoding) | 0 that = allocate(that, length) that.write(string, encoding) return that } function fromObject (that, object) { if (Buffer.isBuffer(object)) return fromBuffer(that, object) if (isArray(object)) return fromArray(that, object) if (object == null) { throw new TypeError('must start with number, buffer, array or string') } if (typeof ArrayBuffer !== 'undefined') { if (object.buffer instanceof ArrayBuffer) { return fromTypedArray(that, object) } if (object instanceof ArrayBuffer) { return fromArrayBuffer(that, object) } } if (object.length) return fromArrayLike(that, object) return fromJsonObject(that, object) } function fromBuffer (that, buffer) { var length = checked(buffer.length) | 0 that = allocate(that, length) buffer.copy(that, 0, 0, length) return that } function fromArray (that, array) { var length = checked(array.length) | 0 that = allocate(that, length) for (var i = 0; i < length; i += 1) { that[i] = array[i] & 255 } return that } // Duplicate of fromArray() to keep fromArray() monomorphic. function fromTypedArray (that, array) { var length = checked(array.length) | 0 that = allocate(that, length) // Truncating the elements is probably not what people expect from typed // arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior // of the old Buffer constructor. for (var i = 0; i < length; i += 1) { that[i] = array[i] & 255 } return that } function fromArrayBuffer (that, array) { if (Buffer.TYPED_ARRAY_SUPPORT) { // Return an augmented `Uint8Array` instance, for best performance array.byteLength that = Buffer._augment(new Uint8Array(array)) } else { // Fallback: Return an object instance of the Buffer class that = fromTypedArray(that, new Uint8Array(array)) } return that } function fromArrayLike (that, array) { var length = checked(array.length) | 0 that = allocate(that, length) for (var i = 0; i < length; i += 1) { that[i] = array[i] & 255 } return that } // Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object. // Returns a zero-length buffer for inputs that don't conform to the spec. function fromJsonObject (that, object) { var array var length = 0 if (object.type === 'Buffer' && isArray(object.data)) { array = object.data length = checked(array.length) | 0 } that = allocate(that, length) for (var i = 0; i < length; i += 1) { that[i] = array[i] & 255 } return that } if (Buffer.TYPED_ARRAY_SUPPORT) { Buffer.prototype.__proto__ = Uint8Array.prototype Buffer.__proto__ = Uint8Array } else { // pre-set for values that may exist in the future Buffer.prototype.length = undefined Buffer.prototype.parent = undefined } function allocate (that, length) { if (Buffer.TYPED_ARRAY_SUPPORT) { // Return an augmented `Uint8Array` instance, for best performance that = Buffer._augment(new Uint8Array(length)) that.__proto__ = Buffer.prototype } else { // Fallback: Return an object instance of the Buffer class that.length = length that._isBuffer = true } var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1 if (fromPool) that.parent = rootParent return that } function checked (length) { // Note: cannot use `length < kMaxLength` here because that fails when // length is NaN (which is otherwise coerced to zero.) if (length >= kMaxLength()) { throw new RangeError('Attempt to allocate Buffer larger than maximum ' + 'size: 0x' + kMaxLength().toString(16) + ' bytes') } return length | 0 } function SlowBuffer (subject, encoding) { if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding) var buf = new Buffer(subject, encoding) delete buf.parent return buf } Buffer.isBuffer = function isBuffer (b) { return !!(b != null && b._isBuffer) } Buffer.compare = function compare (a, b) { if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { throw new TypeError('Arguments must be Buffers') } if (a === b) return 0 var x = a.length var y = b.length var i = 0 var len = Math.min(x, y) while (i < len) { if (a[i] !== b[i]) break ++i } if (i !== len) { x = a[i] y = b[i] } if (x < y) return -1 if (y < x) return 1 return 0 } Buffer.isEncoding = function isEncoding (encoding) { switch (String(encoding).toLowerCase()) { case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'raw': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return true default: return false } } Buffer.concat = function concat (list, length) { if (!isArray(list)) throw new TypeError('list argument must be an Array of Buffers.') if (list.leng