The problem with `func_info_t` is that it carries information specific to the instance (like hooks), not only abstract things like the signature, so you can't just apply "current style" function info to "style" object without some additional refactoring. It's hard to comment in more details without the code.
But this `func_info_t` (rather than IID) is used for storing/creating the function object itself (like create_builtin_function but for proxies), not tied to any object, and such function object contains all the "code" of the function not just the signature, so isn't that actually more correct, idiomatically at least?
If this builtin mshtml function were to be implemented in pure jscript somehow, it would contain all its code there, including hooks and everything else. It doesn't feel that right to me to "look up" the function on a specific object when calling it in such case, which may end up with the wrong function if we're not careful.
I'm still hoping to see how the interface capable of handling prototype chains looks like.
There are no interfaces added to deal with prototype chains, unless you mean the new method I added for `func_info_t`?
It's basically like this:
```idl HRESULT BuiltinFuncCall([in] void *func_ctx, [in] BOOL setter, [in] DISPPARAMS *dp, [out, optional] VARIANT *ret, [out] EXCEPINFO *ei, [in] IServiceProvider *caller); ``` and then it's called here: ```c static HRESULT ProxyFunction_call(script_ctx_t *ctx, FunctionInstance *func, jsval_t vthis, unsigned flags, unsigned argc, jsval_t *argv, jsval_t *r, IServiceProvider *caller) { ProxyFunction *function = (ProxyFunction*)func; DISPPARAMS dp = { NULL, NULL, argc, 0 }; IWineJSDispatchHost *proxy_target; VARIANT buf[6], retv; EXCEPINFO ei = { 0 }; IDispatch *this_obj; jsdisp_t *jsdisp; HRESULT hres; unsigned i;
if(flags & DISPATCH_CONSTRUCT) return E_UNEXPECTED;
if(argc > function->function.length) argc = function->function.length;
if(is_undefined(vthis) || is_null(vthis)) this_obj = lookup_global_host(ctx); else if(!is_object_instance(vthis)) return E_UNEXPECTED; else this_obj = get_object(vthis);
jsdisp = to_jsdisp(this_obj); if(jsdisp) { if(!(proxy_target = get_proxy_target(jsdisp))) return E_UNEXPECTED; IWineJSDispatchHost_AddRef(proxy_target); }else if(FAILED(IDispatch_QueryInterface(this_obj, &IID_IWineJSDispatchHost, (void**)&proxy_target)) || !proxy_target) return E_UNEXPECTED;
if(dp.cArgs <= ARRAY_SIZE(buf)) dp.rgvarg = buf; else if(!(dp.rgvarg = malloc(dp.cArgs * sizeof(*dp.rgvarg)))) { hres = E_OUTOFMEMORY; goto fail; }
for(i = 0; i < dp.cArgs; i++) { hres = jsval_to_variant(argv[i], &dp.rgvarg[dp.cArgs - i - 1]); if(FAILED(hres)) goto cleanup; }
V_VT(&retv) = VT_EMPTY; hres = IWineJSDispatchHost_BuiltinFuncCall(proxy_target, function->func_ctx, function->setter, &dp, r ? &retv : NULL, &ei, caller);
if(hres == DISP_E_EXCEPTION) disp_fill_exception(ctx, &ei); else if(hres == E_NOINTERFACE) hres = E_UNEXPECTED; else if(SUCCEEDED(hres) && r) { hres = variant_to_jsval(ctx, &retv, r); VariantClear(&retv); if(SUCCEEDED(hres)) hres = convert_to_proxy(ctx, r); }
cleanup: while(i--) VariantClear(&dp.rgvarg[i]); if(dp.rgvarg != buf) free(dp.rgvarg);
fail: IWineJSDispatchHost_Release(proxy_target); return hres; } ``` nothing special or complicated, and of course the `func_ctx` is stored by PropGetInfo rather than the IID (and we check it for NULL to see whether it's a func/accessor or a proxy prop).