v0.19.0
Pre-releaseAPI updated
Loggers now get a method enabledFor to test whether a level is enabled:
import anylogger from 'anylogger'
const log = anylogger('test')
if (log.enabledFor('info')) {
log.info('message', withExpensiveCalculations())
}By default, this method always returns true. When using an adapter, this method should be hooked into the level system of the logger framework the adapter is for, if any.
I am hoping this will be the last API change before 1.0.
Dependencies updated
The development dependencies Mocha, Sinon and Uglify JS were updated to the latest versions, fixing some potential vulnerabilities in the process.
Made logger instantiation more robust and safe
I was seeing some weird error messages in the wild related to anylogger.new. That method has some very weird and evil stuff going on, because we want to create a named function, having the name property of the function match the one we were given, and that is actually tricky on old browsers (IE, Safari). These browsers have trouble understanding this JS syntax:
var name = 'some:test-logger' // note that this name has characters that are illegal in identifiers
var fn = {[name]: function(){}}[name] // fn.name == 'some:test-logger'So instead, I was doing
var r, name = 'some:test-logger'
eval("r={'" + name + "':function(){}}[name]")which does work on these old browsers... but eval is evil right?
In addition, IE still did not set the name, so after the eval statement I was doing:
// IE support: if the function name is not set, add a property manually
return r.name ? r : Object.defineProperty(r, 'name', {get:function(){return name}})However it seems this lead to Uncaught TypeError: Cannot redefine property: name errors in some rare situations. Looking at the original code I still don't quitte understand how, but I hope the new version is more robust:
a.new = function(n,c,r) {
r = (new Function('a', 'n', "return {'" + n + "':function(){a.log(n,[].slice.call(arguments))}}[n]"))(a,n)
try {Object.defineProperty(r, 'name', {get:function(){return n}})} catch(e) {}
return r
// return {[n]: function(){a.log(n,[].slice.call(arguments))}}[n]
}We now use new Function() instead of eval. Still not great, but at least not as evil. We wrap the defineProperty call in try ... catch and, because we wrapped it anyway, we can drop the test and just always try to define it.
The last, commented out, statement gives a glimp into the future... this is what it can look like in a modern browser. But this is a logger, and loggers should support all platforms that all libraries using the logger need to support, so it will be some time before we drop support for IE and Safari in anylogger.