I’ve been arguing for some time against embedding server-side tags in JavaScript code, but was put on the spot today by a developer who seemed unconvinced
The code in question was a legacy ASP application, although this is largely unimportant as it could equally apply to ASP.NET or PHP (for example).
The example in question revolved around the use of a constant that they had defined in ServerSide code.
'VB
Const MY_CONST: MY_CONST = 1
If sMyVbVar = MY_CONST Then
'Do Something
End If
//JavaScript
if (sMyJsVar === "<%= MY_CONST%>"){
//DoSomething
}
My standard arguments against this are:
- Script injection: The server-side tag could include code that can break the JavaScript code
- Unit testing. Harder to isolate units of code for testing
- Code Separation : We should keep web page technologies apart as much as possible.
The reason for doing this was so that the developer did not have to define the constant in two places. They reasoned that as it was a value that they controlled, that it wasn’t subject to script injection. This reduced my justification for (1) to “We’re trying to keep the standards simple, and defining exception cases would confuse people”
The unit testing and code separation arguments did not hold water either, as the page itself was a horrible amalgam of HTML, JavaScript, ASP.NET, CSS, XML….you name it, it was there. No code that was every going to be included in this page could possibly be unit tested.
So I found myself feeling like a bit of a pedant insisting that the code was changed, given the circumstances.
Are there any further arguments that might support my reasoning, or am I, in fact being a bit pedantic in this insistence?
So write the code properly and make sure that values are correctly escaped when introduced into the JavaScript context. If your framework doesn’t include a JavaScript “quoter” tool (hint: the JSON support is probably all you need), write one.
This is a good point, but if it’s necessary for the server to drop things into the page for code to use, then it’s necessary. I mean, there are times when this simply has to be done. A good way to do it is for the page to contain some sort of minimal block of data. Thus the server-munged JavaScript on the page really isn’t “code” to be tested, it’s just data. The real client code included from .js files can find the data and use it.
Thus, the page may contain:
Now your nicely-encapsulated pure JavaScript code in “.js” files just has to check for
window.pageData, and it’s good to go.Agreed, but it’s simply a fact that sometimes server-side data needs to drive client-side behavior. To create hidden DOM nodes solely for the purpose of storing data and satisfying your rules is itself a pretty ugly practice.
Coding rules and aesthetics are Good Things. However, one should be pragmatic and take everything in perspective. It’s important to remember that the context of such rules is not always a Perfect Divine Creation, and in the case of HTML, CSS, and JavaScript I think that fact is glaringly clear. In such an imperfect environment, hard-line rules can force you into unnecessary work and code that’s actually harder to maintain.
edit — oh here’s something else I just thought of; sort-of a compromise. A “trick” popularized (in part) by the jQuery gang with their “micro template” facility (apologies to the web genius who actually hit upon this first) is to use
<script>tags that are sort-of “neutered”:Now the browser itself will not even execute that script – the “type” attribute isn’t something it understands as being code, so it just ignores it. However, browsers do make the content of such scripts available, so your code can find the script by “id” value and then, via some safe JSON library or a native browser API if available, parse the notation and extract what it needs. The values still have to be properly quoted etc, but you’re somewhat safer from XSS holes because it’s being parsed as JSON and not as “live” full-blown JavaScript.