{"id":1210,"date":"2014-04-04T19:57:15","date_gmt":"2014-04-04T14:27:15","guid":{"rendered":"http:\/\/ramkulkarni.com\/blog\/?p=1210"},"modified":"2014-04-04T19:57:15","modified_gmt":"2014-04-04T14:27:15","slug":"parsing-javascript-code-using-mozilla-rhino","status":"publish","type":"post","link":"http:\/\/ramkulkarni.com\/blog\/parsing-javascript-code-using-mozilla-rhino\/","title":{"rendered":"Parsing JavaScript code using Mozilla Rhino"},"content":{"rendered":"<p>Last year I had blogged &#8220;<strong><a title=\"Understanding AST created by Mozilla Rhino parser\" href=\"http:\/\/ramkulkarni.com\/blog\/understanding-ast-created-by-mozilla-rhino-parser\/\" target=\"_blank\">Understanding AST created by Mozilla Rhino parser<\/a><\/strong>&#8220;, where I exaplained how to traverse AST to get all functions and variables. Since then I have received some comments, public and private, to provide sample code. So here is an example of how to parse JavaScript code and get all functions and variables using Mozilla Rhino.<\/p>\n<p><strong>Note that my intention here is not to build the complete symbol table for any given JavaScript code. And I have not run a lot of test cases on this code. The idea is to show how AST could be traversed and how hierarchy of symbols (functions and variables) be built . <\/strong><\/p>\n<p>So, for example, if you feed following JavaScript code to this program &#8211;<\/p>\n<div style=\"background: white; overflow: auto; width: auto; color: black; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000; font-weight: bold;\">function<\/span> func1()\n{\n\t<span style=\"color: #008000; font-weight: bold;\">var<\/span> local1 <span style=\"color: #666666;\">=<\/span> <span style=\"color: #666666;\">10<\/span>;\n\n\tglobal1 <span style=\"color: #666666;\">=<\/span> <span style=\"color: #666666;\">20<\/span>;\n}\n\nobj1 <span style=\"color: #666666;\">=<\/span> {\n\tobjFunc1 <span style=\"color: #666666;\">:<\/span> <span style=\"color: #008000; font-weight: bold;\">function<\/span>()\n\t{\n\t\t<span style=\"color: #008000; font-weight: bold;\">var<\/span> local2 <span style=\"color: #666666;\">=<\/span> <span style=\"color: #666666;\">30<\/span>;\n\t},\n\tobjProp1 <span style=\"color: #666666;\">:<\/span> <span style=\"color: #ba2121;\">\"prop1\"<\/span>\n}<\/pre>\n<\/div>\n<p>You will get following output &#8211;<\/p>\n<div style=\"border: 2px; border-color: black; border-style: solid;\">\n<pre>Function : func1\n\t\tlocal1\n\tglobal1\n\tobj1\n\tobj1\n\t\tobjFunc1\n\t\tFunction : objFunc1\n\t\t\tlocal2\n\t\tobjProp1<\/pre>\n<\/div>\n<p>Yes, I know there are duplicates for object and closure &#8211; because they are first processed as variable names and then object\/closure. This can be easily fixed, but I am going to leave it that way to keep the code simple.<!--more--><\/p>\n<p>I am not going to produce the complete source code here, but will explain some important parts of the program.<\/p>\n<p>The program uses visitor pattern to first traverse AST and then to print symbol hierarchy. It contains following classes &#8211;<\/p>\n<p><a href=\"http:\/\/ramkulkarni.com\/temp\/2014-04-04\/JSSymbol.java\" target=\"_blank\">JSSymbol<\/a> : This class holds reference to AST node and child elements. We will create hierarchy of objects of this class<\/p>\n<p><a href=\"http:\/\/ramkulkarni.com\/temp\/2014-04-04\/JSNodeVisitor.java\" target=\"_blank\">JSNodeVisitor<\/a>: implements Rhino&#8217;s NodeVisitor interface and builds hierarchy of JSSymbo<\/p>\n<p><a href=\"http:\/\/ramkulkarni.com\/temp\/2014-04-04\/IJSSymbolVisitor.java\" target=\"_blank\">IJSSymbolVisitor<\/a> : visitor interface for JSSymbol<\/p>\n<p><a href=\"http:\/\/ramkulkarni.com\/temp\/2014-04-04\/JSSymbolVisitor.java\" target=\"_blank\">JSSymbolVisitor<\/a> : implements IJSSymbolVisitor and prints hierarchy of JSSymbol objects<\/p>\n<p><a href=\"http:\/\/ramkulkarni.com\/temp\/2014-04-04\/JSErrorReporter.java\" target=\"_blank\">JSErrorReporter<\/a> : implements ErrorReporter interface of Rhino and prints syntax errors in the JS script<\/p>\n<p><a href=\"http:\/\/ramkulkarni.com\/temp\/2014-04-04\/RhinoDemo.java\" target=\"_blank\">RhinoDemo<\/a> : main program<\/p>\n<p>paseJS function in <a href=\"http:\/\/ramkulkarni.com\/temp\/2014-04-04\/RhinoDemo.java\" target=\"_blank\">RhinoDemo<\/a> class parses the script and gets the AstRoot node. It then calls visit method of the root node, passing <a href=\"http:\/\/ramkulkarni.com\/temp\/2014-04-04\/JSNodeVisitor.java\" target=\"_blank\">JSNodeVisitor<\/a> to it. After building the symbol heir achy, it prints it using <a href=\"http:\/\/ramkulkarni.com\/temp\/2014-04-04\/JSSymbolVisitor.java\" target=\"_blank\">JSSymbolVisitor<\/a>.<\/p>\n<div style=\"background: white; overflow: auto; width: auto; color: black; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000; font-weight: bold;\">public<\/span> <span style=\"color: #b00040;\">void<\/span> <span style=\"color: #0000ff;\">parseJS<\/span> <span style=\"color: #666666;\">(<\/span>String filePath<span style=\"color: #666666;\">)<\/span> <span style=\"color: #008000; font-weight: bold;\">throws<\/span> Exception\n<span style=\"color: #666666;\">{<\/span>\n\tCompilerEnvirons env <span style=\"color: #666666;\">=<\/span> <span style=\"color: #008000; font-weight: bold;\">new<\/span> CompilerEnvirons<span style=\"color: #666666;\">();<\/span>\n\n\tenv<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">setRecoverFromErrors<\/span><span style=\"color: #666666;\">(<\/span><span style=\"color: #008000; font-weight: bold;\">true<\/span><span style=\"color: #666666;\">);<\/span>\n\n\tFileReader strReader <span style=\"color: #666666;\">=<\/span> <span style=\"color: #008000; font-weight: bold;\">new<\/span> FileReader<span style=\"color: #666666;\">(<\/span>filePath<span style=\"color: #666666;\">);<\/span>\n\n\tIRFactory factory <span style=\"color: #666666;\">=<\/span> <span style=\"color: #008000; font-weight: bold;\">new<\/span> IRFactory<span style=\"color: #666666;\">(<\/span>env<span style=\"color: #666666;\">,<\/span> <span style=\"color: #008000; font-weight: bold;\">new<\/span> JSErrorReporter<span style=\"color: #666666;\">());<\/span>\n\tAstRoot rootNode <span style=\"color: #666666;\">=<\/span> factory<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">parse<\/span><span style=\"color: #666666;\">(<\/span>strReader<span style=\"color: #666666;\">,<\/span> <span style=\"color: #008000; font-weight: bold;\">null<\/span><span style=\"color: #666666;\">,<\/span> <span style=\"color: #666666;\">0);<\/span>\n\n\tJSNodeVisitor nodeVisitor <span style=\"color: #666666;\">=<\/span> <span style=\"color: #008000; font-weight: bold;\">new<\/span> JSNodeVisitor<span style=\"color: #666666;\">();<\/span>\n\n\trootNode<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">visit<\/span><span style=\"color: #666666;\">(<\/span>nodeVisitor<span style=\"color: #666666;\">);<\/span>\n\n\tnodeVisitor<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">getRoot<\/span><span style=\"color: #666666;\">().<\/span><span style=\"color: #7d9029;\">visit<\/span><span style=\"color: #666666;\">(<\/span><span style=\"color: #008000; font-weight: bold;\">new<\/span> JSSymbolVisitor<span style=\"color: #666666;\">());<\/span>\n<span style=\"color: #666666;\">}<\/span><\/pre>\n<\/div>\n<p>visit method of JSNodeVisistor calls addToParent method which actually builds symbol hierarchy<\/p>\n<div style=\"background: white; overflow: auto; width: auto; color: black; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000; font-weight: bold;\">private<\/span> <span style=\"color: #b00040;\">void<\/span> <span style=\"color: #0000ff;\">addToParent<\/span><span style=\"color: #666666;\">(<\/span>AstNode node<span style=\"color: #666666;\">)<\/span>\n<span style=\"color: #666666;\">{<\/span>\n\t<span style=\"color: #008000; font-weight: bold;\">if<\/span> <span style=\"color: #666666;\">(<\/span>root <span style=\"color: #666666;\">==<\/span> <span style=\"color: #008000; font-weight: bold;\">null<\/span><span style=\"color: #666666;\">)<\/span>\n\t<span style=\"color: #666666;\">{<\/span>\n\t\troot <span style=\"color: #666666;\">=<\/span> <span style=\"color: #008000; font-weight: bold;\">new<\/span> JSSymbol<span style=\"color: #666666;\">(<\/span>node<span style=\"color: #666666;\">);<\/span>\n\t\tfunctionsStack<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">push<\/span><span style=\"color: #666666;\">(<\/span>root<span style=\"color: #666666;\">);<\/span>\n\t\tcurrentFuncEndOffset <span style=\"color: #666666;\">=<\/span> node<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">getAbsolutePosition<\/span><span style=\"color: #666666;\">()<\/span> <span style=\"color: #666666;\">+<\/span> node<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">getLength<\/span><span style=\"color: #666666;\">();<\/span>\n\t\t<span style=\"color: #008000; font-weight: bold;\">return<\/span><span style=\"color: #666666;\">;<\/span>\n\t<span style=\"color: #666666;\">}<\/span>\n\n\t<span style=\"color: #008000; font-weight: bold;\">if<\/span> <span style=\"color: #666666;\">(<\/span>functionsStack<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">size<\/span><span style=\"color: #666666;\">()<\/span> <span style=\"color: #666666;\">==<\/span> <span style=\"color: #666666;\">0)<\/span>\n\t\t<span style=\"color: #008000; font-weight: bold;\">return<\/span><span style=\"color: #666666;\">;<\/span>\n\n\t<span style=\"color: #b00040;\">int<\/span> nodeType <span style=\"color: #666666;\">=<\/span> node<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">getType<\/span><span style=\"color: #666666;\">();<\/span>\n\n\t<span style=\"color: #408080; font-style: italic;\">\/\/we will track only variables and functions<\/span>\n\t<span style=\"color: #008000; font-weight: bold;\">if<\/span> <span style=\"color: #666666;\">(<\/span>nodeType <span style=\"color: #666666;\">!=<\/span> Token<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">FUNCTION<\/span> <span style=\"color: #666666;\">&amp;&amp;<\/span> nodeType <span style=\"color: #666666;\">!=<\/span> Token<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">VAR<\/span> <span style=\"color: #666666;\">&amp;&amp;<\/span> nodeType <span style=\"color: #666666;\">!=<\/span> Token<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">OBJECTLIT<\/span> <span style=\"color: #666666;\">&amp;&amp;<\/span>\n\t\t\t<span style=\"color: #666666;\">!(<\/span>nodeType <span style=\"color: #666666;\">==<\/span> Token<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">NAME<\/span> <span style=\"color: #666666;\">&amp;&amp;<\/span> node<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">getParent<\/span><span style=\"color: #666666;\">()<\/span> <span style=\"color: #008000; font-weight: bold;\">instanceof<\/span> ObjectProperty<span style=\"color: #666666;\">))<\/span>\n\t<span style=\"color: #666666;\">{<\/span>\n\t\t<span style=\"color: #008000; font-weight: bold;\">if<\/span> <span style=\"color: #666666;\">(<\/span>isVariableName<span style=\"color: #666666;\">(<\/span>node<span style=\"color: #666666;\">))<\/span>\n\t\t<span style=\"color: #666666;\">{<\/span>\n\t\t\t<span style=\"color: #408080; font-style: italic;\">\/\/check if it is in the current function<\/span>\n\t\t\tString symbolName <span style=\"color: #666666;\">=<\/span> <span style=\"color: #666666;\">((<\/span>Name<span style=\"color: #666666;\">)<\/span>node<span style=\"color: #666666;\">).<\/span><span style=\"color: #7d9029;\">getIdentifier<\/span><span style=\"color: #666666;\">();<\/span>\n\t\t\tJSSymbol currentSymContainer <span style=\"color: #666666;\">=<\/span> functionsStack<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">peek<\/span><span style=\"color: #666666;\">();<\/span>\n\t\t\t<span style=\"color: #008000; font-weight: bold;\">if<\/span> <span style=\"color: #666666;\">(!<\/span>currentSymContainer<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">childExist<\/span><span style=\"color: #666666;\">(<\/span>symbolName<span style=\"color: #666666;\">))<\/span>\n\t\t\t<span style=\"color: #666666;\">{<\/span>\n\t\t\t\t<span style=\"color: #408080; font-style: italic;\">\/\/this is a global symbol<\/span>\n\t\t\t\troot<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">addChild<\/span><span style=\"color: #666666;\">(<\/span>node<span style=\"color: #666666;\">);<\/span>\n\t\t\t<span style=\"color: #666666;\">}<\/span>\n\t\t<span style=\"color: #666666;\">}<\/span>\n\t\t<span style=\"color: #008000; font-weight: bold;\">return<\/span><span style=\"color: #666666;\">;<\/span>\n\t<span style=\"color: #666666;\">}<\/span>\n\n\t<span style=\"color: #008000; font-weight: bold;\">if<\/span> <span style=\"color: #666666;\">(<\/span>node<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">getType<\/span><span style=\"color: #666666;\">()<\/span> <span style=\"color: #666666;\">==<\/span> Token<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">VAR<\/span> <span style=\"color: #666666;\">&amp;&amp;<\/span> node <span style=\"color: #008000; font-weight: bold;\">instanceof<\/span> VariableInitializer <span style=\"color: #666666;\">==<\/span> <span style=\"color: #008000; font-weight: bold;\">false<\/span><span style=\"color: #666666;\">)<\/span>\n\t\t<span style=\"color: #008000; font-weight: bold;\">return<\/span><span style=\"color: #666666;\">;<\/span>\n\n\tJSSymbol currSym <span style=\"color: #666666;\">=<\/span> <span style=\"color: #008000; font-weight: bold;\">null<\/span><span style=\"color: #666666;\">;<\/span>\n\n\tJSSymbol parent <span style=\"color: #666666;\">=<\/span> functionsStack<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">peek<\/span><span style=\"color: #666666;\">();<\/span>\n\t<span style=\"color: #008000; font-weight: bold;\">if<\/span> <span style=\"color: #666666;\">(<\/span>parent<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">getNode<\/span><span style=\"color: #666666;\">().<\/span><span style=\"color: #7d9029;\">getAbsolutePosition<\/span><span style=\"color: #666666;\">()<\/span> <span style=\"color: #666666;\">+<\/span> parent<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">getNode<\/span><span style=\"color: #666666;\">().<\/span><span style=\"color: #7d9029;\">getLength<\/span><span style=\"color: #666666;\">()<\/span> <span style=\"color: #666666;\">&gt;<\/span> node<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">getAbsolutePosition<\/span><span style=\"color: #666666;\">())<\/span>\n\t<span style=\"color: #666666;\">{<\/span>\n\t\tcurrSym <span style=\"color: #666666;\">=<\/span> <span style=\"color: #008000; font-weight: bold;\">new<\/span> JSSymbol<span style=\"color: #666666;\">(<\/span>node<span style=\"color: #666666;\">);<\/span>\n\t\tparent<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">addChild<\/span><span style=\"color: #666666;\">(<\/span>currSym<span style=\"color: #666666;\">);<\/span>\n\t<span style=\"color: #666666;\">}<\/span>\n\t<span style=\"color: #008000; font-weight: bold;\">else<\/span> <span style=\"color: #408080; font-style: italic;\">\/\/outside current function boundary<\/span>\n\t<span style=\"color: #666666;\">{<\/span>\n\t\t<span style=\"color: #408080; font-style: italic;\">\/\/pop current parent<\/span>\n\t\tfunctionsStack<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">pop<\/span><span style=\"color: #666666;\">();<\/span>\n\t\taddToParent<span style=\"color: #666666;\">(<\/span>node<span style=\"color: #666666;\">);<\/span>\n\t\t<span style=\"color: #008000; font-weight: bold;\">return<\/span><span style=\"color: #666666;\">;<\/span>\n\t<span style=\"color: #666666;\">}<\/span>\n\n\t<span style=\"color: #408080; font-style: italic;\">\/\/currSym is already set above<\/span>\n\t<span style=\"color: #008000; font-weight: bold;\">if<\/span> <span style=\"color: #666666;\">(<\/span>nodeType <span style=\"color: #666666;\">==<\/span> Token<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">FUNCTION<\/span> <span style=\"color: #666666;\">||<\/span> nodeType <span style=\"color: #666666;\">==<\/span> Token<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">OBJECTLIT<\/span><span style=\"color: #666666;\">)<\/span>\n\t<span style=\"color: #666666;\">{<\/span>\n\t\tAstNode parentNode <span style=\"color: #666666;\">=<\/span> node<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">getParent<\/span><span style=\"color: #666666;\">();<\/span>\n\t\tAstNode leftNode <span style=\"color: #666666;\">=<\/span> <span style=\"color: #008000; font-weight: bold;\">null<\/span><span style=\"color: #666666;\">;<\/span>\n\t\t<span style=\"color: #008000; font-weight: bold;\">if<\/span> <span style=\"color: #666666;\">(<\/span>parentNode<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">getType<\/span><span style=\"color: #666666;\">()<\/span> <span style=\"color: #666666;\">==<\/span> Token<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">ASSIGN<\/span><span style=\"color: #666666;\">)<\/span>\n\t\t<span style=\"color: #666666;\">{<\/span>\n\t\t\tleftNode <span style=\"color: #666666;\">=<\/span> <span style=\"color: #666666;\">((<\/span>Assignment<span style=\"color: #666666;\">)<\/span>parentNode<span style=\"color: #666666;\">).<\/span><span style=\"color: #7d9029;\">getLeft<\/span><span style=\"color: #666666;\">();<\/span>\n\t\t<span style=\"color: #666666;\">}<\/span>\n\t\t<span style=\"color: #008000; font-weight: bold;\">else<\/span> <span style=\"color: #0000ff;\">if<\/span> <span style=\"color: #666666;\">(<\/span>parentNode <span style=\"color: #008000; font-weight: bold;\">instanceof<\/span> ObjectProperty<span style=\"color: #666666;\">)<\/span>\n\t\t<span style=\"color: #666666;\">{<\/span>\n\t\t\tleftNode <span style=\"color: #666666;\">=<\/span> <span style=\"color: #666666;\">((<\/span>ObjectProperty<span style=\"color: #666666;\">)<\/span>parentNode<span style=\"color: #666666;\">).<\/span><span style=\"color: #7d9029;\">getLeft<\/span><span style=\"color: #666666;\">();<\/span>\n\t\t<span style=\"color: #666666;\">}<\/span>\n\n\t\t<span style=\"color: #008000; font-weight: bold;\">if<\/span> <span style=\"color: #666666;\">(<\/span>leftNode <span style=\"color: #008000; font-weight: bold;\">instanceof<\/span> Name<span style=\"color: #666666;\">)<\/span>\n\t\t\tcurrSym<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">setName<\/span><span style=\"color: #666666;\">(((<\/span>Name<span style=\"color: #666666;\">)<\/span>leftNode<span style=\"color: #666666;\">).<\/span><span style=\"color: #7d9029;\">getIdentifier<\/span><span style=\"color: #666666;\">());<\/span>\n\n\t\tfunctionsStack<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">push<\/span><span style=\"color: #666666;\">(<\/span>currSym<span style=\"color: #666666;\">);<\/span>\n\t\tcurrentFuncEndOffset <span style=\"color: #666666;\">=<\/span> node<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">getAbsolutePosition<\/span><span style=\"color: #666666;\">()<\/span> <span style=\"color: #666666;\">+<\/span> node<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">getLength<\/span><span style=\"color: #666666;\">();<\/span>\n\t<span style=\"color: #666666;\">}<\/span>\n<span style=\"color: #666666;\">}<\/span><\/pre>\n<\/div>\n<p>The above function uses Stack to keep track of current parent symbol (function or Object). It checks if the node being processed is child of the symbol at the top of <span style=\"margin: 0; line-height: 125%;\">functionsStack<\/span> by comparing node&#8217;s absolute position (AstNode.getAbsolutePosition) with end offset of the current (top) symbol. Since AST is visited in depth first manner, this logic works fine.<\/p>\n<p>Remaining code in this program is quite simple. <a href=\"http:\/\/ramkulkarni.com\/temp\/2014-04-04\/RhinoParserDemo.zip\" target=\"_blank\">Download Eclipse project for this program<\/a> if you use Eclipse.<\/p>\n<p>Again, I do not guarantee that the program will create error-free symbol hierarchy At best, use this code as a reference and modify it to suit your requirements. It is just one of the ways to create symbol heirachy and there could be better ways.<\/p>\n<p>-Ram Kulkarni<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last year I had blogged &#8220;Understanding AST created by Mozilla Rhino parser&#8220;, where I exaplained how to traverse AST to get all functions and variables. Since then I have received some comments, public and private, to provide sample code. So here is an example of how to parse JavaScript code and get all functions and &hellip; <\/p>\n<p class=\"link-more\"><a href=\"http:\/\/ramkulkarni.com\/blog\/parsing-javascript-code-using-mozilla-rhino\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Parsing JavaScript code using Mozilla Rhino&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"Parsing JavaScript code using #Mozilla #Rhino http:\/\/wp.me\/p2g9O8-jw","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[20,76,1],"tags":[5,67,101],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2g9O8-jw","jetpack-related-posts":[],"_links":{"self":[{"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/posts\/1210"}],"collection":[{"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/comments?post=1210"}],"version-history":[{"count":0,"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/posts\/1210\/revisions"}],"wp:attachment":[{"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/media?parent=1210"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/categories?post=1210"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/tags?post=1210"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}