[PATCH 0/7] MR6015: jscript: Refactor indexed properties handling.
In preparation for host properties support. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/6015
From: Jacek Caban <jacek(a)codeweavers.com> --- dlls/jscript/dispex.c | 51 ++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index a678421f0a3..72af7054570 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -244,6 +244,34 @@ static dispex_prop_t *alloc_protref(jsdisp_t *This, const WCHAR *name, DWORD ref return ret; } +static HRESULT find_external_prop(jsdisp_t *This, const WCHAR *name, BOOL case_insens, dispex_prop_t **ret) +{ + dispex_prop_t *prop; + + if(This->builtin_info->idx_length) { + const WCHAR *ptr; + unsigned idx = 0; + + for(ptr = name; is_digit(*ptr) && idx < 0x10000; ptr++) + idx = idx*10 + (*ptr-'0'); + if(!*ptr && idx < This->builtin_info->idx_length(This)) { + unsigned flags = PROPF_ENUMERABLE; + if(This->builtin_info->idx_put) + flags |= PROPF_WRITABLE; + prop = alloc_prop(This, name, PROP_IDX, flags); + if(!prop) + return E_OUTOFMEMORY; + + prop->u.idx = idx; + *ret = prop; + return S_OK; + } + } + + *ret = NULL; + return S_OK; +} + static HRESULT find_prop_name(jsdisp_t *This, unsigned hash, const WCHAR *name, BOOL case_insens, dispex_prop_t **ret) { const builtin_prop_t *builtin; @@ -301,28 +329,7 @@ static HRESULT find_prop_name(jsdisp_t *This, unsigned hash, const WCHAR *name, return S_OK; } - if(This->builtin_info->idx_length) { - const WCHAR *ptr; - unsigned idx = 0; - - for(ptr = name; is_digit(*ptr) && idx < 0x10000; ptr++) - idx = idx*10 + (*ptr-'0'); - if(!*ptr && idx < This->builtin_info->idx_length(This)) { - unsigned flags = PROPF_ENUMERABLE; - if(This->builtin_info->idx_put) - flags |= PROPF_WRITABLE; - prop = alloc_prop(This, name, PROP_IDX, flags); - if(!prop) - return E_OUTOFMEMORY; - - prop->u.idx = idx; - *ret = prop; - return S_OK; - } - } - - *ret = NULL; - return S_OK; + return find_external_prop(This, name, case_insens, ret); } static HRESULT find_prop_name_prot(jsdisp_t *This, unsigned hash, const WCHAR *name, BOOL case_insens, dispex_prop_t **ret) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6015
From: Jacek Caban <jacek(a)codeweavers.com> --- dlls/jscript/dispex.c | 26 +++++++++++++------------- dlls/jscript/engine.c | 8 ++++---- dlls/jscript/function.c | 8 ++++---- dlls/jscript/jscript.h | 4 ++-- dlls/jscript/string.c | 4 ++-- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 72af7054570..ed1cf397927 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -36,7 +36,7 @@ typedef enum { PROP_PROTREF, PROP_ACCESSOR, PROP_DELETED, - PROP_IDX + PROP_EXTERN } prop_type_t; struct _dispex_prop_t { @@ -49,7 +49,7 @@ struct _dispex_prop_t { jsval_t val; const builtin_prop_t *p; DWORD ref; - unsigned idx; + unsigned id; struct { jsdisp_t *getter; jsdisp_t *setter; @@ -256,13 +256,13 @@ static HRESULT find_external_prop(jsdisp_t *This, const WCHAR *name, BOOL case_i idx = idx*10 + (*ptr-'0'); if(!*ptr && idx < This->builtin_info->idx_length(This)) { unsigned flags = PROPF_ENUMERABLE; - if(This->builtin_info->idx_put) + if(This->builtin_info->prop_put) flags |= PROPF_WRITABLE; - prop = alloc_prop(This, name, PROP_IDX, flags); + prop = alloc_prop(This, name, PROP_EXTERN, flags); if(!prop) return E_OUTOFMEMORY; - prop->u.idx = idx; + prop->u.id = idx; *ret = prop; return S_OK; } @@ -475,8 +475,8 @@ static HRESULT prop_get(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t *prop, hres = S_OK; } break; - case PROP_IDX: - hres = prop_obj->builtin_info->idx_get(prop_obj, prop->u.idx, r); + case PROP_EXTERN: + hres = prop_obj->builtin_info->prop_get(prop_obj, prop->u.id, r); break; default: ERR("type %d\n", prop->type); @@ -536,12 +536,12 @@ static HRESULT prop_put(jsdisp_t *This, dispex_prop_t *prop, jsval_t val) return S_OK; } return jsdisp_call_value(prop->u.accessor.setter, jsval_obj(This), DISPATCH_METHOD, 1, &val, NULL); - case PROP_IDX: - if(!This->builtin_info->idx_put) { - TRACE("no put_idx\n"); + case PROP_EXTERN: + if(!This->builtin_info->prop_put) { + TRACE("no prop_put\n"); return S_OK; } - return This->builtin_info->idx_put(This, prop->u.idx, val); + return This->builtin_info->prop_put(This, prop->u.id, val); default: ERR("type %d\n", prop->type); return E_FAIL; @@ -583,7 +583,7 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t flags, argc, argv, r, caller); } case PROP_ACCESSOR: - case PROP_IDX: { + case PROP_EXTERN: { jsval_t val; hres = prop_get(This, jsthis ? jsthis : (IDispatch *)&This->IDispatchEx_iface, prop, &val); @@ -2976,7 +2976,7 @@ HRESULT jsdisp_get_own_property(jsdisp_t *obj, const WCHAR *name, BOOL flags_onl switch(prop->type) { case PROP_BUILTIN: case PROP_JSVAL: - case PROP_IDX: + case PROP_EXTERN: desc->mask |= PROPF_WRITABLE; desc->explicit_value = TRUE; if(!flags_only) { diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index 60b479fb83b..2e52bb5ed2f 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -485,14 +485,14 @@ static unsigned scope_idx_length(jsdisp_t *dispex) return scope->detached_vars->argc; } -static HRESULT scope_idx_get(jsdisp_t *dispex, unsigned idx, jsval_t *r) +static HRESULT scope_prop_get(jsdisp_t *dispex, unsigned idx, jsval_t *r) { scope_chain_t *scope = scope_from_dispex(dispex); return jsval_copy(scope->detached_vars->var[idx], r); } -static HRESULT scope_idx_put(jsdisp_t *dispex, unsigned idx, jsval_t val) +static HRESULT scope_prop_put(jsdisp_t *dispex, unsigned idx, jsval_t val) { scope_chain_t *scope = scope_from_dispex(dispex); jsval_t copy, *ref; @@ -547,8 +547,8 @@ static const builtin_info_t scope_info = { JSCLASS_NONE, .destructor = scope_destructor, .idx_length = scope_idx_length, - .idx_get = scope_idx_get, - .idx_put = scope_idx_put, + .prop_get = scope_prop_get, + .prop_put = scope_prop_put, .gc_traverse = scope_gc_traverse }; diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 9c339b807f7..7f0779c2aff 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -132,7 +132,7 @@ static jsval_t *get_argument_ref(ArgumentsInstance *arguments, unsigned idx) return arguments->scope->detached_vars->var + idx; } -static HRESULT Arguments_idx_get(jsdisp_t *jsdisp, unsigned idx, jsval_t *r) +static HRESULT Arguments_prop_get(jsdisp_t *jsdisp, unsigned idx, jsval_t *r) { ArgumentsInstance *arguments = arguments_from_jsdisp(jsdisp); @@ -141,7 +141,7 @@ static HRESULT Arguments_idx_get(jsdisp_t *jsdisp, unsigned idx, jsval_t *r) return jsval_copy(*get_argument_ref(arguments, idx), r); } -static HRESULT Arguments_idx_put(jsdisp_t *jsdisp, unsigned idx, jsval_t val) +static HRESULT Arguments_prop_put(jsdisp_t *jsdisp, unsigned idx, jsval_t val) { ArgumentsInstance *arguments = arguments_from_jsdisp(jsdisp); jsval_t copy, *ref; @@ -187,8 +187,8 @@ static const builtin_info_t Arguments_info = { .call = Arguments_value, .destructor = Arguments_destructor, .idx_length = Arguments_idx_length, - .idx_get = Arguments_idx_get, - .idx_put = Arguments_idx_put, + .prop_get = Arguments_prop_get, + .prop_put = Arguments_prop_put, .gc_traverse = Arguments_gc_traverse }; diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 80641731006..7ee6949bdea 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -186,8 +186,8 @@ typedef struct { void (*destructor)(jsdisp_t*); void (*on_put)(jsdisp_t*,const WCHAR*); unsigned (*idx_length)(jsdisp_t*); - HRESULT (*idx_get)(jsdisp_t*,unsigned,jsval_t*); - HRESULT (*idx_put)(jsdisp_t*,unsigned,jsval_t); + HRESULT (*prop_get)(jsdisp_t*,unsigned,jsval_t*); + HRESULT (*prop_put)(jsdisp_t*,unsigned,jsval_t); HRESULT (*gc_traverse)(struct gc_ctx*,enum gc_traverse_op,jsdisp_t*); } builtin_info_t; diff --git a/dlls/jscript/string.c b/dlls/jscript/string.c index ab7497912f2..9e1b7aff11c 100644 --- a/dlls/jscript/string.c +++ b/dlls/jscript/string.c @@ -1515,7 +1515,7 @@ static unsigned String_idx_length(jsdisp_t *jsdisp) return string->dispex.ctx->version < 2 ? 0 : jsstr_length(string->str); } -static HRESULT String_idx_get(jsdisp_t *jsdisp, unsigned idx, jsval_t *r) +static HRESULT String_prop_get(jsdisp_t *jsdisp, unsigned idx, jsval_t *r) { StringInstance *string = string_from_jsdisp(jsdisp); jsstr_t *ret; @@ -1584,7 +1584,7 @@ static const builtin_info_t StringInst_info = { .props = StringInst_props, .destructor = String_destructor, .idx_length = String_idx_length, - .idx_get = String_idx_get, + .prop_get = String_prop_get, }; /* ECMA-262 3rd Edition 15.5.3.2 */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6015
From: Jacek Caban <jacek(a)codeweavers.com> And use it in find_external_prop. --- dlls/jscript/dispex.c | 42 +++++++++++++++++++++++++++++------------ dlls/jscript/engine.c | 8 ++++++++ dlls/jscript/function.c | 7 +++++++ dlls/jscript/jscript.h | 8 ++++++++ dlls/jscript/string.c | 29 ++++++++++++++++++++++------ 5 files changed, 76 insertions(+), 18 deletions(-) diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index ed1cf397927..0cb2c650407 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -248,21 +248,20 @@ static HRESULT find_external_prop(jsdisp_t *This, const WCHAR *name, BOOL case_i { dispex_prop_t *prop; - if(This->builtin_info->idx_length) { - const WCHAR *ptr; - unsigned idx = 0; - - for(ptr = name; is_digit(*ptr) && idx < 0x10000; ptr++) - idx = idx*10 + (*ptr-'0'); - if(!*ptr && idx < This->builtin_info->idx_length(This)) { - unsigned flags = PROPF_ENUMERABLE; - if(This->builtin_info->prop_put) - flags |= PROPF_WRITABLE; - prop = alloc_prop(This, name, PROP_EXTERN, flags); + if(This->builtin_info->lookup_prop) { + struct property_info desc; + HRESULT hres; + + hres = This->builtin_info->lookup_prop(This, name, &desc); + if(hres != DISP_E_UNKNOWNNAME) { + if(FAILED(hres)) + return hres; + + prop = alloc_prop(This, name, PROP_EXTERN, desc.flags); if(!prop) return E_OUTOFMEMORY; - prop->u.id = idx; + prop->u.id = desc.id; *ret = prop; return S_OK; } @@ -398,6 +397,25 @@ static HRESULT ensure_prop_name(jsdisp_t *This, const WCHAR *name, DWORD create_ return hres; } +HRESULT jsdisp_index_lookup(jsdisp_t *obj, const WCHAR *name, unsigned length, struct property_info *desc) +{ + const WCHAR *ptr; + unsigned idx = 0; + + for(ptr = name; is_digit(*ptr); ptr++) { + idx = idx * 10 + (*ptr - '0'); + if (idx >= length) + return DISP_E_UNKNOWNNAME; + } + if(*ptr) + return DISP_E_UNKNOWNNAME; + desc->id = idx; + desc->flags = PROPF_ENUMERABLE; + if(obj->builtin_info->prop_put) + desc->flags |= PROPF_WRITABLE; + return S_OK; +} + static IDispatch *get_this(DISPPARAMS *dp) { DWORD i; diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index 2e52bb5ed2f..d20939785fe 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -478,6 +478,13 @@ static void scope_destructor(jsdisp_t *dispex) IDispatch_Release(scope->obj); } +static HRESULT scope_lookup_prop(jsdisp_t *jsdisp, const WCHAR *name, struct property_info *desc) +{ + scope_chain_t *scope = scope_from_dispex(jsdisp); + + return jsdisp_index_lookup(&scope->dispex, name, scope->detached_vars->argc, desc); +} + static unsigned scope_idx_length(jsdisp_t *dispex) { scope_chain_t *scope = scope_from_dispex(dispex); @@ -546,6 +553,7 @@ static HRESULT scope_gc_traverse(struct gc_ctx *gc_ctx, enum gc_traverse_op op, static const builtin_info_t scope_info = { JSCLASS_NONE, .destructor = scope_destructor, + .lookup_prop = scope_lookup_prop, .idx_length = scope_idx_length, .prop_get = scope_prop_get, .prop_put = scope_prop_put, diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 7f0779c2aff..5af834769ff 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -117,6 +117,12 @@ static void Arguments_destructor(jsdisp_t *jsdisp) scope_release(arguments->scope); } +static HRESULT Arguments_lookup_prop(jsdisp_t *jsdisp, const WCHAR *name, struct property_info *desc) +{ + ArgumentsInstance *arguments = arguments_from_jsdisp(jsdisp); + return jsdisp_index_lookup(&arguments->jsdisp, name, arguments->argc, desc); +} + static unsigned Arguments_idx_length(jsdisp_t *jsdisp) { ArgumentsInstance *arguments = arguments_from_jsdisp(jsdisp); @@ -186,6 +192,7 @@ static const builtin_info_t Arguments_info = { .class = JSCLASS_ARGUMENTS, .call = Arguments_value, .destructor = Arguments_destructor, + .lookup_prop = Arguments_lookup_prop, .idx_length = Arguments_idx_length, .prop_get = Arguments_prop_get, .prop_put = Arguments_prop_put, diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 7ee6949bdea..a7a9f8cf6d4 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -178,6 +178,12 @@ typedef struct { builtin_setter_t setter; } builtin_prop_t; +struct property_info +{ + UINT32 id; + UINT32 flags; +}; + typedef struct { jsclass_t class; builtin_invoke_t call; @@ -186,6 +192,7 @@ typedef struct { void (*destructor)(jsdisp_t*); void (*on_put)(jsdisp_t*,const WCHAR*); unsigned (*idx_length)(jsdisp_t*); + HRESULT (*lookup_prop)(jsdisp_t*,const WCHAR*,struct property_info*); HRESULT (*prop_get)(jsdisp_t*,unsigned,jsval_t*); HRESULT (*prop_put)(jsdisp_t*,unsigned,jsval_t); HRESULT (*gc_traverse)(struct gc_ctx*,enum gc_traverse_op,jsdisp_t*); @@ -281,6 +288,7 @@ HRESULT jsdisp_get_id(jsdisp_t*,const WCHAR*,DWORD,DISPID*); HRESULT jsdisp_get_idx_id(jsdisp_t*,DWORD,DISPID*); HRESULT disp_delete(IDispatch*,DISPID,BOOL*); HRESULT disp_delete_name(script_ctx_t*,IDispatch*,jsstr_t*,BOOL*); +HRESULT jsdisp_index_lookup(jsdisp_t*,const WCHAR*,unsigned,struct property_info*); HRESULT jsdisp_delete_idx(jsdisp_t*,DWORD); HRESULT jsdisp_get_own_property(jsdisp_t*,const WCHAR*,BOOL,property_desc_t*); HRESULT jsdisp_define_property(jsdisp_t*,const WCHAR*,property_desc_t*); diff --git a/dlls/jscript/string.c b/dlls/jscript/string.c index 9e1b7aff11c..f5f01adf871 100644 --- a/dlls/jscript/string.c +++ b/dlls/jscript/string.c @@ -1501,6 +1501,22 @@ static void String_destructor(jsdisp_t *dispex) jsstr_release(This->str); } +static HRESULT String_lookup_prop(jsdisp_t *jsdisp, const WCHAR *name, struct property_info *desc) +{ + StringInstance *string = string_from_jsdisp(jsdisp); + + /* + * NOTE: For invoke version < 2, indexed array is not implemented at all. + * Newer jscript.dll versions implement it on string type, not class, + * which is not how it should work according to spec. IE9+ implements it + * properly. + */ + if(string->dispex.ctx->version < 2) + return DISP_E_UNKNOWNNAME; + + return jsdisp_index_lookup(&string->dispex, name, jsstr_length(string->str), desc); +} + static unsigned String_idx_length(jsdisp_t *jsdisp) { StringInstance *string = string_from_jsdisp(jsdisp); @@ -1579,12 +1595,13 @@ static const builtin_prop_t StringInst_props[] = { }; static const builtin_info_t StringInst_info = { - .class = JSCLASS_STRING, - .props_cnt = ARRAY_SIZE(StringInst_props), - .props = StringInst_props, - .destructor = String_destructor, - .idx_length = String_idx_length, - .prop_get = String_prop_get, + .class = JSCLASS_STRING, + .props_cnt = ARRAY_SIZE(StringInst_props), + .props = StringInst_props, + .destructor = String_destructor, + .lookup_prop = String_lookup_prop, + .idx_length = String_idx_length, + .prop_get = String_prop_get, }; /* ECMA-262 3rd Edition 15.5.3.2 */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6015
From: Jacek Caban <jacek(a)codeweavers.com> --- dlls/jscript/dispex.c | 45 +++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 0cb2c650407..ae81accb1b2 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -244,6 +244,30 @@ static dispex_prop_t *alloc_protref(jsdisp_t *This, const WCHAR *name, DWORD ref return ret; } +static dispex_prop_t *lookup_dispex_prop(jsdisp_t *obj, unsigned hash, const WCHAR *name, BOOL case_insens) +{ + unsigned bucket, pos, prev = ~0; + + bucket = get_props_idx(obj, hash); + pos = obj->props[bucket].bucket_head; + while(pos != ~0) { + if(case_insens ? !wcsicmp(name, obj->props[pos].name) : !wcscmp(name, obj->props[pos].name)) { + if(prev != ~0) { + obj->props[prev].bucket_next = obj->props[pos].bucket_next; + obj->props[pos].bucket_next = obj->props[bucket].bucket_head; + obj->props[bucket].bucket_head = pos; + } + + return &obj->props[pos]; + } + + prev = pos; + pos = obj->props[pos].bucket_next; + } + + return NULL; +} + static HRESULT find_external_prop(jsdisp_t *This, const WCHAR *name, BOOL case_insens, dispex_prop_t **ret) { dispex_prop_t *prop; @@ -274,26 +298,13 @@ static HRESULT find_external_prop(jsdisp_t *This, const WCHAR *name, BOOL case_i static HRESULT find_prop_name(jsdisp_t *This, unsigned hash, const WCHAR *name, BOOL case_insens, dispex_prop_t **ret) { const builtin_prop_t *builtin; - unsigned bucket, pos, prev = ~0; dispex_prop_t *prop; HRESULT hres; - bucket = get_props_idx(This, hash); - pos = This->props[bucket].bucket_head; - while(pos != ~0) { - if(case_insens ? !wcsicmp(name, This->props[pos].name) : !wcscmp(name, This->props[pos].name)) { - if(prev != ~0) { - This->props[prev].bucket_next = This->props[pos].bucket_next; - This->props[pos].bucket_next = This->props[bucket].bucket_head; - This->props[bucket].bucket_head = pos; - } - - *ret = &This->props[pos]; - return S_OK; - } - - prev = pos; - pos = This->props[pos].bucket_next; + prop = lookup_dispex_prop(This, hash, name, case_insens); + if(prop) { + *ret = prop; + return S_OK; } builtin = find_builtin_prop(This, name, case_insens); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6015
From: Jacek Caban <jacek(a)codeweavers.com> And use it instead of idx_length. --- dlls/jscript/dispex.c | 34 +++++++++++++++++++++++++++++----- dlls/jscript/engine.c | 8 -------- dlls/jscript/function.c | 6 +++--- dlls/jscript/jscript.h | 3 ++- dlls/jscript/string.c | 16 ++++++---------- 5 files changed, 40 insertions(+), 27 deletions(-) diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index ae81accb1b2..81fdc3d4799 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -427,6 +427,17 @@ HRESULT jsdisp_index_lookup(jsdisp_t *obj, const WCHAR *name, unsigned length, s return S_OK; } +HRESULT jsdisp_next_index(jsdisp_t *obj, unsigned length, unsigned id, struct property_info *desc) +{ + if(id + 1 == length) + return S_FALSE; + desc->id = id + 1; + desc->flags = PROPF_ENUMERABLE; + if(obj->builtin_info->prop_put) + desc->flags |= PROPF_WRITABLE; + return S_OK; +} + static IDispatch *get_this(DISPPARAMS *dp) { DWORD i; @@ -650,15 +661,28 @@ static HRESULT fill_props(jsdisp_t *obj) dispex_prop_t *prop; HRESULT hres; - if(obj->builtin_info->idx_length) { - unsigned i = 0, len = obj->builtin_info->idx_length(obj); + if(obj->builtin_info->next_prop) { + struct property_info desc; + unsigned id = ~0; WCHAR name[12]; - for(i = 0; i < len; i++) { - swprintf(name, ARRAY_SIZE(name), L"%u", i); - hres = find_prop_name(obj, string_hash(name), name, FALSE, &prop); + for(;;) { + hres = obj->builtin_info->next_prop(obj, id, &desc); if(FAILED(hres)) return hres; + if(hres == S_FALSE) + break; + + swprintf(name, ARRAYSIZE(name), L"%u", desc.id); + + prop = lookup_dispex_prop(obj, string_hash(name), name, FALSE); + if(!prop) { + prop = alloc_prop(obj, name, PROP_EXTERN, desc.flags); + if(!prop) + return E_OUTOFMEMORY; + prop->u.id = desc.id; + } + id = desc.id; } } diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index d20939785fe..e84d2f9b2d8 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -485,13 +485,6 @@ static HRESULT scope_lookup_prop(jsdisp_t *jsdisp, const WCHAR *name, struct pro return jsdisp_index_lookup(&scope->dispex, name, scope->detached_vars->argc, desc); } -static unsigned scope_idx_length(jsdisp_t *dispex) -{ - scope_chain_t *scope = scope_from_dispex(dispex); - - return scope->detached_vars->argc; -} - static HRESULT scope_prop_get(jsdisp_t *dispex, unsigned idx, jsval_t *r) { scope_chain_t *scope = scope_from_dispex(dispex); @@ -554,7 +547,6 @@ static const builtin_info_t scope_info = { JSCLASS_NONE, .destructor = scope_destructor, .lookup_prop = scope_lookup_prop, - .idx_length = scope_idx_length, .prop_get = scope_prop_get, .prop_put = scope_prop_put, .gc_traverse = scope_gc_traverse diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 5af834769ff..654bf12c7e9 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -123,10 +123,10 @@ static HRESULT Arguments_lookup_prop(jsdisp_t *jsdisp, const WCHAR *name, struct return jsdisp_index_lookup(&arguments->jsdisp, name, arguments->argc, desc); } -static unsigned Arguments_idx_length(jsdisp_t *jsdisp) +static HRESULT Arguments_next_prop(jsdisp_t *jsdisp, unsigned id, struct property_info *desc) { ArgumentsInstance *arguments = arguments_from_jsdisp(jsdisp); - return arguments->argc; + return jsdisp_next_index(&arguments->jsdisp, arguments->argc, id, desc); } static jsval_t *get_argument_ref(ArgumentsInstance *arguments, unsigned idx) @@ -193,7 +193,7 @@ static const builtin_info_t Arguments_info = { .call = Arguments_value, .destructor = Arguments_destructor, .lookup_prop = Arguments_lookup_prop, - .idx_length = Arguments_idx_length, + .next_prop = Arguments_next_prop, .prop_get = Arguments_prop_get, .prop_put = Arguments_prop_put, .gc_traverse = Arguments_gc_traverse diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index a7a9f8cf6d4..5adf2a2590a 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -191,8 +191,8 @@ typedef struct { const builtin_prop_t *props; void (*destructor)(jsdisp_t*); void (*on_put)(jsdisp_t*,const WCHAR*); - unsigned (*idx_length)(jsdisp_t*); HRESULT (*lookup_prop)(jsdisp_t*,const WCHAR*,struct property_info*); + HRESULT (*next_prop)(jsdisp_t*,unsigned,struct property_info*); HRESULT (*prop_get)(jsdisp_t*,unsigned,jsval_t*); HRESULT (*prop_put)(jsdisp_t*,unsigned,jsval_t); HRESULT (*gc_traverse)(struct gc_ctx*,enum gc_traverse_op,jsdisp_t*); @@ -289,6 +289,7 @@ HRESULT jsdisp_get_idx_id(jsdisp_t*,DWORD,DISPID*); HRESULT disp_delete(IDispatch*,DISPID,BOOL*); HRESULT disp_delete_name(script_ctx_t*,IDispatch*,jsstr_t*,BOOL*); HRESULT jsdisp_index_lookup(jsdisp_t*,const WCHAR*,unsigned,struct property_info*); +HRESULT jsdisp_next_index(jsdisp_t*,unsigned,unsigned,struct property_info*); HRESULT jsdisp_delete_idx(jsdisp_t*,DWORD); HRESULT jsdisp_get_own_property(jsdisp_t*,const WCHAR*,BOOL,property_desc_t*); HRESULT jsdisp_define_property(jsdisp_t*,const WCHAR*,property_desc_t*); diff --git a/dlls/jscript/string.c b/dlls/jscript/string.c index f5f01adf871..3cad5c55a79 100644 --- a/dlls/jscript/string.c +++ b/dlls/jscript/string.c @@ -1517,18 +1517,14 @@ static HRESULT String_lookup_prop(jsdisp_t *jsdisp, const WCHAR *name, struct pr return jsdisp_index_lookup(&string->dispex, name, jsstr_length(string->str), desc); } -static unsigned String_idx_length(jsdisp_t *jsdisp) +static HRESULT String_next_prop(jsdisp_t *jsdisp, unsigned id, struct property_info *desc) { StringInstance *string = string_from_jsdisp(jsdisp); - /* - * NOTE: For invoke version < 2, indexed array is not implemented at all. - * Newer jscript.dll versions implement it on string type, not class, - * which is not how it should work according to spec. IE9 implements it - * properly, but it uses its own JavaScript engine inside MSHTML. We - * implement it here, but in the way IE9 and spec work. - */ - return string->dispex.ctx->version < 2 ? 0 : jsstr_length(string->str); + if(string->dispex.ctx->version < 2) + return S_FALSE; + + return jsdisp_next_index(&string->dispex, jsstr_length(string->str), id, desc); } static HRESULT String_prop_get(jsdisp_t *jsdisp, unsigned idx, jsval_t *r) @@ -1600,7 +1596,7 @@ static const builtin_info_t StringInst_info = { .props = StringInst_props, .destructor = String_destructor, .lookup_prop = String_lookup_prop, - .idx_length = String_idx_length, + .next_prop = String_next_prop, .prop_get = String_prop_get, }; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6015
From: Jacek Caban <jacek(a)codeweavers.com> Based on patch by Gabriel Ivăncescu. --- dlls/jscript/dispex.c | 15 ++------------- dlls/jscript/error.c | 15 +++++++++++++++ dlls/jscript/jscript.h | 1 + 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 81fdc3d4799..e45e22f3a44 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -2496,19 +2496,8 @@ static HRESULT disp_invoke(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD f hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, flags, params, r, &ei, &err); } - if(hres == DISP_E_EXCEPTION) { - TRACE("DISP_E_EXCEPTION: %08lx %s %s\n", ei.scode, debugstr_w(ei.bstrSource), debugstr_w(ei.bstrDescription)); - reset_ei(ctx->ei); - ctx->ei->error = (SUCCEEDED(ei.scode) || ei.scode == DISP_E_EXCEPTION) ? E_FAIL : ei.scode; - if(ei.bstrSource) - ctx->ei->source = jsstr_alloc_len(ei.bstrSource, SysStringLen(ei.bstrSource)); - if(ei.bstrDescription) - ctx->ei->message = jsstr_alloc_len(ei.bstrDescription, SysStringLen(ei.bstrDescription)); - SysFreeString(ei.bstrSource); - SysFreeString(ei.bstrDescription); - SysFreeString(ei.bstrHelpFile); - } - + if(hres == DISP_E_EXCEPTION) + handle_dispatch_exception(ctx, &ei); return hres; } diff --git a/dlls/jscript/error.c b/dlls/jscript/error.c index e1f04aef38c..a3388ee9a27 100644 --- a/dlls/jscript/error.c +++ b/dlls/jscript/error.c @@ -402,6 +402,21 @@ HRESULT throw_error(script_ctx_t *ctx, HRESULT error, const WCHAR *str) return DISP_E_EXCEPTION; } +void handle_dispatch_exception(script_ctx_t *ctx, EXCEPINFO *ei) +{ + TRACE("%08lx %s %s\n", ei->scode, debugstr_w(ei->bstrSource), debugstr_w(ei->bstrDescription)); + + reset_ei(ctx->ei); + ctx->ei->error = (SUCCEEDED(ei->scode) || ei->scode == DISP_E_EXCEPTION) ? E_FAIL : ei->scode; + if(ei->bstrSource) + ctx->ei->source = jsstr_alloc_len(ei->bstrSource, SysStringLen(ei->bstrSource)); + if(ei->bstrDescription) + ctx->ei->message = jsstr_alloc_len(ei->bstrDescription, SysStringLen(ei->bstrDescription)); + SysFreeString(ei->bstrSource); + SysFreeString(ei->bstrDescription); + SysFreeString(ei->bstrHelpFile); +} + void set_error_location(jsexcept_t *ei, bytecode_t *code, unsigned loc, unsigned source_id, jsstr_t *line) { if(is_jscript_error(ei->error)) { diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 5adf2a2590a..e091e7acd90 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -312,6 +312,7 @@ struct _function_code_t *Function_get_code(jsdisp_t*); HRESULT throw_error(script_ctx_t*,HRESULT,const WCHAR*); jsdisp_t *create_builtin_error(script_ctx_t *ctx); +void handle_dispatch_exception(script_ctx_t *ctx, EXCEPINFO *ei); HRESULT create_object(script_ctx_t*,jsdisp_t*,jsdisp_t**); HRESULT create_math(script_ctx_t*,jsdisp_t**); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6015
From: Jacek Caban <jacek(a)codeweavers.com> --- dlls/jscript/dispex.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index e45e22f3a44..8813f6bb71a 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -608,7 +608,7 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t case PROP_BUILTIN: return JS_E_FUNCTION_EXPECTED; case PROP_PROTREF: - return invoke_prop_func(This->prototype, jsthis ? jsthis : (IDispatch *)&This->IDispatchEx_iface, + return invoke_prop_func(This->prototype, jsthis ? jsthis : to_disp(This), This->prototype->props+prop->u.ref, flags, argc, argv, r, caller); case PROP_JSVAL: { if(!is_object_instance(prop->u.val)) { @@ -619,20 +619,20 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t TRACE("call %s %p\n", debugstr_w(prop->name), get_object(prop->u.val)); return disp_call_value_with_caller(This->ctx, get_object(prop->u.val), - jsval_disp(jsthis ? jsthis : (IDispatch*)&This->IDispatchEx_iface), + jsval_disp(jsthis ? jsthis : to_disp(This)), flags, argc, argv, r, caller); } case PROP_ACCESSOR: case PROP_EXTERN: { jsval_t val; - hres = prop_get(This, jsthis ? jsthis : (IDispatch *)&This->IDispatchEx_iface, prop, &val); + hres = prop_get(This, jsthis ? jsthis : to_disp(This), prop, &val); if(FAILED(hres)) return hres; if(is_object_instance(val)) { hres = disp_call_value_with_caller(This->ctx, get_object(val), - jsval_disp(jsthis ? jsthis : (IDispatch*)&This->IDispatchEx_iface), + jsval_disp(jsthis ? jsthis : to_disp(This)), flags, argc, argv, r, caller); }else { FIXME("invoke %s\n", debugstr_jsval(val)); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/6015
Hi, It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated. The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=146876 Your paranoid android. === debian11 (build log) === error: patch failed: dlls/jscript/dispex.c:2496 error: patch failed: dlls/jscript/error.c:402 error: patch failed: dlls/jscript/jscript.h:312 Task: Patch failed to apply === debian11b (build log) === error: patch failed: dlls/jscript/dispex.c:2496 error: patch failed: dlls/jscript/error.c:402 error: patch failed: dlls/jscript/jscript.h:312 Task: Patch failed to apply
It's hard to say without seeing the rest, but are you sure this is going to end up with indexed props not having allocated props (PROP_EXTERN)? I mean that was one of the goals for Typed Arrays, even for enumerating. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/6015#note_75475
On Mon Jul 8 18:36:54 2024 +0000, Gabriel Ivăncescu wrote:
It's hard to say without seeing the rest, but are you sure this is going to end up with indexed props not having allocated props (PROP_EXTERN)? I mean that was one of the goals for Typed Arrays, even for enumerating. Specifically I am talking about needing `next_prop`, or is that temporary? Since we're returning the information needed to handle the property without relying on `dispex_prop_t`, it's a step in that direction (although I didn't actually try to implement that part).
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/6015#note_75478
participants (4)
-
Gabriel Ivăncescu -
Jacek Caban -
Jacek Caban (@jacek) -
Marvin