1

Does someone know where this JavaScript error comes from?

SyntaxError: expected expression, got '.'

I get this error when using a regular expression with a slash (escaped) like el.href.match(/video\/(.*)@/)[1]; as a string passed to a function like createTextNode, textContent or innerHTML.

This regex works when not stored as text. A regex without slash as text works, you can see my code example:

HTML:

<a style="display: none; width: 840px; height: 472px;" href="http://videos.francetv.fr/video/147338657@Info-web" id="catchup" class="video"></a>

JavaScript:

var el = document.getElementById("catchup");
var script = document.createElement("script");
var text = `
    (function() {
        var id = el.href.match(/video\/(.*)@/)[1];
        alert("test 4 - regex with slash as text: " + id);
    })();`; 
script.appendChild(document.createTextNode(text));      
document.getElementsByTagName("head")[0].appendChild(script);

Working and failing tests can be found here:

https://github.com/baptx/baptx.github.io/blob/65f11b77df5a7464365374b3505921a4ef9b1272/get_m3u8_debug/get_m3u8_debug.htm

You can test it live on GitHub Pages (JSFiddle did not work in my case):

https://baptx.github.io/get_m3u8_debug/get_m3u8_debug.htm

baptx
  • 3,428
  • 6
  • 33
  • 42
  • you should have passed the relevant code directly to the question (in case you delete the repo) and the correct link should point to a particular version, not to the master branch - [https://github.com/baptx/baptx.github.io/blob/65f11b77df5a7464365374b3505921a4ef9b1272/get_m3u8_debug/get_m3u8_debug.htm](https://github.com/baptx/baptx.github.io/blob/65f11b77df5a7464365374b3505921a4ef9b1272/get_m3u8_debug/get_m3u8_debug.htm) – Aprillion Oct 22 '16 at 11:42
  • @Aprillion Thanks, I thought about adding the code on StackOverflow but I wanted people to see all the working cases also. Usually I will not delete the repo but I had the idea to backup the link on the Wayback Machine https://web.archive.org/web/20161022102615/https://baptx.github.io/get_m3u8_debug/get_m3u8_debug.htm Good point for the particular version in case I want to fix the error there. – baptx Oct 22 '16 at 12:15

3 Answers3

3

You are escaping the forward slash instead of having a baskward slash.

`el.href.match(/video\/(.*)@/)[1]` === 'el.href.match(/video/(.*)@/)[1]'
// '\/' == '/', not '\\/'

You need to escape the backward slash as well:

`el.href.match(/video\\/(.*)@/)[1]`

You can also take advantage of the template string with the string representation of a regex to get it's source code representation. Basically, eval(/any regex/ + '') will get the same regex.

var regex = /video\/(.*)@/;
var text = `el.href.match(${regex})[1]`;
// Or:
var text = `el.href.match(` + /video\/(.*)@/ + ')[1]';

/video\/(.*)@/igm + '' === '/video\\/(.*)@/gim';
new RegExp('video\\/(.*)@', 'gmi') + '' === '/video\\/(.*)@/gim';
Artyer
  • 31,034
  • 3
  • 47
  • 75
  • Thanks, `${regex.source}` is an awesome trick to keep the original regex. I think it works with ES6 template literals only. Can we also keep the original regex with normal strings? It was hard to choose between the 3 answers but you were the first one ;) Anyway, I have found a better way to use GreaseMonkey with Content Script Injection: https://stackoverflow.com/questions/2303147/injecting-js-functions-into-the-page-from-a-greasemonkey-script-on-chrome/2303228#comment67649467_2303228 – baptx Oct 22 '16 at 11:55
  • 1
    It should be noted that `regex.source` does not work with flags, then you'd have to add `regex.flags` as well, which is ES6 and is not supported in current browsers – adeneo Oct 22 '16 at 11:56
  • @baptx If you are doing a UserScript, just do `// @grant none` and you won't need to inject a content script. https://wiki.greasespot.net/Content_Script_Injection – Artyer Oct 22 '16 at 12:48
  • @Artyer yes, that is what I explained in the link. Do you know if we can keep the original regex with normal strings also? See my first comment to your answer. – baptx Oct 22 '16 at 12:53
  • @adeneo good to know. Do you think it is possible to keep the original regex (without double escaping the slash, using regex.source) with normal strings instead of template literals? – baptx Oct 22 '16 at 14:15
  • @baptx Template literals compile to strings. `regex.source` is a string. `\`abc\` === "abc"`. – Artyer Oct 22 '16 at 14:16
  • @Artyer So it is not possible? Be clear please, I never really used template literals before... – baptx Oct 22 '16 at 20:00
  • @baptx Just do 'Part of a string (' + regex + ') other part of string'. – Artyer Oct 23 '16 at 14:25
  • @Artyer ok, so the only solution with normal strings is to close the quote and concatenate the regex variable. – baptx Oct 27 '16 at 19:10
2

If by "as a string" you mean "video\/(.*)@", then the backslash itself needs to be escaped, "\\" is a string literal containing one backslash:

/video\/(.*)@/

is the same as

new Regex("video\\/(.*)@")
Aprillion
  • 21,510
  • 5
  • 55
  • 89
2

You're using template literals with literal strings as regular expressions, and you have to double-escape the slashes, or any other special character, in those regular expressions.

Javascript interprets and removes the first escape character when parsing the string literal, and you need the escape character to make it into the script, so you'll need two of them.

var text = `
        (function() {
            var id = el.href.match(/video\\/(.*)@/)[1];
            alert("test 4 - regex with slash as text: " + id);
        })();`;
adeneo
  • 312,895
  • 29
  • 395
  • 388
  • Thanks. For information, it also happens with normal strings, not only ES6 template literals. – baptx Oct 22 '16 at 12:18
  • Yes, it would happen with any string you insert, as the first escape character is lost in the parsing of the string literal, and you'll always need two of them, commonly called "double-escaping" in javascript when doing things like this. – adeneo Oct 22 '16 at 12:23
  • Do you or someone else also know why the JavaScript error is called `SyntaxError: expected expression, got '.'`, which '.' are they talking about? – baptx Oct 22 '16 at 12:31
  • 1
    Because the slash isn't escaped, it closes the regular expression. Then you have an opening parentheses, which is valid in javascript, but the period is not, it's a syntax error, and unexpected at that location – adeneo Oct 22 '16 at 12:34
  • Exactly, thank you. That is maybe why I found nothing when searching "SyntaxError: expected expression, got '.'" on Internet, it was too specific to my example. – baptx Oct 22 '16 at 12:39