The logic behind Ractive.DEBUG minify assertion - javascript

I saw in Ractive docs this line of code:
Ractive.DEBUG = /unminified/.test(function() {/*unminified*/});
Can you explain the logic behind this ?
The function should have the same value, despite whether it has inline comments or not.

Minification will remove the comment from the code so the function becomes function() {} when regex test calls .toString() on the function, thus yielding false.
Without minification, the regex test will find the occurrence of unminified and therefore DEBUG will be true

Related

Why is semicolon required for this statement?

The following code returns an error that says
"console.log(...) is not a function"
if (4<5) console.log('hi')
(4<5) ? console.log('hi') : console.log('bye')
The following code does not return any error
if (4<5) console.log('hi')
if (4<5) console.log('hi')
Why is this so?
Without a semicolon at the end of the first line, the code tries to use return value of the first console.log as a function and call it with the argument 4<5; this is clearer if you remove the line break:
if (4<5) console.log('hi')(4<5) ? console.log('hi') : console.log('bye')
// ^^^^^^^^^^^^^^^^^^^^^^---- looks like calling `console.log` and then
// using the result as a function
There's the potential for this any time you combine leaving off semicolons (which means you're relying on an error-correction mechanism1) with expression statements. Since expression statements are, by their nature, expressions, if the parser can use them in the previous expression or statement, it will.
FWIW, astexplorer.net is a cool tool I've recently found (thanks to the Babel project). It's an interactive syntax tree explorer which can use any of several parsers to parse your code and tell you exactly how it was parsed. And from the github account, it was started by our own Felix Kling.
1 Quoting Brendan Eich:
ASI is (formally speaking) a syntactic error correction procedure. If you start to code as if it were a universal significant-newline rule, you will get into trouble.

jshint complains about shorthand AND operator with boolean

I've got a javascript function that needs to be executed based on a boolean value. I really like to use the && operator for this (which only executes the second part if the first results in true).
someBoolean && executeFunction();
However, when JSHint checks my code, I get the following message:
Expected an assignment or function call and instead saw an expression.
I'm wondering why JSHint throws this message. I know I can easily avoid it by using a simple if statement, but I really like the simplicity of this one. Maybe I need to fiddle a bit with some JSHint configuration? Is there some hidden danger in this line of code?

Sweet.js: Error: ASSERT: enforest assumes there are tokens to work with

I was creating my macros and there is a bug than pops up (from my point of view) randomly:
ASSERT: enforest assumes there are tokens to work with
I'm not sure about what does this mean but I did my best to encapsulate the problem and I end with this code:
macro foo {
rule { $bar:expr ? } => { $bar }
rule { $bar:expr } => { $bar }
}
If I invoke foo macro between parentheses and add the ? at the end this error is thrown:
(foo test ?)
// produces ASSERT: enforest assumes there are tokens to work with
But if I remove the parentheses or the ? it just works
foo test ?
// produces: test
(foo test)
// produces: test
You can see it failing here:
http://sweetjs.org/browser/editor.html#macro%20foo%20%7B%0A%20%20rule%20%7B%20$bar:expr%20?%20%7D%20=%3E%20%7B%20$bar%20%7D%0A%20%20rule%20%7B%20$bar:expr%20%7D%20=%3E%20%7B%20$bar%20%7D%0A%7D%0A%0A(foo%20test%20?)%0A
So please, this is driving me crazy I'm facing this error again and again. It should be related to the :expr operator, but I can't replace it with ... because it's so greedy and it selects everything to the last ? it found.
I can see the line than throws this error is here. But I don't know the context.
Any help?
Thanks to #natefaubion I have a answer, it's a bug since it's interprets ? as a ternary operator and fails since it can't find the rest of the expression.
Also to my specific case a custom pattern class (instead of :expr) would be a better solution. The idea was proposed here: https://github.com/mozilla/sweet.js/issues/203.
For now a dirty workaround would be to use a case to parse the pattern manually: http://bit.ly/1aPmwyX
As #natefaubion said
its not really a good answer! It works (kind of), but 1) there's a bug with how ternary operators are enforested 2) what you are really wanting is extensible pattern classes.

Why does 'onhashchange'in(window) work?

'onhashchange'in(window)
Having in() work is not a surprise, as new(XMLHTTPRequest) or typeof(x) are other examples of this construct, but not having to separate the string and in is.
Is this per ECMAScript specs? It works in Chrome and FF, haven't tested IE.
From what I can tell, there's no difference whether you wrap window in parenthesis or not in this particular instance. Either way, it checks for this member on the window object.
Might be less confusing if you use spaces:
'onhashchange' in (window)
The same as
'onhashchange' in window
in is not a function, but when you remove the spaces I can see how you read it as such. One advantage to wrapping window in parenthesis is that you can then minify the code:
'onhashchange'in(window)
Something you could not do without the parenthesis.
' is a token that ends a string, so a pair of '' are semantically unambiguous, you don't need whitespace after the end of a string for the lexer to know that it has reached the end of a string.
Another way of saying that is that this works for the same reason that 'Hello '+'world' works.
Additionally, in is a keyword, not a function. It seems like you're thinking of () as the "function call operator", but in this case it's just a disambiguating parentheses.
It's like asking "why does 1 +(2) work?" + doesn't become a function just because you follow it with a paren, and similarly the following will work:
function foo(){}
foo
();
Javascript is brittle with its whitespace rules.
I'm not sure if the notation is confusing you (that maybe in() is a method?), but in is one of those elements of JS that few people correctly understand (I didn't really understand it until quite recently). This is a simplified version showing what in does:
var foo = {
'bar':1,
'barbar':2
}
console.log('bar' in foo); //true
console.log('baz' in foo); //false
What makes this all the more confusing is that you can use in inside a for() loop, as if it (in) were an iterator. The way I tend to think of for loops is like this:
for (exp1; condition; exp2) {
/* statements */
}
for (condition) {
/* statements */
}
In other words, the loop will continue until the in condition fails, which will happen when it runs out of members.

Are semicolons needed after an object literal assignment in JavaScript?

The following code illustrates an object literal being assigned, but with no semicolon afterwards:
var literal = {
say: function(msg) { alert(msg); }
}
literal.say("hello world!");
This appears to be legal, and doesn't issue a warning (at least in Firefox 3). Is this completely legal, or is there a strict version of JavaScript where this is not allowed?
I'm wondering in particular for future compatibility issues... I would like to be writing "correct" JavaScript, so if technically I need to use the semicolon, I would like to be using it.
Not technically, JavaScript has semicolons as optional in many situations.
But, as a general rule, use them at the end of any statement. Why? Because if you ever want to compress the script, it will save you from countless hours of frustration.
Automatic semicolon insertion is performed by the interpreter, so you can leave them out if you so choose. In the comments, someone claimed that
Semicolons are not optional with statements like break/continue/throw
but this is incorrect. They are optional; what is really happening is that line terminators affect the automatic semicolon insertion; it is a subtle difference.
Here is the rest of the standard on semicolon insertion:
For convenience, however, such semicolons may be omitted from the source text in certain situations. These situations are described by saying that semicolons are automatically inserted into the source code token stream in those situations.
The YUI Compressor and dojo shrinksafe should work perfectly fine without semicolons since they're based on a full JavaScript parser. But Packer and JSMin won't.
The other reason to always use semi-colons at the end of statements is that occasionally you can accidentally combine two statements to create something very different. For example, if you follow the statement with the common technique to create a scope using a closure:
var literal = {
say: function(msg) { alert(msg); }
}
(function() {
// ....
})();
The parser might interpret the brackets as a function call, here causing a type error, but in other circumstances it could cause a subtle bug that's tricky to trace. Another interesting mishap is if the next statement starts with a regular expression, the parser might think the first forward slash is a division symbol.
JavaScript interpreters do something called "semicolon insertion", so if a line without a semicolon is valid, a semicolon will quietly be added to the end of the statement and no error will occur.
var foo = 'bar'
// Valid, foo now contains 'bar'
var bas =
{ prop: 'yay!' }
// Valid, bas now contains object with property 'prop' containing 'yay!'
var zeb =
switch (zeb) {
...
// Invalid, because the lines following 'var zeb =' aren't an assignable value
Not too complicated and at least an error gets thrown when something is clearly not right. But there are cases where an error is not thrown, but the statements are not executed as intended due to semicolon insertion. Consider a function that is supposed to return an object:
return {
prop: 'yay!'
}
// The object literal gets returned as expected and all is well
return
{
prop: 'nay!'
}
// Oops! return by itself is a perfectly valid statement, so a semicolon
// is inserted and undefined is unexpectedly returned, rather than the object
// literal. Note that no error occurred.
Bugs like this can be maddeningly difficult to hunt down and while you can't ensure this never happens (since there's no way I know of to turn off semicolon insertion), these sorts of bugs are easier to identify when you make your intentions clear by consistently using semicolons. That and explicitly adding semicolons is generally considered good style.
I was first made aware of this insidious little possibility when reading Douglas Crockford's superb and succinct book "JavaScript: The Good Parts". I highly recommend it.
In this case there is no need for a semicolon at the end of the statement. The conclusion is the same but the reasoning is way off.
JavaScript does not have semicolons as "optional". Rather, it has strict rules around automatic semicolon insertion. Semicolons are not optional with statements like break, continue, or throw. Refer to the ECMA Language Specification for more details; specifically 11.9.1, rules of automatic semicolon insertion.
Use JSLint to keep your JavaScript clean and tidy
JSLint says:
Error:
Implied global: alert 2
Problem at line 3 character 2: Missing
semicolon.
}
The semi-colon is not necessary. Some people choose to follow the convention of always terminating with a semi-colon instead of allowing JavaScript to do so automatically at linebreaks, but I'm sure you'll find groups advocating either direction.
If you are looking at writing "correct" JavaScript, I would suggest testing things in Firefox with javascript.options.strict (accessed via about:config) set to true. It might not catch everything, but it should help you ensure your JavaScript code is more compliant.
This is not valid (see clarification below) JavaScript code, since the assignment is just a regular statement, no different from
var foo = "bar";
The semicolon can be left out since JavaScript interpreters attempt to add a semicolon to fix syntax errors, but this is an extra and unnecessary step. I don't know of any strict mode, but I do know that automated parsers or compressors / obfuscators need that semicolon.
If you want to be writing correct JavaScript code, write the semicolon :-)
According to the ECMAscript spec, http://www.ecma-international.org/publications/standards/Ecma-262.htm, the semicolons are automatically inserted if missing. This makes them not required for the script author, but it implies they are required for the interpreter. This means the answer to the original question is 'No', they are not required when writing a script, but, as is pointed out by others, it is recommended for various reasons.

Categories

Resources