示例#1
0
        /*
         * @see Flash.Tools.Debugger.Session#setScalarMember(int, java.lang.String, int, java.lang.String)
         */
        public virtual FaultEvent setValue(int type, String value)
        {
            FaultEvent fault = null;

            if (m_session != null && m_session is PlayerSession)
            {
                fault = ((PlayerSession)m_session).setScalarMember(m_nonProtoParentId, m_rawName, type, value);

                if (fault == null)
                {
                    m_firedGetter = false;

                    if (!needsToInvokeGetter())
                    {
                        DValue debugValue = m_value as DValue;

                        if (debugValue.getType() == VariableType.BOOLEAN)
                        {
                            debugValue.Value = value.ToLower() == "true";
                        }
                        else if (debugValue.getType() == VariableType.NUMBER)
                        {
                            debugValue.Value = Double.Parse(value);
                        }
                        else if (debugValue.getType() == VariableType.STRING)
                        {
                            debugValue.Value = value;
                        }
                    }
                }
            }

            return(fault);
        }
示例#2
0
        /// <summary> Create a variable and its value.
        ///
        /// </summary>
        /// <param name="name">the name of the variable within the context of its parent.  For example,
        /// when resolving member "bar" of object "foo", the name will be "bar".
        /// </param>
        /// <param name="value">the variable's value.
        /// </param>
        public DVariable(String name, DValue value)
        {
            m_rawName = name;

            // If the name contains "::", then the name is of the form "namespace::name"
            if (name != null)
            {
                int doubleColon = name.LastIndexOf("::");                 //$NON-NLS-1$
                if (doubleColon >= 0)
                {
                    m_namespace = name.Substring(0, (doubleColon) - (0));
                    int at = m_namespace.IndexOf('@');
                    if (at != -1)
                    {
                        m_namespace = m_namespace.Substring(0, (at) - (0));
                    }
                    name = name.Substring(doubleColon + 2);
                }
            }

            m_name             = name;
            m_attribs          = value.getAttributes();
            m_nonProtoParentId = Value.UNKNOWN_ID;
            m_value            = value;
        }
示例#3
0
        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;
        }
示例#4
0
		/// <summary> Create a variable and its value.
		/// 
		/// </summary>
		/// <param name="name">the name of the variable within the context of its parent.  For example,
		/// when resolving member "bar" of object "foo", the name will be "bar".
		/// </param>
		/// <param name="value">the variable's value.
		/// </param>
		public DVariable(String name, DValue value)
		{
			m_rawName = name;
			
			// If the name contains "::", then the name is of the form "namespace::name"
			if (name != null)
			{
				int doubleColon = name.LastIndexOf("::"); //$NON-NLS-1$
				if (doubleColon >= 0)
				{
					m_namespace = name.Substring(0, (doubleColon) - (0));
					int at = m_namespace.IndexOf('@');
					if (at != - 1)
						m_namespace = m_namespace.Substring(0, (at) - (0));
					name = name.Substring(doubleColon + 2);
				}
			}
			
			m_name = name;
			m_attribs = value.getAttributes();
			m_nonProtoParentId = Value.UNKNOWN_ID;
			m_value = value;
		}
示例#5
0
		/// <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;
		}
示例#6
0
		/// <summary> Correlates the old list of stack frames, from the last time the player
		/// was suspended, with the new list of stack frames, attempting to guess
		/// which frames correspond to each other.  This is done so that
		/// Variable.hasValueChanged() can work correctly for local variables.
		/// </summary>
		private void  mapOldFramesToNew()
		{
			int oldSize = m_previousFrames.Count;
			int newSize = m_frames.Count;
			
			// discard all old frames (we will restore some of them below)
			DValue[] oldFrames = new DValue[oldSize];
			for (int depth = 0; depth < oldSize; depth++)
			{
				oldFrames[depth] = (DValue) m_previousValues.remove(Value.BASE_ID - depth);
			}
			
			// Start at the end of the stack (the stack frame farthest from the
			// current one), and try to match up stack frames
			int oldDepth = oldSize - 1;
			int newDepth = newSize - 1;
			while (oldDepth >= 0 && newDepth >= 0)
			{
				DStackContext oldFrame = (DStackContext) m_previousFrames[oldDepth];
				DStackContext newFrame = (DStackContext) m_frames[newDepth];
				if (oldFrame != null && newFrame != null)
				{
					if (stringsEqual(oldFrame.CallSignature, newFrame.CallSignature))
					{
						DValue frame = oldFrames[oldDepth];
						if (frame != null)
							m_previousValues.put(Value.BASE_ID - newDepth, frame);
					}
				}
				oldDepth--;
				newDepth--;
			}
		}
示例#7
0
		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);
					}
				}
			}
		}
示例#8
0
		internal virtual void  putValue(long id, DValue v)
		{
			if (id != Value.UNKNOWN_ID)
			{
				m_values.put((int) id, v);
			}
		}
示例#9
0
		/// <summary> Variables</summary>
		internal virtual DValue getOrCreateValue(long id)
		{
			DValue v = getValue(id);
			if (v == null)
			{
				v = new DValue(id);
				putValue(id, v);
			}
			return v;
		}
示例#10
0
		/// <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;
		}
示例#11
0
		/// <summary> Here's where some ugly stuff happens. Since our context contains
		/// more info than what's contained within the stackcontext, we
		/// augment it  with the variables.  Also, we build up a
		/// list of variables that appears under root, that can be
		/// accessed without further qualification; this includes args,
		/// locals and _global.
		/// </summary>
		internal virtual void  populateRootNode(DValue frame, System.Collections.ArrayList orderedChildList)
		{
			// first populate the stack node with children
			populateFrame(0, orderedChildList);
			
			/*
			* We mark it as members obtained so that we don't go to the player
			* and request it, which would be bad, since its our artifical creation.
			*/
			DValue base_Renamed = getOrCreateValue(Value.BASE_ID);
			base_Renamed.MembersObtained = true;
			
			/*
			* Technically, we don't need to create the following nodes, but
			* we like to give them nice type names
			*/
			
			// now let's create a _global node and attach it to base
		}