Converting strings to template strings

Andrea Giammarchi andrea.giammarchi at gmail.com
Mon Mar 23 16:54:10 UTC 2015


Mark, is really deadly simple 5 lines of code script which aim is to access
properties without having conflicts with names (using `with(this)`) without
needing SES or anything else in, without needing to change, it's simplified
string templating that works with dynamic strings.

Why do we need dynamic strings? Because internationalization, just to name
one.

```js
// your lang object
var lang = {
  en: {
    greetings: 'Hello ${name}!'
  },
  it: {
    greetings: 'Ciao ${name}!'
  }
};

// one i18n string to show
var greetings = lang[user.lang].greetings;

// there you go
alert(greetings.template(user));
```

The current gist is even overenginered because accepts an optional replacer
per each property but the concept is the following:

```js

function getString() {
  with (this) return name;
}

alert('Ciao ' + getString.call({name: 'Mark'}) + '!');

```

It has been used for I think about 10 years in most famous templating
solutions out there because it's a simple and pragmatic approach.
I don't see real-world harm on it, just convenient ease.

Of course performance is not optimal and of course you don't pass user
defined strings there but even doing so I don't see any difference from
opening a console writing down whatever that is. It's Function, and thanks
gosh still capable of giving `with` ability which in this case I think is
extremely convenient.

However, now I am curious about how would access those properties without
using `with` and avoiding a whole parser for the string.

Thanks and Best Regards



On Mon, Mar 23, 2015 at 6:55 AM, Mark S. Miller <erights at google.com> wrote:

>
>
> On Sun, Mar 22, 2015 at 10:27 AM, Andrea Giammarchi <
> andrea.giammarchi at gmail.com> wrote:
>
>> the snippet is extremely simplified and just works for 99.9% of cases
>> it's meant to be used, a way to provide properties via objects within a
>> string used as template. The string should not be parsed in the wild, same
>> you won't evaluate ever string templates without knowing the source. Of
>> course if you use strings to implement eval like logic you are doing it
>> wrong and makes no sense to use the template but again, that snippets
>> provides what's not possible with string templates.
>>
>> To Mark S. Miller, the strict is a must have for the `with` statement,
>> that snippets works down to IE5 so I don't actually see or understand your
>> surprise.
>>
>> Of course I can implement a full syntax parser instead but then I'd loose
>> on size, simplicity, and portability (performance)
>>
>
> Of course. SES's confine function <
> https://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/ses/startSES.js#901>
> does not use a parser on any browser with adequate ES5 support, i.e., any
> modern browser. Even on Safari, it compensates for Safari's code injection
> vulnerabilities <https://bugs.webkit.org/show_bug.cgi?id=106160> using
> the verifyStrictFunctionBodyByEvalThrowing trick at <
> https://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/ses/repairES5.js#914>.
> Even at the 100x slowdown compared to 'new Function(...)' which we use on
> other browsers, it is still much cheaper than doing our own parse -- if
> nothing else, by virtue of not needing to download a parser.
>
>
>>
>> String templates are not good for templates, these work only for
>> statically defined code and in place meaning you cannot grab content from a
>> DB and inject values like names or numbers as you would do with any
>> templating system.
>>
>
> I still don't understand this. Could you give a simple example and explain
> what it is trying to do? Thanks.
>
>
>
>>
>> So what is your suggested solution?
>>
>
> If it is indeed well motivated not to use templating, and to eval
> user-provided code strings, then use SES's confine.
>
> The implementation of SES's confine does resort to an internal bit of
> sloppy code in order to do a 'with', like your's. But SES puts the
> user-provided source string inside a strict function nested within this
> 'with'. See securableWrapperSrc at <
> https://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/ses/startSES.js#702>.
> No user-provided string is parsed in sloppy mode (except for the
> ugly-but-harmless double check in verifyStrictFunctionBodyByEvalThrowing
> needed to allow lexically nested functions).
>
> SES needs to resort to a 'with' because it uses the scope object to
> emulate an ES5 global scope, where the global variables/properties change
> over time. In your case, are you interested in a changing set of
> variable/property names? If a fixed set, do the values of these properties
> change over time? Are you trying to turn writes to the variables into
> writes to the properties? In either case, yes, you still need an internal
> sloppy 'with' like SES's implementation.
>
> If you're only concerned about a fixed set of properties, and only about
> capturing their current values, then you don't need a 'with'. Please let me
> know if you're interested in how.
>
>
>>
>>
>> On Sun, Mar 22, 2015 at 11:50 AM, Mark Miller <erights at gmail.com> wrote:
>>
>>> The pattern  [\S\s]*? admits a lot. Why are you confident that it can't
>>> contain a string that, for example, closes the function with an unbalanced
>>> "}", then  has an evil expression which evaluates, followed by an
>>> unbalanced "{" so the whole thing still parses?
>>>
>>> On Sun, Mar 22, 2015 at 7:38 AM, Andrea Giammarchi <
>>> andrea.giammarchi at gmail.com> wrote:
>>>
>>>> Hi Mark, thanks for pointing that out but if I understand the problem
>>>> correctly then the snippet I've suggested concatenates strings and will
>>>> never produce those problematic syntax errors. Can I say it's still safe?
>>>> Or do you think it might have some problem in Safari?
>>>>
>>>> Cheers
>>>>
>>>> On Sun, Mar 22, 2015 at 11:28 AM, Mark S. Miller <erights at google.com>
>>>> wrote:
>>>>
>>>>>
>>>>>
>>>>> On Sun, Mar 22, 2015 at 6:46 AM, Andrea Giammarchi <
>>>>> andrea.giammarchi at gmail.com> wrote:
>>>>>
>>>>>> There's no such functionality indeed but you might want to have a
>>>>>> look at this gist:
>>>>>> https://gist.github.com/WebReflection/8f227532143e63649804
>>>>>>
>>>>>> It gives you the ability to write `'test1 ${1 + 2} test2 ${3 + 4}'
>>>>>> .template();` and read `test1 3 test2 7` or to pass an object
>>>>>> similar to .Net String.format so that your Stack overflow code would be
>>>>>> like the following:
>>>>>>
>>>>>> ```js
>>>>>>
>>>>>> let a = "b:${b}";
>>>>>> let b = 10;
>>>>>>
>>>>>> console.log(a.template({b:b}));
>>>>>>
>>>>>> // or
>>>>>>
>>>>>> console.log(a.template({b:27}));
>>>>>>
>>>>>> ```
>>>>>>
>>>>>> You pass named properties and it works with nested properties too
>>>>>> (i.e. ${down.the.road})
>>>>>>
>>>>>> It does use Function which is safe,
>>>>>>
>>>>>
>>>>>
>>>>> Function is safe almost everywhere, but it is worth pointing out
>>>>>
>>>>> https://bugs.webkit.org/show_bug.cgi?id=106160
>>>>> https://bugs.webkit.org/show_bug.cgi?id=131137
>>>>> test_CANT_SAFELY_VERIFY_SYNTAX at
>>>>> https://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/ses/repairES5.js#3198
>>>>> repair_CANT_SAFELY_VERIFY_SYNTAX at
>>>>> https://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/ses/repairES5.js#4170
>>>>>
>>>>> After the repair, the Function constructor is safe again on Safari,
>>>>> but at considerable expense.
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>> compared to eval, and needed to eventually de-opt from 'use strict'
>>>>>> but of course you could write your own parser avoiding Function completely.
>>>>>>
>>>>>> Finally, I agree it would be nice to be able to have a standard way
>>>>>> to template strings in JS, the templating as it is plays very poorly with
>>>>>> runtime generated strings, using eval for that looks the dirtiest thing on
>>>>>> earth.
>>>>>>
>>>>>> Regards
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Sun, Mar 22, 2015 at 10:05 AM, KOLANICH <kolan_n at mail.ru> wrote:
>>>>>>
>>>>>>> I needed a functionality but haven't found it.
>>>>>>> See
>>>>>>> https://stackoverflow.com/questions/29182244/convert-a-string-to-a-template-string
>>>>>>> for more details.
>>>>>>> I think that this should be included into standard;
>>>>>>>
>>>>>>>
>>>>>>> Also we need a standard format string functionality like
>>>>>>> https://msdn.microsoft.com/en-us/library/system.string.format.aspx
>>>>>>> and
>>>>>>> <https://docs.python.org/2/library/string.html#string-formatting>
>>>>>>> https://docs.python.org/2/library/string.html#string-formatting
>>>>>>>
>>>>>>> _______________________________________________
>>>>>>> es-discuss mailing list
>>>>>>> es-discuss at mozilla.org
>>>>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>>>>
>>>>>>>
>>>>>>
>>>>>> _______________________________________________
>>>>>> es-discuss mailing list
>>>>>> es-discuss at mozilla.org
>>>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>> --
>>>>>     Cheers,
>>>>>     --MarkM
>>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> es-discuss mailing list
>>>> es-discuss at mozilla.org
>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>
>>>>
>>>
>>>
>>> --
>>> Text by me above is hereby placed in the public domain
>>>
>>>   Cheers,
>>>   --MarkM
>>>
>>
>>
>
>
> --
>     Cheers,
>     --MarkM
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20150323/57a41a28/attachment-0001.html>


More information about the es-discuss mailing list