/// <summary> Returns an array of all ids from an object and its prototypes. /// <p> /// </summary> /// <param name="obj">a JavaScript object /// </param> /// <returns> an array of all ids from all object in the prototype chain. /// If a given id occurs multiple times in the prototype chain, /// it will occur only once in this list. /// </returns> public static object [] GetPropertyIds (IScriptable obj) { if (obj == null) { return ScriptRuntime.EmptyArgs; } object [] result = obj.GetIds (); ObjToIntMap map = null; for (; ; ) { obj = obj.GetPrototype (); if (obj == null) { break; } object [] ids = obj.GetIds (); if (ids.Length == 0) { continue; } if (map == null) { if (result.Length == 0) { result = ids; continue; } map = new ObjToIntMap (result.Length + ids.Length); for (int i = 0; i != result.Length; ++i) { map.intern (result [i]); } result = null; // Allow to GC the result } for (int i = 0; i != ids.Length; ++i) { map.intern (ids [i]); } } if (map != null) { result = map.getKeys (); } return result; }
private static void toStringTreeHelper(ScriptOrFnNode treeTop, Node n, ObjToIntMap printIds, int level, System.Text.StringBuilder sb) { if (Token.printTrees) { if (printIds == null) { printIds = new ObjToIntMap (); generatePrintIds (treeTop, printIds); } for (int i = 0; i != level; ++i) { sb.Append (" "); } n.toString (printIds, sb); sb.Append ('\n'); for (Node cursor = n.FirstChild; cursor != null; cursor = cursor.Next) { if (cursor.Type == Token.FUNCTION) { int fnIndex = cursor.getExistingIntProp (Node.FUNCTION_PROP); FunctionNode fn = treeTop.getFunctionNode (fnIndex); toStringTreeHelper (fn, fn, null, level + 1, sb); } else { toStringTreeHelper (treeTop, cursor, printIds, level + 1, sb); } } } }
private void toString(ObjToIntMap printIds, System.Text.StringBuilder sb) { if (Token.printTrees) { sb.Append (Token.name (this.Type)); if (this is StringNode) { sb.Append (' '); sb.Append (String); } else if (this is ScriptOrFnNode) { ScriptOrFnNode sof = (ScriptOrFnNode)this; if (this is FunctionNode) { FunctionNode fn = (FunctionNode)this; sb.Append (' '); sb.Append (fn.FunctionName); } sb.Append (" [source name: "); sb.Append (sof.SourceName); sb.Append ("] [encoded source length: "); sb.Append (sof.EncodedSourceEnd - sof.EncodedSourceStart); sb.Append ("] [base line: "); sb.Append (sof.BaseLineno); sb.Append ("] [end line: "); sb.Append (sof.EndLineno); sb.Append (']'); } else if (this is Jump) { Jump jump = (Jump)this; if (this.Type == Token.BREAK || this.Type == Token.CONTINUE) { sb.Append (" [label: "); appendPrintId (jump.JumpStatement, printIds, sb); sb.Append (']'); } else if (this.Type == Token.TRY) { Node catchNode = jump.target; Node finallyTarget = jump.Finally; if (catchNode != null) { sb.Append (" [catch: "); appendPrintId (catchNode, printIds, sb); sb.Append (']'); } if (finallyTarget != null) { sb.Append (" [finally: "); appendPrintId (finallyTarget, printIds, sb); sb.Append (']'); } } else if (this.Type == Token.LABEL || this.Type == Token.LOOP || this.Type == Token.SWITCH) { sb.Append (" [break: "); appendPrintId (jump.target, printIds, sb); sb.Append (']'); if (this.Type == Token.LOOP) { sb.Append (" [continue: "); appendPrintId (jump.Continue, printIds, sb); sb.Append (']'); } } else { sb.Append (" [target: "); appendPrintId (jump.target, printIds, sb); sb.Append (']'); } } else if (this.Type == Token.NUMBER) { sb.Append (' '); sb.Append (Double); } else if (this.Type == Token.TARGET) { sb.Append (' '); appendPrintId (this, printIds, sb); } if (lineno != -1) { sb.Append (' '); sb.Append (lineno); } for (PropListItem x = propListHead; x != null; x = x.next) { int Type = x.Type; sb.Append (" ["); sb.Append (propToString (Type)); sb.Append (": "); string value; switch (Type) { case TARGETBLOCK_PROP: // can't add this as it recurses value = "target block property"; break; case LOCAL_BLOCK_PROP: // can't add this as it is dull value = "last local block"; break; case ISNUMBER_PROP: switch (x.intValue) { case BOTH: value = "both"; break; case RIGHT: value = "right"; break; case LEFT: value = "left"; break; default: throw Context.CodeBug (); } break; case SPECIALCALL_PROP: switch (x.intValue) { case SPECIALCALL_EVAL: value = "eval"; break; case SPECIALCALL_WITH: value = "with"; break; default: // NON_SPECIALCALL should not be stored throw Context.CodeBug (); } break; default: object obj = x.objectValue; if (obj != null) { value = obj.ToString (); } else { value = Convert.ToString (x.intValue); } break; } sb.Append (value); sb.Append (']'); } } }
private static void generatePrintIds(Node n, ObjToIntMap map) { if (Token.printTrees) { map.put (n, map.size ()); for (Node cursor = n.FirstChild; cursor != null; cursor = cursor.Next) { generatePrintIds (cursor, map); } } }
private static void appendPrintId(Node n, ObjToIntMap printIds, System.Text.StringBuilder sb) { if (Token.printTrees) { if (n != null) { int id = printIds.Get (n, -1); sb.Append ('#'); if (id != -1) { sb.Append (id + 1); } else { sb.Append ("<not_available>"); } } } }
private void ChangeObject () { object [] ids = null; while (obj != null) { ids = obj.GetIds (); if (ids.Length != 0) { break; } obj = obj.GetPrototype (); } if (obj != null && this.ids != null) { object [] previous = this.ids; int L = previous.Length; if (used == null) { used = new ObjToIntMap (L); } for (int i = 0; i != L; ++i) { used.intern (previous [i]); } } this.ids = ids; this.index = 0; }
internal Iterator (ObjToIntMap master) { this.master = master; }
internal Iterator(ObjToIntMap master) { this.master = master; }