Entries:
Comments:
Posts:

Loading User Information from Channel 9

Something went wrong getting user information from Channel 9

Latest Achievement:

Loading User Information from MSDN

Something went wrong getting user information from MSDN

Visual Studio Achievements

Latest Achievement:

Loading Visual Studio Achievements

Something went wrong getting the Visual Studio Achievements

JavaScript Reflection

I was writing an application for creating a manifest for JavaScript. I was unable to do it using DOM; instead I wrote my own application for parsing JavaScript files. It is little tough to peek into JavaScript objects, initial I could only get the members and fields using for-in. but that was not enough, what if someone stored a file locally and I have to write code to execute it, I would be able to get only the members, just executing members without passing the required input parameter if any will not work. The code below will parse the file and give me the options as to what input is required and if something is returned what it could possibly be returning except primitive types. Knowing these things in advance makes it easier to execute the code. Well it worked for me; let's see how it works for you. I know many people are looking for something like this.
My Space

Difficulty: Intermediate
Time Required: 1-3 hours
Cost: Free
Software:
Hardware:
Download: Download

The code might not be perfect or might not do everything for you, since I wrote to cater my needs. But the basic utilities are implemented, you can add thing according to your needs. I am using the code from my project, therefore you will not see lot of other code that the project refers to, but you can input you JavaScript file to see the results or use the sample file that's provided in the project.
Some assumptions that I made; it will only look for 'prototype' and 'this' keywords in the JS code.

The core code:
This code finds all the objects, their members and inputs for each member:

   1:        x = content.IndexOf(".prototype.", x);
   2:   
   3:        for (int i = 0; x != -1; i++)
   4:        {
   5:           int j = 0;
   6:           int k = 0;
   7:   
   8:           for (j = x - 1; (' ' != content[j] && '\n' != content[j]); j--) { }
   9:           for (k = x + 10; (' ' != content[k] && '=' != content[k]); k++) { }
  10:   
  11:           int y = content.IndexOf("function(", k);
  12:   
  13:           if (y == -1)
  14:              break;
  15:   
  16:           int z = content.IndexOf(')', y);
  17:           string[] inputs = content.Substring(y + 8 + 1, z - (y + 8) - 1).Split(chArr);
  18:           string className = content.Substring(j + 1, x - j - 1);
  19:           string member = content.Substring(x + 10 + 1, k - (x + 10) - 1);
  20:   
  21:           JSObject jsObj = null;
  22:   
  23:           if (!jsObjs.TryGetValue(className, out jsObj))
  24:           {
  25:              jsObj = new JSObject(className);
  26:              jsObjs.Add(jsObj.Name, jsObj);
  27:           }
  28:   
  29:           JSOperation operation = jsObj.addOperation(member);
  30:           
  31:           for (j = 0; j < inputs.Length; j++)
  32:           {
  33:              if (inputs[j] != string.Empty)
  34:                 operation.addInput(inputs[j].Trim());
  35:           }
  36:           
  37:           x = content.IndexOf(".prototype.", x + 1);
  38:        }

Below code finds out all the methods that could be potential outputs for any of the operation, if the operation is not returning primitive data type then most likely it could be one of these types. The problem with associating the output to the operation is to find out what the return type is, since JavaScript supports loosely typed data, no one can be sure of the output data type unless the code is executed. therefore this code at least looks up all the non-primitive data types that could be one of the output types.

   1:        x = content.IndexOf("this.", 0);
   2:   
   3:        for (int i = 0; x != -1; i++)
   4:        {
   5:            int j = 0;
   6:            int k = 0;
   7:            string strObj = string.Empty;
   8:   
   9:            for (j = x - 1; '{' != content[j]; j--) { }
  10:            
  11:            for (k = j - 1; ; k--)
  12:            {
  13:                string fun = content.Substring(k, 8);
  14:                
  15:                if (fun == "function")
  16:                    break;
  17:            }
  18:   
  19:            int y = 0;
  20:   
  21:            for (y = k + 8; content[y] != '('; y++) { }
  22:                  
  23:            if ((k + 8) < y)
  24:            {              
  25:                string objName = content.Substring(k + 9, y - (k + 9));
  26:                JSOutputFunction obj = new JSOutputFunction();
  27:                obj.ObjName = objName;
  28:                int cnt = 1;
  29:                      
  30:                for (k = j + 1; cnt != 0; k++)                    
  31:                {
  32:                    if (content[k] == '{')
  33:                        cnt++;
  34:                          
  35:                    if (content[k] == '}')
  36:                        cnt--;
  37:                }
  38:                      
  39:                strObj = content.Substring(j, k - j);
  40:                k = strObj.IndexOf("this.", 0);
  41:                      
  42:                for (; k != -1; )
  43:                {
  44:                    y = strObj.IndexOfAny(ch, k + 1);
  45:                    string fieldName = strObj.Substring(k + 5, y - k - 5);
  46:                          
  47:                    if (fieldName.Trim() != "toString")
  48:                        obj.AddField(fieldName.Trim());                        
  49:                
  50:                    k = strObj.IndexOf("this.", k + 1);
  51:                }
  52:                outputUtil.AddOutput(obj);
  53:            }
  54:            else
  55:                j = x + 1;          
  56:            x = content.IndexOf("this.", j + strObj.Length);
  57:        }

After running the application, it would look something like this:

JSRef

I am currently working as a Program Manager at Microsoft.

If I missed something or you have any questions, please email me. If you have any feedback or comments please do write I would definitely appreciate it.

Shreyans Kothari (MCAD)
Program Manager
Aditi @ Microsoft
Feedback/Comments

Follow the Discussion

  • Nico WesterdaleNico Westerdale

    Take a look at this Javascript Serializer, similar idea:

    http://www.iconico.com/workshop/jsSerializer/

  • Markus BonkowskiMarkus Bonkowski

    Hello Shreyans Kothari,

    I was searching for javascript reflection with google and found your article.

    I am not really shure if we both have the same understanding what javascript reflection is, but I found a very simple approach that resolves my javascript reflection problems... maybe you are interested in that Wink

    In the web application I am currently creating, I needed to send an AJAX reply that invokes a javascript funktion which exists in the main html page. I thought that this can only be done via javascript reflection, means I am not directly calling a method, instead I send a simple string and that "reflects" the method call. In my application my php scripts now e.g. sends a "@alert('generic reflection proxy')" string. The javascript that requested the site just makes a call to "setTimeout" with the substring after the '@' symbol.

    Kind Regards,

    Markus

  • Narender JakharNarender Jakhar

       Hello Shreyans Kothari,

    I want actual coding of javascript with refleaction in a simple way

       I am not really shure if we both have the same understanding what javascript reflection is, but I found a very simple approach that resolves my javascript reflection problems... maybe you are interested in that Wink

       In the web application I am currently creating, I needed to send an AJAX reply that invokes a javascript funktion which exists in the main html page. I thought that this can only be done via javascript reflection, means I am not directly calling a method, instead I send a simple string and that "reflects" the method call. In my application my php scripts now e.g. sends a "@alert('generic reflection proxy')" string. The javascript that requested the site just makes a call to "setTimeout" with the substring after the '@' symbol.

       Kind Regards,

     Narender jakhar

Remove this comment

Remove this thread

close

Comments Closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums,
or Contact Us and let us know.