From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/arraybuf.c | 4 - dlls/jscript/dispex.c | 191 ++++++++++++++++++++++++++++---------- dlls/jscript/engine.c | 60 ++++++++---- dlls/jscript/enumerator.c | 2 - dlls/jscript/function.c | 97 +++++++++++++------ dlls/jscript/jscript.h | 21 ++++- dlls/jscript/jsregexp.c | 4 - dlls/jscript/set.c | 6 -- dlls/jscript/string.c | 72 +++++++++----- 9 files changed, 319 insertions(+), 138 deletions(-)
diff --git a/dlls/jscript/arraybuf.c b/dlls/jscript/arraybuf.c index ce0c482e914..697a9cbe7ad 100644 --- a/dlls/jscript/arraybuf.c +++ b/dlls/jscript/arraybuf.c @@ -641,8 +641,6 @@ static const builtin_info_t DataView_info = { dispex_prop_get_name, dispex_prop_define, NULL, - NULL, - NULL, DataView_gc_traverse };
@@ -660,8 +658,6 @@ static const builtin_info_t DataViewInst_info = { dispex_prop_get_name, dispex_prop_define, NULL, - NULL, - NULL, DataView_gc_traverse };
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 232c6034e3b..f64ebfcae8b 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -36,7 +36,6 @@ typedef enum { PROP_PROTREF, PROP_ACCESSOR, PROP_DELETED, - PROP_IDX } prop_type_t;
struct _dispex_prop_t { @@ -49,7 +48,6 @@ struct _dispex_prop_t { jsval_t val; const builtin_prop_t *p; DWORD ref; - unsigned idx; struct { jsdisp_t *getter; jsdisp_t *setter; @@ -74,7 +72,12 @@ static void fix_protref_prop(jsdisp_t *jsdisp, dispex_prop_t *prop) ref = prop->u.ref;
while((jsdisp = jsdisp->prototype)) { - if(ref >= jsdisp->prop_cnt || jsdisp->props[ref].type == PROP_DELETED) + if(ref >= jsdisp->prop_cnt) { + if(jsdisp->builtin_info->idx_length && indexed_prop_id_to_idx(ref + 1) < jsdisp->builtin_info->idx_length(jsdisp)) + return; + break; + } + if(jsdisp->props[ref].type == PROP_DELETED) break; if(jsdisp->props[ref].type != PROP_PROTREF) return; @@ -94,7 +97,7 @@ static inline BOOL is_dispid_prop(jsdisp_t *This, DISPID id) DWORD idx = prop_id_to_idx(id);
if(idx >= This->prop_cnt) - return FALSE; + return This->builtin_info->idx_length && indexed_prop_id_to_idx(id) < This->builtin_info->idx_length(This); fix_protref_prop(This, &This->props[idx]);
if(This->props[idx].type == PROP_DELETED) @@ -122,6 +125,8 @@ static BOOL is_enumerable(jsdisp_t *This, dispex_prop_t *prop)
if(prop->u.ref < This->prototype->prop_cnt) parent = &This->prototype->props[prop->u.ref]; + else if(This->prototype->builtin_info->idx_length && indexed_prop_id_to_idx(prop->u.ref + 1) < This->prototype->builtin_info->idx_length(This->prototype)) + return TRUE;
if(!parent || parent->type == PROP_DELETED) { prop->type = PROP_DELETED; @@ -313,15 +318,8 @@ static HRESULT find_prop_name(jsdisp_t *This, unsigned hash, const WCHAR *name, 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; - goto ret; + *ret = indexed_prop_idx_to_id(idx); + return S_OK; } }
@@ -339,7 +337,7 @@ static HRESULT find_prop_name_prot(jsdisp_t *This, unsigned hash, const WCHAR *n HRESULT hres;
hres = find_prop_name(This, hash, name, case_insens, ret); - if(FAILED(hres)) + if(FAILED(hres) || is_indexed_prop_id(*ret)) return hres;
if(hres == S_OK) { @@ -386,7 +384,7 @@ static HRESULT ensure_prop_name(jsdisp_t *This, const WCHAR *name, DWORD create_ HRESULT hres;
hres = find_prop_name_prot(This, string_hash(name), name, case_insens, ret); - if(hres != S_FALSE) + if(hres != S_FALSE || is_indexed_prop_id(*ret)) return hres;
if(is_dispex_prop_id(*ret)) { @@ -466,17 +464,14 @@ HRESULT builtin_set_const(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t value) HRESULT dispex_prop_get(jsdisp_t *jsdisp, IDispatch *jsthis, DISPID id, jsval_t *r) { dispex_prop_t *prop = &jsdisp->props[prop_id_to_idx(id)]; - jsdisp_t *prop_obj = jsdisp; HRESULT hres;
- while(prop->type == PROP_PROTREF) { - prop_obj = prop_obj->prototype; - prop = prop_obj->props + prop->u.ref; - } + if(prop->type == PROP_PROTREF) + return jsdisp->prototype->builtin_info->prop_get(jsdisp->prototype, jsthis, prop->u.ref + 1, r);
switch(prop->type) { case PROP_BUILTIN: - hres = prop->u.p->getter(jsdisp->ctx, prop_obj, r); + hres = prop->u.p->getter(jsdisp->ctx, jsdisp, r); break; case PROP_JSVAL: hres = jsval_copy(prop->u.val, r); @@ -490,9 +485,6 @@ HRESULT dispex_prop_get(jsdisp_t *jsdisp, IDispatch *jsthis, DISPID id, jsval_t hres = S_OK; } break; - case PROP_IDX: - hres = prop_obj->builtin_info->idx_get(prop_obj, prop->u.idx, r); - break; default: ERR("type %d\n", prop->type); return E_FAIL; @@ -518,6 +510,9 @@ HRESULT dispex_prop_put(jsdisp_t *jsdisp, DISPID id, jsval_t val)
do { prototype_iter = prototype_iter->prototype; + if(!is_dispex_prop_id(prop_iter->u.ref + 1)) + break; + prop_iter = prototype_iter->props + prop_iter->u.ref; } while(prop_iter->type == PROP_PROTREF);
@@ -552,12 +547,6 @@ HRESULT dispex_prop_put(jsdisp_t *jsdisp, DISPID id, jsval_t val) return S_OK; } return jsdisp_call_value(prop->u.accessor.setter, jsval_obj(jsdisp), DISPATCH_METHOD, 1, &val, NULL); - case PROP_IDX: - if(!jsdisp->builtin_info->idx_put) { - TRACE("no put_idx\n"); - return S_OK; - } - return jsdisp->builtin_info->idx_put(jsdisp, prop->u.idx, val); default: ERR("type %d\n", prop->type); return E_FAIL; @@ -596,8 +585,7 @@ HRESULT dispex_prop_invoke(jsdisp_t *jsdisp, IDispatch *jsthis, DISPID id, WORD jsval_disp(jsthis ? jsthis : (IDispatch*)&jsdisp->IDispatchEx_iface), flags, argc, argv, r, caller); } - case PROP_ACCESSOR: - case PROP_IDX: { + case PROP_ACCESSOR: { jsval_t val;
hres = dispex_prop_get(jsdisp, jsthis ? jsthis : (IDispatch*)&jsdisp->IDispatchEx_iface, id, &val); @@ -660,7 +648,6 @@ HRESULT dispex_prop_get_desc(jsdisp_t *jsdisp, DISPID id, BOOL flags_only, prope switch(prop->type) { case PROP_BUILTIN: case PROP_JSVAL: - case PROP_IDX: desc->explicit_value = TRUE; if(!flags_only) { hres = dispex_prop_get(jsdisp, to_disp(jsdisp), id, &desc->value); @@ -818,24 +805,108 @@ const WCHAR *dispex_prop_get_static_name(jsdisp_t *jsdisp, DISPID id) return jsdisp->props[prop_id_to_idx(id)].name; }
-static HRESULT fill_props(jsdisp_t *obj) +HRESULT indexed_prop_invoke(jsdisp_t *jsdisp, IDispatch *jsthis, DISPID id, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r, IServiceProvider *caller) { HRESULT hres; - DISPID id; + jsval_t val;
- if(obj->builtin_info->idx_length) { - unsigned i = 0, len = obj->builtin_info->idx_length(obj); - WCHAR name[12]; + if(is_dispex_prop_id(id)) + return dispex_prop_invoke(jsdisp, jsthis, id, flags, argc, argv, r, caller);
- for(i = 0; i < len; i++) { - swprintf(name, ARRAY_SIZE(name), L"%u", i); - hres = find_prop_name(obj, string_hash(name), name, FALSE, &id); + hres = jsdisp->builtin_info->prop_get(jsdisp, jsthis ? jsthis : (IDispatch*)&jsdisp->IDispatchEx_iface, id, &val); + if(FAILED(hres)) + return hres; + + if(is_object_instance(val)) { + hres = disp_call_value_with_caller(jsdisp->ctx, get_object(val), + jsval_disp(jsthis ? jsthis : (IDispatch*)&jsdisp->IDispatchEx_iface), + flags, argc, argv, r, caller); + }else { + FIXME("invoke %s\n", debugstr_jsval(val)); + hres = E_NOTIMPL; + } + + jsval_release(val); + return hres; +} + +HRESULT indexed_prop_delete(jsdisp_t *jsdisp, DISPID id, BOOL *ret) +{ + if(is_dispex_prop_id(id)) + return dispex_prop_delete(jsdisp, id, ret); + + /* indexed props are not configurable */ + *ret = FALSE; + return S_OK; +} + +void *indexed_prop_get_name(jsdisp_t *jsdisp, DISPID id, BOOL bstr) +{ + WCHAR buf[11]; + unsigned len; + + if(is_dispex_prop_id(id)) + return dispex_prop_get_name(jsdisp, id, bstr); + + len = swprintf(buf, ARRAY_SIZE(buf), L"%u", indexed_prop_id_to_idx(id)); + if(bstr) + return SysAllocStringLen(buf, len); + return jsstr_alloc_len(buf, len); +} + +HRESULT indexed_prop_define(jsdisp_t *jsdisp, DISPID id, const property_desc_t *desc) +{ + property_desc_t prop_desc; + WCHAR buf[11]; + HRESULT hres; + jsval_t val; + BOOL eq; + + if(is_dispex_prop_id(id)) + return dispex_prop_define(jsdisp, id, desc); + + TRACE("existing prop L"%lu" desc flags %x desc mask %x\n", indexed_prop_id_to_idx(id), desc->flags, desc->mask); + + if((desc->mask & desc->flags & (PROPF_CONFIGURABLE | PROPF_ENUMERABLE)) != (desc->mask & PROPF_ENUMERABLE)) { + hres = JS_E_NONCONFIGURABLE_REDEFINED; + goto throw; + } + + if(desc->explicit_value || (desc->mask & PROPF_WRITABLE)) { + if(jsdisp->builtin_info->prop_get_desc(jsdisp, id, TRUE, &prop_desc) == S_OK && !(prop_desc.flags & PROPF_WRITABLE)) { + if(desc->mask & desc->flags & PROPF_WRITABLE) { + hres = JS_E_NONWRITABLE_MODIFIED; + goto throw; + } + if(desc->explicit_value) { + hres = jsdisp->builtin_info->prop_get(jsdisp, to_disp(jsdisp), id, &val); + if(FAILED(hres)) + return hres; + hres = jsval_strict_equal(desc->value, val, &eq); + jsval_release(val); + if(FAILED(hres)) + return hres; + if(!eq) { + hres = JS_E_NONWRITABLE_MODIFIED; + goto throw; + } + } + }else if(desc->explicit_value) { + HRESULT hres = jsdisp->builtin_info->prop_put(jsdisp, id, desc->value); if(FAILED(hres)) return hres; } + }else if(desc->explicit_getter || desc->explicit_setter) { + hres = JS_E_NONCONFIGURABLE_REDEFINED; + goto throw; }
return S_OK; + +throw: + swprintf(buf, ARRAY_SIZE(buf), L"%u", indexed_prop_id_to_idx(id)); + return throw_error(jsdisp->ctx, hres, buf); }
static HRESULT fill_protref(jsdisp_t *This, unsigned hash, const WCHAR *name, DWORD ref) @@ -846,6 +917,8 @@ static HRESULT fill_protref(jsdisp_t *This, unsigned hash, const WCHAR *name, DW hres = find_prop_name(This, hash, name, FALSE, &id); if(hres != S_FALSE) return hres; + if(is_indexed_prop_id(id)) + return S_OK; if(is_dispex_prop_id(id)) { dispex_prop_t *p = &This->props[prop_id_to_idx(id)]; p->type = PROP_PROTREF; @@ -862,10 +935,6 @@ static HRESULT fill_protrefs(jsdisp_t *This) dispex_prop_t *iter; HRESULT hres;
- hres = fill_props(This); - if(FAILED(hres)) - return hres; - if(!This->prototype) return S_OK;
@@ -873,6 +942,18 @@ static HRESULT fill_protrefs(jsdisp_t *This) if(FAILED(hres)) return hres;
+ if(This->prototype->builtin_info->idx_length) { + DWORD i, len = This->prototype->builtin_info->idx_length(This->prototype); + WCHAR buf[11]; + + for(i = 0; i < len; i++) { + swprintf(buf, ARRAY_SIZE(buf), L"%u", i); + hres = fill_protref(This, string_hash(buf), buf, prop_id_to_idx(indexed_prop_idx_to_id(i))); + if(hres != S_OK) + return hres; + } + } + for(iter = This->prototype->props; iter < This->prototype->props+This->prototype->prop_cnt; iter++) { hres = fill_protref(This, iter->hash, iter->name, iter - This->prototype->props); if(hres != S_OK) @@ -3042,15 +3123,25 @@ HRESULT disp_delete(IDispatch *disp, DISPID id, BOOL *ret) HRESULT jsdisp_next_prop(jsdisp_t *obj, DISPID id, enum jsdisp_enum_type enum_type, DISPID *ret) { dispex_prop_t *iter; - DWORD idx = id; + BOOL fill = FALSE; HRESULT hres; + DWORD idx; + + id = (id == DISPID_STARTENUM) ? indexed_prop_idx_to_id(0) : id + 1; + if(is_indexed_prop_id(id)) { + if(obj->builtin_info->idx_length && indexed_prop_id_to_idx(id) < obj->builtin_info->idx_length(obj)) { + *ret = id; + return S_OK; + } + fill = TRUE; + id = 1; + } + idx = prop_id_to_idx(id);
- if(id == DISPID_STARTENUM || idx >= obj->prop_cnt) { - hres = (enum_type == JSDISP_ENUM_ALL) ? fill_protrefs(obj) : fill_props(obj); + if(fill || idx >= obj->prop_cnt) { + hres = (enum_type == JSDISP_ENUM_ALL) ? fill_protrefs(obj) : S_OK; if(FAILED(hres)) return hres; - if(id == DISPID_STARTENUM) - idx = 0; if(idx >= obj->prop_cnt) return S_FALSE; } diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index e8437780d1b..0062b9889f2 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -479,36 +479,60 @@ static void scope_destructor(jsdisp_t *dispex) free(scope); }
-static unsigned scope_idx_length(jsdisp_t *dispex) +static HRESULT scope_prop_get(jsdisp_t *dispex, IDispatch *jsthis, DISPID id, jsval_t *r) { scope_chain_t *scope = scope_from_dispex(dispex);
- return scope->detached_vars->argc; -} + if(is_dispex_prop_id(id)) + return dispex_prop_get(&scope->dispex, jsthis, id, r);
-static HRESULT scope_idx_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); + return jsval_copy(scope->detached_vars->var[indexed_prop_id_to_idx(id)], r); }
-static HRESULT scope_idx_put(jsdisp_t *dispex, unsigned idx, jsval_t val) +static HRESULT scope_prop_put(jsdisp_t *dispex, DISPID id, jsval_t val) { scope_chain_t *scope = scope_from_dispex(dispex); jsval_t copy, *ref; HRESULT hres;
+ if(is_dispex_prop_id(id)) + return dispex_prop_put(&scope->dispex, id, val); + hres = jsval_copy(val, ©); if(FAILED(hres)) return hres;
- ref = &scope->detached_vars->var[idx]; + ref = &scope->detached_vars->var[indexed_prop_id_to_idx(id)]; jsval_release(*ref); *ref = copy; return S_OK; }
+static HRESULT scope_prop_get_desc(jsdisp_t *dispex, DISPID id, BOOL flags_only, property_desc_t *desc) +{ + scope_chain_t *scope = scope_from_dispex(dispex); + + if(is_dispex_prop_id(id)) + return dispex_prop_get_desc(&scope->dispex, id, flags_only, desc); + + if(!flags_only) { + HRESULT hres = scope_prop_get(&scope->dispex, to_disp(&scope->dispex), id, &desc->value); + if(FAILED(hres)) + return hres; + } + + desc->explicit_value = TRUE; + desc->flags = PROPF_ENUMERABLE | PROPF_WRITABLE; + return S_OK; +} + +static unsigned scope_idx_length(jsdisp_t *dispex) +{ + scope_chain_t *scope = scope_from_dispex(dispex); + + return scope->detached_vars->argc; +} + static HRESULT scope_gc_traverse(struct gc_ctx *gc_ctx, enum gc_traverse_op op, jsdisp_t *dispex) { scope_chain_t *scope = scope_from_dispex(dispex); @@ -550,16 +574,14 @@ static const builtin_info_t scope_info = { 0, NULL, scope_destructor, - dispex_prop_get, - dispex_prop_put, - dispex_prop_invoke, - dispex_prop_delete, - dispex_prop_get_desc, - dispex_prop_get_name, - dispex_prop_define, + scope_prop_get, + scope_prop_put, + indexed_prop_invoke, + indexed_prop_delete, + scope_prop_get_desc, + indexed_prop_get_name, + indexed_prop_define, scope_idx_length, - scope_idx_get, - scope_idx_put, scope_gc_traverse };
diff --git a/dlls/jscript/enumerator.c b/dlls/jscript/enumerator.c index 1282882ae8f..b394beb15ec 100644 --- a/dlls/jscript/enumerator.c +++ b/dlls/jscript/enumerator.c @@ -210,8 +210,6 @@ static const builtin_info_t EnumeratorInst_info = { dispex_prop_get_name, dispex_prop_define, NULL, - NULL, - NULL, Enumerator_gc_traverse };
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 3b43b763512..3091a08f033 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -68,6 +68,7 @@ typedef struct { jsval_t *buf; scope_chain_t *scope; unsigned argc; + BYTE readonly_flags[]; } ArgumentsInstance;
static HRESULT create_bind_function(script_ctx_t*,FunctionInstance*,jsval_t,unsigned,jsval_t*,jsdisp_t**r); @@ -119,12 +120,6 @@ static void Arguments_destructor(jsdisp_t *jsdisp) free(arguments); }
-static unsigned Arguments_idx_length(jsdisp_t *jsdisp) -{ - ArgumentsInstance *arguments = arguments_from_jsdisp(jsdisp); - return arguments->argc; -} - static jsval_t *get_argument_ref(ArgumentsInstance *arguments, unsigned idx) { if(arguments->buf) @@ -134,22 +129,33 @@ 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, IDispatch *jsthis, DISPID id, jsval_t *r) { ArgumentsInstance *arguments = arguments_from_jsdisp(jsdisp); + DWORD idx = indexed_prop_id_to_idx(id); + + if(is_dispex_prop_id(id)) + return dispex_prop_get(&arguments->jsdisp, jsthis, id, r);
- TRACE("%p[%u]\n", arguments, idx); + TRACE("%p[%lu]\n", arguments, idx);
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, DISPID id, jsval_t val) { ArgumentsInstance *arguments = arguments_from_jsdisp(jsdisp); + DWORD idx = indexed_prop_id_to_idx(id); jsval_t copy, *ref; HRESULT hres;
- TRACE("%p[%u] = %s\n", arguments, idx, debugstr_jsval(val)); + if(is_dispex_prop_id(id)) + return dispex_prop_put(&arguments->jsdisp, id, val); + + TRACE("%p[%lu] = %s\n", arguments, idx, debugstr_jsval(val)); + + if(arguments->readonly_flags[idx / 8] & (1u << idx % 8)) + return S_OK;
hres = jsval_copy(val, ©); if(FAILED(hres)) @@ -161,6 +167,51 @@ static HRESULT Arguments_idx_put(jsdisp_t *jsdisp, unsigned idx, jsval_t val) return S_OK; }
+static HRESULT Arguments_prop_get_desc(jsdisp_t *jsdisp, DISPID id, BOOL flags_only, property_desc_t *desc) +{ + ArgumentsInstance *arguments = arguments_from_jsdisp(jsdisp); + DWORD idx = indexed_prop_id_to_idx(id); + + if(is_dispex_prop_id(id)) + return dispex_prop_get_desc(&arguments->jsdisp, id, flags_only, desc); + + if(!flags_only) { + HRESULT hres = Arguments_prop_get(&arguments->jsdisp, to_disp(&arguments->jsdisp), id, &desc->value); + if(FAILED(hres)) + return hres; + } + + desc->explicit_value = TRUE; + desc->flags = PROPF_ENUMERABLE; + if(!(arguments->readonly_flags[idx / 8] & (1u << idx % 8))) + desc->flags |= PROPF_WRITABLE; + + return S_OK; +} + +static HRESULT Arguments_prop_define(jsdisp_t *jsdisp, DISPID id, const property_desc_t *desc) +{ + ArgumentsInstance *arguments = arguments_from_jsdisp(jsdisp); + DWORD idx = indexed_prop_id_to_idx(id); + HRESULT hres; + + hres = indexed_prop_define(&arguments->jsdisp, id, desc); + if(FAILED(hres)) + return hres; + + /* Need to keep track of props made read-only */ + if((desc->mask & PROPF_WRITABLE) && !(desc->flags & PROPF_WRITABLE)) + arguments->readonly_flags[idx / 8] |= 1u << idx % 8; + + return hres; +} + +static unsigned Arguments_idx_length(jsdisp_t *jsdisp) +{ + ArgumentsInstance *arguments = arguments_from_jsdisp(jsdisp); + return arguments->argc; +} + static HRESULT Arguments_gc_traverse(struct gc_ctx *gc_ctx, enum gc_traverse_op op, jsdisp_t *jsdisp) { ArgumentsInstance *arguments = arguments_from_jsdisp(jsdisp); @@ -189,16 +240,14 @@ static const builtin_info_t Arguments_info = { Arguments_value, 0, NULL, Arguments_destructor, - dispex_prop_get, - dispex_prop_put, - dispex_prop_invoke, - dispex_prop_delete, - dispex_prop_get_desc, - dispex_prop_get_name, - dispex_prop_define, + Arguments_prop_get, + Arguments_prop_put, + indexed_prop_invoke, + indexed_prop_delete, + Arguments_prop_get_desc, + indexed_prop_get_name, + Arguments_prop_define, Arguments_idx_length, - Arguments_idx_get, - Arguments_idx_put, Arguments_gc_traverse };
@@ -207,7 +256,7 @@ HRESULT setup_arguments_object(script_ctx_t *ctx, call_frame_t *frame) ArgumentsInstance *args; HRESULT hres;
- args = calloc(1, sizeof(*args)); + args = calloc(1, FIELD_OFFSET(ArgumentsInstance, readonly_flags[(frame->argc + 7) / 8])); if(!args) return E_OUTOFMEMORY;
@@ -621,8 +670,6 @@ static const builtin_info_t Function_info = { dispex_prop_get_name, dispex_prop_define, NULL, - NULL, - NULL, Function_gc_traverse };
@@ -646,8 +693,6 @@ static const builtin_info_t FunctionInst_info = { dispex_prop_get_name, dispex_prop_define, NULL, - NULL, - NULL, Function_gc_traverse };
@@ -839,8 +884,6 @@ static const builtin_info_t InterpretedFunction_info = { dispex_prop_get_name, dispex_prop_define, NULL, - NULL, - NULL, Function_gc_traverse };
@@ -977,8 +1020,6 @@ static const builtin_info_t BindFunction_info = { dispex_prop_get_name, dispex_prop_define, NULL, - NULL, - NULL, Function_gc_traverse };
diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 70edb27447d..2c2868291c7 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -138,6 +138,10 @@ HRESULT dispex_prop_get_desc(jsdisp_t*,DISPID,BOOL,property_desc_t*); void *dispex_prop_get_name(jsdisp_t*,DISPID,BOOL); HRESULT dispex_prop_define(jsdisp_t*,DISPID,const property_desc_t*); const WCHAR *dispex_prop_get_static_name(jsdisp_t*,DISPID); +HRESULT indexed_prop_invoke(jsdisp_t*,IDispatch*,DISPID,WORD,unsigned,jsval_t*,jsval_t*,IServiceProvider*); +HRESULT indexed_prop_delete(jsdisp_t*,DISPID,BOOL*); +void *indexed_prop_get_name(jsdisp_t*,DISPID,BOOL); +HRESULT indexed_prop_define(jsdisp_t*,DISPID,const property_desc_t*);
struct thread_data { LONG ref; @@ -200,8 +204,6 @@ typedef struct { void *(*prop_get_name)(jsdisp_t*,DISPID,BOOL); HRESULT (*prop_define)(jsdisp_t*,DISPID,const property_desc_t*); unsigned (*idx_length)(jsdisp_t*); - HRESULT (*idx_get)(jsdisp_t*,unsigned,jsval_t*); - HRESULT (*idx_put)(jsdisp_t*,unsigned,jsval_t); HRESULT (*gc_traverse)(struct gc_ctx*,enum gc_traverse_op,jsdisp_t*); } builtin_info_t;
@@ -266,6 +268,21 @@ static inline BOOL is_dispex_prop_id(DISPID id) return id > 0; }
+static inline BOOL is_indexed_prop_id(DISPID id) +{ + return id < 0; +} + +static inline DWORD indexed_prop_id_to_idx(DISPID id) +{ + return (DWORD)id - 0x80000000u; +} + +static inline DISPID indexed_prop_idx_to_id(DWORD idx) +{ + return idx + 0x80000000u; +} + enum jsdisp_enum_type { JSDISP_ENUM_ALL, JSDISP_ENUM_OWN, diff --git a/dlls/jscript/jsregexp.c b/dlls/jscript/jsregexp.c index 02a35c09f71..c80dcd4ffd5 100644 --- a/dlls/jscript/jsregexp.c +++ b/dlls/jscript/jsregexp.c @@ -583,8 +583,6 @@ static const builtin_info_t RegExp_info = { dispex_prop_get_name, dispex_prop_define, NULL, - NULL, - NULL, RegExp_gc_traverse };
@@ -610,8 +608,6 @@ static const builtin_info_t RegExpInst_info = { dispex_prop_get_name, dispex_prop_define, NULL, - NULL, - NULL, RegExp_gc_traverse };
diff --git a/dlls/jscript/set.c b/dlls/jscript/set.c index 4310cd6f86c..78a38ef7cf0 100644 --- a/dlls/jscript/set.c +++ b/dlls/jscript/set.c @@ -429,8 +429,6 @@ static const builtin_info_t Map_info = { dispex_prop_get_name, dispex_prop_define, NULL, - NULL, - NULL, Map_gc_traverse };
@@ -600,8 +598,6 @@ static const builtin_info_t Set_info = { dispex_prop_get_name, dispex_prop_define, NULL, - NULL, - NULL, Map_gc_traverse };
@@ -909,8 +905,6 @@ static const builtin_info_t WeakMap_info = { dispex_prop_get_name, dispex_prop_define, NULL, - NULL, - NULL, WeakMap_gc_traverse };
diff --git a/dlls/jscript/string.c b/dlls/jscript/string.c index e3aa61483d1..40e416fc9aa 100644 --- a/dlls/jscript/string.c +++ b/dlls/jscript/string.c @@ -1502,6 +1502,48 @@ static void String_destructor(jsdisp_t *dispex) free(This); }
+static HRESULT String_prop_get(jsdisp_t *jsdisp, IDispatch *jsthis, DISPID id, jsval_t *r) +{ + StringInstance *string = string_from_jsdisp(jsdisp); + DWORD idx = indexed_prop_id_to_idx(id); + jsstr_t *ret; + + if(is_dispex_prop_id(id)) + return dispex_prop_get(&string->dispex, jsthis, id, r); + + ret = jsstr_substr(string->str, idx, 1); + if(!ret) + return E_OUTOFMEMORY; + + TRACE("%p[%lu] = %s\n", string, idx, debugstr_jsstr(ret)); + + *r = jsval_string(ret); + return S_OK; +} + +static HRESULT String_prop_put(jsdisp_t *jsdisp, DISPID id, jsval_t val) +{ + if(is_dispex_prop_id(id)) + return dispex_prop_put(jsdisp, id, val); + return S_OK; +} + +static HRESULT String_prop_get_desc(jsdisp_t *jsdisp, DISPID id, BOOL flags_only, property_desc_t *desc) +{ + if(is_dispex_prop_id(id)) + return dispex_prop_get_desc(jsdisp, id, flags_only, desc); + + if(!flags_only) { + HRESULT hres = String_prop_get(jsdisp, to_disp(jsdisp), id, &desc->value); + if(FAILED(hres)) + return hres; + } + + desc->explicit_value = TRUE; + desc->flags = PROPF_ENUMERABLE; + return S_OK; +} + static unsigned String_idx_length(jsdisp_t *jsdisp) { StringInstance *string = string_from_jsdisp(jsdisp); @@ -1516,21 +1558,6 @@ 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) -{ - StringInstance *string = string_from_jsdisp(jsdisp); - jsstr_t *ret; - - ret = jsstr_substr(string->str, idx, 1); - if(!ret) - return E_OUTOFMEMORY; - - TRACE("%p[%u] = %s\n", string, idx, debugstr_jsstr(ret)); - - *r = jsval_string(ret); - return S_OK; -} - static const builtin_prop_t String_props[] = { {L"anchor", String_anchor, PROPF_METHOD|1}, {L"big", String_big, PROPF_METHOD}, @@ -1593,15 +1620,14 @@ static const builtin_info_t StringInst_info = { ARRAY_SIZE(StringInst_props), StringInst_props, String_destructor, - dispex_prop_get, - dispex_prop_put, - dispex_prop_invoke, - dispex_prop_delete, - dispex_prop_get_desc, - dispex_prop_get_name, - dispex_prop_define, + String_prop_get, + String_prop_put, + indexed_prop_invoke, + indexed_prop_delete, + String_prop_get_desc, + indexed_prop_get_name, + indexed_prop_define, String_idx_length, - String_idx_get };
/* ECMA-262 3rd Edition 15.5.3.2 */