Welcome!

Machine Learning Authors: Zakia Bouachraoui, Liz McMillan, Roger Strukhoff, Pat Romanski, Carmen Gonzalez

Related Topics: AJAXWorld RIA Conference & Expo, Machine Learning

AJAXWorld RIA Conference & Expo: Article

AJAX Coding - Is This a Little Too Much Hack for Prototype.js?

Prototype.js adds methods to built-in JavaScript objects - but there's nothing wrong per se with that

Coach Wei's Enterprise Web 2.0 Blog

Prototype.js is a popular Ajax toolkit for web developers. I have enjoyed using it despite the complains I heard from people about how Prototype.js does too much JavaScript hacking that breaks other people's code. One of the common one complains is that Prototype.js adds methods to built-in JavaScript objects (such as String object). I tend to brush such complains aside - "well, there is nothing wrong per se by adding some methods to JavaScript objects via standard permitted means".

But this recent incident with my adoption of the latest and greatest Prototype.js 1.6 really made me wonder: is this a little too much hack for Prototype.js? Or is it just bad coding practice?

I built a little application using Prototype and Scriptaculous. The application was fairly straightforward and Prototype+Scriptaculous made building such an application fairly easy too. Well, then. I used a JavaScript compression tool to compress the JavaScript files. The tool I used is Dojo ShrinkSafe. I have used ShrinkSafe a few thousand times and it never disappointed me. Well, this time, with Prototype.js, the shrinked result disappointed me, because it didn't work. Here is what I got when trying to run the application on IE:

The code that produced this error is here (compressed code):

    function(_133,url,_135){
    _133(_135);
    this.transport=Ajax.getTransport();
    this.request(url);
    }

The error is in line "_133(_135): Microsoft JScript runtime error: Function expected", which means that _133 is not a function. This compressed code corresponds to the following original code:

Ajax.Request = Class.create(Ajax.Base, {
   _complete: false,
     initialize: function($super, url, options) {
       $super(options);
       this.transport = Ajax.getTransport();
       this.request(url);
     },
   ....

So this method "initialize" is a method in "Ajax.Request" class, which extends a class called "Ajax.Base" using the class creation mechanism provided by Prototype.js. The error is in line "$super(options)". It says the argument value to parameter "$super" is not a function. So this means the caller did not pass the correct argument to this method? The code that called the above code is here(compressed code):

    return new Ajax.Request(_2,_3);}

Obviously this is a little hard to decode. But If I map the compressed code back to the original code:

    return new Ajax.Request(action, options);

As I looked into Prototype.js source code, I just don't see the first argument passed into this method call being a function at all. The "action" argument in the above code is actually a URL string. In fact, there is no place in Prototype.js that passes a function argument in calling Ajax.Request method. Since the "initialize" function itself is expecting the first argument being a function, this is fairly puzzling.

So maybe the Class creation mechanism in Prototype.js itself is doing some magic here? Well, this method looks suspetious:

Class.Methods = {
   addMethods: function(source) {
     var ancestor = this.superclass && this.superclass.prototype;
     var properties = Object.keys(source);
     if (!Object.keys({ toString: true }).length)
       properties.push("toString", "valueOf");
     for (var i = 0, length = properties.length; i < length; i++) {
       var property = properties[i], value = source[property];
       if (ancestor && Object.isFunction(value) &&
           value.argumentNames().first() == "$super") {
         var method = value, value = Object.extend((function(m) {
           return function() { return ancestor[m].apply(this, arguments) };
         })(property).wrap(method), {
           valueOf: function() { return method },
           toString: function() { return method.toString() }
         });
       }
       this.prototype[property] = value;
     }
     return this;
   }
};

Aaaaaahhhhhaaaa! Here we go. When creating a class by extending another class, Prototype.js actually checks the function definitions in the code that defines this new class. If the first argument to a function is named "$super", it does some magic here by automatically creating a function to pass onto this method. This explains why the first argument to "Ajax.Request" is not a function at all, but Prototype.js has taken care of this automatically during the process of defining the "Ajax.request" class. It looked at the source code for function "initialize", saw the first argument called "$super", and automatically created a function internally for it already.

Well, this is clearly a clever hack. It works and it is obviously permitted by the JavaScript language. Yes, in JavaScript, you can obtain the source code of a function definition and do some magic by inspecting the source code. For example, you can trigger some mission critical processing if the 3rd and 4th words of a certain function's source code is "Easter Egg".

However, isn't this a little too much hacking? Doing some special processing conditioned upon how some function argument is named in the source code? What if I just happen to name the first argument of a function "$super", without any intention to have any special magic happening? What if a developer somehow decided to name the first argument to method "initialize" as shown in the above to "method" instead of "$super"? What if some day JavaScript is actually running in a compiled fashion (which means that variable names are not necessarily preserved in its source code form)? No wonder Dojo ShrinkSafe didn't work here because ShrinkSafe renames function arguments to shorter names. -Well, ShrinkSafe made a reasonable assumption - who would expect someone to write code conditioned upon how a variable is named in the source code?

Isn't this just a little too much hacking, Prototype.js? Well, I could be wrong, but I couldn't help but feel exactly how a nervous mother would react to a "look, Ma, no hands" kid dangling on a four floor balcony rail.

More Stories By Coach Wei

Coach Wei is founder and CEO of Yottaa, a web performance optimization company. He is also founder and Chairman of Nexaweb, an enterprise application modernization software company. Coding, running, magic, robot, big data, speed...are among his favorite list of things (not necessarily in that order. His coding capability is really at PowerPoint level right now). Caffeine, doing something entrepreneurial and getting out of sleeping are three reasons that he gets up in the morning and gets really excited.

Comments (1)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


CloudEXPO Stories
The platform combines the strengths of Singtel's extensive, intelligent network capabilities with Microsoft's cloud expertise to create a unique solution that sets new standards for IoT applications," said Mr Diomedes Kastanis, Head of IoT at Singtel. "Our solution provides speed, transparency and flexibility, paving the way for a more pervasive use of IoT to accelerate enterprises' digitalisation efforts. AI-powered intelligent connectivity over Microsoft Azure will be the fastest connected path for IoT innovators to scale globally, and the smartest path to cross-device synergy in an instrumented, connected world.
There are many examples of disruption in consumer space – Uber disrupting the cab industry, Airbnb disrupting the hospitality industry and so on; but have you wondered who is disrupting support and operations? AISERA helps make businesses and customers successful by offering consumer-like user experience for support and operations. We have built the world’s first AI-driven IT / HR / Cloud / Customer Support and Operations solution.
ScaleMP is presenting at CloudEXPO 2019, held June 24-26 in Santa Clara, and we’d love to see you there. At the conference, we’ll demonstrate how ScaleMP is solving one of the most vexing challenges for cloud — memory cost and limit of scale — and how our innovative vSMP MemoryONE solution provides affordable larger server memory for the private and public cloud. Please visit us at Booth No. 519 to connect with our experts and learn more about vSMP MemoryONE and how it is already serving some of the world’s largest data centers. Click here to schedule a meeting with our experts and executives.
Darktrace is the world's leading AI company for cyber security. Created by mathematicians from the University of Cambridge, Darktrace's Enterprise Immune System is the first non-consumer application of machine learning to work at scale, across all network types, from physical, virtualized, and cloud, through to IoT and industrial control systems. Installed as a self-configuring cyber defense platform, Darktrace continuously learns what is ‘normal' for all devices and users, updating its understanding as the environment changes.
Codete accelerates their clients growth through technological expertise and experience. Codite team works with organizations to meet the challenges that digitalization presents. Their clients include digital start-ups as well as established enterprises in the IT industry. To stay competitive in a highly innovative IT industry, strong R&D departments and bold spin-off initiatives is a must. Codete Data Science and Software Architects teams help corporate clients to stay up to date with the modern business digitalization solutions. Achieve up to 50% early-stage technological process development cost cutdown with science and R&D-driven investment strategy with Codete's support.