Example #1
0
        private static int PrintSourceString(string source, int offset, bool asQuotedString, System.Text.StringBuilder sb)
        {
            int length = source [offset];

            ++offset;
            if ((0x8000 & length) != 0)
            {
                length = ((0x7FFF & length) << 16) | source [offset];
                ++offset;
            }
            if (sb != null)
            {
                string str = source.Substring(offset, (offset + length) - (offset));
                if (!asQuotedString)
                {
                    sb.Append(str);
                }
                else
                {
                    sb.Append('"');
                    sb.Append(ScriptRuntime.escapeString(str));
                    sb.Append('"');
                }
            }
            return(offset + length);
        }
Example #2
0
 private static void toSourceImpl(string uri, string localName, string prefix, System.Text.StringBuilder sb)
 {
     sb.Append("new QName(");
     if (uri == null && prefix == null)
     {
         if (!"*".Equals(localName))
         {
             sb.Append("null, ");
         }
     }
     else
     {
         Namespace.toSourceImpl(prefix, uri, sb);
         sb.Append(", ");
     }
     sb.Append('\'');
     sb.Append(ScriptRuntime.escapeString(localName, '\''));
     sb.Append("')");
 }
Example #3
0
 internal static void toSourceImpl(string prefix, string uri, System.Text.StringBuilder sb)
 {
     sb.Append("new Namespace(");
     if (uri.Length == 0)
     {
         if (!"".Equals(prefix))
         {
             throw new System.ArgumentException(prefix);
         }
     }
     else
     {
         sb.Append('\'');
         if (prefix != null)
         {
             sb.Append(ScriptRuntime.escapeString(prefix, '\''));
             sb.Append("', '");
         }
         sb.Append(ScriptRuntime.escapeString(uri, '\''));
         sb.Append('\'');
     }
     sb.Append(')');
 }
Example #4
0
        /// <summary> Decompile the source information associated with this js
        /// function/script back into a string.  For the most part, this
        /// just means translating tokens back to their string
        /// representations; there's a little bit of lookahead logic to
        /// decide the proper spacing/indentation.  Most of the work in
        /// mapping the original source to the prettyprinted decompiled
        /// version is done by the parser.
        ///
        /// </summary>
        /// <param name="source">encoded source tree presentation
        ///
        /// </param>
        /// <param name="flags">flags to select output format
        ///
        /// </param>
        /// <param name="properties">indentation properties
        ///
        /// </param>
        public static string Decompile(string source, int flags, UintMap properties)
        {
            int length = source.Length;

            if (length == 0)
            {
                return("");
            }

            int indent = properties.getInt(INITIAL_INDENT_PROP, 0);

            if (indent < 0)
            {
                throw new ArgumentException();
            }
            int indentGap = properties.getInt(INDENT_GAP_PROP, 4);

            if (indentGap < 0)
            {
                throw new ArgumentException();
            }
            int caseGap = properties.getInt(CASE_GAP_PROP, 2);

            if (caseGap < 0)
            {
                throw new ArgumentException();
            }

            System.Text.StringBuilder result = new System.Text.StringBuilder();
            bool justFunctionBody            = (0 != (flags & Decompiler.ONLY_BODY_FLAG));
            bool toSource = (0 != (flags & Decompiler.TO_SOURCE_FLAG));
            bool toString = (0 != (flags & Decompiler.TO_STRING_FLAG));

            // Spew tokens in source, for debugging.
            // as TYPE number char
            if (printSource)
            {
                System.Console.Error.WriteLine("length:" + length);
                for (int i = 0; i < length; ++i)
                {
                    // Note that tokenToName will fail unless Context.printTrees
                    // is true.
                    string tokenname = null;
                    if (Token.printNames)
                    {
                        tokenname = Token.name(source [i]);
                    }
                    if (tokenname == null)
                    {
                        tokenname = "---";
                    }
                    string pad = tokenname.Length > 7 ? "\t" : "\t\t";
                    System.Console.Error.WriteLine(tokenname + pad + (int)source [i] + "\t'" + ScriptRuntime.escapeString(source.Substring(i, (i + 1) - (i))) + "'");
                }
                System.Console.Error.WriteLine();
            }

            int  braceNesting  = 0;
            bool afterFirstEOL = false;
            int  i2            = 0;
            int  topFunctionType;

            if (source [i2] == Token.SCRIPT)
            {
                ++i2;
                topFunctionType = -1;
            }
            else
            {
                topFunctionType = source [i2 + 1];
            }

            if (!toSource)
            {
                if (!toString)
                {
                    // add an initial newline to exactly match js.
                    result.Append('\n');
                }
                for (int j = 0; j < indent; j++)
                {
                    result.Append(' ');
                }
            }
            else
            {
                if (topFunctionType == FunctionNode.FUNCTION_EXPRESSION)
                {
                    result.Append('(');
                }
            }

            while (i2 < length)
            {
                switch (source [i2])
                {
                case (char)(Token.NAME):
                case (char)(Token.REGEXP):      // re-wrapped in '/'s in parser...
                    i2 = PrintSourceString(source, i2 + 1, false, result);
                    continue;


                case (char)(Token.STRING):
                    i2 = PrintSourceString(source, i2 + 1, true, result);
                    continue;


                case (char)(Token.NUMBER):
                    i2 = PrintSourceNumber(source, i2 + 1, result);
                    continue;


                case (char)(Token.TRUE):
                    result.Append("true");
                    break;


                case (char)(Token.FALSE):
                    result.Append("false");
                    break;


                case (char)(Token.NULL):
                    result.Append("null");
                    break;


                case (char)(Token.THIS):
                    result.Append("this");
                    break;


                case (char)(Token.FUNCTION):
                    ++i2;     // skip function type
                    result.Append("function ");
                    break;


                case (char)(FUNCTION_END):
                    // Do nothing
                    break;


                case (char)(Token.COMMA):
                    result.Append(", ");
                    break;


                case (char)(Token.LC):
                    ++braceNesting;
                    if (Token.EOL == GetNext(source, length, i2))
                    {
                        indent += indentGap;
                    }
                    result.Append('{');
                    break;


                case (char)(Token.RC): {
                    --braceNesting;

                    /* don't print the closing RC if it closes the
                     * toplevel function and we're called from
                     * decompileFunctionBody.
                     */
                    if (justFunctionBody && braceNesting == 0)
                    {
                        break;
                    }

                    result.Append('}');
                    switch (GetNext(source, length, i2))
                    {
                    case Token.EOL:
                    case FUNCTION_END:
                        indent -= indentGap;
                        break;

                    case Token.WHILE:
                    case Token.ELSE:
                        indent -= indentGap;
                        result.Append(' ');
                        break;
                    }
                    break;
                }

                case (char)(Token.LP):
                    result.Append('(');
                    break;


                case (char)(Token.RP):
                    result.Append(')');
                    if (Token.LC == GetNext(source, length, i2))
                    {
                        result.Append(' ');
                    }
                    break;


                case (char)(Token.LB):
                    result.Append('[');
                    break;


                case (char)(Token.RB):
                    result.Append(']');
                    break;


                case (char)(Token.EOL): {
                    if (toSource)
                    {
                        break;
                    }
                    bool newLine = true;
                    if (!afterFirstEOL)
                    {
                        afterFirstEOL = true;
                        if (justFunctionBody)
                        {
                            /* throw away just added 'function name(...) {'
                             * and restore the original indent
                             */
                            result.Length = 0;
                            indent       -= indentGap;
                            newLine       = false;
                        }
                    }
                    if (newLine)
                    {
                        result.Append('\n');
                    }

                    /* add indent if any tokens remain,
                     * less setback if next token is
                     * a label, case or default.
                     */
                    if (i2 + 1 < length)
                    {
                        int less      = 0;
                        int nextToken = source [i2 + 1];
                        if (nextToken == Token.CASE || nextToken == Token.DEFAULT)
                        {
                            less = indentGap - caseGap;
                        }
                        else if (nextToken == Token.RC)
                        {
                            less = indentGap;
                        }

                        /* elaborate check against label... skip past a
                         * following inlined NAME and look for a COLON.
                         */
                        else if (nextToken == Token.NAME)
                        {
                            int afterName = GetSourceStringEnd(source, i2 + 2);
                            if (source [afterName] == Token.COLON)
                            {
                                less = indentGap;
                            }
                        }

                        for (; less < indent; less++)
                        {
                            result.Append(' ');
                        }
                    }
                    break;
                }

                case (char)(Token.DOT):
                    result.Append('.');
                    break;


                case (char)(Token.NEW):
                    result.Append("new ");
                    break;


                case (char)(Token.DELPROP):
                    result.Append("delete ");
                    break;


                case (char)(Token.IF):
                    result.Append("if ");
                    break;


                case (char)(Token.ELSE):
                    result.Append("else ");
                    break;


                case (char)(Token.FOR):
                    result.Append("for ");
                    break;


                case (char)(Token.IN):
                    result.Append(" in ");
                    break;


                case (char)(Token.WITH):
                    result.Append("with ");
                    break;


                case (char)(Token.WHILE):
                    result.Append("while ");
                    break;


                case (char)(Token.DO):
                    result.Append("do ");
                    break;


                case (char)(Token.TRY):
                    result.Append("try ");
                    break;


                case (char)(Token.CATCH):
                    result.Append("catch ");
                    break;


                case (char)(Token.FINALLY):
                    result.Append("finally ");
                    break;


                case (char)(Token.THROW):
                    result.Append("throw ");
                    break;


                case (char)(Token.SWITCH):
                    result.Append("switch ");
                    break;


                case (char)(Token.BREAK):
                    result.Append("break");
                    if (Token.NAME == GetNext(source, length, i2))
                    {
                        result.Append(' ');
                    }
                    break;


                case (char)(Token.CONTINUE):
                    result.Append("continue");
                    if (Token.NAME == GetNext(source, length, i2))
                    {
                        result.Append(' ');
                    }
                    break;


                case (char)(Token.CASE):
                    result.Append("case ");
                    break;


                case (char)(Token.DEFAULT):
                    result.Append("default");
                    break;


                case (char)(Token.RETURN):
                    result.Append("return");
                    if (Token.SEMI != GetNext(source, length, i2))
                    {
                        result.Append(' ');
                    }
                    break;


                case (char)(Token.VAR):
                    result.Append("var ");
                    break;


                case (char)(Token.SEMI):
                    result.Append(';');
                    if (Token.EOL != GetNext(source, length, i2))
                    {
                        // separators in FOR
                        result.Append(' ');
                    }
                    break;


                case (char)(Token.ASSIGN):
                    result.Append(" = ");
                    break;


                case (char)(Token.ASSIGN_ADD):
                    result.Append(" += ");
                    break;


                case (char)(Token.ASSIGN_SUB):
                    result.Append(" -= ");
                    break;


                case (char)(Token.ASSIGN_MUL):
                    result.Append(" *= ");
                    break;


                case (char)(Token.ASSIGN_DIV):
                    result.Append(" /= ");
                    break;


                case (char)(Token.ASSIGN_MOD):
                    result.Append(" %= ");
                    break;


                case (char)(Token.ASSIGN_BITOR):
                    result.Append(" |= ");
                    break;


                case (char)(Token.ASSIGN_BITXOR):
                    result.Append(" ^= ");
                    break;


                case (char)(Token.ASSIGN_BITAND):
                    result.Append(" &= ");
                    break;


                case (char)(Token.ASSIGN_LSH):
                    result.Append(" <<= ");
                    break;


                case (char)(Token.ASSIGN_RSH):
                    result.Append(" >>= ");
                    break;


                case (char)(Token.ASSIGN_URSH):
                    result.Append(" >>>= ");
                    break;


                case (char)(Token.HOOK):
                    result.Append(" ? ");
                    break;


                case (char)(Token.OBJECTLIT):
                    // pun OBJECTLIT to mean colon in objlit property
                    // initialization.
                    // This needs to be distinct from COLON in the general case
                    // to distinguish from the colon in a ternary... which needs
                    // different spacing.
                    result.Append(':');
                    break;


                case (char)(Token.COLON):
                    if (Token.EOL == GetNext(source, length, i2))
                    {
                        // it's the end of a label
                        result.Append(':');
                    }
                    // it's the middle part of a ternary
                    else
                    {
                        result.Append(" : ");
                    }
                    break;


                case (char)(Token.OR):
                    result.Append(" || ");
                    break;


                case (char)(Token.AND):
                    result.Append(" && ");
                    break;


                case (char)(Token.BITOR):
                    result.Append(" | ");
                    break;


                case (char)(Token.BITXOR):
                    result.Append(" ^ ");
                    break;


                case (char)(Token.BITAND):
                    result.Append(" & ");
                    break;


                case (char)(Token.SHEQ):
                    result.Append(" === ");
                    break;


                case (char)(Token.SHNE):
                    result.Append(" !== ");
                    break;


                case (char)(Token.EQ):
                    result.Append(" == ");
                    break;


                case (char)(Token.NE):
                    result.Append(" != ");
                    break;


                case (char)(Token.LE):
                    result.Append(" <= ");
                    break;


                case (char)(Token.LT):
                    result.Append(" < ");
                    break;


                case (char)(Token.GE):
                    result.Append(" >= ");
                    break;


                case (char)(Token.GT):
                    result.Append(" > ");
                    break;


                case (char)(Token.INSTANCEOF):
                    result.Append(" instanceof ");
                    break;


                case (char)(Token.LSH):
                    result.Append(" << ");
                    break;


                case (char)(Token.RSH):
                    result.Append(" >> ");
                    break;


                case (char)(Token.URSH):
                    result.Append(" >>> ");
                    break;


                case (char)(Token.TYPEOF):
                    result.Append("typeof ");
                    break;


                case (char)(Token.VOID):
                    result.Append("void ");
                    break;


                case (char)(Token.NOT):
                    result.Append('!');
                    break;


                case (char)(Token.BITNOT):
                    result.Append('~');
                    break;


                case (char)(Token.POS):
                    result.Append('+');
                    break;


                case (char)(Token.NEG):
                    result.Append('-');
                    break;


                case (char)(Token.INC):
                    result.Append("++");
                    break;


                case (char)(Token.DEC):
                    result.Append("--");
                    break;


                case (char)(Token.ADD):
                    result.Append(" + ");
                    break;


                case (char)(Token.SUB):
                    result.Append(" - ");
                    break;


                case (char)(Token.MUL):
                    result.Append(" * ");
                    break;


                case (char)(Token.DIV):
                    result.Append(" / ");
                    break;


                case (char)(Token.MOD):
                    result.Append(" % ");
                    break;


                case (char)(Token.COLONCOLON):
                    result.Append("::");
                    break;


                case (char)(Token.DOTDOT):
                    result.Append("..");
                    break;


                case (char)(Token.DOTQUERY):
                    result.Append(".(");
                    break;


                case (char)(Token.XMLATTR):
                    result.Append('@');
                    break;


                default:
                    // If we don't know how to decompile it, raise an exception.
                    throw new ApplicationException();
                }
                ++i2;
            }

            if (!toSource)
            {
                // add that trailing newline if it's an outermost function.
                if (!justFunctionBody && !toString)
                {
                    result.Append('\n');
                }
            }
            else
            {
                if (topFunctionType == FunctionNode.FUNCTION_EXPRESSION)
                {
                    result.Append(')');
                }
            }

            return(result.ToString());
        }
        public override object ExecIdCall(IdFunctionObject f, Context cx, IScriptable scope, IScriptable thisObj, object [] args)
        {
            if (!f.HasTag(STRING_TAG))
            {
                return(base.ExecIdCall(f, cx, scope, thisObj, args));
            }
            int id = f.MethodId;

            switch (id)
            {
            case ConstructorId_fromCharCode: {
                int N = args.Length;
                if (N < 1)
                {
                    return("");
                }
                System.Text.StringBuilder sb = new System.Text.StringBuilder(N);
                for (int i = 0; i != N; ++i)
                {
                    sb.Append(ScriptConvert.ToUint16(args [i]));
                }
                return(sb.ToString());
            }


            case Id_constructor: {
                string s = (args.Length >= 1) ? ScriptConvert.ToString(args [0]) : "";
                if (thisObj == null)
                {
                    // new String(val) creates a new String object.
                    return(new BuiltinString(s));
                }
                // String(val) converts val to a string value.
                return(s);
            }


            case Id_toString:
            case Id_valueOf:
                // ECMA 15.5.4.2: 'the toString function is not generic.
                return(RealThis(thisObj, f).m_Value);


            case Id_toSource: {
                string s = RealThis(thisObj, f).m_Value;
                return("(new String(\"" + ScriptRuntime.escapeString(s) + "\"))");
            }


            case Id_charAt:
            case Id_charCodeAt: {
                // See ECMA 15.5.4.[4,5]
                string target = ScriptConvert.ToString(thisObj);
                double pos    = ScriptConvert.ToInteger(args, 0);
                if (pos < 0 || pos >= target.Length)
                {
                    if (id == Id_charAt)
                    {
                        return("");
                    }
                    else
                    {
                        return(double.NaN);
                    }
                }
                char c = target [(int)pos];
                if (id == Id_charAt)
                {
                    return(Convert.ToString(c));
                }
                else
                {
                    return((int)c);
                }
            }


            case Id_indexOf:
                return(js_indexOf(ScriptConvert.ToString(thisObj), args));


            case Id_lastIndexOf:
                return(js_lastIndexOf(ScriptConvert.ToString(thisObj), args));


            case Id_split:
                return(ImplSplit(cx, scope, ScriptConvert.ToString(thisObj), args));


            case Id_substring:
                return(js_substring(cx, ScriptConvert.ToString(thisObj), args));


            case Id_toLowerCase:
                // See ECMA 15.5.4.11
                return(ScriptConvert.ToString(thisObj).ToLower());


            case Id_toUpperCase:
                // See ECMA 15.5.4.12
                return(ScriptConvert.ToString(thisObj).ToUpper());

            case Id_substr:
                return(js_substr(ScriptConvert.ToString(thisObj), args));


            case Id_concat:
                return(js_concat(ScriptConvert.ToString(thisObj), args));


            case Id_slice:
                return(js_slice(ScriptConvert.ToString(thisObj), args));


            case Id_bold:
                return(Tagify(thisObj, "b", null, null));


            case Id_italics:
                return(Tagify(thisObj, "i", null, null));


            case Id_fixed:
                return(Tagify(thisObj, "tt", null, null));


            case Id_strike:
                return(Tagify(thisObj, "strike", null, null));


            case Id_small:
                return(Tagify(thisObj, "small", null, null));


            case Id_big:
                return(Tagify(thisObj, "big", null, null));


            case Id_blink:
                return(Tagify(thisObj, "blink", null, null));


            case Id_sup:
                return(Tagify(thisObj, "sup", null, null));


            case Id_sub:
                return(Tagify(thisObj, "sub", null, null));


            case Id_fontsize:
                return(Tagify(thisObj, "font", "size", args));


            case Id_fontcolor:
                return(Tagify(thisObj, "font", "color", args));


            case Id_link:
                return(Tagify(thisObj, "a", "href", args));


            case Id_anchor:
                return(Tagify(thisObj, "a", "name", args));


            case Id_equals:
            case Id_equalsIgnoreCase: {
                string s1 = ScriptConvert.ToString(thisObj);
                string s2 = ScriptConvert.ToString(args, 0);
                return((id == Id_equals) ? s1.Equals(s2) : s1.ToUpper().Equals(s2.ToUpper()));
            }


            case Id_match:
            case Id_search:
            case Id_replace: {
                RegExpActions actionType;
                if (id == Id_match)
                {
                    actionType = EcmaScript.NET.RegExpActions.Match;
                }
                else if (id == Id_search)
                {
                    actionType = EcmaScript.NET.RegExpActions.Search;
                }
                else
                {
                    actionType = EcmaScript.NET.RegExpActions.Replace;
                }
                return(cx.regExpProxy.Perform(cx, scope, thisObj, args, actionType));
            }
            }
            throw new ArgumentException(Convert.ToString(id));
        }