-- v5: jscript: Remove PROP_IDX dispex props by handling them in object prop methods. jscript: Move filling the PROTREF into a helper. jscript: Simplify get_flags to only check whether it's enumerable. jscript: Get rid of on_put in the object vtbl. jscript: Inline prop_put. jscript: Inline prop_get. jscript: Inline invoke_prop_func and invoke PROTREFs using their vtbl method. jscript: Inline delete_prop. jscript: Use mandatory methods in the object vtbl to operate on props found jscript: Use mandatory methods in the object vtbl to operate on props mshtml/tests: Test redefining a writable indexed prop.
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/tests/es5.js | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 353d0b0b5c0..57fde4d7c9d 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -829,6 +829,16 @@ sync_test("defineProperty", function() { test_accessor_prop_desc(child.prototype, "funcprop_prot", desc); ok(obj.funcprop_prot(100) === 10, "obj.funcprop_prot() = " + obj.funcprop_prot(100));
+ (function() { + ok(arguments.length === 3, "arguments.length = " + arguments.length); + ok(arguments[0] === 1, "arguments[0] = " + arguments[0]); + ok(arguments[1] === 2, "arguments[1] = " + arguments[1]); + ok(arguments[2] === 3, "arguments[2] = " + arguments[2]); + Object.defineProperty(arguments, "1", {value: "foobar", writable: false, enumerable: true, configurable: false}); + test_own_data_prop_desc(arguments, "1", false, true, false); + ok(arguments[1] === "foobar", "arguments[1] after defineProperty = " + arguments[1]); + })(1, 2, 3); + expect_exception(function() { Object.defineProperty(null, "funcprop", desc); }, JS_E_OBJECT_EXPECTED);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/array.c | 21 ++++- dlls/jscript/arraybuf.c | 38 ++++++++- dlls/jscript/bool.c | 14 +++- dlls/jscript/date.c | 21 ++++- dlls/jscript/dispex.c | 165 +++++++++++++++++++++----------------- dlls/jscript/engine.c | 5 ++ dlls/jscript/enumerator.c | 19 ++++- dlls/jscript/error.c | 14 +++- dlls/jscript/function.c | 25 ++++++ dlls/jscript/global.c | 7 +- dlls/jscript/jscript.c | 7 +- dlls/jscript/jscript.h | 10 +++ dlls/jscript/json.c | 7 +- dlls/jscript/jsregexp.c | 17 +++- dlls/jscript/math.c | 7 +- dlls/jscript/number.c | 14 +++- dlls/jscript/object.c | 21 ++++- dlls/jscript/set.c | 36 ++++++++- dlls/jscript/string.c | 19 ++++- dlls/jscript/vbarray.c | 7 +- 20 files changed, 370 insertions(+), 104 deletions(-)
diff --git a/dlls/jscript/array.c b/dlls/jscript/array.c index 078e2ce7d4c..9b1ca03cfa5 100644 --- a/dlls/jscript/array.c +++ b/dlls/jscript/array.c @@ -1645,7 +1645,12 @@ static const builtin_info_t Array_info = { ARRAY_SIZE(Array_props), Array_props, Array_destructor, - Array_on_put + Array_on_put, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
static const builtin_prop_t ArrayInst_props[] = { @@ -1658,7 +1663,12 @@ static const builtin_info_t ArrayInst_info = { ARRAY_SIZE(ArrayInst_props), ArrayInst_props, Array_destructor, - Array_on_put + Array_on_put, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
/* ECMA-262 5.1 Edition 15.4.3.2 */ @@ -1766,7 +1776,12 @@ static const builtin_info_t ArrayConstr_info = { ARRAY_SIZE(ArrayConstr_props), ArrayConstr_props, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
HRESULT create_array_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret) diff --git a/dlls/jscript/arraybuf.c b/dlls/jscript/arraybuf.c index 62dfe614d65..014f2373fc6 100644 --- a/dlls/jscript/arraybuf.c +++ b/dlls/jscript/arraybuf.c @@ -126,7 +126,12 @@ static const builtin_info_t ArrayBuffer_info = { ARRAY_SIZE(ArrayBuffer_props), ArrayBuffer_props, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
static const builtin_prop_t ArrayBufferInst_props[] = { @@ -139,7 +144,12 @@ static const builtin_info_t ArrayBufferInst_info = { ARRAY_SIZE(ArrayBufferInst_props), ArrayBufferInst_props, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
static HRESULT create_arraybuf(script_ctx_t *ctx, DWORD size, ArrayBufferInstance **ret) @@ -219,7 +229,12 @@ static const builtin_info_t ArrayBufferConstr_info = { ARRAY_SIZE(ArrayBufferConstr_props), ArrayBufferConstr_props, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
static inline DataViewInstance *dataview_this(jsval_t vthis) @@ -616,6 +631,11 @@ static const builtin_info_t DataView_info = { DataView_props, DataView_destructor, NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, NULL, NULL, NULL, @@ -629,6 +649,11 @@ static const builtin_info_t DataViewInst_info = { NULL, DataView_destructor, NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, NULL, NULL, NULL, @@ -706,7 +731,12 @@ static const builtin_info_t DataViewConstr_info = { 0, NULL, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
HRESULT init_arraybuf_constructors(script_ctx_t *ctx) diff --git a/dlls/jscript/bool.c b/dlls/jscript/bool.c index 57c5cf5b4c6..574450ca898 100644 --- a/dlls/jscript/bool.c +++ b/dlls/jscript/bool.c @@ -124,7 +124,12 @@ static const builtin_info_t Bool_info = { ARRAY_SIZE(Bool_props), Bool_props, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
static const builtin_info_t BoolInst_info = { @@ -132,7 +137,12 @@ static const builtin_info_t BoolInst_info = { Bool_value, 0, NULL, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
static HRESULT BoolConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, diff --git a/dlls/jscript/date.c b/dlls/jscript/date.c index b1846fb3245..1006a82fab5 100644 --- a/dlls/jscript/date.c +++ b/dlls/jscript/date.c @@ -1905,7 +1905,12 @@ static const builtin_info_t Date_info = { ARRAY_SIZE(Date_props), Date_props, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
static const builtin_info_t DateInst_info = { @@ -1913,7 +1918,12 @@ static const builtin_info_t DateInst_info = { NULL, 0, NULL, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
static HRESULT create_date(script_ctx_t *ctx, jsdisp_t *object_prototype, DOUBLE time, DateInstance **ret) @@ -2441,7 +2451,12 @@ static const builtin_info_t DateConstr_info = { ARRAY_SIZE(DateConstr_props), DateConstr_props, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
HRESULT create_date_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret) diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 57882bf499e..baf6c6d9de8 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -60,6 +60,11 @@ struct _dispex_prop_t { int bucket_next; };
+static inline DWORD prop_id_to_idx(DISPID id) +{ + return id - 1; +} + static void fix_protref_prop(jsdisp_t *jsdisp, dispex_prop_t *prop) { DWORD ref; @@ -84,15 +89,17 @@ static inline DISPID prop_to_id(jsdisp_t *This, dispex_prop_t *prop) return prop - This->props + 1; }
-static inline dispex_prop_t *get_prop(jsdisp_t *This, DISPID id) +static inline BOOL is_dispid_prop(jsdisp_t *This, DISPID id) { - DWORD idx = id - 1; + DWORD idx = prop_id_to_idx(id);
if(idx >= This->prop_cnt) - return NULL; + return FALSE; fix_protref_prop(This, &This->props[idx]);
- return This->props[idx].type == PROP_DELETED ? NULL : &This->props[idx]; + if(This->props[idx].type == PROP_DELETED) + return FALSE; + return TRUE; }
static inline BOOL is_function_prop(dispex_prop_t *prop) @@ -603,12 +610,67 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t return E_FAIL; }
+static HRESULT delete_prop(dispex_prop_t *prop, BOOL *ret) +{ + if(prop->type == PROP_PROTREF) { + *ret = TRUE; + return S_OK; + } + + if(!(prop->flags & PROPF_CONFIGURABLE)) { + *ret = FALSE; + return S_OK; + } + + *ret = TRUE; + + if(prop->type == PROP_JSVAL) + jsval_release(prop->u.val); + if(prop->type == PROP_ACCESSOR) { + if(prop->u.accessor.getter) + jsdisp_release(prop->u.accessor.getter); + if(prop->u.accessor.setter) + jsdisp_release(prop->u.accessor.setter); + } + prop->type = PROP_DELETED; + return S_OK; +} + HRESULT builtin_set_const(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t value) { TRACE("%p %s\n", jsthis, debugstr_jsval(value)); return S_OK; }
+HRESULT dispex_prop_get(jsdisp_t *jsdisp, IDispatch *jsthis, DISPID id, jsval_t *r) +{ + return prop_get(jsdisp, jsthis, &jsdisp->props[prop_id_to_idx(id)], r); +} + +HRESULT dispex_prop_put(jsdisp_t *jsdisp, DISPID id, jsval_t val) +{ + return prop_put(jsdisp, &jsdisp->props[prop_id_to_idx(id)], val); +} + +HRESULT dispex_prop_invoke(jsdisp_t *jsdisp, IDispatch *jsthis, DISPID id, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r, IServiceProvider *caller) +{ + return invoke_prop_func(jsdisp, jsthis, &jsdisp->props[prop_id_to_idx(id)], flags, argc, argv, r, caller); +} + +HRESULT dispex_prop_delete(jsdisp_t *jsdisp, DISPID id, BOOL *ret) +{ + return delete_prop(&jsdisp->props[prop_id_to_idx(id)], ret); +} + +void *dispex_prop_get_name(jsdisp_t *jsdisp, DISPID id, BOOL bstr) +{ + const WCHAR *name = jsdisp->props[prop_id_to_idx(id)].name; + if(bstr) + return SysAllocString(name); + return jsstr_alloc(name); +} + static HRESULT fill_props(jsdisp_t *obj) { dispex_prop_t *prop; @@ -1916,7 +1978,6 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc { jsdisp_t *This = impl_from_IDispatchEx(iface); IServiceProvider *prev_caller; - dispex_prop_t *prop; jsexcept_t ei; HRESULT hres;
@@ -1925,8 +1986,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc if(pvarRes) V_VT(pvarRes) = VT_EMPTY;
- prop = get_prop(This, id); - if(!prop && id != DISPID_VALUE) { + if(!is_dispid_prop(This, id) && id != DISPID_VALUE) { TRACE("invalid id\n"); return DISP_E_MEMBERNOTFOUND; } @@ -1953,8 +2013,8 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc break;
passed_this = get_this(pdp); - if(prop) - hres = invoke_prop_func(This, passed_this, prop, wFlags, argc, argv, pvarRes ? &r : NULL, pspCaller); + if(id != DISPID_VALUE) + hres = This->builtin_info->prop_invoke(This, passed_this, id, wFlags, argc, argv, pvarRes ? &r : NULL, pspCaller); else hres = jsdisp_call_value(This, passed_this ? jsval_disp(passed_this) : jsval_undefined(), wFlags, argc, argv, pvarRes ? &r : NULL);
@@ -1971,8 +2031,8 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc case DISPATCH_PROPERTYGET: { jsval_t r;
- if(prop) - hres = prop_get(This, to_disp(This), prop, &r); + if(id != DISPID_VALUE) + hres = This->builtin_info->prop_get(This, to_disp(This), id, &r); else { hres = to_primitive(This->ctx, jsval_obj(This), &r, NO_HINT); if(hres == JS_E_TO_PRIMITIVE) @@ -1991,7 +2051,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc jsval_t val; DWORD i;
- if(!prop) { + if(id == DISPID_VALUE) { hres = DISP_E_MEMBERNOTFOUND; break; } @@ -2011,7 +2071,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc if(FAILED(hres)) break;
- hres = prop_put(This, prop, val); + This->builtin_info->prop_put(This, id, val); jsval_release(val); break; } @@ -2027,32 +2087,6 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc return leave_script(This->ctx, hres); }
-static HRESULT delete_prop(dispex_prop_t *prop, BOOL *ret) -{ - if(prop->type == PROP_PROTREF) { - *ret = TRUE; - return S_OK; - } - - if(!(prop->flags & PROPF_CONFIGURABLE)) { - *ret = FALSE; - return S_OK; - } - - *ret = TRUE; - - if(prop->type == PROP_JSVAL) - jsval_release(prop->u.val); - if(prop->type == PROP_ACCESSOR) { - if(prop->u.accessor.getter) - jsdisp_release(prop->u.accessor.getter); - if(prop->u.accessor.setter) - jsdisp_release(prop->u.accessor.setter); - } - prop->type = PROP_DELETED; - return S_OK; -} - static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) { jsdisp_t *This = impl_from_IDispatchEx(iface); @@ -2079,18 +2113,16 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bst static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id) { jsdisp_t *This = impl_from_IDispatchEx(iface); - dispex_prop_t *prop; BOOL b;
TRACE("(%p)->(%lx)\n", This, id);
- prop = get_prop(This, id); - if(!prop) { + if(!is_dispid_prop(This, id)) { WARN("invalid id\n"); return DISP_E_MEMBERNOTFOUND; }
- return delete_prop(prop, &b); + return This->builtin_info->prop_delete(This, id, &b); }
static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex) @@ -2103,15 +2135,13 @@ static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName) { jsdisp_t *This = impl_from_IDispatchEx(iface); - dispex_prop_t *prop;
TRACE("(%p)->(%lx %p)\n", This, id, pbstrName);
- prop = get_prop(This, id); - if(!prop) + if(!is_dispid_prop(This, id)) return DISP_E_MEMBERNOTFOUND;
- *pbstrName = SysAllocString(prop->name); + *pbstrName = This->builtin_info->prop_get_name(This, id, TRUE); if(!*pbstrName) return E_OUTOFMEMORY;
@@ -2209,7 +2239,12 @@ static const builtin_info_t dispex_info = { NULL, 0, NULL, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
HRESULT create_dispex(script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *prototype, jsdisp_t **dispex) @@ -2388,13 +2423,10 @@ HRESULT jsdisp_call_value(jsdisp_t *jsfunc, jsval_t vthis, WORD flags, unsigned
HRESULT jsdisp_call(jsdisp_t *disp, DISPID id, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - dispex_prop_t *prop; - - prop = get_prop(disp, id); - if(!prop) + if(!is_dispid_prop(disp, id)) return DISP_E_MEMBERNOTFOUND;
- return invoke_prop_func(disp, to_disp(disp), prop, flags, argc, argv, r, &disp->ctx->jscaller->IServiceProvider_iface); + return disp->builtin_info->prop_invoke(disp, to_disp(disp), id, flags, argc, argv, r, &disp->ctx->jscaller->IServiceProvider_iface); }
HRESULT jsdisp_call_name(jsdisp_t *disp, const WCHAR *name, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) @@ -2672,11 +2704,8 @@ HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t val)
jsdisp = iface_to_jsdisp(disp); if(jsdisp && jsdisp->ctx == ctx) { - dispex_prop_t *prop; - - prop = get_prop(jsdisp, id); - if(prop) - hres = prop_put(jsdisp, prop, val); + if(is_dispid_prop(jsdisp, id)) + hres = jsdisp->builtin_info->prop_put(jsdisp, id, val); else hres = DISP_E_MEMBERNOTFOUND;
@@ -2778,13 +2807,10 @@ HRESULT jsdisp_get_idx(jsdisp_t *obj, DWORD idx, jsval_t *r)
HRESULT jsdisp_propget(jsdisp_t *jsdisp, DISPID id, jsval_t *val) { - dispex_prop_t *prop; - - prop = get_prop(jsdisp, id); - if(!prop) + if(!is_dispid_prop(jsdisp, id)) return DISP_E_MEMBERNOTFOUND;
- return prop_get(jsdisp, to_disp(jsdisp), prop, val); + return jsdisp->builtin_info->prop_get(jsdisp, to_disp(jsdisp), id, val); }
HRESULT disp_propget(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t *val) @@ -2839,11 +2865,8 @@ HRESULT disp_delete(IDispatch *disp, DISPID id, BOOL *ret)
jsdisp = iface_to_jsdisp(disp); if(jsdisp) { - dispex_prop_t *prop; - - prop = get_prop(jsdisp, id); - if(prop) - hres = delete_prop(prop, ret); + if(is_dispid_prop(jsdisp, id)) + hres = jsdisp->builtin_info->prop_delete(jsdisp, id, ret); else hres = DISP_E_MEMBERNOTFOUND;
@@ -3199,11 +3222,9 @@ BOOL jsdisp_is_frozen(jsdisp_t *obj, BOOL sealed)
HRESULT jsdisp_get_prop_name(jsdisp_t *obj, DISPID id, jsstr_t **r) { - dispex_prop_t *prop = get_prop(obj, id); - - if(!prop) + if(!is_dispid_prop(obj, id)) return DISP_E_MEMBERNOTFOUND;
- *r = jsstr_alloc(prop->name); + *r = obj->builtin_info->prop_get_name(obj, id, FALSE); return *r ? S_OK : E_OUTOFMEMORY; } diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index 76e6a271bdf..091d7f2c072 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -551,6 +551,11 @@ static const builtin_info_t scope_info = { NULL, scope_destructor, NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, scope_idx_length, scope_idx_get, scope_idx_put, diff --git a/dlls/jscript/enumerator.c b/dlls/jscript/enumerator.c index d962c65d229..dcceafa01b5 100644 --- a/dlls/jscript/enumerator.c +++ b/dlls/jscript/enumerator.c @@ -187,7 +187,12 @@ static const builtin_info_t Enumerator_info = { ARRAY_SIZE(Enumerator_props), Enumerator_props, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
static const builtin_info_t EnumeratorInst_info = { @@ -197,6 +202,11 @@ static const builtin_info_t EnumeratorInst_info = { NULL, Enumerator_destructor, NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, NULL, NULL, NULL, @@ -329,7 +339,12 @@ static const builtin_info_t EnumeratorConstr_info = { 0, NULL, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
HRESULT create_enumerator_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret) diff --git a/dlls/jscript/error.c b/dlls/jscript/error.c index 81e3a3a9739..a3473a8cd86 100644 --- a/dlls/jscript/error.c +++ b/dlls/jscript/error.c @@ -144,7 +144,12 @@ static const builtin_info_t Error_info = { ARRAY_SIZE(Error_props), Error_props, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
static const builtin_info_t ErrorInst_info = { @@ -153,7 +158,12 @@ static const builtin_info_t ErrorInst_info = { 0, NULL, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
static HRESULT alloc_error(script_ctx_t *ctx, jsdisp_t *prototype, diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 68f841b38a1..7384dce26aa 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -190,6 +190,11 @@ static const builtin_info_t Arguments_info = { 0, NULL, Arguments_destructor, NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, Arguments_idx_length, Arguments_idx_get, Arguments_idx_put, @@ -608,6 +613,11 @@ static const builtin_info_t Function_info = { Function_props, Function_destructor, NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, NULL, NULL, NULL, @@ -627,6 +637,11 @@ static const builtin_info_t FunctionInst_info = { FunctionInst_props, Function_destructor, NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, NULL, NULL, NULL, @@ -814,6 +829,11 @@ static const builtin_info_t InterpretedFunction_info = { InterpretedFunction_props, Function_destructor, NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, NULL, NULL, NULL, @@ -946,6 +966,11 @@ static const builtin_info_t BindFunction_info = { BindFunction_props, Function_destructor, NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, NULL, NULL, NULL, diff --git a/dlls/jscript/global.c b/dlls/jscript/global.c index cc108b84e4b..9ca65c88224 100644 --- a/dlls/jscript/global.c +++ b/dlls/jscript/global.c @@ -910,7 +910,12 @@ static const builtin_info_t JSGlobal_info = { ARRAY_SIZE(JSGlobal_props), JSGlobal_props, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
static HRESULT init_object_prototype_accessors(script_ctx_t *ctx, jsdisp_t *object_prototype) diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index 6829f80f299..6eda89a3246 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -127,7 +127,12 @@ HRESULT create_named_item_script_obj(script_ctx_t *ctx, named_item_t *item) NULL, 0, NULL, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
return create_dispex(ctx, &disp_info, NULL, &item->script_obj); diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 1a9446893a1..a9819449c00 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -130,6 +130,11 @@ typedef HRESULT (*builtin_getter_t)(script_ctx_t*,jsdisp_t*,jsval_t*); typedef HRESULT (*builtin_setter_t)(script_ctx_t*,jsdisp_t*,jsval_t);
HRESULT builtin_set_const(script_ctx_t*,jsdisp_t*,jsval_t); +HRESULT dispex_prop_get(jsdisp_t*,IDispatch*,DISPID,jsval_t*); +HRESULT dispex_prop_put(jsdisp_t*,DISPID,jsval_t); +HRESULT dispex_prop_invoke(jsdisp_t*,IDispatch*,DISPID,WORD,unsigned,jsval_t*,jsval_t*,IServiceProvider*); +HRESULT dispex_prop_delete(jsdisp_t*,DISPID,BOOL*); +void *dispex_prop_get_name(jsdisp_t*,DISPID,BOOL);
struct thread_data { LONG ref; @@ -185,6 +190,11 @@ typedef struct { const builtin_prop_t *props; void (*destructor)(jsdisp_t*); void (*on_put)(jsdisp_t*,const WCHAR*); + HRESULT (*prop_get)(jsdisp_t*,IDispatch*,DISPID,jsval_t*); + HRESULT (*prop_put)(jsdisp_t*,DISPID,jsval_t); + HRESULT (*prop_invoke)(jsdisp_t*,IDispatch*,DISPID,WORD,unsigned,jsval_t*,jsval_t*,IServiceProvider*); + HRESULT (*prop_delete)(jsdisp_t*,DISPID,BOOL*); + void *(*prop_get_name)(jsdisp_t*,DISPID,BOOL); unsigned (*idx_length)(jsdisp_t*); HRESULT (*idx_get)(jsdisp_t*,unsigned,jsval_t*); HRESULT (*idx_put)(jsdisp_t*,unsigned,jsval_t); diff --git a/dlls/jscript/json.c b/dlls/jscript/json.c index 277a5e01144..9087a48a827 100644 --- a/dlls/jscript/json.c +++ b/dlls/jscript/json.c @@ -953,7 +953,12 @@ static const builtin_info_t JSON_info = { ARRAY_SIZE(JSON_props), JSON_props, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
HRESULT create_json(script_ctx_t *ctx, jsdisp_t **ret) diff --git a/dlls/jscript/jsregexp.c b/dlls/jscript/jsregexp.c index 70673ec190e..48257f03ee5 100644 --- a/dlls/jscript/jsregexp.c +++ b/dlls/jscript/jsregexp.c @@ -576,6 +576,11 @@ static const builtin_info_t RegExp_info = { RegExp_props, RegExp_destructor, NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, NULL, NULL, NULL, @@ -597,6 +602,11 @@ static const builtin_info_t RegExpInst_info = { RegExpInst_props, RegExp_destructor, NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, NULL, NULL, NULL, @@ -966,7 +976,12 @@ static const builtin_info_t RegExpConstr_info = { ARRAY_SIZE(RegExpConstr_props), RegExpConstr_props, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
HRESULT create_regexp_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret) diff --git a/dlls/jscript/math.c b/dlls/jscript/math.c index 362b877cb5e..2401acaf62d 100644 --- a/dlls/jscript/math.c +++ b/dlls/jscript/math.c @@ -496,7 +496,12 @@ static const builtin_info_t Math_info = { ARRAY_SIZE(Math_props), Math_props, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
HRESULT create_math(script_ctx_t *ctx, jsdisp_t **ret) diff --git a/dlls/jscript/number.c b/dlls/jscript/number.c index 27c3d5ecfee..ff2d73f5722 100644 --- a/dlls/jscript/number.c +++ b/dlls/jscript/number.c @@ -591,7 +591,12 @@ static const builtin_info_t Number_info = { ARRAY_SIZE(Number_props), Number_props, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
static const builtin_info_t NumberInst_info = { @@ -599,7 +604,12 @@ static const builtin_info_t NumberInst_info = { NULL, 0, NULL, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
static HRESULT NumberConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, diff --git a/dlls/jscript/object.c b/dlls/jscript/object.c index 16ecc3dea3c..1053f5d27c8 100644 --- a/dlls/jscript/object.c +++ b/dlls/jscript/object.c @@ -470,7 +470,12 @@ static const builtin_info_t Object_info = { ARRAY_SIZE(Object_props), Object_props, Object_destructor, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
static const builtin_info_t ObjectInst_info = { @@ -478,7 +483,12 @@ static const builtin_info_t ObjectInst_info = { NULL, 0, NULL, Object_destructor, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
static void release_property_descriptor(property_desc_t *desc) @@ -1074,7 +1084,12 @@ static const builtin_info_t ObjectConstr_info = { ARRAY_SIZE(ObjectConstr_props), ObjectConstr_props, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
static HRESULT ObjectConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, diff --git a/dlls/jscript/set.c b/dlls/jscript/set.c index 7e49e31a5d5..1f7f8f2be20 100644 --- a/dlls/jscript/set.c +++ b/dlls/jscript/set.c @@ -406,7 +406,12 @@ static const builtin_info_t Map_prototype_info = { ARRAY_SIZE(Map_prototype_props), Map_prototype_props, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
static const builtin_info_t Map_info = { @@ -416,6 +421,11 @@ static const builtin_info_t Map_info = { Map_props, Map_destructor, NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, NULL, NULL, NULL, @@ -565,7 +575,12 @@ static const builtin_info_t Set_prototype_info = { ARRAY_SIZE(Set_prototype_props), Set_prototype_props, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
static const builtin_info_t Set_info = { @@ -575,6 +590,11 @@ static const builtin_info_t Set_info = { Map_props, Map_destructor, NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, NULL, NULL, NULL, @@ -862,7 +882,12 @@ static const builtin_info_t WeakMap_prototype_info = { ARRAY_SIZE(WeakMap_prototype_props), WeakMap_prototype_props, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
static const builtin_info_t WeakMap_info = { @@ -872,6 +897,11 @@ static const builtin_info_t WeakMap_info = { NULL, WeakMap_destructor, NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, NULL, NULL, NULL, diff --git a/dlls/jscript/string.c b/dlls/jscript/string.c index 4033f0a2b56..0ab9df0a588 100644 --- a/dlls/jscript/string.c +++ b/dlls/jscript/string.c @@ -1574,7 +1574,12 @@ static const builtin_info_t String_info = { ARRAY_SIZE(String_props), String_props, String_destructor, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
static const builtin_prop_t StringInst_props[] = { @@ -1588,6 +1593,11 @@ static const builtin_info_t StringInst_info = { StringInst_props, String_destructor, NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, String_idx_length, String_idx_get }; @@ -1708,7 +1718,12 @@ static const builtin_info_t StringConstr_info = { ARRAY_SIZE(StringConstr_props), StringConstr_props, NULL, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
HRESULT create_string_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret) diff --git a/dlls/jscript/vbarray.c b/dlls/jscript/vbarray.c index 998dc230818..3cfa84d8de7 100644 --- a/dlls/jscript/vbarray.c +++ b/dlls/jscript/vbarray.c @@ -252,7 +252,12 @@ static const builtin_info_t VBArray_info = { ARRAY_SIZE(VBArray_props), VBArray_props, VBArray_destructor, - NULL + NULL, + dispex_prop_get, + dispex_prop_put, + dispex_prop_invoke, + dispex_prop_delete, + dispex_prop_get_name, };
static HRESULT alloc_vbarray(script_ctx_t *ctx, jsdisp_t *object_prototype, VBArrayInstance **ret)
From: Gabriel Ivăncescu gabrielopcode@gmail.com
is_dispex_prop_id will be more useful later when we'll also have indexed props with their own vtbl, for now it avoids DISPID_VALUE.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/array.c | 6 + dlls/jscript/arraybuf.c | 12 + dlls/jscript/bool.c | 4 + dlls/jscript/date.c | 6 + dlls/jscript/dispex.c | 526 ++++++++++++++++++++------------------ dlls/jscript/engine.c | 2 + dlls/jscript/enumerator.c | 6 + dlls/jscript/error.c | 4 + dlls/jscript/function.c | 10 + dlls/jscript/global.c | 2 + dlls/jscript/jscript.c | 2 + dlls/jscript/jscript.h | 9 + dlls/jscript/json.c | 2 + dlls/jscript/jsregexp.c | 6 + dlls/jscript/math.c | 2 + dlls/jscript/number.c | 4 + dlls/jscript/object.c | 6 + dlls/jscript/set.c | 12 + dlls/jscript/string.c | 6 + dlls/jscript/vbarray.c | 2 + 20 files changed, 377 insertions(+), 252 deletions(-)
diff --git a/dlls/jscript/array.c b/dlls/jscript/array.c index 9b1ca03cfa5..6d2bbd7e32e 100644 --- a/dlls/jscript/array.c +++ b/dlls/jscript/array.c @@ -1650,7 +1650,9 @@ static const builtin_info_t Array_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
static const builtin_prop_t ArrayInst_props[] = { @@ -1668,7 +1670,9 @@ static const builtin_info_t ArrayInst_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
/* ECMA-262 5.1 Edition 15.4.3.2 */ @@ -1781,7 +1785,9 @@ static const builtin_info_t ArrayConstr_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
HRESULT create_array_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret) diff --git a/dlls/jscript/arraybuf.c b/dlls/jscript/arraybuf.c index 014f2373fc6..cd92fb47924 100644 --- a/dlls/jscript/arraybuf.c +++ b/dlls/jscript/arraybuf.c @@ -131,7 +131,9 @@ static const builtin_info_t ArrayBuffer_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
static const builtin_prop_t ArrayBufferInst_props[] = { @@ -149,7 +151,9 @@ static const builtin_info_t ArrayBufferInst_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
static HRESULT create_arraybuf(script_ctx_t *ctx, DWORD size, ArrayBufferInstance **ret) @@ -234,7 +238,9 @@ static const builtin_info_t ArrayBufferConstr_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
static inline DataViewInstance *dataview_this(jsval_t vthis) @@ -635,7 +641,9 @@ static const builtin_info_t DataView_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, NULL, NULL, NULL, @@ -653,7 +661,9 @@ static const builtin_info_t DataViewInst_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, NULL, NULL, NULL, @@ -736,7 +746,9 @@ static const builtin_info_t DataViewConstr_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
HRESULT init_arraybuf_constructors(script_ctx_t *ctx) diff --git a/dlls/jscript/bool.c b/dlls/jscript/bool.c index 574450ca898..51a51cd48de 100644 --- a/dlls/jscript/bool.c +++ b/dlls/jscript/bool.c @@ -129,7 +129,9 @@ static const builtin_info_t Bool_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
static const builtin_info_t BoolInst_info = { @@ -142,7 +144,9 @@ static const builtin_info_t BoolInst_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
static HRESULT BoolConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, diff --git a/dlls/jscript/date.c b/dlls/jscript/date.c index 1006a82fab5..f712a7f5805 100644 --- a/dlls/jscript/date.c +++ b/dlls/jscript/date.c @@ -1910,7 +1910,9 @@ static const builtin_info_t Date_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
static const builtin_info_t DateInst_info = { @@ -1923,7 +1925,9 @@ static const builtin_info_t DateInst_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
static HRESULT create_date(script_ctx_t *ctx, jsdisp_t *object_prototype, DOUBLE time, DateInstance **ret) @@ -2456,7 +2460,9 @@ static const builtin_info_t DateConstr_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
HRESULT create_date_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret) diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index baf6c6d9de8..ecba9522f39 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -251,7 +251,7 @@ static dispex_prop_t *alloc_protref(jsdisp_t *This, const WCHAR *name, DWORD ref return ret; }
-static HRESULT find_prop_name(jsdisp_t *This, unsigned hash, const WCHAR *name, BOOL case_insens, dispex_prop_t **ret) +static HRESULT find_prop_name(jsdisp_t *This, unsigned hash, const WCHAR *name, BOOL case_insens, DISPID *ret) { const builtin_prop_t *builtin; unsigned bucket, pos, prev = ~0; @@ -268,8 +268,8 @@ static HRESULT find_prop_name(jsdisp_t *This, unsigned hash, const WCHAR *name, This->props[bucket].bucket_head = pos; }
- *ret = &This->props[pos]; - return S_OK; + prop = &This->props[pos]; + goto ret; }
prev = pos; @@ -294,8 +294,7 @@ static HRESULT find_prop_name(jsdisp_t *This, unsigned hash, const WCHAR *name,
prop->type = PROP_JSVAL; prop->u.val = jsval_obj(obj); - *ret = prop; - return S_OK; + goto ret; }else if(builtin->setter) flags |= PROPF_WRITABLE; flags &= PROPF_ENUMERABLE | PROPF_WRITABLE | PROPF_CONFIGURABLE; @@ -304,8 +303,7 @@ static HRESULT find_prop_name(jsdisp_t *This, unsigned hash, const WCHAR *name, return E_OUTOFMEMORY;
prop->u.p = builtin; - *ret = prop; - return S_OK; + goto ret; }
if(This->builtin_info->idx_length) { @@ -323,79 +321,89 @@ static HRESULT find_prop_name(jsdisp_t *This, unsigned hash, const WCHAR *name, return E_OUTOFMEMORY;
prop->u.idx = idx; - *ret = prop; - return S_OK; + goto ret; } }
- *ret = NULL; - return S_OK; + *ret = 0; + return S_FALSE; + +ret: + *ret = prop_to_id(This, prop); + return prop->type != PROP_DELETED ? S_OK : S_FALSE; }
-static HRESULT find_prop_name_prot(jsdisp_t *This, unsigned hash, const WCHAR *name, BOOL case_insens, dispex_prop_t **ret) +static HRESULT find_prop_name_prot(jsdisp_t *This, unsigned hash, const WCHAR *name, BOOL case_insens, DISPID *ret) { - dispex_prop_t *prop, *del=NULL; + dispex_prop_t *prop, *del = NULL; HRESULT hres;
- hres = find_prop_name(This, hash, name, case_insens, &prop); + hres = find_prop_name(This, hash, name, case_insens, ret); if(FAILED(hres)) return hres; - if(prop && prop->type==PROP_DELETED) { - del = prop; - } else if(prop) { + + if(hres == S_OK) { + prop = &This->props[prop_id_to_idx(*ret)]; fix_protref_prop(This, prop); - *ret = prop; - return S_OK; + return prop->type != PROP_DELETED ? S_OK : S_FALSE; }
+ if(is_dispex_prop_id(*ret)) + del = &This->props[prop_id_to_idx(*ret)]; + if(This->prototype) { - hres = find_prop_name_prot(This->prototype, hash, name, case_insens, &prop); + hres = find_prop_name_prot(This->prototype, hash, name, case_insens, ret); if(FAILED(hres)) return hres; - if(prop && prop->type != PROP_DELETED) { + if(hres == S_OK) { if(del) { del->type = PROP_PROTREF; - del->u.ref = prop - This->prototype->props; + del->u.ref = prop_id_to_idx(*ret); prop = del; }else { - prop = alloc_protref(This, prop->name, prop - This->prototype->props); + prop = alloc_protref(This, name, prop_id_to_idx(*ret)); if(!prop) return E_OUTOFMEMORY; } - - *ret = prop; - return S_OK; + goto ret; } }
- *ret = del; - return S_OK; + if(!del) { + *ret = 0; + return S_FALSE; + } + prop = del; + +ret: + *ret = prop_to_id(This, prop); + return prop->type != PROP_DELETED ? S_OK : S_FALSE; }
-static HRESULT ensure_prop_name(jsdisp_t *This, const WCHAR *name, DWORD create_flags, BOOL case_insens, dispex_prop_t **ret) +static HRESULT ensure_prop_name(jsdisp_t *This, const WCHAR *name, DWORD create_flags, BOOL case_insens, DISPID *ret) { dispex_prop_t *prop; HRESULT hres;
- hres = find_prop_name_prot(This, string_hash(name), name, case_insens, &prop); - if(SUCCEEDED(hres) && (!prop || prop->type == PROP_DELETED)) { - TRACE("creating prop %s flags %lx\n", debugstr_w(name), create_flags); - - if(prop) { - prop->type = PROP_JSVAL; - prop->flags = create_flags; - prop->u.val = jsval_undefined(); - }else { - prop = alloc_prop(This, name, PROP_JSVAL, create_flags); - if(!prop) - return E_OUTOFMEMORY; - } + hres = find_prop_name_prot(This, string_hash(name), name, case_insens, ret); + if(hres != S_FALSE) + return hres;
- prop->u.val = jsval_undefined(); + if(is_dispex_prop_id(*ret)) { + prop = &This->props[prop_id_to_idx(*ret)]; + prop->type = PROP_JSVAL; + prop->flags = create_flags; + }else { + prop = alloc_prop(This, name, PROP_JSVAL, create_flags); + if(!prop) + return E_OUTOFMEMORY; }
- *ret = prop; - return hres; + TRACE("creating prop %s flags %lx\n", debugstr_w(name), create_flags); + + prop->u.val = jsval_undefined(); + *ret = prop_to_id(This, prop); + return S_OK; }
static IDispatch *get_this(DISPPARAMS *dp) @@ -663,6 +671,38 @@ HRESULT dispex_prop_delete(jsdisp_t *jsdisp, DISPID id, BOOL *ret) return delete_prop(&jsdisp->props[prop_id_to_idx(id)], ret); }
+HRESULT dispex_prop_get_desc(jsdisp_t *jsdisp, DISPID id, BOOL flags_only, property_desc_t *desc) +{ + dispex_prop_t *prop = &jsdisp->props[prop_id_to_idx(id)]; + HRESULT hres; + + 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); + if(FAILED(hres)) + return hres; + } + break; + case PROP_ACCESSOR: + desc->mask = PROPF_ENUMERABLE | PROPF_CONFIGURABLE; + desc->explicit_getter = desc->explicit_setter = TRUE; + if(!flags_only) { + desc->getter = prop->u.accessor.getter ? jsdisp_addref(prop->u.accessor.getter) : NULL; + desc->setter = prop->u.accessor.setter ? jsdisp_addref(prop->u.accessor.setter) : NULL; + } + break; + default: + return DISP_E_UNKNOWNNAME; + } + + desc->flags = prop->flags & (PROPF_ENUMERABLE | PROPF_WRITABLE | PROPF_CONFIGURABLE); + return S_OK; +} + void *dispex_prop_get_name(jsdisp_t *jsdisp, DISPID id, BOOL bstr) { const WCHAR *name = jsdisp->props[prop_id_to_idx(id)].name; @@ -671,10 +711,131 @@ void *dispex_prop_get_name(jsdisp_t *jsdisp, DISPID id, BOOL bstr) return jsstr_alloc(name); }
+HRESULT dispex_prop_define(jsdisp_t *jsdisp, DISPID id, const property_desc_t *desc) +{ + dispex_prop_t *prop = &jsdisp->props[prop_id_to_idx(id)]; + script_ctx_t *ctx = jsdisp->ctx; + HRESULT hres; + + if(prop->type == PROP_DELETED || prop->type == PROP_PROTREF) { + if(prop->type == PROP_PROTREF && !jsdisp->extensible) + return throw_error(ctx, JS_E_OBJECT_NONEXTENSIBLE, prop->name); + + prop->flags = desc->flags; + if(desc->explicit_getter || desc->explicit_setter) { + prop->type = PROP_ACCESSOR; + prop->u.accessor.getter = desc->getter ? jsdisp_addref(desc->getter) : NULL; + prop->u.accessor.setter = desc->setter ? jsdisp_addref(desc->setter) : NULL; + TRACE("%s = accessor { get: %p set: %p }\n", debugstr_w(prop->name), + prop->u.accessor.getter, prop->u.accessor.setter); + }else { + prop->type = PROP_JSVAL; + if(desc->explicit_value) { + hres = jsval_copy(desc->value, &prop->u.val); + if(FAILED(hres)) + return hres; + }else { + prop->u.val = jsval_undefined(); + } + TRACE("%s = %s\n", debugstr_w(prop->name), debugstr_jsval(prop->u.val)); + } + return S_OK; + } + + TRACE("existing prop %s prop flags %lx desc flags %x desc mask %x\n", debugstr_w(prop->name), + prop->flags, desc->flags, desc->mask); + + if(!(prop->flags & PROPF_CONFIGURABLE)) { + if(((desc->mask & PROPF_CONFIGURABLE) && (desc->flags & PROPF_CONFIGURABLE)) + || ((desc->mask & PROPF_ENUMERABLE) + && ((desc->flags & PROPF_ENUMERABLE) != (prop->flags & PROPF_ENUMERABLE)))) + return throw_error(ctx, JS_E_NONCONFIGURABLE_REDEFINED, prop->name); + } + + if(desc->explicit_value || (desc->mask & PROPF_WRITABLE)) { + if(prop->type == PROP_ACCESSOR) { + if(!(prop->flags & PROPF_CONFIGURABLE)) + return throw_error(ctx, JS_E_NONCONFIGURABLE_REDEFINED, prop->name); + if(prop->u.accessor.getter) + jsdisp_release(prop->u.accessor.getter); + if(prop->u.accessor.setter) + jsdisp_release(prop->u.accessor.setter); + + prop->type = PROP_JSVAL; + hres = jsval_copy(desc->value, &prop->u.val); + if(FAILED(hres)) { + prop->u.val = jsval_undefined(); + return hres; + } + }else { + if(!(prop->flags & PROPF_CONFIGURABLE) && !(prop->flags & PROPF_WRITABLE)) { + if((desc->mask & PROPF_WRITABLE) && (desc->flags & PROPF_WRITABLE)) + return throw_error(ctx, JS_E_NONWRITABLE_MODIFIED, prop->name); + if(desc->explicit_value) { + if(prop->type == PROP_JSVAL) { + BOOL eq; + hres = jsval_strict_equal(desc->value, prop->u.val, &eq); + if(FAILED(hres)) + return hres; + if(!eq) + return throw_error(ctx, JS_E_NONWRITABLE_MODIFIED, prop->name); + }else { + FIXME("redefinition of property type %d\n", prop->type); + } + } + } + if(desc->explicit_value) { + if(prop->type == PROP_JSVAL) + jsval_release(prop->u.val); + else + prop->type = PROP_JSVAL; + hres = jsval_copy(desc->value, &prop->u.val); + if(FAILED(hres)) { + prop->u.val = jsval_undefined(); + return hres; + } + } + } + }else if(desc->explicit_getter || desc->explicit_setter) { + if(prop->type != PROP_ACCESSOR) { + if(!(prop->flags & PROPF_CONFIGURABLE)) + return throw_error(ctx, JS_E_NONCONFIGURABLE_REDEFINED, prop->name); + if(prop->type == PROP_JSVAL) + jsval_release(prop->u.val); + prop->type = PROP_ACCESSOR; + prop->u.accessor.getter = prop->u.accessor.setter = NULL; + }else if(!(prop->flags & PROPF_CONFIGURABLE)) { + if((desc->explicit_getter && desc->getter != prop->u.accessor.getter) + || (desc->explicit_setter && desc->setter != prop->u.accessor.setter)) + return throw_error(ctx, JS_E_NONCONFIGURABLE_REDEFINED, prop->name); + } + + if(desc->explicit_getter) { + if(prop->u.accessor.getter) { + jsdisp_release(prop->u.accessor.getter); + prop->u.accessor.getter = NULL; + } + if(desc->getter) + prop->u.accessor.getter = jsdisp_addref(desc->getter); + } + if(desc->explicit_setter) { + if(prop->u.accessor.setter) { + jsdisp_release(prop->u.accessor.setter); + prop->u.accessor.setter = NULL; + } + if(desc->setter) + prop->u.accessor.setter = jsdisp_addref(desc->setter); + } + } + + prop->flags = (prop->flags & ~desc->mask) | (desc->flags & desc->mask); + return S_OK; +} + static HRESULT fill_props(jsdisp_t *obj) { - dispex_prop_t *prop; HRESULT hres; + DISPID id;
if(obj->builtin_info->idx_length) { unsigned i = 0, len = obj->builtin_info->idx_length(obj); @@ -682,7 +843,7 @@ static HRESULT fill_props(jsdisp_t *obj)
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); + hres = find_prop_name(obj, string_hash(name), name, FALSE, &id); if(FAILED(hres)) return hres; } @@ -693,8 +854,9 @@ static HRESULT fill_props(jsdisp_t *obj)
static HRESULT fill_protrefs(jsdisp_t *This) { - dispex_prop_t *iter, *prop; + dispex_prop_t *iter; HRESULT hres; + DISPID id;
hres = fill_props(This); if(FAILED(hres)) @@ -708,18 +870,17 @@ static HRESULT fill_protrefs(jsdisp_t *This) return hres;
for(iter = This->prototype->props; iter < This->prototype->props+This->prototype->prop_cnt; iter++) { - hres = find_prop_name(This, iter->hash, iter->name, FALSE, &prop); + hres = find_prop_name(This, iter->hash, iter->name, FALSE, &id); if(FAILED(hres)) return hres; - if(!prop || prop->type==PROP_DELETED) { - if(prop) { - prop->type = PROP_PROTREF; - prop->flags = 0; - prop->u.ref = iter - This->prototype->props; - }else { - prop = alloc_protref(This, iter->name, iter - This->prototype->props); - if(!prop) - return E_OUTOFMEMORY; + if(hres != S_OK) { + if(is_dispex_prop_id(id)) { + dispex_prop_t *p = &This->props[prop_id_to_idx(id)]; + p->type = PROP_PROTREF; + p->flags = 0; + p->u.ref = iter - This->prototype->props; + }else if(!alloc_protref(This, iter->name, iter - This->prototype->props)) { + return E_OUTOFMEMORY; } } } @@ -2090,7 +2251,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) { jsdisp_t *This = impl_from_IDispatchEx(iface); - dispex_prop_t *prop; + DISPID id; BOOL b; HRESULT hres;
@@ -2099,15 +2260,15 @@ static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bst if(grfdex & ~(fdexNameCaseSensitive|fdexNameCaseInsensitive|fdexNameEnsure|fdexNameImplicit|FDEX_VERSION_MASK)) FIXME("Unsupported grfdex %lx\n", grfdex);
- hres = find_prop_name(This, string_hash(bstrName), bstrName, grfdex & fdexNameCaseInsensitive, &prop); + hres = find_prop_name(This, string_hash(bstrName), bstrName, grfdex & fdexNameCaseInsensitive, &id); if(FAILED(hres)) return hres; - if(!prop) { + if(hres != S_OK) { TRACE("not found\n"); return S_OK; }
- return delete_prop(prop, &b); + return This->builtin_info->prop_delete(This, id, &b); }
static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id) @@ -2244,7 +2405,9 @@ static const builtin_info_t dispex_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
HRESULT create_dispex(script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *prototype, jsdisp_t **dispex) @@ -2332,14 +2495,14 @@ void jsdisp_release(jsdisp_t *jsdisp) HRESULT init_dispex_from_constr(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *constr) { jsdisp_t *prot = NULL; - dispex_prop_t *prop; HRESULT hres; + DISPID id;
- hres = find_prop_name_prot(constr, string_hash(L"prototype"), L"prototype", FALSE, &prop); - if(SUCCEEDED(hres) && prop && prop->type!=PROP_DELETED) { + hres = find_prop_name_prot(constr, string_hash(L"prototype"), L"prototype", FALSE, &id); + if(hres == S_OK) { jsval_t val;
- hres = prop_get(constr, to_disp(constr), prop, &val); + hres = constr->builtin_info->prop_get(constr, to_disp(constr), id, &val); if(FAILED(hres)) { ERR("Could not get prototype\n"); return hres; @@ -2369,21 +2532,18 @@ jsdisp_t *iface_to_jsdisp(IDispatch *iface)
HRESULT jsdisp_get_id(jsdisp_t *jsdisp, const WCHAR *name, DWORD flags, DISPID *id) { - dispex_prop_t *prop; HRESULT hres;
if(jsdisp->extensible && (flags & fdexNameEnsure)) hres = ensure_prop_name(jsdisp, name, PROPF_ENUMERABLE | PROPF_CONFIGURABLE | PROPF_WRITABLE, - flags & fdexNameCaseInsensitive, &prop); + flags & fdexNameCaseInsensitive, id); else - hres = find_prop_name_prot(jsdisp, string_hash(name), name, flags & fdexNameCaseInsensitive, &prop); + hres = find_prop_name_prot(jsdisp, string_hash(name), name, flags & fdexNameCaseInsensitive, id); if(FAILED(hres)) return hres;
- if(prop && prop->type!=PROP_DELETED) { - *id = prop_to_id(jsdisp, prop); + if(hres == S_OK) return S_OK; - }
TRACE("not found %s\n", debugstr_w(name)); *id = DISPID_UNKNOWN; @@ -2431,17 +2591,14 @@ HRESULT jsdisp_call(jsdisp_t *disp, DISPID id, WORD flags, unsigned argc, jsval_
HRESULT jsdisp_call_name(jsdisp_t *disp, const WCHAR *name, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - dispex_prop_t *prop; HRESULT hres; + DISPID id;
- hres = find_prop_name_prot(disp, string_hash(name), name, FALSE, &prop); - if(FAILED(hres)) - return hres; - - if(!prop || prop->type == PROP_DELETED) - return JS_E_INVALID_PROPERTY; + hres = find_prop_name_prot(disp, string_hash(name), name, FALSE, &id); + if(hres != S_OK) + return FAILED(hres) ? hres : JS_E_INVALID_PROPERTY;
- return invoke_prop_func(disp, to_disp(disp), prop, flags, argc, argv, r, &disp->ctx->jscaller->IServiceProvider_iface); + return disp->builtin_info->prop_invoke(disp, to_disp(disp), id, flags, argc, argv, r, &disp->ctx->jscaller->IServiceProvider_iface); }
static HRESULT disp_invoke(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, DISPPARAMS *params, VARIANT *r, @@ -2669,19 +2826,19 @@ HRESULT disp_call_value_with_caller(script_ctx_t *ctx, IDispatch *disp, jsval_t
HRESULT jsdisp_propput(jsdisp_t *obj, const WCHAR *name, DWORD flags, BOOL throw, jsval_t val) { - dispex_prop_t *prop; HRESULT hres; + DISPID id;
if(obj->extensible) - hres = ensure_prop_name(obj, name, flags, FALSE, &prop); + hres = ensure_prop_name(obj, name, flags, FALSE, &id); else - hres = find_prop_name(obj, string_hash(name), name, FALSE, &prop); + hres = find_prop_name(obj, string_hash(name), name, FALSE, &id); if(FAILED(hres)) return hres; - if(!prop || (prop->type == PROP_DELETED && !obj->extensible)) + if(hres != S_OK && (!id || !obj->extensible)) return throw ? JS_E_INVALID_ACTION : S_OK;
- return prop_put(obj, prop, val); + return obj->builtin_info->prop_put(obj, id, val); }
HRESULT jsdisp_propput_name(jsdisp_t *obj, const WCHAR *name, jsval_t val) @@ -2770,39 +2927,39 @@ HRESULT disp_propput_name(script_ctx_t *ctx, IDispatch *disp, const WCHAR *name,
HRESULT jsdisp_propget_name(jsdisp_t *obj, const WCHAR *name, jsval_t *val) { - dispex_prop_t *prop; HRESULT hres; + DISPID id;
- hres = find_prop_name_prot(obj, string_hash(name), name, FALSE, &prop); + hres = find_prop_name_prot(obj, string_hash(name), name, FALSE, &id); if(FAILED(hres)) return hres;
- if(!prop || prop->type==PROP_DELETED) { + if(hres != S_OK) { *val = jsval_undefined(); return S_OK; }
- return prop_get(obj, to_disp(obj), prop, val); + return obj->builtin_info->prop_get(obj, to_disp(obj), id, val); }
HRESULT jsdisp_get_idx(jsdisp_t *obj, DWORD idx, jsval_t *r) { WCHAR name[12]; - dispex_prop_t *prop; HRESULT hres; + DISPID id;
swprintf(name, ARRAY_SIZE(name), L"%d", idx);
- hres = find_prop_name_prot(obj, string_hash(name), name, FALSE, &prop); + hres = find_prop_name_prot(obj, string_hash(name), name, FALSE, &id); if(FAILED(hres)) return hres;
- if(!prop || prop->type==PROP_DELETED) { + if(hres != S_OK) { *r = jsval_undefined(); return DISP_E_UNKNOWNNAME; }
- return prop_get(obj, to_disp(obj), prop, r); + return obj->builtin_info->prop_get(obj, to_disp(obj), id, r); }
HRESULT jsdisp_propget(jsdisp_t *jsdisp, DISPID id, jsval_t *val) @@ -2841,17 +2998,17 @@ HRESULT disp_propget(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t *val HRESULT jsdisp_delete_idx(jsdisp_t *obj, DWORD idx) { WCHAR buf[12]; - dispex_prop_t *prop; + DISPID id; BOOL b; HRESULT hres;
swprintf(buf, ARRAY_SIZE(buf), L"%d", idx);
- hres = find_prop_name(obj, string_hash(buf), buf, FALSE, &prop); - if(FAILED(hres) || !prop) - return hres; + hres = find_prop_name(obj, string_hash(buf), buf, FALSE, &id); + if(hres != S_OK) + return FAILED(hres) ? hres : S_OK;
- hres = delete_prop(prop, &b); + hres = obj->builtin_info->prop_delete(obj, id, &b); if(FAILED(hres)) return hres; return b ? S_OK : JS_E_INVALID_ACTION; @@ -2931,8 +3088,8 @@ HRESULT disp_delete_name(script_ctx_t *ctx, IDispatch *disp, jsstr_t *name, BOOL
jsdisp = iface_to_jsdisp(disp); if(jsdisp) { - dispex_prop_t *prop; const WCHAR *ptr; + DISPID id;
ptr = jsstr_flatten(name); if(!ptr) { @@ -2940,9 +3097,9 @@ HRESULT disp_delete_name(script_ctx_t *ctx, IDispatch *disp, jsstr_t *name, BOOL return E_OUTOFMEMORY; }
- hres = find_prop_name(jsdisp, string_hash(ptr), ptr, FALSE, &prop); - if(prop) { - hres = delete_prop(prop, ret); + hres = find_prop_name(jsdisp, string_hash(ptr), ptr, FALSE, &id); + if(hres == S_OK) { + hres = jsdisp->builtin_info->prop_delete(jsdisp, id, ret); }else { *ret = TRUE; hres = S_OK; @@ -2984,173 +3141,38 @@ HRESULT disp_delete_name(script_ctx_t *ctx, IDispatch *disp, jsstr_t *name, BOOL HRESULT jsdisp_get_own_property(jsdisp_t *obj, const WCHAR *name, BOOL flags_only, property_desc_t *desc) { - dispex_prop_t *prop; HRESULT hres; + DISPID id;
- hres = find_prop_name(obj, string_hash(name), name, FALSE, &prop); - if(FAILED(hres)) - return hres; - - if(!prop) - return DISP_E_UNKNOWNNAME; + hres = find_prop_name(obj, string_hash(name), name, FALSE, &id); + if(hres != S_OK) + return FAILED(hres) ? hres : DISP_E_UNKNOWNNAME;
memset(desc, 0, sizeof(*desc)); - - switch(prop->type) { - case PROP_BUILTIN: - case PROP_JSVAL: - case PROP_IDX: - desc->mask |= PROPF_WRITABLE; - desc->explicit_value = TRUE; - if(!flags_only) { - hres = prop_get(obj, to_disp(obj), prop, &desc->value); - if(FAILED(hres)) - return hres; - } - break; - case PROP_ACCESSOR: - desc->explicit_getter = desc->explicit_setter = TRUE; - if(!flags_only) { - desc->getter = prop->u.accessor.getter - ? jsdisp_addref(prop->u.accessor.getter) : NULL; - desc->setter = prop->u.accessor.setter - ? jsdisp_addref(prop->u.accessor.setter) : NULL; - } - break; - default: - return DISP_E_UNKNOWNNAME; - } - - desc->flags = prop->flags & (PROPF_ENUMERABLE | PROPF_WRITABLE | PROPF_CONFIGURABLE); - desc->mask |= PROPF_ENUMERABLE | PROPF_CONFIGURABLE; - return S_OK; + desc->mask = PROPF_ENUMERABLE | PROPF_WRITABLE | PROPF_CONFIGURABLE; + return obj->builtin_info->prop_get_desc(obj, id, flags_only, desc); }
HRESULT jsdisp_define_property(jsdisp_t *obj, const WCHAR *name, property_desc_t *desc) { - dispex_prop_t *prop; HRESULT hres; + DISPID id;
- hres = find_prop_name(obj, string_hash(name), name, FALSE, &prop); + hres = find_prop_name(obj, string_hash(name), name, FALSE, &id); if(FAILED(hres)) return hres;
- if((!prop || prop->type == PROP_DELETED || prop->type == PROP_PROTREF) && !obj->extensible) + if(hres != S_OK && !obj->extensible) return throw_error(obj->ctx, JS_E_OBJECT_NONEXTENSIBLE, name);
- if(!prop && !(prop = alloc_prop(obj, name, PROP_DELETED, 0))) - return E_OUTOFMEMORY; - - if(prop->type == PROP_DELETED || prop->type == PROP_PROTREF) { - prop->flags = desc->flags; - if(desc->explicit_getter || desc->explicit_setter) { - prop->type = PROP_ACCESSOR; - prop->u.accessor.getter = desc->getter ? jsdisp_addref(desc->getter) : NULL; - prop->u.accessor.setter = desc->setter ? jsdisp_addref(desc->setter) : NULL; - TRACE("%s = accessor { get: %p set: %p }\n", debugstr_w(name), - prop->u.accessor.getter, prop->u.accessor.setter); - }else { - prop->type = PROP_JSVAL; - if(desc->explicit_value) { - hres = jsval_copy(desc->value, &prop->u.val); - if(FAILED(hres)) - return hres; - }else { - prop->u.val = jsval_undefined(); - } - TRACE("%s = %s\n", debugstr_w(name), debugstr_jsval(prop->u.val)); - } - return S_OK; - } - - TRACE("existing prop %s prop flags %lx desc flags %x desc mask %x\n", debugstr_w(name), - prop->flags, desc->flags, desc->mask); - - if(!(prop->flags & PROPF_CONFIGURABLE)) { - if(((desc->mask & PROPF_CONFIGURABLE) && (desc->flags & PROPF_CONFIGURABLE)) - || ((desc->mask & PROPF_ENUMERABLE) - && ((desc->flags & PROPF_ENUMERABLE) != (prop->flags & PROPF_ENUMERABLE)))) - return throw_error(obj->ctx, JS_E_NONCONFIGURABLE_REDEFINED, name); - } - - if(desc->explicit_value || (desc->mask & PROPF_WRITABLE)) { - if(prop->type == PROP_ACCESSOR) { - if(!(prop->flags & PROPF_CONFIGURABLE)) - return throw_error(obj->ctx, JS_E_NONCONFIGURABLE_REDEFINED, name); - if(prop->u.accessor.getter) - jsdisp_release(prop->u.accessor.getter); - if(prop->u.accessor.setter) - jsdisp_release(prop->u.accessor.setter); - - prop->type = PROP_JSVAL; - hres = jsval_copy(desc->value, &prop->u.val); - if(FAILED(hres)) { - prop->u.val = jsval_undefined(); - return hres; - } - }else { - if(!(prop->flags & PROPF_CONFIGURABLE) && !(prop->flags & PROPF_WRITABLE)) { - if((desc->mask & PROPF_WRITABLE) && (desc->flags & PROPF_WRITABLE)) - return throw_error(obj->ctx, JS_E_NONWRITABLE_MODIFIED, name); - if(desc->explicit_value) { - if(prop->type == PROP_JSVAL) { - BOOL eq; - hres = jsval_strict_equal(desc->value, prop->u.val, &eq); - if(FAILED(hres)) - return hres; - if(!eq) - return throw_error(obj->ctx, JS_E_NONWRITABLE_MODIFIED, name); - }else { - FIXME("redefinition of property type %d\n", prop->type); - } - } - } - if(desc->explicit_value) { - if(prop->type == PROP_JSVAL) - jsval_release(prop->u.val); - else - prop->type = PROP_JSVAL; - hres = jsval_copy(desc->value, &prop->u.val); - if(FAILED(hres)) { - prop->u.val = jsval_undefined(); - return hres; - } - } - } - }else if(desc->explicit_getter || desc->explicit_setter) { - if(prop->type != PROP_ACCESSOR) { - if(!(prop->flags & PROPF_CONFIGURABLE)) - return throw_error(obj->ctx, JS_E_NONCONFIGURABLE_REDEFINED, name); - if(prop->type == PROP_JSVAL) - jsval_release(prop->u.val); - prop->type = PROP_ACCESSOR; - prop->u.accessor.getter = prop->u.accessor.setter = NULL; - }else if(!(prop->flags & PROPF_CONFIGURABLE)) { - if((desc->explicit_getter && desc->getter != prop->u.accessor.getter) - || (desc->explicit_setter && desc->setter != prop->u.accessor.setter)) - return throw_error(obj->ctx, JS_E_NONCONFIGURABLE_REDEFINED, name); - } - - if(desc->explicit_getter) { - if(prop->u.accessor.getter) { - jsdisp_release(prop->u.accessor.getter); - prop->u.accessor.getter = NULL; - } - if(desc->getter) - prop->u.accessor.getter = jsdisp_addref(desc->getter); - } - if(desc->explicit_setter) { - if(prop->u.accessor.setter) { - jsdisp_release(prop->u.accessor.setter); - prop->u.accessor.setter = NULL; - } - if(desc->setter) - prop->u.accessor.setter = jsdisp_addref(desc->setter); - } + if(!id) { + dispex_prop_t *prop = alloc_prop(obj, name, PROP_DELETED, 0); + if(!prop) + return E_OUTOFMEMORY; + id = prop_to_id(obj, prop); }
- prop->flags = (prop->flags & ~desc->mask) | (desc->flags & desc->mask); - return S_OK; + return obj->builtin_info->prop_define(obj, id, desc); }
HRESULT jsdisp_define_data_property(jsdisp_t *obj, const WCHAR *name, unsigned flags, jsval_t value) diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index 091d7f2c072..777a3462c3a 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -555,7 +555,9 @@ static const builtin_info_t scope_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, scope_idx_length, scope_idx_get, scope_idx_put, diff --git a/dlls/jscript/enumerator.c b/dlls/jscript/enumerator.c index dcceafa01b5..7c14955759b 100644 --- a/dlls/jscript/enumerator.c +++ b/dlls/jscript/enumerator.c @@ -192,7 +192,9 @@ static const builtin_info_t Enumerator_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
static const builtin_info_t EnumeratorInst_info = { @@ -206,7 +208,9 @@ static const builtin_info_t EnumeratorInst_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, NULL, NULL, NULL, @@ -344,7 +348,9 @@ static const builtin_info_t EnumeratorConstr_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
HRESULT create_enumerator_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret) diff --git a/dlls/jscript/error.c b/dlls/jscript/error.c index a3473a8cd86..00e748b1f60 100644 --- a/dlls/jscript/error.c +++ b/dlls/jscript/error.c @@ -149,7 +149,9 @@ static const builtin_info_t Error_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
static const builtin_info_t ErrorInst_info = { @@ -163,7 +165,9 @@ static const builtin_info_t ErrorInst_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
static HRESULT alloc_error(script_ctx_t *ctx, jsdisp_t *prototype, diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 7384dce26aa..1335aad4a40 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -194,7 +194,9 @@ static const builtin_info_t Arguments_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, Arguments_idx_length, Arguments_idx_get, Arguments_idx_put, @@ -617,7 +619,9 @@ static const builtin_info_t Function_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, NULL, NULL, NULL, @@ -641,7 +645,9 @@ static const builtin_info_t FunctionInst_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, NULL, NULL, NULL, @@ -833,7 +839,9 @@ static const builtin_info_t InterpretedFunction_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, NULL, NULL, NULL, @@ -970,7 +978,9 @@ static const builtin_info_t BindFunction_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, NULL, NULL, NULL, diff --git a/dlls/jscript/global.c b/dlls/jscript/global.c index 9ca65c88224..ab00017cda2 100644 --- a/dlls/jscript/global.c +++ b/dlls/jscript/global.c @@ -915,7 +915,9 @@ static const builtin_info_t JSGlobal_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
static HRESULT init_object_prototype_accessors(script_ctx_t *ctx, jsdisp_t *object_prototype) diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index 6eda89a3246..721a2edf826 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -132,7 +132,9 @@ HRESULT create_named_item_script_obj(script_ctx_t *ctx, named_item_t *item) dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
return create_dispex(ctx, &disp_info, NULL, &item->script_obj); diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index a9819449c00..67f5c3a90da 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -134,7 +134,9 @@ HRESULT dispex_prop_get(jsdisp_t*,IDispatch*,DISPID,jsval_t*); HRESULT dispex_prop_put(jsdisp_t*,DISPID,jsval_t); HRESULT dispex_prop_invoke(jsdisp_t*,IDispatch*,DISPID,WORD,unsigned,jsval_t*,jsval_t*,IServiceProvider*); HRESULT dispex_prop_delete(jsdisp_t*,DISPID,BOOL*); +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*);
struct thread_data { LONG ref; @@ -194,7 +196,9 @@ typedef struct { HRESULT (*prop_put)(jsdisp_t*,DISPID,jsval_t); HRESULT (*prop_invoke)(jsdisp_t*,IDispatch*,DISPID,WORD,unsigned,jsval_t*,jsval_t*,IServiceProvider*); HRESULT (*prop_delete)(jsdisp_t*,DISPID,BOOL*); + HRESULT (*prop_get_desc)(jsdisp_t*,DISPID,BOOL,property_desc_t*); 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); @@ -257,6 +261,11 @@ void jsdisp_release(jsdisp_t*);
#endif
+static inline BOOL is_dispex_prop_id(DISPID id) +{ + return id > 0; +} + enum jsdisp_enum_type { JSDISP_ENUM_ALL, JSDISP_ENUM_OWN, diff --git a/dlls/jscript/json.c b/dlls/jscript/json.c index 9087a48a827..66c220e1c18 100644 --- a/dlls/jscript/json.c +++ b/dlls/jscript/json.c @@ -958,7 +958,9 @@ static const builtin_info_t JSON_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
HRESULT create_json(script_ctx_t *ctx, jsdisp_t **ret) diff --git a/dlls/jscript/jsregexp.c b/dlls/jscript/jsregexp.c index 48257f03ee5..93e5b1351f9 100644 --- a/dlls/jscript/jsregexp.c +++ b/dlls/jscript/jsregexp.c @@ -580,7 +580,9 @@ static const builtin_info_t RegExp_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, NULL, NULL, NULL, @@ -606,7 +608,9 @@ static const builtin_info_t RegExpInst_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, NULL, NULL, NULL, @@ -981,7 +985,9 @@ static const builtin_info_t RegExpConstr_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
HRESULT create_regexp_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret) diff --git a/dlls/jscript/math.c b/dlls/jscript/math.c index 2401acaf62d..11e9670a71a 100644 --- a/dlls/jscript/math.c +++ b/dlls/jscript/math.c @@ -501,7 +501,9 @@ static const builtin_info_t Math_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
HRESULT create_math(script_ctx_t *ctx, jsdisp_t **ret) diff --git a/dlls/jscript/number.c b/dlls/jscript/number.c index ff2d73f5722..186fcc6ee2f 100644 --- a/dlls/jscript/number.c +++ b/dlls/jscript/number.c @@ -596,7 +596,9 @@ static const builtin_info_t Number_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
static const builtin_info_t NumberInst_info = { @@ -609,7 +611,9 @@ static const builtin_info_t NumberInst_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
static HRESULT NumberConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, diff --git a/dlls/jscript/object.c b/dlls/jscript/object.c index 1053f5d27c8..a2097cb2d3c 100644 --- a/dlls/jscript/object.c +++ b/dlls/jscript/object.c @@ -475,7 +475,9 @@ static const builtin_info_t Object_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
static const builtin_info_t ObjectInst_info = { @@ -488,7 +490,9 @@ static const builtin_info_t ObjectInst_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
static void release_property_descriptor(property_desc_t *desc) @@ -1089,7 +1093,9 @@ static const builtin_info_t ObjectConstr_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
static HRESULT ObjectConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, diff --git a/dlls/jscript/set.c b/dlls/jscript/set.c index 1f7f8f2be20..24bdc059b27 100644 --- a/dlls/jscript/set.c +++ b/dlls/jscript/set.c @@ -411,7 +411,9 @@ static const builtin_info_t Map_prototype_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
static const builtin_info_t Map_info = { @@ -425,7 +427,9 @@ static const builtin_info_t Map_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, NULL, NULL, NULL, @@ -580,7 +584,9 @@ static const builtin_info_t Set_prototype_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
static const builtin_info_t Set_info = { @@ -594,7 +600,9 @@ static const builtin_info_t Set_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, NULL, NULL, NULL, @@ -887,7 +895,9 @@ static const builtin_info_t WeakMap_prototype_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
static const builtin_info_t WeakMap_info = { @@ -901,7 +911,9 @@ static const builtin_info_t WeakMap_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, NULL, NULL, NULL, diff --git a/dlls/jscript/string.c b/dlls/jscript/string.c index 0ab9df0a588..3dac3bd41e1 100644 --- a/dlls/jscript/string.c +++ b/dlls/jscript/string.c @@ -1579,7 +1579,9 @@ static const builtin_info_t String_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
static const builtin_prop_t StringInst_props[] = { @@ -1597,7 +1599,9 @@ static const builtin_info_t StringInst_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, String_idx_length, String_idx_get }; @@ -1723,7 +1727,9 @@ static const builtin_info_t StringConstr_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
HRESULT create_string_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdisp_t **ret) diff --git a/dlls/jscript/vbarray.c b/dlls/jscript/vbarray.c index 3cfa84d8de7..55b9e0df109 100644 --- a/dlls/jscript/vbarray.c +++ b/dlls/jscript/vbarray.c @@ -257,7 +257,9 @@ static const builtin_info_t VBArray_info = { dispex_prop_put, dispex_prop_invoke, dispex_prop_delete, + dispex_prop_get_desc, dispex_prop_get_name, + dispex_prop_define, };
static HRESULT alloc_vbarray(script_ctx_t *ctx, jsdisp_t *object_prototype, VBArrayInstance **ret)
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 51 ++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 27 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index ecba9522f39..bc4463d8023 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -618,32 +618,6 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t return E_FAIL; }
-static HRESULT delete_prop(dispex_prop_t *prop, BOOL *ret) -{ - if(prop->type == PROP_PROTREF) { - *ret = TRUE; - return S_OK; - } - - if(!(prop->flags & PROPF_CONFIGURABLE)) { - *ret = FALSE; - return S_OK; - } - - *ret = TRUE; - - if(prop->type == PROP_JSVAL) - jsval_release(prop->u.val); - if(prop->type == PROP_ACCESSOR) { - if(prop->u.accessor.getter) - jsdisp_release(prop->u.accessor.getter); - if(prop->u.accessor.setter) - jsdisp_release(prop->u.accessor.setter); - } - prop->type = PROP_DELETED; - return S_OK; -} - HRESULT builtin_set_const(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t value) { TRACE("%p %s\n", jsthis, debugstr_jsval(value)); @@ -668,7 +642,30 @@ HRESULT dispex_prop_invoke(jsdisp_t *jsdisp, IDispatch *jsthis, DISPID id, WORD
HRESULT dispex_prop_delete(jsdisp_t *jsdisp, DISPID id, BOOL *ret) { - return delete_prop(&jsdisp->props[prop_id_to_idx(id)], ret); + dispex_prop_t *prop = &jsdisp->props[prop_id_to_idx(id)]; + + if(prop->type == PROP_PROTREF) { + *ret = TRUE; + return S_OK; + } + + if(!(prop->flags & PROPF_CONFIGURABLE)) { + *ret = FALSE; + return S_OK; + } + + *ret = TRUE; + + if(prop->type == PROP_JSVAL) + jsval_release(prop->u.val); + if(prop->type == PROP_ACCESSOR) { + if(prop->u.accessor.getter) + jsdisp_release(prop->u.accessor.getter); + if(prop->u.accessor.setter) + jsdisp_release(prop->u.accessor.setter); + } + prop->type = PROP_DELETED; + return S_OK; }
HRESULT dispex_prop_get_desc(jsdisp_t *jsdisp, DISPID id, BOOL flags_only, property_desc_t *desc)
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 57 ++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 31 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index bc4463d8023..297f2f14789 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -567,17 +567,34 @@ static HRESULT prop_put(jsdisp_t *This, dispex_prop_t *prop, jsval_t val) return S_OK; }
-static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t *prop, WORD flags, - unsigned argc, jsval_t *argv, jsval_t *r, IServiceProvider *caller) +HRESULT builtin_set_const(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t value) +{ + TRACE("%p %s\n", jsthis, debugstr_jsval(value)); + return S_OK; +} + +HRESULT dispex_prop_get(jsdisp_t *jsdisp, IDispatch *jsthis, DISPID id, jsval_t *r) +{ + return prop_get(jsdisp, jsthis, &jsdisp->props[prop_id_to_idx(id)], r); +} + +HRESULT dispex_prop_put(jsdisp_t *jsdisp, DISPID id, jsval_t val) +{ + return prop_put(jsdisp, &jsdisp->props[prop_id_to_idx(id)], val); +} + +HRESULT dispex_prop_invoke(jsdisp_t *jsdisp, IDispatch *jsthis, DISPID id, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r, IServiceProvider *caller) { + dispex_prop_t *prop = &jsdisp->props[prop_id_to_idx(id)]; HRESULT hres;
switch(prop->type) { case PROP_BUILTIN: return JS_E_FUNCTION_EXPECTED; case PROP_PROTREF: - return invoke_prop_func(This->prototype, jsthis ? jsthis : (IDispatch *)&This->IDispatchEx_iface, - This->prototype->props+prop->u.ref, flags, argc, argv, r, caller); + return jsdisp->prototype->builtin_info->prop_invoke(jsdisp->prototype, jsthis ? jsthis : (IDispatch*)&jsdisp->IDispatchEx_iface, + prop->u.ref + 1, flags, argc, argv, r, caller); case PROP_JSVAL: { if(!is_object_instance(prop->u.val)) { FIXME("invoke %s\n", debugstr_jsval(prop->u.val)); @@ -586,21 +603,21 @@ 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), + return disp_call_value_with_caller(jsdisp->ctx, get_object(prop->u.val), + jsval_disp(jsthis ? jsthis : (IDispatch*)&jsdisp->IDispatchEx_iface), flags, argc, argv, r, caller); } case PROP_ACCESSOR: case PROP_IDX: { jsval_t val;
- hres = prop_get(This, jsthis ? jsthis : (IDispatch *)&This->IDispatchEx_iface, prop, &val); + hres = dispex_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(This->ctx, get_object(val), - jsval_disp(jsthis ? jsthis : (IDispatch*)&This->IDispatchEx_iface), + 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)); @@ -618,28 +635,6 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t return E_FAIL; }
-HRESULT builtin_set_const(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t value) -{ - TRACE("%p %s\n", jsthis, debugstr_jsval(value)); - return S_OK; -} - -HRESULT dispex_prop_get(jsdisp_t *jsdisp, IDispatch *jsthis, DISPID id, jsval_t *r) -{ - return prop_get(jsdisp, jsthis, &jsdisp->props[prop_id_to_idx(id)], r); -} - -HRESULT dispex_prop_put(jsdisp_t *jsdisp, DISPID id, jsval_t val) -{ - return prop_put(jsdisp, &jsdisp->props[prop_id_to_idx(id)], val); -} - -HRESULT dispex_prop_invoke(jsdisp_t *jsdisp, IDispatch *jsthis, DISPID id, WORD flags, - unsigned argc, jsval_t *argv, jsval_t *r, IServiceProvider *caller) -{ - return invoke_prop_func(jsdisp, jsthis, &jsdisp->props[prop_id_to_idx(id)], flags, argc, argv, r, caller); -} - HRESULT dispex_prop_delete(jsdisp_t *jsdisp, DISPID id, BOOL *ret) { dispex_prop_t *prop = &jsdisp->props[prop_id_to_idx(id)];
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 84 +++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 44 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 297f2f14789..bc17d6c4ad0 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -457,49 +457,6 @@ static HRESULT convert_params(script_ctx_t *ctx, const DISPPARAMS *dp, jsval_t * return S_OK; }
-static HRESULT prop_get(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t *prop, jsval_t *r) -{ - jsdisp_t *prop_obj = This; - HRESULT hres; - - while(prop->type == PROP_PROTREF) { - prop_obj = prop_obj->prototype; - prop = prop_obj->props + prop->u.ref; - } - - switch(prop->type) { - case PROP_BUILTIN: - hres = prop->u.p->getter(This->ctx, prop_obj, r); - break; - case PROP_JSVAL: - hres = jsval_copy(prop->u.val, r); - break; - case PROP_ACCESSOR: - if(prop->u.accessor.getter) { - hres = jsdisp_call_value(prop->u.accessor.getter, jsval_disp(jsthis), - DISPATCH_METHOD, 0, NULL, r); - }else { - *r = jsval_undefined(); - 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; - } - - if(FAILED(hres)) { - TRACE("fail %08lx\n", hres); - return hres; - } - - TRACE("%p.%s ret %s\n", This, debugstr_w(prop->name), debugstr_jsval(*r)); - return hres; -} - static HRESULT prop_put(jsdisp_t *This, dispex_prop_t *prop, jsval_t val) { HRESULT hres; @@ -575,7 +532,46 @@ 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) { - return prop_get(jsdisp, jsthis, &jsdisp->props[prop_id_to_idx(id)], 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; + } + + switch(prop->type) { + case PROP_BUILTIN: + hres = prop->u.p->getter(jsdisp->ctx, prop_obj, r); + break; + case PROP_JSVAL: + hres = jsval_copy(prop->u.val, r); + break; + case PROP_ACCESSOR: + if(prop->u.accessor.getter) { + hres = jsdisp_call_value(prop->u.accessor.getter, jsval_disp(jsthis), + DISPATCH_METHOD, 0, NULL, r); + }else { + *r = jsval_undefined(); + 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; + } + + if(FAILED(hres)) { + TRACE("fail %08lx\n", hres); + return hres; + } + + TRACE("%p.%s ret %s\n", jsdisp, debugstr_w(prop->name), debugstr_jsval(*r)); + return hres; }
HRESULT dispex_prop_put(jsdisp_t *jsdisp, DISPID id, jsval_t val)
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 126 ++++++++++++++++++++---------------------- 1 file changed, 61 insertions(+), 65 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index bc17d6c4ad0..227e33becee 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -457,13 +457,64 @@ static HRESULT convert_params(script_ctx_t *ctx, const DISPPARAMS *dp, jsval_t * return S_OK; }
-static HRESULT prop_put(jsdisp_t *This, dispex_prop_t *prop, jsval_t val) +HRESULT builtin_set_const(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t value) +{ + TRACE("%p %s\n", jsthis, debugstr_jsval(value)); + return S_OK; +} + +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; + } + + switch(prop->type) { + case PROP_BUILTIN: + hres = prop->u.p->getter(jsdisp->ctx, prop_obj, r); + break; + case PROP_JSVAL: + hres = jsval_copy(prop->u.val, r); + break; + case PROP_ACCESSOR: + if(prop->u.accessor.getter) { + hres = jsdisp_call_value(prop->u.accessor.getter, jsval_disp(jsthis), + DISPATCH_METHOD, 0, NULL, r); + }else { + *r = jsval_undefined(); + 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; + } + + if(FAILED(hres)) { + TRACE("fail %08lx\n", hres); + return hres; + } + + TRACE("%p.%s ret %s\n", jsdisp, debugstr_w(prop->name), debugstr_jsval(*r)); + return hres; +} + +HRESULT dispex_prop_put(jsdisp_t *jsdisp, DISPID id, jsval_t val) +{ + dispex_prop_t *prop = &jsdisp->props[prop_id_to_idx(id)]; HRESULT hres;
if(prop->type == PROP_PROTREF) { dispex_prop_t *prop_iter = prop; - jsdisp_t *prototype_iter = This; + jsdisp_t *prototype_iter = jsdisp;
do { prototype_iter = prototype_iter->prototype; @@ -480,10 +531,10 @@ static HRESULT prop_put(jsdisp_t *This, dispex_prop_t *prop, jsval_t val) TRACE("getter with no setter\n"); return S_OK; } - return prop->u.p->setter(This->ctx, This, val); + return prop->u.p->setter(jsdisp->ctx, jsdisp, val); case PROP_PROTREF: case PROP_DELETED: - if(!This->extensible) + if(!jsdisp->extensible) return S_OK; prop->type = PROP_JSVAL; prop->flags = PROPF_ENUMERABLE | PROPF_CONFIGURABLE | PROPF_WRITABLE; @@ -500,85 +551,30 @@ static HRESULT prop_put(jsdisp_t *This, dispex_prop_t *prop, jsval_t val) TRACE("no setter\n"); return S_OK; } - return jsdisp_call_value(prop->u.accessor.setter, jsval_obj(This), DISPATCH_METHOD, 1, &val, NULL); + return jsdisp_call_value(prop->u.accessor.setter, jsval_obj(jsdisp), DISPATCH_METHOD, 1, &val, NULL); case PROP_IDX: - if(!This->builtin_info->idx_put) { + if(!jsdisp->builtin_info->idx_put) { TRACE("no put_idx\n"); return S_OK; } - return This->builtin_info->idx_put(This, prop->u.idx, val); + return jsdisp->builtin_info->idx_put(jsdisp, prop->u.idx, val); default: ERR("type %d\n", prop->type); return E_FAIL; }
- TRACE("%p.%s = %s\n", This, debugstr_w(prop->name), debugstr_jsval(val)); + TRACE("%p.%s = %s\n", jsdisp, debugstr_w(prop->name), debugstr_jsval(val));
hres = jsval_copy(val, &prop->u.val); if(FAILED(hres)) return hres;
- if(This->builtin_info->on_put) - This->builtin_info->on_put(This, prop->name); - - return S_OK; -} + if(jsdisp->builtin_info->on_put) + jsdisp->builtin_info->on_put(jsdisp, prop->name);
-HRESULT builtin_set_const(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t value) -{ - TRACE("%p %s\n", jsthis, debugstr_jsval(value)); return S_OK; }
-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; - } - - switch(prop->type) { - case PROP_BUILTIN: - hres = prop->u.p->getter(jsdisp->ctx, prop_obj, r); - break; - case PROP_JSVAL: - hres = jsval_copy(prop->u.val, r); - break; - case PROP_ACCESSOR: - if(prop->u.accessor.getter) { - hres = jsdisp_call_value(prop->u.accessor.getter, jsval_disp(jsthis), - DISPATCH_METHOD, 0, NULL, r); - }else { - *r = jsval_undefined(); - 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; - } - - if(FAILED(hres)) { - TRACE("fail %08lx\n", hres); - return hres; - } - - TRACE("%p.%s ret %s\n", jsdisp, debugstr_w(prop->name), debugstr_jsval(*r)); - return hres; -} - -HRESULT dispex_prop_put(jsdisp_t *jsdisp, DISPID id, jsval_t val) -{ - return prop_put(jsdisp, &jsdisp->props[prop_id_to_idx(id)], val); -} - HRESULT dispex_prop_invoke(jsdisp_t *jsdisp, IDispatch *jsthis, DISPID id, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r, IServiceProvider *caller) {
From: Gabriel Ivăncescu gabrielopcode@gmail.com
We can just use the object's prop_put now.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/array.c | 31 ++++++++++++++++++------------- dlls/jscript/arraybuf.c | 6 ------ dlls/jscript/bool.c | 2 -- dlls/jscript/date.c | 3 --- dlls/jscript/dispex.c | 9 +++++---- dlls/jscript/engine.c | 1 - dlls/jscript/enumerator.c | 3 --- dlls/jscript/error.c | 2 -- dlls/jscript/function.c | 5 ----- dlls/jscript/global.c | 1 - dlls/jscript/jscript.c | 1 - dlls/jscript/jscript.h | 2 +- dlls/jscript/json.c | 1 - dlls/jscript/jsregexp.c | 3 --- dlls/jscript/math.c | 1 - dlls/jscript/number.c | 2 -- dlls/jscript/object.c | 3 --- dlls/jscript/set.c | 6 ------ dlls/jscript/string.c | 3 --- dlls/jscript/vbarray.c | 1 - 20 files changed, 24 insertions(+), 62 deletions(-)
diff --git a/dlls/jscript/array.c b/dlls/jscript/array.c index 6d2bbd7e32e..f6449ec0ad1 100644 --- a/dlls/jscript/array.c +++ b/dlls/jscript/array.c @@ -1594,25 +1594,33 @@ static void Array_destructor(jsdisp_t *dispex) free(dispex); }
-static void Array_on_put(jsdisp_t *dispex, const WCHAR *name) +static HRESULT Array_prop_put(jsdisp_t *dispex, DISPID id, jsval_t val) { ArrayInstance *array = array_from_jsdisp(dispex); - const WCHAR *ptr = name; - DWORD id = 0; + const WCHAR *ptr; + DWORD idx = 0; + HRESULT hres; + + hres = dispex_prop_put(&array->dispex, id, val); + if(hres != S_OK) + return hres;
+ ptr = dispex_prop_get_static_name(&array->dispex, id); if(!is_digit(*ptr)) - return; + return hres;
while(*ptr && is_digit(*ptr)) { - id = id*10 + (*ptr-'0'); + idx = idx*10 + (*ptr-'0'); ptr++; }
if(*ptr) - return; + return hres;
- if(id >= array->length) - array->length = id+1; + if(idx >= array->length) + array->length = idx + 1; + + return hres; }
static const builtin_prop_t Array_props[] = { @@ -1645,9 +1653,8 @@ static const builtin_info_t Array_info = { ARRAY_SIZE(Array_props), Array_props, Array_destructor, - Array_on_put, dispex_prop_get, - dispex_prop_put, + Array_prop_put, dispex_prop_invoke, dispex_prop_delete, dispex_prop_get_desc, @@ -1665,9 +1672,8 @@ static const builtin_info_t ArrayInst_info = { ARRAY_SIZE(ArrayInst_props), ArrayInst_props, Array_destructor, - Array_on_put, dispex_prop_get, - dispex_prop_put, + Array_prop_put, dispex_prop_invoke, dispex_prop_delete, dispex_prop_get_desc, @@ -1780,7 +1786,6 @@ static const builtin_info_t ArrayConstr_info = { ARRAY_SIZE(ArrayConstr_props), ArrayConstr_props, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, diff --git a/dlls/jscript/arraybuf.c b/dlls/jscript/arraybuf.c index cd92fb47924..ce0c482e914 100644 --- a/dlls/jscript/arraybuf.c +++ b/dlls/jscript/arraybuf.c @@ -126,7 +126,6 @@ static const builtin_info_t ArrayBuffer_info = { ARRAY_SIZE(ArrayBuffer_props), ArrayBuffer_props, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -146,7 +145,6 @@ static const builtin_info_t ArrayBufferInst_info = { ARRAY_SIZE(ArrayBufferInst_props), ArrayBufferInst_props, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -233,7 +231,6 @@ static const builtin_info_t ArrayBufferConstr_info = { ARRAY_SIZE(ArrayBufferConstr_props), ArrayBufferConstr_props, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -636,7 +633,6 @@ static const builtin_info_t DataView_info = { ARRAY_SIZE(DataView_props), DataView_props, DataView_destructor, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -656,7 +652,6 @@ static const builtin_info_t DataViewInst_info = { 0, NULL, DataView_destructor, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -741,7 +736,6 @@ static const builtin_info_t DataViewConstr_info = { 0, NULL, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, diff --git a/dlls/jscript/bool.c b/dlls/jscript/bool.c index 51a51cd48de..0b5f9a2c34f 100644 --- a/dlls/jscript/bool.c +++ b/dlls/jscript/bool.c @@ -124,7 +124,6 @@ static const builtin_info_t Bool_info = { ARRAY_SIZE(Bool_props), Bool_props, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -139,7 +138,6 @@ static const builtin_info_t BoolInst_info = { Bool_value, 0, NULL, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, diff --git a/dlls/jscript/date.c b/dlls/jscript/date.c index f712a7f5805..25a99a45b54 100644 --- a/dlls/jscript/date.c +++ b/dlls/jscript/date.c @@ -1905,7 +1905,6 @@ static const builtin_info_t Date_info = { ARRAY_SIZE(Date_props), Date_props, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -1920,7 +1919,6 @@ static const builtin_info_t DateInst_info = { NULL, 0, NULL, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -2455,7 +2453,6 @@ static const builtin_info_t DateConstr_info = { ARRAY_SIZE(DateConstr_props), DateConstr_props, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 227e33becee..587ae1c87cb 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -569,9 +569,6 @@ HRESULT dispex_prop_put(jsdisp_t *jsdisp, DISPID id, jsval_t val) if(FAILED(hres)) return hres;
- if(jsdisp->builtin_info->on_put) - jsdisp->builtin_info->on_put(jsdisp, prop->name); - return S_OK; }
@@ -816,6 +813,11 @@ HRESULT dispex_prop_define(jsdisp_t *jsdisp, DISPID id, const property_desc_t *d return S_OK; }
+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 hres; @@ -2384,7 +2386,6 @@ static const builtin_info_t dispex_info = { NULL, 0, NULL, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index 777a3462c3a..e8437780d1b 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -550,7 +550,6 @@ static const builtin_info_t scope_info = { 0, NULL, scope_destructor, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, diff --git a/dlls/jscript/enumerator.c b/dlls/jscript/enumerator.c index 7c14955759b..1282882ae8f 100644 --- a/dlls/jscript/enumerator.c +++ b/dlls/jscript/enumerator.c @@ -187,7 +187,6 @@ static const builtin_info_t Enumerator_info = { ARRAY_SIZE(Enumerator_props), Enumerator_props, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -203,7 +202,6 @@ static const builtin_info_t EnumeratorInst_info = { 0, NULL, Enumerator_destructor, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -343,7 +341,6 @@ static const builtin_info_t EnumeratorConstr_info = { 0, NULL, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, diff --git a/dlls/jscript/error.c b/dlls/jscript/error.c index 00e748b1f60..88e9e14fede 100644 --- a/dlls/jscript/error.c +++ b/dlls/jscript/error.c @@ -144,7 +144,6 @@ static const builtin_info_t Error_info = { ARRAY_SIZE(Error_props), Error_props, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -160,7 +159,6 @@ static const builtin_info_t ErrorInst_info = { 0, NULL, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 1335aad4a40..3b43b763512 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -189,7 +189,6 @@ static const builtin_info_t Arguments_info = { Arguments_value, 0, NULL, Arguments_destructor, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -614,7 +613,6 @@ static const builtin_info_t Function_info = { ARRAY_SIZE(Function_props), Function_props, Function_destructor, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -640,7 +638,6 @@ static const builtin_info_t FunctionInst_info = { ARRAY_SIZE(FunctionInst_props), FunctionInst_props, Function_destructor, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -834,7 +831,6 @@ static const builtin_info_t InterpretedFunction_info = { ARRAY_SIZE(InterpretedFunction_props), InterpretedFunction_props, Function_destructor, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -973,7 +969,6 @@ static const builtin_info_t BindFunction_info = { ARRAY_SIZE(BindFunction_props), BindFunction_props, Function_destructor, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, diff --git a/dlls/jscript/global.c b/dlls/jscript/global.c index ab00017cda2..a97ec29c7e8 100644 --- a/dlls/jscript/global.c +++ b/dlls/jscript/global.c @@ -910,7 +910,6 @@ static const builtin_info_t JSGlobal_info = { ARRAY_SIZE(JSGlobal_props), JSGlobal_props, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index 721a2edf826..38a65471bb5 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -127,7 +127,6 @@ HRESULT create_named_item_script_obj(script_ctx_t *ctx, named_item_t *item) NULL, 0, NULL, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 67f5c3a90da..70edb27447d 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -137,6 +137,7 @@ HRESULT dispex_prop_delete(jsdisp_t*,DISPID,BOOL*); 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);
struct thread_data { LONG ref; @@ -191,7 +192,6 @@ typedef struct { DWORD props_cnt; const builtin_prop_t *props; void (*destructor)(jsdisp_t*); - void (*on_put)(jsdisp_t*,const WCHAR*); HRESULT (*prop_get)(jsdisp_t*,IDispatch*,DISPID,jsval_t*); HRESULT (*prop_put)(jsdisp_t*,DISPID,jsval_t); HRESULT (*prop_invoke)(jsdisp_t*,IDispatch*,DISPID,WORD,unsigned,jsval_t*,jsval_t*,IServiceProvider*); diff --git a/dlls/jscript/json.c b/dlls/jscript/json.c index 66c220e1c18..6ae5bf961cb 100644 --- a/dlls/jscript/json.c +++ b/dlls/jscript/json.c @@ -953,7 +953,6 @@ static const builtin_info_t JSON_info = { ARRAY_SIZE(JSON_props), JSON_props, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, diff --git a/dlls/jscript/jsregexp.c b/dlls/jscript/jsregexp.c index 93e5b1351f9..02a35c09f71 100644 --- a/dlls/jscript/jsregexp.c +++ b/dlls/jscript/jsregexp.c @@ -575,7 +575,6 @@ static const builtin_info_t RegExp_info = { ARRAY_SIZE(RegExp_props), RegExp_props, RegExp_destructor, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -603,7 +602,6 @@ static const builtin_info_t RegExpInst_info = { ARRAY_SIZE(RegExpInst_props), RegExpInst_props, RegExp_destructor, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -980,7 +978,6 @@ static const builtin_info_t RegExpConstr_info = { ARRAY_SIZE(RegExpConstr_props), RegExpConstr_props, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, diff --git a/dlls/jscript/math.c b/dlls/jscript/math.c index 11e9670a71a..6d820ec71e1 100644 --- a/dlls/jscript/math.c +++ b/dlls/jscript/math.c @@ -496,7 +496,6 @@ static const builtin_info_t Math_info = { ARRAY_SIZE(Math_props), Math_props, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, diff --git a/dlls/jscript/number.c b/dlls/jscript/number.c index 186fcc6ee2f..9be6f6a2f90 100644 --- a/dlls/jscript/number.c +++ b/dlls/jscript/number.c @@ -591,7 +591,6 @@ static const builtin_info_t Number_info = { ARRAY_SIZE(Number_props), Number_props, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -606,7 +605,6 @@ static const builtin_info_t NumberInst_info = { NULL, 0, NULL, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, diff --git a/dlls/jscript/object.c b/dlls/jscript/object.c index a2097cb2d3c..8739c0089e7 100644 --- a/dlls/jscript/object.c +++ b/dlls/jscript/object.c @@ -470,7 +470,6 @@ static const builtin_info_t Object_info = { ARRAY_SIZE(Object_props), Object_props, Object_destructor, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -485,7 +484,6 @@ static const builtin_info_t ObjectInst_info = { NULL, 0, NULL, Object_destructor, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -1088,7 +1086,6 @@ static const builtin_info_t ObjectConstr_info = { ARRAY_SIZE(ObjectConstr_props), ObjectConstr_props, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, diff --git a/dlls/jscript/set.c b/dlls/jscript/set.c index 24bdc059b27..4310cd6f86c 100644 --- a/dlls/jscript/set.c +++ b/dlls/jscript/set.c @@ -406,7 +406,6 @@ static const builtin_info_t Map_prototype_info = { ARRAY_SIZE(Map_prototype_props), Map_prototype_props, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -422,7 +421,6 @@ static const builtin_info_t Map_info = { ARRAY_SIZE(Map_props), Map_props, Map_destructor, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -579,7 +577,6 @@ static const builtin_info_t Set_prototype_info = { ARRAY_SIZE(Set_prototype_props), Set_prototype_props, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -595,7 +592,6 @@ static const builtin_info_t Set_info = { ARRAY_SIZE(Map_props), Map_props, Map_destructor, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -890,7 +886,6 @@ static const builtin_info_t WeakMap_prototype_info = { ARRAY_SIZE(WeakMap_prototype_props), WeakMap_prototype_props, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -906,7 +901,6 @@ static const builtin_info_t WeakMap_info = { 0, NULL, WeakMap_destructor, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, diff --git a/dlls/jscript/string.c b/dlls/jscript/string.c index 3dac3bd41e1..e3aa61483d1 100644 --- a/dlls/jscript/string.c +++ b/dlls/jscript/string.c @@ -1574,7 +1574,6 @@ static const builtin_info_t String_info = { ARRAY_SIZE(String_props), String_props, String_destructor, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -1594,7 +1593,6 @@ static const builtin_info_t StringInst_info = { ARRAY_SIZE(StringInst_props), StringInst_props, String_destructor, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, @@ -1722,7 +1720,6 @@ static const builtin_info_t StringConstr_info = { ARRAY_SIZE(StringConstr_props), StringConstr_props, NULL, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke, diff --git a/dlls/jscript/vbarray.c b/dlls/jscript/vbarray.c index 55b9e0df109..81eaf83f908 100644 --- a/dlls/jscript/vbarray.c +++ b/dlls/jscript/vbarray.c @@ -252,7 +252,6 @@ static const builtin_info_t VBArray_info = { ARRAY_SIZE(VBArray_props), VBArray_props, VBArray_destructor, - NULL, dispex_prop_get, dispex_prop_put, dispex_prop_invoke,
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
It's the only thing it was used for anyway, this will simplify next patches. --- dlls/jscript/dispex.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 587ae1c87cb..7f81b136d56 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -115,7 +115,7 @@ static inline BOOL is_function_prop(dispex_prop_t *prop) return ret; }
-static DWORD get_flags(jsdisp_t *This, dispex_prop_t *prop) +static BOOL is_enumerable(jsdisp_t *This, dispex_prop_t *prop) { if(prop->type == PROP_PROTREF) { dispex_prop_t *parent = NULL; @@ -125,13 +125,13 @@ static DWORD get_flags(jsdisp_t *This, dispex_prop_t *prop)
if(!parent || parent->type == PROP_DELETED) { prop->type = PROP_DELETED; - return 0; + return FALSE; }
- return get_flags(This->prototype, parent); + return is_enumerable(This->prototype, parent); }
- return prop->flags; + return !!(prop->flags & PROPF_ENUMERABLE); }
static const builtin_prop_t *find_builtin_prop(jsdisp_t *This, const WCHAR *name, BOOL case_insens) @@ -3052,7 +3052,7 @@ HRESULT jsdisp_next_prop(jsdisp_t *obj, DISPID id, enum jsdisp_enum_type enum_ty continue; if(enum_type != JSDISP_ENUM_ALL && iter->type == PROP_PROTREF) continue; - if(enum_type != JSDISP_ENUM_OWN && !(get_flags(obj, iter) & PROPF_ENUMERABLE)) + if(enum_type != JSDISP_ENUM_OWN && !is_enumerable(obj, iter)) continue; *ret = prop_to_id(obj, iter); return S_OK;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 7f81b136d56..46e4d878417 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -838,11 +838,29 @@ static HRESULT fill_props(jsdisp_t *obj) return S_OK; }
+static HRESULT fill_protref(jsdisp_t *This, unsigned hash, const WCHAR *name, DWORD ref) +{ + HRESULT hres; + DISPID id; + + hres = find_prop_name(This, hash, name, FALSE, &id); + if(hres != S_FALSE) + return hres; + if(is_dispex_prop_id(id)) { + dispex_prop_t *p = &This->props[prop_id_to_idx(id)]; + p->type = PROP_PROTREF; + p->flags = 0; + p->u.ref = ref; + }else if(!alloc_protref(This, name, ref)) { + return E_OUTOFMEMORY; + } + return S_OK; +} + static HRESULT fill_protrefs(jsdisp_t *This) { dispex_prop_t *iter; HRESULT hres; - DISPID id;
hres = fill_props(This); if(FAILED(hres)) @@ -856,19 +874,9 @@ static HRESULT fill_protrefs(jsdisp_t *This) return hres;
for(iter = This->prototype->props; iter < This->prototype->props+This->prototype->prop_cnt; iter++) { - hres = find_prop_name(This, iter->hash, iter->name, FALSE, &id); - if(FAILED(hres)) + hres = fill_protref(This, iter->hash, iter->name, iter - This->prototype->props); + if(hres != S_OK) return hres; - if(hres != S_OK) { - if(is_dispex_prop_id(id)) { - dispex_prop_t *p = &This->props[prop_id_to_idx(id)]; - p->type = PROP_PROTREF; - p->flags = 0; - p->u.ref = iter - This->prototype->props; - }else if(!alloc_protref(This, iter->name, iter - This->prototype->props)) { - return E_OUTOFMEMORY; - } - } }
return S_OK;
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 46e4d878417..ec48fa1c101 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 */
I just realized prop_put was wrong for indexed props on prototypes, fixed it now (same behavior as before/normal values, it's only accessors that have special behavior).
Sorry for the noise.