Click here to Skip to main content
15,890,123 members
Articles / Web Development / ASP.NET
Article

JavaScript Reflection

Rate me:
Please Sign up or sign in to vote.
3.67/5 (7 votes)
27 Jul 2007CPOL2 min read 28.3K   197   10  
Reflection of JavaScript Object through Text Parsing of *.js files

Introduction

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 slightly tough to peek into JavaScript objects, initially 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.

Using the Code

The code might not be perfect or might not do everything for you, since I wrote it to cater to my needs. But the basic utilities are implemented, you can add things according to your needs. I am using the code from my project, therefore you will not see a lot of other code that the project refers to, but you can input your 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:

C#
 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:        }

The code below finds out all the methods that could be potential outputs for any of the operations, if the operation is not returning primitive data types 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.

C#
 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:

Screenshot - JSRefle.jpg

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.

History

  • 27th July, 2007: Initial post

About the Author

I am currently working as a Program Manager at Microsoft.

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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead Avaya
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --