- From: Ojan Vafai <ojan@chromium.org>
- Date: Tue, 15 Nov 2011 11:32:35 -0800
- To: Aryeh Gregor <ayg@aryeh.name>
- Cc: Ryosuke Niwa <rniwa@webkit.org>, Anne van Kesteren <annevk@opera.com>, "www-dom@w3.org" <www-dom@w3.org>
- Message-ID: <CANMdWTu3HqHcOm34NvoMyiMU0N1vkaUyjuvfwvQg51GL4E7bSw@mail.gmail.com>
On Tue, Nov 15, 2011 at 11:06 AM, Aryeh Gregor <ayg@aryeh.name> wrote:
> On Mon, Nov 14, 2011 at 7:04 PM, Ojan Vafai <ojan@chromium.org> wrote:
> > With a browser-provided html quasi-literal, this could be:
> > var table = html'<table><tbody></tbody></table>';
> > for (var i = 0; i < labels.length; i++) {
> > table.childNodes[0].append(html'<tr>
> > <td>${labels[i]}</td>
> > <td>
> > <span class="bar" style="width:${some expression}%"></span>
> > <span class="value-container">${values[i]}</span>
> > </td>
> > </tr>');
> > }
> > element.append(table);
>
> This seems like it's clearly the best solution proposed so far. It's
> hard to come up with a syntax for DOMs that's more concise or familiar
> than HTML. It's worth pointing out that if this returns a
> DocumentFragment, it's actually impossible for authors to use string
> concatenation -- the *only* way for them to embed variable quantities
> is by the ${} syntax, which will auto-escape. So this would really be
> superb for preventing XSS.
>
I believe preventing XSS was one of the primary use-cases driving the
quasis spec.
> It's also worth pointing out that sadly, running an HTML parser on
> <tr> with no context node will simply make the <tr> disappear, so this
> particular case would completely fail. If the html quasi-function
> uses the existing HTML parser without adjustment, you'll append a
> bunch of spans and text nodes directly to the <tbody>, with no <tr> or
> <td>. There's discussion in another thread (I can't remember which
> list) about how best to handle this for DocumentFragment.innerHTML,
> which is relevant here. It's not so simple to add a new magic
> insertion mode that picks the right insertion context automatically,
> particularly when you mix in SVG.
>
Yes. I agree with Jonas on the other thread, we just need to define this
and make it work in as sane a way as possible. Heh "just" :) To avoid
splitting that part of the discussion on two threads, I was just assuming
that the other thread would resolve how to make it work. :)
> But I think this syntax is far more concise and readable than anything
> else proposed so far, and it's also likely to be the most efficient
> (only one function call). This is the only kind of syntax that will
> actually displace innerHTML and all its XSS problems.
>
Agreed. Although, I share Ryosuke's sadness that it encourages having lots
of whitespace textnodes everywhere in your DOM. Not sure what we could do
about that.
> (There is one aspect in which innerHTML might be better: if you're
> adding hundreds of thousands of rows, it's going to be much faster to
> run the HTML parser once instead of hundreds of thousands of times.
> Is the idea that it's also possible to call the html quasi-function on
> an arbitrary string you build, so you can resort to string
> concatenation if you really need to?)
>
Kind of. The html is actually just a javascript function. So you could call
it explicitly with the right object. You could write a simple function that
would construct the right arguments for the html quasi function argument
given an HTML string.
So the following:
var b = 0, d = 1;
html`aaaa${b}cc\nc${d}eee`
Desugars to:
var $__0 = Object.freeze({
raw: Object.freeze(["aaaa", "cc\\nc", "eee"]),
cooked: Object.freeze(["aaaa", "cc\nc", "eee"])
});
var b = 0, d = 1, f = function() { };
html($__0, b, d);
And b and d are interleaved between the items in the array.
Received on Tuesday, 15 November 2011 19:33:44 UTC