AutoHotkey_3.0-alpha.1\AutoHotkey32.exe:
Code: Select all
; <COMPILER: v1.1.33.05>
JKVersion := '3.0-alpha.1'
#Requires AutoHotkey v2.0-a128+
functions_use_lowercase_initial_letter := true
allow_wildcard_in_include := false
default_script_name := RegExReplace(A_ScriptName, '\.[^\.]*$', '.j?')
class JsRT
{
static Call()
{
throw Error("This class is abstract. Use JsRT.IE() or JSRT.Edge() to initialize.", -1)
}
static IE()
{
if !this._hmod := DllCall("LoadLibrary", "str", "jscript9", "ptr")
throw Error("Failed to load jscript9.dll", -1)
if DllCall("jscript9\JsCreateRuntime", "int", 0, "int", -1, "ptr", 0, "ptr*", &runtime:=0) != 0
throw Error("Failed to initialize JsRT", -1)
DllCall("jscript9\JsCreateContext", "ptr", runtime, "ptr", 0, "ptr*", &context:=0)
return this._Initialize("jscript9", runtime, context)
}
static Edge()
{
if !this._hmod := DllCall("LoadLibrary", "str", "chakra", "ptr")
throw Error("Failed to load chakra.dll", -1)
if DllCall("chakra\JsCreateRuntime", "int", 0, "ptr", 0, "ptr*", &runtime:=0) != 0
throw Error("Failed to initialize JsRT", -1)
DllCall("chakra\JsCreateContext", "ptr", runtime, "ptr*", &context:=0)
return this._Initialize("chakra", runtime, context)
}
static _Initialize(dll, runtime, context)
{
this._dll := dll
this._runtime := runtime
this._context := context
this._ImportAPI()
DllCall(dll "\JsSetCurrentContext", "ptr", context)
this._sources := Map()
this._sources.CaseSense := 'Off'
this._sources['eval'] := 0
return this._dsp := this.FromJs(this.JsGetGlobalObject())
}
static _ImportAPI()
{
API := '
(
JsAddRef(ptr ref, uint* return count)
JsBooleanToBool(ptr valref, char* return bool)
JsCallFunction(ptr function, ptr arguments, ushort argumentCount, ptr* return valref)
JsCollectGarbage(ptr runtime)
JsCreateError(ptr message, ptr* return valref)
JsCreateExternalObject(ptr data, ptr finalizeCallback, ptr* return valref)
JsCreateFunction(ptr nativeGetCb, ptr callbackState, ptr* return valref)
JsCreateTypeError(ptr message, ptr* return valref)
JsGetAndClearException(ptr* return valref)
JsGetArrayBufferStorage(ptr arrayBuffer, ptr* buf, int* byteCount)
JsGetDataViewStorage(ptr dataView, ptr* buf, int* byteCount)
JsGetExternalData(ptr object, ptr* return)
JsGetGlobalObject(ptr* return valref)
JsGetOwnPropertyNames(ptr object, ptr* return valref)
JsGetOwnPropertySymbols(ptr object, ptr* return valref)
JsGetProperty(ptr object, ptr propertyId, ptr* return valref)
JsGetPropertyIdFromName(str name, ptr* return propId)
JsGetPrototype(ptr object, ptr* return valref)
JsGetTypedArrayStorage(ptr typedArray, ptr* buf, int* byteCount, int* arrayType, int* elemSize)
JsGetUndefinedValue(ptr* return undefined)
JsGetValueType(ptr value, int* return)
JsHasException(char* return bool)
JsHasExternalData(ptr object, char* return bool)
JsIdle(uint* return nextIdleTick)
JsInstanceOf(ptr object, ptr constructor, char* return bool)
JsParseScript(wstr script, ptr sourceContext, wstr sourceUrl, ptr* return valref)
JsPointerToString(ptr stringValue, uptr stringLength, ptr* return valref)
JsProjectWinRTNamespace(wstr namespace)
JsRelease(ptr ref, uint* return count)
JsRunScript(wstr script, ptr sourceContext, wstr sourceUrl, ptr* return valref)
JsSetException(ptr exception)
JsSetExternalData(ptr object, ptr data)
JsSetObjectBeforeCollectCallback(ptr ref, ptr callbackState, ptr callback)
JsSetProperty(ptr object, ptr propertyId, ptr value, char useStrictRules)
JsSetPrototype(ptr object, ptr proto)
JsValueToVariant(ptr valref, ptr variant)
JsVariantToValue(ptr variant, ptr* return valref)
)'
static kernel32 := DllCall("GetModuleHandle", "str", "kernel32", "ptr")
static GPA := DllCall.Bind(DllCall("GetProcAddress", "ptr", kernel32, "astr", "GetProcAddress", "ptr"), "ptr", , "astr", , "ptr")
Loop Parse API, '`n'
{
if !RegExMatch(A_LoopField, "^(\w+)\((.*)\)$", &m)
{
MsgBox "DEBUG: Fatal error in JsRT API declarations, line " A_Index
ExitApp
}
funcname := m.1
argtypes := RegExReplace(m.2, '(?<=^|,) *(\w+(?: *\*|[Pp](?= ))?) *+([\w ]*?) *(?=,|$)', '$1,$2')
argtypes := StrSplit(argtypes, ',', ' ')
if !(pfn := GPA(this._hmod, funcname))
throw Error('Failed to load JsRT function "' funcname '" from DLL "' this._dll '"')
api := {ptr: pfn, name: funcname}
if argtypes.Length && argtypes[-1] ~= '^return\b'
api.return := argtypes.Length
Loop argtypes.Length // 2
argtypes.Delete A_Index * 2
this.%funcname% := (api.HasProp('return') ? CallApiRet : CallApi)
.Bind( , api, argtypes*)
}
CallApi(thisJsRT, api, args*)
{
if errorCode := DllCall(api.ptr, args*)
this._ThrowApiError api.name, errorCode
}
CallApiRet(thisJsRT, api, args*)
{
args[api.return] := &(retval := 0)
if errorCode := DllCall(api.ptr, args*)
this._ThrowApiError api.name, errorCode
return retval
}
}
static _ThrowApiError(apiName, errorCode)
{
if errorCode = 0x30001 || errorCode = 0x30002
throw this.FromJs(this.JsGetAndClearException())
throw (this.Error)(Format("Call to {1} failed with error 0x{2:x}", apiName, errorCode), -1, errorCode)
}
static __Delete()
{
this._dsp := ""
if dll := this._dll
{
DllCall(dll "\JsSetCurrentContext", "ptr", 0)
DllCall(dll "\JsDisposeRuntime", "ptr", this._runtime)
}
DllCall("FreeLibrary", "ptr", this._hmod)
}
static FromJs(valref)
{
ref := ComObject(0x400C, (var := BufferAlloc(24, 0)).ptr)
this.JsValueToVariant(valref, var)
return (val := ref[], ref[] := 0, val)
}
static ToJs(val)
{
ref := ComObject(0x400C, (var := BufferAlloc(24, 0)).ptr)
ref[] := val
valref := this.JsVariantToValue(var)
ref[] := 0
return valref
}
static SourceContext(filename)
{
if !this._sources.has(filename)
this._sources[filename] := this._sources.Count
return this._sources[filename]
}
static RunFile(filename, readOpt:="")
{
this.JsRunScript(FileRead(filename, readOpt), this.SourceContext(filename), filename)
}
static Eval(code)
{
return this.FromJs(this.JsRunScript(code, 0, "eval"))
}
class Error extends Error
{
}
}
GetCommandLineArgs() {
if !ptr := DllCall("shell32\CommandLineToArgvW", "ptr", DllCall("GetCommandLineW", "ptr"), "int*", &nargs:=0, "ptr")
throw MemoryError()
try {
args := []
loop nargs
args.Push StrGet(NumGet(ptr, (A_Index-1)*A_PtrSize, "ptr"), "UTF-16")
return args
}
finally DllCall("LocalFree", "ptr", ptr)
}
#NoTrayIcon
#SingleInstance Off
OnError ErrorMsg
A_AllowMainWindow := true
PatchMenus
ParseCommandLine
ParseCommandLine() {
global default_script_encoding := "UTF-8"
global J_Args := GetCommandLineArgs()
global is_restart := false
global ErrorStdOut := false
drop_jk_ahk := !A_IsCompiled
J_Args.RemoveAt 1
while J_Args.Length {
if J_Args[1] ~= 'i)^/r(?:estart)$'
is_restart := true
else if J_Args[1] ~= 'i)^/cp\d+$'
default_script_encoding := SubStr(J_Args[1], 2)
else if J_Args[1] ~= 'i)^/ErrorStdOut(?:=|$)'
ErrorStdOut := FileOpen('**', 'w', SubStr(J_Args[1], 14))
else if J_Args[1] ~= 'i)^/Debug(?:=|$)' && drop_jk_ahk
{}
else if drop_jk_ahk && J_Args[1] ~= 'i)(?:[\\/]|^)\Q' A_ScriptName '\E$'
drop_jk_ahk := false
else
break
J_Args.RemoveAt 1
}
if !J_Args.Length {
for prefix in ['', A_MyDocuments '\'] {
Loop Files prefix default_script_name {
jkfile := A_LoopFileFullPath
break 2
}
}
if !IsSet(&jkfile) {
jkfile := FileSelect("1", default_script_name, "Select Script File", "Script Files (*.jk;*.js)")
if jkfile = ""
ExitApp
}
}
else if !(J_Args[1] ~= '[*?<>"]') {
Loop Files J_Args.RemoveAt(1)
jkfile := A_LoopFileFullPath
}
if !IsSet(&jkfile) {
MsgBox "Script file not found.",, "IconX"
ExitApp
}
global J_ScriptFullPath := jkfile
}
WinSetTitle jktitle := J_ScriptFullPath ' - AutoHotkey v' JKVersion, A_ScriptHwnd
if is_restart
TerminatePreviousInstance 'Reload'
SplitPath J_ScriptFullPath, &J_ScriptName, &J_ScriptDir
A_IconTip := A_ScriptName := J_ScriptName
SetWorkingDir J_ScriptDir
undefined := ComObject(0,0), null := ComObject(9,0)
jsTrue := ComObject(0xB, -1), jsFalse := ComObject(0xB, 0)
AdjustFuncName := functions_use_lowercase_initial_letter
? n => RegExReplace(n, '^[A-Z]+', '$l0') : n => n
AdjustPropName := AdjustFuncName
AdjustMethodName := AdjustFuncName
AdjustClassName := n => n
js := JsRT.Edge()
MIN_SAFE_INTEGER := js.Number.MIN_SAFE_INTEGER
MAX_SAFE_INTEGER := js.Number.MAX_SAFE_INTEGER
AddAhkObjects js
IsSet(&D) ? js.D := WrapBif(D) : %'D'% := _ => ""
loading_script := true
StartupIconTimer true
JsRT.RunFile J_ScriptFullPath, default_script_encoding
ErrorStdOut := false
loading_script := false
StartupIconTimer
AddAhkObjects(scope) {
defProp := scope.Object.defineProperty
Hotkey := _Hotkey
Boolean(r) => r ? jsTrue : jsFalse
functions := "
(Join`s
!Abs !ACos !ASin !ATan BlockInput !BufferAlloc CallbackCreate CallbackFree
CaretGetPos !Ceil !Chr Click ClipWait ComCall ComObjActive ComObjArray
ComObjConnect ComObjCreate ComObject ComObjFlags ComObjGet ComObjQuery
ComObjType ComObjValue ControlAddItem ControlChooseIndex ControlChooseString
ControlClick ControlDeleteItem ControlFindItem ControlFocus ControlGetChecked
ControlGetChoice ControlGetClassNN ControlGetEnabled ControlGetExStyle
ControlGetFocus ControlGetHwnd ControlGetIndex ControlGetItems ControlGetPos
ControlGetStyle ControlGetText ControlGetVisible ControlHide ControlHideDropDown
ControlMove ControlSend ControlSendText ControlSetChecked ControlSetEnabled
ControlSetExStyle ControlSetStyle ControlSetText ControlShow ControlShowDropDown
CoordMode !Cos !Critical !DateAdd !DateDiff DetectHiddenText DetectHiddenWindows
DirCopy DirCreate DirDelete DirExist DirMove DirSelect DllCall Download
DriveEject DriveGetCapacity DriveGetFilesystem DriveGetLabel DriveGetList
DriveGetSerial DriveGetSpaceFree DriveGetStatus DriveGetStatusCD DriveGetType
DriveLock DriveSetLabel DriveUnlock Edit EditGetCurrentCol EditGetCurrentLine
EditGetLine EditGetLineCount EditGetSelectedText EditPaste EnvGet EnvSet
!Exception !Exit ExitApp !Exp FileAppend FileCopy FileCreateShortcut FileDelete
FileEncoding FileExist FileGetAttrib FileGetShortcut FileGetSize FileGetTime
FileGetVersion FileInstall FileMove FileOpen FileRead FileRecycle
FileRecycleEmpty FileSelect FileSetAttrib FileSetTime !Floor Format FormatTime
GetKeyName GetKeySC GetKeyState GetKeyVK !GetMethod GroupActivate GroupAdd
GroupClose GroupDeactivate GuiCtrlFromHwnd GuiFromHwnd !HasBase !HasMethod !HasProp
HotIf HotIfWinActive HotIfWinExist HotIfWinNotActive HotIfWinNotExist Hotkey
Hotstring IL_Add IL_Create IL_Destroy ImageSearch IniDelete IniRead IniWrite
InputBox !InStr !IsAlnum !IsAlpha !IsDigit !IsFloat !IsInteger !IsLabel !IsLower
!IsNumber !IsObject !IsSet !IsSpace !IsTime !IsUpper !IsXDigit KeyHistory KeyWait
ListHotkeys !ListLines !ListVars ListViewGetContent !Ln LoadPicture !Log !LTrim !Max
MenuFromHandle MenuSelect !Min !Mod MonitorGet MonitorGetCount MonitorGetName
MonitorGetPrimary MonitorGetWorkArea MouseClick MouseClickDrag MouseGetPos
MouseMove MsgBox NumGet NumPut !ObjAddRef !ObjBindMethod !ObjFromPtr
!ObjFromPtrAddRef !ObjGetBase !ObjGetCapacity !ObjHasOwnProp !ObjOwnPropCount
!ObjOwnProps !ObjPtr !ObjPtrAddRef !ObjRelease !ObjSetBase !ObjSetCapacity
OnClipboardChange OnError OnExit OnMessage !Ord OutputDebug Pause PixelGetColor
PixelSearch PostMessage ProcessClose ProcessExist ProcessSetPriority ProcessWait
ProcessWaitClose Random RandomSeed RegDelete RegDeleteKey !RegExMatch
!RegExReplace RegRead RegWrite Reload !Round !RTrim Run RunAs RunWait Send
SendEvent SendInput SendLevel SendMessage SendMode SendPlay SendText
SetCapslockState SetControlDelay SetDefaultMouseSpeed SetKeyDelay SetMouseDelay
SetNumlockState SetRegView SetScrollLockState SetStoreCapsLockMode SetTimer
SetTitleMatchMode SetWinDelay SetWorkingDir Shutdown !Sin Sleep !Sort SoundBeep
SoundGetInterface SoundGetMute SoundGetName SoundGetVolume SoundPlay
SoundSetMute SoundSetVolume SplitPath !Sqrt StatusBarGetText StatusBarWait
!StrCompare StrGet !StrLen !StrLower !StrPtr StrPut !StrReplace !StrSplit !StrUpper
!SubStr Suspend SysGet SysGetIPAddresses !Tan Thread ToolTip TraySetIcon TrayTip
!Trim !Type !VarSetStrCapacity WinActivate WinActivateBottom WinActive WinClose
WinExist WinGetClass WinGetClientPos WinGetControls WinGetControlsHwnd
WinGetCount WinGetExStyle WinGetID WinGetIDLast WinGetList WinGetMinMax
WinGetPID WinGetPos WinGetProcessName WinGetProcessPath WinGetStyle WinGetText
WinGetTitle WinGetTransColor WinGetTransparent WinHide WinKill WinMaximize
WinMinimize WinMinimizeAll WinMinimizeAllUndo WinMove WinMoveBottom WinMoveTop
WinRedraw WinRestore WinSetAlwaysOnTop WinSetEnabled WinSetExStyle WinSetRegion
WinSetStyle WinSetTitle WinSetTransColor WinSetTransparent WinShow WinWait
WinWaitActive WinWaitClose WinWaitNotActive
)"
CaretGetPos.output := ['x', 'y']
ControlGetPos.output := ['x', 'y', 'width', 'height']
FileGetShortcut.output := [, 'target', 'dir', 'args', 'description', 'icon', 'iconNum', 'runState']
ImageSearch.output := ['x', 'y']
LoadPicture.output := [, , 'imageType']
MonitorGet.output := MonitorGetWorkArea.output := [, 'left', 'top', 'right', 'bottom']
MouseGetPos.output := ['x', 'y', 'win', 'control']
PixelSearch.output := ['x', 'y']
Run.output := RunWait.output := [, , , 'pid']
SplitPath.output := [, 'name', 'dir', 'ext', 'nameNoExt', 'drive']
WinGetClientPos.output := WinGetPos.output := ['x', 'y', 'width', 'height']
Gui.Prototype.GetPos.output
:= Gui.Prototype.GetClientPos.output
:= Gui.Control.Prototype.GetPos.output := [, 'x', 'y', 'width', 'height']
CaretGetPos.returns := (r, o) => (r ? o : jsFalse)
ImageSearch.returns := (r, o) => (r ? o : jsFalse)
LoadPicture.returns := (r, o) => (o.handle := r, o)
PixelSearch.returns := (r, o) => (r ? o : jsFalse)
Run.returns := (r, o) => o.pid
RunWait.returns := (r, o) => (o.exitCode := r, o)
ControlGetChecked.returns := Boolean
ControlGetEnabled.returns := Boolean
ControlGetVisible.returns := Boolean
KeyWait.returns := Boolean
SoundGetMute.returns := Boolean
StatusBarWait.returns := Boolean
WinWait.returns := Boolean
WinWaitActive.returns := Boolean
WinWaitClose.returns := Boolean
WinWaitNotActive.returns := Boolean
Loop Parse functions, ' ' {
if A_LoopField ~= '\W'
continue
fn_name := A_LoopField
fn := %fn_name%
fn_name := AdjustFuncName(fn_name)
scope.%fn_name% := WrapBif(fn)
}
AddHotkeySettings(scope)
Gui.Prototype.Control := Gui.Prototype.GetOwnPropDesc('__Item').get
for cls in [ClipboardAll, File, Gui, InputHook, Menu, MenuBar]
scope.%cls.Prototype.__class% := WrapClass(cls)
for cls in [MemoryError, OSError, TargetError, TimeoutError]
scope.%cls.Prototype.__class% := WrapErrorClass(cls)
GetLineFile := js.Function('return /\((.+?:.+?):(\d+):\d+\)/.exec(Error().stack)[1];')
GetLineNumber := js.Function('return parseInt(/\((.+?:.+?):(\d+):\d+\)/.exec(Error().stack)[2]);')
readable := {prototype: {}}
readwriteable := {base: readable, prototype: {base: readable.prototype}}
variables := define_vars()
define_vars() {
r := {base: readable.prototype}
rw := {base: readwriteable.prototype}
return {
AhkPath: A_ScriptFullPath,
AhkVersion: JKVersion,
AllowMainWindow: r,
AppData: r,
AppDataCommon: r,
Clipboard: rw,
ComputerName: r,
ComSpec: r,
ControlDelay: rw,
CoordModeCaret: rw,
CoordModeMenu: rw,
CoordModeMouse: rw,
CoordModePixel: rw,
CoordModeToolTip: rw,
Cursor: r,
DD: r,
DDD: r,
DDDD: r,
DefaultMouseSpeed: rw,
Desktop: r,
DesktopCommon: r,
DetectHiddenText: rw,
DetectHiddenWindows: rw,
EndChar: r,
EventInfo: rw,
FileEncoding: rw,
Hour: r,
IconFile: r,
IconHidden: {get: GetIconHidden, set: SetIconHidden},
IconNumber: r,
IconTip: rw,
InitialWorkingDir: A_InitialWorkingDir,
Is64bitOS: ComObject(0xB, -A_Is64bitOS),
IsAdmin: ComObject(0xB, -A_IsAdmin),
IsCompiled: ComObject(0xB, 0),
IsPaused: {get: () => ComObject(0xB, -A_IsPaused)},
IsSuspended: {get: () => ComObject(0xB, -A_IsSuspended)},
KeyDelay: rw,
KeyDelayPlay: rw,
KeyDuration: rw,
KeyDurationPlay: rw,
Language: r,
LastError: rw,
LineFile: {get: GetLineFile},
LineNumber: {get: GetLineNumber},
ListLines: rw,
MDay: r,
Min: r,
MM: r,
MMM: r,
MMMM: r,
Mon: r,
MouseDelay: rw,
MouseDelayPlay: rw,
MSec: r,
MyDocuments: r,
Now: r,
NowUTC: r,
OSVersion: A_OSVersion,
PriorHotkey: r,
PriorKey: r,
ProgramFiles: r,
Programs: r,
ProgramsCommon: r,
PtrSize: A_PtrSize,
RegView: rw,
ScreenDPI: r,
ScreenHeight: r,
ScreenWidth: r,
ScriptDir: J_ScriptDir,
ScriptFullPath: J_ScriptFullPath,
ScriptHwnd: A_ScriptHwnd,
ScriptName: rw,
Sec: r,
SendLevel: rw,
SendMode: rw,
StartMenu: r,
StartMenuCommon: r,
Startup: r,
StartupCommon: r,
StoreCapsLockMode: rw,
Temp: r,
ThisHotkey: r,
TickCount: r,
TimeIdle: r,
TimeIdleKeyboard: r,
TimeIdleMouse: r,
TimeIdlePhysical: r,
TimeSincePriorHotkey: r,
TimeSinceThisHotkey: r,
TitleMatchMode: rw,
TitleMatchModeSpeed: rw,
TrayMenu: r,
UserName: r,
WDay: r,
WinDelay: rw,
WinDir: r,
WorkingDir: rw,
YDay: r,
Year: r,
YWeek: r,
YYYY: r,
}
}
defProp scope, 'A_Args', {value: js.Array(J_Args*), writable: true}
variables.Clipboard := {
get: () => A_Clipboard,
set: (value) => A_Clipboard := IsObject(value) ? ObjectFromJs(JsRT.ToJs(value)) : value
}
variables.TrayMenu := JsRT.FromJs(ObjectToJs(J_TrayMenu))
defProp variables.TrayMenu, AdjustMethodName('Show'), {value: WrapBif(TrayMenu_Show_Fix)}
get_var(name) => %name%
set_var(name, value) => %name% := value
for name, value in variables.OwnProps() {
defProp scope, 'A_' name, value is readable ? {
get: get_var.Bind('A_' name),
set: value is readwriteable ? set_var.Bind('A_' name) : undefined
} : value is Object ? value : {value: value}
}
Persistent(n:=true) {
global Persistent
static isPersistent
if IsSet(&Persistent) && Persistent is Func
wasPersistent := Persistent(n)
else {
wasPersistent := isPersistent
OnMessage(0xBADC0DE, (*) => "", isPersistent := n)
}
return wasPersistent ? jsTrue : jsFalse
}
for fn in [Include, InstallKeybdHook, InstallMouseHook, Persistent, SingleInstance]
scope.%AdjustFuncName(fn.Name)% := WrapBif(fn)
scope.%AdjustFuncName('LoopFiles')% := WrapBif(_LoopFiles)
scope.%AdjustFuncName('LoopReg')% := WrapBif(_LoopReg)
scope.%AdjustFuncName('CollectGarbage')% := WrapBif(JsRT.JsCollectGarbage.Bind(JsRT, JsRT._runtime))
}
WrapBif(fn) {
op_return := fn.DeleteProp('returns')
if op_array := fn.DeleteProp('output') {
op := Map()
loop op_array.length
if op_array.Has(A_Index)
op[A_Index] := op_array[A_Index]
op.in_count := fn.MaxParams - op.count
fn := BifCallReturnOutputVars.Bind(fn, op, op_return)
}
else if op_return {
fn := ((r, fn, p*) => r(fn(p*))).Bind(op_return, fn)
}
static callbackFromJS := CallbackCreate(CallFromJS, "F")
static callbackBeforeCollect := CallbackCreate((rfn, pfn) => ObjRelease(pfn), "F")
rfn := JsRT.JsCreateFunction(callbackFromJS, pfn := ObjPtrAddRef(fn))
JsRT.JsSetObjectBeforeCollectCallback(rfn, pfn, callbackBeforeCollect)
return JsRT.FromJs(rfn)
}
CallFromJS(callee, isCtor, argv, argc, state) {
argc &= 0xffff, isCtor &= 0xff
try {
fn := ObjFromPtrAddRef(state)
if isCtor
throw TypeError(fn.Name ' is not a constructor')
if JsRT.JsGetValueType(NumGet(argv, "ptr")) = 0
argv += A_PtrSize, argc -= 1
args := ArrayFromArgv(argv, argc)
if HasProp(fn, 'belongsTo') && not HasBase(args[1], fn.belongsTo)
throw TypeError("'this' is not a " fn.belongsTo.__Class)
return ToJs(fn(args*))
} catch e {
JsRT.JsSetException ErrorToJs(e)
return 0
}
}
CallClassFromJS(callee, isCtor, argv, argc, state) {
argc &= 0xffff, isCtor &= 0xff
try {
this := NumGet(argv, "ptr"), cls := ObjFromPtrAddRef(state)
if !isCtor
throw TypeError(cls.Prototype.__Class ' cannot be called without the new keyword')
if !JsRT.JsInstanceOf(this, callee)
throw TypeError("'this' is not a " cls.Prototype.__Class)
return ObjectToJs(cls(ArrayFromArgv(argv + A_PtrSize, argc - 1)*))
} catch e {
if e is ValueError && cls.Call = Object.Call
e := TypeError(cls.Prototype.__Class " cannot be instantiated directly")
JsRT.JsSetException ErrorToJs(e)
return 0
}
}
CallIntoJS(callee, args) {
return JsRT.FromJs(JsRT.JsCallFunction(callee, ArrayToArgv(args), args.Length))
}
ArrayToArgv(args) {
b := BufferAlloc(args.Length * A_PtrSize, 0)
for arg in args {
if IsSet(&arg)
NumPut 'ptr', ToJs(arg), b, (A_Index-1)*A_PtrSize
else
NumPut 'ptr', JsRT.JsGetUndefinedValue(), b, (A_Index-1)*A_PtrSize
}
return b
}
WrapClass(acls) {
if ObjHasOwnProp(acls, '__js')
return acls.__js
static callbackFromJS := CallbackCreate(CallClassFromJS, "F")
jcls := JsRT.FromJs(rjcls := JsRT.JsCreateFunction(callbackFromJS, ObjPtrAddRef(acls)))
acls .__js := jcls
acls.Prototype.__js := jcls.prototype
WrapMethods acls , jcls
WrapMethods acls.Prototype, jcls.prototype
if acls.base != Object {
JsRT.JsSetPrototype(rjcls, JsRT.ToJs(jb := WrapClass(acls.base)))
JsRT.JsSetPrototype(JsRT.ToJs(jcls.prototype), JsRT.ToJs(jb.prototype))
}
static setTag := js.Function('obj', 'tag', 'obj[Symbol.toStringTag] = tag')
setTag jcls.prototype, acls.Prototype.__Class
return jcls
}
WrapErrorClass(acls) {
jcls := JsRT.Eval(Format('{ class {1} extends Error {}; {1}.prototype.name = "{1}"; {1} }', acls.Prototype.__class))
acls.Prototype.__js := jcls.prototype
return jcls
}
WrapMethods(aobj, jobj) {
defProp := js.Object.defineProperty
for p in aobj.OwnProps() {
if SubStr(p, 1, 2) = '__' {
if p = '__Enum'
SetIterator jobj, aobj.%p%
continue
}
pd := aobj.GetOwnPropDesc(p)
for name, value in pd.OwnProps()
if value is Func
value.belongsTo := aobj
if pd.HasProp('value') {
if pd.value is Func {
pd.value := WrapBif(pd.value)
p := AdjustMethodName(p)
}
else if pd.value is Class {
pd.value := WrapClass(pd.value)
p := AdjustClassName(p)
}
else
continue
}
else if pd.HasProp('call') {
pd := {value: WrapBif(pd.call)}
p := AdjustMethodName(p)
}
else {
if pd.HasProp('get')
pd.get := WrapBif(pd.get)
if pd.HasProp('set')
pd.set := WrapBif(pd.set)
p := AdjustPropName(p)
}
pd.enumerable := true
defProp jobj, p, pd
}
}
SetIterator(jobj, f) {
static setIt := js.Function('v', 'f', 'v[Symbol.iterator] = f')
get_iterator(f, this) {
next(f, this) {
o := js.Object()
if (o.done := f(&v) ? jsFalse : jsTrue) = jsFalse
o.value := v
return o
}
proto := js.Object()
proto.next := WrapBif(next.Bind(f(this, 1)))
return proto
}
setIt jobj, WrapBif(get_iterator.Bind(f))
}
ArrayFromArgv(argv, argc) {
loop (args := []).Length := argc {
v := NumGet(argv + (A_Index-1)*A_PtrSize, "ptr")
switch JsRT.JsGetValueType(v) {
case 0:
continue
case 1:
throw TypeError("Invalid use of null")
case 4:
v := JsRT.JsBooleanToBool(v)
case 5:
v := ObjectFromJs(v)
case 6:
v := JsFunctionProxy(v)
case 8:
v := [ValuesOf(JsRT.FromJs(v))*]
case 10:
v := JsArrayBufferProxy(v)
case 11:
v := JsTypedArrayProxy(v)
case 12:
v := JsDataViewProxy(v)
default:
v := JsRT.FromJs(v)
}
args[A_Index] := v
}
return args
}
ObjectToJs(v) {
if ObjHasOwnProp(v, '__rj')
return v.__rj
if ObjHasOwnProp(b := ObjGetBase(v), '__js') {
static finalizer := CallbackCreate(p => ObjFromPtr(p).DeleteProp('__rj'), 'F', 1)
rj := JsRT.JsCreateExternalObject(ObjPtrAddRef(v), finalizer)
JsRT.JsSetPrototype(rj, JsRT.ToJs(b.__js))
return v.__rj := rj
}
if b = Object.prototype {
jv := js.Object()
for pn, pv in ObjOwnProps(v)
jv.%pn% := pv
return JsRT.ToJs(jv)
}
D 'no conversion for ' type(v)
return JsRT.ToJs(v)
}
ToJs(v) {
if v is Object
return ObjectToJs(v)
if v is Integer && (v < MIN_SAFE_INTEGER || v > MAX_SAFE_INTEGER)
v := String(v)
return JsRT.ToJs(v)
}
ErrorToJs(e) {
if not e is Error
return JsRT.ToJs(e)
if e is TypeError
return JsRT.ToJS(js.TypeError(StrReplace(e.message, "a ComO", "an o")))
if e is MemberError && RegExMatch(e.message, 'named "(.*?)"', &m)
return JsRT.ToJS(js.TypeError("Object doesn't support property or method '" m.1 "'"))
je := js.Error(e.message)
je.extra := e.Extra
if (b := ObjGetBase(e)).HasProp('__js')
je.__proto__ := b.__js
return JsRT.ToJs(je)
}
ObjectFromJs(rj) {
if JsRT.JsHasExternalData(rj)
return ObjFromPtrAddRef(JsRT.JsGetExternalData(rj))
return JsRT.FromJs(rj)
}
ExternalProperty(rv, name, ptr:=unset) {
id := JsRT.JsGetPropertyIdFromName(name)
rx := JsRT.JsGetProperty(rv, id)
if JsRT.JsGetValueType(rx) = 0 {
if !IsSet(&ptr) || !ptr
return 0
rx := JsRT.JsCreateExternalObject(ptr, 0)
JsRT.JsSetProperty(rv, id, rx, true)
}
else if IsSet(&ptr)
JsRT.JsSetExternalData(rx, ptr)
else
ptr := JsRT.JsGetExternalData(rx)
return ptr
}
class JsCachingProxy {
static Call(rj) {
if p := ExternalProperty(rj, '__p')
return ObjFromPtrAddRef(p)
return super(rj)
}
__New(rj) {
this.__rj := rj
JsRT.JsAddRef(rj)
ExternalProperty(rj, '__p', ObjPtr(this))
}
__Delete() {
if err := JsRT.JsHasException()
err := JsRT.JsGetAndClearException(), JsRT.JsAddRef(err)
ExternalProperty(this.__rj, '__p', 0)
JsRT.JsRelease(this.__rj)
if err
JsRT.JsSetException(err), JsRT.JsRelease(err)
}
}
class JsFunctionProxy extends JsCachingProxy {
Call(params*) {
static missing := (_ => (_.Length := 1, _))([])
params.InsertAt(1, missing*)
return CallIntoJS(this.__rj, params)
}
MinParams => 0
MaxParams => 0
IsVariadic => true
}
class JsBufferProxy {
__new(rj) => JsRT.JsAddRef(this.__rj := rj)
__delete() => JsRT.JsRelease(this.__rj)
Ptr => (this._GetStorage(&ptr), ptr)
Size => (this._GetStorage(, &size), size)
}
class JsArrayBufferProxy extends JsBufferProxy {
_GetStorage(&ptr:=unset, &length:=unset) {
JsRT.JsGetArrayBufferStorage(this.__rj, &ptr:=0, &length:=0)
}
}
class JsTypedArrayProxy extends JsBufferProxy {
_GetStorage(&ptr:=unset, &length:=unset) {
JsRT.JsGetTypedArrayStorage(this.__rj, &ptr:=0, &length:=0, 0, 0)
}
}
class JsDataViewProxy extends JsBufferProxy {
_GetStorage(&ptr:=unset, &length:=unset) {
JsRT.JsGetDataViewStorage(this.__rj, &ptr:=0, &length:=0)
}
}
BifCallReturnOutputVars(ahkfn, op, opr, p*) {
MakeRef(s:='') => &s
if p.length < op.in_count
p.length := op.in_count
for i in op
p.InsertAt i, MakeRef()
r := ahkfn(p*)
o := js.Object()
for i, name in op
o.%name% := %p[i]%
return opr ? opr(r, o) : o
}
ValuesOf(v) {
static getIt := js.Function('v', 'return v[Symbol.iterator]()')
it := getIt(v)
return (&a) => (s := it.next()).done ? false : (a := s.value, true)
}
ErrorMsg(err, mode) {
if ComObjType(err) {
try {
if err.name = "SyntaxError" {
if ErrorStdOut
ErrorStdOut.WriteLine(Format("{1} ({2:i}) : ==> {3}`n Specifically: {4}"
, err.url, err.line, err.message, err.source))
else
MsgBox Format("Syntax error: {1}`n`nFile:`t{2}`nLine:`t{3:i}`nCol:`t{4:i}`nSource:`t{5}"
, err.message = "Syntax error" ? "" : err.message
, err.url, err.line, err.column, err.source),, "IconX"
if loading_script
ExitApp 2
} else {
MsgBox err.stack,, "IconX"
}
return true
}
}
try {
stack := "", specifically := ""
try (!A_IsCompiled) && stack := '`n`n' RegExReplace(err.stack, 'm)^.*?\\(?=[^\\]* \(\d+\) :)', '')
try (err.extra != "") && specifically := "`n`nSpecifically: " err.extra
MsgBox err.message specifically stack,, "IconX"
} catch {
try {
try value := err.toString()
catch
try value := String(err)
catch
value := err
}
MsgBox "Value thrown and not caught.`n`nSpecifically: " value,, "IconX"
}
return true
}
PatchMenus() {
hmenu := DllCall("GetMenu", "ptr", A_ScriptHwnd)
DllCall("RemoveMenu", "ptr", hmenu, "uint", 65406, "uint", 0)
DllCall("RemoveMenu", "ptr", hmenu, "uint", 65407, "uint", 0)
A_TrayMenu.Delete
global J_TrayMenu := Menu()
global Menu_AddStandard := Menu.Prototype.AddStandard
Menu.Prototype.DefineProp 'AddStandard', {Call: Menu_AddStandard_Fix}
Menu_AddStandard_Fix J_TrayMenu
MsgCommand(wParam, lParam, nmsg, hwnd) {
switch wParam & 0xFFFF {
case 65406: (A_IsCompiled) || ListLines()
case 65407: (A_IsCompiled) || ListVars()
case 65400, 65303: Reload
case 65401, 65304: Edit
case 65403, 65306: Pause -1
case 65300:
WinShow A_ScriptHwnd
WinActivate A_ScriptHwnd
default: return
}
return 0
}
MsgNotifyIcon(wParam, lParam, nmsg, hwnd) {
activate_default_tray_item() {
global J_TrayMenu
if -1 != default_id := DllCall("GetMenuDefaultItem", "ptr", J_TrayMenu.handle, "uint", false, "uint", 1)
PostMessage(0x111, default_id,, A_ScriptHwnd)
}
switch lParam {
case 0x205:
TrayMenu_Show_Fix J_TrayMenu, true
case 0x201:
if J_TrayMenu.ClickCount = 1
activate_default_tray_item
case 0x203:
activate_default_tray_item
}
return 0
}
static newproc := CallbackCreate(WindowProc, "", 4)
static oldproc := DllCall((A_PtrSize=8 ? "SetWindowLongPtrW" : "SetWindowLongW"), "ptr", A_ScriptHwnd, "int", -4, "ptr", newproc, "ptr")
WindowProc(hwnd, nmsg, wParam, lParam) {
if (nmsg = 0x111 && (wParam & 0xFFFF) >= 65300) {
if "" != r := MsgCommand(wParam, lParam, nmsg, hwnd)
return r
}
else if (nmsg = 1028)
return MsgNotifyIcon(wParam, lParam, nmsg, hwnd)
Critical 0
return DllCall("CallWindowProc", "ptr", oldproc, "ptr", hwnd, "uint", nmsg, "ptr", wParam, "ptr", lParam, "ptr")
}
}
Edit() {
for hwnd in WinGetList(J_ScriptName) {
if WinGetClass(hwnd) ~= '^(#32770|AutoHotkey)$'
continue
return WinActivate(hwnd)
}
try
Run '*edit "' J_ScriptFullPath '"'
catch
Run 'notepad.exe "' J_ScriptFullPath '"'
}
Reload() {
Run Format(A_IsCompiled ? '"{2}" /restart "{3}"' : '"{1}" "{2}" /restart "{3}"'
, A_AhkPath, A_ScriptFullPath, J_ScriptFullPath), A_InitialWorkingDir
}
SingleInstance(mode:='force') {
dhw := A_DetectHiddenWindows
switch StrLower(mode) {
case 'force':
TerminatePreviousInstance 'SingleInstance'
case 'ignore':
A_DetectHiddenWindows := true
for hwnd in WinGetList(jktitle " ahk_class AutoHotkey")
if hwnd != A_ScriptHwnd
ExitApp
case 'prompt':
prompted := false
A_DetectHiddenWindows := true
for hwnd in WinGetList(jktitle " ahk_class AutoHotkey") {
if hwnd != A_ScriptHwnd {
if prompted || MsgBox("An older instance of this script is already running. Replace it with this instance?",, "y/n") = "no"
ExitApp
prompted := true
TerminateInstance hwnd, 'SingleInstance'
}
}
default:
throw ValueError('Invalid mode "' mode '"')
}
A_DetectHiddenWindows := dhw
}
Include(path) {
if !allow_wildcard_in_include && path ~= '[*?<>"]'
throw Error('Include file "' path '" cannot be opened.')
static already_included := (_ => (_.CaseSense := 'Off', _))(Map())
included := 0
Loop Files path, 'F' {
path := A_LoopFileFullPath
if already_included.Has(path)
continue
already_included[path] := true
JsRT.RunFile path, default_script_encoding
++included
}
if !included && !(path ~= '[*?]')
throw Error('Include file "' path '" cannot be opened.')
if allow_wildcard_in_include
return included
}
InstallKeybdHook() {
static ih
if IsSet(&ih)
return
ih := InputHook('I255 L0 B V')
ih.Start
}
InstallMouseHook() {
Hotkey '~XButton2 & ~XButton2', _ => 0
}
StartupIconTimer(enable := unset) {
if !IsSet(&enable) {
if !IconTimerIsSet
return
A_IconHidden := false
enable := false
}
global IconTimerIsSet := enable
SetTimer StartupIconTimer, enable ? -100 : 0
}
GetIconHidden() => A_IconHidden && !IconTimerIsSet
SetIconHidden(value) {
A_IconHidden := value
StartupIconTimer false
}
_LoopFiles(pattern, mode, body:=unset) {
IsSet(&body) || (body := mode, mode := 'F')
static fields := ['attrib', 'dir', 'ext', 'fullPath', 'name', 'path', 'shortName'
, 'shortPath', 'size', 'timeAccessed', 'timeCreated', 'timeModified']
Loop Files pattern, mode {
item := js.Object()
for field in fields
item.%field% := A_LoopFile%field%
body(item)
}
}
_LoopReg(keyname, mode, body:=unset) {
IsSet(&body) || (body := mode, mode := 'F')
static fields := ['name', 'type', 'key', 'timeModified']
Loop Reg keyname, mode {
item := js.Object()
for field in fields
item.%field% := A_LoopReg%field%
body(item)
}
}
AddHotkeySettings(scope) {
hk := scope.hotkey, defProp := js.Object.defineProperty
_Hotkey.B := '', _Hotkey.T := '', _Hotkey.I := '', _Hotkey.useHook := false
defProp hk, AdjustPropName('MaxThreadsBuffer'), {
get: () => _Hotkey.B ? jsTrue : jsFalse,
set: (value) => _Hotkey.B := value ? 'B' : ''
}
defProp hk, AdjustPropName('MaxThreadsPerHotkey'), {
get: () => _Hotkey.T ? Integer(SubStr(_Hotkey.T, 2)) : 1,
set: (value) => _Hotkey.T := (value := intInRange(value, 1, 255)) != 1 ? 'T' value : ''
}
defProp hk, AdjustPropName('InputLevel'), {
get: () => _Hotkey.I ? Integer(SubStr(_Hotkey.I, 2)) : 0,
set: (value) => _Hotkey.I := (value := intInRange(value, 0, 100)) ? 'I' value : ''
}
defProp hk, AdjustPropName('UseHook'), {
get: () => _Hotkey.useHook ? jsTrue : jsFalse,
set: (value) => _Hotkey.useHook := value ? true : false
}
intInRange(i, low, high) {
if (i := Integer(i)) < low || i > high
throw ValueError("Invalid value")
return i
}
}
_Hotkey(keyname, callback:="", options:="") {
try
Hotkey keyname
catch e {
if not e is TargetError
throw e
options := _Hotkey.B _Hotkey.T _Hotkey.I options
Hotkey keyname, callback, options
if _Hotkey.useHook
Hotkey '$' keyname
return
}
if (callback != "" || options != "")
Hotkey keyname, callback, options
}
TerminatePreviousInstance(by) {
DetectHiddenWindows (dhw := A_DetectHiddenWindows, true)
for hwnd in WinGetList(jktitle " ahk_class AutoHotkey") {
if hwnd != A_ScriptHwnd {
TerminateInstance hwnd, by
break
}
}
DetectHiddenWindows dhw
}
TerminateInstance(hwnd, by) {
static WM_COMMNOTIFY := 0x44
static AHK_EXIT_BY_RELOAD := 1030
static AHK_EXIT_BY_SINGLEINSTANCE := 1031
PostMessage WM_COMMNOTIFY, AHK_EXIT_BY_%by%, 0, hwnd
Loop {
if WinWaitClose(hwnd,, 2)
break
if MsgBox("Could not close the previous instance of this script. Keep waiting?",, "y/n") = "no"
ExitApp 2
}
}
Menu_AddStandard_Fix(m) {
item_count() => DllCall('GetMenuItemCount', 'ptr', m.handle)
id_exists(id) => DllCall('GetMenuState', 'ptr', m.handle, 'uint', id, 'uint', 0) != -1
name_exists(name) {
try {
m.Rename name, name
return true
}
return false
}
CMD(id) => (*) => PostMessage(0x111, id, 0, A_ScriptHwnd)
static group := [
[["&Open", CMD(65300)],
["&Help", CMD(65301)]],
[["&Window Spy", CMD(65302)],
["&Reload This Script", CMD(65303)],
["&Edit This Script", CMD(65304)]],
[["&Suspend Hotkeys", CMD(65305)],
["&Pause Script", CMD(65306)],
["E&xit", CMD(65307)]]
]
number_to_add(items) {
n := 0
for item in items
if !name_exists(item[1])
++n
return n
}
index := item_count() + 1
adding1 := number_to_add(group[1]) > 1
adding2 := number_to_add(group[2]) > 1
adding3 := number_to_add(group[3]) > 1
add_sep := [adding1 && (adding2 || adding3), adding2 && adding3, false]
first_added := ""
add_if_needed(name, action) {
if !name_exists(name) {
m.Add name, action
if first_added = ""
first_added := name
}
}
for items in group {
for item in items
if !name_exists(item[1])
add_if_needed(item*)
if add_sep[A_Index]
m.Add
}
if m = J_TrayMenu && !m.Default && first_added = "&Open"
m.Default := index '&'
}
TrayMenu_Show_Fix(m, postCmd:=false) {
if m = J_TrayMenu {
try m.%A_IsPaused?"Check":"Uncheck"%("&Pause Script")
try m.%A_IsSuspended?"Check":"Uncheck"%("&Suspend Hotkeys")
}
DllCall("GetCursorPos", "ptr", pt := BufferAlloc(8))
x := NumGet(pt, 0, "int"), y := NumGet(pt, 4, "int")
flags := postCmd ? 0x180 : 0
GFW() => DllCall("GetForegroundWindow", "ptr")
active_wnd := GFW()
WinActivate A_ScriptHwnd
id := DllCall("TrackPopupMenuEx", "ptr", m.handle, "uint", flags, "int", x, "int", y, "ptr", A_ScriptHwnd, "ptr", 0)
if GFW() = A_ScriptHwnd
WinActivate active_wnd
if postCmd && id
PostMessage 0x111, id,, A_ScriptHwnd
}
AutoHotkey_3.0-alpha.1\AutoHotkey64.exe:
Code: Select all
; <COMPILER: v1.1.33.05>
JKVersion := '3.0-alpha.1'
#Requires AutoHotkey v2.0-a128+
functions_use_lowercase_initial_letter := true
allow_wildcard_in_include := false
default_script_name := RegExReplace(A_ScriptName, '\.[^\.]*$', '.j?')
class JsRT
{
static Call()
{
throw Error("This class is abstract. Use JsRT.IE() or JSRT.Edge() to initialize.", -1)
}
static IE()
{
if !this._hmod := DllCall("LoadLibrary", "str", "jscript9", "ptr")
throw Error("Failed to load jscript9.dll", -1)
if DllCall("jscript9\JsCreateRuntime", "int", 0, "int", -1, "ptr", 0, "ptr*", &runtime:=0) != 0
throw Error("Failed to initialize JsRT", -1)
DllCall("jscript9\JsCreateContext", "ptr", runtime, "ptr", 0, "ptr*", &context:=0)
return this._Initialize("jscript9", runtime, context)
}
static Edge()
{
if !this._hmod := DllCall("LoadLibrary", "str", "chakra", "ptr")
throw Error("Failed to load chakra.dll", -1)
if DllCall("chakra\JsCreateRuntime", "int", 0, "ptr", 0, "ptr*", &runtime:=0) != 0
throw Error("Failed to initialize JsRT", -1)
DllCall("chakra\JsCreateContext", "ptr", runtime, "ptr*", &context:=0)
return this._Initialize("chakra", runtime, context)
}
static _Initialize(dll, runtime, context)
{
this._dll := dll
this._runtime := runtime
this._context := context
this._ImportAPI()
DllCall(dll "\JsSetCurrentContext", "ptr", context)
this._sources := Map()
this._sources.CaseSense := 'Off'
this._sources['eval'] := 0
return this._dsp := this.FromJs(this.JsGetGlobalObject())
}
static _ImportAPI()
{
API := '
(
JsAddRef(ptr ref, uint* return count)
JsBooleanToBool(ptr valref, char* return bool)
JsCallFunction(ptr function, ptr arguments, ushort argumentCount, ptr* return valref)
JsCollectGarbage(ptr runtime)
JsCreateError(ptr message, ptr* return valref)
JsCreateExternalObject(ptr data, ptr finalizeCallback, ptr* return valref)
JsCreateFunction(ptr nativeGetCb, ptr callbackState, ptr* return valref)
JsCreateTypeError(ptr message, ptr* return valref)
JsGetAndClearException(ptr* return valref)
JsGetArrayBufferStorage(ptr arrayBuffer, ptr* buf, int* byteCount)
JsGetDataViewStorage(ptr dataView, ptr* buf, int* byteCount)
JsGetExternalData(ptr object, ptr* return)
JsGetGlobalObject(ptr* return valref)
JsGetOwnPropertyNames(ptr object, ptr* return valref)
JsGetOwnPropertySymbols(ptr object, ptr* return valref)
JsGetProperty(ptr object, ptr propertyId, ptr* return valref)
JsGetPropertyIdFromName(str name, ptr* return propId)
JsGetPrototype(ptr object, ptr* return valref)
JsGetTypedArrayStorage(ptr typedArray, ptr* buf, int* byteCount, int* arrayType, int* elemSize)
JsGetUndefinedValue(ptr* return undefined)
JsGetValueType(ptr value, int* return)
JsHasException(char* return bool)
JsHasExternalData(ptr object, char* return bool)
JsIdle(uint* return nextIdleTick)
JsInstanceOf(ptr object, ptr constructor, char* return bool)
JsParseScript(wstr script, ptr sourceContext, wstr sourceUrl, ptr* return valref)
JsPointerToString(ptr stringValue, uptr stringLength, ptr* return valref)
JsProjectWinRTNamespace(wstr namespace)
JsRelease(ptr ref, uint* return count)
JsRunScript(wstr script, ptr sourceContext, wstr sourceUrl, ptr* return valref)
JsSetException(ptr exception)
JsSetExternalData(ptr object, ptr data)
JsSetObjectBeforeCollectCallback(ptr ref, ptr callbackState, ptr callback)
JsSetProperty(ptr object, ptr propertyId, ptr value, char useStrictRules)
JsSetPrototype(ptr object, ptr proto)
JsValueToVariant(ptr valref, ptr variant)
JsVariantToValue(ptr variant, ptr* return valref)
)'
static kernel32 := DllCall("GetModuleHandle", "str", "kernel32", "ptr")
static GPA := DllCall.Bind(DllCall("GetProcAddress", "ptr", kernel32, "astr", "GetProcAddress", "ptr"), "ptr", , "astr", , "ptr")
Loop Parse API, '`n'
{
if !RegExMatch(A_LoopField, "^(\w+)\((.*)\)$", &m)
{
MsgBox "DEBUG: Fatal error in JsRT API declarations, line " A_Index
ExitApp
}
funcname := m.1
argtypes := RegExReplace(m.2, '(?<=^|,) *(\w+(?: *\*|[Pp](?= ))?) *+([\w ]*?) *(?=,|$)', '$1,$2')
argtypes := StrSplit(argtypes, ',', ' ')
if !(pfn := GPA(this._hmod, funcname))
throw Error('Failed to load JsRT function "' funcname '" from DLL "' this._dll '"')
api := {ptr: pfn, name: funcname}
if argtypes.Length && argtypes[-1] ~= '^return\b'
api.return := argtypes.Length
Loop argtypes.Length // 2
argtypes.Delete A_Index * 2
this.%funcname% := (api.HasProp('return') ? CallApiRet : CallApi)
.Bind( , api, argtypes*)
}
CallApi(thisJsRT, api, args*)
{
if errorCode := DllCall(api.ptr, args*)
this._ThrowApiError api.name, errorCode
}
CallApiRet(thisJsRT, api, args*)
{
args[api.return] := &(retval := 0)
if errorCode := DllCall(api.ptr, args*)
this._ThrowApiError api.name, errorCode
return retval
}
}
static _ThrowApiError(apiName, errorCode)
{
if errorCode = 0x30001 || errorCode = 0x30002
throw this.FromJs(this.JsGetAndClearException())
throw (this.Error)(Format("Call to {1} failed with error 0x{2:x}", apiName, errorCode), -1, errorCode)
}
static __Delete()
{
this._dsp := ""
if dll := this._dll
{
DllCall(dll "\JsSetCurrentContext", "ptr", 0)
DllCall(dll "\JsDisposeRuntime", "ptr", this._runtime)
}
DllCall("FreeLibrary", "ptr", this._hmod)
}
static FromJs(valref)
{
ref := ComObject(0x400C, (var := BufferAlloc(24, 0)).ptr)
this.JsValueToVariant(valref, var)
return (val := ref[], ref[] := 0, val)
}
static ToJs(val)
{
ref := ComObject(0x400C, (var := BufferAlloc(24, 0)).ptr)
ref[] := val
valref := this.JsVariantToValue(var)
ref[] := 0
return valref
}
static SourceContext(filename)
{
if !this._sources.has(filename)
this._sources[filename] := this._sources.Count
return this._sources[filename]
}
static RunFile(filename, readOpt:="")
{
this.JsRunScript(FileRead(filename, readOpt), this.SourceContext(filename), filename)
}
static Eval(code)
{
return this.FromJs(this.JsRunScript(code, 0, "eval"))
}
class Error extends Error
{
}
}
GetCommandLineArgs() {
if !ptr := DllCall("shell32\CommandLineToArgvW", "ptr", DllCall("GetCommandLineW", "ptr"), "int*", &nargs:=0, "ptr")
throw MemoryError()
try {
args := []
loop nargs
args.Push StrGet(NumGet(ptr, (A_Index-1)*A_PtrSize, "ptr"), "UTF-16")
return args
}
finally DllCall("LocalFree", "ptr", ptr)
}
#NoTrayIcon
#SingleInstance Off
OnError ErrorMsg
A_AllowMainWindow := true
PatchMenus
ParseCommandLine
ParseCommandLine() {
global default_script_encoding := "UTF-8"
global J_Args := GetCommandLineArgs()
global is_restart := false
global ErrorStdOut := false
drop_jk_ahk := !A_IsCompiled
J_Args.RemoveAt 1
while J_Args.Length {
if J_Args[1] ~= 'i)^/r(?:estart)$'
is_restart := true
else if J_Args[1] ~= 'i)^/cp\d+$'
default_script_encoding := SubStr(J_Args[1], 2)
else if J_Args[1] ~= 'i)^/ErrorStdOut(?:=|$)'
ErrorStdOut := FileOpen('**', 'w', SubStr(J_Args[1], 14))
else if J_Args[1] ~= 'i)^/Debug(?:=|$)' && drop_jk_ahk
{}
else if drop_jk_ahk && J_Args[1] ~= 'i)(?:[\\/]|^)\Q' A_ScriptName '\E$'
drop_jk_ahk := false
else
break
J_Args.RemoveAt 1
}
if !J_Args.Length {
for prefix in ['', A_MyDocuments '\'] {
Loop Files prefix default_script_name {
jkfile := A_LoopFileFullPath
break 2
}
}
if !IsSet(&jkfile) {
jkfile := FileSelect("1", default_script_name, "Select Script File", "Script Files (*.jk;*.js)")
if jkfile = ""
ExitApp
}
}
else if !(J_Args[1] ~= '[*?<>"]') {
Loop Files J_Args.RemoveAt(1)
jkfile := A_LoopFileFullPath
}
if !IsSet(&jkfile) {
MsgBox "Script file not found.",, "IconX"
ExitApp
}
global J_ScriptFullPath := jkfile
}
WinSetTitle jktitle := J_ScriptFullPath ' - AutoHotkey v' JKVersion, A_ScriptHwnd
if is_restart
TerminatePreviousInstance 'Reload'
SplitPath J_ScriptFullPath, &J_ScriptName, &J_ScriptDir
A_IconTip := A_ScriptName := J_ScriptName
SetWorkingDir J_ScriptDir
undefined := ComObject(0,0), null := ComObject(9,0)
jsTrue := ComObject(0xB, -1), jsFalse := ComObject(0xB, 0)
AdjustFuncName := functions_use_lowercase_initial_letter
? n => RegExReplace(n, '^[A-Z]+', '$l0') : n => n
AdjustPropName := AdjustFuncName
AdjustMethodName := AdjustFuncName
AdjustClassName := n => n
js := JsRT.Edge()
MIN_SAFE_INTEGER := js.Number.MIN_SAFE_INTEGER
MAX_SAFE_INTEGER := js.Number.MAX_SAFE_INTEGER
AddAhkObjects js
IsSet(&D) ? js.D := WrapBif(D) : %'D'% := _ => ""
loading_script := true
StartupIconTimer true
JsRT.RunFile J_ScriptFullPath, default_script_encoding
ErrorStdOut := false
loading_script := false
StartupIconTimer
AddAhkObjects(scope) {
defProp := scope.Object.defineProperty
Hotkey := _Hotkey
Boolean(r) => r ? jsTrue : jsFalse
functions := "
(Join`s
!Abs !ACos !ASin !ATan BlockInput !BufferAlloc CallbackCreate CallbackFree
CaretGetPos !Ceil !Chr Click ClipWait ComCall ComObjActive ComObjArray
ComObjConnect ComObjCreate ComObject ComObjFlags ComObjGet ComObjQuery
ComObjType ComObjValue ControlAddItem ControlChooseIndex ControlChooseString
ControlClick ControlDeleteItem ControlFindItem ControlFocus ControlGetChecked
ControlGetChoice ControlGetClassNN ControlGetEnabled ControlGetExStyle
ControlGetFocus ControlGetHwnd ControlGetIndex ControlGetItems ControlGetPos
ControlGetStyle ControlGetText ControlGetVisible ControlHide ControlHideDropDown
ControlMove ControlSend ControlSendText ControlSetChecked ControlSetEnabled
ControlSetExStyle ControlSetStyle ControlSetText ControlShow ControlShowDropDown
CoordMode !Cos !Critical !DateAdd !DateDiff DetectHiddenText DetectHiddenWindows
DirCopy DirCreate DirDelete DirExist DirMove DirSelect DllCall Download
DriveEject DriveGetCapacity DriveGetFilesystem DriveGetLabel DriveGetList
DriveGetSerial DriveGetSpaceFree DriveGetStatus DriveGetStatusCD DriveGetType
DriveLock DriveSetLabel DriveUnlock Edit EditGetCurrentCol EditGetCurrentLine
EditGetLine EditGetLineCount EditGetSelectedText EditPaste EnvGet EnvSet
!Exception !Exit ExitApp !Exp FileAppend FileCopy FileCreateShortcut FileDelete
FileEncoding FileExist FileGetAttrib FileGetShortcut FileGetSize FileGetTime
FileGetVersion FileInstall FileMove FileOpen FileRead FileRecycle
FileRecycleEmpty FileSelect FileSetAttrib FileSetTime !Floor Format FormatTime
GetKeyName GetKeySC GetKeyState GetKeyVK !GetMethod GroupActivate GroupAdd
GroupClose GroupDeactivate GuiCtrlFromHwnd GuiFromHwnd !HasBase !HasMethod !HasProp
HotIf HotIfWinActive HotIfWinExist HotIfWinNotActive HotIfWinNotExist Hotkey
Hotstring IL_Add IL_Create IL_Destroy ImageSearch IniDelete IniRead IniWrite
InputBox !InStr !IsAlnum !IsAlpha !IsDigit !IsFloat !IsInteger !IsLabel !IsLower
!IsNumber !IsObject !IsSet !IsSpace !IsTime !IsUpper !IsXDigit KeyHistory KeyWait
ListHotkeys !ListLines !ListVars ListViewGetContent !Ln LoadPicture !Log !LTrim !Max
MenuFromHandle MenuSelect !Min !Mod MonitorGet MonitorGetCount MonitorGetName
MonitorGetPrimary MonitorGetWorkArea MouseClick MouseClickDrag MouseGetPos
MouseMove MsgBox NumGet NumPut !ObjAddRef !ObjBindMethod !ObjFromPtr
!ObjFromPtrAddRef !ObjGetBase !ObjGetCapacity !ObjHasOwnProp !ObjOwnPropCount
!ObjOwnProps !ObjPtr !ObjPtrAddRef !ObjRelease !ObjSetBase !ObjSetCapacity
OnClipboardChange OnError OnExit OnMessage !Ord OutputDebug Pause PixelGetColor
PixelSearch PostMessage ProcessClose ProcessExist ProcessSetPriority ProcessWait
ProcessWaitClose Random RandomSeed RegDelete RegDeleteKey !RegExMatch
!RegExReplace RegRead RegWrite Reload !Round !RTrim Run RunAs RunWait Send
SendEvent SendInput SendLevel SendMessage SendMode SendPlay SendText
SetCapslockState SetControlDelay SetDefaultMouseSpeed SetKeyDelay SetMouseDelay
SetNumlockState SetRegView SetScrollLockState SetStoreCapsLockMode SetTimer
SetTitleMatchMode SetWinDelay SetWorkingDir Shutdown !Sin Sleep !Sort SoundBeep
SoundGetInterface SoundGetMute SoundGetName SoundGetVolume SoundPlay
SoundSetMute SoundSetVolume SplitPath !Sqrt StatusBarGetText StatusBarWait
!StrCompare StrGet !StrLen !StrLower !StrPtr StrPut !StrReplace !StrSplit !StrUpper
!SubStr Suspend SysGet SysGetIPAddresses !Tan Thread ToolTip TraySetIcon TrayTip
!Trim !Type !VarSetStrCapacity WinActivate WinActivateBottom WinActive WinClose
WinExist WinGetClass WinGetClientPos WinGetControls WinGetControlsHwnd
WinGetCount WinGetExStyle WinGetID WinGetIDLast WinGetList WinGetMinMax
WinGetPID WinGetPos WinGetProcessName WinGetProcessPath WinGetStyle WinGetText
WinGetTitle WinGetTransColor WinGetTransparent WinHide WinKill WinMaximize
WinMinimize WinMinimizeAll WinMinimizeAllUndo WinMove WinMoveBottom WinMoveTop
WinRedraw WinRestore WinSetAlwaysOnTop WinSetEnabled WinSetExStyle WinSetRegion
WinSetStyle WinSetTitle WinSetTransColor WinSetTransparent WinShow WinWait
WinWaitActive WinWaitClose WinWaitNotActive
)"
CaretGetPos.output := ['x', 'y']
ControlGetPos.output := ['x', 'y', 'width', 'height']
FileGetShortcut.output := [, 'target', 'dir', 'args', 'description', 'icon', 'iconNum', 'runState']
ImageSearch.output := ['x', 'y']
LoadPicture.output := [, , 'imageType']
MonitorGet.output := MonitorGetWorkArea.output := [, 'left', 'top', 'right', 'bottom']
MouseGetPos.output := ['x', 'y', 'win', 'control']
PixelSearch.output := ['x', 'y']
Run.output := RunWait.output := [, , , 'pid']
SplitPath.output := [, 'name', 'dir', 'ext', 'nameNoExt', 'drive']
WinGetClientPos.output := WinGetPos.output := ['x', 'y', 'width', 'height']
Gui.Prototype.GetPos.output
:= Gui.Prototype.GetClientPos.output
:= Gui.Control.Prototype.GetPos.output := [, 'x', 'y', 'width', 'height']
CaretGetPos.returns := (r, o) => (r ? o : jsFalse)
ImageSearch.returns := (r, o) => (r ? o : jsFalse)
LoadPicture.returns := (r, o) => (o.handle := r, o)
PixelSearch.returns := (r, o) => (r ? o : jsFalse)
Run.returns := (r, o) => o.pid
RunWait.returns := (r, o) => (o.exitCode := r, o)
ControlGetChecked.returns := Boolean
ControlGetEnabled.returns := Boolean
ControlGetVisible.returns := Boolean
KeyWait.returns := Boolean
SoundGetMute.returns := Boolean
StatusBarWait.returns := Boolean
WinWait.returns := Boolean
WinWaitActive.returns := Boolean
WinWaitClose.returns := Boolean
WinWaitNotActive.returns := Boolean
Loop Parse functions, ' ' {
if A_LoopField ~= '\W'
continue
fn_name := A_LoopField
fn := %fn_name%
fn_name := AdjustFuncName(fn_name)
scope.%fn_name% := WrapBif(fn)
}
AddHotkeySettings(scope)
Gui.Prototype.Control := Gui.Prototype.GetOwnPropDesc('__Item').get
for cls in [ClipboardAll, File, Gui, InputHook, Menu, MenuBar]
scope.%cls.Prototype.__class% := WrapClass(cls)
for cls in [MemoryError, OSError, TargetError, TimeoutError]
scope.%cls.Prototype.__class% := WrapErrorClass(cls)
GetLineFile := js.Function('return /\((.+?:.+?):(\d+):\d+\)/.exec(Error().stack)[1];')
GetLineNumber := js.Function('return parseInt(/\((.+?:.+?):(\d+):\d+\)/.exec(Error().stack)[2]);')
readable := {prototype: {}}
readwriteable := {base: readable, prototype: {base: readable.prototype}}
variables := define_vars()
define_vars() {
r := {base: readable.prototype}
rw := {base: readwriteable.prototype}
return {
AhkPath: A_ScriptFullPath,
AhkVersion: JKVersion,
AllowMainWindow: r,
AppData: r,
AppDataCommon: r,
Clipboard: rw,
ComputerName: r,
ComSpec: r,
ControlDelay: rw,
CoordModeCaret: rw,
CoordModeMenu: rw,
CoordModeMouse: rw,
CoordModePixel: rw,
CoordModeToolTip: rw,
Cursor: r,
DD: r,
DDD: r,
DDDD: r,
DefaultMouseSpeed: rw,
Desktop: r,
DesktopCommon: r,
DetectHiddenText: rw,
DetectHiddenWindows: rw,
EndChar: r,
EventInfo: rw,
FileEncoding: rw,
Hour: r,
IconFile: r,
IconHidden: {get: GetIconHidden, set: SetIconHidden},
IconNumber: r,
IconTip: rw,
InitialWorkingDir: A_InitialWorkingDir,
Is64bitOS: ComObject(0xB, -A_Is64bitOS),
IsAdmin: ComObject(0xB, -A_IsAdmin),
IsCompiled: ComObject(0xB, 0),
IsPaused: {get: () => ComObject(0xB, -A_IsPaused)},
IsSuspended: {get: () => ComObject(0xB, -A_IsSuspended)},
KeyDelay: rw,
KeyDelayPlay: rw,
KeyDuration: rw,
KeyDurationPlay: rw,
Language: r,
LastError: rw,
LineFile: {get: GetLineFile},
LineNumber: {get: GetLineNumber},
ListLines: rw,
MDay: r,
Min: r,
MM: r,
MMM: r,
MMMM: r,
Mon: r,
MouseDelay: rw,
MouseDelayPlay: rw,
MSec: r,
MyDocuments: r,
Now: r,
NowUTC: r,
OSVersion: A_OSVersion,
PriorHotkey: r,
PriorKey: r,
ProgramFiles: r,
Programs: r,
ProgramsCommon: r,
PtrSize: A_PtrSize,
RegView: rw,
ScreenDPI: r,
ScreenHeight: r,
ScreenWidth: r,
ScriptDir: J_ScriptDir,
ScriptFullPath: J_ScriptFullPath,
ScriptHwnd: A_ScriptHwnd,
ScriptName: rw,
Sec: r,
SendLevel: rw,
SendMode: rw,
StartMenu: r,
StartMenuCommon: r,
Startup: r,
StartupCommon: r,
StoreCapsLockMode: rw,
Temp: r,
ThisHotkey: r,
TickCount: r,
TimeIdle: r,
TimeIdleKeyboard: r,
TimeIdleMouse: r,
TimeIdlePhysical: r,
TimeSincePriorHotkey: r,
TimeSinceThisHotkey: r,
TitleMatchMode: rw,
TitleMatchModeSpeed: rw,
TrayMenu: r,
UserName: r,
WDay: r,
WinDelay: rw,
WinDir: r,
WorkingDir: rw,
YDay: r,
Year: r,
YWeek: r,
YYYY: r,
}
}
defProp scope, 'A_Args', {value: js.Array(J_Args*), writable: true}
variables.Clipboard := {
get: () => A_Clipboard,
set: (value) => A_Clipboard := IsObject(value) ? ObjectFromJs(JsRT.ToJs(value)) : value
}
variables.TrayMenu := JsRT.FromJs(ObjectToJs(J_TrayMenu))
defProp variables.TrayMenu, AdjustMethodName('Show'), {value: WrapBif(TrayMenu_Show_Fix)}
get_var(name) => %name%
set_var(name, value) => %name% := value
for name, value in variables.OwnProps() {
defProp scope, 'A_' name, value is readable ? {
get: get_var.Bind('A_' name),
set: value is readwriteable ? set_var.Bind('A_' name) : undefined
} : value is Object ? value : {value: value}
}
Persistent(n:=true) {
global Persistent
static isPersistent
if IsSet(&Persistent) && Persistent is Func
wasPersistent := Persistent(n)
else {
wasPersistent := isPersistent
OnMessage(0xBADC0DE, (*) => "", isPersistent := n)
}
return wasPersistent ? jsTrue : jsFalse
}
for fn in [Include, InstallKeybdHook, InstallMouseHook, Persistent, SingleInstance]
scope.%AdjustFuncName(fn.Name)% := WrapBif(fn)
scope.%AdjustFuncName('LoopFiles')% := WrapBif(_LoopFiles)
scope.%AdjustFuncName('LoopReg')% := WrapBif(_LoopReg)
scope.%AdjustFuncName('CollectGarbage')% := WrapBif(JsRT.JsCollectGarbage.Bind(JsRT, JsRT._runtime))
}
WrapBif(fn) {
op_return := fn.DeleteProp('returns')
if op_array := fn.DeleteProp('output') {
op := Map()
loop op_array.length
if op_array.Has(A_Index)
op[A_Index] := op_array[A_Index]
op.in_count := fn.MaxParams - op.count
fn := BifCallReturnOutputVars.Bind(fn, op, op_return)
}
else if op_return {
fn := ((r, fn, p*) => r(fn(p*))).Bind(op_return, fn)
}
static callbackFromJS := CallbackCreate(CallFromJS, "F")
static callbackBeforeCollect := CallbackCreate((rfn, pfn) => ObjRelease(pfn), "F")
rfn := JsRT.JsCreateFunction(callbackFromJS, pfn := ObjPtrAddRef(fn))
JsRT.JsSetObjectBeforeCollectCallback(rfn, pfn, callbackBeforeCollect)
return JsRT.FromJs(rfn)
}
CallFromJS(callee, isCtor, argv, argc, state) {
argc &= 0xffff, isCtor &= 0xff
try {
fn := ObjFromPtrAddRef(state)
if isCtor
throw TypeError(fn.Name ' is not a constructor')
if JsRT.JsGetValueType(NumGet(argv, "ptr")) = 0
argv += A_PtrSize, argc -= 1
args := ArrayFromArgv(argv, argc)
if HasProp(fn, 'belongsTo') && not HasBase(args[1], fn.belongsTo)
throw TypeError("'this' is not a " fn.belongsTo.__Class)
return ToJs(fn(args*))
} catch e {
JsRT.JsSetException ErrorToJs(e)
return 0
}
}
CallClassFromJS(callee, isCtor, argv, argc, state) {
argc &= 0xffff, isCtor &= 0xff
try {
this := NumGet(argv, "ptr"), cls := ObjFromPtrAddRef(state)
if !isCtor
throw TypeError(cls.Prototype.__Class ' cannot be called without the new keyword')
if !JsRT.JsInstanceOf(this, callee)
throw TypeError("'this' is not a " cls.Prototype.__Class)
return ObjectToJs(cls(ArrayFromArgv(argv + A_PtrSize, argc - 1)*))
} catch e {
if e is ValueError && cls.Call = Object.Call
e := TypeError(cls.Prototype.__Class " cannot be instantiated directly")
JsRT.JsSetException ErrorToJs(e)
return 0
}
}
CallIntoJS(callee, args) {
return JsRT.FromJs(JsRT.JsCallFunction(callee, ArrayToArgv(args), args.Length))
}
ArrayToArgv(args) {
b := BufferAlloc(args.Length * A_PtrSize, 0)
for arg in args {
if IsSet(&arg)
NumPut 'ptr', ToJs(arg), b, (A_Index-1)*A_PtrSize
else
NumPut 'ptr', JsRT.JsGetUndefinedValue(), b, (A_Index-1)*A_PtrSize
}
return b
}
WrapClass(acls) {
if ObjHasOwnProp(acls, '__js')
return acls.__js
static callbackFromJS := CallbackCreate(CallClassFromJS, "F")
jcls := JsRT.FromJs(rjcls := JsRT.JsCreateFunction(callbackFromJS, ObjPtrAddRef(acls)))
acls .__js := jcls
acls.Prototype.__js := jcls.prototype
WrapMethods acls , jcls
WrapMethods acls.Prototype, jcls.prototype
if acls.base != Object {
JsRT.JsSetPrototype(rjcls, JsRT.ToJs(jb := WrapClass(acls.base)))
JsRT.JsSetPrototype(JsRT.ToJs(jcls.prototype), JsRT.ToJs(jb.prototype))
}
static setTag := js.Function('obj', 'tag', 'obj[Symbol.toStringTag] = tag')
setTag jcls.prototype, acls.Prototype.__Class
return jcls
}
WrapErrorClass(acls) {
jcls := JsRT.Eval(Format('{ class {1} extends Error {}; {1}.prototype.name = "{1}"; {1} }', acls.Prototype.__class))
acls.Prototype.__js := jcls.prototype
return jcls
}
WrapMethods(aobj, jobj) {
defProp := js.Object.defineProperty
for p in aobj.OwnProps() {
if SubStr(p, 1, 2) = '__' {
if p = '__Enum'
SetIterator jobj, aobj.%p%
continue
}
pd := aobj.GetOwnPropDesc(p)
for name, value in pd.OwnProps()
if value is Func
value.belongsTo := aobj
if pd.HasProp('value') {
if pd.value is Func {
pd.value := WrapBif(pd.value)
p := AdjustMethodName(p)
}
else if pd.value is Class {
pd.value := WrapClass(pd.value)
p := AdjustClassName(p)
}
else
continue
}
else if pd.HasProp('call') {
pd := {value: WrapBif(pd.call)}
p := AdjustMethodName(p)
}
else {
if pd.HasProp('get')
pd.get := WrapBif(pd.get)
if pd.HasProp('set')
pd.set := WrapBif(pd.set)
p := AdjustPropName(p)
}
pd.enumerable := true
defProp jobj, p, pd
}
}
SetIterator(jobj, f) {
static setIt := js.Function('v', 'f', 'v[Symbol.iterator] = f')
get_iterator(f, this) {
next(f, this) {
o := js.Object()
if (o.done := f(&v) ? jsFalse : jsTrue) = jsFalse
o.value := v
return o
}
proto := js.Object()
proto.next := WrapBif(next.Bind(f(this, 1)))
return proto
}
setIt jobj, WrapBif(get_iterator.Bind(f))
}
ArrayFromArgv(argv, argc) {
loop (args := []).Length := argc {
v := NumGet(argv + (A_Index-1)*A_PtrSize, "ptr")
switch JsRT.JsGetValueType(v) {
case 0:
continue
case 1:
throw TypeError("Invalid use of null")
case 4:
v := JsRT.JsBooleanToBool(v)
case 5:
v := ObjectFromJs(v)
case 6:
v := JsFunctionProxy(v)
case 8:
v := [ValuesOf(JsRT.FromJs(v))*]
case 10:
v := JsArrayBufferProxy(v)
case 11:
v := JsTypedArrayProxy(v)
case 12:
v := JsDataViewProxy(v)
default:
v := JsRT.FromJs(v)
}
args[A_Index] := v
}
return args
}
ObjectToJs(v) {
if ObjHasOwnProp(v, '__rj')
return v.__rj
if ObjHasOwnProp(b := ObjGetBase(v), '__js') {
static finalizer := CallbackCreate(p => ObjFromPtr(p).DeleteProp('__rj'), 'F', 1)
rj := JsRT.JsCreateExternalObject(ObjPtrAddRef(v), finalizer)
JsRT.JsSetPrototype(rj, JsRT.ToJs(b.__js))
return v.__rj := rj
}
if b = Object.prototype {
jv := js.Object()
for pn, pv in ObjOwnProps(v)
jv.%pn% := pv
return JsRT.ToJs(jv)
}
D 'no conversion for ' type(v)
return JsRT.ToJs(v)
}
ToJs(v) {
if v is Object
return ObjectToJs(v)
if v is Integer && (v < MIN_SAFE_INTEGER || v > MAX_SAFE_INTEGER)
v := String(v)
return JsRT.ToJs(v)
}
ErrorToJs(e) {
if not e is Error
return JsRT.ToJs(e)
if e is TypeError
return JsRT.ToJS(js.TypeError(StrReplace(e.message, "a ComO", "an o")))
if e is MemberError && RegExMatch(e.message, 'named "(.*?)"', &m)
return JsRT.ToJS(js.TypeError("Object doesn't support property or method '" m.1 "'"))
je := js.Error(e.message)
je.extra := e.Extra
if (b := ObjGetBase(e)).HasProp('__js')
je.__proto__ := b.__js
return JsRT.ToJs(je)
}
ObjectFromJs(rj) {
if JsRT.JsHasExternalData(rj)
return ObjFromPtrAddRef(JsRT.JsGetExternalData(rj))
return JsRT.FromJs(rj)
}
ExternalProperty(rv, name, ptr:=unset) {
id := JsRT.JsGetPropertyIdFromName(name)
rx := JsRT.JsGetProperty(rv, id)
if JsRT.JsGetValueType(rx) = 0 {
if !IsSet(&ptr) || !ptr
return 0
rx := JsRT.JsCreateExternalObject(ptr, 0)
JsRT.JsSetProperty(rv, id, rx, true)
}
else if IsSet(&ptr)
JsRT.JsSetExternalData(rx, ptr)
else
ptr := JsRT.JsGetExternalData(rx)
return ptr
}
class JsCachingProxy {
static Call(rj) {
if p := ExternalProperty(rj, '__p')
return ObjFromPtrAddRef(p)
return super(rj)
}
__New(rj) {
this.__rj := rj
JsRT.JsAddRef(rj)
ExternalProperty(rj, '__p', ObjPtr(this))
}
__Delete() {
if err := JsRT.JsHasException()
err := JsRT.JsGetAndClearException(), JsRT.JsAddRef(err)
ExternalProperty(this.__rj, '__p', 0)
JsRT.JsRelease(this.__rj)
if err
JsRT.JsSetException(err), JsRT.JsRelease(err)
}
}
class JsFunctionProxy extends JsCachingProxy {
Call(params*) {
static missing := (_ => (_.Length := 1, _))([])
params.InsertAt(1, missing*)
return CallIntoJS(this.__rj, params)
}
MinParams => 0
MaxParams => 0
IsVariadic => true
}
class JsBufferProxy {
__new(rj) => JsRT.JsAddRef(this.__rj := rj)
__delete() => JsRT.JsRelease(this.__rj)
Ptr => (this._GetStorage(&ptr), ptr)
Size => (this._GetStorage(, &size), size)
}
class JsArrayBufferProxy extends JsBufferProxy {
_GetStorage(&ptr:=unset, &length:=unset) {
JsRT.JsGetArrayBufferStorage(this.__rj, &ptr:=0, &length:=0)
}
}
class JsTypedArrayProxy extends JsBufferProxy {
_GetStorage(&ptr:=unset, &length:=unset) {
JsRT.JsGetTypedArrayStorage(this.__rj, &ptr:=0, &length:=0, 0, 0)
}
}
class JsDataViewProxy extends JsBufferProxy {
_GetStorage(&ptr:=unset, &length:=unset) {
JsRT.JsGetDataViewStorage(this.__rj, &ptr:=0, &length:=0)
}
}
BifCallReturnOutputVars(ahkfn, op, opr, p*) {
MakeRef(s:='') => &s
if p.length < op.in_count
p.length := op.in_count
for i in op
p.InsertAt i, MakeRef()
r := ahkfn(p*)
o := js.Object()
for i, name in op
o.%name% := %p[i]%
return opr ? opr(r, o) : o
}
ValuesOf(v) {
static getIt := js.Function('v', 'return v[Symbol.iterator]()')
it := getIt(v)
return (&a) => (s := it.next()).done ? false : (a := s.value, true)
}
ErrorMsg(err, mode) {
if ComObjType(err) {
try {
if err.name = "SyntaxError" {
if ErrorStdOut
ErrorStdOut.WriteLine(Format("{1} ({2:i}) : ==> {3}`n Specifically: {4}"
, err.url, err.line, err.message, err.source))
else
MsgBox Format("Syntax error: {1}`n`nFile:`t{2}`nLine:`t{3:i}`nCol:`t{4:i}`nSource:`t{5}"
, err.message = "Syntax error" ? "" : err.message
, err.url, err.line, err.column, err.source),, "IconX"
if loading_script
ExitApp 2
} else {
MsgBox err.stack,, "IconX"
}
return true
}
}
try {
stack := "", specifically := ""
try (!A_IsCompiled) && stack := '`n`n' RegExReplace(err.stack, 'm)^.*?\\(?=[^\\]* \(\d+\) :)', '')
try (err.extra != "") && specifically := "`n`nSpecifically: " err.extra
MsgBox err.message specifically stack,, "IconX"
} catch {
try {
try value := err.toString()
catch
try value := String(err)
catch
value := err
}
MsgBox "Value thrown and not caught.`n`nSpecifically: " value,, "IconX"
}
return true
}
PatchMenus() {
hmenu := DllCall("GetMenu", "ptr", A_ScriptHwnd)
DllCall("RemoveMenu", "ptr", hmenu, "uint", 65406, "uint", 0)
DllCall("RemoveMenu", "ptr", hmenu, "uint", 65407, "uint", 0)
A_TrayMenu.Delete
global J_TrayMenu := Menu()
global Menu_AddStandard := Menu.Prototype.AddStandard
Menu.Prototype.DefineProp 'AddStandard', {Call: Menu_AddStandard_Fix}
Menu_AddStandard_Fix J_TrayMenu
MsgCommand(wParam, lParam, nmsg, hwnd) {
switch wParam & 0xFFFF {
case 65406: (A_IsCompiled) || ListLines()
case 65407: (A_IsCompiled) || ListVars()
case 65400, 65303: Reload
case 65401, 65304: Edit
case 65403, 65306: Pause -1
case 65300:
WinShow A_ScriptHwnd
WinActivate A_ScriptHwnd
default: return
}
return 0
}
MsgNotifyIcon(wParam, lParam, nmsg, hwnd) {
activate_default_tray_item() {
global J_TrayMenu
if -1 != default_id := DllCall("GetMenuDefaultItem", "ptr", J_TrayMenu.handle, "uint", false, "uint", 1)
PostMessage(0x111, default_id,, A_ScriptHwnd)
}
switch lParam {
case 0x205:
TrayMenu_Show_Fix J_TrayMenu, true
case 0x201:
if J_TrayMenu.ClickCount = 1
activate_default_tray_item
case 0x203:
activate_default_tray_item
}
return 0
}
static newproc := CallbackCreate(WindowProc, "", 4)
static oldproc := DllCall((A_PtrSize=8 ? "SetWindowLongPtrW" : "SetWindowLongW"), "ptr", A_ScriptHwnd, "int", -4, "ptr", newproc, "ptr")
WindowProc(hwnd, nmsg, wParam, lParam) {
if (nmsg = 0x111 && (wParam & 0xFFFF) >= 65300) {
if "" != r := MsgCommand(wParam, lParam, nmsg, hwnd)
return r
}
else if (nmsg = 1028)
return MsgNotifyIcon(wParam, lParam, nmsg, hwnd)
Critical 0
return DllCall("CallWindowProc", "ptr", oldproc, "ptr", hwnd, "uint", nmsg, "ptr", wParam, "ptr", lParam, "ptr")
}
}
Edit() {
for hwnd in WinGetList(J_ScriptName) {
if WinGetClass(hwnd) ~= '^(#32770|AutoHotkey)$'
continue
return WinActivate(hwnd)
}
try
Run '*edit "' J_ScriptFullPath '"'
catch
Run 'notepad.exe "' J_ScriptFullPath '"'
}
Reload() {
Run Format(A_IsCompiled ? '"{2}" /restart "{3}"' : '"{1}" "{2}" /restart "{3}"'
, A_AhkPath, A_ScriptFullPath, J_ScriptFullPath), A_InitialWorkingDir
}
SingleInstance(mode:='force') {
dhw := A_DetectHiddenWindows
switch StrLower(mode) {
case 'force':
TerminatePreviousInstance 'SingleInstance'
case 'ignore':
A_DetectHiddenWindows := true
for hwnd in WinGetList(jktitle " ahk_class AutoHotkey")
if hwnd != A_ScriptHwnd
ExitApp
case 'prompt':
prompted := false
A_DetectHiddenWindows := true
for hwnd in WinGetList(jktitle " ahk_class AutoHotkey") {
if hwnd != A_ScriptHwnd {
if prompted || MsgBox("An older instance of this script is already running. Replace it with this instance?",, "y/n") = "no"
ExitApp
prompted := true
TerminateInstance hwnd, 'SingleInstance'
}
}
default:
throw ValueError('Invalid mode "' mode '"')
}
A_DetectHiddenWindows := dhw
}
Include(path) {
if !allow_wildcard_in_include && path ~= '[*?<>"]'
throw Error('Include file "' path '" cannot be opened.')
static already_included := (_ => (_.CaseSense := 'Off', _))(Map())
included := 0
Loop Files path, 'F' {
path := A_LoopFileFullPath
if already_included.Has(path)
continue
already_included[path] := true
JsRT.RunFile path, default_script_encoding
++included
}
if !included && !(path ~= '[*?]')
throw Error('Include file "' path '" cannot be opened.')
if allow_wildcard_in_include
return included
}
InstallKeybdHook() {
static ih
if IsSet(&ih)
return
ih := InputHook('I255 L0 B V')
ih.Start
}
InstallMouseHook() {
Hotkey '~XButton2 & ~XButton2', _ => 0
}
StartupIconTimer(enable := unset) {
if !IsSet(&enable) {
if !IconTimerIsSet
return
A_IconHidden := false
enable := false
}
global IconTimerIsSet := enable
SetTimer StartupIconTimer, enable ? -100 : 0
}
GetIconHidden() => A_IconHidden && !IconTimerIsSet
SetIconHidden(value) {
A_IconHidden := value
StartupIconTimer false
}
_LoopFiles(pattern, mode, body:=unset) {
IsSet(&body) || (body := mode, mode := 'F')
static fields := ['attrib', 'dir', 'ext', 'fullPath', 'name', 'path', 'shortName'
, 'shortPath', 'size', 'timeAccessed', 'timeCreated', 'timeModified']
Loop Files pattern, mode {
item := js.Object()
for field in fields
item.%field% := A_LoopFile%field%
body(item)
}
}
_LoopReg(keyname, mode, body:=unset) {
IsSet(&body) || (body := mode, mode := 'F')
static fields := ['name', 'type', 'key', 'timeModified']
Loop Reg keyname, mode {
item := js.Object()
for field in fields
item.%field% := A_LoopReg%field%
body(item)
}
}
AddHotkeySettings(scope) {
hk := scope.hotkey, defProp := js.Object.defineProperty
_Hotkey.B := '', _Hotkey.T := '', _Hotkey.I := '', _Hotkey.useHook := false
defProp hk, AdjustPropName('MaxThreadsBuffer'), {
get: () => _Hotkey.B ? jsTrue : jsFalse,
set: (value) => _Hotkey.B := value ? 'B' : ''
}
defProp hk, AdjustPropName('MaxThreadsPerHotkey'), {
get: () => _Hotkey.T ? Integer(SubStr(_Hotkey.T, 2)) : 1,
set: (value) => _Hotkey.T := (value := intInRange(value, 1, 255)) != 1 ? 'T' value : ''
}
defProp hk, AdjustPropName('InputLevel'), {
get: () => _Hotkey.I ? Integer(SubStr(_Hotkey.I, 2)) : 0,
set: (value) => _Hotkey.I := (value := intInRange(value, 0, 100)) ? 'I' value : ''
}
defProp hk, AdjustPropName('UseHook'), {
get: () => _Hotkey.useHook ? jsTrue : jsFalse,
set: (value) => _Hotkey.useHook := value ? true : false
}
intInRange(i, low, high) {
if (i := Integer(i)) < low || i > high
throw ValueError("Invalid value")
return i
}
}
_Hotkey(keyname, callback:="", options:="") {
try
Hotkey keyname
catch e {
if not e is TargetError
throw e
options := _Hotkey.B _Hotkey.T _Hotkey.I options
Hotkey keyname, callback, options
if _Hotkey.useHook
Hotkey '$' keyname
return
}
if (callback != "" || options != "")
Hotkey keyname, callback, options
}
TerminatePreviousInstance(by) {
DetectHiddenWindows (dhw := A_DetectHiddenWindows, true)
for hwnd in WinGetList(jktitle " ahk_class AutoHotkey") {
if hwnd != A_ScriptHwnd {
TerminateInstance hwnd, by
break
}
}
DetectHiddenWindows dhw
}
TerminateInstance(hwnd, by) {
static WM_COMMNOTIFY := 0x44
static AHK_EXIT_BY_RELOAD := 1030
static AHK_EXIT_BY_SINGLEINSTANCE := 1031
PostMessage WM_COMMNOTIFY, AHK_EXIT_BY_%by%, 0, hwnd
Loop {
if WinWaitClose(hwnd,, 2)
break
if MsgBox("Could not close the previous instance of this script. Keep waiting?",, "y/n") = "no"
ExitApp 2
}
}
Menu_AddStandard_Fix(m) {
item_count() => DllCall('GetMenuItemCount', 'ptr', m.handle)
id_exists(id) => DllCall('GetMenuState', 'ptr', m.handle, 'uint', id, 'uint', 0) != -1
name_exists(name) {
try {
m.Rename name, name
return true
}
return false
}
CMD(id) => (*) => PostMessage(0x111, id, 0, A_ScriptHwnd)
static group := [
[["&Open", CMD(65300)],
["&Help", CMD(65301)]],
[["&Window Spy", CMD(65302)],
["&Reload This Script", CMD(65303)],
["&Edit This Script", CMD(65304)]],
[["&Suspend Hotkeys", CMD(65305)],
["&Pause Script", CMD(65306)],
["E&xit", CMD(65307)]]
]
number_to_add(items) {
n := 0
for item in items
if !name_exists(item[1])
++n
return n
}
index := item_count() + 1
adding1 := number_to_add(group[1]) > 1
adding2 := number_to_add(group[2]) > 1
adding3 := number_to_add(group[3]) > 1
add_sep := [adding1 && (adding2 || adding3), adding2 && adding3, false]
first_added := ""
add_if_needed(name, action) {
if !name_exists(name) {
m.Add name, action
if first_added = ""
first_added := name
}
}
for items in group {
for item in items
if !name_exists(item[1])
add_if_needed(item*)
if add_sep[A_Index]
m.Add
}
if m = J_TrayMenu && !m.Default && first_added = "&Open"
m.Default := index '&'
}
TrayMenu_Show_Fix(m, postCmd:=false) {
if m = J_TrayMenu {
try m.%A_IsPaused?"Check":"Uncheck"%("&Pause Script")
try m.%A_IsSuspended?"Check":"Uncheck"%("&Suspend Hotkeys")
}
DllCall("GetCursorPos", "ptr", pt := BufferAlloc(8))
x := NumGet(pt, 0, "int"), y := NumGet(pt, 4, "int")
flags := postCmd ? 0x180 : 0
GFW() => DllCall("GetForegroundWindow", "ptr")
active_wnd := GFW()
WinActivate A_ScriptHwnd
id := DllCall("TrackPopupMenuEx", "ptr", m.handle, "uint", flags, "int", x, "int", y, "ptr", A_ScriptHwnd, "ptr", 0)
if GFW() = A_ScriptHwnd
WinActivate active_wnd
if postCmd && id
PostMessage 0x111, id,, A_ScriptHwnd
}