String.raw: some features and limitations

    I. Opportunities


    When I read on MDN : “The static String.raw()method is a tag function of template literals, similar to the rprefix in Python or the @prefix in C # for string literals” - I was really happy because I often lacked something like JavaScript single quotes in Perl.

    I immediately came up with several uses and began to actively use them in scripts.

    1. Defining paths to Windows files without double escaping.

    const r = String.raw;
    const test_module = require(r`e:\DOC\prg\js\node\-lib\test.js`);
    

    2. Defining paths to Windows registry keys.

    const r = String.raw;
    const Winreg = require('winreg');
    const regKey = new Winreg({
      hive: Winreg.HKCU,
      key: r`\Software\MPC-HC\MPC-HC\Settings`
    });
    

    3. Creating complex regular expressions from compound literals.

    See a code example in a recent article.

    II. Limitations


    However, over time, I began to come across unexpected restrictions. Having written about one of them in the V8 bugtracker, I got a sobering explanation. It turns out that although String.rawit produces a string without interpreting escaped literals, at the stage of parsing the code, the analyzer still requires that the literals comply with the rules. The unobvious limitations for the mentioned use cases follow from this.

    1. After the backslash, characters cannot be followed by xor uwithout corresponding hex sequences.

    The following code throws an error Uncaught SyntaxError: Invalid hexadecimal escape sequence:

    console.log(String.raw`с:\x.js`);
    

    The following code throws an error Uncaught SyntaxError: Invalid Unicode escape sequence:

    console.log(String.raw`с:\u.js`);
    

    Moreover, the correct combinations are still serialized uninterpreted:

    console.log(String.raw`\x61`);
    //\x61
    console.log(String.raw`\u0061`);
    //\u0061
    

    I did not find simple ways to solve the problem:

    console.log(String.raw`с:\\x.js`);
    // с:\\x.js
    console.log(String.raw`с:\\x78.js`);
    // с:\\x78.js
    console.log(String.raw`с:\${'x'}.js`);
    // с:\${'x'}.js
    console.log(String.raw`с:\\${'x'}.js`);
    // с:\\x.js
    console.log(String.raw`с:\\u.js`);
    // с:\\u.js
    console.log(String.raw`с:\\x75.js`);
    // с:\\x75.js
    console.log(String.raw`с:\${'u'}.js`);
    // с:\${'u'}.js
    console.log(String.raw`с:\\${'u'}.js`);
    // с:\\u.js
    

    The working solutions are so complex that it will be easier to return to using ordinary double-shielded quotes:

    console.log(String.raw`с:${'\\'}x.js`);
    // с:\x.js
    console.log(String.raw`с:${'\\'}u.js`);
    // с:\u.js
    

    The remaining matches with escaped literals do not cause difficulties and are displayed literally:

    console.log(String.raw`с:\ab\0 cd`);
    console.log(String.raw`с:\ab\' cd`);
    console.log(String.raw`с:\ab\" cd`);
    console.log(String.raw`с:\ab\\ cd`);
    console.log(String.raw`с:\ab\n cd`);
    console.log(String.raw`с:\ab\r cd`);
    console.log(String.raw`с:\ab\v cd`);
    console.log(String.raw`с:\ab\t cd`);
    console.log(String.raw`с:\ab\b cd`);
    console.log(String.raw`с:\ab\f cd`);
    

    2. There is no easy way to include the character itself in the string `.

    This symbol sometimes replaces the English apostrophe, and is also used in some transliteration systems .

    Expected errorUncaught SyntaxError: missing ) after argument list:

    console.log(String.raw`с:\John`s.js`);
    

    Broken solutions:

    console.log(String.raw`с:\John\`s.js`);
    // с:\John\`s.js
    console.log(String.raw`с:\John\x60s.js`);
    // с:\John\x60s.js
    

    Unjustified complexity:

    console.log(String.raw`с:\John${'`'}s.js`);
    // с:\John`s.js
    

    3. There is no easy way to create a backslash string at the very end.

    Expected errorUncaught SyntaxError: Unterminated template literal:

    console.log(String.raw`с:\`);
    

    Broken solutions:

    console.log(String.raw`с:\\`);
    // с:\\
    console.log(String.raw`с:\x5c`);
    // с:\x5c
    

    Unjustified complexity:

    console.log(String.raw`с:${'\\'}`);
    // с:\
    

    III. Comparison with other languages


    The corresponding means of the languages ​​mentioned at the beginning of the note work, as expected, which can be checked, for example, here .

    C # :



    Perl :



    Python :



    If you find other interesting ways to use it String.raw, run into other unexpected restrictions, or come up with elegant ways to work around them, please share.

    PS Pending changes: www.2ality.com/2016/09/template-literal-revision.html

    Also popular now: