A friend of mine just posted a question on StackOverflow, regarding having reserved member names in code, which doesn’t play well with the minifier. I opened up object explorer and started to look over the API in WebGrease and the System.Web.Optimazation framework. Just took a few minutes and put together some prototype code that will replace the reserved member name in the code, from e.g “delete” to “fooDelete”. It just doesn’t change the member names, but it will also update the usages of them as well. Note! Really not sure why you would like to do this though. Reserved is usually reserved by a meaning. Also note. I didn’t put any love into the code. It should just work. It’s a StackOverflow question, right?

First lets define a custom bundle that we will use only for the code that we want to apply our changes to. You would use this class when registrering your bundles instead of ScriptBundle.

public class CustomBundle : ScriptBundle
{
    public CustomBundle(string virtualPath) 
        : base(virtualPath)
    {
        this.Builder = new CustomBuilder();
    }
    public CustomBundle(string virtualPath, string cdnPath) 
        : base(virtualPath, cdnPath) {
        this.Builder = new CustomBuilder();
    }
}

Now lets define a custom builder that does the work. The key is the usage of JSParser found in WebGrease.

public class CustomBuilder : IBundleBuilder {
    public string BuildBundleContent(
        Bundle bundle, BundleContext context, IEnumerable<FileInfo> files)
    {
        var content = new StringBuilder();
        foreach (var fileInfo in files)
        {
            var parser = new Microsoft.Ajax.Utilities.JSParser(Read(fileInfo));

            //The magic happens here
            parser.Settings.AddRenamePair("delete", "fooDelete");

            content.Append(parser.Parse(parser.Settings).ToCode());
            content.Append(";");
        }

        return content.ToString();
    }

    private string Read(FileInfo file)
    {
        using(var r = file.OpenText())
        {
            return r.ReadToEnd();
        }
    }
}

That’s it. And again. Not much love in this code. But I tested to minifi with it, and it will take care of:

var myObj = {delete: function(){
    ... ... ...
}};

var myOtherObj = { test: function(){
    myObj.delete();
}};

and turn it to:

var myObj = {fooDelete: function(){
    ... ... ...
}};

var myOtherObj = { test: function(){
    myObj.fooDelete();
}};

Any use of the real delete will not be affected, which is exactly what we want. Also note, the result of the code above only kicks in when it’s minified. If you want it always, you’ll have to tweak it.

As an alternative solution you perhaps should use the minifier instead. That will look something like this:

public class CustomBuilder : IBundleBuilder
{
    public string BuildBundleContent(Bundle bundle, BundleContext context, IEnumerable<FileInfo> files)
    {
        var settings = new CodeSettings();
        settings.AddRenamePair("delete", "fooDelete");

        var content = new StringBuilder();
        foreach (var fileInfo in files)
        {
            var minifier = new Microsoft.Ajax.Utilities.Minifier();
            content.Append(minifier.MinifyJavaScript(Read(fileInfo), settings));
            content.Append(";");
        }

        return content.ToString();
    }

    private string Read(FileInfo file)
    {
        using (var r = file.OpenText())
        {
            return r.ReadToEnd();
        }
    }
}

I also have to say something negative about the bundler. When it failed, it failed in silence, just injecting a comment in the generated JS and then didn’t minify the JavaScript. Come on. That should fail with a big fat BOOOOOM!

//Daniel

Category:
ASP.Net MVC & WebAPI, Development, JavaScript
Tags:
, ,

Join the conversation! 8 Comments

  1. Hey Daniel. (garfbradaz from the SO question) – As you said reserved words should be in essence, reserved. I work in EDI which is a heavily standardized-based way of communicating data, thus I’m of the thinking that if there is a standard use it and do not use the reserved words (and break the standard), which is what I think MS thoughts were. A nice example though.

    Reply
    • Agreed on that, the scary part is that I don’t think it was his code (which I knew it wouldn’t be since he is awesome) but a big framework out there. Not confirmed yet though.

      //Daniel

      Reply
    • I like EDI (Created an edifact parser in c# many moons ago for a client that didn’t want biztalk :) – lol) To allow the use of keywords EDI has ? C# has @. Javascript allows [“”]

      Reply
  2. I’ve found some of these silent compile errors with minification/bundling when using some of the LESS parser and the “@import” directive specifically when it didn’t include files within nested folder paths. A new framework I know, but like you said a big fail from MS part in letting these sorts of errors through silently.

    Reply
  3. Thank Daniel! Never seen this before snockets, sprockets and less all crash and burn if minify fails.

    Reply
    • BTW, you can get it to minify without replacing the reserved words. Just use the custom code above and skip the replace of “delete”. It will however insert the comment, but it’s still minified. The comment will probably be easy to remove.

      //Daniel

      Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: