Skip to content

Commit

Permalink
mshtml: Move the global proxy constructors/prototypes from the js ctx…
Browse files Browse the repository at this point in the history
… to the window.

Signed-off-by: Gabriel Ivăncescu <[email protected]>
  • Loading branch information
g-insn authored and Gabriel Ivăncescu committed Dec 5, 2023
1 parent c24d399 commit e4bf8b4
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 204 deletions.
90 changes: 52 additions & 38 deletions dlls/jscript/dispex.c
Original file line number Diff line number Diff line change
Expand Up @@ -2529,7 +2529,7 @@ static HRESULT set_js_globals(jsdisp_t *obj)

static HRESULT get_proxy_default_prototype(script_ctx_t *ctx, IWineDispatchProxyPrivate *proxy, jsdisp_t **prot)
{
IDispatch *disp = proxy->lpVtbl->GetDefaultPrototype(proxy, &ctx->proxy_prototypes);
IDispatch *disp = proxy->lpVtbl->GetDefaultPrototype(proxy, ctx->global->proxy);
HRESULT hres;

if(!disp)
Expand All @@ -2549,45 +2549,58 @@ static HRESULT get_proxy_default_prototype(script_ctx_t *ctx, IWineDispatchProxy
return S_OK;
}

static HRESULT get_proxy_default_constructor(script_ctx_t *ctx, jsdisp_t *prot, jsdisp_t **ctor)
static HRESULT get_proxy_default_constructor(script_ctx_t *ctx, jsdisp_t *jsdisp, jsdisp_t **ctor)
{
IDispatch *disp = prot->proxy->lpVtbl->GetDefaultConstructor(prot->proxy, ctx->global->proxy, ctx->proxy_prototypes);
jsdisp_t *old_global = ctx->global;
IDispatch *disp;
HRESULT hres;
jsval_t tmp;

if(!disp)
return E_OUTOFMEMORY;
/* This may end up in CreateConstructor from a nested GetDefaultConstructor via some
* prototype's setup, if we're actually calling it on the window, which would define
* all of the constructors, and that assumes the global to be the one required. But
* in this case we haven't even finished setting up the window, so set it temporarily. */
ctx->global = jsdisp;
hres = jsdisp->proxy->lpVtbl->GetDefaultConstructor(jsdisp->proxy, old_global->proxy, &disp);
ctx->global = old_global;
if(FAILED(hres))
return hres;

if(!disp) {
/* Set the globals on it if we're the window itself (not the prototype).
* We also have to set the props on the constructor and prototype, because
* we had to skip them earlier, since our window was *not* set up yet... */
if(hres == S_FALSE) {
hres = set_js_globals(jsdisp);
if(SUCCEEDED(hres)) {
dispex_prop_t *ctor_prop = find_prop_name_raw(jsdisp, string_hash(L"Window"), L"Window", FALSE);
jsdisp_t *ctor_obj;

if(ctor_prop && ctor_prop->type == PROP_JSVAL && is_object_instance(ctor_prop->u.val) &&
(ctor_obj = to_jsdisp(get_object(ctor_prop->u.val))))
{
hres = jsdisp_define_data_property(ctor_obj, L"prototype", 0, jsval_obj(jsdisp->prototype));
if(SUCCEEDED(hres))
hres = jsdisp_define_data_property(jsdisp->prototype, L"constructor", PROPF_WRITABLE | PROPF_CONFIGURABLE, jsval_obj(ctor_obj));
}
}
}
*ctor = NULL;
return hres;
}

tmp = jsval_disp(disp);
hres = convert_to_proxy(ctx, &tmp);
if(FAILED(hres))
return hres;
*ctor = as_jsdisp(get_object(tmp));

hres = jsdisp_define_data_property(*ctor, L"prototype", 0, jsval_obj(prot));
hres = jsdisp_define_data_property(*ctor, L"prototype", 0, jsval_obj(jsdisp));
if(FAILED(hres))
jsdisp_release(*ctor);
return hres;
}

static HRESULT maybe_init_global_proxy(jsdisp_t *jsdisp)
{
script_ctx_t *ctx = jsdisp->ctx;
jsdisp_t *tmp = ctx->global;
HRESULT hres;

/* DefineConstructors may end up in CreateConstructor from GetDefaultConstructor via some
prototype's setup, which assumes the global to be the one required. Since we can have
window objects that are not the actual global (e.g. from iframe), set it temporarily. */
ctx->global = jsdisp;
hres = jsdisp->proxy->lpVtbl->DefineConstructors(jsdisp->proxy, &ctx->proxy_prototypes);
ctx->global = tmp;

if(hres == S_OK)
hres = set_js_globals(jsdisp);
return hres;
}

static inline jsdisp_t *impl_from_IWineDispatchProxyCbPrivate(IWineDispatchProxyCbPrivate *iface)
{
return impl_from_IDispatchEx((IDispatchEx*)iface);
Expand Down Expand Up @@ -2634,7 +2647,7 @@ static HRESULT WINAPI WineDispatchProxyCbPrivate_HostUpdated(IWineDispatchProxyC
jsdisp_t *This = impl_from_IWineDispatchProxyCbPrivate(iface);
script_ctx_t *ctx = get_script_ctx(script);
dispex_prop_t *prop, *end;
jsdisp_t *prot;
jsdisp_t *prot, *ctor;
HRESULT hres;
BOOL b;

Expand Down Expand Up @@ -2684,7 +2697,10 @@ static HRESULT WINAPI WineDispatchProxyCbPrivate_HostUpdated(IWineDispatchProxyC
alloc_proxy_prop(This, &info, &prop);
}

return maybe_init_global_proxy(This);
/* Populate the constructors on the window */
hres = get_proxy_default_constructor(ctx, This, &ctor);
assert(FAILED(hres) || ctor == NULL);
return hres;
}

static IDispatch* WINAPI WineDispatchProxyCbPrivate_CreateConstructor(IWineDispatchProxyCbPrivate *iface,
Expand Down Expand Up @@ -2721,8 +2737,10 @@ static HRESULT WINAPI WineDispatchProxyCbPrivate_DefineConstructor(IWineDispatch
if(ctor_disp)
hres = create_proxy_constructor(ctor_disp, name, prot, &ctor);
else {
/* The prototype's proxy should have already set up the constructor, so it can't fail */
val = jsval_disp(prot->proxy->lpVtbl->GetDefaultConstructor(prot->proxy, This->proxy, This->ctx->proxy_prototypes));
/* The prototype's proxy should have already set up the constructor, so this can't fail */
IDispatch *tmp_disp;
prot->proxy->lpVtbl->GetDefaultConstructor(prot->proxy, This->proxy, &tmp_disp);
val = jsval_disp(tmp_disp);
convert_to_proxy(This->ctx, &val);
ctor = as_jsdisp(get_object(val));
}
Expand Down Expand Up @@ -2897,7 +2915,7 @@ HRESULT convert_to_proxy(script_ctx_t *ctx, jsval_t *val)
{
IWineDispatchProxyCbPrivate **proxy_ref;
IWineDispatchProxyPrivate *proxy;
jsdisp_t *jsdisp, *prot;
jsdisp_t *jsdisp, *prot, *ctor;
IDispatch *obj;
HRESULT hres;

Expand Down Expand Up @@ -2934,15 +2952,11 @@ HRESULT convert_to_proxy(script_ctx_t *ctx, jsval_t *val)

*proxy_ref = (IWineDispatchProxyCbPrivate*)&jsdisp->IDispatchEx_iface;
jsdisp->proxy = proxy;
if(proxy->lpVtbl->IsPrototype(proxy)) {
jsdisp_t *ctor;
hres = get_proxy_default_constructor(ctx, jsdisp, &ctor);
if(SUCCEEDED(hres)) {
hres = jsdisp_define_data_property(jsdisp, L"constructor", PROPF_WRITABLE | PROPF_CONFIGURABLE, jsval_obj(ctor));
jsdisp_release(ctor);
}
}else {
hres = maybe_init_global_proxy(jsdisp);

hres = get_proxy_default_constructor(ctx, jsdisp, &ctor);
if(SUCCEEDED(hres) && ctor) {
hres = jsdisp_define_data_property(jsdisp, L"constructor", PROPF_WRITABLE | PROPF_CONFIGURABLE, jsval_obj(ctor));
jsdisp_release(ctor);
}
if(FAILED(hres)) {
*proxy_ref = NULL;
Expand Down
13 changes: 0 additions & 13 deletions dlls/jscript/jscript.c
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,6 @@ static void exec_queued_code(JScript *This)
static void decrease_state(JScript *This, SCRIPTSTATE state)
{
named_item_t *item, *item_next;
unsigned int i;

if(This->ctx) {
switch(This->ctx->state) {
Expand Down Expand Up @@ -504,18 +503,6 @@ static void decrease_state(JScript *This, SCRIPTSTATE state)
}
}

if(This->ctx->proxy_prototypes) {
for(i = 0; i < This->ctx->proxy_prototypes->num; i++) {
if(This->ctx->proxy_prototypes->disp[i].prototype)
IDispatch_Release(This->ctx->proxy_prototypes->disp[i].prototype);
if(This->ctx->proxy_prototypes->disp[i].ctor)
IDispatch_Release(This->ctx->proxy_prototypes->disp[i].ctor);
}

free(This->ctx->proxy_prototypes);
This->ctx->proxy_prototypes = NULL;
}

if(This->ctx->secmgr) {
IInternetHostSecurityManager_Release(This->ctx->secmgr);
This->ctx->secmgr = NULL;
Expand Down
16 changes: 2 additions & 14 deletions dlls/jscript/jscript.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,6 @@ typedef struct {

DEFINE_GUID(IID_nsXPCOMCycleCollectionParticipant, 0x9674489b,0x1f6f,0x4550,0xa7,0x30, 0xcc,0xae,0xdd,0x10,0x4c,0xf9);

struct proxy_prototypes
{
unsigned int num;
struct {
IDispatch *prototype;
IDispatch *ctor;
} disp[];
};

struct proxy_func_invoker
{
HRESULT (STDMETHODCALLTYPE *invoke)(IDispatch*,void*,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*);
Expand Down Expand Up @@ -113,10 +104,8 @@ struct proxy_cc_api
typedef struct {
IDispatchExVtbl dispex;
IWineDispatchProxyCbPrivate** (STDMETHODCALLTYPE *GetProxyFieldRef)(IWineDispatchProxyPrivate *This);
IDispatch* (STDMETHODCALLTYPE *GetDefaultPrototype)(IWineDispatchProxyPrivate *This, struct proxy_prototypes **prots_ref);
IDispatch* (STDMETHODCALLTYPE *GetDefaultConstructor)(IWineDispatchProxyPrivate *This, IWineDispatchProxyPrivate *window, struct proxy_prototypes *prots);
HRESULT (STDMETHODCALLTYPE *DefineConstructors)(IWineDispatchProxyPrivate *This, struct proxy_prototypes **prots_ref);
BOOL (STDMETHODCALLTYPE *IsPrototype)(IWineDispatchProxyPrivate *This);
IDispatch* (STDMETHODCALLTYPE *GetDefaultPrototype)(IWineDispatchProxyPrivate *This, IWineDispatchProxyPrivate *window);
HRESULT (STDMETHODCALLTYPE *GetDefaultConstructor)(IWineDispatchProxyPrivate *This, IWineDispatchProxyPrivate *window, IDispatch **ret);
BOOL (STDMETHODCALLTYPE *IsConstructor)(IWineDispatchProxyPrivate *This);
HRESULT (STDMETHODCALLTYPE *PropFixOverride)(IWineDispatchProxyPrivate *This, struct proxy_prop_info *info);
HRESULT (STDMETHODCALLTYPE *PropOverride)(IWineDispatchProxyPrivate *This, const WCHAR *name, VARIANT *value);
Expand Down Expand Up @@ -573,7 +562,6 @@ struct _script_ctx_t {
};
jsdisp_t *global_objects[26 + NUM_TYPEDARRAY_TYPES];
};
struct proxy_prototypes *proxy_prototypes;
};
C_ASSERT(RTL_SIZEOF_THROUGH_FIELD(script_ctx_t, weakmap_prototype) == RTL_SIZEOF_THROUGH_FIELD(script_ctx_t, global_objects));

Expand Down
Loading

0 comments on commit e4bf8b4

Please sign in to comment.