Универсальный трейсер.
Недавно был здесь ( на флешере ) блог MikroAcse на тему трейсов непростых объектов ( или объектов непростого типа). Там он приводил сыренький скрипт такого трейса, а в постах были интересные комментарии и подсказки. Блога нет, и скрипт он кажется до ума не довёл.
Когда я начал работать с социальными сетями такой плагинчик мне стал нужен, т.к. не все объекты можно "пощупать" через консоли, ведь консоли обычно привязаны к отображаемым объектам, а у меня, например, вьюер не имеет ссылки на контроллер и провайдер данных, ну и прочее. В общем нужен стал. Чужое во-первых искать не охота, во-вторых юзать незнакомый плагин не комфортно, в-третьих интересно было самому сделать
такой, хоть и "велосипед" - да, да, я знаю ).
Ниже код того, что у меня получилось. Можно регулировать "глубину просмотра" объектов соотв. параметром,
можно запретить "парсить" экземпляры классов (т.к. нативные классы содержат много, возможно, ненужной информации - если таких объектов много, то это просто катастрофа будет), если парсинг экземпляров классов отключен, то парситься будет лишь тот экземпляр класса который и был передан в аргументах вызова метода Dumper.dump(). Можно включать/отключать определение простых типов. XML- объекты не парсятся, лишь обозначаются, т.к. хмл документы могут быть ( и обычно бывают ) достаточно большими, и помимо этого они простым трейсом хорошо просматриваются я решил исключить их содержимое из выдачи, может быть потом передумаю - опыт покажет ).
И кстати, трейсер этот ничего, на самом деле, не трейсит. Он возвращает отформатированную строку, с переносами и табуляцией. Во-первых это удобно мне, т.к. я использую для установки трейса в программе снипет такого вида:
Код:
///TODO trace ////////////////////////// T R A C E /////////////////////////////// var d:Date = new Date(); trace(d.valueOf() + ". $(TypName)::$(MbrName)() : " + $(EntryPoint)); //////////////////////// E N D T R A C E //////////////////////////
то будет непонятно - где именно происходит обращение. Ну и во-вторых, такую строку не обязательно выводить в трейс, можно и в консоль отправить если с ней удобнее работать.
Из косяков: немного "едет" табуляция, попозже проверю, уже сейчас некогда, и я не уверен что правильно
расчитывается "глубина" просмотра когда дело касается экземпляров классов на которые ссылаются перем.
изучаемого объекта, это тоже попозже хочу проверить...
Внимание! Класс не умеет обрабатывать объекты с циклическими ссылками ( когда объект ссылается сам на себя в своих полях и подобное ).
update 28.05.12
///******************************************************************** ///* Copyright © 2012 fishr (fishr.flash@gmail.com) ///******************************************************************** package su.fishr.utils { import flash.utils.*; /** * Возвращает форматированную строку, с перечислением * доступных полей, акцессоров и их значений объекта ссылка на который * получена в аргументах единственного публичного метода. * * @playerversion Flash 10 * @langversion 3.0 * @author fishr * @created 20.05.2012 1:11 * @since 20.05.2012 1:11 */ final public class Dumper { static private var _timeDie:int; static private const _MAX_TIME_DIE:int = 200; /**------------------------------------------------------------------------------- * * P U B L I C * * -------------------------------------------------------------------------------- */ //{ public function Dumper() { throw( new Error( "Not create exemplar this" ) ); } /** * Имеет один обязательный параметр - объект любого сложного или простого типа. * Возвращает форматированную строку, с переносами и табуляцей, в которой перечислены * все доступные поля, акцессоры и их значения обнаруженные в полученном по ссылке в * аргументах вызова объекте. * * <P> * <P> * <B>Важно!</B> * <I>Класс не умеет обрабатывать циклические ссылки ( когда объект ссылается сам на себя в своих * полях и т.п. ). Для предотвращения зацикливания время непрерывной работы скрипта ограничивается * значением константы _MAX_TIME_DIE * </I> * </P> * * <P> * <B>Примечание.</B> Так как переменные числовых типов утрачивают первоначальный тип. * Обнаруженные поля числовых типов описываются следующим образом: * - если значение - целое число в диапазоне <CODE>int</CODE> оно характерезуется типом <CODE>int</CODE>, * - если значение - целое положительное число за диапазоном <CODE>int</CODE> (но меньше <CODE>uint.MAX_VALUE</CODE> )оно характерезуется типом <CODE>uint</CODE>, * - во всех остальных случаях числа описываются типом <CODE>number</CODE>. * </P> * * <B>Примечание.</B> Данные xml-типов не разбираются, только указывается тип таких данных. * * <P> * * <B>Примечание.</B> В круглых скобках указывается тип поля, если этот тип - строка или числовой тип далее * следуют цифры, которые при строковом типе указывают длину строки, в числовом кол-во цифр целой и дробной части числа * в формате: целая_часть[.дробная_часть]. * </P> * * <P> * * <B>Примечание.</B> Максимальная длительность непрерывной обработки - 0.512 секунды. Максимальная длина возвращаемой строки - 1024 символов. * </P> * * <P> * * <B>Примечание.</B> Парсинг ссылок на классы в полях DisplayObject-ов находящихся в списке отображения не выполняется. * </P> * * @param arg объект любого типа информацию о доступных полях которого нужно получить * @param onType ( default: true ) флаг указывающий следует ли указывать тип возвращаемых данных * @param level ( default: -1 ) "глубина" просмотра вложенных объектов обнаруженных в разбираемом объекте * @param openClasses ( default: false ) нужно ли разбирать поля вложенных объектов со статическим типом данных, * т.к. экземпляры нативных классов могут содержать данные о своих полях довольно внушительного объёма * этот параметр по умолчанию отключен. * @return форматированную строку содержащую инофрмацию об обнаруженных доступных полях объекта переданного * в аргументах вызова метода. */ static public function dump( arg:*, level:int = -1, onType:Boolean = true, openClasses:Boolean = false ):String { if ( !arg ) return "No object body"; var result:String; if( !_timeDie ) _timeDie = getTimer(); if ( typeof arg !== "object" ) { result = " value = ( " + analisisSimple( arg ) + " ) " + arg; _timeDie = 0; return result; } else { if ( arg.hasOwnProperty( "stage" ) && arg.stage !== null) openClasses = false; result = analisisObject( arg, onType, level, "\r", openClasses, true); _timeDie = 0; return result; } } //} /**------------------------------------------------------------------------------- * * P R I V A T E * * -------------------------------------------------------------------------------- */ //{ static private function dumpArray( arr:Array, onType:Boolean, level:int, space:String, openClasses:Boolean ):String { if ( level === 0 ) return "Array " + ( onType?"( " + arr.length + " )":"" ) + " /limiting level.../" ; else level --; const timer:int = getTimer(); if ( timer > _timeDie + _MAX_TIME_DIE ) return " too long processing... "; var parseArray:String = "Array" + ( onType?"(" + arr.length + "):":":" ); var stepSpace:String = space + "\t"; var type:String; var descript:String; for ( var nm:String in arr ) { if ( typeof arr[ nm ] !== "object" ) { const typingValue:String = analisisSimple( arr[ nm ] ); descript = stepSpace + "[" + nm + "] => " + ( onType?"(" + typingValue + ") ":"" ); parseArray += descript + ( ( typingValue === "xml" )?"/not shown.../":arr[ nm ] ); } else { descript = stepSpace + "[" + nm + "] => "; parseArray += descript + analisisObject( arr[ nm ], onType, level, stepSpace, openClasses ) ; } } return parseArray; } static private function dumpObject( arg:Object , onType:Boolean, level:int, space:String, openClasses:Boolean ):String { if ( level === 0 ) return "Object /limiting level.../" ; else level --; const timer:int = getTimer(); if ( timer > _timeDie + _MAX_TIME_DIE ) return " too long processing... "; var parseObject:String = "Object"; var parseContent:String = ""; var stepSpace:String = space + "\t"; var type:String; var descript:String; var countElems:int = 0; for ( var nm:String in arg ) { if ( typeof arg[ nm ] !== "object" ) { const typingValue:String = analisisSimple( arg[ nm ] ); descript = stepSpace + "" + nm + ":" + ( onType?"(" + typingValue + ") ":"" ) parseContent += descript + ( ( typingValue === "xml" )?"/not shown.../":arg[ nm ] ); } else { descript = stepSpace + "" + nm + ":"; parseContent += descript + analisisObject( arg[ nm ], onType, level, stepSpace, openClasses ) ; } countElems++; } parseObject += " (" + countElems + "): " + parseContent; return parseObject; } static private function dumpClass( arg:*, onType:Boolean, level:int, space:String, openClasses:Boolean ):String { if ( level === 0 ) return arg.toString() + " /limiting level.../"; else level--; const timer:int = getTimer(); if ( timer > _timeDie + _MAX_TIME_DIE ) return " too long processing... "; var parseClass:String = arg.toString() + ": "; var stepSpace:String = space + "\t"; var type:String; const xmlDescription:XML = describeType( arg ); const variables:XMLList = xmlDescription.variable; const accessors:XMLList = xmlDescription.accessor; const constant:XMLList = xmlDescription.constant; const method:XMLList = xmlDescription.method; ///variables var descript:String = "variables"; parseClass += stepSpace + descript; stepSpace += "\t"; var contenVar:String = ""; var countElems:int = 0; for each ( var publicVar:XML in variables ) { if ( typeof arg[ publicVar.@name ] !== "object" ) { const typeVar:String = analisisSimple( arg[ publicVar.@name ] ); descript = stepSpace + "" + publicVar.@name + " = " + ( onType?"(" + typeVar + ") ":"" ) contenVar += descript + ( ( typeVar === "xml" )?"/not shown.../":( arg[ publicVar.@name ] ) ); } else { descript = stepSpace + " " + publicVar.@name + " = "; contenVar += ( arg[ publicVar.@name ] === null || arg[ publicVar.@name ] === undefined)? descript + ( onType?"(" + publicVar.@type + ",0)":"" ) + arg[ publicVar.@name ]: descript + analisisObject( arg[ publicVar.@name ], onType, level, stepSpace, openClasses); } countElems++; } parseClass += " (" + countElems + "): " + contenVar; ///constants descript = "constants"; stepSpace = space + "\t"; parseClass += stepSpace + descript; var contentConst:String = ""; countElems = 0; stepSpace += new Array( descript.length ).join( " " ); for each ( var publicConst:XML in constant ) { if ( typeof arg[ publicConst.@name ] !== "object" ) { const typeConst:String = analisisSimple( arg[ publicConst.@name ] ); descript = stepSpace + "" + publicConst.@name + " = " + ( onType?"(" + typeConst + ") ":"" ) contentConst += descript + ( ( typeConst === "xml" )?"/not shown.../":( arg[ publicConst.@name ] ) ); } else { descript = stepSpace + " " + publicConst.@name + " = "; contentConst += ( arg[ publicConst.@name ] === null || arg[ publicConst.@name ] === undefined)? descript + ( onType?"(" + publicConst.@type + ",0)":"" ) + arg[ publicConst.@name ]: descript + analisisObject( arg[ publicConst.@name ], onType, level, stepSpace + "\t", openClasses); } countElems++; } parseClass += " (" + countElems + "): " + contentConst; ///accessors stepSpace = space + "\t"; descript = "accessors"; parseClass += stepSpace + descript; stepSpace += "\t"; var contentAcc:String = ""; countElems = 0; for each ( var publicAcc:XML in accessors ) { if ( publicAcc.@access == "writeonly" ) continue; if ( typeof arg[ publicAcc.@name ] !== "object" ) { const typeAcc:String = analisisSimple( arg[ publicAcc.@name ] ); descript = stepSpace + publicAcc.@access + " " + publicAcc.@name + " = " + ( onType?"(" + typeAcc + ") ":"" ); contentAcc += descript + ( ( typeAcc === "xml" )?"/not shown.../":( arg[ publicAcc.@name ] ) ); } else { descript = stepSpace + publicAcc.@access + " " + publicAcc.@name + " = "; contentAcc += ( arg[ publicAcc.@name ] === null || arg[ publicAcc.@name ] === undefined)? descript + ( onType?"(" + publicAcc.@type + ",0)":"" ) + arg[ publicAcc.@name ]: descript + analisisObject( arg[ publicAcc.@name ], onType, level, stepSpace + "\t", openClasses); } countElems++; } parseClass += " (" + countElems + ") " + contentAcc; ///methods stepSpace = space + "\t"; descript = "methods"; parseClass += stepSpace + descript; stepSpace += "\t"; var contentMethods:String = ""; countElems = 0; for each ( var publicMethod:XML in method ) { contentMethods += stepSpace + publicMethod.@name + ":" + publicMethod.@returnType; countElems++; } parseClass += " (" + countElems + ") " + contentMethods; return parseClass; } static private function dumpVector( arg:*, onType:Boolean, level:int, space:String, openClasses:Boolean ):String { if ( level === 0 ) return getQualifiedClassName( arg ) + " /limiting level.../"; else level--; const timer:int = getTimer(); if ( timer > _timeDie + _MAX_TIME_DIE ) return " too long processing... "; var parseVector:String = "( " + arg.length + " )"; var stepSpace:String = space + "\t"; var type:String; var descript:String; for ( var nm:String in arg ) { if ( typeof arg[ nm ] !== "object" ) { const typingValue:String = analisisSimple( arg[ nm ] ); descript = stepSpace + "[" + nm + "] => " + ( onType?"(" + typingValue + ") ":"" ) parseVector += descript +( ( typingValue === "xml" )?"/not shown.../":arg[ nm ] ); } else { descript = stepSpace + "[" + nm + "] => "; parseVector += descript + analisisObject( arg[ nm ], onType, level, stepSpace + "\t", openClasses ) ; } } return parseVector; } static private function dumpDictionary( arg:*, onType:Boolean, level:int, space:String, openClasses:Boolean ):String { if ( level === 0 ) return getQualifiedClassName( arg ) + " /limiting level.../"; else level--; const timer:int = getTimer(); if ( timer > _timeDie + _MAX_TIME_DIE ) return " too long processing... "; var parseDict:String = getQualifiedClassName( arg ); var parseContent:String = ""; var stepSpace:String = space + "\t"; var type:String; var descript:String; var countElem:int = 0; for ( var nm:* in arg ) { if ( typeof arg[ nm ] !== "object" ) { const typingValue:String = analisisSimple( arg[ nm ] ); descript = stepSpace + "[" + getQualifiedClassName( nm )+ "] => " + ( onType?"(" + typingValue + ") ":"" ) parseContent += descript + ( ( typingValue === "xml" )?"/not shown.../":arg[ nm ] ); } else { descript = stepSpace + "[" + getQualifiedClassName( nm ) + "] => "; parseContent += descript + analisisObject( arg[ nm ], onType, level, stepSpace , openClasses ) ; } countElem++; } parseDict += " (" + countElem +"): " + parseContent; return parseDict; } static private function analisisObject( arg:*, onType:Boolean, level:int, space:String, openClasses:Boolean, firstFlag:Boolean = false ):String { var parseData:String; const classType:String = getQualifiedClassName( arg ); switch ( classType ) { case "flash.utils::Dictionary": parseData = dumpDictionary( arg, onType, level, space, openClasses ); break; case "Object": parseData = dumpObject( arg, onType, level, space, openClasses ); break; case "Array": parseData = dumpArray( arg as Array, onType, level, space, openClasses ); break; case ( classType.indexOf( "Vector" ) !== -1 )?classType:"": parseData = dumpVector( arg, onType, level, space, openClasses ); break; default: if ( firstFlag && !( openClasses ) || openClasses && !( arg.hasOwnProperty( "stage" ) && arg.stage !== null)) parseData = dumpClass( arg, onType, level, space, openClasses ); else parseData = arg; } return parseData; } static private function analisisSimple( arg:* ):String { var type:String; if ( typeof arg === "xml" ) { type = "xml"; } else if ( typeof arg === "string" ) { String( arg ); type = "str" + "," + String( arg ).length; } else if ( typeof arg === "number" ) { if ( arg is int ) { type = "int"; type += "," + String( arg + "").length; } else if ( arg as uint ) { type = "uint"; type += "," + String( arg + "").length; } else { type = "number"; const floor:int = String( Math.floor( arg ) ).length; const fract:Array = ( arg + "" ).split( "." ); const fractional:int = fract.length > 1?fract[ 1 ].length:0; type += "," + String( floor + "." + fractional); } } else if ( typeof arg === "boolean" ) type = "bool"; else type = ""; return type; } //} } }
Описание тестового класса:
///******************************************************************** ///* Copyright © 2012 fishr (fishr.flash@gmail.com) ///******************************************************************** package { import flash.display.MovieClip; import flash.display.Sprite; import flash.utils.Dictionary; import su.fishr.utils.Dumper; /** * Для тестирования трейсера Dumper() * * @playerversion Flash 9 * @langversion 3.0 * @author fishr * @created 24.05.2012 22:05 * @since 24.05.2012 22:05 */ public class Demo { /**------------------------------------------------------------------------------- * * P U B L I C * * -------------------------------------------------------------------------------- */ //{ public function Demo() { init(); } //} /**------------------------------------------------------------------------------- * * P R I V A T E * * -------------------------------------------------------------------------------- */ //{ private function init():void { const xmlNodes:XML = <data> <some_node> "some_value"</some_node> <some_node> anower_value </some_node></data>; const pseudoXML:String = '<data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data>'; const xmlList:XMLList = xmlNodes.some_node; const nmbr:Number = 3094530495.394304999303300; const sprite:Sprite = new Sprite(); const movie:MovieClip = new MovieClip(); movie.addChild( sprite ); const array:Array = [ "abc", "bcd", "cde", "def", nmbr, xmlNodes, pseudoXML ]; const obj:Object = { someElem:"String Elem", someArray:array, someNm:nmbr, xml:xmlNodes }; const vect:Vector.<*> = new Vector.<*>; vect.push( nmbr ); vect.push( array ); vect.push( obj ); vect.push( xmlNodes ); const dictionary:Dictionary = new Dictionary(); dictionary[ nmbr ] = nmbr; dictionary[ array ] = [ array, array, array, { array:array, array1:array } ]; dictionary[ vect ] = vect; dictionary[ movie ] = movie; dictionary[ xmlNodes ] = xmlNodes; ///TODO trace ////////////////////////// T R A C E /////////////////////////////// var d:Date = new Date(); trace(d.valueOf() + ". Demo::init() : \r\r" + Dumper.dump( [ dictionary, dictionary , { dictionary:dictionary } ], -1, true)); //////////////////////// E N D T R A C E ////////////////////////// } //} } }
Результат работы:
Код:
1338214593171. Demo::init() : Array(3): [0] => flash.utils::Dictionary (5): [String] => (number,10.6) 3094530495.394305 [__AS3__.vec::Vector.<*>] => ( 4 ) [0] => (number,10.6) 3094530495.394305 [1] => Array(7): [0] => (str,3) abc [1] => (str,3) bcd [2] => (str,3) cde [3] => (str,3) def [4] => (number,10.6) 3094530495.394305 [5] => (xml) /not shown.../ [6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data> [2] => Object (4): someElem:(str,11) String Elem someArray:Array(7): [0] => (str,3) abc [1] => (str,3) bcd [2] => (str,3) cde [3] => (str,3) def [4] => (number,10.6) 3094530495.394305 [5] => (xml) /not shown.../ [6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data> someNm:(number,10.6) 3094530495.394305 xml:(xml) /not shown.../ [3] => (xml) /not shown.../ [flash.display::MovieClip] => [object MovieClip] [Array] => Array(4): [0] => Array(7): [0] => (str,3) abc [1] => (str,3) bcd [2] => (str,3) cde [3] => (str,3) def [4] => (number,10.6) 3094530495.394305 [5] => (xml) /not shown.../ [6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data> [1] => Array(7): [0] => (str,3) abc [1] => (str,3) bcd [2] => (str,3) cde [3] => (str,3) def [4] => (number,10.6) 3094530495.394305 [5] => (xml) /not shown.../ [6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data> [2] => Array(7): [0] => (str,3) abc [1] => (str,3) bcd [2] => (str,3) cde [3] => (str,3) def [4] => (number,10.6) 3094530495.394305 [5] => (xml) /not shown.../ [6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data> [3] => Object (2): array:Array(7): [0] => (str,3) abc [1] => (str,3) bcd [2] => (str,3) cde [3] => (str,3) def [4] => (number,10.6) 3094530495.394305 [5] => (xml) /not shown.../ [6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data> array1:Array(7): [0] => (str,3) abc [1] => (str,3) bcd [2] => (str,3) cde [3] => (str,3) def [4] => (number,10.6) 3094530495.394305 [5] => (xml) /not shown.../ [6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data> [XML] => (xml) /not shown.../ [1] => flash.utils::Dictionary (5): [String] => (number,10.6) 3094530495.394305 [__AS3__.vec::Vector.<*>] => ( 4 ) [0] => (number,10.6) 3094530495.394305 [1] => Array(7): [0] => (str,3) abc [1] => (str,3) bcd [2] => (str,3) cde [3] => (str,3) def [4] => (number,10.6) 3094530495.394305 [5] => (xml) /not shown.../ [6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data> [2] => Object (4): someElem:(str,11) String Elem someArray:Array(7): [0] => (str,3) abc [1] => (str,3) bcd [2] => (str,3) cde [3] => (str,3) def [4] => (number,10.6) 3094530495.394305 [5] => (xml) /not shown.../ [6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data> someNm:(number,10.6) 3094530495.394305 xml:(xml) /not shown.../ [3] => (xml) /not shown.../ [flash.display::MovieClip] => [object MovieClip] [Array] => Array(4): [0] => Array(7): [0] => (str,3) abc [1] => (str,3) bcd [2] => (str,3) cde [3] => (str,3) def [4] => (number,10.6) 3094530495.394305 [5] => (xml) /not shown.../ [6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data> [1] => Array(7): [0] => (str,3) abc [1] => (str,3) bcd [2] => (str,3) cde [3] => (str,3) def [4] => (number,10.6) 3094530495.394305 [5] => (xml) /not shown.../ [6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data> [2] => Array(7): [0] => (str,3) abc [1] => (str,3) bcd [2] => (str,3) cde [3] => (str,3) def [4] => (number,10.6) 3094530495.394305 [5] => (xml) /not shown.../ [6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data> [3] => Object (2): array:Array(7): [0] => (str,3) abc [1] => (str,3) bcd [2] => (str,3) cde [3] => (str,3) def [4] => (number,10.6) 3094530495.394305 [5] => (xml) /not shown.../ [6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data> array1:Array(7): [0] => (str,3) abc [1] => (str,3) bcd [2] => (str,3) cde [3] => (str,3) def [4] => (number,10.6) 3094530495.394305 [5] => (xml) /not shown.../ [6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data> [XML] => (xml) /not shown.../ [2] => Object (1): dictionary:flash.utils::Dictionary (5): [String] => (number,10.6) 3094530495.394305 [__AS3__.vec::Vector.<*>] => ( 4 ) [0] => (number,10.6) 3094530495.394305 [1] => Array(7): [0] => (str,3) abc [1] => (str,3) bcd [2] => (str,3) cde [3] => (str,3) def [4] => (number,10.6) 3094530495.394305 [5] => (xml) /not shown.../ [6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data> [2] => Object (4): someElem:(str,11) String Elem someArray:Array(7): [0] => (str,3) abc [1] => (str,3) bcd [2] => (str,3) cde [3] => (str,3) def [4] => (number,10.6) 3094530495.394305 [5] => (xml) /not shown.../ [6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data> someNm:(number,10.6) 3094530495.394305 xml:(xml) /not shown.../ [3] => (xml) /not shown.../ [flash.display::MovieClip] => [object MovieClip] [Array] => Array(4): [0] => Array(7): [0] => (str,3) abc [1] => (str,3) bcd [2] => (str,3) cde [3] => (str,3) def [4] => (number,10.6) 3094530495.394305 [5] => (xml) /not shown.../ [6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data> [1] => Array(7): [0] => (str,3) abc [1] => (str,3) bcd [2] => (str,3) cde [3] => (str,3) def [4] => (number,10.6) 3094530495.394305 [5] => (xml) /not shown.../ [6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data> [2] => Array(7): [0] => (str,3) abc [1] => (str,3) bcd [2] => (str,3) cde [3] => (str,3) def [4] => (number,10.6) 3094530495.394305 [5] => (xml) /not shown.../ [6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data> [3] => Object (2): array:Array(7): [0] => (str,3) abc [1] => (str,3) bcd [2] => (str,3) cde [3] => (str,3) def [4] => (number,10.6) 3094530495.394305 [5] => (xml) /not shown.../ [6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data> array1:Array(7): [0] => (str,3) abc [1] => (str,3) bcd [2] => (str,3) cde [3] => (str,3) def [4] => (number,10.6) 3094530495.394305 [5] => (xml) /not shown.../ [6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data> [XML] => (xml) /not shown.../
Всего комментариев 30
Комментарии
![]() ![]() |
|
Обновил(-а) fish_r 23.05.2012 в 13:27
|
![]() ![]() |
|
Если Flex проект, то есть ObjectUtil.toString.
Тупо зацикливается и падает. Да табуляция явно узкое место, прочитать вообще ничего не возможно, имхо. |
|
Обновил(-а) Inet_PC 23.05.2012 в 13:06
|
![]() ![]() |
|
Цитата:
![]() Это исправляться не будет, т.к. это статический класс и состояний у него быть не должно, поэтому никакая информация им запоминаться не будет в принципе. Посмотрим на практике, если слишком часто буду на эти грабли наступать может что то и придумаю. Объект делать очень не хочется ибо нужен глобальный доступ, может стек?... Не знаю пока. |
|
Обновил(-а) fish_r 23.05.2012 в 14:29
|
![]() ![]() |
|
Для реализации такого контроля нужно чтобы объект запоминал все те объекты которые он уже разбирал
и сравнивал с вновь поступающими на разбор. Реализация такой штуки лишит смысла статический характер класса, а объекту надо будет предоставлять глобальный доступ каким то иным способом. Можно обернуть такой объект в статик, но тогда уже ему нужно будет давать каллбэк, или разрешать самому трейсить... В общем пока нет достойных идей - как это контролировать. Пока - есть уровень просмотра, есть запрет на разбор классов... Цитата:
Не думаю, что кто-то хочет получить такую ошибку и сидеть разбираться.
|
|
Обновил(-а) fish_r 23.05.2012 в 20:30
|
![]() ![]() |
|
Цитата:
Реализация такой штуки лишит смысла статический характер класса, а объекту надо будет предоставлять глобальный доступ каким то иным способом.
Цитата:
Разбираться там особо не надо. В этих случаях плеер исключение выкидывает с указанием места где закольцевалось.
|
|
Обновил(-а) Inet_PC 24.05.2012 в 09:29
|
![]() ![]() |
|
Цитата:
Вы еще и меня в это вмешали!
![]() |
![]() ![]() |
|
Цитата:
А если во время обработки одного запроса поступит другой, третий, пятый и т.д. Это статик. Он в единственном числе.
|
![]() ![]() |
|
Замкнутые ссылки можно было у Блуда посмотреть, как решаются.
|
![]() ![]() |
|
fish_r, ИМХО надуманная проблема.
|
![]() ![]() |
|
update
Класс по прежнему не умеет обрабатывать объекты с циклическими ссылками. Но непрерывная его работа ограничена 0.228 частью секунды ( потом правда ещё минуту выводится трейс, если пользоваться ИДЕ, но зато лог файл не усекается) Это конечно можно произвольно изменять. |
|
Обновил(-а) fish_r 28.05.2012 в 19:26
|
![]() ![]() |
|
У тебя все так запутанно.
Объекты внутри объектов. import com.mikroacse.utils.log.Tracer; var o:Object = { num:1, str:'hello', arr:['hi', 'welcome'], obj:{ num:1, str:'hello', arr:['hi', 'welcome'] }, num2:1, str2:'2' }; Tracer.viewObject(o, false); [1] arr is Array: [1] hi > [class String] [2] welcome > [class String] [2] obj is Object: [1] arr is Array: [1] hi > [class String] [2] welcome > [class String] [2] str: hello > [class String] [3] num: 1 > [class Number] [3] num2: 1 > [class Number] [4] str: hello > [class String] [5] str2: 2 > [class String] [6] num: 1 > [class Number] |
|
Обновил(-а) MikroAcse 25.05.2012 в 13:46
|
![]() ![]() |
|
Многомерные массивы.
import com.mikroacse.utils.log.Tracer; var a:Array = [['hello', ['welcome', [1, [2, [3, ['hi', ['i am', ['mikroacse']]]]]]]]]; Tracer.viewArray(a, false); [1] [hello,welcome,1,2,3,hi,i am,mikroacse] is Array: [1] hello > [class String] [2] [welcome,1,2,3,hi,i am,mikroacse] is Array: [1] welcome > [class String] [2] [1,2,3,hi,i am,mikroacse] is Array: [1] 1 > [class Number] [2] [2,3,hi,i am,mikroacse] is Array: [1] 2 > [class Number] [2] [3,hi,i am,mikroacse] is Array: [1] 3 > [class Number] [2] [hi,i am,mikroacse] is Array: [1] hi > [class String] [2] [i am,mikroacse] is Array: [1] i am > [class String] [2] [mikroacse] is Array: [1] mikroacse > [class String] |
|
Обновил(-а) MikroAcse 25.05.2012 в 10:49
|
![]() ![]() |
|
У тебя аккуратнее, есть похоже смысл отказаться от длины строки и разносить табом...
|
![]() ![]() |
|
Обновил(-а) MikroAcse 25.05.2012 в 13:56
|
![]() ![]() |
|
Окей а если ссылка на ДанныйОбъект не у параметра, а у параметра параметра?
|
![]() ![]() |
|
Да все уже описали выше, у blooddy отличное решение - создать слварь и каждый объект пихать в него. Если объект в словаре уже есть - то это ссылка и трейсить его не нужно.
|
![]() ![]() |
|
Цитата:
Окей а если ссылка на ДанныйОбъект не у параметра, а у параметра параметра?
|
![]() ![]() |
|
MikroAcse, постоянно.
|
![]() ![]() |
|
Цитата:
MikroAcse, постоянно.
|
Последние записи от fish_r
- Odnoklassniki.API 2.0 photo upload V2 (09.06.2012)
- Универсальный трейсер. (21.05.2012)
- SVN. Автоматическая архивация локального репозитория. (23.06.2011)
- Поворот объекта вокруг произвольной точки. (30.04.2011)