Skip to content
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

Improve exception handling #368

Open
wants to merge 6 commits into
base: release-3.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions packages/blaze/exceptions.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var debugFunc;
var customFn;

// We call into user code in many places, and it's nice to catch exceptions
// propagated from user code immediately so that the whole system doesn't just
Expand All @@ -22,12 +23,26 @@ var debugFunc;
// useful in unit tests that test error messages.
Blaze._throwNextException = false;

/**
* Allows to set a custom exceptions handler.
* @param fn {function} the function where exceptions will be piped
*/
Blaze.setExceptionHandler = function (fn) {
customFn = fn;
};

Blaze._reportException = function (e, msg) {
if (Blaze._throwNextException) {
Blaze._throwNextException = false;
throw e;
}

// if we have a custom exception handler we pipe the exception
// directly into it and omit the Meteor._debug handler here
if (customFn) {
return customFn(msg, e)
}

if (! debugFunc)
// adapted from Tracker
debugFunc = function () {
Expand All @@ -43,14 +58,19 @@ Blaze._reportException = function (e, msg) {
};

Blaze._wrapCatchingExceptions = function (f, where) {
if (typeof f !== 'function')
if (typeof f !== 'function') {
return f;
}

return function () {
try {
return f.apply(this, arguments);
} catch (e) {
Blaze._reportException(e, 'Exception in ' + where + ':');
if (Meteor.isPackageTest) {
jankapunkt marked this conversation as resolved.
Show resolved Hide resolved
throw e;
} else {
Blaze._reportException(e, `Exception in ${where}:`);
}
}
};
};
41 changes: 17 additions & 24 deletions packages/blaze/lookup.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ var bindIfIsFunction = function (x, target) {
var bindDataContext = function (x) {
if (typeof x === 'function') {
return function () {
var data = Blaze.getData();
let data = Blaze.getData();
if (data == null)
data = {};
return x.apply(data, arguments);
Expand All @@ -36,40 +36,30 @@ var bindDataContext = function (x) {
Blaze._OLDSTYLE_HELPER = {};

Blaze._getTemplateHelper = function (template, name, tmplInstanceFunc) {
// XXX COMPAT WITH 0.9.3
var isKnownOldStyleHelper = false;

if (template.__helpers.has(name)) {
var helper = template.__helpers.get(name);
let helper = template.__helpers.get(name);
if (helper === Blaze._OLDSTYLE_HELPER) {
isKnownOldStyleHelper = true;
} else if (helper != null) {
return wrapHelper(bindDataContext(helper), tmplInstanceFunc);
throw new Meteor.Error("not-suported", "We removed support for old style templates");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pardon me, but what does improving exceptions or allowing setting a custom handler function has to do with disabling old template helpers?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you read a bit further in the code it will basically raise a deprecated message. @StorytellerCZ should I restore this? We can drop old style helpers in 3.0 but then we should target 2.6.2 with this PR

} else if (helper !== null) {
return wrapHelper(
bindDataContext(helper),
tmplInstanceFunc,
`${template.viewName} ${name}`
);
} else {
return null;
}
}

// old-style helper
// all unkown-old style helpers
if (name in template) {
// Only warn once per helper
if (! isKnownOldStyleHelper) {
template.__helpers.set(name, Blaze._OLDSTYLE_HELPER);
if (! template._NOWARN_OLDSTYLE_HELPERS) {
Blaze._warn('Assigning helper with `' + template.viewName + '.' +
name + ' = ...` is deprecated. Use `' + template.viewName +
'.helpers(...)` instead.');
}
}
if (template[name] != null) {
return wrapHelper(bindDataContext(template[name]), tmplInstanceFunc);
}
throw new Meteor.Error("not-suported", "We removed support for old style templates");
}

return null;
};

var wrapHelper = function (f, templateFunc) {
var wrapHelper = function (f, templateFunc, name) {
if (typeof f !== "function") {
return f;
}
Expand All @@ -79,7 +69,7 @@ var wrapHelper = function (f, templateFunc) {
var args = arguments;

return Blaze.Template._withTemplateInstanceFunc(templateFunc, function () {
return Blaze._wrapCatchingExceptions(f, 'template helper').apply(self, args);
return Blaze._wrapCatchingExceptions(f, name).apply(self, args);
});
};
};
Expand Down Expand Up @@ -134,7 +124,10 @@ Blaze._getTemplate = function (name, templateInstance) {

Blaze._getGlobalHelper = function (name, templateInstance) {
if (Blaze._globalHelpers[name] != null) {
return wrapHelper(bindDataContext(Blaze._globalHelpers[name]), templateInstance);
return wrapHelper(
bindDataContext(Blaze._globalHelpers[name]),
templateInstance,
`global helper ${name}`);
}
return null;
};
Expand Down
14 changes: 10 additions & 4 deletions packages/spacebars-tests/template_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -3782,20 +3782,26 @@ Tinytest.add(

// Test old-style helper
tmpl.foo = 'hello';
var div = renderToDiv(tmpl);
test.equal(canonicalizeHtml(div.innerHTML), 'hello');
test.throws(function () {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to add tests for the new custom handler. Tests are only modified to check for the throw of /We removed support for old style templates/ but nothing to account for the new changes!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@harryadel thanks for pointing this out I will add tests to it

var div = renderToDiv(tmpl);
test.equal(canonicalizeHtml(div.innerHTML), 'hello');
}, /We removed support for old style templates/)

// Test that replacing a helper still works (i.e. we don't cache them).
// We can change this behavior if we need to, but it is more breaking
// to do so. It breaks some unit tests, for example.
tmpl.foo = 'world';
var div = renderToDiv(tmpl);
test.equal(canonicalizeHtml(div.innerHTML), 'world');

test.throws(function () {
var div = renderToDiv(tmpl);
test.equal(canonicalizeHtml(div.innerHTML), 'world');
}, /We removed support for old style templates/)

// Test that you can delete an old-style helper with `delete`.
// As with the previous case, we can break this functionality, but
// we should do it intentionally.
delete tmpl.foo;

var div = renderToDiv(tmpl);
test.equal(canonicalizeHtml(div.innerHTML), '');
}
Expand Down
2 changes: 1 addition & 1 deletion packages/spacebars-tests/templating_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ Tinytest.add("spacebars-tests - templating_tests - template arg", function (test
Tinytest.add("spacebars-tests - templating_tests - helpers", function (test) {
var tmpl = Template.test_template_helpers_a;

tmpl._NOWARN_OLDSTYLE_HELPERS = true;
// tmpl._NOWARN_OLDSTYLE_HELPERS = true;
tmpl.foo = 'z';
tmpl.helpers({bar: 'b'});
// helpers(...) takes precendence of assigned helper
Expand Down