http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/concrete/DStackContext.java ---------------------------------------------------------------------- diff --git a/debugger/src/main/java/flash/tools/debugger/concrete/DStackContext.java b/debugger/src/main/java/flash/tools/debugger/concrete/DStackContext.java new file mode 100644 index 0000000..855082e --- /dev/null +++ b/debugger/src/main/java/flash/tools/debugger/concrete/DStackContext.java @@ -0,0 +1,176 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package flash.tools.debugger.concrete; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import flash.tools.debugger.Frame; +import flash.tools.debugger.Location; +import flash.tools.debugger.NoResponseException; +import flash.tools.debugger.NotConnectedException; +import flash.tools.debugger.NotSuspendedException; +import flash.tools.debugger.Session; +import flash.tools.debugger.Variable; + +public class DStackContext implements Frame +{ + private DModule m_source; + private String m_functionSignature; + private int m_depth; + private int m_module; + private int m_line; + private DVariable m_this; + private Map<String, DVariable> m_args; + private Map<String, DVariable> m_locals; + private List<DVariable> m_scopeChain; + private DLocation m_location; + private int m_swfIndex; /* index of swf that we halted within (really part of location) */ + private int m_offset; /* offset within swf where we halted. (really part of location) */ + private boolean m_populated; + private DVariable m_activationObject; + private int m_isolateId; + + public DStackContext(int module, int line, DModule f, long thisId /* bogus */, + String functionSignature, int depth, int isolateId) + { + 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<String, DVariable>(); // preserves order + m_locals = new LinkedHashMap<String, DVariable>(); // preserves order + m_scopeChain = new ArrayList<DVariable>(); + m_populated = false; + m_isolateId = isolateId; + m_location = new DLocation(m_source, line, isolateId); + } + + /* + * @see flash.tools.debugger.Frame#getLocation() + */ + public Location getLocation() + { + return m_location; + } + + /* + * @see flash.tools.debugger.Frame#getArguments(flash.tools.debugger.Session) + */ + public Variable[] getArguments(Session s) throws NoResponseException, NotSuspendedException, NotConnectedException + { + populate(s); + return m_args.values().toArray( new Variable[m_args.size()] ); + } + + /* + * @see flash.tools.debugger.Frame#getLocals(flash.tools.debugger.Session) + */ + public Variable[] getLocals(Session s) throws NoResponseException, NotSuspendedException, NotConnectedException + { + populate(s); + return m_locals.values().toArray( new Variable[m_locals.size()] ); + } + + /* + * @see flash.tools.debugger.Frame#getThis(flash.tools.debugger.Session) + */ + public Variable getThis(Session s) throws NoResponseException, NotSuspendedException, NotConnectedException + { + populate(s); + return getThis(); + } + + /* + * @see flash.tools.debugger.Frame#getScopeChain() + */ + public Variable[] getScopeChain(Session s) throws NoResponseException, NotSuspendedException, NotConnectedException + { + populate(s); + return m_scopeChain.toArray(new Variable[m_scopeChain.size()]); + } + + /* getters */ + public String getCallSignature() { return m_functionSignature; } + public int getModule() { return m_module; } + public int getLine() { return m_line; } + public DVariable getThis() { return m_this; } + + /* setters */ + void addArgument(DVariable v) { m_args.put(v.getName(), v); } + void addLocal(DVariable v) { m_locals.put(v.getName(), v); } + void addScopeChainEntry(DVariable v) { m_scopeChain.add(v); } + void removeAllArguments() { m_args.clear(); } + void removeAllLocals() { m_locals.clear(); m_activationObject = null; } + void removeAllScopeChainEntries() { m_scopeChain.clear(); } + void removeAllVariables() { removeAllLocals(); removeAllArguments(); removeAllScopeChainEntries(); } + void setDepth(int depth) { m_depth = depth; } + void setThis(DVariable v) { m_this = v; } + void setSwfIndex(int index) { m_swfIndex = index; } + void setOffset(int offset) { m_offset = offset; } + void setIsolateId(int id) { m_isolateId = id; } + void markStale() { m_populated = false; } // triggers a reload of variables. + + /** + * 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. + */ + void convertLocalToActivationObject(DVariable v) + { + m_activationObject = v; + m_locals.remove(v.getName()); + } + + /** + * Gets the activation object for this frame, or <code>null</code> + * if none. See bug FB-2674. + */ + DVariable getActivationObject() + { + return m_activationObject; + } + + /** + * Populate ensures that we have some locals and args. That is + * that we have triggered a InFrame call to the player + * @throws NoResponseException + * @throws NotSuspendedException + * @throws NotConnectedException + */ + void populate(Session s) throws NoResponseException, NotSuspendedException, NotConnectedException + { + if (!m_populated) + { + PlayerSession ses = ((PlayerSession)s); + ses.requestFrame(m_depth, m_isolateId); + + m_populated = true; + } + } + + public int getIsolateId() + { + return m_isolateId; + } +}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/concrete/DSuspendInfo.java ---------------------------------------------------------------------- diff --git a/debugger/src/main/java/flash/tools/debugger/concrete/DSuspendInfo.java b/debugger/src/main/java/flash/tools/debugger/concrete/DSuspendInfo.java new file mode 100644 index 0000000..e051c21 --- /dev/null +++ b/debugger/src/main/java/flash/tools/debugger/concrete/DSuspendInfo.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package flash.tools.debugger.concrete; + +import flash.tools.debugger.SuspendReason; + +/** + * The suspend information object returns information about the + * current halted state of the Player. + */ +public class DSuspendInfo +{ + int m_reason; + int m_actionIndex; // which script caused the halt + int m_offset; // offset into the actions that the player has halted + int m_previousOffset; // previous offset, if any, which lies on the same source line (-1 means unknown) + int m_nextOffset; // next offset, if any, which lies on the same source line (-1 means unknown) + + public DSuspendInfo() + { + m_reason = SuspendReason.Unknown; + m_actionIndex = -1; + m_offset = -1; + m_previousOffset = -1; + m_nextOffset = -1; + } + + public DSuspendInfo(int reason, int actionIndex, int offset, int previousOffset, int nextOffset) + { + m_reason = reason; + m_actionIndex = actionIndex; + m_offset = offset; + m_previousOffset = previousOffset; + m_nextOffset = nextOffset; + } + + public int getReason() { return m_reason; } + public int getActionIndex() { return m_actionIndex; } + public int getOffset() { return m_offset; } + public int getPreviousOffset() { return m_previousOffset; } + public int getNextOffset() { return m_nextOffset; } +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/concrete/DSwfInfo.java ---------------------------------------------------------------------- diff --git a/debugger/src/main/java/flash/tools/debugger/concrete/DSwfInfo.java b/debugger/src/main/java/flash/tools/debugger/concrete/DSwfInfo.java new file mode 100644 index 0000000..226dd72 --- /dev/null +++ b/debugger/src/main/java/flash/tools/debugger/concrete/DSwfInfo.java @@ -0,0 +1,323 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package flash.tools.debugger.concrete; + +import java.util.Map; + +import flash.swf.debug.DebugModule; +import flash.swf.debug.LineRecord; +import flash.tools.ActionLocation; +import flash.tools.debugger.InProgressException; +import flash.tools.debugger.Isolate; +import flash.tools.debugger.NoResponseException; +import flash.tools.debugger.Session; +import flash.tools.debugger.SourceFile; +import flash.tools.debugger.SwfInfo; +import flash.tools.debugger.events.FunctionMetaDataAvailableEvent; +import flash.util.IntMap; + +public class DSwfInfo implements SwfInfo +{ + private int m_index; + private long m_id; + private IntMap m_source; + private String m_path; + private String m_url; + private String m_host; + private int m_port; + private boolean m_swdLoading; + private int m_swfSize; + private int m_swdSize; + private int m_bpCount; + private int m_offsetCount; + private int m_scriptsExpected; + private int m_minId; // first script id in the swf + private int m_maxId; // last script id in this swf + private byte[] m_swf; // actual swf contents + private byte[] m_swd; // actual swd contents + private boolean m_unloaded; // set if the player has unloaded this swf + private Map<Long,Integer> m_local2Global; // local script id to global script id mapping table + private int m_numRefreshes; // number of refreshes we have taken + private int m_vmVersion; // version of the vm + + private boolean m_populated; // set if we have already tried to load swf/swd for this info + private LineFunctionContainer m_container; // used for pulling out detailed info about the swf + + private final static String UNKNOWN = PlayerSessionManager.getLocalizationManager().getLocalizedTextString("unknown"); //$NON-NLS-1$ + + public DSwfInfo(int index, int isolateId) + { + // defaults values of zero + m_id = 0; + m_index = index; + m_source = new IntMap(); + m_path = UNKNOWN; + m_url = UNKNOWN; + m_host = UNKNOWN; + m_port = 0; + m_swdLoading = true; + m_scriptsExpected = -1; // means not yet set by anyone! + m_isolateId = isolateId; + // rest default to null, 0 or false + } + + /** SwfInfo interface */ + public String getPath() { return m_path; } + public String getUrl() { return m_url; } + public int getSwfSize() { return m_swfSize; } + public int getSwdSize(Session s) throws InProgressException { swdLoaded(s); return m_swdSize; } + public boolean isUnloaded() { return m_unloaded; } + public boolean isProcessingComplete() { return isPopulated(); } + public boolean containsSource(SourceFile f) { return m_source.contains(f.getId()); } + + /* getters */ + public long getId() { return m_id; } + public String getHost() { return m_host; } + public int getPort() { return m_port; } + public int getSwdSize() { return m_swdSize; } + public int getRefreshCount() { return m_numRefreshes; } + public boolean isSwdLoading() { return m_swdLoading; } + public boolean isPopulated() { return m_populated; } + public byte[] getSwf() { return m_swf; } + public byte[] getSwd() { return m_swd; } + public int getSourceExpectedCount() { return m_scriptsExpected; } + public int getVmVersion() { return m_vmVersion; } + +// public int getBreakpointCount() throws InProgressException { swdLoading(); return m_bpCount; } +// public int getOffsetCount() { swdLoading(); return m_offsetCount; } + public int getSourceCount() { return m_source.size(); } + public int getFirstSourceId() { return m_minId; } + public int getLastSourceId() { return m_maxId; } + + public void setVmVersion(int vmVersion) { m_vmVersion = vmVersion; } + public void setUnloaded() { m_unloaded = true; } + public void setSwf(byte[] swf) { m_swf = swf; } + public void setSwd(byte[] swd) { m_swd = swd; } + public void setPopulated() { m_swdLoading = false; m_populated = true; } // no more waiting for swd, we're done + public void setSourceExpectedCount(int c) { m_scriptsExpected = c; } + + public void addSource(int i, DModule m) { m_source.put(i, m); } + + /** + * Return the number of sources that we have + */ + public int getSourceCount(Session s) throws InProgressException + { + // only if we don't have it all yet + // then try to force a load + if (!hasAllSource()) + swdLoaded(s); + + return getSourceCount(); + } + + /** + * Return a list of our sources + */ + public SourceFile[] getSourceList(Session s) throws InProgressException + { + // only if we don't have it all yet + // then try to force a load + if (!hasAllSource()) + swdLoaded(s); + + return (SourceFile[])m_source.valuesToArray( new SourceFile[m_source.size()] ); + } + + /** + * Make sure that the player has loaded our swd. If not + * we continue InProgressException to query the player for when its complete. + * At some point we give up and finally admit that + * we don't have a swd associated with this swf. + */ + void swdLoaded(Session s) throws InProgressException + { + if (isSwdLoading() && !isUnloaded()) + { + // make the request +// System.out.println("Swdloaded " + m_isolateId); + try { ((PlayerSession)s).requestSwfInfo(m_index, m_isolateId); } catch(NoResponseException nre) {} + + // I should now be complete + if (!m_swdLoading) + ; // done! + else if (getSourceExpectedCount() > -1 && m_numRefreshes > 10) + setPopulated(); // tried too many times, so bail big time, no swd available (only if we already have our expected count) + else + throw new InProgressException(); // still loading!!! + } + } + + /** + * This method returns true once we have all the scripts + * that we expect to ever have. We can get the information about + * how many scripts we should get from two sources, 1) we may + * get an InSwfInfo message from the player which contains + * this value and 2) we may get a InNumScript message which + * contains a script count. A small caveat of course, is that + * in case 1. we may also not get the a value if the swd has + * not been fully processed by the player yet. + */ + public boolean hasAllSource() + { + boolean yes = false; + int expect = getSourceExpectedCount(); + int have = getSourceCount(); + + // if they are equal we are done, unless + // our expectation has not been set and have not yet loaded our swd + if (expect == -1 && isSwdLoading()) + yes = false; + else if (expect == have) + yes = true; + else + yes = false; + + return yes; + } + + public void freshen(long id, String path, String url, String host, long port, boolean swdLoading, long swfSize, long swdSize, long bpCount, long offsetCount, long scriptCount, Map<Long,Integer> map, int minId, int maxId) + { + m_id = (int)id; + m_path = path; + m_url = url; + m_host = host; + m_port = (int)port; + m_swfSize = (int)swfSize; + m_swdSize = (int)swdSize; + m_bpCount = (int)bpCount; + m_offsetCount = (int)offsetCount; + m_local2Global = map; + m_minId = (swdSize > 0) ? minId : 0; + m_maxId = (swdSize > 0) ? maxId : 0; + m_swdLoading = swdLoading; + m_numRefreshes++; + + // only touch expected count if swd already loaded + if (!swdLoading) + m_scriptsExpected = (int)scriptCount; + } + + /** + * Locate the given offset within the swf + */ + public ActionLocation locate(int offset) + { + return m_container.locationLessOrEqualTo(offset); + } + + /** + * Ask the container to locate the next line + * record following the location specified in the + * location, without spilling over into the next + * action list + */ + public ActionLocation locateSourceLineEnd(ActionLocation l) + { + return locateSourceLineEnd(l, -1); + } + + public ActionLocation locateSourceLineEnd(ActionLocation l, int stopAt) + { + ActionLocation end = m_container.endOfSourceLine(l); + if (stopAt > -1 && end.at > stopAt) + end.at = stopAt; + return end; + } + + /** + * Use the local2global script id map that was provided by the + * Player, so that we can take the local id contained in the swd + * and convert it to a global one that the player has annointed + * to this script. + */ + int local2Global(long id) + { + Integer g = m_local2Global.get(id); + if (g != null) + id = g.intValue(); + + return (int) id; + } + + /** + * Freshen the contents of this object with the given swf info + * The items that we touch are all swd related, as everything else + * has arrriave + */ + + // temporary while we parse + DManager m_manager; + private int m_isolateId = Isolate.DEFAULT_ID; + + /** + * Extracts information out of the SWF/SWD in order to populate + * function line number tables in SourceFile variabels. + */ + public void parseSwfSwd(DManager manager) + { + m_manager = manager; + + // suck in the swf/swd into action lists and then walk the lists + // looking for LineRecords + m_container = new LineFunctionContainer(m_swf, m_swd); + m_container.combForLineRecords(this); + + // we are done, sucess or no + setPopulated(); + + // log event that we have complete done + manager.addEvent(new FunctionMetaDataAvailableEvent()); + m_manager = null; + } + + /** + * This is a callback function from LineFunctionContainer.combForLineRecords() + * We extract what we want and then update the associated module + */ + public void processLineRecord(ActionLocation where, LineRecord r) + { + int line = r.lineno; + String func = (where.function == null) ? null : where.function.name; + DebugModule dm = r.module; + + // locate the source file + int id = -1; + DModule module; + + if (dm == null || where.at == -1) + ; + else if ( (id = local2Global(dm.id)) < 0 ) + ; + else if ( (module = m_manager.getSource(id, Isolate.DEFAULT_ID)) == null ) + ; + else + module.addLineFunctionInfo(where.actions.getOffset(where.at), line, func); + } + + /* for debugging */ + @Override + public String toString() { + return m_path; + } + + @Override + public int getIsolateId() { + return m_isolateId; + } +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/concrete/DValue.java ---------------------------------------------------------------------- diff --git a/debugger/src/main/java/flash/tools/debugger/concrete/DValue.java b/debugger/src/main/java/flash/tools/debugger/concrete/DValue.java new file mode 100644 index 0000000..2652ba1 --- /dev/null +++ b/debugger/src/main/java/flash/tools/debugger/concrete/DValue.java @@ -0,0 +1,534 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package flash.tools.debugger.concrete; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import flash.tools.debugger.Isolate; +import flash.tools.debugger.NoResponseException; +import flash.tools.debugger.NotConnectedException; +import flash.tools.debugger.NotSuspendedException; +import flash.tools.debugger.Session; +import flash.tools.debugger.Value; +import flash.tools.debugger.ValueAttribute; +import flash.tools.debugger.Variable; +import flash.tools.debugger.VariableType; +import flash.tools.debugger.expression.Context; + +/** + * Implementation of an ActionScript value. + */ +public class DValue implements Value +{ + /** @see VariableType */ + private int m_type; + + /** @see Variable#getTypeName() */ + private String m_typeName; + + /** @see Variable#getClassName() */ + private String m_className; + + /** @see ValueAttribute */ + private int m_attribs; + + /** Maps "varname" (without its namespace) to a Variable */ + private Map<String, DVariable> m_members; + + /** + * Either my own ID, or else my parent's ID if I am <code>__proto__</code>. + */ + long m_nonProtoId; + + /** + * <code>m_value</code> can have one of several possible meanings: + * + * <ul> + * <li> If this variable's value is an <code>Object</code> or a <code>MovieClip</code>, + * then <code>m_value</code> contains the ID of the <code>Object</code> or + * <code>MovieClip</code>, stored as a <code>Long</code>. </li> + * <li> If this variable refers to a Getter which has not yet been invoked, then + * <code>m_value</code> contains the ID of the Getter, stored as a + * <code>Long</code>. </li> + * <li> If this variable's value is <code>undefined</code>, then <code>m_value</code> + * will be equal to <code>Value.UNDEFINED</code>. + * <li> Otherwise, this variable's value is a simple type such as <code>int</code> or + * <code>String</code>, in which case <code>m_value</code> holds the actual value. + * </ul> + */ + private Object m_value; + + /** + * The list of classes that contributed members to this object, from + * the class itself all the way down to Object. + */ + private String[] m_classHierarchy; + + /** + * How many members of <code>m_classHierarchy</code> actually contributed + * members to this object. + */ + private int m_levelsWithMembers; + + private Session m_session; + + /** Maps duplicate private "varname" to a list of Variable objects */ + private Map<String, List<DVariable>> m_inheritedPrivates; + + private int m_isolateId; + + + /** + * Create a top-level variable which has no parent. This may be used for + * _global, _root, stack frames, etc. + * + * @param id the ID of the variable + */ + public DValue(long id, int isolateId) + { + init(VariableType.UNKNOWN, null, null, 0, new Long(id)); + setIsolateId(isolateId); + } + + /** + * Create a value. + * + * @param type see <code>VariableType</code> + * @param typeName + * @param className + * @param attribs + * the attributes of this value; see <code>ValueAttribute</code> + * @param value + * for an Object or MovieClip, this should be a Long which contains the + * ID of this variable. For a variable of any other type, such as integer + * or string, this should be the value of the variable. + * @param isolateId + * the worker to which this value belongs + */ + public DValue(int type, String typeName, String className, int attribs, Object value, int isolateId) + { + init(type, typeName, className, attribs, value); + setIsolateId(isolateId); + } + + /** + * Constructs a DValue for a primitive value (null, undefined, Boolean, Number, String). + * + * There is nothing special about these objects -- it would be just as legitimate for + * anyone who wants a Value for a primitive to make their own subclass of Value. + */ + public static DValue forPrimitive(Object primitiveValue, int isolateId) + { + if (primitiveValue == null) + return new DValue(VariableType.NULL, "null", "", 0, primitiveValue, isolateId); //$NON-NLS-1$ //$NON-NLS-2$ + else if (primitiveValue == Value.UNDEFINED) + return new DValue(VariableType.UNDEFINED, "undefined", "", 0, primitiveValue, isolateId); //$NON-NLS-1$ //$NON-NLS-2$ + else if (primitiveValue instanceof Boolean) + return new DValue(VariableType.BOOLEAN, "Boolean", "", 0, primitiveValue, isolateId); //$NON-NLS-1$ //$NON-NLS-2$ + else if (primitiveValue instanceof Double) + return new DValue(VariableType.NUMBER, "Number", "", 0, primitiveValue, isolateId); //$NON-NLS-1$ //$NON-NLS-2$ + else if (primitiveValue instanceof String) + return new DValue(VariableType.STRING, "String", "", 0, primitiveValue, isolateId); //$NON-NLS-1$ //$NON-NLS-2$ + assert false; + return null; + } + + /** + * Initialize a variable. + * + * For the meanings of the arguments, see the DVariable constructor. + */ + private void init(int type, String typeName, String className, int attribs, Object value) + { + if (value == null && type == VariableType.UNDEFINED) + value = Value.UNDEFINED; + + m_type = type; + m_typeName = typeName; + m_className = className; + m_attribs = attribs; + m_value = value; + m_members = null; + m_inheritedPrivates = null; + m_nonProtoId = getId(); + m_isolateId = Isolate.DEFAULT_ID; + } + + public int getIsolateId() { + return m_isolateId; + } + + public void setIsolateId(int isolateid) { + m_isolateId = isolateid; + } + + /* + * @see flash.tools.debugger.Value#getAttributes() + */ + public int getAttributes() + { + return m_attribs; + } + + /* + * @see flash.tools.debugger.Value#getClassName() + */ + public String getClassName() + { + return m_className; + } + + /* + * @see flash.tools.debugger.Value#getId() + */ + public long getId() + { + // see if we support an id concept + if (m_value instanceof Long) + return ((Long)m_value).longValue(); + else + return Value.UNKNOWN_ID; + } + + /* + * @see flash.tools.debugger.Value#getMemberCount(flash.tools.debugger.Session) + */ + public int getMemberCount(Session s) throws NotSuspendedException, + NoResponseException, NotConnectedException + { + obtainMembers(s); + return (m_members == null) ? 0 : m_members.size(); + } + + /* + * @see flash.tools.debugger.Value#getMemberNamed(flash.tools.debugger.Session, java.lang.String) + */ + public Variable getMemberNamed(Session s, String name) + throws NotSuspendedException, NoResponseException, + NotConnectedException + { + obtainMembers(s); + return findMember(name); + } + + /* + * @see flash.tools.debugger.Value#getClassHierarchy(boolean) + */ + public String[] getClassHierarchy(boolean allLevels) { + if (allLevels) { + return m_classHierarchy; + } else { + String[] partialClassHierarchy; + + if (m_classHierarchy != null) + { + partialClassHierarchy = new String[m_levelsWithMembers]; + System.arraycopy(m_classHierarchy, 0, partialClassHierarchy, 0, m_levelsWithMembers); + } + else + { + partialClassHierarchy = new String[0]; + } + return partialClassHierarchy; + } + } + + /* TODO should this really be public? */ + public DVariable findMember(String named) + { + if (m_members == null) + return null; + else + return m_members.get(named); + } + + /* + * @see flash.tools.debugger.Value#getMembers(flash.tools.debugger.Session) + */ + public Variable[] getMembers(Session s) throws NotSuspendedException, + NoResponseException, NotConnectedException + { + obtainMembers(s); + + /* find out the size of the array */ + int count = getMemberCount(s); + DVariable[] ar = new DVariable[count]; + + if (count > 0) + { + count = 0; + Iterator<DVariable> itr = m_members.values().iterator(); + while(itr.hasNext()) + { + DVariable sf = itr.next(); + ar[count++] = sf; + } + + // sort the member list by name + Arrays.sort(ar); + } + + return ar; + } + + /** + * WARNING: this call will initiate a call to the session to obtain the members + * the first time around. + * @throws NotConnectedException + * @throws NoResponseException + * @throws NotSuspendedException + */ + private void obtainMembers(Session s) throws NotSuspendedException, NoResponseException, NotConnectedException + { + if (s == null) + s = m_session; + else + m_session = s; + + if (m_members == null && s != null) + { + // performing a get on this variable obtains all its members + long id = getId(); + if (id != Value.UNKNOWN_ID) + { + if (((PlayerSession)s).getRawValue(id, m_isolateId) == this) + ((PlayerSession)s).obtainMembers(id, m_isolateId); + if (m_members != null) + { + Iterator<DVariable> iter = m_members.values().iterator(); + while (iter.hasNext()) + { + Object next = iter.next(); + if (next instanceof DVariable) + { + ((DVariable)next).setSession(s); + } + } + } + } + } + } + + public boolean membersObtained() + { + return (getId() == UNKNOWN_ID || m_members != null); + } + + public void setMembersObtained(boolean obtained) + { + if (obtained) + { + if (m_members == null) + m_members = Collections.emptyMap(); + if (m_inheritedPrivates == null) + m_inheritedPrivates = Collections.emptyMap(); + } + else + { + m_members = null; + m_inheritedPrivates = null; + } + } + + public void addMember(DVariable v) + { + if (m_members == null) + m_members = new HashMap<String, DVariable>(); + + // 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.getId(); //$NON-NLS-1$ // TODO is this right? + v.m_nonProtoParentId = m_nonProtoId; + + m_members.put(name, v); + } + + public void addInheritedPrivateMember(DVariable v) + { + if (m_inheritedPrivates == null) + m_inheritedPrivates = new HashMap<String, List<DVariable>>(); + + // 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.getId(); //$NON-NLS-1$ // TODO is this right? + v.m_nonProtoParentId = m_nonProtoId; + List<DVariable> resultList = m_inheritedPrivates.get(name); + if (resultList == null) { + resultList = new ArrayList<DVariable>(); + resultList.add(v); + m_inheritedPrivates.put(name, resultList); + } + else + resultList.add(v); + //m_inheritedPrivates.put(name, v); + } + + public void removeAllMembers() + { + m_members = null; + m_inheritedPrivates = null; + } + + /* + * @see flash.tools.debugger.Value#getType() + */ + public int getType() + { + return m_type; + } + + /* + * @see flash.tools.debugger.Value#getTypeName() + */ + public String getTypeName() + { + return m_typeName; + } + + /* + * @see flash.tools.debugger.Value#getValueAsObject() + */ + public Object getValueAsObject() + { + return m_value; + } + + /* + * @see flash.tools.debugger.Value#getValueAsString() + */ + public String getValueAsString() + { + return getValueAsString(m_value); + } + + /** + * @param value an object which might be one of these types: + * Boolean, Integer, Long, Double, String, Value.UNDEFINED (representing + * the value 'undefined'); or null. + */ + public static String getValueAsString(Object value) + { + if (value == null) + return "null"; //$NON-NLS-1$ + + if (value instanceof Double) + { + // Java often formats whole numbers in ugly ways. For example, + // the number 3 might be formatted as "3.0" and, even worse, + // the number 12345678 might be formatted as "1.2345678E7" ! + // So, if the number has no fractional part, then we override + // the default display behavior. + double doubleValue = ((Double)value).doubleValue(); + long longValue = (long) doubleValue; + if (doubleValue == longValue) + return Long.toString(longValue); + } + + return value.toString(); + } + + /* + * @see flash.tools.debugger.Value#isAttributeSet(int) + */ + public boolean isAttributeSet(int variableAttribute) + { + return (m_attribs & variableAttribute) != 0; + } + + public void setTypeName(String s) { m_typeName = s; } + public void setClassName(String s) { m_className = s; } + public void setType(int t) { m_type = t; } + public void setValue(Object o) { m_value = o; } + public void setAttributes(int f) { m_attribs = f; } + + public void setClassHierarchy(String[] classHierarchy, int levelsWithMembers) + { + m_classHierarchy = classHierarchy; + m_levelsWithMembers = levelsWithMembers; + } + + public String membersToString() + { + StringBuilder sb = new StringBuilder(); + + /* find out the size of the array */ + if (m_members == null) + sb.append(PlayerSessionManager.getLocalizationManager().getLocalizedTextString("empty")); //$NON-NLS-1$ + else + { + Iterator<DVariable> itr = m_members.values().iterator(); + while(itr.hasNext()) + { + DVariable sf = itr.next(); + sb.append(sf); + sb.append(",\n"); //$NON-NLS-1$ + } + } + return sb.toString(); + } + + public void setSession(Session s) + { + m_session = s; + } + + /** + * Necessary for expression evaluation. + * @see Context#lookup(Object) + */ + @Override + public String toString() { return getValueAsString(); } + + public Variable[] getPrivateInheritedMembers() { + if (m_inheritedPrivates == null) + return new DVariable[0]; + + ArrayList<DVariable> finalList = new ArrayList<DVariable>(); + + Iterator<List<DVariable>> itr = m_inheritedPrivates.values().iterator(); + while(itr.hasNext()) + { + List<DVariable> varList = itr.next(); + finalList.addAll(varList); + } + + DVariable[] ar = finalList.toArray(new DVariable[0]); + // sort the member list by name + Arrays.sort(ar); + + return ar; + } + + public Variable[] getPrivateInheritedMemberNamed(String name) { + if (m_inheritedPrivates == null) + return new DVariable[0]; + List<DVariable> list = m_inheritedPrivates.get(name); + if (list != null) { + return list.toArray(new Variable[0]); + } + return new DVariable[0]; + } +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/concrete/DVariable.java ---------------------------------------------------------------------- diff --git a/debugger/src/main/java/flash/tools/debugger/concrete/DVariable.java b/debugger/src/main/java/flash/tools/debugger/concrete/DVariable.java new file mode 100644 index 0000000..16d6799 --- /dev/null +++ b/debugger/src/main/java/flash/tools/debugger/concrete/DVariable.java @@ -0,0 +1,517 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package flash.tools.debugger.concrete; + +import flash.tools.debugger.NoResponseException; +import flash.tools.debugger.NotConnectedException; +import flash.tools.debugger.NotSuspendedException; +import flash.tools.debugger.PlayerDebugException; +import flash.tools.debugger.Session; +import flash.tools.debugger.SessionManager; +import flash.tools.debugger.Value; +import flash.tools.debugger.Variable; +import flash.tools.debugger.VariableAttribute; +import flash.tools.debugger.VariableType; +import flash.tools.debugger.events.FaultEvent; +import flash.tools.debugger.expression.Context; + +public class DVariable implements Variable, Comparable +{ + /** + * The raw name, exactly as it came back from the Player. For example, this + * might be <code>mynamespace@12345678::myvar</code>, which indicates that + * the variable is in namespace "mynamespace", which has atom 12345678. + */ + private String m_rawName; + + /** Just name, without namespace */ + private String m_name; + + /** @see Variable#getNamespace() */ + private String m_namespace = ""; //$NON-NLS-1$ + + /** @see VariableAttribute */ + private int m_attribs; + + /** + * The variable's value. + */ + protected Value m_value; + + /** + * Whether we have fired the getter for this value. Only applicable if + * the VariableAttribute.HAS_GETTER attribute is set. + */ + private boolean m_firedGetter; + + /** + * The class in which this member was actually defined. For example, if class + * B extends class A, and class A has member variable V, then for variable + * V, the defining class is always "A", even though the parent variable might + * be an instance of class B. + */ + private String m_definingClass; + + /** + * The variable's "level" -- see <code>Variable.getLevel()</code> + * @see Variable#getLevel() + */ + private byte m_level; + + /** + * The session object that was used when creating this variable, if known. + */ + private Session m_session; + + /** + * My parent's <code>m_nonProtoId</code>. In other words, either my + * parent's ID, or else my parent's parent's ID if my parent is <code>__proto__</code>. + */ + long m_nonProtoParentId; + + /** + * The worker to which this variable belongs. + */ + private int m_isolateId; + + /** + * Create a variable and its value. + * + * @param 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 value + * the variable's value. + */ + public DVariable(String name, DValue value, int isolateId) + { + m_rawName = name; + m_attribs = value.getAttributes(); + + // If the name contains "::", then the name is of the form "namespace::name" + if (name != null) + { + /** + * anirudhs - Compute namespace only for non-public variables. + * This check helps us avoid cases where public variables have + * dynamic keys with :: in them. See FB-26126. + */ + if (!isAttributeSet(VariableAttribute.PUBLIC_SCOPE)) + { + int doubleColon = name.lastIndexOf("::"); //$NON-NLS-1$ + if (doubleColon >= 0) + { + m_namespace = name.substring(0, doubleColon); + int at = m_namespace.indexOf('@'); + if (at != -1) + m_namespace = m_namespace.substring(0, at); + + name = name.substring(doubleColon+2); + } + } + } + + m_name = name; + m_nonProtoParentId = Value.UNKNOWN_ID; + m_value = value; + value.setSession(m_session); + m_isolateId = isolateId; + } + + /* getters/setters */ + public String getName() { return m_name; } + public int getAttributes() { return m_attribs; } + public String getNamespace() { return m_namespace; } + public int getScope() { return m_attribs & VariableAttribute.SCOPE_MASK; } + public int getLevel() { return m_level; } + public String getDefiningClass() { return m_definingClass; } + + public int getIsolateId() { + return m_isolateId; + } + + public void makePublic() + { + int attributes = getAttributes(); + attributes &= ~VariableAttribute.SCOPE_MASK; + attributes |= VariableAttribute.PUBLIC_SCOPE; + setAttributes(attributes); + + m_namespace = ""; //$NON-NLS-1$ + } + + /* + * @see flash.tools.debugger.Variable#getValue() + */ + public Value getValue() + { + if (m_session != null && m_session.getPreference(SessionManager.PREF_INVOKE_GETTERS) != 0) { + try { + invokeGetter(m_session); + } catch (NotSuspendedException e) { + // fall through -- return raw value without invoking getter + } catch (NoResponseException e) { + // fall through -- return raw value without invoking getter + } catch (NotConnectedException e) { + // fall through -- return raw value without invoking getter + } + } + + return m_value; + } + + /* + * @see flash.tools.debugger.Variable#hasValueChanged(flash.tools.debugger.Session) + */ + public boolean hasValueChanged(Session s) + { + boolean hasValueChanged = false; + if (s instanceof PlayerSession) + { + Value previousParent = ((PlayerSession)s).getPreviousValue(m_nonProtoParentId, m_isolateId); + if (previousParent != null) + { + try { + Variable previousMember = previousParent.getMemberNamed(null, getName()); + // If the old variable had a getter but never invoked that getter, + // then it's too late, we don't know the old value. + if (previousMember instanceof DVariable && !previousMember.needsToInvokeGetter()) + { + Value previousValue = ((DVariable)previousMember).m_value; + if (previousValue != null) + { + String previousValueAsString = previousValue.getValueAsString(); + if (previousValueAsString != null) + { + if (!previousValueAsString.equals(getValue().getValueAsString())) + { + hasValueChanged = true; + } + } + } + } + } catch (PlayerDebugException e) { + // ignore + } + } + } + return hasValueChanged; + } + + /* + * @see flash.tools.debugger.Session#setScalarMember(int, java.lang.String, int, java.lang.String) + */ + public FaultEvent setValue(Session s, int type, String value) throws NotSuspendedException, NoResponseException, NotConnectedException + { + return ((PlayerSession)s).setScalarMember(m_nonProtoParentId, m_rawName, type, value, m_isolateId); + } + + /* + * @see flash.tools.debugger.Variable#isAttributeSet(int) + */ + public boolean isAttributeSet(int att) + { + if ((att & VariableAttribute.SCOPE_MASK) == att) + return (getScope() == att); + else + return ( ( (getAttributes() & att) == att) ? true : false ); + } + + public void clearAttribute(int att) + { + if ((att & VariableAttribute.SCOPE_MASK) == att) + m_attribs = (m_attribs & ~VariableAttribute.SCOPE_MASK) | VariableAttribute.PUBLIC_SCOPE; + else + m_attribs &= ~att; + } + + public void setAttribute(int att) + { + if ((att & VariableAttribute.SCOPE_MASK) == att) + m_attribs = (m_attribs & ~VariableAttribute.SCOPE_MASK) | att; + else + m_attribs |= att; + } + + public String getRawName() + { + return m_rawName; + } + + /* + * @see flash.tools.debugger.Variable#getQualifiedName() + */ + public String getQualifiedName() + { + if (m_namespace.length() > 0) + return m_namespace + "::" + m_name; //$NON-NLS-1$ + else + return m_name; + } + + /** + * Comparator interface for sorting Variables + */ + public int compareTo(Object o2) + { + Variable v2 = (Variable)o2; + + String n1 = getName(); + String n2 = v2.getName(); + + return String.CASE_INSENSITIVE_ORDER.compare(n1, n2); + } + + /* + * @see flash.tools.debugger.Variable#needsToFireGetter() + */ + public boolean needsToInvokeGetter() + { + // If this variable has a getter, and the getter has not yet been invoked + return (isAttributeSet(VariableAttribute.HAS_GETTER) && m_value.getId() != Value.UNKNOWN_ID && !m_firedGetter); + } + + /* + * @see flash.tools.debugger.Value#invokeGetter(flash.tools.debugger.Session) + */ + public void invokeGetter(Session s) throws NotSuspendedException, + NoResponseException, NotConnectedException { + if (needsToInvokeGetter()) + { + PlayerSession playerSession = (PlayerSession) s; + + // If this Variable is stale (that is, the program has run since this Variable + // was created), then we can't invoke the getter. + if (playerSession.getRawValue(m_value.getId(), m_isolateId) == m_value) + { + // temporarily turn on "invoke getters" preference + int oldInvokeGetters = playerSession.getPreference(SessionManager.PREF_INVOKE_GETTERS); + playerSession.setPreference(SessionManager.PREF_INVOKE_GETTERS, 1); + + try { + // fire the getter using the original object id. make sure we get something reasonable back + Value v = playerSession.getValue(m_nonProtoParentId, getRawName(), m_isolateId); + if (v != null) + { + m_value = v; + m_firedGetter = true; + if (m_value instanceof DValue) + ((DValue)m_value).setSession(s); + } + } finally { + playerSession.setPreference(SessionManager.PREF_INVOKE_GETTERS, oldInvokeGetters); + } + } + } + } + + public void setName(String s) { m_name = s; } + public void setAttributes(int f) { m_attribs = f; ((DValue)getValue()).setAttributes(f); } + + public void setSession(Session s) + { + m_session = s; + if (m_value instanceof DValue) + ((DValue)m_value).setSession(s); + } + + public void setDefiningClass(int level, String definingClass) + { + m_level = (byte) Math.min(level, 255); + m_definingClass = definingClass; + } + + /** + * Added so that expressions such as <code>a.b.c = e.f</code> work in the command-line interface. + * @see Context#lookup(Object) + */ + @Override + public String toString() { return getValue().getValueAsString(); } + + /** + * Return the internal player string type representation for this variable. + * Currently used for passing in the type to the Player when doing + * a set variable command + */ + public static String typeNameFor(int type) + { + String s = "string"; //$NON-NLS-1$ + switch(type) + { + case VariableType.NUMBER: + s = "number"; //$NON-NLS-1$ + break; + + case VariableType.BOOLEAN: + s = "boolean"; //$NON-NLS-1$ + break; + + case VariableType.STRING: + s = "string"; //$NON-NLS-1$ + break; + + case VariableType.OBJECT: + s = "object"; //$NON-NLS-1$ + break; + + case VariableType.FUNCTION: + s = "function"; //$NON-NLS-1$ + break; + + case VariableType.MOVIECLIP: + s = "movieclip"; //$NON-NLS-1$ + break; + + case VariableType.NULL: + s = "null"; //$NON-NLS-1$ + break; + + case VariableType.UNDEFINED: + case VariableType.UNKNOWN: + default: + s = "undefined"; //$NON-NLS-1$ + break; + } + return s; + } + + /** + * These values are obtained directly from the Player. + * See ScriptObject in splay.h. + */ + public static final int kNormalObjectType = 0; + public static final int kXMLSocketObjectType = 1; + public static final int kTextFieldObjectType = 2; + public static final int kButtonObjectType = 3; + public static final int kNumberObjectType = 4; + public static final int kBooleanObjectType = 5; + public static final int kNativeStringObject = 6; + public static final int kNativeArrayObject = 7; + public static final int kDateObjectType = 8; + public static final int kSoundObjectType = 9; + public static final int kNativeXMLDoc = 10; + public static final int kNativeXMLNode = 11; + public static final int kNativeCameraObject = 12; + public static final int kNativeMicrophoneObject = 13; + public static final int kNativeCommunicationObject = 14; + public static final int kNetConnectionObjectType = 15; + public static final int kNetStreamObjectType = 16; + public static final int kVideoObjectType = 17; + public static final int kTextFormatObjectType = 18; + public static final int kSharedObjectType = 19; + public static final int kSharedObjectDataType = 20; + public static final int kPrintJobObjectType = 21; + public static final int kMovieClipLoaderObjectType = 22; + public static final int kStyleSheetObjectType = 23; + public static final int kFapPacketDummyObject = 24; + public static final int kLoadVarsObject = 25; + public static final int kTextSnapshotType = 26; + + public static String classNameFor(long clsType, boolean isMc) + { + String clsName; + switch ((int)clsType) + { + case kNormalObjectType: + clsName = (isMc) ? "MovieClip" : "Object"; //$NON-NLS-1$ //$NON-NLS-2$ + break; + case kXMLSocketObjectType: + clsName = "XMLSocket"; //$NON-NLS-1$ + break; + case kTextFieldObjectType: + clsName = "TextField"; //$NON-NLS-1$ + break; + case kButtonObjectType: + clsName = "Button"; //$NON-NLS-1$ + break; + case kNumberObjectType: + clsName = "Number"; //$NON-NLS-1$ + break; + case kBooleanObjectType: + clsName = "Boolean"; //$NON-NLS-1$ + break; + case kNativeStringObject: + clsName = "String"; //$NON-NLS-1$ + break; + case kNativeArrayObject: + clsName = "Array"; //$NON-NLS-1$ + break; + case kDateObjectType: + clsName = "Date"; //$NON-NLS-1$ + break; + case kSoundObjectType: + clsName = "Sound"; //$NON-NLS-1$ + break; + case kNativeXMLDoc: + clsName = "XML"; //$NON-NLS-1$ + break; + case kNativeXMLNode: + clsName = "XMLNode"; //$NON-NLS-1$ + break; + case kNativeCameraObject: + clsName = "Camera"; //$NON-NLS-1$ + break; + case kNativeMicrophoneObject: + clsName = "Microphone"; //$NON-NLS-1$ + break; + case kNativeCommunicationObject: + clsName = "Communication"; //$NON-NLS-1$ + break; + case kNetConnectionObjectType: + clsName = "Connection"; //$NON-NLS-1$ + break; + case kNetStreamObjectType: + clsName = "Stream"; //$NON-NLS-1$ + break; + case kVideoObjectType: + clsName = "Video"; //$NON-NLS-1$ + break; + case kTextFormatObjectType: + clsName = "TextFormat"; //$NON-NLS-1$ + break; + case kSharedObjectType: + clsName = "SharedObject"; //$NON-NLS-1$ + break; + case kSharedObjectDataType: + clsName = "SharedObjectData"; //$NON-NLS-1$ + break; + case kPrintJobObjectType: + clsName = "PrintJob"; //$NON-NLS-1$ + break; + case kMovieClipLoaderObjectType: + clsName = "MovieClipLoader"; //$NON-NLS-1$ + break; + case kStyleSheetObjectType: + clsName = "StyleSheet"; //$NON-NLS-1$ + break; + case kFapPacketDummyObject: + clsName = "FapPacket"; //$NON-NLS-1$ + break; + case kLoadVarsObject: + clsName = "LoadVars"; //$NON-NLS-1$ + break; + case kTextSnapshotType: + clsName = "TextSnapshot"; //$NON-NLS-1$ + break; + default: + clsName = PlayerSessionManager.getLocalizationManager().getLocalizedTextString("unknown") + "<" + clsType + ">"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + break; + } + return clsName; + } +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/concrete/DWatch.java ---------------------------------------------------------------------- diff --git a/debugger/src/main/java/flash/tools/debugger/concrete/DWatch.java b/debugger/src/main/java/flash/tools/debugger/concrete/DWatch.java new file mode 100644 index 0000000..35b2c41 --- /dev/null +++ b/debugger/src/main/java/flash/tools/debugger/concrete/DWatch.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package flash.tools.debugger.concrete; + +import flash.tools.debugger.Watch; + +/** + * Holder of Watchpoint information + */ +public class DWatch implements Watch +{ + long m_parentValueId; + String m_rawMemberName; // corresponds to Variable.getRawName() + int m_kind; + int m_tag; + int m_isolateId; + + public DWatch(long id, String name, int kind, int tag, int isolateId) + { + m_parentValueId = id; + m_rawMemberName = name; + m_kind = kind; + m_tag = tag; + m_isolateId = isolateId; + } + + public long getValueId() { return m_parentValueId; } + public String getMemberName() { return m_rawMemberName; } + public int getKind() { return m_kind; } + public int getTag() { return m_tag; } + + public int getIsolateId() { + return m_isolateId; + } +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/concrete/GetVariableFlag.java ---------------------------------------------------------------------- diff --git a/debugger/src/main/java/flash/tools/debugger/concrete/GetVariableFlag.java b/debugger/src/main/java/flash/tools/debugger/concrete/GetVariableFlag.java new file mode 100644 index 0000000..f7604ec --- /dev/null +++ b/debugger/src/main/java/flash/tools/debugger/concrete/GetVariableFlag.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package flash.tools.debugger.concrete; + +/** + * Flags to the OutGetVariable and OutGetVariableWhichInvokesGetter commands + * which are sent from the debugger to the player. + * + * These values must be kept in sync with 'enum OutGetVariableFlags' in + * the player's playerdebugger.h file. + * + * @author mmorearty + */ +public interface GetVariableFlag +{ + /** + * Indicates that if the variable which is being retrieved is a + * getter, then the player should invoke the getter and return + * the result. If this flag is *not* set, then the player will + * simply return the address of the getter itself. + */ + public static final int INVOKE_GETTER = 0x00000001; + + /** + * Indicates that if the variable which is being retrieved is a + * compound object (e.g. an instance of a class, as opposed to + * a string or int or something like that), then the player + * should also return all of the child members of the object. + */ + public static final int ALSO_GET_CHILDREN = 0x00000002; + + /** + * Indicates that when retrieving children, we only want fields + * and getters -- we are not interested in regular functions. + * This is an optimization to decrease the amount of network + * traffic. + */ + public static final int DONT_GET_FUNCTIONS = 0x00000004; + + /** + * Indicates that when retrieving children, we also want to + * know exactly which class each child was defined in. For + * example, if the variable is of class Foo which extends + * class Bar, we want to know which member fields came from + * Foo and which ones came from Bar. + */ + public static final int GET_CLASS_HIERARCHY = 0x00000008; +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/concrete/IsolatePlayerSession.java ---------------------------------------------------------------------- diff --git a/debugger/src/main/java/flash/tools/debugger/concrete/IsolatePlayerSession.java b/debugger/src/main/java/flash/tools/debugger/concrete/IsolatePlayerSession.java new file mode 100644 index 0000000..887b9c0 --- /dev/null +++ b/debugger/src/main/java/flash/tools/debugger/concrete/IsolatePlayerSession.java @@ -0,0 +1,221 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package flash.tools.debugger.concrete; + +import flash.tools.debugger.Frame; +import flash.tools.debugger.IsolateController; +import flash.tools.debugger.IsolateSession; +import flash.tools.debugger.Location; +import flash.tools.debugger.NoResponseException; +import flash.tools.debugger.NotConnectedException; +import flash.tools.debugger.NotSupportedException; +import flash.tools.debugger.NotSuspendedException; +import flash.tools.debugger.PlayerDebugException; +import flash.tools.debugger.SuspendedException; +import flash.tools.debugger.SwfInfo; +import flash.tools.debugger.Value; +import flash.tools.debugger.Variable; +import flash.tools.debugger.VersionException; +import flash.tools.debugger.Watch; +import flash.tools.debugger.expression.PlayerFaultException; + +/** + * Concrete implementation of IsolateSession. Re-routes + * calls to the *worker() method equivalents. + * @author anirudhs + * + */ +public class IsolatePlayerSession implements IsolateSession { + + private IsolateController fSession; + private int fIsolateId; + + public IsolatePlayerSession(int isolateId, IsolateController mainSession) { + fIsolateId = isolateId; + fSession = mainSession; + } + + @Override + public void resume() throws NotSuspendedException, NotConnectedException, + NoResponseException { + fSession.resumeWorker(fIsolateId); + } + + @Override + public void suspend() throws SuspendedException, NotConnectedException, + NoResponseException { + fSession.suspendWorker(fIsolateId); + } + + @Override + public boolean isSuspended() throws NotConnectedException { + return fSession.isWorkerSuspended(fIsolateId); + } + + @Override + public int suspendReason() throws NotConnectedException { + return fSession.suspendReasonWorker(fIsolateId); + } + + @Override + public Frame[] getFrames() throws NotConnectedException { + return fSession.getFramesWorker(fIsolateId); + } + + @Override + public void stepInto() throws NotSuspendedException, NoResponseException, + NotConnectedException { + fSession.stepIntoWorker(fIsolateId); + } + + @Override + public void stepOut() throws NotSuspendedException, NoResponseException, + NotConnectedException { + fSession.stepOutWorker(fIsolateId); + } + + @Override + public void stepOver() throws NotSuspendedException, NoResponseException, + NotConnectedException { + fSession.stepOverWorker(fIsolateId); + } + + @Override + public void stepContinue() throws NotSuspendedException, + NoResponseException, NotConnectedException { + fSession.stepContinueWorker(fIsolateId); + } + + @Override + public SwfInfo[] getSwfs() throws NoResponseException { + return fSession.getSwfsWorker(fIsolateId); + } + + @Override + public Location setBreakpoint(int fileId, int lineNum) + throws NoResponseException, NotConnectedException { + return fSession.setBreakpointWorker(fileId, lineNum, fIsolateId); + } + + @Override + public Watch[] getWatchList() throws NoResponseException, + NotConnectedException { + return fSession.getWatchListWorker(fIsolateId); + } + + @Override + public Variable[] getVariableList() throws NotSuspendedException, + NoResponseException, NotConnectedException, VersionException { + return fSession.getVariableListWorker(fIsolateId); + } + + @Override + public Value getValue(long valueId) throws NotSuspendedException, + NoResponseException, NotConnectedException { + return fSession.getValueWorker(valueId, fIsolateId); + } + + @Override + public Value getGlobal(String name) throws NotSuspendedException, + NoResponseException, NotConnectedException { + return fSession.getGlobalWorker(name, fIsolateId); + } + + @Override + public boolean evalIs(Value value, Value type) throws PlayerDebugException, + PlayerFaultException { + return fSession.evalIsWorker(value, type, fIsolateId); + } + + @Override + public boolean evalIs(Value value, String type) + throws PlayerDebugException, PlayerFaultException { + return fSession.evalIsWorker(value, type, fIsolateId); + } + + @Override + public boolean evalInstanceof(Value value, Value type) + throws PlayerDebugException, PlayerFaultException { + return fSession.evalInstanceofWorker(value, type, fIsolateId); + } + + @Override + public boolean evalInstanceof(Value value, String type) + throws PlayerDebugException, PlayerFaultException { + return fSession.evalInstanceofWorker(value, type, fIsolateId); + } + + @Override + public boolean evalIn(Value property, Value object) + throws PlayerDebugException, PlayerFaultException { + return fSession.evalInWorker(property, object, fIsolateId); + } + + @Override + public Value evalAs(Value value, Value type) throws PlayerDebugException, + PlayerFaultException { + return fSession.evalAsWorker(value, type, fIsolateId); + } + + @Override + public Value callFunction(Value thisObject, String functionName, + Value[] args) throws PlayerDebugException { + return fSession.callFunctionWorker(thisObject, functionName, args, fIsolateId); + } + + @Override + public Value callConstructor(String classname, Value[] args) + throws PlayerDebugException { + return fSession.callConstructorWorker(classname, args, fIsolateId); + } + + @Override + public boolean setExceptionBreakpoint(String exceptionClass) throws NoResponseException, NotConnectedException { + return fSession.setExceptionBreakpointWorker(exceptionClass, fIsolateId); + } + + @Override + public boolean clearExceptionBreakpoint(String exceptionClass) throws NoResponseException, NotConnectedException { + return fSession.clearExceptionBreakpointWorker(exceptionClass, fIsolateId); + } + + @Override + public void breakOnCaughtExceptions(boolean b) throws NotSupportedException, NoResponseException { + fSession.breakOnCaughtExceptions(b, fIsolateId); + } + + @Override + public boolean supportsWatchpoints() { + return fSession.supportsWatchpoints(fIsolateId); + } + + @Override + public boolean playerCanBreakOnAllExceptions() { + return fSession.playerCanBreakOnAllExceptions(fIsolateId); + } + + @Override + public boolean supportsWideLineNumbers() { + return fSession.supportsWideLineNumbers(fIsolateId); + } + + @Override + public boolean playerCanCallFunctions() { + return fSession.playerCanCallFunctions(fIsolateId); + } + +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/concrete/LineFunctionContainer.java ---------------------------------------------------------------------- diff --git a/debugger/src/main/java/flash/tools/debugger/concrete/LineFunctionContainer.java b/debugger/src/main/java/flash/tools/debugger/concrete/LineFunctionContainer.java new file mode 100644 index 0000000..57d1d31 --- /dev/null +++ b/debugger/src/main/java/flash/tools/debugger/concrete/LineFunctionContainer.java @@ -0,0 +1,162 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package flash.tools.debugger.concrete; + +import flash.swf.Action; +import flash.swf.ActionConstants; +import flash.swf.types.ActionList; +import flash.swf.actions.DefineFunction; +import flash.swf.debug.LineRecord; +import flash.tools.ActionLocation; +import flash.swf.MovieMetaData; +import flash.tools.SwfActionContainer; +import flash.util.Trace; + +/** + * This class extends the SwfActionContainer. + * It performs a number of passes on the master + * action list in order to extract line/function + * mapping information. + */ +public class LineFunctionContainer extends SwfActionContainer +{ + public LineFunctionContainer(byte[] swf, byte[] swd) + { + super(swf, swd); + + // now that we've got all the action lists + // nicely extracted and lined up we perform a + // bit of magic which modifies the DefineFunction + // records augmenting them with function names + // if they have have none. + buildFunctionNames(getMasterList(), getHeader().version); + } + + /** + * Use the action list located in the given location + * and return a new action location that corresponds + * to the next line record that is encountered + * after this location. This routine does not + * span into another action list. + */ + public ActionLocation endOfSourceLine(ActionLocation l) + { + ActionLocation current = new ActionLocation(l); + int size = l.actions.size(); + for(int i= l.at+1; i<size; i++) + { + // hit a line record => we done + Action a = l.actions.getAction(i); + if (a.code == ActionList.sactionLineRecord) + break; + + // hit a function => we are done + if ( (a.code == ActionConstants.sactionDefineFunction) || + (a.code == ActionConstants.sactionDefineFunction2) ) + break; + + current.at = i; + } + return current; + } + + /** + * This routine is called from the DSwfInfo object + * and is used to obtain LineRecord information + * from the ActionLists + */ + public void combForLineRecords(DSwfInfo info) + { + probeForLineRecords(getMasterList(), new ActionLocation(), info); + } + + /** + * This routine is called from the DSwfInfo object + * and is used to obtain LineRecord information + * from the ActionLists + * + * The ActionLocation record is used as a holding + * container for state as we traverse the lists + */ + void probeForLineRecords(ActionList list, ActionLocation where, DSwfInfo info) + { + int size = list.size(); + for(int i=0; i<size; i++) + { + try + { + // set our context + where.at = i; + where.actions = list; + + // pull the action + Action a = list.getAction(i); + + // then see if we need to traverse + if ( (a.code == ActionConstants.sactionDefineFunction) || + (a.code == ActionConstants.sactionDefineFunction2) ) + { + where.function = (DefineFunction)a; + probeForLineRecords(((DefineFunction)a).actionList, where, info); + where.function = null; + } + else if (a.code == ActionList.sactionLineRecord) + { + // hit a line record, so let's do our callback + info.processLineRecord(where, (LineRecord)a); + } + else if (a instanceof DummyAction) + { + // our dummy container, then we drop in + where.className = ((DummyAction)a).getClassName(); + probeForLineRecords(((DummyAction)a).getActionList(), where, info); + where.className = null; + } + } + catch(Exception e) + { + // this is fairly bad and probably means that we have corrupt line + // records in the swd, the exception being an ArrayIndexOutOfBoundsException. + // I've seen this in cases where a bad swc is built by authoring wherein a + // script id collision occurs and thus the offset table will contain references + // to line numbers that are non existent in one of the scripts. + // If its another type of exception...well, hopefully the trace message will + // help you track it down :) + if (Trace.error) + { + Trace.trace("Error processing ActionList at "+where.at+" at offset "+where.actions.getOffset(where.at)+" in swf "+info.getUrl()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + e.printStackTrace(); + } + } + } + } + + /** + * Go off and fill our DefineFunction records with function names. + * @see MovieMetaData#walkActions for a discussion on how this is done. + */ + void buildFunctionNames(ActionList list, int version) + { + int size = list.size(); + for(int i=0; i<size; i++) + { + DummyAction a = (DummyAction)list.getAction(i); + MovieMetaData.walkActions( a.getActionList(), version, null, a.getClassName(), null ); + } + } +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/main/java/flash/tools/debugger/concrete/NetscapePluginPlayer.java ---------------------------------------------------------------------- diff --git a/debugger/src/main/java/flash/tools/debugger/concrete/NetscapePluginPlayer.java b/debugger/src/main/java/flash/tools/debugger/concrete/NetscapePluginPlayer.java new file mode 100644 index 0000000..757c84d --- /dev/null +++ b/debugger/src/main/java/flash/tools/debugger/concrete/NetscapePluginPlayer.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package flash.tools.debugger.concrete; + +import java.io.File; + +/** + * @author mmorearty + */ +public class NetscapePluginPlayer extends AbstractPlayer +{ + /** + * @param path + */ + public NetscapePluginPlayer(File browserExe, File path) + { + super(browserExe, path); + } + + /* + * @see flash.tools.debugger.Player#getType() + */ + public int getType() + { + return NETSCAPE_PLUGIN; + } +}
