Modify

Opened 10 years ago

Closed 4 years ago

#2955 closed Bug (Fixed)

Using Is### breaks Maps passed ByRef

Reported by: anonymous Owned by: Jon
Milestone: 3.3.15.3 Component: AutoIt
Version: 3.3.13.19 Severity: None
Keywords: Cc:

Description

Depending on various things, some map values can be broken

Shortest working example i got:

#AutoIt3Wrapper_Version=Beta
#include <Debug.au3>

WTF() ; works, if outside of func
MsgBox(0, Default, "Yep!")

Func WTF()
	Local $MAP[]
	$MAP["mod"] = "Mod"
	$MAP["more"] = "More actions"
	$MAP["delete"] = "Delete"

	Local $sTest1 = $MAP["more"] ; after this $Map["more"] is Null
	Local $sTest2 = $MAP["more"]
	_Assert("$sTest1 == $sTest2") ; Assertion Failed
EndFunc

Attachments (0)

Change History (9)

comment:1 Changed 10 years ago by Melba23

Nothing wrong with the Map itself - the problem is in way the statement is passed to the _Assert function. I am investigating further.

M23

Edit: The problem arises because the 2 variables in the passed statement are Local to the WTF function and so are not recognised by the _Assert function. So the passed string is executed as a literal string and fails. You can see this happening in this example script:

#include <MsgBoxConstants.au3>

Global $sTest1, $sTest2 ; Comment out to see the fail <<<<<<<<<<<<<<<<<<<<<<<<<<<<<

WTF() ; works, if outside of func
MsgBox(0, Default, "Yep!")

Func WTF()
	Local $MAP[]
	$MAP["mod"] = "Mod"
	$MAP["more"] = "More actions"
	$MAP["delete"] = "Delete"

	For $vKey In MapKeys($MAP)
		ConsoleWrite($vKey & " - " & $Map[$vKey] & @CRLF)
	Next

	$sTest1 = $MAP["more"]

	For $vKey In MapKeys($MAP)
		ConsoleWrite($vKey & " - " & $Map[$vKey] & @CRLF)
	Next
	ConsoleWrite("$sTest1: " & $sTest1 & @CRLF)

	$sTest2 = $MAP["more"]

	For $vKey In MapKeys($MAP)
		ConsoleWrite($vKey & " - " & $Map[$vKey] & @CRLF)
	Next
	ConsoleWrite("$sTest2: " & $sTest2 & @CRLF)

	ConsoleWrite(@CRLF)

	_Assert_Mod("$sTest1 == $sTest2")
EndFunc

Func _Assert_Mod($sCondition, $bExit = True, $nCode = 0x7FFFFFFF, $sLine = @ScriptLineNumber, Const $iCurERR = @error, Const $iCurEXT = @extended)
	Local $bCondition = Execute($sCondition)

	ConsoleWrite($sCondition & " : " & $bCondition & " - " & Execute($sCondition) & @CRLF)

	If Not $bCondition Then
		MsgBox($MB_SYSTEMMODAL, "AutoIt Assert", "Assertion Failed (Line " & $sLine & "): " & @CRLF & @CRLF & $sCondition)
		If $bExit Then Exit $nCode
	EndIf
	Return SetError($iCurERR, $iCurEXT, $bCondition)
EndFunc   ;==>_Assert

As you can see the Map contents are unchanged, but when the passed variables are not Global in scope the _Assert function fails.

The basic problem is that Execute needs to recognise the variable names in the passed string as variables - and it seems that it only looks in the Global variable list. So a possible bug, but nothing to do with Maps per se I suggest that you open a new ticket that covers the failure of _Assert when passed Local variables.

M23

Last edited 10 years ago by Melba23 (previous) (diff)

comment:2 Changed 10 years ago by Melba23

  • Resolution set to No Bug
  • Status changed from new to closed

comment:3 Changed 10 years ago by anonymous

Um... Sorry... There is no problem with _Assert() at all. I trying to make a shorter example and lost problem in process.
Seems that this problem is related to some non-trivial code when passing maps or sub-maps to user function without and using Is<KindOf> functions AND only if you use some specific keys.

Here is a valid example (no assertion is used here):

#AutoIt3Wrapper_Version=Beta
AutoItSetOption("MustDeclareVars", 1)

Global $TEST = "more" ; works correctly if you use other sting
Global $mMap = Map()
Error($mMap)

Func Error($mTest) ; works correctly if you use ByRef
	Local $sTest1 = $mTest[$TEST]
	IsString($mTest["mod"]) ; works correctly if you comment this line
	Local $sTest2 = $mTest[$TEST]
	MsgBox(0, Default, VarGetType($sTest1) & ":" & $sTest1 & @CRLF & VarGetType($sTest2) & ":" & $sTest2)
EndFunc

Func Map()
	Local $mTest[]
	$mTest["mod"] = "Mod"
	$mTest["caption"] = "Mod list (%s)"
	$mTest["no_game_dir1"] = "no game dir - select from ""More actions"""
	$mTest["up"] = "Move up"
	$mTest["down"] = "Move down"
	$mTest["enable"] = "Enable"
	$mTest["disable"] = "Disable"
	$mTest["missing"] = "%s (missing mod)"
	$mTest["remove"] = "Remove"
	$mTest[$TEST] = "More actions"
	; works correctly if you comment remaining items
	$mTest["plugins"] = "Plugins"
	$mTest["homepage"] = "Go to webpage"
	$mTest["delete"] = "Delete"
	$mTest["delete_confirm"] = "Do you really want to delete this mod? \n%s\n\n(The mod will be moved to recycle bin, if it's possible))"
	$mTest["add_new"] = "Add new mod(s)"
	$mTest["compatibility"] = "Compatibility"
	$mTest["open_dir"] = "Open mod directory"
	Return $mTest
EndFunc

comment:4 Changed 10 years ago by Melba23

  • Resolution No Bug deleted
  • Status changed from closed to reopened
  • Summary changed from Map content is randomly broken to Using Is### breaks Maps passed ByRef

I now agree that there is a problem - but not the one you think you have found. I believe it happens when you pass a Map ByRef and check on the values. This example shows it clearly:

#AutoIt3Wrapper_Version=Beta
AutoItSetOption("MustDeclareVars", 1)

Global $TEST = "more"
Global $mMap = Map()

For $vKey In MapKeys($mMap)
	ConsoleWrite($vKey & ": " & @TAB & $mMap[$vKey] & @CRLF)
Next

ConsoleWrite(@CRLF)
_Error_ByRef($mMap)

ConsoleWrite(@CRLF)
_Error_Global()


Func _Error_ByRef($mTest)

	ConsoleWrite(@CRLF & "ByRef - before IsString" & @CRLF)
	For $vKey In MapKeys($mTest)
		ConsoleWrite($vKey & ": " & @TAB & $mTest[$vKey] & @CRLF)
	Next

	Local $sTest1 = $mTest[$TEST]
	IsString($mTest["mod"]) ; This is the problem line <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

	ConsoleWrite(@CRLF & "ByRef - after IsString" & @CRLF)
	For $vKey In MapKeys($mTest)
		ConsoleWrite($vKey & ": " & @TAB & $mTest[$vKey] & @CRLF)
	Next

	Local $sTest2 = $mTest[$TEST]
	MsgBox(0, "ByRef", VarGetType($sTest1) & ": " & $sTest1 & @CRLF & VarGetType($sTest2) & ": " & $sTest2)
EndFunc

Func _Error_Global()

	ConsoleWrite(@CRLF & "Direct - before IsString" & @CRLF)
	For $vKey In MapKeys($mMap)
		ConsoleWrite($vKey & ": " & @TAB & $mMap[$vKey] & @CRLF)
	Next

	Local $sTest1 = $mMap[$TEST]
	IsString($mMap["mod"])

	ConsoleWrite(@CRLF & "Direct - after IsString" & @CRLF)
	For $vKey In MapKeys($mMap)
		ConsoleWrite($vKey & ": " & @TAB & $mMap[$vKey] & @CRLF)
	Next

	Local $sTest2 = $mMap[$TEST]
	MsgBox(0, "Global", VarGetType($sTest1) & ": " & $sTest1 & @CRLF & VarGetType($sTest2) & ": " & $sTest2)
EndFunc

Func Map()

	Local $mTest[]
	$mTest["mod"] = "Mod"
	$mTest["caption"] = "Mod list (%s)"
	$mTest["no_game_dir1"] = "no game dir - select from ""More actions"""
	$mTest["up"] = "Move up"
	$mTest["down"] = "Move down"
	$mTest["enable"] = "Enable"
	$mTest["disable"] = "Disable"
	$mTest["missing"] = "%s (missing mod)"
	$mTest["remove"] = "Remove"
	$mTest[$TEST] = "More actions"
	; works correctly if you comment remaining items
	$mTest["plugins"] = "Plugins"
	$mTest["homepage"] = "Go to webpage"
	$mTest["delete"] = "Delete"
	$mTest["delete_confirm"] = "Do you really want to delete this mod? \n%s\n\n(The mod will be moved to recycle bin, if it's possible))"
	$mTest["add_new"] = "Add new mod(s)"
	$mTest["compatibility"] = "Compatibility"
	$mTest["open_dir"] = "Open mod directory"
	Return $mTest
EndFunc

So the bug appears to be using Is##### on a Map passed ByRef - I have amended the title.

M23

P.S. By the way, I notice the reference to "game" in your script - could I gently point you to the Forum rules:
http://www.autoitscript.com/forum/index.php?app=forums&module=extras&section=boardrules

comment:5 Changed 10 years ago by anonymous

... but not the one you think you have found...

I don't know what sort of problem it is. There is so many things should be used together to reproduce this bug (so i can make some small changes to code and it will work correctly)... but in any way Is<KindOf> should not modify its param.

... reference to "game" ...

This script don't interact with game (only can launch process) or game server in any way.
See gen_lng_validate.au3, lng_auto.au3 (this "bug" affects only "more" key) and lng\english.json for details
https://bitbucket.org/SyDr/ramm/src/0d6f035cf547b66d425f91a72dda41a189e8f25d?at=no_regrets

comment:6 Changed 10 years ago by jchd18

M23,
$mTest is not passed ByRef in the code exposed.
If one changes the function into:

Func _Error_ByRef(ByRef $mTest)

then everything works as expected.

But with your code, this:

	Local $sTest1 = $mTest[$TEST]

assigns Null to $sTest1.

comment:7 Changed 10 years ago by Melba23

jchd,

I realised that last night as I went to bed - the problem happens when the Map is passed as a parameter and a copy is made. Sorry for the confusion.

I will try and get a simple reproducer script working today and post it in "Dev Chat" - this needs more scrutiny that it is getting in Trac.

M23

comment:8 Changed 9 years ago by anonymous

Hi. Any news?

comment:9 Changed 4 years ago by Jon

  • Milestone set to 3.3.15.3
  • Owner set to Jon
  • Resolution set to Fixed
  • Status changed from reopened to closed

Fixed by revision [12297] in version: 3.3.15.3

Guidelines for posting comments:

  • You cannot re-open a ticket but you may still leave a comment if you have additional information to add.
  • In-depth discussions should take place on the forum.

For more information see the full version of the ticket guidelines here.

Add Comment

Modify Ticket

Action
as closed The owner will remain Jon.
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.