-
Notifications
You must be signed in to change notification settings - Fork 479
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Client Side Debugging #279
Changes from 4 commits
3087834
a23170c
3fc6322
a30725e
d6a16c3
0cfc740
0d70d34
f938761
3a52a58
2d5ed4f
ff6c725
b2e9e24
2b27f71
2cf0028
708b5ed
c83414b
cbcc030
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,24 +16,94 @@ function getGlobal(){ | |
|
||
(function(dust) { | ||
|
||
if(!dust) { | ||
if(window.console && window.console.error) { | ||
window.console.error('dust is not defined'); | ||
} | ||
return; | ||
} | ||
|
||
dust.logger = { | ||
// set the 'level' in the host environment equal to or more than the level of error you want to display. | ||
// set 'syncronous' in the host environment to true if you want to manually print out errors in a batch using dust.logErrors() | ||
// set 'forceLevel' in the host environment to an error level in order to only show errors of that level. | ||
DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, level: 4, synchronous: false, | ||
|
||
methodMap: {0: 'debug', 1: 'info', 2: 'warn', 3: 'error'}, | ||
|
||
errorsList: [], | ||
|
||
// can be overridden in the host environment | ||
// log an error based on the level passed in and the current level set on this object | ||
log: function(level, obj) { | ||
if (dust.logger.level <= level) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggest adding this in a try/catch. logging should not generate errors. |
||
if(dust.logger.forceLevel === undefined || dust.logger.forceLevel === level) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typeof dust.logger.forceLevel === 'undefined' or should we just define dust.logger.forceLevel = -1 by default. |
||
var method = dust.logger.methodMap[level]; | ||
if (typeof window.console !== 'undefined' && window.console[method]) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. see note above. don't know if we need .call here |
||
window.console[method].call(window.console, obj); | ||
} | ||
} | ||
} | ||
}, | ||
|
||
addError: function(level, obj) { | ||
dust.logger.errorsList.push({level: level, obj:obj}); | ||
}, | ||
|
||
logErrors: function() { | ||
var i, len; | ||
if(console.group) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. see above. if we shim out |
||
console.group('dust errors'); | ||
} | ||
for(i=0,len=dust.logger.errorsList.length; i<len; i++) { | ||
dust.logger.log(dust.logger.errorsList[i].level, dust.logger.errorsList[i].obj); | ||
} | ||
if(console.groupEnd) { | ||
console.groupEnd(); | ||
} | ||
} | ||
}; | ||
|
||
// if dust.logger.synchronous is set to true, only add the error instead of logging it. | ||
dust.log = function(level, obj) { dust.logger.synchronous ? dust.logger.addError(level, obj) : dust.logger.log(level, obj); }; | ||
|
||
// use this to manually print out synchronlously printed errors. | ||
dust.logErrors = function() { dust.logger.logErrors(); }; | ||
|
||
dust.helpers = {}; | ||
|
||
dust.cache = {}; | ||
|
||
dust.register = function(name, tmpl) { | ||
if (!name) return; | ||
if (!name) { | ||
dust.log(2, 'template name is undefined'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should use the enums created dust.logger.WARN. |
||
return; | ||
} | ||
if(typeof tmpl !== 'function') { | ||
dust.log(2, 'template [' + name + '] cannot be resolved to a dust function'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Very nit-picky: Dust (the language is capitalized. |
||
} | ||
dust.cache[name] = tmpl; | ||
}; | ||
|
||
dust.render = function(name, context, callback) { | ||
var chunk = new Stub(callback).head; | ||
dust.load(name, chunk, Context.wrap(context, name)).end(); | ||
var chunk = new Stub(callback).head, | ||
loadedChunk = dust.load(name, chunk, Context.wrap(context, name)); | ||
// catch errors from dust.load | ||
if(loadedChunk.error && loadedChunk.error.message) { | ||
dust.log(2, loadedChunk.error.message); | ||
} | ||
loadedChunk.end(); | ||
}; | ||
|
||
dust.stream = function(name, context) { | ||
var stream = new Stream(); | ||
dust.nextTick(function() { | ||
dust.load(name, stream.head, Context.wrap(context, name)).end(); | ||
var loadedChunk = dust.load(name, stream.head, Context.wrap(context, name)); | ||
// catch errors from dust.load | ||
if(loadedChunk.error && loadedChunk.error.message) { | ||
dust.log(2, loadedChunk.error.message); | ||
} | ||
loadedChunk.end(); | ||
}); | ||
return stream; | ||
}; | ||
|
@@ -47,7 +117,12 @@ dust.compileFn = function(source, name) { | |
return function(context, callback) { | ||
var master = callback ? new Stub(callback) : new Stream(); | ||
dust.nextTick(function() { | ||
tmpl(master.head, Context.wrap(context, name)).end(); | ||
if(typeof tmpl === 'function') { | ||
tmpl(master.head, Context.wrap(context, name)).end(); | ||
} | ||
else { | ||
dust.log(2, 'template [' + name + '] cannot be resolved to a dust function'); | ||
} | ||
}); | ||
return master; | ||
}; | ||
|
@@ -75,11 +150,12 @@ dust.loadSource = function(source, path) { | |
return eval(source); | ||
}; | ||
|
||
dust.prototype = Object.prototype; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why? the dust namespace is already pretty cluttered. this indirection doesn't by us much. |
||
if (Array.isArray) { | ||
dust.isArray = Array.isArray; | ||
} else { | ||
dust.isArray = function(arr) { | ||
return Object.prototype.toString.call(arr) == "[object Array]"; | ||
return dust.prototype.toString.call(arr) === "[object Array]"; | ||
}; | ||
} | ||
|
||
|
@@ -106,11 +182,14 @@ dust.filter = function(string, auto, filters) { | |
var name = filters[i]; | ||
if (name === "s") { | ||
auto = null; | ||
dust.log(0, 'using unescape filter on [' + string + ']'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure how useful the string is to a dev. Wouldn't they be more interested in the template name or line number? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can't get at the current template name. |
||
} | ||
// fail silently for invalid filters | ||
else if (typeof dust.filters[name] === 'function') { | ||
string = dust.filters[name](string); | ||
} | ||
else { | ||
dust.log(2, 'invalid filter [' + name + ']'); | ||
} | ||
} | ||
} | ||
// by default always apply the h filter, unless asked to unescape with |s | ||
|
@@ -125,8 +204,8 @@ dust.filters = { | |
j: function(value) { return dust.escapeJs(value); }, | ||
u: encodeURI, | ||
uc: encodeURIComponent, | ||
js: function(value) { if (!JSON) { return value; } return JSON.stringify(value); }, | ||
jp: function(value) { if (!JSON) { return value; } return JSON.parse(value); } | ||
js: function(value) { if (!JSON) { dust.log(2, 'JSON is undefined. JSON stringify has not been used on [' + value + ']'); return value; } return JSON.stringify(value); }, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure how useful the value is here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As stated above, can't get at the current template name, which would make it more useful. |
||
jp: function(value) { if (!JSON) { dust.log(2, 'JSON is undefined. JSON parse has not been used on [' + value + ']'); return value; } return JSON.parse(value); } | ||
}; | ||
|
||
function Context(stack, global, blocks) { | ||
|
@@ -153,19 +232,36 @@ Context.prototype.get = function(key) { | |
|
||
while(ctx) { | ||
if (ctx.isObject) { | ||
value = ctx.head[key]; | ||
if(ctx.head) { | ||
value = ctx.head[key]; | ||
} | ||
else { | ||
dust.log(2, 'context head is undefined for[' + key + ']'); | ||
} | ||
if (!(value === undefined)) { | ||
return value; | ||
} | ||
} | ||
else { | ||
dust.log(0, 'current context is not an object. Cannot find value for [{' + key + '}]'); | ||
} | ||
dust.log(0, 'Looking for [{' + key + '}] up the context stack'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this can potentially run many many times. not sure how useful the key is here. Not sure how this would affect perf. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can be useful for debugging if we pair it with the template name somehow. It would only affect perf on pages with this option enabled. It would be turned off in a production environment. |
||
ctx = ctx.tail; | ||
} | ||
dust.log(0, 'Looking for [{' + key + '}] in the globals'); | ||
return this.global ? this.global[key] : undefined; | ||
}; | ||
|
||
Context.prototype.getPath = function(cur, down) { | ||
var ctx = this.stack, | ||
len = down.length; | ||
len = down && dust.isArray(down) ? down.length : 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. getpath calls are generated by the compiler which is written to guarantee an array is there. this might not be useful |
||
|
||
if(!down) { | ||
dust.log(1, 'array parameter in getPath is not defined'); | ||
} | ||
if(!dust.isArray(down)) { | ||
dust.log(1, 'array parameter in getPath is not an array'); | ||
} | ||
|
||
if (cur && len === 0) return ctx.head; | ||
ctx = ctx.head; | ||
|
@@ -178,11 +274,25 @@ Context.prototype.getPath = function(cur, down) { | |
}; | ||
|
||
Context.prototype.push = function(head, idx, len) { | ||
return new Context(new Stack(head, this.stack, idx, len), this.global, this.blocks); | ||
var context = new Context(new Stack(head, this.stack, idx, len), this.global, this.blocks); | ||
if(context) { | ||
return context; | ||
} | ||
else { | ||
dust.log(2, 'Head [' + head + '] could not be resolved to a context'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. head is an object. so you'll get ['object' 'object'] here. not sure how useful knowing the JSON value would be. |
||
return {}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is not the same. the return value needs to be an instance of context. |
||
} | ||
}; | ||
|
||
Context.prototype.rebase = function(head) { | ||
return new Context(new Stack(head), this.global, this.blocks); | ||
var context = new Context(new Stack(head), this.global, this.blocks); | ||
if(context) { | ||
return context; | ||
} | ||
else { | ||
dust.log(2, 'Head [' + head + '] could not be resolved to a context'); | ||
return {}; | ||
} | ||
}; | ||
|
||
Context.prototype.current = function() { | ||
|
@@ -197,7 +307,10 @@ Context.prototype.getBlock = function(key, chk, ctx) { | |
|
||
var blocks = this.blocks; | ||
|
||
if (!blocks) return; | ||
if (!blocks) { | ||
dust.log(1, 'no blocks defined for function getBlock'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should only need to be DEBUG. this is OK since blocks are not necesary |
||
return; | ||
} | ||
var len = blocks.length, fn; | ||
while (len--) { | ||
fn = blocks[len][key]; | ||
|
@@ -223,7 +336,13 @@ Context.prototype.shiftBlocks = function(locals) { | |
function Stack(head, tail, idx, len) { | ||
this.tail = tail; | ||
this.isObject = !dust.isArray(head) && head && typeof head === "object"; | ||
this.head = head; | ||
if(head !== undefined && head !== null) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this can be shortened to head != null |
||
this.head = head; | ||
} | ||
else { | ||
dust.log(0, 'head was undefined. Defaulting to {}'); | ||
this.head = {}; | ||
} | ||
this.index = idx; | ||
this.of = len; | ||
} | ||
|
@@ -242,6 +361,7 @@ Stub.prototype.flush = function() { | |
this.out += chunk.data.join(""); //ie7 perf | ||
} else if (chunk.error) { | ||
this.callback(chunk.error); | ||
dust.log(2, 'chunk error [' + chunk.error + '] thrown. Setting flush function to empty function.'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this stops rendering in a template in the middle of rendering. we should consider rewording this somehow. |
||
this.flush = function() {}; | ||
return; | ||
} else { | ||
|
@@ -265,6 +385,7 @@ Stream.prototype.flush = function() { | |
this.emit('data', chunk.data.join("")); //ie7 perf | ||
} else if (chunk.error) { | ||
this.emit('error', chunk.error); | ||
dust.log(2, 'chunk error [' + chunk.error + '] thrown. Setting flush function to empty function.'); | ||
this.flush = function() {}; | ||
return; | ||
} else { | ||
|
@@ -277,25 +398,39 @@ Stream.prototype.flush = function() { | |
}; | ||
|
||
Stream.prototype.emit = function(type, data) { | ||
if (!this.events) return false; | ||
if (!this.events) { | ||
dust.log(1, 'no events to emit'); | ||
return false; | ||
} | ||
var handler = this.events[type]; | ||
if (!handler) return false; | ||
if (!handler) { | ||
dust.log(2, 'Event type [' + type + '] does not exist'); | ||
return false; | ||
} | ||
if (typeof handler == 'function') { | ||
handler(data); | ||
} else { | ||
} else if (dust.isArray(handler)) { | ||
var listeners = handler.slice(0); | ||
for (var i = 0, l = listeners.length; i < l; i++) { | ||
listeners[i](data); | ||
} | ||
} | ||
else { | ||
dust.log(0, 'handler [' + handler + '] is not of a type that is handled by emit'); | ||
} | ||
}; | ||
|
||
Stream.prototype.on = function(type, callback) { | ||
if (!this.events) { | ||
this.events = {}; | ||
} | ||
if (!this.events[type]) { | ||
this.events[type] = callback; | ||
dust.log(2, 'event type [' + type + '] does not exist. using just the specified callback.'); | ||
if(callback) { | ||
this.events[type] = callback; | ||
} else { | ||
dust.log(2, 'callback for type [' + type + '] does not exist. listener not registered.'); | ||
} | ||
} else if(typeof this.events[type] === 'function') { | ||
this.events[type] = [this.events[type], callback]; | ||
} else { | ||
|
@@ -385,6 +520,7 @@ Chunk.prototype.reference = function(elem, context, auto, filters) { | |
if (!dust.isEmpty(elem)) { | ||
return this.write(dust.filter(elem, auto, filters)); | ||
} else { | ||
dust.log(1, 'reference for element [' + elem + '] was not found. defaulting to chunk.'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can remove defaulting to chunk. |
||
return this; | ||
} | ||
}; | ||
|
@@ -419,9 +555,7 @@ Chunk.prototype.section = function(elem, context, bodies, params) { | |
if (len > 0) { | ||
// any custom helper can blow up the stack | ||
// and store a flattened context, guard defensively | ||
if(context.stack.head) { | ||
context.stack.head['$len'] = len; | ||
} | ||
context.stack.head['$len'] = len; | ||
for (var i=0; i<len; i++) { | ||
if(context.stack.head) { | ||
context.stack.head['$idx'] = i; | ||
|
@@ -455,7 +589,8 @@ Chunk.prototype.section = function(elem, context, bodies, params) { | |
// undefined are all falsy | ||
} else if (skip) { | ||
return skip(this, context); | ||
} | ||
} | ||
dust.log(2, 'can not handle the element [' + elem + '] given for the section tag'); | ||
return this; | ||
}; | ||
|
||
|
@@ -468,6 +603,7 @@ Chunk.prototype.exists = function(elem, context, bodies) { | |
} else if (skip) { | ||
return skip(this, context); | ||
} | ||
dust.log(0, 'not rendering body or skip'); | ||
return this; | ||
}; | ||
|
||
|
@@ -480,6 +616,7 @@ Chunk.prototype.notexists = function(elem, context, bodies) { | |
} else if (skip) { | ||
return skip(this, context); | ||
} | ||
dust.log(0, 'not rendering body or skip'); | ||
return this; | ||
}; | ||
|
||
|
@@ -527,6 +664,7 @@ Chunk.prototype.helper = function(name, context, bodies, params) { | |
if( dust.helpers[name]){ | ||
return dust.helpers[name](this, context, bodies, params); | ||
} else { | ||
dust.log(3, 'invalid helper [' + name + ']'); | ||
return this; | ||
} | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will break in v8 and node where window is not defined.
in dustjs-helpers we just did: