{
    'use strict';


    const assert = require('assert');




    module.exports = class CallSite {





        /**
        * returns a serializable frame
        *
        * @param {object} frame v8 callsit object
        *
        * @returns {object} frame
        */
        convertStackFrame(frame) {
            assert(typeof frame === 'object', 'the callsite must be an object');

            const callsite = {};

            callsite.type          = frame.getTypeName();
            callsite.function      = frame.getFunctionName();
            callsite.method        = frame.getMethodName();
            callsite.fileName      = frame.getFileName();
            callsite.lineNumber    = frame.getLineNumber();
            callsite.character     = frame.getColumnNumber();
            callsite.message       = frame.toString();

            return callsite;
        }







        /**
        * returns the callsites for an error object, but only
        * if the stack wasnt accessed before
        *
        * @param {error} err error object
        * @param {number} slice the numebr of frames to remove of the top
        * @param {numebr} limit how many frames to get
        *
        * @returns {array} stack
        */
        getFromError(err, slice = 0, limit = 20) {
            assert(err, 'expected an error obejct');
            assert(err instanceof Error, 'expected an error obejct');

            // return unqiue files
            return this.getCallSite(slice, limit, err);
        }








        /**
        * gets the call site of a specific frame
        *
        * @param {number} slice the numebr of frames to remove of the top
        * @param {numebr} limit how many frames to get
        *
        * @returns {set} list containing filepaths
        */
        getCaller(slice = 0, limit = 5) {
            return this.getCallSite(slice, limit).slice(0, 1)[0];
        }








        /**
        * gets all files called before
        *
        * @param {number} slice the numebr of frames to remove of the top
        * @param {numebr} limit how many frames to get
        *
        * @returns {set} list containing filepaths
        */
        getParentFiles(slice = 0, limit = Infinity) {
            const set = new Set();

            // egt unique files
            this.getCallSite(slice, limit).forEach(s => set.add(s.getFileName()));
            
            // return unqiue files
            return Array.from(set);
        }








        /**
        * gets the callsite object 
        *
        * @param {number} slice the numebr of frames to remove of the top
        * @param {numebr} limit how many frames to get
        *
        * @returns {array} stack
        */
        getCallSite(slice = 0, limit = 10, err) {
            const originalFunction = Error.prepareStackTrace;
            const originalLimit = Error.stackTraceLimit;

            Error.stackTraceLimit = limit;
            Error.prepareStackTrace = (originalFunction, stack) => stack;

            const stack = (err || new Error()).stack.slice((err ? 0 : 2)+slice);

            // revert
            Error.prepareStackTrace = originalFunction;
            Error.stackTraceLimit = originalLimit;
            
            // return unqiue files
            return stack;
        }
    };
}

@@ -317,112 +317,79 @@
     
-assert(typeof frame === 'object', 'the callsite must be an object');%0A%0A            const callsite = %7B%7D;%0A%0A
+const callsite = %7B%7D;%0A%0A            if (typeof frame === 'object') %7B%0A    
     
@@ -446,32 +446,36 @@
 ();%0A            
+    
 callsite.functio
@@ -512,32 +512,36 @@
 ();%0A            
+  
+  
 callsite.method 
@@ -576,32 +576,36 @@
 ();%0A            
+    
 callsite.fileNam
@@ -638,32 +638,36 @@
 ();%0A            
+  
+  
 callsite.lineNum
@@ -690,32 +690,36 @@
 etLineNumber();%0A
+    
             call
@@ -768,32 +768,36 @@
 ();%0A            
+ 
+   
 callsite.message
@@ -822,16 +822,376 @@
 tring();
+%0A            %7D else %7B%0A                callsite.type          = null;%0A                callsite.function      = null;%0A                callsite.method        = null;%0A                callsite.fileName      = 'n/a';%0A                callsite.lineNumber    = '';%0A                callsite.character     = '';%0A                callsite.message       = '-';%0A            %7D
 %0A%0A      
@@ -1676,26 +1676,26 @@
  an error ob
-e
 j
+e
 ct');%0A      
@@ -1754,10 +1754,10 @@
 r ob
-e
 j
+e
 ct')

handle empty callsites graceful