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); }
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("')"); }
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(')'); }
/// <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)); }