3

JS lint gives the following error in commercial source code (therefore code that is tested on all browsers without issue). Is there a way to suppress this warning by editing the code? I would rather not upgrade jslint if possible.

**** redactor/redactor917.js ****

redactor917.js
/var/moteevate/js/redactor/redactor917.js(1471): SyntaxError: unterminated character class ^
if (current.remove && current.nodeType === 3 && current.nodeValue.match(/[^/\u200B]/g) == null)
........................................................................................................^


1 error(s), 0 warning(s)
user1122069
  • 1,767
  • 1
  • 24
  • 52
  • 2
    Most likely, if the owner of the code lints, it's with JSHint which allows you a lot more flexibility with the options, which is why it might not pass a JSLint parse. And don't assume all commercial code is linted for that matter. [This](https://stackoverflow.com/questions/14639339/javascript-unterminated-character-class) might help you understand the issue. – Andy Mar 26 '14 at 17:21
  • 2
    "commercial" doesn't necessarily mean "good" or "fully tested" ;-) – gen_Eric Mar 26 '14 at 18:25

2 Answers2

3

Interesting regular expression. If I'm reading that right, it looks like if you're removing, and your nodeType is 3, and your nodeValue isn't made up (matches are null) of anything that's not a zero-width space, take the branch.

The problem really isn't escaping ^, as blueberryfields suggests. The ^ is fine. It's just a regexp not operator when it's inside of the brackets.

The problem here is that Crockford (JSLint's author & maintainer) doesn't want you to say what shouldn't match a regular expression (here, you're looking for everything that's not a zero-width space).

He wants your regexp to be specific: Instead, say what should be valid so that items you weren't thinking about when setting up the negative case don't slip through. That's why the error you're seeing should be Insecure '^'.. It's insecure because you could let in patterns you didn't think of.

"I'd like a hamburger without onions, sauerkraut, or cheese."

"Sure thing! Here ya' go!"

"But this has motor oil on it!"

Perhaps that's not an issue in this case, but as a general rule, not too shabby.

Though I think that's a useful motivation, as it's catching that weird "double not" logic from the original regexp, let's not worry about the merits of if we agree with that or not for now and just see what needs to happen to fix it. ;^)

So if I'm doing this right, the current regexp's "nodeValue isn't made up of anything that's not a zero-width space" equates to "nodeValue is made up of zero or more zero-width spaces".

To make this JSLint happy, then, rearrange the regexp to check for "between the start of the string and the end of the string, we want zero or more zero-width spaces. That looks like this (fiddle)...

/*jslint browser: true, white:true, sloppy:true */
var current = {
    remove: true,
    nodeType: 3,
    nodeValue: "\u200b\u200b\u200b"
};

if (current.remove && current.nodeType === 3 
    && current.nodeValue.match(/^[\u200B]*$/g) !== null)
{
    window.alert("YOU CAN DO IT");
}

And yes, "".match(/^[\u200B]*$/g); gives one match as well.

Admittedly, I didn't know what character \u200B was initially. Good info on that here.

==============================================================

EDIT: Responding to the OP's comment.

Bergi's edit shouldn't pass JSLint.

So try this code:

/*jslint browser: true, white:true, sloppy:true */
var current = {
    remove: true,
    nodeType: 3,
    nodeValue: "\u200b\u200b\u200b"
};

if (current.remove && current.nodeType === 3 
    && current.nodeValue.match(/[^\/\u200B]/g) === null) // with Bergi's edit.
{
    window.alert("YOU CAN DO IT");
}    else    {
    window.alert("you can't do");
}

insecure carot

So it's not JSLint compliant.

But if your tool isn't complaining about the insecure ^, I'm not sure what's going on.

Community
  • 1
  • 1
ruffin
  • 16,507
  • 9
  • 88
  • 138
  • 1
    +1, though you could also use ES5's `string.trim()` method and compare against empty string `current.nodeValue.trim() === ''` or check for character length `current.nodeValue.trim().length`. – Fabrício Matté Mar 27 '14 at 21:35
  • Oh never mind, the above would also discard other visible white space which is apparently valid. – Fabrício Matté Mar 27 '14 at 21:37
  • "*That's why the error you're seeing should be `Insecure '^'`*" But the error is `SyntaxError: unterminated character class ^`, what does that have to do with it? – Bergi Mar 27 '14 at 21:41
  • That's a good question. If you paste the bogus code (here's a [JSLint-ready pastebin](http://pastebin.com/iFzzgeK5)) into JSLint.com, you get both errors. So I was guessing that the JSLinter the OP is using only reports the last error on the line. I *bet* fixing the `insecure ^` makes the other go away, as it does if you paste the code above, from this answer, into JSLint.com. So I think the error he's seeing reported is a red herring. – ruffin Mar 27 '14 at 22:03
  • Can you say that Bergi's code is correct or incorrect? – user1122069 Mar 27 '14 at 23:08
  • Okay, looks like his code is fine, though it's not JSLint compliant. Not sure why your tool isn't complaining. ? – ruffin Mar 28 '14 at 16:17
2
/[^/\u200B]/g

is a regex that does contain a slash, which is a regex literal delimiter actually, but is also valid inside a character class. However, JSLint does parse the regex as /[^/ and states for it that the character class is unterminated.

You should escape that slash:

/[^\/\u200B]/g
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • No, try the original and you will see it does not match the slash either. Of course, this might not be intended by the developer, as your considerations about the its purposes show. – Bergi Mar 28 '14 at 16:05
  • I think you're right; I mistakenly kept the `!==` from my version. I'll take down that comment. Your edit still shouldn't pass JSLint, though. ?? – ruffin Mar 28 '14 at 16:14
  • I must confess I haven't even tried, I just explained where that specific error came from. You in-depth refactoring might be beneficial as well :-) – Bergi Mar 28 '14 at 16:17