No more errors like this in the logs!
```
INFO  2018-01-05T18:33:15.942Z Message.saveErrors: null Error
    at file:///C:/Users/Test/AppData/Local/Programs/signal-desktop/resources/app.asar/js/libtextsecure.js:30:33
    at file:///C:/Users/Test/AppData/Local/Programs/signal-desktop/resources/app.asar/js/libtextsecure.js:138:3
    at file:///C:/Users/Test/AppData/Local/Programs/signal-desktop/resources/app.asar/js/libtextsecure.js:40718:3
```
It has no information in the title, and then the callstack points to
the `new Error()` line in the old `errors.js`.
This change will include the actual error name and message details in
the stack, and will include the original http error stack as well if
provided.
		
	
			
		
			
				
	
	
		
			168 lines
		
	
	
	
		
			5.7 KiB
			
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			168 lines
		
	
	
	
		
			5.7 KiB
			
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/*
 | 
						|
 * vim: ts=4:sw=4:expandtab
 | 
						|
 */
 | 
						|
;(function() {
 | 
						|
    'use strict';
 | 
						|
 | 
						|
    var registeredFunctions = {};
 | 
						|
    var Type = {
 | 
						|
        ENCRYPT_MESSAGE: 1,
 | 
						|
        INIT_SESSION: 2,
 | 
						|
        TRANSMIT_MESSAGE: 3,
 | 
						|
        REBUILD_MESSAGE: 4,
 | 
						|
        RETRY_SEND_MESSAGE_PROTO: 5
 | 
						|
    };
 | 
						|
    window.textsecure = window.textsecure || {};
 | 
						|
    window.textsecure.replay = {
 | 
						|
        Type: Type,
 | 
						|
        registerFunction: function(func, functionCode) {
 | 
						|
            registeredFunctions[functionCode] = func;
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    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.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;
 | 
						|
    }
 | 
						|
    inherit(Error, ReplayableError);
 | 
						|
 | 
						|
    ReplayableError.prototype.replay = function() {
 | 
						|
        var argumentsAsArray = Array.prototype.slice.call(arguments, 0);
 | 
						|
        var args = this.args.concat(argumentsAsArray);
 | 
						|
        return registeredFunctions[this.functionCode].apply(window, args);
 | 
						|
    };
 | 
						|
 | 
						|
    function IncomingIdentityKeyError(number, message, key) {
 | 
						|
        this.number = number.split('.')[0];
 | 
						|
        this.identityKey = key;
 | 
						|
 | 
						|
        ReplayableError.call(this, {
 | 
						|
            functionCode : Type.INIT_SESSION,
 | 
						|
            args         : [number, message],
 | 
						|
            name         : 'IncomingIdentityKeyError',
 | 
						|
            message      : "The identity of " + this.number + " has changed."
 | 
						|
        });
 | 
						|
    }
 | 
						|
    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],
 | 
						|
            name         : 'OutgoingIdentityKeyError',
 | 
						|
            message      : "The identity of " + this.number + " has changed."
 | 
						|
        });
 | 
						|
    }
 | 
						|
    inherit(ReplayableError, OutgoingIdentityKeyError);
 | 
						|
 | 
						|
    function OutgoingMessageError(number, message, timestamp, httpError) {
 | 
						|
        ReplayableError.call(this, {
 | 
						|
            functionCode : Type.ENCRYPT_MESSAGE,
 | 
						|
            args         : [number, message, timestamp],
 | 
						|
            name         : 'OutgoingMessageError',
 | 
						|
            message      : httpError ? httpError.message : 'no http error'
 | 
						|
        });
 | 
						|
 | 
						|
        if (httpError) {
 | 
						|
            this.code = httpError.code;
 | 
						|
            appendStack(this, httpError);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    inherit(ReplayableError, OutgoingMessageError);
 | 
						|
 | 
						|
    function SendMessageNetworkError(number, jsonData, httpError, timestamp) {
 | 
						|
        this.number = number;
 | 
						|
        this.code = httpError.code;
 | 
						|
 | 
						|
        ReplayableError.call(this, {
 | 
						|
            functionCode : Type.TRANSMIT_MESSAGE,
 | 
						|
            args         : [number, jsonData, timestamp],
 | 
						|
            name         : 'SendMessageNetworkError',
 | 
						|
            message      : httpError.message
 | 
						|
        });
 | 
						|
 | 
						|
        appendStack(this, httpError);
 | 
						|
    }
 | 
						|
    inherit(ReplayableError, SendMessageNetworkError);
 | 
						|
 | 
						|
    function SignedPreKeyRotationError(numbers, message, timestamp) {
 | 
						|
        ReplayableError.call(this, {
 | 
						|
            functionCode : Type.RETRY_SEND_MESSAGE_PROTO,
 | 
						|
            args         : [numbers, message, timestamp],
 | 
						|
            name         : 'SignedPreKeyRotationError',
 | 
						|
            message      : "Too many signed prekey rotation failures"
 | 
						|
        });
 | 
						|
    }
 | 
						|
    inherit(ReplayableError, SignedPreKeyRotationError);
 | 
						|
 | 
						|
    function MessageError(message, httpError) {
 | 
						|
        this.code = httpError.code;
 | 
						|
 | 
						|
        ReplayableError.call(this, {
 | 
						|
            functionCode : Type.REBUILD_MESSAGE,
 | 
						|
            args         : [message],
 | 
						|
            name         : 'MessageError',
 | 
						|
            message      : httpError.message
 | 
						|
        });
 | 
						|
 | 
						|
        appendStack(this, httpError);
 | 
						|
    }
 | 
						|
    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;
 | 
						|
 | 
						|
        appendStack(this, httpError);
 | 
						|
    }
 | 
						|
    inherit(Error, UnregisteredUserError);
 | 
						|
 | 
						|
    window.textsecure.UnregisteredUserError = UnregisteredUserError;
 | 
						|
    window.textsecure.SendMessageNetworkError = SendMessageNetworkError;
 | 
						|
    window.textsecure.IncomingIdentityKeyError = IncomingIdentityKeyError;
 | 
						|
    window.textsecure.OutgoingIdentityKeyError = OutgoingIdentityKeyError;
 | 
						|
    window.textsecure.ReplayableError = ReplayableError;
 | 
						|
    window.textsecure.OutgoingMessageError = OutgoingMessageError;
 | 
						|
    window.textsecure.MessageError = MessageError;
 | 
						|
    window.textsecure.SignedPreKeyRotationError = SignedPreKeyRotationError;
 | 
						|
 | 
						|
})();
 |