Added: Debugger - Remove watch

Added: Debugger - List of watches
Added: Debugger - Show flag of watch type (read/write)
Fixed: Debugger - Threading issues with multiple SWFs
Fixed: Debugger - Reading variables on 64bit flash players (like in browsers)
Enhanced debug game test SWFs
This commit is contained in:
Jindra Petřík
2026-02-22 18:33:27 +01:00
parent f447b4f286
commit 87f94768a0
36 changed files with 1239 additions and 369 deletions

View File

@@ -4,10 +4,14 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
### Added
- Debugger - Debugged SWF file name in the session title
- Debugger - Remove watch
- Debugger - List of watches
- Debugger - Show flag of watch type (read/write)
### Fixed
- [#2639] Export to FLA - missing sound streams
- Debugger - Threading issues with multiple SWFs
- Debugger - Reading variables on 64bit flash players (like in browsers)
## [25.1.1] - 2026-02-19
### Fixed

Binary file not shown.

Binary file not shown.

View File

@@ -6,6 +6,8 @@
<Include href="Button1.xml" itemIcon="0" loadImmediate="false" itemID="699362e3-000001d5" lastModified="1771267090"/>
<Include href="Button2.xml" itemIcon="0" loadImmediate="false" itemID="6993636a-000001dc" lastModified="1771267096"/>
<Include href="Button3.xml" itemIcon="0" loadImmediate="false" itemID="699367b4-000001e5" lastModified="1771268063"/>
<Include href="ButtonDown.xml" itemIcon="0" loadImmediate="false" itemID="6999ec93-000001e6" lastModified="1771695532"/>
<Include href="ButtonUp.xml" itemIcon="0" loadImmediate="false" itemID="6999ec8b-000001e1" lastModified="1771695510"/>
</symbols>
<timelines>
<DOMTimeline name="Scene 1">
@@ -43,6 +45,7 @@ stop();]]></script>
var score = parseInt(_root.inpScore.text);
score = score + 5;
_root.inpScore.text = score;
trace("plus 5");
}]]></script>
</Actionscript>
</DOMSymbolInstance>
@@ -58,6 +61,7 @@ stop();]]></script>
var score = parseInt(_root.inpScore.text);
score = score * 2;
_root.inpScore.text = score;
trace("multiply 2");
}]]></script>
</Actionscript>
</DOMSymbolInstance>
@@ -100,7 +104,7 @@ stop();]]></script>
</DOMTextRun>
</textRuns>
</DOMDynamicText>
<DOMSymbolInstance libraryItemName="Button3" symbolType="button">
<DOMSymbolInstance libraryItemName="Button3" selected="true" symbolType="button">
<matrix>
<Matrix tx="216.95" ty="294.5"/>
</matrix>
@@ -110,6 +114,48 @@ stop();]]></script>
<Actionscript>
<script><![CDATA[on(press) {
_root.inpScore.text = 0;
trace("reset");
}]]></script>
</Actionscript>
</DOMSymbolInstance>
<DOMStaticText fontRenderingMode="standard" width="51" height="22.15" isSelectable="false">
<matrix>
<Matrix tx="474.2" ty="12"/>
</matrix>
<textRuns>
<DOMTextRun>
<characters>Speed</characters>
<textAttrs>
<DOMTextAttrs aliasText="false" size="20" bitmapSize="400" face="TimesNewRomanPSMT"/>
</textAttrs>
</DOMTextRun>
</textRuns>
</DOMStaticText>
<DOMSymbolInstance libraryItemName="ButtonUp" name="btnSpeedUp" symbolType="button">
<matrix>
<Matrix tx="450" ty="11.3"/>
</matrix>
<transformationPoint>
<Point x="6.6" y="5.6"/>
</transformationPoint>
<Actionscript>
<script><![CDATA[on(press) {
_root.delay = Math.round(_root.delay / 1.1);
trace("speed up");
}]]></script>
</Actionscript>
</DOMSymbolInstance>
<DOMSymbolInstance libraryItemName="ButtonDown" name="btnSpeedDown" symbolType="button">
<matrix>
<Matrix tx="450" ty="26"/>
</matrix>
<transformationPoint>
<Point x="6.6" y="5.6"/>
</transformationPoint>
<Actionscript>
<script><![CDATA[on(press) {
_root.delay = Math.round(_root.delay * 1.1);
trace("speed down");
}]]></script>
</Actionscript>
</DOMSymbolInstance>
@@ -122,6 +168,10 @@ stop();]]></script>
</timelines>
<PrinterSettings/>
<publishHistory>
<PublishItem publishSize="9272" publishTime="1771699758"/>
<PublishItem publishSize="9288" publishTime="1771695673" publishDebug="true"/>
<PublishItem publishSize="9287" publishTime="1771695604" publishDebug="true"/>
<PublishItem publishSize="9303" publishTime="1771695543" publishDebug="true"/>
<PublishItem publishSize="8792" publishTime="1771271352"/>
<PublishItem publishSize="8784" publishTime="1771269741"/>
<PublishItem publishSize="8774" publishTime="1771269515"/>
@@ -138,6 +188,5 @@ stop();]]></script>
<PublishItem publishSize="7223" publishTime="1771267567" publishDebug="true"/>
<PublishItem publishSize="7203" publishTime="1771267511" publishDebug="true"/>
<PublishItem publishSize="7172" publishTime="1771267431" publishDebug="true"/>
<PublishItem publishSize="7170" publishTime="1771267362" publishDebug="true"/>
</publishHistory>
</DOMDocument>

View File

@@ -0,0 +1,90 @@
<DOMSymbolItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://ns.adobe.com/xfl/2008/" name="ButtonDown" itemID="6999ec93-000001e6" symbolType="button" lastModified="1771695532">
<timeline>
<DOMTimeline name="ButtonDown" currentFrame="2">
<layers>
<DOMLayer name="Layer 1" color="#4FFF4F" current="true" isSelected="true">
<frames>
<DOMFrame index="0" keyMode="9728">
<elements>
<DOMShape>
<fills>
<FillStyle index="1">
<SolidColor color="#0099FF"/>
</FillStyle>
</fills>
<strokes>
<StrokeStyle index="1">
<SolidStroke scaleMode="normal">
<fill>
<SolidColor/>
</fill>
</SolidStroke>
</StrokeStyle>
</strokes>
<edges>
<Edge fillStyle0="1" strokeStyle="1" edges="!135 225S5|265 0!265 0|0 0!0 0|135 225"/>
<Edge cubics="!265 0(;265,0 0,0 0,0q265 0 0 0);"/>
<Edge cubics="!0 0(;0,0 135,225 135,225q0 0 135 225);"/>
<Edge cubics="!135 225(;135,225 265,0 265,0q135 225 265 0);"/>
</edges>
</DOMShape>
</elements>
</DOMFrame>
<DOMFrame index="1" keyMode="9728">
<elements>
<DOMShape>
<fills>
<FillStyle index="1">
<SolidColor color="#00FFFF"/>
</FillStyle>
</fills>
<strokes>
<StrokeStyle index="1">
<SolidStroke scaleMode="normal">
<fill>
<SolidColor/>
</fill>
</SolidStroke>
</StrokeStyle>
</strokes>
<edges>
<Edge fillStyle0="1" strokeStyle="1" edges="!265 0|0 0!0 0|135 225!135 225|265 0"/>
<Edge cubics="!265 0(;265,0 0,0 0,0q265 0 0 0);"/>
<Edge cubics="!0 0(;0,0 135,225 135,225q0 0 135 225);"/>
<Edge cubics="!135 225(;135,225 265,0 265,0q135 225 265 0);"/>
</edges>
</DOMShape>
</elements>
</DOMFrame>
<DOMFrame index="2" keyMode="9728">
<elements>
<DOMShape>
<fills>
<FillStyle index="1">
<SolidColor color="#0000FF"/>
</FillStyle>
</fills>
<strokes>
<StrokeStyle index="1">
<SolidStroke scaleMode="normal">
<fill>
<SolidColor/>
</fill>
</SolidStroke>
</StrokeStyle>
</strokes>
<edges>
<Edge fillStyle0="1" strokeStyle="1" edges="!265 0|0 0!0 0|135 225!135 225|265 0"/>
<Edge cubics="!265 0(;265,0 0,0 0,0q265 0 0 0);"/>
<Edge cubics="!0 0(;0,0 135,225 135,225q0 0 135 225);"/>
<Edge cubics="!135 225(;135,225 265,0 265,0q135 225 265 0);"/>
</edges>
</DOMShape>
</elements>
</DOMFrame>
</frames>
</DOMLayer>
</layers>
</DOMTimeline>
</timeline>
</DOMSymbolItem>

View File

@@ -0,0 +1,90 @@
<DOMSymbolItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://ns.adobe.com/xfl/2008/" name="ButtonUp" itemID="6999ec8b-000001e1" symbolType="button" lastModified="1771695510">
<timeline>
<DOMTimeline name="ButtonUp" currentFrame="2">
<layers>
<DOMLayer name="Layer 1" color="#4FFF4F" current="true" isSelected="true">
<frames>
<DOMFrame index="0" keyMode="9728">
<elements>
<DOMShape>
<fills>
<FillStyle index="1">
<SolidColor color="#0099FF"/>
</FillStyle>
</fills>
<strokes>
<StrokeStyle index="1">
<SolidStroke scaleMode="normal">
<fill>
<SolidColor/>
</fill>
</SolidStroke>
</StrokeStyle>
</strokes>
<edges>
<Edge fillStyle0="1" strokeStyle="1" edges="!130 0S5|0 225!0 225|265 225!265 225|130 0"/>
<Edge cubics="!0 225(;0,225 265,225 265,225q0 225 265 225);"/>
<Edge cubics="!265 225(;265,225 130,0 130,0q265 225 130 0);"/>
<Edge cubics="!130 0(;130,0 0,225 0,225q130 0 0 225);"/>
</edges>
</DOMShape>
</elements>
</DOMFrame>
<DOMFrame index="1" keyMode="9728">
<elements>
<DOMShape>
<fills>
<FillStyle index="1">
<SolidColor color="#00FFFF"/>
</FillStyle>
</fills>
<strokes>
<StrokeStyle index="1">
<SolidStroke scaleMode="normal">
<fill>
<SolidColor/>
</fill>
</SolidStroke>
</StrokeStyle>
</strokes>
<edges>
<Edge fillStyle0="1" strokeStyle="1" edges="!0 225|265 225!265 225|130 0!130 0|0 225"/>
<Edge cubics="!0 225(;0,225 265,225 265,225q0 225 265 225);"/>
<Edge cubics="!265 225(;265,225 130,0 130,0q265 225 130 0);"/>
<Edge cubics="!130 0(;130,0 0,225 0,225q130 0 0 225);"/>
</edges>
</DOMShape>
</elements>
</DOMFrame>
<DOMFrame index="2" keyMode="9728">
<elements>
<DOMShape>
<fills>
<FillStyle index="1">
<SolidColor color="#0000FF"/>
</FillStyle>
</fills>
<strokes>
<StrokeStyle index="1">
<SolidStroke scaleMode="normal">
<fill>
<SolidColor/>
</fill>
</SolidStroke>
</StrokeStyle>
</strokes>
<edges>
<Edge fillStyle0="1" strokeStyle="1" edges="!265 225|130 0!130 0|0 225!0 225|265 225"/>
<Edge cubics="!0 225(;0,225 265,225 265,225q0 225 265 225);"/>
<Edge cubics="!265 225(;265,225 130,0 130,0q265 225 130 0);"/>
<Edge cubics="!130 0(;130,0 0,225 0,225q130 0 0 225);"/>
</edges>
</DOMShape>
</elements>
</DOMFrame>
</frames>
</DOMLayer>
</layers>
</DOMTimeline>
</timeline>
</DOMSymbolItem>

View File

@@ -5,8 +5,8 @@
xmlns:xmp="http://ns.adobe.com/xap/1.0/">
<xmp:CreatorTool>Adobe Flash Professional CS6 - build 481</xmp:CreatorTool>
<xmp:CreateDate>2026-02-16T10:31:42-08:00</xmp:CreateDate>
<xmp:MetadataDate>2026-02-16T11:18:35-08:00</xmp:MetadataDate>
<xmp:ModifyDate>2026-02-16T11:18:35-08:00</xmp:ModifyDate>
<xmp:MetadataDate>2026-02-21T09:35:10-08:00</xmp:MetadataDate>
<xmp:ModifyDate>2026-02-21T09:35:10-08:00</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:dc="http://purl.org/dc/elements/1.1/">
@@ -17,7 +17,7 @@
xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#">
<xmpMM:DerivedFrom rdf:parseType="Resource"/>
<xmpMM:DocumentID>xmp.did:7FE581FA660BF11197008EF33C376745</xmpMM:DocumentID>
<xmpMM:InstanceID>xmp.iid:9BDF39F36B0BF11197008EF33C376745</xmpMM:InstanceID>
<xmpMM:InstanceID>xmp.iid:377DE8AB4B0FF111A0D3B09FD2F43FD4</xmpMM:InstanceID>
<xmpMM:OriginalDocumentID>xmp.did:7FE581FA660BF11197008EF33C376745</xmpMM:OriginalDocumentID>
<xmpMM:History>
<rdf:Seq>
@@ -39,6 +39,12 @@
<stEvt:when>2026-02-16T10:31:42-08:00</stEvt:when>
<stEvt:softwareAgent>Adobe Flash Professional CS6 - build 481</stEvt:softwareAgent>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<stEvt:action>created</stEvt:action>
<stEvt:instanceID>xmp.iid:377DE8AB4B0FF111A0D3B09FD2F43FD4</stEvt:instanceID>
<stEvt:when>2026-02-16T10:31:42-08:00</stEvt:when>
<stEvt:softwareAgent>Adobe Flash Professional CS6 - build 481</stEvt:softwareAgent>
</rdf:li>
</rdf:Seq>
</xmpMM:History>
</rdf:Description>

View File

@@ -6,6 +6,8 @@
<Include href="Button1.xml" itemIcon="0" loadImmediate="false" itemID="699362e3-000001d5" lastModified="1771267090"/>
<Include href="Button2.xml" itemIcon="0" loadImmediate="false" itemID="6993636a-000001dc" lastModified="1771267096"/>
<Include href="Button3.xml" itemIcon="0" loadImmediate="false" itemID="699367b4-000001e5" lastModified="1771268063"/>
<Include href="ButtonDown.xml" itemIcon="0" loadImmediate="false" itemID="6999ec93-000001e6" lastModified="1771695532"/>
<Include href="ButtonUp.xml" itemIcon="0" loadImmediate="false" itemID="6999ec8b-000001e1" lastModified="1771695510"/>
</symbols>
<timelines>
<DOMTimeline name="Scene 1">
@@ -42,7 +44,8 @@ setTimeout(decreaseScore, delay);
function onPlus5(e:MouseEvent):void {
var score:int = getScore();
score = score + 5;
setScore(score);
setScore(score);
trace("plus 5");
}
butPlus5.addEventListener(MouseEvent.CLICK, onPlus5);
@@ -51,15 +54,32 @@ function onMultiply2(e:MouseEvent):void {
var score:int = getScore();
score = score * 2;
setScore(score);
trace("multiply 2");
}
butMultiply2.addEventListener(MouseEvent.CLICK, onMultiply2);
function onReset(e:MouseEvent):void {
setScore(0);
trace("reset");
}
butReset.addEventListener(MouseEvent.CLICK, onReset);]]></script>
butReset.addEventListener(MouseEvent.CLICK, onReset);
function onSpeedUp(e:MouseEvent): void {
delay = Math.round(delay / 1.1);
trace("speed up");
}
btnSpeedUp.addEventListener(MouseEvent.CLICK, onSpeedUp);
function onSpeedDown(e:MouseEvent): void {
delay = Math.round(delay * 1.1);
trace("speed down");
}
btnSpeedDown.addEventListener(MouseEvent.CLICK, onSpeedDown);
]]></script>
</Actionscript>
<elements>
<DOMSymbolInstance libraryItemName="Button1" name="butPlus5" symbolType="button">
@@ -125,6 +145,35 @@ butReset.addEventListener(MouseEvent.CLICK, onReset);]]></script>
<Point/>
</transformationPoint>
</DOMSymbolInstance>
<DOMStaticText fontRenderingMode="standard" width="51" height="22.15" isSelectable="false">
<matrix>
<Matrix tx="474.2" ty="12"/>
</matrix>
<textRuns>
<DOMTextRun>
<characters>Speed</characters>
<textAttrs>
<DOMTextAttrs aliasText="false" size="20" bitmapSize="400" face="TimesNewRomanPSMT"/>
</textAttrs>
</DOMTextRun>
</textRuns>
</DOMStaticText>
<DOMSymbolInstance libraryItemName="ButtonUp" name="btnSpeedUp" symbolType="button">
<matrix>
<Matrix tx="450" ty="11.3"/>
</matrix>
<transformationPoint>
<Point x="6.6" y="5.6"/>
</transformationPoint>
</DOMSymbolInstance>
<DOMSymbolInstance libraryItemName="ButtonDown" name="btnSpeedDown" symbolType="button">
<matrix>
<Matrix tx="450" ty="26"/>
</matrix>
<transformationPoint>
<Point x="6.6" y="5.6"/>
</transformationPoint>
</DOMSymbolInstance>
</elements>
</DOMFrame>
</frames>
@@ -134,6 +183,8 @@ butReset.addEventListener(MouseEvent.CLICK, onReset);]]></script>
</timelines>
<PrinterSettings/>
<publishHistory>
<PublishItem publishSize="9791" publishTime="1771699753"/>
<PublishItem publishSize="10087" publishTime="1771695966" publishDebug="true"/>
<PublishItem publishSize="9267" publishTime="1771270767"/>
<PublishItem publishSize="9269" publishTime="1771270237"/>
<PublishItem publishSize="9215" publishTime="1771270105"/>
@@ -152,7 +203,5 @@ butReset.addEventListener(MouseEvent.CLICK, onReset);]]></script>
<PublishItem publishSize="7221" publishTime="1771267633" publishDebug="true"/>
<PublishItem publishSize="7221" publishTime="1771267610" publishDebug="true"/>
<PublishItem publishSize="7223" publishTime="1771267567" publishDebug="true"/>
<PublishItem publishSize="7203" publishTime="1771267511" publishDebug="true"/>
<PublishItem publishSize="7172" publishTime="1771267431" publishDebug="true"/>
</publishHistory>
</DOMDocument>

View File

@@ -0,0 +1,90 @@
<DOMSymbolItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://ns.adobe.com/xfl/2008/" name="ButtonDown" itemID="6999ec93-000001e6" symbolType="button" lastModified="1771695532">
<timeline>
<DOMTimeline name="ButtonDown" currentFrame="2">
<layers>
<DOMLayer name="Layer 1" color="#4FFF4F" current="true" isSelected="true">
<frames>
<DOMFrame index="0" keyMode="9728">
<elements>
<DOMShape>
<fills>
<FillStyle index="1">
<SolidColor color="#0099FF"/>
</FillStyle>
</fills>
<strokes>
<StrokeStyle index="1">
<SolidStroke scaleMode="normal">
<fill>
<SolidColor/>
</fill>
</SolidStroke>
</StrokeStyle>
</strokes>
<edges>
<Edge fillStyle0="1" strokeStyle="1" edges="!135 225S5|265 0!265 0|0 0!0 0|135 225"/>
<Edge cubics="!265 0(;265,0 0,0 0,0q265 0 0 0);"/>
<Edge cubics="!0 0(;0,0 135,225 135,225q0 0 135 225);"/>
<Edge cubics="!135 225(;135,225 265,0 265,0q135 225 265 0);"/>
</edges>
</DOMShape>
</elements>
</DOMFrame>
<DOMFrame index="1" keyMode="9728">
<elements>
<DOMShape>
<fills>
<FillStyle index="1">
<SolidColor color="#00FFFF"/>
</FillStyle>
</fills>
<strokes>
<StrokeStyle index="1">
<SolidStroke scaleMode="normal">
<fill>
<SolidColor/>
</fill>
</SolidStroke>
</StrokeStyle>
</strokes>
<edges>
<Edge fillStyle0="1" strokeStyle="1" edges="!265 0|0 0!0 0|135 225!135 225|265 0"/>
<Edge cubics="!265 0(;265,0 0,0 0,0q265 0 0 0);"/>
<Edge cubics="!0 0(;0,0 135,225 135,225q0 0 135 225);"/>
<Edge cubics="!135 225(;135,225 265,0 265,0q135 225 265 0);"/>
</edges>
</DOMShape>
</elements>
</DOMFrame>
<DOMFrame index="2" keyMode="9728">
<elements>
<DOMShape>
<fills>
<FillStyle index="1">
<SolidColor color="#0000FF"/>
</FillStyle>
</fills>
<strokes>
<StrokeStyle index="1">
<SolidStroke scaleMode="normal">
<fill>
<SolidColor/>
</fill>
</SolidStroke>
</StrokeStyle>
</strokes>
<edges>
<Edge fillStyle0="1" strokeStyle="1" edges="!265 0|0 0!0 0|135 225!135 225|265 0"/>
<Edge cubics="!265 0(;265,0 0,0 0,0q265 0 0 0);"/>
<Edge cubics="!0 0(;0,0 135,225 135,225q0 0 135 225);"/>
<Edge cubics="!135 225(;135,225 265,0 265,0q135 225 265 0);"/>
</edges>
</DOMShape>
</elements>
</DOMFrame>
</frames>
</DOMLayer>
</layers>
</DOMTimeline>
</timeline>
</DOMSymbolItem>

View File

@@ -0,0 +1,90 @@
<DOMSymbolItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://ns.adobe.com/xfl/2008/" name="ButtonUp" itemID="6999ec8b-000001e1" symbolType="button" lastModified="1771695510">
<timeline>
<DOMTimeline name="ButtonUp" currentFrame="2">
<layers>
<DOMLayer name="Layer 1" color="#4FFF4F" current="true" isSelected="true">
<frames>
<DOMFrame index="0" keyMode="9728">
<elements>
<DOMShape>
<fills>
<FillStyle index="1">
<SolidColor color="#0099FF"/>
</FillStyle>
</fills>
<strokes>
<StrokeStyle index="1">
<SolidStroke scaleMode="normal">
<fill>
<SolidColor/>
</fill>
</SolidStroke>
</StrokeStyle>
</strokes>
<edges>
<Edge fillStyle0="1" strokeStyle="1" edges="!130 0S5|0 225!0 225|265 225!265 225|130 0"/>
<Edge cubics="!0 225(;0,225 265,225 265,225q0 225 265 225);"/>
<Edge cubics="!265 225(;265,225 130,0 130,0q265 225 130 0);"/>
<Edge cubics="!130 0(;130,0 0,225 0,225q130 0 0 225);"/>
</edges>
</DOMShape>
</elements>
</DOMFrame>
<DOMFrame index="1" keyMode="9728">
<elements>
<DOMShape>
<fills>
<FillStyle index="1">
<SolidColor color="#00FFFF"/>
</FillStyle>
</fills>
<strokes>
<StrokeStyle index="1">
<SolidStroke scaleMode="normal">
<fill>
<SolidColor/>
</fill>
</SolidStroke>
</StrokeStyle>
</strokes>
<edges>
<Edge fillStyle0="1" strokeStyle="1" edges="!0 225|265 225!265 225|130 0!130 0|0 225"/>
<Edge cubics="!0 225(;0,225 265,225 265,225q0 225 265 225);"/>
<Edge cubics="!265 225(;265,225 130,0 130,0q265 225 130 0);"/>
<Edge cubics="!130 0(;130,0 0,225 0,225q130 0 0 225);"/>
</edges>
</DOMShape>
</elements>
</DOMFrame>
<DOMFrame index="2" keyMode="9728">
<elements>
<DOMShape>
<fills>
<FillStyle index="1">
<SolidColor color="#0000FF"/>
</FillStyle>
</fills>
<strokes>
<StrokeStyle index="1">
<SolidStroke scaleMode="normal">
<fill>
<SolidColor/>
</fill>
</SolidStroke>
</StrokeStyle>
</strokes>
<edges>
<Edge fillStyle0="1" strokeStyle="1" edges="!265 225|130 0!130 0|0 225!0 225|265 225"/>
<Edge cubics="!0 225(;0,225 265,225 265,225q0 225 265 225);"/>
<Edge cubics="!265 225(;265,225 130,0 130,0q265 225 130 0);"/>
<Edge cubics="!130 0(;130,0 0,225 0,225q130 0 0 225);"/>
</edges>
</DOMShape>
</elements>
</DOMFrame>
</frames>
</DOMLayer>
</layers>
</DOMTimeline>
</timeline>
</DOMSymbolItem>

View File

@@ -5,8 +5,8 @@
xmlns:xmp="http://ns.adobe.com/xap/1.0/">
<xmp:CreatorTool>Adobe Flash Professional CS6 - build 481</xmp:CreatorTool>
<xmp:CreateDate>2026-02-16T10:31:42-08:00</xmp:CreateDate>
<xmp:MetadataDate>2026-02-16T11:18:44-08:00</xmp:MetadataDate>
<xmp:ModifyDate>2026-02-16T11:18:44-08:00</xmp:ModifyDate>
<xmp:MetadataDate>2026-02-21T09:45:46-08:00</xmp:MetadataDate>
<xmp:ModifyDate>2026-02-21T09:45:46-08:00</xmp:ModifyDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:dc="http://purl.org/dc/elements/1.1/">
@@ -22,7 +22,7 @@
<stRef:originalDocumentID>xmp.did:7FE581FA660BF11197008EF33C376745</stRef:originalDocumentID>
</xmpMM:DerivedFrom>
<xmpMM:DocumentID>xmp.did:EDF1CDD4690BF11197008EF33C376745</xmpMM:DocumentID>
<xmpMM:InstanceID>xmp.iid:9DDF39F36B0BF11197008EF33C376745</xmpMM:InstanceID>
<xmpMM:InstanceID>xmp.iid:3B7DE8AB4B0FF111A0D3B09FD2F43FD4</xmpMM:InstanceID>
<xmpMM:OriginalDocumentID>xmp.did:7FE581FA660BF11197008EF33C376745</xmpMM:OriginalDocumentID>
<xmpMM:History>
<rdf:Seq>
@@ -45,6 +45,12 @@
<stEvt:when>2026-02-16T10:31:42-08:00</stEvt:when>
<stEvt:softwareAgent>Adobe Flash Professional CS6 - build 481</stEvt:softwareAgent>
</rdf:li>
<rdf:li rdf:parseType="Resource">
<stEvt:action>created</stEvt:action>
<stEvt:instanceID>xmp.iid:3B7DE8AB4B0FF111A0D3B09FD2F43FD4</stEvt:instanceID>
<stEvt:when>2026-02-16T10:31:42-08:00</stEvt:when>
<stEvt:softwareAgent>Adobe Flash Professional CS6 - build 481</stEvt:softwareAgent>
</rdf:li>
</rdf:Seq>
</xmpMM:History>
</rdf:Description>

View File

@@ -16,6 +16,8 @@
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.debugger.flash.Debugger;
import com.jpexs.debugger.flash.DebuggerCommands;
import com.jpexs.debugger.flash.Variable;
import com.jpexs.debugger.flash.messages.in.InConstantPool;
import com.jpexs.debugger.flash.messages.in.InFrame;
@@ -70,7 +72,9 @@ public class DebugPanel extends JPanel {
private MyTreeTable debugRegistersTable;
private MyTreeTable debugLocalsTable; //JTable debugLocalsTable;
private MyTreeTable debugLocalsTable;
private MyTreeTable debugWatchesTable;
private MyTreeTable debugScopeTable;
@@ -91,14 +95,14 @@ public class DebugPanel extends JPanel {
private boolean loading = false;
public ABCPanel.VariablesTableModel localsTable;
private WeakReference<DebuggerSession> currentSessionRef = null;
private boolean as3;
public static enum SelectedTab {
LOG, STACK, SCOPECHAIN, LOCALS, REGISTERS, CALLSTACK, CONSTANTPOOL
LOG, STACK, SCOPECHAIN, LOCALS, WATCHES, REGISTERS, CALLSTACK, CONSTANTPOOL
}
public synchronized boolean isLoading() {
@@ -107,6 +111,7 @@ public class DebugPanel extends JPanel {
public synchronized void setLoading(boolean loading) {
this.loading = loading;
//varTabs.setVisible(!loading);
}
private SelectedTab selectedTab = null;
@@ -157,15 +162,16 @@ public class DebugPanel extends JPanel {
//ignore
}
if (wasEmpty) {
refresh(session);
refresh();
}
}
public DebugPanel(boolean as3) {
super(new BorderLayout());
this.as3 = as3;
debugRegistersTable = new MyTreeTable(new ABCPanel.VariablesTableModel(as3, debugRegistersTable, new ArrayList<>()), false);
debugLocalsTable = new MyTreeTable(new ABCPanel.VariablesTableModel(as3, debugLocalsTable, new ArrayList<>()), false);
debugRegistersTable = new MyTreeTable(new ABCPanel.VariablesTableModel(null, as3, debugRegistersTable, new ArrayList<>(), new ArrayList<>()), false);
debugLocalsTable = new MyTreeTable(new ABCPanel.VariablesTableModel(null, as3, debugLocalsTable, new ArrayList<>(), new ArrayList<>()), false);
debugWatchesTable = new MyTreeTable(new ABCPanel.VariablesTableModel(null, as3, debugWatchesTable, new ArrayList<>(), new ArrayList<>()), false);
MouseAdapter watchHandler = new MouseAdapter() {
@@ -184,7 +190,7 @@ public class DebugPanel extends JPanel {
}
private void dopop(MouseEvent e) {
if (currentSessionRef == null) {
return;
}
@@ -192,11 +198,13 @@ public class DebugPanel extends JPanel {
if (session == null) {
return;
}
if (debugLocalsTable.getSelectedRow() == -1) {
MyTreeTable src = (MyTreeTable) e.getSource();
if (src.getSelectedRow() == -1) {
return;
}
Object node = debugLocalsTable.getTree().getPathForRow(debugLocalsTable.getSelectedRow()).getLastPathComponent();
Object node = src.getTree().getPathForRow(src.getSelectedRow()).getLastPathComponent();
Variable v;
ABCPanel.VariableNode vn;
if (node instanceof ABCPanel.VariableNode) {
@@ -261,7 +269,7 @@ public class DebugPanel extends JPanel {
if (igv == null) {
return;
}
Variable debugConnectionClass = igv.parent;
Variable debugConnectionClass = igv.parent;
String dataStr = (String) session.callMethod(debugConnectionClass, "readCommaSeparatedFromByteArray", Arrays.asList(v)).variables.get(0).value;
String[] parts = dataStr.split(",");
byte[] data = new byte[parts.length];
@@ -356,35 +364,63 @@ public class DebugPanel extends JPanel {
watchReadMenuItem.addActionListener((ActionEvent e1) -> {
if (!Main.addWatch(session, v, watchParentId, true, false)) {
ViewMessages.showMessageDialog(DebugPanel.this, AppStrings.translate("error.debug.watch.add"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
return;
}
refresh();
});
JMenuItem watchWriteMenuItem = new JMenuItem(AppStrings.translate("debug.watch.add.write"));
watchWriteMenuItem.addActionListener((ActionEvent e1) -> {
if (!Main.addWatch(session, v, watchParentId, false, true)) {
ViewMessages.showMessageDialog(DebugPanel.this, AppStrings.translate("error.debug.watch.add"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
return;
}
refresh();
});
JMenuItem watchReadWriteMenuItem = new JMenuItem(AppStrings.translate("debug.watch.add.readwrite"));
watchReadWriteMenuItem.addActionListener((ActionEvent e1) -> {
if (!Main.addWatch(session, v, watchParentId, true, true)) {
ViewMessages.showMessageDialog(DebugPanel.this, AppStrings.translate("error.debug.watch.add"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
return;
}
refresh();
});
addWatchMenu.add(watchReadMenuItem);
addWatchMenu.add(watchWriteMenuItem);
addWatchMenu.add(watchReadWriteMenuItem);
pm.add(addWatchMenu);
JMenuItem removeWatcheMenuItem = new JMenuItem(AppStrings.translate("debug.watch.remove"));
removeWatcheMenuItem.addActionListener((ActionEvent e1) -> {
if (!Main.removeWatch(session, v, watchParentId)) {
ViewMessages.showMessageDialog(DebugPanel.this, AppStrings.translate("error.debug.watch.remove"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
return;
}
refresh();
});
if (session.getWatch(v.name, watchParentId) != null) {
pm.add(removeWatcheMenuItem);
}
pm.show(e.getComponent(), e.getX(), e.getY());
}
};
debugLocalsTable.addMouseListener(watchHandler);
debugWatchesTable.addMouseListener(watchHandler);
//debugScopeTable.addMouseListener(watchHandler);
debugScopeTable = new MyTreeTable(new ABCPanel.VariablesTableModel(as3, debugScopeTable, new ArrayList<>()), false);
debugScopeTable = new MyTreeTable(new ABCPanel.VariablesTableModel(null, as3, debugScopeTable, new ArrayList<>(), new ArrayList<>()), false);
constantPoolTable = new JTable();
constantPoolTable = new JTable(new DefaultTableModel(new Object[2][0], new Object[]{
AppStrings.translate("constantpool.header.id"),
AppStrings.translate("constantpool.header.value")
}) {
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
});
traceLogTextarea = new JTextArea();
traceLogTextarea.setEditable(false);
traceLogTextarea.setOpaque(false);
@@ -408,7 +444,7 @@ public class DebugPanel extends JPanel {
public void errorException(DebuggerSession session, String message, Variable thrownVar) {
logAdd(session, "unhandled exception: " + message);
selectedTab = tabTypes.get(tabTypes.size() - 1);
refresh(session);
refresh();
}
});
@@ -420,19 +456,26 @@ public class DebugPanel extends JPanel {
@Override
public void disconnected(DebuggerSession session) {
refresh(session);
refresh();
}
});
Main.getDebugHandler().addSelectionListener(new DebuggerHandler.SessionSelectionListener() {
@Override
public void sessionSelected(DebuggerSession newSession, int oldSessionId) {
refresh();
}
});
Main.getDebugHandler().addFrameChangeListener(frameChangeListener = new DebuggerHandler.FrameChangeListener() {
@Override
public void frameChanged(DebuggerSession session) {
View.execInEventDispatchLater(new Runnable() {
@Override
public void run() {
refresh(session);
}
});
/*DebuggerSession currentSession = Main.getCurrentDebugSession();
if (session != currentSession) {
return;
} */
refresh();
}
});
@@ -440,22 +483,18 @@ public class DebugPanel extends JPanel {
@Override
public void doContinue(DebuggerSession session) {
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
refresh(Main.getCurrentDebugSession());
}
});
refresh();
}
@Override
public void breakAt(DebuggerSession session, String scriptName, int line, int classIndex, int traitIndex, int methodIndex) {
View.execInEventDispatch(new Runnable() {
/*View.execInEventDispatch(new Runnable() {
@Override
public void run() {
refresh(Main.getCurrentDebugSession());
}
});
});*/
//reacts to frameChanged instead
}
});
@@ -479,7 +518,7 @@ public class DebugPanel extends JPanel {
});
add(new HeaderLabel(AppStrings.translate("debugpanel.header")), BorderLayout.NORTH);
add(varTabs, BorderLayout.CENTER);
add(varTabs, BorderLayout.CENTER);
}
/* private void getVariableList() {
@@ -509,190 +548,269 @@ public class DebugPanel extends JPanel {
}
return v.getMembers(this);
}*/
public void refresh(DebuggerSession session) {
if (session != null && !session.isPaused()) {
return;
private final Object refreshLock = new Object();
public void refresh() {
DebuggerSession session = Main.getCurrentDebugSession();
if (session != null) {
SWF swf = session.getCurrentSwf();
if (swf != null) {
if (swf.isAS3() != as3) {
return;
}
}
}
currentSessionRef = session == null ? null : new WeakReference<>(session);
View.execInEventDispatch(new Runnable() {
Runnable r = new Runnable() {
@Override
public void run() {
if (session != null && !session.isPaused()) {
return;
}
setLoading(true);
synchronized (DebugPanel.this) {
synchronized (refreshLock) {
try {
setLoading(true);
SelectedTab oldSel = selectedTab;
localsTable = null;
InFrame f = session == null ? null : session.getFrame();
if (f != null) {
List<Variable> locals = new ArrayList<>();
Map<String, Long> placedObjects = session.getPlacedObjects();
for (String poName : placedObjects.keySet()) {
String realName = poName;
if ("/".equals(realName)) {
realName = "_root";
} else if (realName.startsWith("/")) {
continue;
}
InGetVariable igv = session.getVariable(0, realName, false, false);
if (igv != null) {
Variable placedVar = igv.parent;
if (placedVar != null) {
locals.add(placedVar);
int sessionId = -1;
if (session != null) {
sessionId = session.getId();
ABCPanel.VariableNode.stopLoading(sessionId); //stop any previous loading
}
Logger.getLogger(DebugPanel.class.getName()).log(Level.FINE, "session{0}: Refreshing debug panel", new Object[]{sessionId});
localsTable = null;
InFrame f = session == null ? null : session.getFrame();
ABCPanel.VariablesTableModel registersTableModel = new ABCPanel.VariablesTableModel(session, as3, debugRegistersTable, new ArrayList<>(), new ArrayList<>());
ABCPanel.VariablesTableModel localsTableModel = new ABCPanel.VariablesTableModel(session, as3, debugLocalsTable, new ArrayList<>(), new ArrayList<>());
ABCPanel.VariablesTableModel scopeTableModel = new ABCPanel.VariablesTableModel(session, as3, debugScopeTable, new ArrayList<>(), new ArrayList<>());
ABCPanel.VariablesTableModel watchesTableModel = new ABCPanel.VariablesTableModel(session, as3, debugWatchesTable, new ArrayList<>(), new ArrayList<>());
ABCPanel.VariablesTableModel fRegistersTableModel;
ABCPanel.VariablesTableModel fLocalsTableModel;
ABCPanel.VariablesTableModel fScopeTableModel;
ABCPanel.VariablesTableModel fWatchesTableModel;
Object[][] fCpoolData;
if (f != null) {
Logger.getLogger(DebugPanel.class.getName()).log(Level.FINE, "session{0}: Debug panel - has frame", new Object[]{sessionId});
List<Variable> locals = new ArrayList<>();
Map<String, Long> placedObjects = session.getPlacedObjects();
for (String poName : placedObjects.keySet()) {
String realName = poName;
if ("/".equals(realName)) {
realName = "_root";
} else if (realName.startsWith("/")) {
continue;
}
Logger.getLogger(DebugPanel.class.getName()).log(Level.FINE, "session{0}: Getting placedObject {1}", new Object[]{sessionId, realName});
InGetVariable igv = session.getVariable(0, realName, false, false);
if (igv != null) {
Variable placedVar = igv.parent;
if (placedVar != null) {
locals.add(placedVar);
}
} else {
Logger.getLogger(DebugPanel.class.getName()).log(Level.FINE, "session{0}: Cannot get placedObject {1}", new Object[]{sessionId, realName});
}
}
locals.addAll(f.arguments);
locals.addAll(f.variables);
localsTable = new ABCPanel.VariablesTableModel(session, as3, debugLocalsTable, locals, null);
List<Variable> watchedVars = new ArrayList<>();
List<Long> watchedParentIds = new ArrayList<>();
for (DebuggerCommands.Watch w : session.getWatches().values()) {
InGetVariable igv = session.getVariable(w.varId, w.varName, false, false);
if (igv != null) {
Variable wVar = igv.parent;
if (wVar != null) {
watchedVars.add(wVar);
watchedParentIds.add(w.varId);
}
}
}
TreeModelListener refreshListener = new TreeModelListener() {
@Override
public void treeNodesChanged(TreeModelEvent e) {
synchronized (DebugPanel.this) {
if (loading) {
return;
}
}
session.refreshFrame();
}
@Override
public void treeNodesInserted(TreeModelEvent e) {
}
@Override
public void treeNodesRemoved(TreeModelEvent e) {
}
@Override
public void treeStructureChanged(TreeModelEvent e) {
}
};
registersTableModel = new ABCPanel.VariablesTableModel(session, as3, debugRegistersTable, f.registers, null);
localsTableModel = localsTable;
scopeTableModel = new ABCPanel.VariablesTableModel(session, as3, debugScopeTable, f.scopeChain, null);
watchesTableModel = new ABCPanel.VariablesTableModel(session, as3, debugWatchesTable, watchedVars, watchedParentIds);
localsTableModel.addTreeModelListener(refreshListener);
scopeTableModel.addTreeModelListener(refreshListener);
watchesTableModel.addTreeModelListener(refreshListener);
}
safeSetTreeModel(debugRegistersTable, new ABCPanel.VariablesTableModel(as3, debugRegistersTable, f.registers));
locals.addAll(f.arguments);
locals.addAll(f.variables);
localsTable = new ABCPanel.VariablesTableModel(as3, debugLocalsTable, locals);
safeSetTreeModel(debugLocalsTable, localsTable);
safeSetTreeModel(debugScopeTable, new ABCPanel.VariablesTableModel(as3, debugScopeTable, f.scopeChain));
/*TableModelListener refreshListener = new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
Main.getDebugHandler().refreshFrame();
refresh();
}
};*/
TreeModelListener refreshListener = new TreeModelListener() {
@Override
public void treeNodesChanged(TreeModelEvent e) {
session.refreshFrame();
refresh(session);
InConstantPool cpool = session == null ? null : session.getConstantPool();
Object[][] cpoolData = new Object[0][2];
if (cpool != null) {
cpoolData = new Object[cpool.vars.size()][2];
for (int i = 0; i < cpool.vars.size(); i++) {
cpoolData[i][0] = cpool.ids.get(i);
cpoolData[i][1] = cpool.vars.get(i).value;
}
@Override
public void treeNodesInserted(TreeModelEvent e) {
session.refreshFrame();
refresh(session);
}
@Override
public void treeNodesRemoved(TreeModelEvent e) {
session.refreshFrame();
refresh(session);
}
@Override
public void treeStructureChanged(TreeModelEvent e) {
session.refreshFrame();
refresh(session);
}
};
debugLocalsTable.getTreeTableModel().addTreeModelListener(refreshListener);
debugScopeTable.getTreeTableModel().addTreeModelListener(refreshListener);
} else {
debugRegistersTable.setTreeModel(new ABCPanel.VariablesTableModel(as3, debugRegistersTable, new ArrayList<>()));
debugLocalsTable.setTreeModel(new ABCPanel.VariablesTableModel(as3, debugLocalsTable, new ArrayList<>()));
debugScopeTable.setTreeModel(new ABCPanel.VariablesTableModel(as3, debugScopeTable, new ArrayList<>()));
}
InConstantPool cpool = session == null ? null : session.getConstantPool();
if (cpool != null) {
Object[][] data2 = new Object[cpool.vars.size()][2];
for (int i = 0; i < cpool.vars.size(); i++) {
data2[i][0] = cpool.ids.get(i);
data2[i][1] = cpool.vars.get(i).value;
}
constantPoolTable.setModel(new DefaultTableModel(data2, new Object[]{
AppStrings.translate("constantpool.header.id"),
AppStrings.translate("constantpool.header.value")
}) {
fRegistersTableModel = registersTableModel;
fLocalsTableModel = localsTableModel;
fScopeTableModel = scopeTableModel;
fWatchesTableModel = watchesTableModel;
fCpoolData = cpoolData;
View.execInEventDispatch(new Runnable() {
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
public void run() {
try {
if (f != null) {
safeSetTreeModel(debugRegistersTable, fRegistersTableModel);
safeSetTreeModel(debugLocalsTable, fLocalsTableModel);
safeSetTreeModel(debugScopeTable, fScopeTableModel);
safeSetTreeModel(debugWatchesTable, fWatchesTableModel);
} else {
debugRegistersTable.setTreeModel(fRegistersTableModel);
debugLocalsTable.setTreeModel(fLocalsTableModel);
debugScopeTable.setTreeModel(fScopeTableModel);
debugWatchesTable.setTreeModel(fWatchesTableModel);
}
});
} else {
constantPoolTable.setModel(new DefaultTableModel());
}
constantPoolTable.setModel(new DefaultTableModel(fCpoolData, new Object[]{
AppStrings.translate("constantpool.header.id"),
AppStrings.translate("constantpool.header.value")
}) {
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
varTabs.removeAll();
tabTypes.clear();
JPanel pa;
if (debugRegistersTable.getRowCount() > 0) {
tabTypes.add(SelectedTab.REGISTERS);
pa = new JPanel(new BorderLayout());
pa.add(new FasterScrollPane(debugRegistersTable), BorderLayout.CENTER);
varTabs.addTab(AppStrings.translate("variables.header.registers"), pa);
}
if (debugLocalsTable.getRowCount() > 0) {
tabTypes.add(SelectedTab.LOCALS);
});
pa = new JPanel(new BorderLayout());
pa.add(new FasterScrollPane(debugLocalsTable), BorderLayout.CENTER);
varTabs.addTab(AppStrings.translate("variables.header.locals"), pa);
}
varTabs.removeAll();
tabTypes.clear();
JPanel pa;
if (debugRegistersTable.getRowCount() > 0) {
tabTypes.add(SelectedTab.REGISTERS);
pa = new JPanel(new BorderLayout());
pa.add(new FasterScrollPane(debugRegistersTable), BorderLayout.CENTER);
varTabs.addTab(AppStrings.translate("variables.header.registers"), pa);
}
if (debugLocalsTable.getRowCount() > 0) {
tabTypes.add(SelectedTab.LOCALS);
if (debugScopeTable.getRowCount() > 0) {
tabTypes.add(SelectedTab.SCOPECHAIN);
pa = new JPanel(new BorderLayout());
pa.add(new FasterScrollPane(debugLocalsTable), BorderLayout.CENTER);
varTabs.addTab(AppStrings.translate("variables.header.locals"), pa);
}
pa = new JPanel(new BorderLayout());
pa.add(new FasterScrollPane(debugScopeTable), BorderLayout.CENTER);
varTabs.addTab(AppStrings.translate("variables.header.scopeChain"), pa);
}
if (debugWatchesTable.getRowCount() > 0) {
tabTypes.add(SelectedTab.WATCHES);
if (constantPoolTable.getRowCount() > 0) {
tabTypes.add(SelectedTab.CONSTANTPOOL);
pa = new JPanel(new BorderLayout());
pa.add(new FasterScrollPane(debugWatchesTable), BorderLayout.CENTER);
varTabs.addTab(AppStrings.translate("variables.header.watches"), pa);
}
pa = new JPanel(new BorderLayout());
pa.add(new FasterScrollPane(constantPoolTable), BorderLayout.CENTER);
varTabs.addTab(AppStrings.translate("constantpool.header"), pa);
}
if (debugScopeTable.getRowCount() > 0) {
tabTypes.add(SelectedTab.SCOPECHAIN);
if (logLength > 0) {
tabTypes.add(SelectedTab.LOG);
pa = new JPanel(new BorderLayout());
pa.add(new FasterScrollPane(debugScopeTable), BorderLayout.CENTER);
varTabs.addTab(AppStrings.translate("variables.header.scopeChain"), pa);
}
pa = new JPanel(new BorderLayout());
pa.add(new FasterScrollPane(traceLogTextarea), BorderLayout.CENTER);
JButton clearButton = new JButton(AppStrings.translate("debuglog.button.clear"));
clearButton.addActionListener(new ActionListener() {
if (constantPoolTable.getRowCount() > 0) {
tabTypes.add(SelectedTab.CONSTANTPOOL);
pa = new JPanel(new BorderLayout());
pa.add(new FasterScrollPane(constantPoolTable), BorderLayout.CENTER);
varTabs.addTab(AppStrings.translate("constantpool.header"), pa);
}
if (logLength > 0) {
tabTypes.add(SelectedTab.LOG);
pa = new JPanel(new BorderLayout());
pa.add(new FasterScrollPane(traceLogTextarea), BorderLayout.CENTER);
JButton clearButton = new JButton(AppStrings.translate("debuglog.button.clear"));
clearButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
traceLogTextarea.setText("");
logLength = 0;
refresh();
}
});
JPanel butPanel = new JPanel(new FlowLayout());
butPanel.add(clearButton);
pa.add(butPanel, BorderLayout.SOUTH);
varTabs.addTab(AppStrings.translate("debuglog.header"), pa);
}
boolean newVisible = !tabTypes.isEmpty();
if (newVisible != isVisible()) {
setVisible(newVisible);
}
SelectedTab oldSel = selectedTab;
if (!tabTypes.isEmpty()) {
if (oldSel != null && !tabTypes.contains(oldSel)) {
oldSel = null;
}
}
if (oldSel != null) {
selectedTab = oldSel;
varTabs.setSelectedIndex(tabTypes.indexOf(selectedTab));
}
} catch (Throwable t) {
int sessionId = session == null ? -1 : session.getId();
Logger.getLogger(DebugPanel.class.getName()).log(Level.FINE, "session" + sessionId + ": Error refeshing debug panel in UI thread", t);
}
setLoading(false);
Logger.getLogger(DebugPanel.class.getName()).log(Level.FINE, "session{0}: Refreshed debug panel", new Object[]{session == null ? -1 : session.getId()});
@Override
public void actionPerformed(ActionEvent e) {
traceLogTextarea.setText("");
logLength = 0;
refresh(session);
}
});
JPanel butPanel = new JPanel(new FlowLayout());
butPanel.add(clearButton);
pa.add(butPanel, BorderLayout.SOUTH);
varTabs.addTab(AppStrings.translate("debuglog.header"), pa);
} catch (Throwable t) {
int sessionId = session == null ? -1 : session.getId();
Logger.getLogger(DebugPanel.class.getName()).log(Level.FINE, "session" + sessionId + ": Error refeshing debug panel", t);
}
boolean newVisible = !tabTypes.isEmpty();
if (newVisible != isVisible()) {
setVisible(newVisible);
}
if (!tabTypes.isEmpty()) {
if (oldSel != null && !tabTypes.contains(oldSel)) {
oldSel = null;
}
}
if (oldSel != null) {
selectedTab = oldSel;
varTabs.setSelectedIndex(tabTypes.indexOf(selectedTab));
}
setLoading(false);
}
}
});
};
DebuggerHandler.getPool().submit(r);
}
public void dispose() {

View File

@@ -45,6 +45,7 @@ import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
/**
* @author JPEXS
@@ -67,8 +68,23 @@ public class DebugStackPanel extends JPanel {
private int[] traitIndices = new int[0];
private WeakReference<DebuggerSession> currentSessionRef = null;
private DefaultTableModel getStackTableModel(Object[][] data) {
return new DefaultTableModel(data, new Object[]{
AppStrings.translate("callStack.header.swf"),
AppStrings.translate("callStack.header.file"),
AppStrings.translate("callStack.header.line"),
AppStrings.translate("stack.header.item")
}) {
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
}
public DebugStackPanel() {
stackTable = new JTable();
stackTable = new JTable(getStackTableModel(new Object[0][4]));
Main.getDebugHandler().addFrameChangeListener(new DebuggerHandler.FrameChangeListener() {
@Override
public void frameChanged(DebuggerSession session) {
@@ -160,8 +176,10 @@ public class DebugStackPanel extends JPanel {
sessionComboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (sessionComboBoxCreating) {
return;
synchronized (DebugStackPanel.this) {
if (sessionComboBoxCreating) {
return;
}
}
SessionItem selection = (SessionItem) sessionComboBox.getSelectedItem();
if (selection != null) {
@@ -174,12 +192,13 @@ public class DebugStackPanel extends JPanel {
lastSessionComboBoxIndex = sessionComboBox.getSelectedIndex();
Main.getDebugHandler().setSelectedSessionId(session.getId());
//session.refreshFrame();
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
refresh(session);
}
});
});
View.execInEventDispatchLater(new Runnable() {
@Override
public void run() {
@@ -210,7 +229,7 @@ public class DebugStackPanel extends JPanel {
SessionItem item = (SessionItem) value;
if (item != null) {
DebuggerSession session = Main.getDebugHandler().getSessionById(item.id);
if (!session.isPaused()) {
if (session == null || !session.isPaused()) {
c.setForeground(Color.GRAY);
c.setBackground(list.getBackground());
} else {
@@ -279,8 +298,8 @@ public class DebugStackPanel extends JPanel {
}
}
public void clear() {
stackTable.setModel(new DefaultTableModel());
public void clear() {
stackTable.setModel(getStackTableModel(new Object[0][4]));
if (Main.getDebugHandler().getActiveSessions().isEmpty()) {
active = false;
}
@@ -304,7 +323,10 @@ public class DebugStackPanel extends JPanel {
model.addElement(new SessionItem(id));
j++;
}
sessionComboBoxCreating = true;
synchronized (this) {
sessionComboBoxCreating = true;
}
if (itemIndex > -1) {
final int fItemIndex = itemIndex;
View.execInEventDispatchLater(new Runnable() {
@@ -315,7 +337,9 @@ public class DebugStackPanel extends JPanel {
sessionComboBox.setSelectedIndex(fItemIndex);
}
lastSessionComboBoxIndex = fItemIndex;
sessionComboBoxCreating = false;
synchronized (DebugStackPanel.this) {
sessionComboBoxCreating = false;
}
}
});
}
@@ -378,19 +402,7 @@ public class DebugStackPanel extends JPanel {
newTraitIndices[i] = newTraitIndex == null ? -1 : newTraitIndex;
}
DefaultTableModel tm = new DefaultTableModel(data, new Object[]{
AppStrings.translate("callStack.header.swf"),
AppStrings.translate("callStack.header.file"),
AppStrings.translate("callStack.header.line"),
AppStrings.translate("stack.header.item")
}) {
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
stackTable.setModel(tm);
stackTable.setModel(getStackTableModel(data));
this.swfHashes = newSwfHashes;
this.classIndices = newClassIndices;
this.methodIndices = newMethodIndices;
@@ -410,11 +422,12 @@ public class DebugStackPanel extends JPanel {
}
};
if (stackTable.getColumnModel().getColumnCount() >= 3) {
stackTable.setDefaultRenderer(String.class, renderer);
/*if (stackTable.getColumnModel().getColumnCount() >= 3) {
stackTable.getColumnModel().getColumn(0).setCellRenderer(renderer);
stackTable.getColumnModel().getColumn(1).setCellRenderer(renderer);
stackTable.getColumnModel().getColumn(2).setCellRenderer(renderer);
}
}*/
repaint();
}
});

View File

@@ -31,6 +31,10 @@ import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.WeakHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author JPEXS
@@ -46,6 +50,8 @@ public class DebuggerHandler implements DebugConnectionListener {
private boolean terminating = false;
private Map<SWF, Map<String, Set<Integer>>> allBreakPoints = new WeakHashMap<>();
private static ExecutorService pool = null;
public static class ActionScriptException extends Exception {
@@ -263,6 +269,11 @@ public class DebuggerHandler implements DebugConnectionListener {
synchronized (this) {
terminating = false;
}
if (pool != null) {
pool.shutdownNow();
pool = null;
}
}
public synchronized Map<String, Set<Integer>> getAllSessionsBreakPoints(SWF swf) {
@@ -423,4 +434,20 @@ public class DebuggerHandler implements DebugConnectionListener {
}
return true;
}
public static synchronized ExecutorService getPool() {
if (pool == null) {
AtomicInteger counter = new AtomicInteger(1);
ThreadFactory namedThreadFactory = runnable -> {
Thread t = new Thread(runnable);
t.setName("debugger-handler-thread-" + counter.getAndIncrement());
return t;
};
pool = Executors.newCachedThreadPool(namedThreadFactory);
}
return pool;
}
}

View File

@@ -17,6 +17,7 @@
package com.jpexs.decompiler.flash.gui;
import com.jpexs.debugger.flash.DebugMessageListener;
import com.jpexs.debugger.flash.Debugger;
import com.jpexs.debugger.flash.DebuggerCommands;
import com.jpexs.debugger.flash.DebuggerConnection;
import com.jpexs.debugger.flash.Variable;
@@ -34,6 +35,7 @@ import com.jpexs.debugger.flash.messages.in.InFrame;
import com.jpexs.debugger.flash.messages.in.InGetSwf;
import com.jpexs.debugger.flash.messages.in.InGetVariable;
import com.jpexs.debugger.flash.messages.in.InNumScript;
import com.jpexs.debugger.flash.messages.in.InOption;
import com.jpexs.debugger.flash.messages.in.InPlaceObject;
import com.jpexs.debugger.flash.messages.in.InProcessTag;
import com.jpexs.debugger.flash.messages.in.InScript;
@@ -47,6 +49,7 @@ import com.jpexs.debugger.flash.messages.out.OutGetSwf;
import com.jpexs.debugger.flash.messages.out.OutPlay;
import com.jpexs.debugger.flash.messages.out.OutProcessedTag;
import com.jpexs.debugger.flash.messages.out.OutRewind;
import com.jpexs.debugger.flash.messages.out.OutSetOption;
import com.jpexs.debugger.flash.messages.out.OutSwfInfo;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.configuration.Configuration;
@@ -56,6 +59,7 @@ import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -136,14 +140,17 @@ public class DebuggerSession {
private InSetBreakpoint inSetBreakpoint;
private int id;
private String title = "";
private static final int DEFAULT_TIMEOUT = 1000;
private List<Thread> getSwfThreadList = Collections.synchronizedList(new ArrayList<>());
private Map<String, DebuggerCommands.Watch> watches = new LinkedHashMap<>();
public DebuggerSession(DebuggerHandler handler, DebuggerConnection con, Map<SWF, Map<String, Set<Integer>>> breakpoints) {
id = con.getId();
id = con.getId();
toAddBPointMap = breakpoints;
this.handler = handler;
@@ -157,10 +164,8 @@ public class DebuggerSession {
@Override
public void run() {
Main.getMainFrame().getPanel().updateMenu();
}
}
});
//enlog(DebuggerConnection.class);
//enlog(DebuggerCommands.class);
@@ -291,6 +296,10 @@ public class DebuggerSession {
commands.setGetterTimeout(1500);
commands.setSetterTimeout(5000);
if (commands.playerConcurrency()) {
commands.debuggerSetConcurrency();
}
commands.squelch(true);
con.addMessageListener(new DebugMessageListener<InExit>() {
@@ -340,16 +349,16 @@ public class DebuggerSession {
if (inGetSwf == null) {
Logger.getLogger(DebuggerSession.class.getName()).log(Level.FINE, "session{0}: Cannot read SWF", id);
continue;
}
}
String sha256 = Helper.byteArrayToHex(MessageDigest.getInstance("SHA-256").digest(inGetSwf.swfData));
Logger.getLogger(DebuggerSession.class.getName()).log(Level.FINE, "session{0}: Received SWF hash = {1}", new Object[]{id, sha256});
String originalHash = Main.getHashFromMetadataFromSwfBytes(inGetSwf.swfData);
if (originalHash != null) {
Logger.getLogger(DebuggerSession.class.getName()).log(Level.FINE, "session{0}: Received SWF original hash = {1}", new Object[]{id, originalHash});
sha256 = originalHash;
}
SWF debuggedSwf = Main.findOpenedSwfByHash(sha256);
if (debuggedSwf == null) {
con.disconnect();
@@ -379,9 +388,9 @@ public class DebuggerSession {
}
try {
Set<String> hashes = new LinkedHashSet<>();
for (int file : modulePaths.keySet()) {
String path = modulePaths.get(file);
if (!path.contains(":")) {
@@ -391,22 +400,22 @@ public class DebuggerSession {
String hash = path.substring(0, path.indexOf(":"));
hashes.add(hash);
}
for (String hash : hashes) {
for (String hash : hashes) {
if (Main.findOpenedSwfByHash(hash) == null) {
//This is probably SWF file instrumented by another software
throw new IOException("SWF with hash " + hash + " not found");
}
}
}
if (!debuggedSwfs.isEmpty() && modulesEmptyBefore) {
if (title.isEmpty()) {
title = debuggedSwfs.values().iterator().next().toString();
}
if (con.isAS3) {
//Widelines - only AS3, it hangs in AS1/2 and SWD does not support UI32 lines
con.wideLines = commands.getOption("wide_line_player", "false").equals("true");
//Widelines - only AS3, it hangs in AS1/2 and SWD does not support UI32 lines
con.wideLines = commands.playerIsWideLine();
if (con.wideLines) {
commands.setOption("wide_line_debugger", "on");
commands.debuggerSetWideLine();;
}
} else {
Logger.getLogger(DebuggerSession.class.getName()).log(Level.FINER, "session{0}: End of connect - sending continue", id);
@@ -461,7 +470,19 @@ public class DebuggerSession {
con.addMessageListener(new DebugMessageListener<InPlaceObject>() {
@Override
public void message(InPlaceObject t) {
placedObjects.put(t.path, t.objId);
//Sometimes the player sends _global variable with 4 byte PTR instead of 8 byte
byte[] globalVar = new byte[]{(byte) 0xfe, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x5f, (byte) 0x67, (byte) 0x6c, (byte) 0x6f, (byte) 0x62, (byte) 0x61, (byte) 0x6c, (byte) 0x00};
String placeName = t.path;
long placeId = t.objId;
if (Arrays.equals(t.data, globalVar)) {
Logger.getLogger(DebuggerSession.class.getName()).log(Level.FINER, "session{0}: Received mangled placeobject _global", new Object[]{id});
placeName = "_global";
placeId = -2;
} else {
Logger.getLogger(DebuggerSession.class.getName()).log(Level.FINER, "session{0}: Received placeobject {1}", new Object[]{id, t.path});
}
Logger.getLogger(DebuggerSession.class.getName()).log(Level.FINEST, "session{0}: Placeobject hex data: {1}", new Object[]{id, Helper.byteArrayToHex(t.data)});
placedObjects.put(placeName, placeId);
con.dropMessage(t);
}
});
@@ -474,10 +495,10 @@ public class DebuggerSession {
synchronized (DebuggerSession.this) {
paused = false;
Logger.getLogger(DebuggerSession.class.getName()).log(Level.FINE, "session{0}: continued", id);
}
}
for (DebuggerHandler.BreakListener bl : handler.getBreakListeners()) {
bl.doContinue(DebuggerSession.this);
}
}
}
});
@@ -491,14 +512,13 @@ public class DebuggerSession {
@Override
public void run() {
Logger.getLogger(DebuggerSession.class.getName()).log(Level.FINE, "session{0}: In break at start", id);
synchronized (DebuggerSession.this) {
if (!connected) {
Logger.getLogger(DebuggerSession.class.getName()).log(Level.FINE, "session{0}: Received break while not connected", id);
return;
}
paused = true;
Logger.getLogger(DebuggerSession.class.getName()).log(Level.FINE, "session{0}: paused", id);
}
@@ -543,7 +563,7 @@ public class DebuggerSession {
sendBreakPoints();
} catch (IOException ex) {
//ignore
Logger.getLogger(DebuggerSession.class.getName()).log(Level.FINE, "session{0}: send breakpoints exception: {1}", new Object[] {id, ex.getMessage()});
Logger.getLogger(DebuggerSession.class.getName()).log(Level.FINE, "session{0}: send breakpoints exception: {1}", new Object[]{id, ex.getMessage()});
}
synchronized (DebuggerSession.this) {
@@ -574,14 +594,15 @@ public class DebuggerSession {
} else {
Main.startWork(AppStrings.translate("debug.session").replace("%id%", "" + id) + " - " + AppStrings.translate("work.breakat") + userBreakScriptName + ":" + message.line + " " + AppStrings.translate("debug.break.reason." + reason), null, true);
}
depth = 0;
refreshFrame();
//If there is single one left paused, switch to it
if (Main.getDebugHandler().getNumberOfPausedSessions() == 1) {
Main.getDebugHandler().setSelectedSessionId(getId());
}
depth = 0;
refreshFrame();
for (DebuggerHandler.BreakListener l : handler.getBreakListeners()) {
l.breakAt(DebuggerSession.this, newBreakScriptName, message.line,
moduleToClassIndex.containsKey(message.file) ? moduleToClassIndex.get(message.file) : -1,
@@ -631,7 +652,7 @@ public class DebuggerSession {
} catch (IOException ex) {
Logger.getLogger(DebuggerSession.class.getName()).log(Level.SEVERE, null, ex);
}
}*/
}*/
con.addMessageListener(new DebugMessageListener<InTrace>() {
@Override
@@ -657,8 +678,6 @@ public class DebuggerSession {
public int getId() {
return id;
}
public boolean containsSwf(SWF swf) {
return debuggedSwfs.containsValue(swf);
@@ -705,9 +724,9 @@ public class DebuggerSession {
return stackLines;
}
public InGetVariable getVariable(long parentId, String varName, boolean children, boolean useGetter) {
public synchronized InGetVariable getVariable(long parentId, String varName, boolean children, boolean useGetter) {
try {
return commands.getVariableWithTimeout(parentId, varName, useGetter, children, 100);
return commands.getVariableWithTimeout(parentId, varName, useGetter, children, DEFAULT_TIMEOUT);
} catch (IOException ex) {
return null;
}
@@ -740,7 +759,7 @@ public class DebuggerSession {
}
public void removeBreakPoint(SWF swf, String scriptName, int line) {
synchronized (this) {
synchronized (this) {
if (isBreakpointInvalid(swf, scriptName, line)) {
invalidBreakPointMap.get(swf).get(scriptName).remove(line);
if (invalidBreakPointMap.get(swf).get(scriptName).isEmpty()) {
@@ -772,10 +791,19 @@ public class DebuggerSession {
private int watchTag = 1;
public synchronized com.jpexs.debugger.flash.DebuggerCommands.Watch addWatch(Variable v, long v_id, boolean watchRead, boolean watchWrite) {
public synchronized DebuggerCommands.Watch addWatch(String varName, long varId, boolean watchRead, boolean watchWrite) {
if (getWatch(varName, varId) != null) {
if (!removeWatch(varName, varId)) {
return null;
}
}
int tag = watchTag++;
try {
return commands.addWatch(v_id, v.name, (watchRead ? OutAddWatch2.FLAG_READ : 0) | (watchWrite ? OutAddWatch2.FLAG_WRITE : 0), tag);
com.jpexs.debugger.flash.DebuggerCommands.Watch w = commands.addWatch(varId, varName, (watchRead ? OutAddWatch2.FLAG_READ : 0) | (watchWrite ? OutAddWatch2.FLAG_WRITE : 0), tag);
if (w != null) {
watches.put("" + w.varId + ":" + w.varName, w);
}
return w;
} catch (IOException ex) {
return null;
}
@@ -953,8 +981,11 @@ public class DebuggerSession {
}
public void setDepth(int depth) {
boolean depthChanged = depth != this.depth;
this.depth = depth;
refreshFrame();
if (depthChanged) {
refreshFrame();
}
}
public String moduleToString(int file) {
@@ -991,20 +1022,42 @@ public class DebuggerSession {
}
public void refreshFrame() {
synchronized (this) {
synchronized (DebuggerSession.this) {
if (!paused) {
return;
}
try {
frame = commands.getFrameWithTimeout(depth, 100);
pool = commands.getConstantPoolWithTimeout(0, 100);
} catch (IOException ex) {
//ignore
}
DebuggerHandler.getPool().submit(new Runnable() {
@Override
public void run() {
synchronized (DebuggerSession.this) {
if (!paused) {
return;
}
}
try {
frame = commands.getFrameWithTimeout(depth, DEFAULT_TIMEOUT);
pool = commands.getConstantPoolWithTimeout(0, DEFAULT_TIMEOUT);
} catch (IOException ex) {
//ignore
}
Logger.getLogger(DebugPanel.class.getName()).log(Level.FINE, "session{0}: Frame loaded", new Object[]{getId()});
if (frame == null) {
Logger.getLogger(DebugPanel.class.getName()).log(Level.FINE, "session{0}: Frame is null!", new Object[]{getId()});
}
if (pool == null) {
Logger.getLogger(DebugPanel.class.getName()).log(Level.FINE, "session{0}: CPool is null!", new Object[]{getId()});
}
for (DebuggerHandler.FrameChangeListener l : handler.getFrameChangeListeners()) {
l.frameChanged(DebuggerSession.this);
}
}
}
for (DebuggerHandler.FrameChangeListener l : handler.getFrameChangeListeners()) {
l.frameChanged(DebuggerSession.this);
}
});
}
public synchronized InFrame getFrame() {
@@ -1066,17 +1119,17 @@ public class DebuggerSession {
}
}
}
//If there is single one left paused, switch to it
if (Main.getDebugHandler().getNumberOfPausedSessions() == 1) {
for (DebuggerSession session : Main.getDebugHandler().getActiveSessions().values()) {
for (DebuggerSession session : Main.getDebugHandler().getActiveSessions().values()) {
if (session.isPaused()) {
Main.getDebugHandler().setSelectedSessionId(session.getId());
break;
}
}
}
for (DebuggerHandler.ConnectionListener l : handler.getConnectionListeners()) {
l.disconnected(DebuggerSession.this);
}
@@ -1282,5 +1335,45 @@ public class DebuggerSession {
public String getTitle() {
return title;
}
}
public Map<String, DebuggerCommands.Watch> getWatches() {
return new LinkedHashMap<>(watches);
}
public DebuggerCommands.Watch getWatch(String varName, long varId) {
return watches.get("" + varId + ":" + varName);
}
public boolean removeWatch(String varName, long variId) {
String key = "" + variId + ":" + varName;
if (!watches.containsKey(key)) {
return false;
}
try {
if (commands.removeWatch(variId, varName)) {
watches.remove(key);
return true;
}
} catch (IOException ex) {
//false
}
return false;
}
public SWF getCurrentSwf() {
InBreakAtExt info = getBreakInfo();
if (info == null) {
return null;
}
//Object[][] data = new Object[info.files.size()][4];
String moduleName = moduleToString(info.file);
if (moduleName.contains(":")) {
String swfHash = moduleName.substring(0, moduleName.indexOf(":"));
return Main.findOpenedSwfByHash(swfHash);
} else {
List<SWF> debuggedSwfs = new ArrayList<>(getDebuggedSwfs().values());
return debuggedSwfs.get(debuggedSwfs.size() - 1);
}
}
}

View File

@@ -441,9 +441,13 @@ public class Main {
}
public static synchronized boolean addWatch(DebuggerSession session, Variable v, long v_id, boolean watchRead, boolean watchWrite) {
DebuggerCommands.Watch w = session.addWatch(v, v_id, watchRead, watchWrite);
DebuggerCommands.Watch w = session.addWatch(v.name, v_id, watchRead, watchWrite);
return w != null;
}
public static synchronized boolean removeWatch(DebuggerSession session, Variable v, long v_id) {
return session.removeWatch(v.name, v_id);
}
public static void runPlayer(String title, final String exePath, String file, String flashVars) {
if (!new File(file).exists()) {
@@ -1137,7 +1141,7 @@ public class Main {
}
public static void updateSession() {
DebuggerSession session = getCurrentDebugSession();
/*DebuggerSession session = getCurrentDebugSession();
for (DebuggerHandler.FrameChangeListener l : getDebugHandler().getFrameChangeListeners()) {
l.frameChanged(session);
}
@@ -1145,6 +1149,7 @@ public class Main {
if (getDebugHandler().getNumberOfPausedSessions() > 0) {
mainFrame.getPanel().showDebugStackFrame();
}
*/
}
public static void ensureMainFrame() {
@@ -3197,7 +3202,7 @@ public class Main {
@Override
public void disconnected(DebuggerSession session) {
Main.updateSession();
//Main.updateSession();
if (Main.mainFrame != null) {
Main.mainFrame.getMenu().updateComponents();
}

View File

@@ -1636,7 +1636,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
private void updateUi(final Openable openable) {
View.checkAccess();
Main.updateSession();
//Main.updateSession();
SWF swf = null;
if (openable instanceof SWF) {
swf = (SWF) openable;
@@ -5785,7 +5785,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
return;
}
Main.updateSession();
//Main.updateSession();
if (!(treeItem instanceof OpenableList)) {
Openable openable = treeItem.getOpenable();

View File

@@ -16,10 +16,13 @@
*/
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.debugger.flash.DebuggerCommands;
import com.jpexs.debugger.flash.DebuggerMessage;
import com.jpexs.debugger.flash.Variable;
import com.jpexs.debugger.flash.VariableFlags;
import com.jpexs.debugger.flash.VariableType;
import com.jpexs.debugger.flash.messages.in.InGetVariable;
import com.jpexs.debugger.flash.messages.out.OutAddWatch2;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.ClassPath;
@@ -266,7 +269,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
return;
}
this.abc = abc;
this.abc = abc;
if (Main.isSwfAir(abc.getOpenable())) {
libraryComboBox.setSelectedIndex(SWF.LIBRARY_AIR);
} else {
@@ -301,10 +304,11 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
public static class VariableNode {
private static Thread variableLoaderThread;
private static List<Runnable> loaderList = Collections.synchronizedList(new ArrayList<>());
private static final Object loaderLock = new Object();
private static Map<Integer, Thread> sessionIdToVariableLoaderThread = new HashMap<>();
private static Map<Integer, List<Runnable>> sessionIdToLoaderList = new HashMap<>();
private static Map<Integer, List<VariableNode>> sessionIdToLoadedVariableNode = new HashMap<>();
private static Map<Integer, Object> sessionIdToLoaderLock = new HashMap<>();
public List<VariableNode> path = new ArrayList<>();
public Variable var;
@@ -322,8 +326,25 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
private List<VariableNode> childs;
public List<Variable> traits = new ArrayList<>();
private DebuggerSession session;
private MyTreeTable treeTable;
private boolean as3;
public static void stopLoading(int sessionId) {
if (!sessionIdToLoadedVariableNode.containsKey(sessionId)) {
return;
}
sessionIdToLoaderList.get(sessionId).clear();
for (VariableNode node : sessionIdToLoadedVariableNode.get(sessionId)) {
synchronized (node) {
node.childs = new ArrayList<>();
node.loading = false;
node.loaded = true;
}
}
sessionIdToLoadedVariableNode.get(sessionId).clear();
}
@Override
public int hashCode() {
int hash = 3;
@@ -361,6 +382,8 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
public boolean loaded = false;
private boolean loading = false;
private static boolean isTraits(Variable v) {
return (v.vType == VariableType.UNKNOWN && "traits".equals(v.typeName));
}
@@ -393,19 +416,24 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
boolean useGetter = (var.flags & VariableFlags.IS_CONST) == 0;
//boolean isAS3 = (Main.getMainFrame().getPanel().getCurrentSwf().isAS3());
DebuggerSession currentSession = Main.getCurrentDebugSession();
if (Main.getCurrentDebugSession() == null) {
if (currentSession == null || !currentSession.isPaused()) {
return;
}
if (currentSession != session) {
return;
}
if (parentObjectId == 0 && objectId != 0L && as3) {
igv = Main.getCurrentDebugSession().getVariable(objectId, "", true, useGetter);
igv = currentSession.getVariable(objectId, "", true, useGetter);
} else {
igv = Main.getCurrentDebugSession().getVariable(parentObjectId, var.name, true, useGetter);
igv = currentSession.getVariable(parentObjectId, var.name, true, useGetter);
}
if (igv == null) { //timeout
return;
}
//Logger.getLogger(VariableNode.class.getName()).log(Level.FINE, "session{0}: Get var data: {1}", new Object[]{currentSession.getId(), Helper.byteArrayToHex(igv.data)});
//current var is getter function - set it to value really got
if ((var.flags & VariableFlags.HAS_GETTER) > 0) {
varInsideGetter = igv.parent;
@@ -416,10 +444,10 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
if (!Configuration.showVarsWithDontEnumerateFlag.get() && (igv.childs.get(i).flags & VariableFlags.DONT_ENUMERATE) > 0) {
continue;
}
if (!isTraits(igv.childs.get(i))) {
Long parentObjectId = varToObjectId(varInsideGetter);
childs.add(new VariableNode(as3, path, level + 1, igv.childs.get(i), parentObjectId, curTrait));
childs.add(new VariableNode(currentSession, treeTable, as3, path, level + 1, igv.childs.get(i), parentObjectId, curTrait));
} else {
curTrait = igv.childs.get(i);
traits.add(curTrait);
@@ -427,62 +455,130 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
}
}
private void ensureLoaded() {
if (!loaded) {
/*synchronized (VariableNode.class) {
if (variableLoaderThread == null) {
Runnable r = new Runnable() {
@Override
public void run() {
while(true) {
if (loaderList.isEmpty()) {
synchronized (loaderLock) {
try {
loaderLock.wait(500);
} catch (InterruptedException ex) {
}
}
} else {
Runnable toRun = loaderList.remove(0);
toRun.run();
}
}
}
};
variableLoaderThread = new Thread(r, "Variable loader");
variableLoaderThread.setDaemon(true);
variableLoaderThread.start();
}
private void ensureLoaded() {
synchronized (VariableNode.this) {
if (loaded || loading) {
return;
}
loaderList.add(new Runnable() {
loading = true;
}
int sessionId = session.getId();
if (!sessionIdToVariableLoaderThread.containsKey(sessionId)) {
Runnable r = new Runnable() {
@Override
public void run() {
reloadChildren();
loaded = true;
}
});
synchronized (loaderLock) {
loaderLock.notify();
}*/
reloadChildren();
loaded = true;
while (true) {
if (sessionIdToLoaderList.get(sessionId).isEmpty()) {
Object lock = sessionIdToLoaderLock.get(session.getId());
synchronized (lock) {
try {
lock.wait(500);
} catch (InterruptedException ex) {
//ignored
}
}
} else {
Runnable toRun = sessionIdToLoaderList.get(sessionId).remove(0);
toRun.run();
}
}
}
};
sessionIdToLoaderList.put(sessionId, new ArrayList<>());
sessionIdToLoaderLock.put(sessionId, new Object());
Thread t = new Thread(r, "Variable loader for session " + sessionId);
sessionIdToVariableLoaderThread.put(sessionId, t);
t.setDaemon(true);
t.start();
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
//ignore
}
}
sessionIdToLoaderList.get(sessionId).add(new Runnable() {
@Override
public void run() {
synchronized (VariableNode.this) {
if (!loading) {
Logger.getLogger(VariableNode.class.getName()).log(Level.FINE, "session{0}: Already loaded {1}, skipping", new Object[]{session.getId(), var.name});
return;
}
}
Logger.getLogger(VariableNode.class.getName()).log(Level.FINE, "session{0}: Loading children of {1}", new Object[]{session.getId(), var.name});
reloadChildren();
synchronized (VariableNode.this) {
if (!loading) {
Logger.getLogger(VariableNode.class.getName()).log(Level.FINE, "session{0}: Already loaded {1}, not firing", new Object[]{session.getId(), var.name});
return;
}
loaded = true;
loading = false;
Logger.getLogger(VariableNode.class.getName()).log(Level.FINE, "session{0}: Children of {1} loaded", new Object[]{session.getId(), var.name});
}
DebuggerSession currentSession = Main.getCurrentDebugSession();
if (currentSession == null || currentSession.getId() != sessionId) {
return;
}
VariablesTableModel variableModel = (VariablesTableModel) treeTable.getTreeTableModel();
Object[] changedPath = new Object[path.size()];
for (int i = 0; i < path.size(); i++) {
changedPath[i] = path.get(i);
}
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
Logger.getLogger(VariableNode.class.getName()).log(Level.FINE, "session{0}: Firing change of {1} - {2} childs", new Object[]{session.getId(), var.name, childs.size()});
int[] childIds = new int[childs.size()];
Object[] childObjs = new Object[childs.size()];
for (int i = 0; i < childIds.length; i++) {
childIds[i] = i;
childObjs[i] = childs.get(i);
}
//variableModel.fireTreeStructureChanged(treeTable.getTree(), changedPath, new int[0], null);
variableModel.fireTreeNodesInserted(treeTable.getTree(), changedPath, childIds, childObjs);
treeTable.repaint();
}
});
}
});
if (!sessionIdToLoadedVariableNode.containsKey(sessionId)) {
sessionIdToLoadedVariableNode.put(sessionId, new ArrayList<>());
}
sessionIdToLoadedVariableNode.get(sessionId).add(this);
Object lock = sessionIdToLoaderLock.get(sessionId);
Logger.getLogger(VariableNode.class.getName()).log(Level.FINE, "session{0}: Scheduling loading children of {1}", new Object[]{session.getId(), var.name});
synchronized (lock) {
lock.notify();
}
/*reloadChildren();
loaded = true;*/
}
public VariableNode getChildAt(int index) {
ensureLoaded();
if (!loaded) {
return null;
}
return childs.get(index);
}
public int getChildCount() {
ensureLoaded();
if (!loaded) {
return 0;
}
return childs.size();
}
public VariableNode(boolean as3, List<VariableNode> parentPath, int level, Variable var, Long parentObjectId, Variable trait) {
public VariableNode(DebuggerSession session, MyTreeTable treeTable, boolean as3, List<VariableNode> parentPath, int level, Variable var, Long parentObjectId, Variable trait) {
this.var = var;
this.varInsideGetter = var;
this.parentObjectId = parentObjectId;
@@ -491,10 +587,12 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
this.path.addAll(parentPath);
this.path.add(this);
loaded = false;
this.session = session;
this.treeTable = treeTable;
this.as3 = as3;
}
public VariableNode(boolean as3, List<VariableNode> parentPath, int level, Variable var, Long parentObjectId, Variable trait, List<VariableNode> subvars) {
public VariableNode(DebuggerSession session, MyTreeTable treeTable, boolean as3, List<VariableNode> parentPath, int level, Variable var, Long parentObjectId, Variable trait, List<VariableNode> subvars) {
this.var = var;
this.varInsideGetter = var;
this.parentObjectId = parentObjectId;
@@ -510,6 +608,8 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
vn.path.add(vn);
}
loaded = true;
this.session = session;
this.treeTable = treeTable;
this.as3 = as3;
}
}
@@ -545,17 +645,18 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
private static final int STRUCTURE_CHANGED = 3;
private final MyTreeTable ttable;
private final MyTreeTable treeTable;
public VariablesTableModel(boolean as3, MyTreeTable ttable, List<Variable> vars) {
this.ttable = ttable;
public VariablesTableModel(DebuggerSession session, boolean as3, MyTreeTable treeTable, List<Variable> vars, List<Long> parentIds) {
this.treeTable = treeTable;
List<VariableNode> childs = new ArrayList<>();
for (int i = 0; i < vars.size(); i++) {
childs.add(new VariableNode(as3, new ArrayList<>(), 1, vars.get(i), 0L, null));
childs.add(new VariableNode(session, treeTable, as3, new ArrayList<>(), 1, vars.get(i), parentIds == null ? 0L : parentIds.get(i), null));
}
root = new VariableNode(as3, new ArrayList<>(), 0, null, 0L, null, childs);
root = new VariableNode(session, treeTable, as3, new ArrayList<>(), 0, null, 0L, null, childs);
root.loaded = true;
}
@Override
@@ -767,7 +868,26 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
case COLUMN_SCOPE:
return flagsToScopeString(var.flags);
case COLUMN_FLAGS:
return flagsToString(var.flags);
String flags = flagsToString(var.flags);
DebuggerSession session = Main.getCurrentDebugSession();
DebuggerCommands.Watch w = session == null ? null : session.getWatch(((VariableNode) node).var.name, ((VariableNode) node).parentObjectId);
if (w != null) {
if ((w.flags & OutAddWatch2.FLAG_READ) > 0) {
if (!flags.isEmpty()) {
flags += ", ";
}
flags += "watch:read";
}
if ((w.flags & OutAddWatch2.FLAG_WRITE) > 0) {
if (!flags.isEmpty()) {
flags += ", ";
}
flags += "watch:write";
}
}
return flags;
case COLUMN_TYPE:
String typeStr = val.getTypeAsStr();
if ("Object".equals(typeStr)) {
@@ -782,7 +902,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
case VariableType.OBJECT:
case VariableType.MOVIECLIP:
case VariableType.FUNCTION:
return var.getTypeAsStr() + "(" + val.value + ")";
return var.getTypeAsStr() + "(0x" + Long.toUnsignedString((Long) val.value, 16) + ")";
case VariableType.STRING:
return "\"" + Helper.escapeActionScriptString("" + val.value) + "\"";
default:
@@ -868,7 +988,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
@Override
public void valueForPathChanged(TreePath path, Object newValue) {
fireTreeNodesChanged(ttable, path.getParentPath().getPath(), new int[0], new Object[]{path.getLastPathComponent()});
fireTreeNodesChanged(treeTable, path.getParentPath().getPath(), new int[0], new Object[]{path.getLastPathComponent()});
}
@Override
@@ -1068,8 +1188,8 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
}
String scriptNamePrintable = DottedChain.parseWithSuffix(scriptName.toString()).toPrintableString(new LinkedHashSet<>(), ci.abc.getSwf(), true);
if (swfRef.getVal() == abc.getSwf()) {
if (swfRef.getVal() == abc.getSwf()) {
hilightScript(getOpenable(), scriptNamePrintable);
return;
}
@@ -1131,12 +1251,12 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
private Path typeToPath(GraphTargetItem type) {
if (type instanceof TypeItem) {
TypeItem ti = (TypeItem) type;
TypeItem ti = (TypeItem) type;
return new Path(ti.fullTypeName.getStringParts());
}
return new Path(Helper.splitString(".", type.toString())); //Arrays.asList(type.toString().split("\\.")));
}
@Override
public Path getTraitSubType(Path className, String traitName, int level) {
Reference<Boolean> foundStatic = new Reference<>(null);
@@ -1212,7 +1332,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
Path callType = null;
if (ti != null) {
type = typeToPath(ti.returnType);
callType = typeToPath(ti.callReturnType);
callType = typeToPath(ti.callReturnType);
}
if (ti.trait instanceof TraitSlotConst) {
callType = null;
@@ -1230,7 +1350,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
}
if (tmgs.kindType == Trait.TRAIT_GETTER) {
type = callType;
callType = null;
callType = null;
}
}
ret.add(new com.jpexs.decompiler.flash.simpleparser.Variable(true, new Path(def.getPropertyName()), 0, isStaticList.get(i), type, callType));
@@ -1318,7 +1438,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
JCheckBoxMenuItem deobfuscateIdentifiersMenuItem = new JCheckBoxMenuItem(AppStrings.translate("deobfuscate_options.deobfuscateIdentifiers"));
deobfuscateIdentifiersMenuItem.setSelected(Configuration.autoDeobfuscateIdentifiers.get());
deobfuscateIdentifiersMenuItem.addActionListener(ABCPanel.this::autoDeobfuscateIdentifiersMenuItemActionPerformed);
JCheckBoxMenuItem simplifyExpressionsMenuItem = new JCheckBoxMenuItem(AppStrings.translate("deobfuscate_options.simplify_expressions"));
simplifyExpressionsMenuItem.setSelected(Configuration.simplifyExpressions.get());
simplifyExpressionsMenuItem.addActionListener(ABCPanel.this::simplifyExpressionsMenuItemActionPerformed);
@@ -1326,14 +1446,12 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
removeObfuscatedDeclarationsMenuItem.setSelected(Configuration.deobfuscateAs12RemoveInvalidNamesAssignments.get());
removeObfuscatedDeclarationsMenuItem.addActionListener(this::removeObfuscatedDeclarationsMenuItemActionPerformed);
*/
JCheckBoxMenuItem disableDecompilationMenuItem = new JCheckBoxMenuItem(AppStrings.translate("menu.settings.disabledecompilation"));
disableDecompilationMenuItem.setSelected(!Configuration.decompile.get());
disableDecompilationMenuItem.addActionListener(ABCPanel.this::disableDecompilationMenuItemActionPerformed);
popupMenu.add(deobfuscateIdentifiersMenuItem);
popupMenu.add(deobfuscateIdentifiersMenuItem);
popupMenu.add(simplifyExpressionsMenuItem);
//popupMenu.add(removeObfuscatedDeclarationsMenuItem);
popupMenu.add(disableDecompilationMenuItem);
@@ -1549,6 +1667,8 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
splitPane = null;
add(panB, BorderLayout.CENTER);
}
debugPanel.refresh();
}
private void decompiledTextAreaTextChanged() {
@@ -1811,12 +1931,12 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
String swfHash = nameIncludingSwfHash.substring(nameIncludingSwfHash.indexOf(":"));
String name = nameIncludingSwfHash.substring(nameIncludingSwfHash.indexOf(":") + 1);
Openable openable = Main.findOpenedSwfByHash(swfHash);
if (openable != null) {
hilightScript(openable, name);
}
}
/**
* Hilights specific script.
*
@@ -2188,13 +2308,13 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
Configuration.simplifyExpressions.set(menuItem.isSelected());
mainPanel.autoDeobfuscateChanged();
}
private void autoDeobfuscateIdentifiersMenuItemActionPerformed(ActionEvent evt) {
JCheckBoxMenuItem menuItem = (JCheckBoxMenuItem) evt.getSource();
Configuration.autoDeobfuscateIdentifiers.set(menuItem.isSelected());
mainPanel.autoDeobfuscateChanged();
}
private void disableDecompilationMenuItemActionPerformed(ActionEvent evt) {
JCheckBoxMenuItem menuItem = (JCheckBoxMenuItem) evt.getSource();
Configuration.decompile.set(!menuItem.isSelected());

View File

@@ -1158,7 +1158,7 @@ public class ActionPanel extends JPanel implements SearchListener<ScriptSearchRe
editor.addTextChangedListener(this::editorTextChanged);
decompiledEditor.addTextChangedListener(this::decompiledEditorTextChanged);
debugPanel.refresh(Main.getCurrentDebugSession());
debugPanel.refresh();
decompiledEditor.refreshMarkers();
editor.refreshMarkers();
}

View File

@@ -598,7 +598,7 @@ button.edit.script.disassembled = Edit P-code
debug.watch.add = Add watch to %name%
debug.watch.add.read = Read
debug.watch.add.write = Write
debug.watch.add.readwrite = Read+Write-
debug.watch.add.readwrite = Read + Write
error.debug.watch.add = Cannot add watch to this variable.
variables.column.scope = Scope
variables.column.flags = Flags
@@ -1127,4 +1127,9 @@ message.info.debugListen = The listening action allows you to run SWF files via
You can prepare SWF with context menu action "Prepare file for debugging".\n\
Unprepared files will be ignored by the debugger!\n\n\
Tip: If you want just Debug SWF in the standalone content debugger,\n\
use "Debug" action instead, because that will prepare SWF automatically.\n\n
use "Debug" action instead, because that will prepare SWF automatically.\n\n
#after 25.1.1
debug.watch.remove = Remove watch
error.debug.watch.remove = Cannot remove watch from this variable.
variables.header.watches = Watches

View File

@@ -598,7 +598,7 @@ button.edit.script.disassembled = Edita codi-P
debug.watch.add = Afegeix guaita a %name%
debug.watch.add.read = Lectura
debug.watch.add.write = Escriptura
debug.watch.add.readwrite = Lectura+Escriptura-
debug.watch.add.readwrite = Lectura + Escriptura
error.debug.watch.add = No es pot afegir un guaita a aquesta variable.
variables.column.scope = Abast
variables.column.flags = Banderes

View File

@@ -598,7 +598,7 @@ button.edit.script.disassembled = Upravit P-k\u00f3d
debug.watch.add = P\u0159idat sledov\u00e1n\u00ed pro %name%
debug.watch.add.read = \u010cten\u00ed
debug.watch.add.write = Z\u00e1pis
debug.watch.add.readwrite = \u010cten\u00ed+Z\u00e1pis-
debug.watch.add.readwrite = \u010cten\u00ed + Z\u00e1pis
error.debug.watch.add = Nelze p\u0159idat sledov\u00e1n\u00ed na tuto prom\u011bnnou.
variables.column.scope = Rozsah
variables.column.flags = P\u0159\u00edznaky
@@ -1127,4 +1127,9 @@ message.info.debugListen = Akce naslouch\u00e1n\u00ed v\u00e1m umo\u017en\u00ed
menu s n\u00e1zvem "P\u0159ipravit soubor pro lad\u011bn\u00ed".\n\
Nep\u0159ipraven\u00e9 soubory budou v debuggeru ignorov\u00e1ny!\n\n\
Tip: Pokud chcete pouze ladit SWF v standalone content debuggeru,\n\
pou\u017eijte m\u00edsto toho akci "Ladit", proto\u017ee ta p\u0159ipravuje SWF automaticky.\n\n
pou\u017eijte m\u00edsto toho akci "Ladit", proto\u017ee ta p\u0159ipravuje SWF automaticky.\n\n
#after 25.1.1
debug.watch.remove = Odstranit sledov\u00e1n\u00ed
error.debug.watch.remove = Nelze odstranit sledov\u00e1n\u00ed z t\u00e9to prom\u011bnn\u00e9.
variables.header.watches = Sledov\u00e1n\u00ed

View File

@@ -989,3 +989,8 @@ message.info.debugListen = Die Listening-Aktion erm\u00f6glicht es Ihnen, SWF-Da
Nicht vorbereitete Dateien werden vom Debugger ignoriert!\n\n\
Tipp: Wenn Sie SWF nur im eigenst\u00e4ndigen Content-Debugger debuggen m\u00f6chten,\n\
verwenden Sie stattdessen die Aktion "Debuggen", da diese SWF automatisch vorbereitet.\n\n
#after 25.1.1
debug.watch.remove = \u00dcberwachung entfernen
error.debug.watch.remove = \u00dcberwachung kann von dieser Variablen nicht entfernt werden.
variables.header.watches = \u00dcberwachungen

View File

@@ -598,7 +598,7 @@ button.edit.script.disassembled = P-code \u3092\u7de8\u96c6
debug.watch.add = %name% \u306b\u30a6\u30a9\u30c3\u30c1\u3092\u8ffd\u52a0
debug.watch.add.read = \u8aad\u307f\u53d6\u308a
debug.watch.add.write = \u66f8\u304d\u8fbc\u307f
debug.watch.add.readwrite = \u8aad\u307f\u53d6\u308a+\u66f8\u304d\u8fbc\u307f-
debug.watch.add.readwrite = \u8aad\u307f\u53d6\u308a + \u66f8\u304d\u8fbc\u307f
error.debug.watch.add = \u3053\u306e\u5909\u6570\u306b\u30a6\u30a9\u30c3\u30c1\u3092\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093\u3002
variables.column.scope = \u30b9\u30b3\u30fc\u30d7
variables.column.flags = \u30d5\u30e9\u30b0

View File

@@ -598,7 +598,7 @@ button.edit.script.disassembled = P-code bewerken
debug.watch.add = Voeg bekijken toe aan %name%
debug.watch.add.read = Lezen
debug.watch.add.write = Schrijven
debug.watch.add.readwrite = Lezen+Schrijven+
debug.watch.add.readwrite = Lezen + Schrijven
error.debug.watch.add = Kan bekijken niet toevoegen aan deze variabele
variables.column.scope = Scope
variables.column.flags = Vlaggen

View File

@@ -598,7 +598,7 @@ button.edit.script.disassembled = Editar P-code
debug.watch.add = Adicionar rel\u00f3gio a %name%
debug.watch.add.read = Ler
debug.watch.add.write = Escrever
debug.watch.add.readwrite = Ler+Escrever-
debug.watch.add.readwrite = Ler + Escrever
error.debug.watch.add = N\u00e3o foi poss\u00edvel adicionar rel\u00f3gio a esta vari\u00e1vel.
variables.column.scope = Escopo
variables.column.flags = Flags

View File

@@ -598,7 +598,7 @@ button.edit.script.disassembled = Upravi\u0165 P-code
debug.watch.add = Prida\u0165 sledovanie pre %name%
debug.watch.add.read = \u010c\u00edtanie
debug.watch.add.write = Z\u00e1pis
debug.watch.add.readwrite = \u010c\u00edtanie+Z\u00e1pis-
debug.watch.add.readwrite = \u010c\u00edtanie + Z\u00e1pis
error.debug.watch.add = Nie je mo\u017en\u00e9 prida\u0165 sledovanie pre t\u00fato premenn\u00fa.
variables.column.scope = Rozsah
variables.column.flags = Pr\u00edznaky
@@ -1128,3 +1128,8 @@ message.info.debugListen = Akcia po\u010d\u00favania v\u00e1m umo\u017e\u0148uje
Nepripraven\u00e9 s\u00fabory bud\u00fa debuggerom ignorovan\u00e9!\n\n\
Tip: Ak chcete len ladi\u0165 SWF v samostatnom content debuggeri,\n\
pou\u017eite namiesto toho akciu "Ladi\u0165", preto\u017ee t\u00e1 pripravi SWF automaticky.\n\n
#after 25.1.1
debug.watch.remove = Odstr\u00e1ni\u0165 sledovanie
error.debug.watch.remove = Nie je mo\u017en\u00e9 odstr\u00e1ni\u0165 sledovanie z tejto premennej.
variables.header.watches = Sledovania

View File

@@ -598,7 +598,7 @@ button.edit.script.disassembled = Uredi P-kodo
debug.watch.add = Dodaj nadzor v %name%
debug.watch.add.read = Preberi
debug.watch.add.write = Pi\u0161i
debug.watch.add.readwrite = Branje + pisanje-
debug.watch.add.readwrite = Branje + pisanje
error.debug.watch.add = Tej spremenljivki ni mogo\u010de dodati nadzora.
variables.column.scope = Obseg
variables.column.flags = Zastavice

View File

@@ -596,7 +596,7 @@ button.edit.script.disassembled = Redigera P-Kod
debug.watch.add = L\u00e4gg till watch till %name%
debug.watch.add.read = L\u00e4s
debug.watch.add.write = Skriv
debug.watch.add.readwrite = L\u00e4s+Skriv-
debug.watch.add.readwrite = L\u00e4s + Skriv
error.debug.watch.add = Kan inte l\u00e4gga till watch till denna variabel.
variables.column.scope = Scope
variables.column.flags = Flags

View File

@@ -598,7 +598,7 @@ button.edit.script.disassembled = P kodu d\u00fczenle
debug.watch.add = \u0130zlemeyi %name% i\u00e7in ekle
debug.watch.add.read = Oku
debug.watch.add.write = Yaz
debug.watch.add.readwrite = Oku+yaz-
debug.watch.add.readwrite = Oku + yaz
error.debug.watch.add = Bu de\u011fi\u015fkene izleme eklenemez.
variables.column.scope = Kapsam
variables.column.flags = Bayraklar

View File

@@ -598,7 +598,7 @@ button.edit.script.disassembled = \u7f16\u8f91 P-code
debug.watch.add = \u5c06\u76d1\u89c6\u6dfb\u52a0\u5230%name%
debug.watch.add.read = \u8bfb\u53d6
debug.watch.add.write = \u5199\u5165
debug.watch.add.readwrite = \u8bfb+\u5199-
debug.watch.add.readwrite = \u8bfb+\u5199
error.debug.watch.add = \u65e0\u6cd5\u5c06\u76d1\u89c6\u6dfb\u52a0\u5230\u6b64\u53d8\u91cf\u3002
variables.column.scope = \u8303\u56f4
variables.column.flags = \u6807\u8bb0