Modify

Opened 10 years ago

Closed 5 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

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 10 years ago by anonymous

Hi. Any news?

comment:9 Changed 5 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

Author


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

 
Note: See TracTickets for help on using tickets.