Module: wine Branch: master Commit: 78654e3890a0b1bb12a5e1fea2371789878c6a43 URL: https://gitlab.winehq.org/wine/wine/-/commit/78654e3890a0b1bb12a5e1fea237178...
Author: Jacek Caban jacek@codeweavers.com Date: Sun Jul 7 14:23:10 2024 +0200
jscript: Introduce lookup_prop callback.
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 */