Fixed: #1678 Removing AS3 class does not correctly clear cache

This commit is contained in:
Jindra Petřík
2021-04-05 16:38:07 +02:00
parent bf387eba06
commit 1690fce8fa
4 changed files with 130 additions and 117 deletions

View File

@@ -31,10 +31,10 @@ All notable changes to this project will be documented in this file.
- [#1676] Messages on movie tags when Flash Player ActiveX not available
- [#1677] DefineFont2/3 - missing codeTableOffset if numGlyphs is zero and font has layout
- AS decompilation - §§push before loop
- [#1678] Flash viewer - shapes with mitter join do not render correctly
- [#1678] Removing AS3 class does not correctly clear cache
### Removed
- Flash viewer - miter with clip support removed as it was not working correctly
- [#1678] Flash viewer - miter with clip support removed as it was not working correctly
## [14.3.1] - 2021-03-25
### Fixed

View File

@@ -2620,11 +2620,11 @@ public final class SWF implements SWFContainerItem, Timelined {
public void clearScriptCache() {
as2Cache.clear();
as3Cache.clear();
if (abcList != null) {
for (ABCContainerTag c : abcList) {
c.getABC().clearPacksCache();
}
List<ABCContainerTag> abcList = getAbcList();
for (ABCContainerTag c : abcList) {
c.getABC().clearPacksCache();
}
asmsCache = null;
asmsCacheExportFilenames = null;
IdentifiersDeobfuscation.clearCache();
@@ -2652,11 +2652,11 @@ public final class SWF implements SWFContainerItem, Timelined {
public void clearAllCache() {
characters = null;
characterIdTags = null;
clearAbcListCache();
timeline = null;
clearReadOnlyListCache();
clearImageCache();
clearScriptCache();
clearAbcListCache();
clearAllStaticCache();
}

View File

@@ -1581,6 +1581,10 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
public void run() {
((Tag) abc.parentTag).getSwf().clearScriptCache();
fTraits.traits.remove(fTraitIndex);
if (fTraits.traits.isEmpty()) {
abc.script_info.get(decompiledTextArea.getScriptLeaf().scriptIndex).delete(abc, true);
abc.pack();
}
((Tag) abc.parentTag).setModified(true);
}
});

View File

@@ -1477,118 +1477,127 @@ public class TagTreeContextMenu extends JPopupMenu {
}
if (ViewMessages.showConfirmDialog(mainPanel, confirmationMessage, mainPanel.translate("message.confirm"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
Runnable r = new Runnable() {
@Override
public void run() {
Map<SWF, List<Tag>> tagsToRemoveBySwf = new HashMap<>();
Set<SWF> swfsToClearCache = new HashSet<>();
for (int i = 0; i < itemsToRemove.size(); i++) {
Object item = itemsToRemove.get(i);
if (item instanceof AS3Package) {
List<ScriptPack> subScriptPacks = new ArrayList<>();
getAllAS3PackageScriptPacks((AS3Package) item, subScriptPacks);
for (ScriptPack pack : subScriptPacks) {
if (!itemsToRemove.contains(pack)) {
itemsToRemove.add(pack);
itemsToRemoveParents.add(new Object());
itemsToRemoveSprites.add(new Object());
}
}
}
if (item instanceof AS2Package) {
List<ASMSource> subAsmSources = new ArrayList<>();
getAllAS2PackageScriptPacks((AS2Package) item, subAsmSources);
for (ASMSource asmSource : subAsmSources) {
if (!itemsToRemove.contains(asmSource)) {
tagsToRemove.add((Tag) asmSource);
}
}
}
}
List<ABC> abcsToPack = new ArrayList<>();
for (int i = 0; i < itemsToRemove.size(); i++) {
Object item = itemsToRemove.get(i);
Object parent = itemsToRemoveParents.get(i);
if (item instanceof BUTTONCONDACTION) {
DefineButton2Tag button = (DefineButton2Tag) parent;
BUTTONCONDACTION buttonCondAction = (BUTTONCONDACTION) item;
button.actions.remove(buttonCondAction);
if (buttonCondAction.isLast) {
if (!button.actions.isEmpty()) {
button.actions.get(button.actions.size() - 1).isLast = true;
}
}
button.setModified(true);
}
if (item instanceof CLIPACTIONRECORD) {
PlaceObjectTypeTag place = (PlaceObjectTypeTag) parent;
Timelined tim = (itemsToRemoveSprites.get(i) instanceof DefineSpriteTag) ? (DefineSpriteTag) itemsToRemoveSprites.get(i) : place.getSwf();
CLIPACTIONRECORD clipActionRecord = (CLIPACTIONRECORD) item;
CLIPACTIONS clipActions = place.getClipActions();
clipActions.clipActionRecords.remove(clipActionRecord);
if (clipActions.clipActionRecords.isEmpty()) {
place.setPlaceFlagHasClipActions(false);
place.setClipActions(null);
}
clipActions.calculateAllEventFlags();
place.setModified(true);
tim.resetTimeline();
}
if (item instanceof ScriptPack) {
ScriptPack sp = (ScriptPack) item;
sp.delete(sp.abc, true);
abcsToPack.add(sp.abc);
swfsToClearCache.add(sp.getSwf());
for (ABCContainerTag ct : sp.getSwf().getAbcList()) {
if (ct.getABC() == sp.abc) {
((Tag) ct).setModified(true);
break;
}
}
}
}
for (ABC abc : abcsToPack) {
abc.pack();
ABCContainerTag container = null;
for (ABCContainerTag ct : abc.getSwf().getAbcList()) {
if (ct.getABC() == abc) {
container = ct;
break;
}
}
if (abc.script_info.isEmpty()) { //all scripts in abc were removed
abc.getSwf().removeTag((Tag) container);
abc.getSwf().setModified(true);
} else {
((Tag) container).setModified(true);
}
}
for (Tag tag : tagsToRemove) {
SWF swf = tag.getSwf();
if (!tagsToRemoveBySwf.containsKey(swf)) {
tagsToRemoveBySwf.put(swf, new ArrayList<>());
}
tagsToRemoveBySwf.get(swf).add(tag);
}
for (SWF swf : tagsToRemoveBySwf.keySet()) {
swf.removeTags(tagsToRemoveBySwf.get(swf), removeDependencies);
}
for (SWF swf : swfsToClearCache) {
swf.clearAllCache();
}
}
};
if (mainPanel.folderPreviewPanel.selectedItems.isEmpty()) {
tagTree.clearSelection();
mainPanel.treeOperation(r);
} else {
//current folder must stay selected
r.run();
mainPanel.refreshTree();
}
Map<SWF, List<Tag>> tagsToRemoveBySwf = new HashMap<>();
Set<SWF> swfsToClearCache = new HashSet<>();
for (int i = 0; i < itemsToRemove.size(); i++) {
Object item = itemsToRemove.get(i);
if (item instanceof AS3Package) {
List<ScriptPack> subScriptPacks = new ArrayList<>();
getAllAS3PackageScriptPacks((AS3Package) item, subScriptPacks);
for (ScriptPack pack : subScriptPacks) {
if (!itemsToRemove.contains(pack)) {
itemsToRemove.add(pack);
itemsToRemoveParents.add(new Object());
itemsToRemoveSprites.add(new Object());
}
}
}
if (item instanceof AS2Package) {
List<ASMSource> subAsmSources = new ArrayList<>();
getAllAS2PackageScriptPacks((AS2Package) item, subAsmSources);
for (ASMSource asmSource : subAsmSources) {
if (!itemsToRemove.contains(asmSource)) {
tagsToRemove.add((Tag) asmSource);
}
}
}
}
List<ABC> abcsToPack = new ArrayList<>();
for (int i = 0; i < itemsToRemove.size(); i++) {
Object item = itemsToRemove.get(i);
Object parent = itemsToRemoveParents.get(i);
if (item instanceof BUTTONCONDACTION) {
DefineButton2Tag button = (DefineButton2Tag) parent;
BUTTONCONDACTION buttonCondAction = (BUTTONCONDACTION) item;
button.actions.remove(buttonCondAction);
if (buttonCondAction.isLast) {
if (!button.actions.isEmpty()) {
button.actions.get(button.actions.size() - 1).isLast = true;
}
}
button.setModified(true);
}
if (item instanceof CLIPACTIONRECORD) {
PlaceObjectTypeTag place = (PlaceObjectTypeTag) parent;
Timelined tim = (itemsToRemoveSprites.get(i) instanceof DefineSpriteTag) ? (DefineSpriteTag) itemsToRemoveSprites.get(i) : place.getSwf();
CLIPACTIONRECORD clipActionRecord = (CLIPACTIONRECORD) item;
CLIPACTIONS clipActions = place.getClipActions();
clipActions.clipActionRecords.remove(clipActionRecord);
if (clipActions.clipActionRecords.isEmpty()) {
place.setPlaceFlagHasClipActions(false);
place.setClipActions(null);
}
clipActions.calculateAllEventFlags();
place.setModified(true);
tim.resetTimeline();
}
if (item instanceof ScriptPack) {
ScriptPack sp = (ScriptPack) item;
sp.delete(sp.abc, true);
abcsToPack.add(sp.abc);
swfsToClearCache.add(sp.getSwf());
for (ABCContainerTag ct : sp.getSwf().getAbcList()) {
if (ct.getABC() == sp.abc) {
((Tag) ct).setModified(true);
break;
}
}
}
}
for (ABC abc : abcsToPack) {
abc.pack();
ABCContainerTag container = null;
for (ABCContainerTag ct : abc.getSwf().getAbcList()) {
if (ct.getABC() == abc) {
container = ct;
break;
}
}
if (abc.script_info.isEmpty()) { //all scripts in abc were removed
abc.getSwf().removeTag((Tag) container);
abc.getSwf().setModified(true);
} else {
((Tag) container).setModified(true);
}
}
for (Tag tag : tagsToRemove) {
SWF swf = tag.getSwf();
if (!tagsToRemoveBySwf.containsKey(swf)) {
tagsToRemoveBySwf.put(swf, new ArrayList<>());
}
tagsToRemoveBySwf.get(swf).add(tag);
}
for (SWF swf : tagsToRemoveBySwf.keySet()) {
swf.removeTags(tagsToRemoveBySwf.get(swf), removeDependencies);
}
for (SWF swf : swfsToClearCache) {
swf.clearAllCache();
}
mainPanel.refreshTree();
}
}
}