console-shim icon indicating copy to clipboard operation
console-shim copied to clipboard

IE memory Leak

Open jbadeau opened this issue 12 years ago • 7 comments

The line with:

var console = (/** @type {Object} */ global.console); results in memory leak in IE9-

jbadeau avatar Mar 05 '13 09:03 jbadeau

It's called only once. Do you mean it's leaking across page reloads? Also, what tool did you use to detect the leak?

dmp42 avatar Mar 05 '13 13:03 dmp42

Hi, Sorry for the short explanation, I accidentally pressed comment. This issues happens after a page refresh. I noticed it by using the good old windows process viewer. Seems the console var cannot be dereferenced. I have fixed the issue and will make a pull request.

jbadeau avatar Mar 06 '13 17:03 jbadeau

@jbadeau - Any progress on this?

beatgammit avatar May 04 '13 10:05 beatgammit

I am not allowed to do a pullrequest but I can post the changes:

/**

  • @preserve console-shim 1.0.2
  • https://github.com/kayahr/console-shim
  • Copyright (C) 2011 Klaus Reimer [email protected]
  • Licensed under the MIT license
  • (See http://www.opensource.org/licenses/mit-license) */

(function(){ "use strict";

/**

  • Returns a function which calls the specified function in the specified
  • scope. *
  • @param {Function} func
  •        The function to call.
    
  • @param {Object} scope
  •        The scope to call the function in.
    
  • @param {...*} args
  •        Additional arguments to pass to the bound function.
    
  • @returns {function(...[*]): undefined}
  •        The bound function.
    
    / var bind = function(func, scope, args) { var fixedArgs = Array.prototype.slice.call(arguments, 2); return function() { var args = fixedArgs.concat(Array.prototype.slice.call(arguments, 0)); (/* @type {Function} */ func).apply(scope, args); }; };

// Create console if not present if (!window["console"]) window.console = /** @type {Console} / ({}); var console = (/* @type {Object} */ window.console);

// Implement console log if needed if (!console["log"]) { // Use log4javascript if present if (window["log4javascript"]) { var log = log4javascript.getDefaultLogger(); console.log = bind(log.info, log); console.debug = bind(log.debug, log); console.info = bind(log.info, log); console.warn = bind(log.warn, log); console.error = bind(log.error, log); }

// Use empty dummy implementation to ignore logging
else
{
    console.log = (/** @param {...*} args */ function(args) {});
}

}

// Implement other log levels to console.log if missing if (!console["debug"]) console.debug = console.log; if (!console["info"]) console.info = console.log; if (!console["warn"]) console.warn = console.log; if (!console["error"]) console.error = console.log;

// Wrap the log methods in IE (<=9) because their argument handling is wrong // This wrapping is also done if the consoleShimTest symbol is set. This // is needed for unit testing. if (window["consoleShimTest"] != null || eval("/_@cc_on @jscript_version <= 9@/")) { /** * Wraps the call to a real IE logging method. Modifies the arguments so * parameters which are not represented by a placeholder are properly * printed with a space character as separator. * * @param {...*} args * The function arguments. First argument is the log function * to call, the other arguments are the log arguments. */ var wrap = function(args) { var i, max, match, log;

    // Convert argument list to real array
    args = Array.prototype.slice.call(arguments, 0);

    // First argument is the log method to call
    log = args.shift();

    max = args.length;
    if (max > 1 && window["__consoleShimTest__"] !== false)
    {
        // When first parameter is not a string then add a format string to
        // the argument list so we are able to modify it in the next stop
        if (typeof(args[0]) != "string")
        {
            args.unshift("%o");
            max += 1;
        }

        // For each additional parameter which has no placeholder in the
        // format string we add another placeholder separated with a
        // space character.
        match = args[0].match(/%[a-z]/g);
        for (i = match ? match.length + 1 : 1; i < max; i += 1)
        {
            args[0] += " %o";
        }
    }
    Function.apply.call(log, console, args);
};

// Wrap the native log methods of IE to fix argument output problems
console.log = bind(wrap, window, console.log);
console.debug = bind(wrap, window, console.debug);
console.info = bind(wrap, window, console.info);
console.warn = bind(wrap, window, console.warn);
console.error = bind(wrap, window, console.error);

}

// Implement console.assert if missing if (!console["assert"]) { console["assert"] = function() { var args = Array.prototype.slice.call(arguments, 0); var expr = args.shift(); if (!expr) { args[0] = "Assertion failed: " + args[0]; console.error.apply(console, args); } }; }

// Linking console.dir and console.dirxml to the console.log method if // missing. Hopefully the browser already logs objects and DOM nodes as a // tree. if (!console["dir"]) console["dir"] = console.log; if (!console["dirxml"]) console["dirxml"] = console.log;

// Linking console.exception to console.error. This is not the same but // at least some error message is displayed. if (!console["exception"]) console["exception"] = console.error;

// Implement console.time and console.timeEnd if one of them is missing if (!console["time"] || !console["timeEnd"]) { var timers = {}; console["time"] = function(id) { timers[id] = new Date().getTime(); }; console["timeEnd"] = function(id) { var start = timers[id]; if (start) { console.log(id + ": " + (new Date().getTime() - start) + "ms"); delete timers[id]; } }; }

// Implement console.table if missing if (!console["table"]) { console["table"] = function(data, columns) { var i, iMax, row, j, jMax, k;

    // Do nothing if data has wrong type or no data was specified
    if (!data || !(data instanceof Array) || !data.length) return;

    // Auto-calculate columns array if not set
    if (!columns || !(columns instanceof Array))
    {
        columns = [];
        for (k in data[0])
        {
            if (!data[0].hasOwnProperty(k)) continue;
            columns.push(k);
        }
    }

    for (i = 0, iMax = data.length; i < iMax; i += 1)
    {
        row = [];
        for (j = 0, jMax = columns.length; j < jMax; j += 1)
        {
            row.push(data[i][columns[j]]);
        }

        Function.apply.call(console.log, console, row);
    }
};

}

// Dummy implementations of other console features to prevent error messages // in browsers not supporting it. if (!console["clear"]) console["clear"] = function() {}; if (!console["trace"]) console["trace"] = function() {}; if (!console["group"]) console["group"] = function() {}; if (!console["groupCollapsed"]) console["groupCollapsed"] = function() {}; if (!console["groupEnd"]) console["groupEnd"] = function() {}; if (!console["timeStamp"]) console["timeStamp"] = function() {}; if (!console["profile"]) console["profile"] = function() {}; if (!console["profileEnd"]) console["profileEnd"] = function() {}; if (!console["count"]) console["count"] = function() {};

})();

jbadeau avatar May 07 '13 14:05 jbadeau

What do you mean with "I am not allowed to do a pullrequest"? I don't know of any pull request restrictions. Anyone can fork the repo and create pull requests. Unfortunately in the current form it is hard to see what exactly you have changed to fix this memory leak. If you really can't create a pull request then can you please post the changes in diff format?

kayahr avatar May 07 '13 16:05 kayahr

Hm. Only difference I can find is this: var console = (/** @type {Object} */ window.console); => var console = (/* @type {Object} */ window.console);

sigod avatar May 08 '15 14:05 sigod

Nah, never mind. #8

sigod avatar May 08 '15 15:05 sigod