AutoHotkey v3.0-alpha.1 - Switching to JavaScript (not really)

Community news and information about new or upcoming versions of AutoHotkey
lexikos
Posts: 7412
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: AutoHotkey v3.0-alpha.1 - Switching to JavaScript

Post by lexikos » 02 Apr 2021, 06:37

Rest assured/sorry to disappoint, I have no intention of abandoning the language I've spent the last 10 years developing.

This is more than just an elaborate prank:
  • It is meant to show that AutoHotkey is AutoHotkey, regardless of the language; that the ease with which it can be used to get things done is primarily due to its library of functions, not its unique language.
  • It is a test of the current state of AutoHotkey v2, its flexibility and capabilities.
  • It is for sounding out some ideas for the future of AutoHotkey (post v2.0).
There is truth to everything I wrote, except the topic title... maybe even the topic title (only time will tell). ;)

I fully intend to bring the development of v2 alpha to an end within a few months, by releasing a beta. Anyone who has looked at v2-thoughts recently might have noticed there's not much there that hasn't been deferred. I do have another list of items to look into or change (which has grown while working on this project), but they are small things that I'll either implement soon or defer until a later release. If I don't set a deadline, there will always be more things added to the list before I finish the last "important" item.

Did you know v2.0-a001 was released on April 2, 2011? :happybday:

Being familiar with several languages before I found AutoHotkey, and having an interest in languages in general, it's always seemed inevitable to me that AutoHotkey would be brought to other languages. I haven't done it myself because my interest lies more with developing the language than actually using it to get things done. It seemed to me that "porting" all of the functions would be tedious work, but not difficult. It still puzzles me that several users have asked for it, but no one (to my knowledge) has attempted it (not counting scripts like this one).

In 2016, I hit a wall of sorts; I wasn't happy with the state of the language, but didn't know what to do about it. I thought about porting to other languages, but the last thing I wanted was to burn out (more) by working on something tedious. So I created a project to experiment with binding to different languages and frameworks, without the tedious work of actually porting the existing functions. It would take a declaration like nil MouseGetPos(out int X, out int Y) and generate "glue" code to bind a C++ function into a COM library (usable from JScript and VBScript), a .NET assembly, Python and Lua, with language-appropriate syntax. I put it aside once I got it to a basic functioning state, for whatever reason; probably because all of the interesting parts were already done, and by that time I had decided to make The Big Changes and move forward with v2.

That project isn't dead, just on hold. Post-v2.0, I plan to clean up the code and separate most of AutoHotkey's functionality from its script engine, with a view to binding the functionality to other languages, opening up other possibilities for the script engine, and making the code more maintainable, among other reasons. However, although v2.0-beta.1 might not be far away, there is still a lot of work to be done to catch up on code maintenance (I have a long TODO list) and polish things up for a proper v2.0.0 release.



This Script

The original concept for this script came from @Aurelain's Exo. I started rewriting it for AutoHotkey v2 and JsRT in 2015, but I didn't get very far. Some parts of v2 still weren't flexible enough for first-class integration, like Hotkey If requiring an #if already present in the script. This iteration of the script was written over the last few weeks.

The basic premise is incredibly simple:

Code: Select all

jscode := '
(
    hotkey('#+n', function() { run('notepad') }); // No fat arrows in this version of JScript.
    hotkey('#n', openNotepad);

    function openNotepad() {
        if (winExist('ahk_exe notepad.exe'))
            winActivate();
        else
            run('notepad.exe');
    }
)'
js := ComObjCreate("ScriptControl"), js.Language := "JScript"  ; Requires 32-bit !
for f in [Hotkey, Run, WinExist, WinActivate]
    js.AddObject(RegExReplace(f.name, '^\w', '$L0'), f)
js.Eval(jscode)
Although being familiar with the limitations of ScriptControl, I started by updating JsRT.ahk to work with v2.0-a128 (and then I modified it extensively).

This works on the surface, but there are a number of problems:
  • When an error is thrown by AutoHotkey back to JavaScript back to AutoHotkey, the type of the error is lost and there's nothing indicating which part of the JavaScript code was executing. Fortunately, JsRT provides some simple functions for putting the engine into an "exception state", checking whether it's in that state, and retrieving whatever value was thrown by the script. I use this to translate AutoHotkey errors to JavaScript errors, and throw JavaScript errors back to OnError, which shows an error dialog.
  • I solve a number of problems by wrapping all functions which are "exported" to JavaScript, and translating parameters and the return value as needed:
    • In JavaScript, omitting a parameter is the same as passing undefined, but undefined passes through the IDispatch interface as VT_EMPTY, which AutoHotkey translates to "". Passing "" isn't always the same as omitting the parameter.
    • true translates to -1 (VARIANT_TRUE), which produces counter-intuitive results for some functions.
    • AutoHotkey returns integers for boolean values, where one would expect proper boolean values in JavaScript.
    • When a callback function is passed from JavaScript to AutoHotkey through the built-in COM support, it gets a new ComObject wrapper each time. This means that functions which use the callback as an identifier won't work as expected; e.g. calling setTimer twice would register two timers, or fail to delete the timer if period is 0.
    • Objects returned by AutoHotkey functions don't behave like JavaScript objects.
    • Objects passed to AutoHotkey functions are required to have properties that don't follow JavaScript conventions, like Ptr, Size and Hwnd.
    • A couple of functions currently require an actual AutoHotkey Array, and won't work with anything else.
    • Some functions require the use of ByRef for output, which currently requires a native AutoHotkey VarRef. Even if a function to create one (i.e. _ => &_) is provided, output parameters are not the JavaScript way.
  • Functions which take string parameters don't use JavaScript semantics for converting the value to a string. (I haven't fixed this yet because it would probably require marking which parameters require such conversion, or new language features which are tentatively planned for the distant future.)
Working on the script revealed a few issues with AutoHotkey (some of which I was conscious of, but hadn't considered the simple solutions):
  • Various bugs and several minor inconsistencies which will be fixed by v2.0-a130.
  • No way to conditionally put directives such as #Persistent, #InstallKeybdHook and #InstallMouseHook into effect at runtime; i.e. one must rely on the side-effects of other functions. I realized that simply replacing these with functions increases flexibility and requires hardly any change to scripts.
  • No way to use OnMessage without making the script persistent. I worked around it by using window subclassing, but this has some obvious and some hidden drawbacks.
  • No way to customize the tray menu without making the script persistent. (The tray menu is customized to restore the standard items which are normally omitted by compiled scripts.) I worked around it by avoiding A_TrayMenu and instead showing some other menu in its place. However, replicating the standard behaviour was unexpectedly complicated, especially because the window subclassing caused issues with Pause.
  • Some directives cannot be replicated at runtime, and/or control settings which can't be retrieved by the script. In some cases this simplifies the code (e.g. sizing the key history buffer at load time avoids issues of thread safety), but in some other cases a script function or variable would work just as well or better.
When I initially made changes to persistence and removed #Persistent, I was probably thinking it could be completely automatic and not require anything explicit from the script. The new rules are evaluated when the last thread exits, or one of the conditions change (such as a GUI being closed). It turned out there were still undetected cases where an author wanted the script to become persistent, so I restored #Persistent. Unfortunately, there are also cases where automatically making the script persistent is not what the author wants. At the time, I probably only considered the cases where one obviously wants the script to continue running, such as the OnMessage WM_COPYDATA example, or a script which doesn't do anything until activated by the tray menu.

In v2.0-a130, OnMessage and custom tray menu items will not make the script persistent; instead, the script will have to call Persistent() if needed. I figure this increases flexibility without sacrificing much convenience. (Follow the links for detailed comments.)

Another issue I was already aware of is that unless you Suspend all hotkeys, creating hotkeys with the Hotkey function is relatively inefficient:
Creating hotkeys via the double-colon syntax performs better than using the Hotkey function because the hotkeys can all be enabled as a batch when the script starts (rather than one by one). Therefore, it is best to use this function to create only those hotkeys whose key names are not known until after the script has started running.
A possible solution would be to not enable hotkeys until some time (relatively short, maybe 100ms) has passed or the auto-execute thread completes. I think this generally wouldn't be noticeable.



Now on GitHub:
AutoHotkey-jk

User avatar
boiler
Posts: 8044
Joined: 21 Dec 2014, 02:44

Re: AutoHotkey v3.0-alpha.1 - Switching to JavaScript

Post by boiler » 02 Apr 2021, 06:47

lexikos wrote:
02 Apr 2021, 06:37
Did you know v2.0-a001 was released on April 2, 2011? :happybday:
Image

(jk)

Glad to hear you’ll be driving the train for some time to come. :thumbup:

User avatar
SKAN
Posts: 949
Joined: 29 Sep 2013, 16:58

Re: AutoHotkey v3.0-alpha.1 - Switching to JavaScript

Post by SKAN » 02 Apr 2021, 07:13

boiler wrote:
02 Apr 2021, 06:47
Glad to hear you’ll be driving the train for some time to come. :thumbup:
+1 :thumbup:

User avatar
joedf
Posts: 7966
Joined: 29 Sep 2013, 17:08
Facebook: J0EDF
Google: +joedf
GitHub: joedf
Location: Canada
Contact:

Re: AutoHotkey v3.0-alpha.1 - Switching to JavaScript (not really)

Post by joedf » 02 Apr 2021, 07:37

Again, I have to say... I am always in awe of your work Lexikos! :bravo:


SOTE
Posts: 1230
Joined: 15 Jun 2015, 06:21

Re: AutoHotkey v3.0-alpha.1 - Switching to JavaScript (not really)

Post by SOTE » 02 Apr 2021, 13:22

I was reluctant to post, thinking it was an April fool's prank too. AutoHotkey and JavaScript is a great team, so a closer relationship could be vastly beneficial in ways unforeseen.

OpalMonkey
Posts: 6
Joined: 23 Jan 2014, 03:02

Re: AutoHotkey v3.0-alpha.1 - Switching to JavaScript (not really)

Post by OpalMonkey » 02 Apr 2021, 16:04

lexikos wrote:
02 Apr 2021, 06:37
This is more than just an elaborate prank [...] There is truth to everything I wrote, except the topic title... maybe even the topic title (only time will tell). ;)
Well played, lexikos! That's kind of what I started to expect after thinking it through yesterday. The best pranks/lies/deceptions are the ones that warp the truth just enough to work.

IMO, this is the right way to do April Fools'. Use it to announce something meaningful in a way that messes with everyone for a bit.

boiler wrote:
02 Apr 2021, 06:47
Glad to hear you’ll be driving the train for some time to come. :thumbup:
joedf wrote:
02 Apr 2021, 07:37
Again, I have to say... I am always in awe of your work Lexikos! :bravo:
+1 to both!

User avatar
TheArkive
Posts: 530
Joined: 05 Aug 2016, 08:06
GitHub: TheArkive

Re: AutoHotkey v3.0-alpha.1 - Switching to JavaScript (not really)

Post by TheArkive » 03 Apr 2021, 01:40

This is cool! I'm looking forward to seeing this stuff in action :D

lexikos
Posts: 7412
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: AutoHotkey v3.0-alpha.1 - Switching to JavaScript (not really)

Post by lexikos » 03 Apr 2021, 21:39

v2.0-a130 replaces some directives with functions/variables to increase flexibility. The latest commit to AutoHotkey-jk utilizes these changes if you run or compile it with v2.0-a130.

(I might keep updating the script, but I don't plan to update the download in this topic.)

tuzi
Posts: 106
Joined: 27 Apr 2016, 23:40

Re: AutoHotkey v3.0-alpha.1 - Switching to JavaScript (not really)

Post by tuzi » 09 Apr 2021, 22:29

You really fooled me.
Frankly, it was sad to see the language I've used and loved for 10+ years to give up.
But now it's nice to see that you and many others are still here. :D
Thanks to all of you.

Post Reply

Return to “Announcements”