Skip to content

Commit 3102494

Browse files
authored
Merge pull request #150 from Kanaye/master
Debugging enhancments (custom Messages and more )
2 parents bc129d7 + 0b44441 commit 3102494

File tree

6 files changed

+120
-58
lines changed

6 files changed

+120
-58
lines changed

build/tasks/debug.js

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ module.exports = function (grunt) {
99
grunt.registerTask('debug', function () {
1010
var code = grunt.file.read('dist/blocks.js');
1111
var queries = {};
12+
var methods = {};
13+
var methodId = 0;
1214
var parsed = API().parse(code, {
1315
onparse: function (data, node) {
1416
if (data.examples) {
@@ -62,12 +64,39 @@ module.exports = function (grunt) {
6264
if (func) {
6365
// FunctionExpression.BlockStatement.body(Array)
6466
var funcBody = func.body.body;
65-
esprima.parse('blocks.debug && blocks.debug.checkArgs(' + toValueString(data) + ', Array.prototype.slice.call(arguments), {})').body.forEach(function (chunk) {
66-
funcBody.unshift(chunk);
67+
methods[++methodId] = data;
68+
funcBody.unshift.apply(funcBody, esprima.parse('var __METHOD_ID = ' + methodId + '; if (blocks.debug && blocks.debug.available()) { blocks.debug.checkArgs(blocks.debug.methods[__METHOD_ID], Array.prototype.slice.call(arguments), {});}').body);
69+
}
70+
}
71+
});
72+
73+
var estraverse = require('estraverse');
74+
var regexDebugMessage = /@debugMessage\((:?"|')(.*?)\1,?\s*(Error|Warning|Info)?\)/mi;
75+
function insertMessageIfExsists(raw ,node, parent) {
76+
var message = regexDebugMessage.exec(raw);
77+
if (message) {
78+
var debugChunks = esprima.parse('blocks.debug.throwMessage(\'' + message[2] + '\', blocks.debug.methods[__METHOD_ID] || null ' + (message[3] ? ',\'' + message[3] + '\'' : '') + ');' ).body;
79+
debugChunks.unshift(parent.body.indexOf(node));
80+
debugChunks.unshift(0);
81+
parent.body.splice.apply(parent.body, debugChunks);
82+
}
83+
}
84+
estraverse.traverse(parsed.parseTree(), {
85+
enter: function (node, parent) {
86+
if (node.trailingComments) {
87+
node.trailingComments.forEach(function (comment) {
88+
insertMessageIfExsists(comment.value, node, parent);
89+
});
90+
}
91+
92+
if (node.leadingComments) {
93+
node.leadingComments.forEach(function (comment) {
94+
insertMessageIfExsists(comment.value, node, parent);
6795
});
6896
}
6997
}
7098
});
99+
71100
var targetCode = escodegen.generate(parsed.parseTree(), {
72101
format: {
73102
indent: {
@@ -79,8 +108,9 @@ module.exports = function (grunt) {
79108
comment: true
80109
});
81110

111+
82112
targetCode = insertSourceCode(targetCode, grunt.file.read('lib/blocks/jsdebug.js'));
83-
targetCode = insertSourceCode(targetCode, 'blocks.debug.queries = ' + toValueString(queries));
113+
targetCode = insertSourceCode(targetCode, 'blocks.debug.queries = ' + toValueString(queries) + '; blocks.debug.methods = ' + toValueString(methods) + ';');
84114
// enable blocks.debug after the framework initialized completly (jsdebug uses some functions that aren't initialized when they are needed the first time)
85115
targetCode = insertSourceCode(targetCode, 'blocks.debug.enabled = true;', true);
86116
grunt.file.write('dist/blocks.js', targetCode);

lib/blocks/jsdebug.js

Lines changed: 65 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ blocks.debug = {
2020
addType: function (name, checkCallback) {
2121
customTypes[name.toLowerCase()] = checkCallback;
2222
},
23+
available: function () {
24+
return blocks.debug.enabled && !blocks.debug.executing && blocks.debug.paused === 0;
25+
},
2326
paused: 0,
2427
checkArgs: debugFunc(function (method, args, options) {
2528
if (!blocks.debug.enabled) {
@@ -37,6 +40,44 @@ blocks.debug = {
3740
blocks.debug.printErrors(method, args, options, errors);
3841
}),
3942

43+
throwMessage: debugFunc(function(errorMessage, method, style) {
44+
if (!errorMessage) return;
45+
46+
var type = typeof style == 'string' ? style : 'Info';
47+
48+
if (!style || typeof style != 'object') {
49+
style = defaultStyles[type.toLowerCase()];
50+
}
51+
52+
var message = blocks.debug.Message();
53+
54+
message.addSpan(type, style).addText(' in ');
55+
56+
// No method => No name and no usage, so we at least print a stack trace
57+
if (!method) {
58+
message.addText('unspecified method - ')
59+
.addText(errorMessage);
60+
61+
message.beginCollapsedGroup();
62+
63+
message.addText('Stack trace:')
64+
.newLine()
65+
.addText(new Error().stack);
66+
67+
message.endGroup();
68+
}
69+
70+
// Print method name, error message and add usage
71+
if (method) {
72+
message.addSpan(method.name + '()', {background: '#EEE'})
73+
.addText(' - ')
74+
.addText(errorMessage);
75+
addMethodReference(message, method, true);
76+
}
77+
78+
message.print();
79+
}),
80+
4081
printErrors: function (method, args, options, errors) {
4182
if (!blocks.debug.enabled) {
4283
return;
@@ -52,7 +93,7 @@ blocks.debug = {
5293
}
5394

5495
message
55-
.addSpan('Arguments mismatch:', { background: 'yellow'})
96+
.addSpan('Arguments mismatch:', defaultStyles.info)
5697
.addText(' ');
5798

5899
if (one) {
@@ -95,10 +136,10 @@ blocks.debug = {
95136
queryNotExists: debugFunc(function (query, element) {
96137
var message = blocks.debug.Message();
97138
message.beginSpan({ 'font-weight': 'bold' });
98-
message.addSpan('Warning:', { background: 'orange', padding: '0 3px' });
139+
message.addSpan('Warning:', blocks.extend({}, defaultStyles.warning, {padding: '0 3px' }));
99140

100141
message.addText(' ');
101-
message.addSpan(query.name, { background: 'red', color: 'white' });
142+
message.addSpan(query.name, defaultStyles.error);
102143
message.addSpan('(' + query.params.join(', ') + ')', { background: '#EEE' });
103144

104145
message.addText(' - data-query ');
@@ -122,14 +163,14 @@ blocks.debug = {
122163

123164
message.beginCollapsedGroup();
124165
message.beginSpan({ 'font-weight': 'bold' });
125-
message.addSpan('Critical:', { background: 'red', color: 'white' });
166+
message.addSpan('Critical:', defaultStyles.error);
126167
message.addText(' ');
127168
message.beginSpan({ background: '#EEE' });
128169
message.addText(query.name + '(');
129170
for (var i = 0; i < params.length; i++) {
130171
param = params[i];
131172
if (param == failedParameter) {
132-
message.addSpan(param, { background: 'red', color: 'white' });
173+
message.addSpan(param, defaultStyles.error);
133174
} else {
134175
message.addText(param);
135176
}
@@ -154,9 +195,9 @@ blocks.debug = {
154195
var message = new blocks.debug.Message();
155196

156197
message.beginSpan({ 'font-weight': 'bold' });
157-
message.addSpan('Critical:', { background: 'red', color: 'white' });
198+
message.addSpan('Critical:', defaultStyles.error);
158199
message.addText(' ');
159-
message.addSpan('{{' + expressionText + '}}', { background: 'red', color: 'white' });
200+
message.addSpan('{{' + expressionText + '}}', defaultStyles.error);
160201
message.addText(' - exception thrown while executing expression');
161202
message.endSpan();
162203

@@ -244,7 +285,7 @@ function addError(message, error, method, paramNames) {
244285
}
245286

246287
message.beginSpan({
247-
'background-color': '#EEE'
288+
'background': '#EEE'
248289
});
249290

250291
message.addText(method.name + '(');
@@ -258,11 +299,7 @@ function addError(message, error, method, paramNames) {
258299
}
259300
for (index = error.actual; index < error.expected; index++) {
260301
message
261-
.beginSpan({
262-
'background-color': 'red',
263-
padding: '0 5px',
264-
color: 'white'
265-
})
302+
.beginSpan(blocks.extend({}, defaultStyles.error, { padding: '0 5px'}))
266303
.addText(paramNames[index] || '?')
267304
.endSpan();
268305
if (index != error.expected - 1) {
@@ -279,11 +316,7 @@ function addError(message, error, method, paramNames) {
279316
message.addText(', ');
280317
}
281318
for (index = error.expected; index < error.actual; index++) {
282-
message.addSpan(paramNames[index], {
283-
'background-color': 'red',
284-
'text-decoration': 'line-through',
285-
color: 'white'
286-
});
319+
message.addSpan(paramNames[index], blocks.extend({}, defaultStyles.error, {'text-decoration': 'line-through'}));
287320
if (index != error.actual - 1) {
288321
message.addText(', ');
289322
}
@@ -295,10 +328,7 @@ function addError(message, error, method, paramNames) {
295328
case 'param':
296329
for (index = 0; index < paramNames.length; index++) {
297330
if (method.params[index] == error.param) {
298-
message.addSpan(paramNames[index], {
299-
'background-color': 'red',
300-
color: 'white'
301-
});
331+
message.addSpan(paramNames[index], defaultStyles.error);
302332
} else {
303333
message.addText(paramNames[index]);
304334
}
@@ -556,30 +586,6 @@ function addMethodSignature(message, method) {
556586
message.newLine();
557587
}
558588

559-
function examples(method) {
560-
var examples = method.examples;
561-
562-
if (examples) {
563-
console.groupCollapsed('%cUsage examples', 'color: blue;');
564-
565-
for (var i = 0; i < examples.length; i++) {
566-
console.log(examples[i].code);
567-
if (i != examples.length - 1) {
568-
console.log('-------------------------------');
569-
}
570-
}
571-
572-
console.groupEnd();
573-
}
574-
}
575-
576-
function params(method) {
577-
var params = method.params;
578-
for (var i = 0; i < params.length; i++) {
579-
console.log(' ' + method.params[i].name + ': ' + method.params[i].description);
580-
}
581-
}
582-
583589
function hasArgumentsParam(method) {
584590
var params = method.params;
585591
for (var i = 0; i < params.length; i++) {
@@ -828,3 +834,16 @@ var highlightjs = {
828834
color: '#e7635f'
829835
}
830836
};
837+
838+
var defaultStyles = {
839+
warning: {
840+
background: 'orange'
841+
},
842+
error: {
843+
background: 'red',
844+
color: 'white'
845+
},
846+
info: {
847+
background: 'yellow'
848+
}
849+
};

src/mvc/Application.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,12 @@ define([
261261
if (arguments.length == 1) {
262262
return this._views[name];
263263
}
264+
265+
if (this._started) {
266+
// @debugMessage('Views can not be constructed / added after the application has been started. Try to add your views synchronous before document.readyState is "complete".', Error);
267+
return;
268+
}
269+
264270
if (blocks.isString(prototype)) {
265271
this._viewPrototypes[prototype] = this._createView(nestedViewPrototype);
266272
nestedViewPrototype.options.parentView = name;

src/query/DomQuery.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,9 @@ define([
216216

217217
if (VirtualElement.Is(element)) {
218218
if (VirtualComment.Is(element) && !method.supportsComments) {
219-
// TODO: Should throw debug message
219+
// @if DEBUG
220+
blocks.debug.throwMessage('data-query ' + methods[i].name + ' does not support to be executed as on a comment.', blocks.debug.queries[methods[i].name], 'Error');
221+
// @endif
220222
continue;
221223
}
222224

src/query/Expression.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ define([
99
Html: 0,
1010
ValueOnly: 2,
1111
NodeWise: 4,
12-
12+
1313
Create: function (text, attributeName, element) {
1414
var index = -1;
1515
var endIndex = 0;
@@ -55,7 +55,7 @@ define([
5555

5656
character = text.substring(endIndex);
5757
if (character) {
58-
result.push({
58+
result.push({
5959
value: character
6060
});
6161
}
@@ -95,15 +95,15 @@ define([
9595
if ((expression.nodeLength - lastNodeIndex) == 2) {
9696
value[expression.nodeLength - 2] = null;
9797
}
98-
value[expression.nodeLength - 1] = tempValue;
98+
value[expression.nodeLength - 1] = tempValue;
9999
} else {
100100
value = Expression.Execute(context, elementData, expression[0], expression, type);
101101
}
102102
} else {
103103
while (++index < length) {
104104
lastNodeIndex = expression.nodeLength;
105105
chunk = expression[index];
106-
106+
107107
if (chunk.value) {
108108
if (type !== Expression.ValueOnly && expression.nodeLength === 0) {
109109
expression.nodeLength++;
@@ -121,7 +121,7 @@ define([
121121
} else {
122122
value += tempValue;
123123
}
124-
}
124+
}
125125
}
126126

127127
expression.lastResult = value;
@@ -142,7 +142,7 @@ define([
142142
// jshint -W054
143143
// Disable JSHint error: The Function constructor is a form of eval
144144
func = parameterQueryCache[expression] = parameterQueryCache[expression] ||
145-
new Function('c', 'with(c){with($this){ return ' + expression + '}}');
145+
new Function('c', 'with(c){with($this){ return ' + expression + '}}'/*@if DEBUG */ + '//# sourceURL=' + encodeURI(entireExpression.text)/* @endif */);
146146

147147
Observer.startObserving();
148148

src/query/observable.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ define([
3737
} else if (!blocks.equals(value, currentValue, false) && Events.trigger(observable, 'changing', value, currentValue) !== false) {
3838
observable.update = blocks.noop;
3939
if (!observable._dependencyType) {
40-
if (blocks.isArray(currentValue) && blocks.isArray(value) && observable.reset) {
40+
if (blocks.isArray(currentValue) && (blocks.isArray(value) || !value) && observable.reset) {
4141
observable.reset(value);
42-
} else {
42+
} else if (!blocks.isArray(currentValue) && !observable.reset) {
4343
observable.__value__ = value;
4444
}
4545
} else if (observable._dependencyType == 2) {
@@ -368,6 +368,11 @@ define([
368368

369369
array = blocks.unwrap(array);
370370

371+
if (!blocks.isArray(array) && !!array) {
372+
//@debugMessage('Array-Observables can not be reseted to a non array type! Reset got aborted.', Warning);
373+
return;
374+
}
375+
371376
var current = this.__value__;
372377
var chunkManager = this._chunkManager;
373378
var addCount = Math.max(array.length - current.length, 0);

0 commit comments

Comments
 (0)