“Moving from AppleScript to Javascript for Automation”
Short answer:
I wouldn’t, if I were you. JXA is crippled, buggy, unsupported, and long dead. Tasks that work perfectly in AS may break in JXA and when they do there’s not a thing you can do. If you are able to remain on AppleScript (which is a not good language but at least works right and has a community of users happy to help when you’re stuck), that will be the least painful option for you by far.
…
Long, very boring, technical answer:
I’m pretty certain this is the problem command (your syntax is correct, FWIW):
vo.commander.performCommand('item chooser');
If that doesn’t work, it doesn’t work. And it wouldn’t surprise me if it didn’t: the Mac Automation engineers who wrote JXA had a surprisingly poor understanding of how AppleScript and the “AppleScriptable” apps it talks to actually speak Apple events. (Apple events are the OS-level messaging system that AppleScript uses to talk to Mac apps.)
Here is your original AppleScript, which I’ve tidied to better show its structure:
tell application "VoiceOver"
tell commander
perform command "item chooser"
end tell
end tell
I will assume you have already tested this AppleScript and it works correctly, as expected, on your machine.†
The issue here, I wager, is that VO’s perform command
command requires both a tell
target and a string as a direct parameter. This is an unusual combination, but it is valid.
Normally when an application command is wrapped in a tell
block, it takes the tell
block’s target as its direct parameter when packing that command into an Apple event. However, this command already has a string as its direct parameter, so AppleScript instead packs that target object in a different area of the Apple event: its “subject” attribute (keySubjectAttr
). And since AppleScript is the de facto standard as to how Apple events are spoken, the receiving app—in this case VoiceOver—knows to retrieve the command’s target object from that attribute.
What’s likely happening here‡ is the JXA engineers failed to implement this particular detail of Apple event/AppleScript behavior in JXA’s Apple event bridge: thus JXA can accept either a target object or a direct parameter, but not both. If your command needs both, you’re SOOL: JXA simply doesn’t support it.
If you really must use JavaScript, you can always install Node.js and try using nodeautomation:
#!/usr/bin/env node
const na = require('nodeautomation');
const vo = na.app('VoiceOver');
vo.commander.performCommand({_: 'item chooser'});
I don’t use/understand VO so I’ve not tested this code myself, but it is the direct translation of your original AppleScript. Note that nodeautomation’s syntax is slightly different to JXA’s, and also it is a bit rough and occasionally buggy. (If you do try it and it fails, let me know as it’s probably a bug I should fix.)
nodeautomation’s design is based on appscript (I wrote both, btw), and appscript achieved >99.9% compatibility with “AppleScriptable” apps by 2007, proving it can be done (though it did take several years and a lot of real-world testing and use by hundreds of users to get to that level).
However, I no longer provide (free) support for appscript, etc, which is why I recommend sticking with AppleScript if you can. While the AE/OSA/AS platform is the walking dead nowadays, out of all its ambulatory corpses AS is the least unsafe bet by a mile.
HTH
† I get an error -1708 when I run it; I suspect this is because I don’t have an “item chooser” available—whatever that is—and VO is being somewhat misleading on error codes. (-1708 means a command is not recognized, whereas VO obviously understands the perform command
command but was unable to carry it out for some other reason.)
‡ I won’t bother running further tests to confirm this guess as there’s nothing we can do about it anyway: after JXA failed, Apple eliminated the entire Mac Automation department in 2016 and dumped the whole platform into minimal maintenance mode where it rots. But I am the world expert in this stuff so my guesses usually are.