public DStackContext(int module, int line, DModule f, int thisId, String functionSignature, int depth) { m_source = f; m_module = module; m_line = line; // the passed-in 'thisId' seems to always be equal to one, which does more harm than good m_this = null; m_functionSignature = functionSignature; m_depth = depth; m_args = new LinkedHashMap(); // preserves order m_locals = new LinkedHashMap(); // preserves order m_scopeChain = new System.Collections.ArrayList(); m_populated = false; m_location = new DLocation(m_source, line); }
public virtual void addMember(DVariable v) { if (m_members == null) { m_members = new System.Collections.Hashtable(); } // if we are a proto member house away our original parent id String name = v.getName(); DValue val = (DValue)v.getValue(); val.m_nonProtoId = (name != null && name.Equals("__proto__"))?m_nonProtoId:val.Id; //$NON-NLS-1$ // TODO is this right? v.m_nonProtoParentId = m_nonProtoId; m_members[name] = v; }
/* * @see Flash.Tools.Debugger.Value#getMembers(Flash.Tools.Debugger.Session) */ public override Variable[] getMembers(Session s) { obtainMembers(s); /* find out the size of the array */ int count = getMemberCount(s); DVariable[] ar = new DVariable[count]; if (count > 0) { m_members.Values.CopyTo(ar, 0); // sort the member list by name ArrayUtil.sort(ar); } return(ar); }
public virtual void clearLastVariable() { m_lastInGetVariable = null; }
internal virtual void setThis(DVariable v) { m_this = v; }
internal virtual void addScopeChainEntry(DVariable v) { m_scopeChain.Add(v); }
/* setters */ internal virtual void addArgument(DVariable v) { m_args[v.getName()] = v; }
/// <summary> Get the value of the variable named 'name' using varId /// as the context id for the Variable. /// /// This call is used to fire getters, where the id must /// be that of the original object and not the object id /// of where the getter actually lives. For example /// a getter a() may live under o.__proto__.__proto__ /// but you must use the id of o and the name of 'a' /// in order for the getter to fire correctly. [Note: This /// paragraph was written for AS2; __proto__ doesn't exist /// in AS3. TODO: revise this paragraph] /// </summary> public virtual Value getValue(int varId, String name) { Value v = null; if (Suspended) { int fireGetter = getPreference(SessionManager.PREF_INVOKE_GETTERS); // disable children attaching to parent variables and clear our // most recently seen variable m_manager.clearLastVariable(); m_manager.enableChildAttach(false); try { requestVariable(varId, name, (fireGetter != 0), false); v = m_manager.lastVariable().getValue(); } catch (NoResponseException e) { if (fireGetter != 0) { // We fired a getter -- most likely, what happened is that that getter // (which is actual code in the user's movie) just took too long to // calculate its value. So rather than throwing an exception, we store // some error text for the value of the variable itself. // // TODO [mmorearty 4/20/06] Even though I wrote the below code, I now // am wondering if it is incorrect that I am calling addVariableMember(), // because in every other case, this function does not add members to // existing objects. Need to revisit this. v = new DValue(VariableType.STRING, "String", "String", ValueAttribute.IS_EXCEPTION, e.getLocalizedMessage()); DVariable var = new DVariable(name, (DValue) v); m_manager.enableChildAttach(true); m_manager.addVariableMember(varId, var); } else { throw e; // re-throw } } finally { // reset our attach flag, so that children attach to parent variables. m_manager.enableChildAttach(true); } } else throw new NotSuspendedException(); return v; }
// TODO is this right? internal virtual void addVariableMember(long parentId, DVariable child, long doubleAsId) { addVariableMember(parentId, child); // double book the child under another id if (m_attachChildren) putValue(doubleAsId, (DValue) child.getValue()); }
} // triggers a reload of variables. /// <summary> Removes the specified variable from the list of locals, and /// remembers that the specified variable is the "activation object" /// for this frame. See bug 155031. /// </summary> internal virtual void convertLocalToActivationObject(DVariable v) { m_activationObject = v; m_locals.Remove(v.getName()); }
internal virtual void removeAllLocals() { m_locals.Clear(); m_activationObject = null; }
internal virtual void addLocal(DVariable v) { m_locals[v.getName()] = v; }
internal virtual void addVariableMember(long parentId, DVariable child) { DValue parent = getValue(parentId); addVariableMember(parent, child); }
internal virtual void addVariableMember(DValue parent, DVariable child) { if (m_attachChildren) { // There are certain situations when the Flash player will send us more // than one variable or getter with the same name. Basically, when a // subclass implements (or overrides) something that was also declared in a // superclass, then we'll see that variable or getter in both the // superclass and the subclass. // // Here are a few situations where that affects the debugger in different // ways: // // 1. When a class implements an interface, the class instance actually has // *two* members for each implemented function: One which is public and // represents the implementation function, and another which is internal // to the interface, and represents the declaration of the function. // Both of these come in to us. In the UI, the one we want to show is // the public one. They come in in random order (they are stored in a // hash table in the VM), so we don't know which one will come first. // // 2. When a superclass has a private member "m", and a subclass has its own // private member with the same name "m", we will receive both of them. // (They are scoped by different packages.) In this case, the first one // the player sent us is the one from the subclass, and that is the one // we want to display in the debugger. // // The following logic correctly deals with all variations of those cases. DVariable existingChildWithSameName = parent.findMember(child.getName()); if (existingChildWithSameName != null) { int existingScope = existingChildWithSameName.Scope; int newScope = child.Scope; if (existingScope == VariableAttribute.NAMESPACE_SCOPE && newScope == VariableAttribute.PUBLIC_SCOPE) { // This is the case described above where a class implements an interface, // so that class's definition includes both a namespace-scoped declaration // and a public declaration, in random order; in this case, the // namespace-scoped declaration came first. We want to use the public // declaration. parent.addMember(child); } else if (existingScope == VariableAttribute.PUBLIC_SCOPE && newScope == VariableAttribute.NAMESPACE_SCOPE) { // One of two things happened here: // // 1. This is the case described above where a class implements an interface, // so that class's definition includes both a namespace-scoped declaration // and a public declaration, in random order; in this case, the // public declaration came first. It is tempting to use the public // member in this case, but there is a catch... // 2. It might be more complicated than that: Perhaps there is interface I, // and class C1 implements I, but class C2 extends C1, and overrides // one of the members of I that was already implemented by C1. In this // case, the public declaration from C2 came first, but now we are seeing // a namespace-scoped declaration in C1. We need to record that the // member is public, but we also need to record that it is a member // of the base class, not just a member of the superclass. // // The easiest way to deal with both cases is to use the child that came from // the superclass, but to change its scope to public. child.makePublic(); parent.addMember(child); } else if (existingScope != VariableAttribute.PRIVATE_SCOPE && existingScope == newScope) { // This is a public, protected, internal, or namespace-scoped member which // was defined in a base class and overridden in a subclass. We want to // use the member from the base class, to that the debugger knows where the // variable was actually defined. parent.addMember(child); } } else { parent.addMember(child); } // put child in the registry if it has an id and not already there DValue childValue = (DValue) child.getValue(); int childId = childValue.Id; if (childId != Value.UNKNOWN_ID) { DValue existingValue = getValue(childId); if (existingValue != null) { Debug.Assert(existingValue == childValue); // TODO is this right? what about getters? } else { putValue(childId, childValue); } } } }
/* * @see Flash.Tools.Debugger.Value#getMembers(Flash.Tools.Debugger.Session) */ public override Variable[] getMembers(Session s) { obtainMembers(s); /* find out the size of the array */ int count = getMemberCount(s); DVariable[] ar = new DVariable[count]; if (count > 0) { m_members.Values.CopyTo(ar, 0); // sort the member list by name ArrayUtil.sort(ar); } return ar; }
/// <summary> This is the core routine for decoding incoming messages and deciding what should be /// done with them. We have registered ourself with DProtocol to be notified when any /// incoming messages have been received. /// /// It is important to note that we should not rely on the contents of the message /// since it may be reused after we exit this method. /// </summary> public virtual void messageArrived(DMessage msg, DProtocol which) { /* at this point we just open up a big switch statement and walk through all possible cases */ int type = msg.Type; // System.out.println("manager msg = "+DMessage.inTypeName(type)); switch (type) { case DMessage.InVersion: { long ver = msg.getDWord(); m_playerVersion = (int) ver; break; } case DMessage.InErrorExecLimit: { handleFaultEvent(new RecursionLimitFault()); break; } case DMessage.InErrorWith: { handleFaultEvent(new InvalidWithFault()); break; } case DMessage.InErrorProtoLimit: { handleFaultEvent(new ProtoLimitFault()); break; } case DMessage.InErrorURLOpen: { String url = msg.getString(); handleFaultEvent(new InvalidURLFault(url)); break; } case DMessage.InErrorTarget: { String name = msg.getString(); handleFaultEvent(new InvalidTargetFault(name)); break; } case DMessage.InErrorException: { long offset = msg.getDWord(); // As of FP9, the player will also send the "toString()" message // of the exception. But for backward compatibility with older // players, we won't assume that that is there. String exceptionMessage; if (msg.Remaining > 0) exceptionMessage = msg.getString(); else exceptionMessage = ""; //$NON-NLS-1$ handleFaultEvent(new ExceptionFault(exceptionMessage)); break; } case DMessage.InErrorStackUnderflow: { long offset = msg.getDWord(); handleFaultEvent(new StackUnderFlowFault()); break; } case DMessage.InErrorZeroDivide: { long offset = msg.getDWord(); handleFaultEvent(new DivideByZeroFault()); break; } case DMessage.InErrorScriptStuck: { handleFaultEvent(new ScriptTimeoutFault()); break; } case DMessage.InErrorConsole: { String s = msg.getString(); handleFaultEvent(new ConsoleErrorFault(s)); break; } case DMessage.InTrace: { String text = msg.getString(); addEvent(new TraceEvent(text)); break; } case DMessage.InSquelch: { long state = msg.getDWord(); m_squelchEnabled = (state != 0)?true:false; break; } case DMessage.InParam: { String name = msg.getString(); String value = msg.getString(); // here's where we get movie = URL and password which I'm not sure what to do with? // System.out.println(name+"="+value); m_parms[name] = value; // if string is a "movie", then this is a URL if (name.StartsWith("movie")) //$NON-NLS-1$ m_uri = convertToURI(value); break; } case DMessage.InPlaceObject: { long objId = msg.getDWord(); String path = msg.getString(); // m_bag.placeObject((int)objId, path); break; } case DMessage.InSetProperty: { long objId = msg.getDWord(); int item = msg.getWord(); String value = msg.getString(); break; } case DMessage.InNewObject: { long objId = msg.getDWord(); break; } case DMessage.InRemoveObject: { long objId = msg.getDWord(); // m_bag.removeObject((int)objId); break; } case DMessage.InSetVariable: { long objId = msg.getDWord(); String name = msg.getString(); int dType = msg.getWord(); int flags = (int)msg.getDWord(); String value = msg.getString(); // m_bag.createVariable((int)objId, name, dType, flags, value); break; } case DMessage.InDeleteVariable: { long objId = msg.getDWord(); String name = msg.getString(); // m_bag.deleteVariable((int)objId, name); break; } case DMessage.InScript: { int module = (int)msg.getDWord(); int bitmap = (int)msg.getDWord(); String name = msg.getString(); // in "basepath;package;filename" format String text = msg.getString(); int swfIndex = - 1; /* new in flash player 9: player tells us what swf this is for */ if (msg.Remaining >= 4) swfIndex = (int)msg.getDWord(); lock (m_source) { // create new source file if (putSource(swfIndex, module, bitmap, name, text)) { // have we changed the list since last query if (!m_sourceListModified) addEvent(new FileListModifiedEvent()); m_sourceListModified = true; /* current source list is stale */ } } break; } case DMessage.InRemoveScript: { long module = msg.getDWord(); lock (m_source) { if (removeSource((int) module)) { // have we changed the list since last query if (!m_sourceListModified) addEvent(new FileListModifiedEvent()); m_sourceListModified = true; /* current source list is stale */ } } break; } case DMessage.InAskBreakpoints: { // the player has just loaded a swf and we know the player // has halted, waiting for us to continue. The only caveat // is that it looks like it still does a number of things in // the background which take a few seconds to complete. if (m_suspendInfo == null) m_suspendInfo = new DSuspendInfo(SuspendReason.ScriptLoaded, 0, 0, 0, 0); break; } case DMessage.InBreakAt: { long bp = msg.getDWord(); long id = msg.getDWord(); String stack = msg.getString(); // System.out.println(msg.getInTypeName()+",bp="+(bp&0xffff)+":"+(bp>>16)+",id="+id+",stack=\n"+stack); //System.out.println("InBreakAt"); int module = DLocation.decodeFile(bp); int line = DLocation.decodeLine(bp); addEvent(new BreakEvent(module, line)); break; } case DMessage.InContinue: { /* we are running again so trash all our variable contents */ continuing(); break; } case DMessage.InSetLocalVariables: { long objId = msg.getDWord(); // m_bag.markObjectLocal((int)objId, true); break; } case DMessage.InSetBreakpoint: { long count = msg.getDWord(); while (count-- > 0) { long bp = msg.getDWord(); int fileId = DLocation.decodeFile(bp); int line = DLocation.decodeLine(bp); DModule file = getSource(fileId); DLocation l = new DLocation(file, line); if (file != null) addBreakpoint((int) bp, l); } break; } case DMessage.InNumScript: { /* lets us know how many scripts there are */ int num = (int)msg.getDWord(); DSwfInfo swf; /* * New as of flash player 9: another dword indicating which swf this is for. * That means we don't have to guess whether this is for an old SWF * which has just had some more modules loaded, or for a new SWF! */ if (msg.Remaining >= 4) { int swfIndex = (int)msg.getDWord(); swf = getOrCreateSwfInfo(swfIndex); m_lastSwfInfo = swf; } else { /* This is not flash player 9 (or it is an early build of fp9). * * We use this message as a trigger that a new swf has been loaded, so make sure * we are ready to accept the scripts. */ swf = ActiveSwfInfo; } // It is NOT an error for the player to have sent us a new, // different sourceExpectedCount from whatever we had before! // In fact, this happens all the time, whenever a SWF has more // than one ABC. swf.SourceExpectedCount = num; break; } case DMessage.InRemoveBreakpoint: { long count = msg.getDWord(); while (count-- > 0) { long bp = msg.getDWord(); removeBreakpoint((int) bp); } break; } case DMessage.InBreakAtExt: { long bp = msg.getDWord(); long num = msg.getDWord(); // System.out.println(msg.getInTypeName()+",bp="+(bp&0xffff)+":"+(bp>>16)); /* we have stack info to store away */ clearFrames(); // just in case int depth = 0; while (num-- > 0) { long bpi = msg.getDWord(); long id = msg.getDWord(); String stack = msg.getString(); int module = DLocation.decodeFile(bpi); int line = DLocation.decodeLine(bpi); DModule m = getSource(module); DStackContext c = new DStackContext(module, line, m, (int) id, stack, depth); // If addFrame() returns false, that means it chose to ignore this // frame, so we do NOT want to increment our depth for the next // time through the loop. If it returns true, then we do want to. if (addFrame(c)) ++depth; // System.out.println(" this="+id+",@"+(bpi&0xffff)+":"+(bpi>>16)+",stack="+stack); } mapOldFramesToNew(); break; } case DMessage.InFrame: { // For InFrame the first element is really our frame id DValue frame = null; DVariable child = null; System.Collections.ArrayList v = new System.Collections.ArrayList(); System.Collections.ArrayList registers = new System.Collections.ArrayList(); int depth = (int)msg.getDWord(); // depth of frame // make sure we have a valid depth if (depth > - 1) { // first thing is number of registers int num = (int)msg.getDWord(); for (int i = 0; i < num; i++) registers.Add(extractRegister(msg, i + 1)); } int currentArg = - 1; bool gettingScopeChain = false; // then our frame itself while (msg.Remaining > 0) { long frameId = msg.getDWord(); if (frame == null) { frame = getOrCreateValue(frameId); extractVariable(msg); // put the rest of the info in the trash } else { child = extractVariable(msg); if (currentArg == - 1 && child.getName().Equals(ARGUMENTS_MARKER)) { currentArg = 0; gettingScopeChain = false; } else if (child.getName().Equals(SCOPE_CHAIN_MARKER)) { currentArg = - 1; gettingScopeChain = true; } else if (currentArg >= 0) { // work around a compiler bug: If the variable's name is "undefined", // then change its name to "_argN", where "N" is the argument index, // e.g. _arg1, _arg2, etc. ++currentArg; if (child.getName().Equals("undefined")) //$NON-NLS-1$ child.setName("_arg" + currentArg); //$NON-NLS-1$ } // All args and locals get added as "children" of // the frame; but scope chain entries do not. if (!gettingScopeChain) addVariableMember(frameId, child); // Everything gets added to the ordered list of // variables that came in. v.Add(child); } } // let's transfer our newly gained knowledge into the stack context if (depth == 0) populateRootNode(frame, v); else populateFrame(depth, v); break; } case DMessage.InOption: { String s = msg.getString(); String v = msg.getString(); m_options[s] = v; break; } case DMessage.InGetVariable: { // For InGetVariable the first element is the original entity we requested DValue parent = null; DVariable child = null; String definingClass = null; int level = 0; int highestLevelWithMembers = - 1; System.Collections.IList classes = new System.Collections.ArrayList(); while (msg.Remaining > 0) { long parentId = msg.getDWord(); // build or get parent node if (parent == null) { String name = msg.getString(); // pull the contents of the node which normally are disposed of except if we did a 0,name call m_lastInGetVariable = extractVariable(msg, name); parent = getOrCreateValue(parentId); } else { // extract the child and add it to the parent. child = extractVariable(msg); if (showMember(child)) { if (child.isAttributeSet(VariableAttribute.IS_DYNAMIC)) { // Dynamic attributes always come in marked as a member of // class "Object"; but to the user, it makes more sense to // consider them as members of the topmost class. if (classes.Count > 0) { child.setDefiningClass(0, (String) classes[0]); highestLevelWithMembers = Math.Max(highestLevelWithMembers, 0); } } else { child.setDefiningClass(level, definingClass); if (definingClass != null) { highestLevelWithMembers = Math.Max(highestLevelWithMembers, level); } } addVariableMember(parent.Id, child); } else { if (isTraits(child)) { definingClass = child.QualifiedName; level = classes.Count; // If the traits name end with "$", then it represents a class object -- // in other words, the variables inside it are static variables of that // class. In that case, we need to juggle the information. For example, // if we are told that a variable is a member of "MyClass$", we actually // store it into the information for "MyClass". if (definingClass.EndsWith("$")) { //$NON-NLS-1$ String classWithoutDollar = definingClass.Substring(0, (definingClass.Length - 1) - (0)); int indexOfClass = classes.IndexOf(classWithoutDollar); if (indexOfClass != - 1) { level = indexOfClass; definingClass = classWithoutDollar; } } // It wasn't static -- so, add this class to the end of the list of classes if (level == classes.Count) { classes.Add(definingClass); } } } } } if (parent != null && parent.getClassHierarchy(true) == null) { String[] classesArray = new String[classes.Count]; int index = 0; foreach (String className in classes) { classesArray[index++] = className; } parent.setClassHierarchy(classesArray, highestLevelWithMembers + 1); } break; } case DMessage.InWatch: // for AS2; sends 16-bit ID field case DMessage.InWatch2: // for AS3; sends 32-bit ID field { // This message is sent whenever a watchpoint is added // modified or removed. // // For an addition, flags will be non-zero and // success will be true. // // For a modification flags will be non-zero. // and oldFlags will be non-zero and success // will be true. Additionally oldFlags will not // be equal to flags. // // For a removal flags will be zero. oldFlags // will be non-zero. // // flags identifies the type of watchpoint added, // see WatchKind. // // success indicates whether the operation was successful // // request. It will be associated with the watchpoint. int success = msg.getWord(); int oldFlags = msg.getWord(); int oldTag = msg.getWord(); int flags = msg.getWord(); int tag = msg.getWord(); // for AS2, the ID came in above as a Word. For AS3, the above value is // bogus, and it has been sent again as a DWord. int id = (int)((type == DMessage.InWatch2) ? msg.getDWord() : msg.getWord()); String name = msg.getString(); if (success != 0) { if (flags == 0) { removeWatchpoint(oldTag); } else { // modification or addition is the same to us // a new watch is created and added into the table // while any old entry if it exists is removed. removeWatchpoint(oldTag); DWatch w = new DWatch(id, name, flags, tag); addWatchpoint(w); } } break; } case DMessage.InGetSwf: { // we only house the swf temporarily, PlayerSession then // pieces it back into swfinfo record. Also, we don't // send any extra data in the message so that we need not // copy the bytes. m_swf = msg.Data; break; } case DMessage.InGetSwd: { // we only house the swd temporarily, PlayerSession then // pieces it back into swfinfo record. m_swd = msg.Data; break; } case DMessage.InBreakReason: { // the id map 1-1 with out SuspendReason interface constants int suspendReason = msg.getWord(); int suspendPlayer = msg.getWord(); // item index of player int breakOffset = (int)msg.getDWord(); // current script offset int prevBreakOffset = (int)msg.getDWord(); // prev script offset int nextBreakOffset = (int)msg.getDWord(); // next script offset m_suspendInfo = new DSuspendInfo(suspendReason, suspendPlayer, breakOffset, prevBreakOffset, nextBreakOffset); // augment the current frame with this information. It // should work ok since we only get this message after a // InBreakAtExt message try { DStackContext c = getFrame(0); c.Offset = breakOffset; c.SwfIndex = suspendPlayer; } catch (Exception e) { if (Trace.error) { Trace.trace("Oh my god, gag me with a spoon...getFrame(0) call failed"); //$NON-NLS-1$ Console.Error.Write(e.StackTrace); Console.Error.Flush(); } } break; } // obtain raw action script byte codes case DMessage.InGetActions: { int item = msg.getWord(); int rsvd = msg.getWord(); int at = (int)msg.getDWord(); int len = (int)msg.getDWord(); int i = 0; m_actions = (len <= 0)?null:new byte[len]; while (len-- > 0) m_actions[i++] = (byte)msg.getByte(); break; } // obtain data about a SWF case DMessage.InSwfInfo: { int count = msg.getWord(); for (int i = 0; i < count; i++) { long index = msg.getDWord(); long id = msg.getDWord(); // get it DSwfInfo info = getOrCreateSwfInfo((int) index); // remember which was last seen m_lastSwfInfo = info; if (id != 0) { bool debugComing = (msg.getByte() == 0) ? false : true; byte vmVersion = (byte)msg.getByte(); // AS vm version number (1 = avm+, 0 == avm-) int rsvd1 = msg.getWord(); long swfSize = msg.getDWord(); long swdSize = msg.getDWord(); long scriptCount = msg.getDWord(); long offsetCount = msg.getDWord(); long breakpointCount = msg.getDWord(); long port = msg.getDWord(); String path = msg.getString(); String url = msg.getString(); String host = msg.getString(); // now we read in the swd debugging map (which provides // local to global mappings of the script ids long num = msg.getDWord(); IntMap local2global = new IntMap(); int minId = Int32.MaxValue; int maxId = Int32.MinValue; for (int j = 0; j < num; j++) { long local = msg.getDWord(); long global = msg.getDWord(); local2global.put((int) local, (Int32) global); minId = ((int) global < minId)?(int) global:minId; maxId = ((int) global > maxId)?(int) global:maxId; } // If its a new record then the swf size would have been unknown at creation time bool justCreated = (info.SwfSize == 0); // if we are a avm+ engine then we don't wait for the swd to load if (vmVersion > 0) { debugComing = false; info.VmVersion = vmVersion; info.setPopulated(); // added by mmorearty on 9/5/05 for RSL debugging } // update this swfinfo with the lastest data info.freshen(id, path, url, host, port, debugComing, swfSize, swdSize, breakpointCount, offsetCount, scriptCount, local2global, minId, maxId); // now tie any scripts that have been loaded into this swfinfo object tieScriptsToSwf(info); // notify if its newly created if (justCreated) addEvent(new SwfLoadedEvent(id, (int) index, path, url, host, port, swfSize)); } else { // note our state before marking it bool alreadyUnloaded = info.isUnloaded(); // clear it out info.setUnloaded(); // notify if this information is new. if (!alreadyUnloaded) addEvent(new SwfUnloadedEvent(info.Id, info.Path, (int) index)); } // System.out.println("[SWFLOAD] Loaded "+path+", size="+swfSize+", scripts="+scriptCount); } break; } // obtain the constant pool of some player case DMessage.InConstantPool: { int item = msg.getWord(); int count = (int)msg.getDWord(); String[] pool = new String[count]; for (int i = 0; i < count; i++) { long id = msg.getDWord(); DVariable var = extractVariable(msg); // we only need the contents of the variable pool[i] = var.getValue().ValueAsString; } m_lastConstantPool = pool; break; } // obtain one or more function name line number mappings. case DMessage.InGetFncNames: { long id = msg.getDWord(); // module id long count = msg.getDWord(); // number of entries // get the DModule DModule m = getSource((int) id); if (m != null) { for (int i = 0; i < count; i++) { int offset = (int)msg.getDWord(); int firstLine = (int)msg.getDWord(); int lastLine = (int)msg.getDWord(); String name = msg.getString(); // now add the entries m.addLineFunctionInfo(offset, firstLine, lastLine, name); } } break; } default: { break; } } }
public virtual void addMember(DVariable v) { if (m_members == null) { m_members = new System.Collections.Hashtable(); } // if we are a proto member house away our original parent id String name = v.getName(); DValue val = (DValue) v.getValue(); val.m_nonProtoId = (name != null && name.Equals("__proto__"))?m_nonProtoId:val.Id; //$NON-NLS-1$ // TODO is this right? v.m_nonProtoParentId = m_nonProtoId; m_members[name] = v; }
/// <summary> Returns whether a given child member should be shown, or should be filtered out.</summary> private bool showMember(DVariable child) { if (isTraits(child)) return false; return true; }
/// <summary> Returns whether this is not a variable at all, but is instead a representation /// of a "traits" object. A "traits" object is the Flash player's way of describing /// one class. /// </summary> private bool isTraits(DVariable variable) { Value value = variable.getValue(); if (value.getType() == VariableType.UNKNOWN && Value.TRAITS_TYPE_NAME.Equals(value.getTypeName())) { return true; } return false; }
/// <summary> Does the job of pulling together a variable based on /// the type of object encountered. /// </summary> internal virtual DVariable extractAtom(DMessage msg, String name, int oType, int flags) { int vType = VariableType.UNKNOWN; Object value = null; String typeName = ""; //$NON-NLS-1$ String className = ""; //$NON-NLS-1$ /* now we vary depending upon type */ switch (oType) { case DMessage.kNumberType: { String s = msg.getString(); double dval = 0; try { System.Globalization.NumberFormatInfo nfi = new System.Globalization.NumberFormatInfo(); dval = Double.Parse(s, nfi); } catch (FormatException) { } value = (double) dval; vType = VariableType.NUMBER; typeName = "Number"; //$NON-NLS-1$ break; } case DMessage.kBooleanType: { int bval = msg.getByte(); value = (bval == 0)?false:true; vType = VariableType.BOOLEAN; typeName = "Boolean"; //$NON-NLS-1$ break; } case DMessage.kStringType: { String s = msg.getString(); value = s; vType = VariableType.STRING; typeName = "String"; //$NON-NLS-1$ break; } case DMessage.kObjectType: case DMessage.kNamespaceType: { long oid = msg.getDWord(); long cType = (oid == -1) ? 0 : msg.getDWord(); int isFnc = (oid == -1) ? 0 : msg.getWord(); int rsvd = (oid == -1) ? 0 : msg.getWord(); typeName = (oid == -1) ? "" : msg.getString(); //$NON-NLS-1$ className = DVariable.classNameFor(cType, false); value = (long) oid; vType = (isFnc == 0)?VariableType.OBJECT:VariableType.FUNCTION; break; } case DMessage.kMovieClipType: { long oid = msg.getDWord(); long cType = (oid == -1) ? 0 : msg.getDWord(); long rsvd = (oid == -1) ? 0 : msg.getDWord(); typeName = (oid == -1) ? "" : msg.getString(); //$NON-NLS-1$ className = DVariable.classNameFor(cType, true); value = (long) oid; vType = VariableType.MOVIECLIP; break; } case DMessage.kNullType: { vType = VariableType.NULL; typeName = "null"; //$NON-NLS-1$ break; } case DMessage.kUndefinedType: { vType = VariableType.UNDEFINED; typeName = "undefined"; //$NON-NLS-1$ break; } case DMessage.kTraitsType: { // This one is special: When passed to the debugger, it indicates // that the "variable" is not a variable at all, but rather is a // class name. For example, if class Y extends class X, then // we will send a kDTypeTraits for class Y; then we'll send all the // members of class Y; then we'll send a kDTypeTraits for class X; // and then we'll send all the members of class X. This is only // used by the AVM+ debugger. vType = VariableType.UNKNOWN; typeName = Value.TRAITS_TYPE_NAME; break; } case DMessage.kReferenceType: case DMessage.kArrayType: case DMessage.kObjectEndType: case DMessage.kStrictArrayType: case DMessage.kDateType: case DMessage.kLongStringType: case DMessage.kUnsupportedType: case DMessage.kRecordSetType: case DMessage.kXMLType: case DMessage.kTypedObjectType: case DMessage.kAvmPlusObjectType: default: { // System.out.println("<unknown>"); break; } } // create the variable based on the content we received. DValue valueObject = null; if (value is Int64) { valueObject = getValue((long) ((Int64) value)); } if (valueObject == null) { valueObject = new DValue(vType, typeName, className, toAttributes(flags), value); if (value is Int64 && (toAttributes(flags) & VariableAttribute.HAS_GETTER) == 0) putValue((long) ((Int64) value), valueObject); } else { valueObject.setType(vType); valueObject.setTypeName(typeName); valueObject.setClassName(className); valueObject.setAttributes(toAttributes(flags)); valueObject.Value = value; } DVariable var = new DVariable(name, valueObject); return var; }
public const String SCOPE_CHAIN_MARKER = "$scopechain"; //$NON-NLS-1$ public DManager() { m_parms = new System.Collections.Hashtable(); m_source = new IntMap(); m_breakpoints = new System.Collections.ArrayList(); m_values = new IntMap(); m_previousValues = new IntMap(); m_frames = new System.Collections.ArrayList(); m_previousFrames = new System.Collections.ArrayList(); m_swfInfo = new System.Collections.ArrayList(); m_watchpoints = new System.Collections.ArrayList(); m_event = new System.Collections.ArrayList(); m_suspendInfo = null; m_sourceLocator = null; m_lastInGetVariable = null; m_attachChildren = true; m_squelchEnabled = false; m_lastConstantPool = null; m_playerVersion = - 1; // -1 => unknown }