-
Notifications
You must be signed in to change notification settings - Fork 583
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
Can we avoid try catch with forOf? #1773
Comments
The try/catch is needed to handle the I agree it is super sucky but the spec mandates it. I don't think there is a way around this :'( |
There's probably a way to reformulate the transpiled output, but I don't see any reformulation that looks prettier. The point is that the loop body could throw, the iterator could throw and the return function of the iterator could throw. If Traceur had a sloppy mode, one could think of disabling all exception handling in this mode. But enable such a mode at the global level of a program sounds hazardous. |
imo we should be able to define our own safe guards for the iterator and anything that happens in the body just like we would a for statement. This would be better than Traceur trying to doing it for us. A good source map will help diagnose back to the source if anything fails. Also what is this return()? is that not something we too can handle ourselves if we expect a return method to be called? |
just to add this is what babel outputs |
@pflannery That is pretty much what we used to output before we added support for Try this: function* f() {
try {
yield 1;
yield 2;
} finally {
console.log('Cleanup');
}
}
for (var x of f()) {
console.log(x);
throw 42;
} Notice how we print @sebmck FYI |
@arv Yeah this was discussed in babel/babel#838, still not sure if the performance penalty is worth is which is unfortunate since I'm a massive believer in spec compliancy. Currently Edit: Although thinking back on it this would be a scenario for loose mode and the default behaviour should be the try-catch. Thanks for the heads up! |
I'm still of the opinion that this kind of scenario should be left to the developer to handle when applicable and not constantly by a transpiler. Also is there a way to detect forOf in native? or is it just a matter of a try/catch test over a forOf statement. Because it would be nice if Traceur at runtime didn't polyfill when forOf is native. |
There's no way this should be handled by a developer. @arv's test case gives a clear example of behavior that a proper transpiler must support. |
@pflannery Wait, a transpiler shouldn't be concerned about spec compliancy? I don't understand. |
@pflannery A dev concerned with this level of detail avoid for-of in the rare performance sensitive case. Making these kinds of things optional is too much work for the benefit, compared to other issues. |
@johnjbarton I'm happy to write for statements manually for the iteration. Would be awesome if native would be used when available instead of poly-filling
|
|
@sebmck now your just being childish. |
@pflannery Sorry, was just quoting what lead me to that assumption. |
@sebmck ah ok no worries |
@arv I wanted to amend the transformForOfStatement so that the runtime generated code checks to see if the iterator has a return() implementation and if so then wrap the for-of in a try-catch, otherwise transform without try-catch. Because currently it's rethrowing the exception regardless. This is what I want to PR var ${iter} = (${tree.collection})[$traceurRuntime.toProperty(Symbol.iterator)]();
var ${normalCompletion} = true;
if (${iter}.return != null) {
var ${throwCompletion} = false;
var ${exception} = undefined;
try {
${innerStatement}
} catch (${ex}) {
${throwCompletion} = true;
${exception} = ${ex};
} finally {
try {
if (!${normalCompletion}) {
${iter}.return();
}
} finally {
if (${throwCompletion}) {
throw ${exception};
}
}
}
} else {
${innerStatement}
} I think this leaves people to handle their own exceptions and still very closely meets the spec. @arv what say you? you ok with me PR'ing this? |
@pflannery When do you want to check whether the iterator has a return() implementation? The iterator could have no return property when the loop begins but could have gained one somewhere in the middle of the loop. |
@mnieper your right I didnt think about iterators being that wild. Would be nice if the spec had things like Symbol.DisposableIterator, Symbol.ThrowableIterator to let compilers know what they need to do :'(.. |
Does "loose mode" disable the try-catch? If not, is there any other way short of modifying the code for the transpiler manually? Because the try-catch in for-of loops really messes with the ability to debug -- when an error occurs, I do not get any of the local variables in the watch because it's thrown much higher in the call-stack. Sometimes a dozen levels higher. I know there's a "break on all exceptions" toggle in Chrome, but that's also a problem because some libraries use try-catch to detect eg. browser abilities, meaning you then have to wade through those as well. It seems there really should be a configuration option to disable the try-catch. The default config can have it enabled, to match the spec, but for the majority of people the try-catch isn't necessary and they'd benefit more from having normal debugging abilities. |
Nevermind, it seems that the "loose" config-option does exactly what I wanted. : ) For people wondering, here is how you enable it:
If you're using the es2015 preset instead of the individual plugins, you'd instead add the More info can be found here (though may be outdated): http://web.archive.org/web/20150215181702/http://babeljs.io/docs/usage/loose |
Babel != Traceur |
I've got a way to produce the simpliest javascript code with Babel. "loose" config-option must be true. let counter = 0;
let testMap = [];
for (var key of [...testMap.keys()]) {
counter++;
} it produce this code. "use strict";
var counter = 0;
var testMap = [];
var _arr = [].concat(testMap.keys());
for (var _i = 0; _i < _arr.length; _i++) {
var key = _arr[_i];
counter++;
} Work on a copy of the array ensure hat you can't have side effects if you modify the array in the for loop. |
Both for-of and Maps are natively supported by ALL modern browsers. You might want to consider not transpiling these for both better runtime and download performance. |
7% of users continue to browse the Internet with the old Internet Explorer 11. My clients can't just avoid 7% of their clients. But your point of view is correct for non-B2B2C websites. |
currently this:
produces this:
is there a way to opt out of this try catch?
I'm guessing the only way is write the for statement manually for the iteration
The text was updated successfully, but these errors were encountered: