From afa7d44f83d1c63a7290001d182dd350a349b7df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sat, 13 Dec 2025 17:04:35 +0100 Subject: [PATCH] Fixed: #2585 AS1/2 direct editation - continue and break in for..in loop --- CHANGELOG.md | 2 + .../action/model/clauses/ForInActionItem.java | 39 +--------- .../parser/script/ActionSourceGenerator.java | 73 +++++++++++++++++++ 3 files changed, 76 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc8a96173..a46e83842 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ All notable changes to this project will be documented in this file. - [#2566] Export bounds of sprites and buttons not containg filter offsets - [#2582] Font normalizer setting small texts when no assigned glyph found - PDF export - not rendering video stream frames +- [#2585] AS1/2 direct editation - continue and break in for..in loop ### Changed - [#2575] dumpSWF CLI command only allows single SWF dump (no imports, etc.) @@ -4068,6 +4069,7 @@ Major version of SWF to XML export changed to 2. [#2573]: https://www.free-decompiler.com/flash/issues/2573 [#2566]: https://www.free-decompiler.com/flash/issues/2566 [#2582]: https://www.free-decompiler.com/flash/issues/2582 +[#2585]: https://www.free-decompiler.com/flash/issues/2585 [#2556]: https://www.free-decompiler.com/flash/issues/2556 [#2536]: https://www.free-decompiler.com/flash/issues/2536 [#2537]: https://www.free-decompiler.com/flash/issues/2537 diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/ForInActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/ForInActionItem.java index ee0d51e61..738b8ce3b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/ForInActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/ForInActionItem.java @@ -198,44 +198,7 @@ public class ForInActionItem extends LoopActionItem implements Block { @Override public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { - List ret = new ArrayList<>(); - ActionSourceGenerator asGenerator = (ActionSourceGenerator) generator; - String charset = asGenerator.getCharset(); - HashMap registerVars = asGenerator.getRegisterVars(localData); - ret.addAll(enumVariable.toSource(localData, generator)); - ret.add(new ActionEnumerate2()); - - List loopExpr = new ArrayList<>(); - int exprReg = asGenerator.getTempRegister(localData); - - loopExpr.add(new ActionStoreRegister(exprReg, charset)); - loopExpr.add(new ActionPush(Null.INSTANCE, charset)); - loopExpr.add(new ActionEquals2()); - ActionIf forInEndIf = new ActionIf(0, charset); - loopExpr.add(forInEndIf); - List loopBody = new ArrayList<>(); - - //assuming (variableName instanceof VariableActionItem) - VariableActionItem vaact = (VariableActionItem) variableName; - GraphTargetItem setVar = vaact.getBoxedValue(); - setVar.value = new DirectValueActionItem(new RegisterNumber(exprReg)); - - loopBody.addAll(asGenerator.toActionList(setVar.toSourceIgnoreReturnValue(localData, generator))); - //loopBody.add(new ActionPush(new RegisterNumber(exprReg))); - int oldForIn = asGenerator.getForInLevel(localData); - asGenerator.setForInLevel(localData, oldForIn + 1); - loopBody.addAll(asGenerator.toActionList(asGenerator.generate(localData, commands))); - asGenerator.setForInLevel(localData, oldForIn); - ActionJump forinJmpBack = new ActionJump(0, charset); - loopBody.add(forinJmpBack); - int bodyLen = Action.actionsToBytes(loopBody, false, SWF.DEFAULT_VERSION).length; - int exprLen = Action.actionsToBytes(loopExpr, false, SWF.DEFAULT_VERSION).length; - forinJmpBack.setJumpOffset(-bodyLen - exprLen); - forInEndIf.setJumpOffset(bodyLen); - ret.addAll(loopExpr); - ret.addAll(loopBody); - asGenerator.releaseTempRegister(localData, exprReg); - return ret; + return ((ActionSourceGenerator) generator).generate(localData, this); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionSourceGenerator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionSourceGenerator.java index 4facbaf00..26bb0565f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionSourceGenerator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionSourceGenerator.java @@ -23,6 +23,7 @@ import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; import com.jpexs.decompiler.flash.action.model.FunctionActionItem; import com.jpexs.decompiler.flash.action.model.GetMemberActionItem; import com.jpexs.decompiler.flash.action.model.GetVariableActionItem; +import com.jpexs.decompiler.flash.action.model.clauses.ForInActionItem; import com.jpexs.decompiler.flash.action.swf4.ActionGetVariable; import com.jpexs.decompiler.flash.action.swf4.ActionIf; import com.jpexs.decompiler.flash.action.swf4.ActionJump; @@ -36,12 +37,14 @@ import com.jpexs.decompiler.flash.action.swf5.ActionCallFunction; import com.jpexs.decompiler.flash.action.swf5.ActionCallMethod; import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; +import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; import com.jpexs.decompiler.flash.action.swf5.ActionGetMember; import com.jpexs.decompiler.flash.action.swf5.ActionNewObject; import com.jpexs.decompiler.flash.action.swf5.ActionPushDuplicate; import com.jpexs.decompiler.flash.action.swf5.ActionSetMember; import com.jpexs.decompiler.flash.action.swf5.ActionStackSwap; import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; +import com.jpexs.decompiler.flash.action.swf6.ActionEnumerate2; import com.jpexs.decompiler.flash.action.swf6.ActionStrictEquals; import com.jpexs.decompiler.flash.action.swf7.ActionExtends; import com.jpexs.decompiler.flash.action.swf7.ActionImplementsOp; @@ -962,6 +965,76 @@ public class ActionSourceGenerator implements SourceGenerator { return ret; } + public List generate(SourceGeneratorLocalData localData, ForInActionItem item) throws CompilationException { + List ret = new ArrayList<>(); + String charset = getCharset(); + HashMap registerVars = getRegisterVars(localData); + ret.addAll(item.enumVariable.toSource(localData, this)); + ret.add(new ActionEnumerate2()); + + List loopExpr = new ArrayList<>(); + int exprReg = getTempRegister(localData); + + loopExpr.add(new ActionStoreRegister(exprReg, charset)); + loopExpr.add(new ActionPush(Null.INSTANCE, charset)); + loopExpr.add(new ActionEquals2()); + ActionIf forInEndIf = new ActionIf(0, charset); + loopExpr.add(forInEndIf); + List loopBody = new ArrayList<>(); + + //assuming (variableName instanceof VariableActionItem) + VariableActionItem vaact = (VariableActionItem) item.variableName; + GraphTargetItem setVar = vaact.getBoxedValue(); + setVar.value = new DirectValueActionItem(new RegisterNumber(exprReg)); + + loopBody.addAll(toActionList(setVar.toSourceIgnoreReturnValue(localData, this))); + //loopBody.add(new ActionPush(new RegisterNumber(exprReg))); + int oldForIn = getForInLevel(localData); + setForInLevel(localData, oldForIn + 1); + loopBody.addAll(toActionList(generate(localData, item.commands))); + setForInLevel(localData, oldForIn); + ActionJump forinJmpBack = new ActionJump(0, charset); + loopBody.add(forinJmpBack); + + boolean hasBreak = false; + for (Action a : loopBody) { + if (a instanceof ActionJump) { + ActionJump aJump = (ActionJump) a; + if (aJump.isBreak) { + hasBreak = true; + break; + } + } + } + + List loopPop = new ArrayList<>(); + int popLen = 0; + if (hasBreak) { + loopPop.add(new ActionPush(Null.INSTANCE, charset)); + loopPop.add(new ActionEquals2()); + loopPop.add(new ActionNot()); + ActionIf forInIfPop = new ActionIf(0, charset); + loopPop.add(forInIfPop); + + popLen = Action.actionsToBytes(loopPop, false, SWF.DEFAULT_VERSION).length; + forInIfPop.setJumpOffset(-popLen); + } + + + int bodyLen = Action.actionsToBytes(loopBody, false, SWF.DEFAULT_VERSION).length; + int exprLen = Action.actionsToBytes(loopExpr, false, SWF.DEFAULT_VERSION).length; + forinJmpBack.setJumpOffset(-bodyLen - exprLen); + forInEndIf.setJumpOffset(bodyLen + popLen); + int forinJmpBackLen = forinJmpBack.getTotalActionLength(); + int forInEndIfLen = forInEndIf.getTotalActionLength(); + ret.addAll(loopExpr); + ret.addAll(loopBody); + ret.addAll(loopPop); + fixLoop(loopBody, bodyLen, -exprLen, item); + releaseTempRegister(localData, exprReg); + return ret; + } + @Override public List generate(SourceGeneratorLocalData localData, ForItem item) throws CompilationException { List ret = new ArrayList<>();