-- v2: 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 | 45 +++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 25 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index bc4463d8023..4e3ce9ff1f6 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -567,17 +567,28 @@ 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 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 +597,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)); @@ -624,22 +635,6 @@ HRESULT builtin_set_const(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t 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 4e3ce9ff1f6..297e1d0d673 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; @@ -569,7 +526,46 @@ static HRESULT prop_put(jsdisp_t *This, dispex_prop_t *prop, jsval_t val)
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 | 114 ++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 59 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 297e1d0d673..55adb9206e2 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -457,13 +457,58 @@ 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 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 +525,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,79 +545,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); + if(jsdisp->builtin_info->on_put) + jsdisp->builtin_info->on_put(jsdisp, prop->name);
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 55adb9206e2..9a235ea34cb 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -563,9 +563,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 9a235ea34cb..f02c68a8cc3 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 f02c68a8cc3..5b425261945 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 | 187 +++++++++++++++++++++++++++++--------- dlls/jscript/engine.c | 60 ++++++++---- dlls/jscript/enumerator.c | 2 - dlls/jscript/function.c | 94 +++++++++++++------ dlls/jscript/jscript.h | 21 ++++- dlls/jscript/jsregexp.c | 4 - dlls/jscript/set.c | 6 -- dlls/jscript/string.c | 72 ++++++++++----- 9 files changed, 318 insertions(+), 132 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 5b425261945..1eea0f2f0e8 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)) { @@ -465,6 +463,10 @@ HRESULT dispex_prop_get(jsdisp_t *jsdisp, IDispatch *jsthis, DISPID id, jsval_t
while(prop->type == PROP_PROTREF) { prop_obj = prop_obj->prototype; + if(!is_dispex_prop_id(prop->u.ref + 1)) { + hres = prop_obj->builtin_info->prop_get(prop_obj, jsthis, prop->u.ref + 1, r); + goto ret; + } prop = prop_obj->props + prop->u.ref; }
@@ -484,9 +486,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; @@ -497,6 +496,7 @@ HRESULT dispex_prop_get(jsdisp_t *jsdisp, IDispatch *jsthis, DISPID id, jsval_t return hres; }
+ret: TRACE("%p.%s ret %s\n", jsdisp, debugstr_w(prop->name), debugstr_jsval(*r)); return hres; } @@ -512,6 +512,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)) + return prototype_iter->builtin_info->prop_put(prototype_iter, prop_iter->u.ref + 1, val); + prop_iter = prototype_iter->props + prop_iter->u.ref; } while(prop_iter->type == PROP_PROTREF);
@@ -546,12 +549,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; @@ -590,8 +587,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 +656,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 +813,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 +925,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 +943,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 +950,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 +3131,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..f44ed46c905 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,30 @@ 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));
hres = jsval_copy(val, ©); if(FAILED(hres)) @@ -161,6 +164,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 +237,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 +253,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 +667,6 @@ static const builtin_info_t Function_info = { dispex_prop_get_name, dispex_prop_define, NULL, - NULL, - NULL, Function_gc_traverse };
@@ -646,8 +690,6 @@ static const builtin_info_t FunctionInst_info = { dispex_prop_get_name, dispex_prop_define, NULL, - NULL, - NULL, Function_gc_traverse };
@@ -839,8 +881,6 @@ static const builtin_info_t InterpretedFunction_info = { dispex_prop_get_name, dispex_prop_define, NULL, - NULL, - NULL, Function_gc_traverse };
@@ -977,8 +1017,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 */
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=144988
Your paranoid android.
=== w7u_el (32 bit report) ===
mshtml: script.c:1223: Test failed: L"/index.html?xhr.js: async_xhr2.readyState = 2" script.c:1223: Test failed: L"/index.html?xhr.js: async_xhr2.readyState = 2"
=== debian11b (64 bit WoW report) ===
Report validation errors: kernel32:console is missing some failure messages
I've sent new version with using object vtbl and mandatory methods—note how we can now override all props, not just indexed props. That's not just to get rid of special checks in callers, but also because it will be needed for those "async" props as outlined above, so it's going to be needed anyway.
And yes, it is also used for calling the DISPID_VALUE (both in `invoke_prop_func` and `jsdisp_call_value`).
`this_obj` useful only for functions, which are implemented in jscript, so they don't go through this interface, right?
On Fri Apr 12 15:33:36 2024 +0000, Jacek Caban wrote:
And yes, it is also used for calling the DISPID_VALUE (both in
`invoke_prop_func` and `jsdisp_call_value`). `this_obj` useful only for functions, which are implemented in jscript, so they don't go through this interface, right?
Yes the new "proxy functions" on jscript side don't use this interface (and so, neither accessors). But I meant using it on objects' DISPID_VALUE. Simplest example is probably imagine calling InvokeEx on a jscript proxy. It will end up in jsdisp_call_value which needs to forward it to the mshtml object.
Of course, the interface could probably be simplified, but we'll still have to pass the "this" pointer separately.
On Fri Apr 12 16:37:32 2024 +0000, Gabriel Ivăncescu wrote:
Yes the new "proxy functions" on jscript side don't use this interface (and so, neither accessors). But I meant using it on objects' DISPID_VALUE. Simplest example is probably imagine calling InvokeEx on a jscript proxy. It will end up in jsdisp_call_value which needs to forward it to the mshtml object. Of course, the interface could probably be simplified, but we'll still have to pass the "this" pointer separately.
Why would we ever want to pass it to any MSHTML object?
On Fri Apr 12 17:46:51 2024 +0000, Jacek Caban wrote:
Why would we ever want to pass it to any MSHTML object?
Oh, I see what you mean. You want to hardcode on jscript the fact that mshtml does not make use of it for DISPID_VALUE? I didn't check this, but it seems plausible and what you meant, right?
I was just trying to forward everything *as if* InvokeEx was called directly on the mshtml object itself (like in pre IE8 modes), i.e. making it "generic". But if that's not a requirement I'll re-evaluate.
From a quick look, it does seem like it's not used, though. So in retrospect, I can probably remove it, though I'll need to test to make sure.
Oh, I see what you mean. You want to hardcode on jscript the fact that mshtml does not make use of it for DISPID_VALUE? I didn't check this, but it seems plausible and what you meant, right?
Yes, kind of, but I wouldn't call it 'hardcoding'. MSHTML may have properties with `DISPID_VALUE`, but they should have no reason to deal with 'this' argument; it's meaningful only for functions and having functions implemented in jscript is a design decision.
I was just trying to forward everything _as if_ InvokeEx was called directly on the mshtml object itself (like in pre IE8 modes), i.e. making it "generic".
Do you intend to use this interface on pre IE8 as well?
On Fri Apr 12 19:07:47 2024 +0000, Jacek Caban wrote:
Oh, I see what you mean. You want to hardcode on jscript the fact that
mshtml does not make use of it for DISPID_VALUE? I didn't check this, but it seems plausible and what you meant, right? Yes, kind of, but I wouldn't call it 'hardcoding'. MSHTML may have properties with `DISPID_VALUE`, but they should have no reason to deal with 'this' argument; it's meaningful only for functions and having functions implemented in jscript is a design decision.
I was just trying to forward everything _as if_ InvokeEx was called
directly on the mshtml object itself (like in pre IE8 modes), i.e. making it "generic". Do you intend to use this interface on pre IE8 as well?
Nope, the only thing I extend to IE8 and below are the cycle collection integration, since it helps as well (with only like a single extra line of code).
What I meant is that, in theory, InvokeEx (on mshtml side!) does receive a "this" argument, in IE8 and below, simplest case is when called from C code. Even though no mshtml object seems to make use of it. So I wanted to keep it generic and play it safe and thus "pass the same thing" if a jscript proxy receives that "this" arg, but if it's not required I'll just get rid of it. :)
BTW for this MR, I already got rid of "on_put" now in a patch, since we override the prop_put on Arrays. That's an example of how the jscript proxy would work as well, except it would be at the top of the function before it's forwarded.
On Fri Apr 12 19:18:49 2024 +0000, Gabriel Ivăncescu wrote:
Nope, the only thing I extend to IE8 and below are the cycle collection integration, since it helps as well (with only like a single extra line of code). What I meant is that, in theory, InvokeEx (on mshtml side!) does receive a "this" argument, in IE8 and below, simplest case is when called from C code. Even though no mshtml object seems to make use of it. So I wanted to keep it generic and play it safe and thus "pass the same thing" if a jscript proxy receives that "this" arg, but if it's not required I'll just get rid of it. :) BTW for this MR, I already got rid of "on_put" now in a patch, since we override the prop_put on Arrays. That's an example of how the jscript proxy would work as well, except it would be at the top of the function before it's forwarded.
It's better now, but I still can't review it on its own while MSHTML bindings design is so blurry. I think it will be better to have a bit more complete prototype for the context before upstreaming its pieces.
On Tue Apr 16 08:49:15 2024 +0000, Jacek Caban wrote:
It's better now, but I still can't review it on its own while MSHTML bindings design is so blurry. I think it will be better to have a bit more complete prototype for the context before upstreaming its pieces.
Well this MR technically isn't about that, is it? It's for indexed props and Typed Arrays (which will come immediately now).
And having something like this is clearly the most "extensible" since it allows overriding every prop's behavior.
Should I rewrite my mshtml-integration patches to use this now? I was actually waiting for it to go upstream first so I only have to do it once in whatever shape it's in—I'm not attached to any particular method, as long as it works.
Well this MR technically isn't about that, is it?
I think it should, see my earlier comments.
And having something like this is clearly the most "extensible" since it allows overriding every prop's behavior.
There are many solutions, we're looking for the one that fits our needs best. I can't review that aspect in its current form and I don't share your confidence about it.