AutoHotkey v2 alpha (UPDATES)

Discuss the future of the AutoHotkey language
Posts: 7422
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos


01 Mar 2021, 05:39


Changed WinSetTransparent to treat "" as "Off" (not as 0).
Added Default parameter to RegRead.
Added validation to LV.GetNext parameter #1.

Fixed WinSetTransparent to validate new value.
Fixed 'functionname'.p to invoke String.Prototype, not Func.Prototype.
Fixed -4.5.%9999% to be evaluated as (-4.5).%9999%, not -((4.5).%9999%).
Merged v1.1.33.03 (bug fixes).

This is a re-release of v2.0-a126-6c420d26 with working hotkeys.

SHA256 hash
Posts: 7422
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos


03 Mar 2021, 05:04

Fixed exit-by-last-GUI-destruction to permit OnExit to prevent exit. (Only applies when no threads are running, such as when a child GUI's parent is destroyed/closed by an external force.)
Fixed WinSetTransColor to permit non-numeric values.
Fixed issues with hotkey variants having different #InputLevels (from v1 branch).
Merged v1.1.33.04.

SHA256 hash
Posts: 7422
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos


07 Mar 2021, 00:58

SHA256 hash

In short:
  • Variables and functions are combined.
  • Properties and methods are combined (as in v1 or prior to v2.0-a104).
  • Variable scope is resolved differently (in particular, global variables).
  • ByRef works differently.

For a little more context, see Preview of changes: scope, function and variable references. For more details, see the documentation.


Function and variable names are now placed in a shared namespace.
  • Each function definition creates a constant (read-only variable) within the current scope; therefore, scripts cannot assign to a variable with that name in the same scope.
  • Use MyFunc in place of Func("MyFunc").
  • Use MyFunc in place of "MyFunc" when passing the function to any built-in function such as SetTimer or Hotkey. Passing a name (string) is no longer supported.
  • Use myVar() in place of %myVar%() when calling a function by value.
  • To call a function when all you have is a function name (string), first use a double-deref to resolve the name to a variable and retrieve its value (the function object). %myVar%() now actually performs a double-deref and then calls the result, equivalent to f := %myVar%, f(). Avoid handling functions by name (string) where possible; use references instead.
Further details:
  • Object(), Array() and Map() now call the corresponding classes; they are no longer functions. Array and Map have the same usage as before, but Object no longer accepts parameters.
  • Func and IsFunc have been removed.
  • As built-in functions such as SetTimer no longer accept function names, passing A_ThisFunc will not work. However, %A_ThisFunc% should resolve to the Func or Closure, which would work.

Super-global variables have been removed (excluding built-in variables, which aren't quite the same as they cannot be redeclared or shadowed). In theory, removing them as an option makes the language and documentation a little simpler, and encourages code that is more robust, at the expense of a little lost convenience (possibly gained by not having to debug certain kinds of issues).

Within an assume-local function, if a given name is not used in a declaration or as the target of a non-dynamic assignment or the reference (&) operator, it may resolve to an existing global variable.

In other words:
  • Functions can now read global variables without declaring them.
  • Functions which have no global declarations cannot directly modify global variables (eliminating one source of unintended side-effects).
  • Adding a new class to the script is much less likely to affect the behaviour of any existing function, as classes are not super-global.
  • The global keyword is currently redundant when used in global scope, but can be used for clarity. Variables declared this way are now much less likely to conflict with local variables (such as when combining or #including scripts), as they are not super-global. On the other hand, some convenience is lost.
  • Declarations are generally not needed as much.
Force-local mode has been removed. It was mostly added to protect a function against unintended references to super-global variables, and would have been even more inconvenient to use than before with the need to declare every global function being called by the function.

Fat arrow functions in global scope are no longer assume-global. Due to the new rules, they can read global variables and create local variables, but not assign global variables.

Expressions in class variable initializers can now create variables local to the implicit __Init method, and can read global variables but cannot assign them.


Function calls now permit virtually any sub-expression for specifying which function to call, provided that there is no space or tab before the open-parenthesis of the parameter list. For example, MyFunc() would call the value MyFunc regardless of whether that is the function's actual name or a variable containing a function object, and (a?b:c)() would call either b or c depending on a. Note that x.y() is still a method call roughly equivalent to (x.y)(x), but a[n]() is now equivalent to (a[n])().

&var is now the "reference" operator, which is used with all ByRef and OutputVar parameters to improve clarity and flexibility (and make other language changes possible). See VarRef in the documentation index for more details.

super() is now equivalent to

Reading an unset variable now raises an error. #Warn UseUnsetLocal and #Warn UseUnsetGlobal have been removed.

Double-derefs such as %var% are no longer capable of creating new variables. This avoids some inconsistencies, in particular relating to the new scope rules. They were already becoming less useful due to a fundamental incompatibility with #Warn VarUnset, which is a very useful tool for error detection. Aside from that, new users sometimes find pseudo-arrays as the answer to a problem, when they would be better served by learning to use a basic array. This removes the inferior option.


No auto-include: Scripts are no longer automatically included from the function library (Lib) folders when a function call is present without a definition, due to increased complexity and potential for accidents (now that the MyFunc in MyFunc() can be any variable). #Include <LibName> works as before. It may be superseded by module support in a future release.

A /validate command-line switch was added to serve the secondary purpose of the /iLib tempfile switch; i.e. load the script, display any warnings and error, then exit without running the script. /iLib currently does the same thing as /validate, since there are no auto-includes to write to tempfile (Ahk2Exe and other scripts might rely on it).

A closure can now refer to itself or other closures by name (of the read-only variable implicitly created by the function definition) without creating a circular reference. Nested functions can now be used in the same outer function as a closure without necessarily becoming a closure (i.e. because they don't capture any variables or closures of the outer function).


ByRef parameters are now declared using &param instead of ByRef param, with some differences in usage.

ByRef parameters no longer implicitly take a reference to the caller's variable. Instead, the caller must explicitly pass a reference with the reference operator (&var). This allows more flexibility, such as storing references elsewhere, accepting them with a variadic function and passing them on with a variadic call.

When a parameter is marked ByRef, any attempt to explicitly pass a non-VarRef value causes an error to be thrown. Otherwise, the function can check for a reference with param is VarRef and explicitly dereference it with %param%. IsByRef has been removed.

DllCall: The output value (if any) of numeric parameters with the * or P suffix is ignored if the script passes a plain variable containing a number. To receive the output value, pass a VarRef such as &myVar or an object with a Ptr property.


Methods and properties are merged once again, so the following were removed: ObjOwnMethods, DefineMethod, DeleteMethod, HasOwnMethod, OwnMethods.

Methods of classes (both built-in and user-defined) are defined as simple value properties.

Static New is renamed to Call, so use MyClass() to instantiate classes. However, an implication of the way methods work is that MyClass.NestedClass() will pass MyClass as this, which ends up being the first parameter of __New. (MyClass.NestedClass)() and MyClass.NestedClass.Call() will work as MyClass.NestedClass.New() did before.

Property descriptors accepted by DefineProp and returned by GetOwnPropDesc have an additional property Call, which specifies a function object to be called when the property is called. If not defined for a call such as x.y(), the y property's getter is called to retrieve a function object, which is then called.

The RegExMatch object's type (class) name is now RegExMatchInfo, since RegExMatch is a function and does not match the usage of a constructor.

Unrelated Bugfix

Fixed hotstrings with potential OTB to interpret R/T correctly.
  • Fixed ::RT::{ not interpreted as OTB due to R or T in hotstring.
  • Fixed :R0 T:x::{ interpreted as OTB due to R0 eclipsing T.
  • Cleaned up and optimized.
Posts: 7422
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos


11 Mar 2021, 04:52

Fixed MyFunc[] to fail when __Item is undefined, not call the function.
Fixed closures in anonymous hotkey functions.
Merged v1.1.33.05.

SHA256 hash
Posts: 7422
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos


03 Apr 2021, 21:26

Changes in behaviour

Changed dynamic properties with a Call function to return the function itself by default when the property is read.
Changed method definitions in classes (and built-in methods) to create dynamic properties with a Call function.
  • Methods cannot be assigned over by default.
  • Methods can coexist with property getters/setters.
Changed WinActivate to throw TargetError if the window is not found.
Changed Array.Prototype.Delete to throw if index is out of range.
Changed local/global to allow redeclaring an existing class/function. (Declaring a class/function global was already permitted up until commit a153948c.)
Changed global to allow redeclaring built-in variables.
Changed DllCall to permit its first parameter to be an object with .Ptr.
Changed __Enum behaviour for Array, Map, Gui and RegExMatchInfo.
  • Mode of enumeration (which variables are assigned which values) now depends on the first parameter of __Enum, not the passed variables.
  • This makes it possible for a for-loop to specify a single variable but control which value it gets by placing a comma to either side. Previously Array and RegExMatchInfo always returned the value, regardless of whether the single variable was first or second.
  • This also changes Gui to return the control object in mode 1 (like Array and RegExMatchInfo), instead of the HWND. Note that mode 1 is also used by Array(enumerable*) and other variadic calls.
Changed the script's main window to keep the script running (persistent) while visible. For instance, a script containing only InstallKeybdHook(), KeyHistory() will not exit until the window is closed.
Changed custom items in A_TrayMenu to not make the script persistent, for flexibility.
Changed OnMessage to not make the script persistent, for flexibility.
Changed OnMessage functions to be able to interrupt the current thread under conditions that previously caused the message to be discarded, such as while a menu is being displayed.

Replaced directives with more flexible alternatives

Replaced #Persistent with Persistent(Persist := true).
Replaced #InstallKeybdHook with InstallKeybdHook(Install := true, Force := false).
Replaced #InstallMouseHook with InstallMouseHook(Install := true, Force := false).
Replaced #HotkeyInterval, #MaxHotkeysPerInterval, #HotkeyModifierTimeout and #MenuMaskKey with corresponding variables: A_HotkeyInterval, A_MaxHotkeysPerInterval, A_HotkeyModifierTimeout and A_MenuMaskKey.
Replaced #KeyHistory N with KeyHistory N (added the N parameter).

Added stuff

Added Number(n).
Added options S (SuspendExempt) and S0 (S zero, not exempt) for the Hotkey and Hotstring functions and the #Hotstring directive.

Fixed bugs

Fixed OnExit/OnClipboardChange/OnError reference count error on failure.
Fixed ComObject to use the AutoHotkey behaviour for undefined properties/methods, instead of unconditionally throwing a COM error. This improves compatibility with function object validation (e.g. when MinParams is not defined).
Fixed &var altering var's capacity in some cases.
Fixed bugs with DllCall/ComCall HRESULT return type. When the result is failure and TRY is not in use, the thread should exit. Instead:
  • An error value was returned, but the documentation says this is never done.
  • Execution was continued regardless of error dialog choice or OnError result.
Fixed DllCall("X" Y) erroneously resolving function X at load time.
Fixed x.y(z) to not pass z to the getter of x.y when it takes parameters.
Fixed crash when Gui enumerator is called without the first var.
Fixed &var allocating memory which is never deleted.
Fixed Trim() not trimming the input when it is pure integer/float.
Fixed detection of conflicts between a function and an already-declared var.
Fixed DllCall to throw the correct error when a parameter is missing.
Fixed IsSet(&%ClassOrFuncName%).

Optimized string return values for some functions (although benchmarks show negligible improvement).
  • SubStr and Trim to not directly require copying (but it may still be required after return, by the evaluator).
  • EditGetLine to not require redundant calculation of the string's length.

SHA256 hash
Posts: 7422
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos


10 Apr 2021, 06:14

New Catch Syntax (and related)

Changed catch syntax to allow type filtering: catch Class1, Class2 as var (with multiple catch statements permitted).
Changed catch without parameters to catch only instances of Error.
Changed try without catch/finally to only suppress instances of Error.
Changed throw within catch to re-throw the exception being handled (instead of a default error).

See the documentation for details: Try, Catch, Throw, etc.

When updating scripts, note that to retain existing behaviour exactly, it is necessary to replace catch var with catch Any as var, and catch with catch Any. However, usually one would be expecting only to catch errors, so catch as var or catch is probably sufficient. Also note that creating custom errors that do not derive from Error is not advisable, unless they are specifically intended to not be caught by catch as var or catch.

New uses for Else

Else can now be used with Loop, For, While and Catch. For loops, it is executed if the loop had zero iterations. For Catch, it is executed if no exception is thrown within Try (and is not executed if any error or value is thrown, even if there is no Catch matching the value's class). Consequently, the interpretation of Else may differ from previous versions when used without braces. For example:

Code: Select all

if condition
    while condition
        statement to execute for each iteration
} ; These braces are now required, otherwise else associates with while
    statement to execute if condition is false
See the documentation for details: Else, Loop, For, etc.

Changes for COM objects

COM object wrappers have been reorganized to (minimally) integrate them into the type hierarchy.

See v2-changes or the documentation for details.

In particular, note:
  • ComObject replaces ComObjCreate; e.g. obj := ComObject(CLSID) constructs a new COM object, and obj is ComObject is true.
  • ComValue(vt, value) replaces that usage of ComObject().
  • ComObjFromPtr(pdsp) replaces that usage of ComObject().
  • ComValue (and derived types ComObject, ComObjArray and ComValueRef) now derive from Any, so value is Any is no longer false for COM object wrappers, and should be true for all values. Thus, catch Any catches any thrown value.

Other Changes

Changed compiled scripts to set ErrorObj.Stack (to "") rather than leaving it undefined.
Changed (...: to be continuation, since it's no longer a valid label.
Changed continuation with .x to not include a space (but . x still does).
Changed OSError(N) to take a Win32 error code instead of a message, generate a message based on it, and store N in ErrorObj.Number.
Changed class property definitions to not permit empty [], to reduce confusion due to this.Property[] being mostly analogous to this.Property.__Item, not this.Property.

Removed Exception(); use Error() instead.

Removed the unintended ability to call a string (function name) without %%.


Fixed some script formatting errors in ListLines/error dialogs.
Fixed non-persistent script to (maybe) exit when main window is hidden.
Fixed class x extends y to ensure y is a Class, not a Func.
Fixed instance var initializers being added to an inherited __Init method (if defined first).
Fixed obj.unknownProp error offering to continue but exiting anyway.
Fixed finally to allow return within a nested function or ()=>fat-arrow.
Fixed global fat-arrow function definitions to not be assume-global.
Fixed SubStr(args*) when args.Length = 3 && !args.Has(3).
Fixed for leaking VarRef references.
Fixed Number/Integer/Float/String not validating minimum parameter count.

Removed redundant handling of WM_SIZE for hiding the main window on minimize.
Cleaned up code relating to execution of loops.

Merged v1.1.33.06 (fixes joystick hotkeys, etc.)

SHA256 hash
Posts: 7422
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos


19 Apr 2021, 04:44


Revised RegExMatchInfo syntax.
  • Removed Value (use []).
  • Added Pos, Len, Name, Count and Mark properties, because: 1) more convenient, 2) avoids unexpected behaviour of m.Pos (etc.) returning a function.
  • Removed Count and Mark methods.
  • Set Name MinParams to 1, so m.Name throws instead of returning "" (in case there is a subpattern with this name).
  • Changed __Get to throw a more detailed error when given an unknown name.
  • Changed __Get to throw when given [parameters].
Note: As before, m.__Item[n] defaults to n=0, therefore m[] returns the overall matched value.

Changed HasMethod and GetMethod to verify the method is callable.
  • Omit param2 to validate param1 itself as a function.
  • Pass param3 the desired parameter count, for validation.
  • Omit param3 to only check if the method has a Call method.
Changed IsSet(var) to check var itself and added IsSetRef(ref). See IsSet for details.

Changed classes to static-initialize on first access, or when the class definition is reached during execution. They were previously initialized before any other global code is executed, strictly in the order of definition. See Class Initialization for details.

Changed calls to nested classes to omit the outer class from the parameter list. For instance, a new class with no __New can be instantiated with a.nested.class() as in v2.0-a127 and earlier, instead of requiring (a.nested.class)() or

To support the above changes, changed nested classes to create a property getter and method instead of storing the class directly as a value property.

Added "as" and "unset" as reserved words.


Added Map.Prototype.Get(Key, Default).
Added optional Default property for Map to return when key is not found.


Fixed ObjGetBase, HasBase and Type treating an omitted parameter as an empty string when called variadically.
Fixed Function[...] being erroneously validated/optimized as if it was Function(...).
Fixed %ref% to throw if the VarRef is unset.
Fixed function calls not being validated on the right hand side of any short-circuit operator.
Fixed the main window appearing in a minimized state if the taskbar is active when the program starts.
Fixed Exit/throw/errors in __Init not causing the thread to exit.
Fixed VarUnset warnings being shown for closure variables.
Fixed static/class var declarations to behave more like instance vars. Specifically:
  • Do not automatically shadow any property setter or __Set.
  • If accessed before initialization, inherit property from base or throw an exception; do not return an empty string.

SHA256 hash
Posts: 7422
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos


24 Apr 2021, 21:02

Removed BufferAlloc() and added constructor for Buffer().

Changed ComValue, ComValueRef and ComObjArray to dispatch via prototype properties, allowing the script to inspect or extend them.
Changed ComObjArray enumerator to be more consistent with Array.
Changed FileInstall (uncompiled) to do nothing when source = dest.

Fixed spurious load-time errors for obj.%expression% (get/set).
Fixed Gui DropFiles event crashing when using an event sink object.
Fixed resolution of nested classes for extends/catch.
Fixed HasProp/HasMethod/GetMethod for ComValue, ComValueRef, ComObjArray and VarRef (but ComObject is still unsupported).
Fixed auto-concat with IsSet() on the right hand side.

SHA256 hash
Posts: 7422
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos


07 May 2021, 23:24

Variadic function calls previously had half-baked support for named parameters. This has been disabled, to remove a possible impediment to the proper implementation of named parameters.

Changed the first call to GuiObj.Show() to shift focus to the Default button if the initial focus lands on a non-default button.
Changed continuation section parsing to treat ( in the options like ), so for example, (( begins an expression, not a continuation section.
Changed continuation sections to report invalid options.
Changed HotIf to default to the criterion currently being evaluated.

Removed the check for AU3_Spy.exe from the Window Spy menu option.
Removed special handling of the .ini file type by Edit().

Improved ComValue() and ComValueRef.Prototype.__Item type conversions.
  • ComValue() accepts appropriate values for R8, R4, Cy, Date, rather than taking the exact binary value of a passed 64-bit integer.
  • ComValue() accepts strings and objects.
  • ComValue(VT_BOOL, b) evaluates b according to AutoHotkey convention.
  • VT_BOOL now converts to 0/1 instead of 0/-1.
  • VT_ERROR now converts to a ComValue wrapper rather than an integer.
  • I1, I8, UI1, UI2, UI4 or UI8 now converts to an integer rather than a string.
Fixed %obj% to throw a TypeError, not "This dynamic variable is blank".
Fixed extending Gui control classes.
Fixed undefined behaviour when StrGet/StrPut address is 0..65535.
Fixed 1 - "" and similar type mismatch errors to display the unexpected non-numeric value, not necessarily the left-hand value.
Fixed deletion of the default menu item leaving a dangling pointer.
Fixed Exit to always exit the thread properly, even if non-persistent.

Merged v1.1.33.09.

SHA256 hash

Return to “AutoHotkey v2 Development”

Who is online

Users browsing this forum: No registered users and 1 guest