[PATCH 4/9] mshtml: Use builtin hooks even when calling function dispatch objects.

Jacek Caban jacek at codeweavers.com
Wed Dec 8 09:22:55 CST 2021


On 12/8/21 3:11 PM, Gabriel Ivăncescu wrote:
> On 07/12/2021 22:34, Jacek Caban wrote:
>> On 12/7/21 9:29 PM, Gabriel Ivăncescu wrote:
>>> On 07/12/2021 21:18, Jacek Caban wrote:
>>>> On 12/7/21 7:52 PM, Gabriel Ivăncescu wrote:
>>>>>> That just doesn't make sense at all. Once we support prototypes 
>>>>>> document.body.setAttribute === 
>>>>>> document.createElement("div").setAttribute === 
>>>>>> document.head.__proto__.setAttribute === Element.setAttribute. 
>>>>>> It's one and the same function object, not separated quirk 
>>>>>> holders. Hooks are an implementation details of such abstract 
>>>>>> functions in context of a specific object type and there is 
>>>>>> nothing special about that. They are not a part of function 
>>>>>> object itself.
>>>>>>
>>>>>
>>>>> I did mention the prototype means it is the same function object, 
>>>>> I was using a hypothetical example with quirks. My point was that 
>>>>> *if* they end up being different functions (for any reason), using 
>>>>> func_info_t is more correct because it represents two different 
>>>>> functions, with possibly two different hooks.
>>>>>
>>>>> Don't get me wrong, I did not find yet a case where such a quirk 
>>>>> exists, that's why I mentioned it's hypothetical. Although I did 
>>>>> find some duplicated props in some places. Anyway I think it's 
>>>>> more technically correct, and can be easier handled in the future 
>>>>> *if* we find such quirks.
>>>>
>>>>
>>>> No, it's not correct. body element hooks from your example are free 
>>>> to cast 'this' object to HTMLBodyElement. If it did that, you'd end 
>>>> up casting div element object to HTMLBodyElement and likely crash.
>>>>
>>>
>>> Oh I see what you mean now, but that's not an issue because the 
>>> hooks behavior needs to change. I have patches for that of course, 
>>> though I don't know if they'll make it before code freeze.
>>>
>>> In short, the hooks will not take any DispatchEx* argument at all 
>>> (in fact, you can't really know *what* object they are called on), 
>>> but a generic IDispatch *this_obj arg.
>>>
>>> This has nothing to do with the things mentioned above: it is much 
>>> more general. Think of the following with an actual, real hook:
>>>
>>> elem.setAttribute.call(arbitrary_dispatch_object, "A", "B");
>>>
>>> As you can see we cannot guarantee that the hook itself is called on 
>>> the respective element anymore, so casting it is already wrong. The 
>>> correct thing would be to QueryInterface, or detect it some other 
>>> ways (but that's not needed with the hooks we have so far).
>>>
>>> But the point is: hooks need to operate on arbitrary this_obj 
>>> IDispatch, and it's a general issue, not related to the proxy 
>>> interface. 
>>
>>
>>
>> By the time the code reaches hooks, we should already have the type 
>> validated. I don't see why you need to change that.
>>
> Currently the type is validated during the builtin invocation, with 
> QueryInterface. I think the hooks should be kept generic without type 
> validation unless necessary (done within the hook itself) because:
>
> 1) We currently have no hooks requiring a *specific* type until it is 
> forwarded (which already handles failure). Adding such validation 
> would duplicate validation for no real gain.


Hooks are part of function implementation and just like 
HTMLElement_setAttribute is free to cast iface to HTMLElement, its hook 
are free to do that too.


> 2) Type checking within the hook is pretty simple. If we use a 
> specific interface, QueryInterface() should do it. If we rely on a 
> specific internal object layout, we can check the vtbl, because in the 
> hook we know what vtbl we want. But checking this before calling the 
> hook in a generic way seems non-trivial in comparison.


Well, it's trivial. Just don't change them and it should be fine, they 
already have proper validation.


> 3) There's some special cases wrt the special constructors/prototypes 
> (in compat modes) where all builtin accessors on them return undefined 
> / do nothing (but only accessors). I currently use a hook to do that, 
> which makes it trivial. They are already called on an "incompatible" 
> object, though, because calling the prototype props *on the prototype* 
> should fail in normal circumstances (error code depends on doc mode). 
> So if I do type validation *before* the hook, the hook will never run 
> in this case.


It seems to me like you're doing something else wrong, but it's hard to 
comment without seeing the code.


>
> Maybe I'm missing something but what would be a way to validate the 
> type in generic way then? If we are to check for the exact internal 
> object layout, rather than just one exposing the interface, we'll have 
> to check the vtbl. This is assuming hooks can use the internal object 
> layout (and not just the interface, which the forwarded builtin does).


If we have (IID,DISPID), then you could just do that in jscript:

if (FAILED(IDispatch_QueryInterface(this_obj, iid, &iface)) //object has 
wrong type

IJSDispatch_call(this_obj, dispid, ....); // now we know that DISPID is 
valid in context of this object, call it


then in MSHTML, you can get func_info_t from dispid and be sure that 
it's the right func_info_t for this object, but that's an internal 
detail of mshtml/dispid.c and nothing to worry in the rest of the interface.


Jacek




More information about the wine-devel mailing list