ScriptObjectTransformer.java 8.81 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  org.mozilla.javascript.CompilerEnvirons
 *  org.mozilla.javascript.EvaluatorException
 *  org.mozilla.javascript.Parser
 *  org.mozilla.javascript.ast.ArrayLiteral
 *  org.mozilla.javascript.ast.AstNode
 *  org.mozilla.javascript.ast.AstRoot
 *  org.mozilla.javascript.ast.FunctionCall
 *  org.mozilla.javascript.ast.FunctionNode
 *  org.mozilla.javascript.ast.KeywordLiteral
 *  org.mozilla.javascript.ast.Name
 *  org.mozilla.javascript.ast.NewExpression
 *  org.mozilla.javascript.ast.NodeVisitor
 *  org.mozilla.javascript.ast.PropertyGet
 *  org.mozilla.javascript.ast.VariableInitializer
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.forms.transformer;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import org.mozilla.javascript.CompilerEnvirons;
import org.mozilla.javascript.EvaluatorException;
import org.mozilla.javascript.Parser;
import org.mozilla.javascript.ast.ArrayLiteral;
import org.mozilla.javascript.ast.AstNode;
import org.mozilla.javascript.ast.AstRoot;
import org.mozilla.javascript.ast.FunctionCall;
import org.mozilla.javascript.ast.FunctionNode;
import org.mozilla.javascript.ast.KeywordLiteral;
import org.mozilla.javascript.ast.Name;
import org.mozilla.javascript.ast.NewExpression;
import org.mozilla.javascript.ast.NodeVisitor;
import org.mozilla.javascript.ast.PropertyGet;
import org.mozilla.javascript.ast.VariableInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ScriptObjectTransformer {
    private static Logger logger = LoggerFactory.getLogger(ScriptObjectTransformer.class);

    public String transformScriptTextToScriptObject(String sScriptText) {
        CompilerEnvirons compileEnv = new CompilerEnvirons();
        compileEnv.setRecordingComments(false);
        compileEnv.setStrictMode(false);
        Parser p = new Parser(compileEnv);
        AstRoot astRoot = null;
        try {
            astRoot = p.parse(sScriptText, null, 0);
        }
        catch (EvaluatorException e) {
            logger.error("Error while parsing scriptText: " + sScriptText, (Throwable)e);
            throw e;
        }
        XfaScriptVisitor scriptVisitor = new XfaScriptVisitor();
        astRoot.visit((NodeVisitor)scriptVisitor);
        String scriptObject = scriptVisitor.getScriptMembers();
        scriptObject = "return Object.defineProperties((baseObject || {}),  { \n" + scriptObject + " \n}); \n";
        ScopeConvertorVisitor scopeVisitor = new ScopeConvertorVisitor(scriptVisitor.getFunctionsMap(), scriptVisitor.getVariablesMap());
        astRoot.visit((NodeVisitor)scopeVisitor);
        String transformedScript = "function(baseObject){ \nvar self = this;\nfunction getContext(context, prop) {\n\tif (prop in context) {\n\t\treturn context;\n\t} else {\n\t\treturn baseObject;\n\t}\n}\n" + astRoot.toSource() + " \n" + scriptVisitor.getTempFunctions() + " \n" + scriptObject + "\n" + "}\n";
        return transformedScript;
    }

    protected static class ScopeConvertorVisitor
    implements NodeVisitor {
        private Hashtable<String, String> functions;
        private Hashtable<String, String> variables;

        public ScopeConvertorVisitor(Hashtable<String, String> funcs, Hashtable<String, String> vars) {
            this.functions = funcs;
            this.variables = vars;
        }

        public void addThisToArgs(FunctionCall callNode) {
            List args = callNode.getArguments();
            ArrayList<Object> newargs = new ArrayList<Object>();
            newargs.add(0, (Object)new Name(0, "this"));
            if (args.size() > 0) {
                ArrayLiteral oldargs = new ArrayLiteral();
                oldargs.setElements(args);
                newargs.add((Object)oldargs);
            }
            callNode.setArguments(newargs);
        }

        public boolean visit(AstNode node) {
            if (node instanceof FunctionCall && !(node instanceof NewExpression)) {
                String fnName;
                Name nm;
                FunctionCall callNode = (FunctionCall)node;
                AstNode target = callNode.getTarget();
                if (target instanceof Name && this.functions.get(fnName = (nm = (Name)target).getIdentifier()) != null) {
                    nm.setIdentifier(fnName + ".apply");
                    this.addThisToArgs(callNode);
                }
            } else if (node instanceof PropertyGet) {
                PropertyGet getter = (PropertyGet)node;
                AstNode accessor = getter.getTarget();
                Name idName = getter.getProperty();
                if (accessor instanceof KeywordLiteral) {
                    KeywordLiteral nm = (KeywordLiteral)accessor;
                    String str = idName.getIdentifier();
                    if (nm.getType() == 43) {
                        if (this.functions.get(str) != null) {
                            getter.setTarget((AstNode)new Name(0, "getContext(this,'" + str + "')"));
                            getter.setProperty(new Name(0, str + ".apply"));
                            this.addThisToArgs((FunctionCall)getter.getParent());
                        } else if (this.variables.get(str) != null) {
                            getter.setTarget((AstNode)new Name(0, "getContext(this,'" + str + "')"));
                        }
                    }
                }
            }
            return true;
        }
    }

    protected static class XfaScriptVisitor
    implements NodeVisitor {
        private StringBuilder buffer = new StringBuilder();
        private Hashtable<String, String> functions = new Hashtable();
        private Hashtable<String, String> variables = new Hashtable();
        private int functionLevel = 0;
        private StringBuilder tmp_functions_buffer = new StringBuilder();

        protected XfaScriptVisitor() {
        }

        public String getScriptMembers() {
            return this.buffer.toString();
        }

        public Hashtable<String, String> getFunctionsMap() {
            return this.functions;
        }

        public Hashtable<String, String> getVariablesMap() {
            return this.variables;
        }

        public String getTempFunctions() {
            return this.tmp_functions_buffer.toString();
        }

        public boolean visit(AstNode node) {
            if (node instanceof VariableInitializer || node instanceof FunctionNode) {
                String identifier = null;
                String modifiedIdentifier = null;
                if (node instanceof VariableInitializer && this.functionLevel == 0) {
                    VariableInitializer varNode = (VariableInitializer)node;
                    if (varNode.getTarget() instanceof Name && ((Name)varNode.getTarget()).getIdentifier() != null) {
                        identifier = ((Name)varNode.getTarget()).getIdentifier();
                    }
                    modifiedIdentifier = identifier;
                    this.variables.put(identifier, modifiedIdentifier);
                } else if (node instanceof FunctionNode) {
                    FunctionNode functionNode = (FunctionNode)node;
                    if (functionNode.getFunctionName() != null && functionNode.getFunctionName().getIdentifier() != null) {
                        identifier = functionNode.getFunctionName().getIdentifier();
                    }
                    ++this.functionLevel;
                    functionNode.getBody().visit((NodeVisitor)this);
                    --this.functionLevel;
                    if (identifier != null && identifier.length() > 0) {
                        modifiedIdentifier = identifier + "_bindParent";
                        this.tmp_functions_buffer.append("\nfunction " + modifiedIdentifier + "() {\n");
                        this.tmp_functions_buffer.append("    return " + identifier + ".apply(self,arguments);\n");
                        this.tmp_functions_buffer.append("}\n");
                        this.functions.put(identifier, modifiedIdentifier);
                    } else {
                        modifiedIdentifier = identifier;
                    }
                }
                if (identifier != null && identifier.length() > 0) {
                    if (this.buffer.length() > 0) {
                        this.buffer.append(",\n");
                    }
                    this.buffer.append(identifier + " : { \n");
                    this.buffer.append("    get : function() { return " + modifiedIdentifier + " ; }");
                    if (node instanceof VariableInitializer) {
                        this.buffer.append(",\n");
                        this.buffer.append("    set : function(mValue) { " + identifier + " = mValue; }");
                    }
                    this.buffer.append(" \n}");
                }
                return false;
            }
            return true;
        }
    }

}