It would have been helpful to mention which alpha you are using, since it isn't the latest one. It must be either v2.0-a128 or v2.0-a129.
Let's say I expose a plain AHK array via a ComObject of type VT_BYREF|VT_VARIANT.
Let's not confuse matters. The ComObject of type VT_BYREF|VT_VARIANT is only used to store the array's IDispatch pointer in the VARIANT. You pass
vref to a DllCall "Ptr" parameter, not a COM method -
"ptr", vref is equivalent to
"ptr", vref.ptr, which is just the address of your VARIANT buffer. You could just as well do this:
Code: Select all
arr := ["this", "is", "a", "test"]
NumPut("int64", 9, "ptr", ObjPtr(arr), arrbuf := BufferAlloc(24))
wv.AddHostObjectToScript("arr", arrbuf)
const arr = await window.chrome.webview.hostObjects.AHK;
I don't think there's any meaning in
awaiting the proxy object. You just get another proxy object, apparently representing the same target object.
const len = await arr.getHostProperty("length");
Why does a proxy object have a length property?
You can use
arr.Length instead.
I was never able to get element indexing to work. I tried manually calling many combinations of arr[1] or arr.__index[0] or arr.getHostProperty("__index")[0].
I assume you tried __item rather than __index.
JavaScript fundamentally does not support indexed or parameterized properties.
arr[1] in JavaScript is just querying the property 1 of arr.
arr.__item[0] is querying
arr.__item and then the 0 property of the result, like
(arr.__item).0 in AutoHotkey. You can't do it that way in AutoHotkey either.
getHostProperty shouldn't be bound by the limitations of the JavaScript language since it's obviously intended for invoking external objects, but if you query it in the console, you'll get something like:
getHostProperty(propertyName) { return (new AsyncRemoteProxy( this._options, true, this._options.remoteMessenger.postRequestMessage( this._remoteObjectId, propertyName, "get", []).then(message => { t…
Clearly it does not support parameters.
The Scripting.Dictionary COM object has a parameterized property named Item. As far as I can tell, it is not possible to call this from WebView2 either. However, the methods of this object work, like
arr.get and not like
arr.push.
The interesting thing is that AHK native Array methods must be called by passing the object itself as the first argument.
That
was interesting, so I fired up the debugger.
- await arr.push(1) calls arr->IDispatch::Invoke with the DISPATCH_PROPERTYGET flag and no parameters to retrieve arr.push, then calls (Array.Prototype.Push)->IDispatch::Invoke with the DISPATCH_METHOD flag and one parameter, 1. In other words, it is equivalent to the AutoHotkey v2 expression (arr.push)(1).
- await arr.get(1) calls arr->IDispatch::Invoke with the DISPATCH_PROPERTYGET flag and no parameters to retrieve arr.get, but this fails. Next, arr->IDispatch::Invoke is called again, but with the DISPATCH_METHOD flag and one parameter, 1.
The failure to retrieve
arr.get is the key here. It fails not because get is user-defined, but specifically because you used DefineProp {Call}. In v2.0-a128 and v2.0-a129, properties defined this way have no default implementation of
get. If you don't define one, attempting to retrieve the property yields a "no such property" result, which is translated to DISP_E_MEMBERNOTFOUND. It appears to be specifically this result which triggers the second call to IDispatch::Invoke on the original target object.
With v2.0-a130 or later,
arr.get(1) will not work, because
arr.get will succeed; i.e. it will return a Func.
It would be interesting to see whether WebView2 uses the
IDispatchEx interface if present. Unlike IDispatch, IDispatchEx allows specifying
this in a call.