diff --git a/js/libtextsecure.js b/js/libtextsecure.js index 823c3cbee0c..187d673bbc2 100644 --- a/js/libtextsecure.js +++ b/js/libtextsecure.js @@ -21,14 +21,36 @@ } }; + function inherit(Parent, Child) { + Child.prototype = Object.create(Parent.prototype, { + constructor: { + value: Child, + writable: true, + configurable: true + } + }); + } + function appendStack(newError, originalError) { + newError.stack += '\nOriginal stack:\n' + originalError.stack; + } + function ReplayableError(options) { options = options || {}; - this.name = options.name || 'ReplayableError'; + this.name = options.name || 'ReplayableError'; + this.message = options.message; + + Error.call(this, options.message); + + // Maintains proper stack trace, where our error was thrown (only available on V8) + // via https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error + if (Error.captureStackTrace) { + Error.captureStackTrace(this); + } + this.functionCode = options.functionCode; - this.args = options.args; + this.args = options.args; } - ReplayableError.prototype = new Error(); - ReplayableError.prototype.constructor = ReplayableError; + inherit(Error, ReplayableError); ReplayableError.prototype.replay = function() { var argumentsAsArray = Array.prototype.slice.call(arguments, 0); @@ -37,94 +59,103 @@ }; function IncomingIdentityKeyError(number, message, key) { + this.number = number.split('.')[0]; + this.identityKey = key; + ReplayableError.call(this, { functionCode : Type.INIT_SESSION, - args : [number, message] - + args : [number, message], + name : 'IncomingIdentityKeyError', + message : "The identity of " + this.number + " has changed." }); - this.number = number.split('.')[0]; - this.name = 'IncomingIdentityKeyError'; - this.message = "The identity of " + this.number + " has changed."; - this.identityKey = key; } - IncomingIdentityKeyError.prototype = new ReplayableError(); - IncomingIdentityKeyError.prototype.constructor = IncomingIdentityKeyError; + inherit(ReplayableError, IncomingIdentityKeyError); function OutgoingIdentityKeyError(number, message, timestamp, identityKey) { + this.number = number.split('.')[0]; + this.identityKey = identityKey; + ReplayableError.call(this, { functionCode : Type.ENCRYPT_MESSAGE, - args : [number, message, timestamp] + args : [number, message, timestamp], + name : 'OutgoingIdentityKeyError', + message : "The identity of " + this.number + " has changed." }); - this.number = number.split('.')[0]; - this.name = 'OutgoingIdentityKeyError'; - this.message = "The identity of " + this.number + " has changed."; - this.identityKey = identityKey; } - OutgoingIdentityKeyError.prototype = new ReplayableError(); - OutgoingIdentityKeyError.prototype.constructor = OutgoingIdentityKeyError; + inherit(ReplayableError, OutgoingIdentityKeyError); function OutgoingMessageError(number, message, timestamp, httpError) { ReplayableError.call(this, { functionCode : Type.ENCRYPT_MESSAGE, - args : [number, message, timestamp] + args : [number, message, timestamp], + name : 'OutgoingMessageError', + message : httpError ? httpError.message : 'no http error' }); - this.name = 'OutgoingMessageError'; + if (httpError) { this.code = httpError.code; - this.message = httpError.message; - this.stack = httpError.stack; + appendStack(this, httpError); } } - OutgoingMessageError.prototype = new ReplayableError(); - OutgoingMessageError.prototype.constructor = OutgoingMessageError; + inherit(ReplayableError, OutgoingMessageError); function SendMessageNetworkError(number, jsonData, httpError, timestamp) { - ReplayableError.call(this, { - functionCode : Type.TRANSMIT_MESSAGE, - args : [number, jsonData, timestamp] - }); - this.name = 'SendMessageNetworkError'; this.number = number; this.code = httpError.code; - this.message = httpError.message; - this.stack = httpError.stack; + + ReplayableError.call(this, { + functionCode : Type.TRANSMIT_MESSAGE, + args : [number, jsonData, timestamp], + name : 'SendMessageNetworkError', + message : httpError.message + }); + + appendStack(this, httpError); } - SendMessageNetworkError.prototype = new ReplayableError(); - SendMessageNetworkError.prototype.constructor = SendMessageNetworkError; + inherit(ReplayableError, SendMessageNetworkError); function SignedPreKeyRotationError(numbers, message, timestamp) { ReplayableError.call(this, { functionCode : Type.RETRY_SEND_MESSAGE_PROTO, - args : [numbers, message, timestamp] + args : [numbers, message, timestamp], + name : 'SignedPreKeyRotationError', + message : "Too many signed prekey rotation failures" }); - this.name = 'SignedPreKeyRotationError'; - this.message = "Too many signed prekey rotation failures"; } - SignedPreKeyRotationError.prototype = new ReplayableError(); - SignedPreKeyRotationError.prototype.constructor = SignedPreKeyRotationError; + inherit(ReplayableError, SignedPreKeyRotationError); function MessageError(message, httpError) { + this.code = httpError.code; + ReplayableError.call(this, { functionCode : Type.REBUILD_MESSAGE, - args : [message] + args : [message], + name : 'MessageError', + message : httpError.message }); - this.name = 'MessageError'; - this.code = httpError.code; - this.message = httpError.message; - this.stack = httpError.stack; + + appendStack(this, httpError); } - MessageError.prototype = new ReplayableError(); - MessageError.prototype.constructor = MessageError; + inherit(ReplayableError, MessageError); function UnregisteredUserError(number, httpError) { + this.message = httpError.message; this.name = 'UnregisteredUserError'; + + Error.call(this, this.message); + + // Maintains proper stack trace, where our error was thrown (only available on V8) + // via https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error + if (Error.captureStackTrace) { + Error.captureStackTrace(this); + } + this.number = number; this.code = httpError.code; - this.message = httpError.message; - this.stack = httpError.stack; + + appendStack(this, httpError); } - UnregisteredUserError.prototype = new Error(); - UnregisteredUserError.prototype.constructor = UnregisteredUserError; + inherit(Error, UnregisteredUserError); window.textsecure.UnregisteredUserError = UnregisteredUserError; window.textsecure.SendMessageNetworkError = SendMessageNetworkError; diff --git a/libtextsecure/errors.js b/libtextsecure/errors.js index 1f9799e2bdf..9a46f84587f 100644 --- a/libtextsecure/errors.js +++ b/libtextsecure/errors.js @@ -20,14 +20,36 @@ } }; + function inherit(Parent, Child) { + Child.prototype = Object.create(Parent.prototype, { + constructor: { + value: Child, + writable: true, + configurable: true + } + }); + } + function appendStack(newError, originalError) { + newError.stack += '\nOriginal stack:\n' + originalError.stack; + } + function ReplayableError(options) { options = options || {}; - this.name = options.name || 'ReplayableError'; + this.name = options.name || 'ReplayableError'; + this.message = options.message; + + Error.call(this, options.message); + + // Maintains proper stack trace, where our error was thrown (only available on V8) + // via https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error + if (Error.captureStackTrace) { + Error.captureStackTrace(this); + } + this.functionCode = options.functionCode; - this.args = options.args; + this.args = options.args; } - ReplayableError.prototype = new Error(); - ReplayableError.prototype.constructor = ReplayableError; + inherit(Error, ReplayableError); ReplayableError.prototype.replay = function() { var argumentsAsArray = Array.prototype.slice.call(arguments, 0); @@ -36,94 +58,103 @@ }; function IncomingIdentityKeyError(number, message, key) { + this.number = number.split('.')[0]; + this.identityKey = key; + ReplayableError.call(this, { functionCode : Type.INIT_SESSION, - args : [number, message] - + args : [number, message], + name : 'IncomingIdentityKeyError', + message : "The identity of " + this.number + " has changed." }); - this.number = number.split('.')[0]; - this.name = 'IncomingIdentityKeyError'; - this.message = "The identity of " + this.number + " has changed."; - this.identityKey = key; } - IncomingIdentityKeyError.prototype = new ReplayableError(); - IncomingIdentityKeyError.prototype.constructor = IncomingIdentityKeyError; + inherit(ReplayableError, IncomingIdentityKeyError); function OutgoingIdentityKeyError(number, message, timestamp, identityKey) { + this.number = number.split('.')[0]; + this.identityKey = identityKey; + ReplayableError.call(this, { functionCode : Type.ENCRYPT_MESSAGE, - args : [number, message, timestamp] + args : [number, message, timestamp], + name : 'OutgoingIdentityKeyError', + message : "The identity of " + this.number + " has changed." }); - this.number = number.split('.')[0]; - this.name = 'OutgoingIdentityKeyError'; - this.message = "The identity of " + this.number + " has changed."; - this.identityKey = identityKey; } - OutgoingIdentityKeyError.prototype = new ReplayableError(); - OutgoingIdentityKeyError.prototype.constructor = OutgoingIdentityKeyError; + inherit(ReplayableError, OutgoingIdentityKeyError); function OutgoingMessageError(number, message, timestamp, httpError) { ReplayableError.call(this, { functionCode : Type.ENCRYPT_MESSAGE, - args : [number, message, timestamp] + args : [number, message, timestamp], + name : 'OutgoingMessageError', + message : httpError ? httpError.message : 'no http error' }); - this.name = 'OutgoingMessageError'; + if (httpError) { this.code = httpError.code; - this.message = httpError.message; - this.stack = httpError.stack; + appendStack(this, httpError); } } - OutgoingMessageError.prototype = new ReplayableError(); - OutgoingMessageError.prototype.constructor = OutgoingMessageError; + inherit(ReplayableError, OutgoingMessageError); function SendMessageNetworkError(number, jsonData, httpError, timestamp) { - ReplayableError.call(this, { - functionCode : Type.TRANSMIT_MESSAGE, - args : [number, jsonData, timestamp] - }); - this.name = 'SendMessageNetworkError'; this.number = number; this.code = httpError.code; - this.message = httpError.message; - this.stack = httpError.stack; + + ReplayableError.call(this, { + functionCode : Type.TRANSMIT_MESSAGE, + args : [number, jsonData, timestamp], + name : 'SendMessageNetworkError', + message : httpError.message + }); + + appendStack(this, httpError); } - SendMessageNetworkError.prototype = new ReplayableError(); - SendMessageNetworkError.prototype.constructor = SendMessageNetworkError; + inherit(ReplayableError, SendMessageNetworkError); function SignedPreKeyRotationError(numbers, message, timestamp) { ReplayableError.call(this, { functionCode : Type.RETRY_SEND_MESSAGE_PROTO, - args : [numbers, message, timestamp] + args : [numbers, message, timestamp], + name : 'SignedPreKeyRotationError', + message : "Too many signed prekey rotation failures" }); - this.name = 'SignedPreKeyRotationError'; - this.message = "Too many signed prekey rotation failures"; } - SignedPreKeyRotationError.prototype = new ReplayableError(); - SignedPreKeyRotationError.prototype.constructor = SignedPreKeyRotationError; + inherit(ReplayableError, SignedPreKeyRotationError); function MessageError(message, httpError) { + this.code = httpError.code; + ReplayableError.call(this, { functionCode : Type.REBUILD_MESSAGE, - args : [message] + args : [message], + name : 'MessageError', + message : httpError.message }); - this.name = 'MessageError'; - this.code = httpError.code; - this.message = httpError.message; - this.stack = httpError.stack; + + appendStack(this, httpError); } - MessageError.prototype = new ReplayableError(); - MessageError.prototype.constructor = MessageError; + inherit(ReplayableError, MessageError); function UnregisteredUserError(number, httpError) { + this.message = httpError.message; this.name = 'UnregisteredUserError'; + + Error.call(this, this.message); + + // Maintains proper stack trace, where our error was thrown (only available on V8) + // via https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error + if (Error.captureStackTrace) { + Error.captureStackTrace(this); + } + this.number = number; this.code = httpError.code; - this.message = httpError.message; - this.stack = httpError.stack; + + appendStack(this, httpError); } - UnregisteredUserError.prototype = new Error(); - UnregisteredUserError.prototype.constructor = UnregisteredUserError; + inherit(Error, UnregisteredUserError); window.textsecure.UnregisteredUserError = UnregisteredUserError; window.textsecure.SendMessageNetworkError = SendMessageNetworkError; diff --git a/libtextsecure/test/index.html b/libtextsecure/test/index.html index 4064ed9e094..ca81c39ad73 100644 --- a/libtextsecure/test/index.html +++ b/libtextsecure/test/index.html @@ -34,6 +34,8 @@ + +