-- v2: mshtml: Use actual referenced prop flags for window script props. jscript: Make most builtin global objects configurable. jscript: Delete external props before redefining them.
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 8 +++++++- dlls/mshtml/tests/es5.js | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index aa81de7ad75..1dd18fcc2ee 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -3282,8 +3282,14 @@ HRESULT jsdisp_define_property(jsdisp_t *obj, const WCHAR *name, property_desc_t if(desc->explicit_value) { if(prop->type == PROP_JSVAL) jsval_release(prop->u.val); - else + else { + if(prop->type == PROP_EXTERN && obj->builtin_info->prop_delete) { + hres = obj->builtin_info->prop_delete(obj, prop->u.id); + if(FAILED(hres)) + return hres; + } prop->type = PROP_JSVAL; + } hres = jsval_copy(desc->value, &prop->u.val); if(FAILED(hres)) { prop->u.val = jsval_undefined(); diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 3adb7cc1d61..efc3bf0f8d1 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -2153,6 +2153,23 @@ sync_test("builtin_context", function() { ok(obj.length === 1, "obj.length = " + obj.length); });
+sync_test("globals override", function() { + wineprop = 1337; /* global */ + ok(window.hasOwnProperty("wineprop"), "wineprop not a prop of window"); + ok(window.wineprop === 1337, "window.wineprop = " + window.wineprop); + ok(wineprop === 1337, "wineprop = " + wineprop); + + var r = Object.defineProperty(window, "wineprop", { value: 42, configurable: true }); + ok(r === window, "defineProperty(window.wineprop) returned " + r); + ok(window.hasOwnProperty("wineprop"), "wineprop not a prop of window after override"); + ok(window.wineprop === 42, "window.wineprop after override = " + window.wineprop); + ok(wineprop === 42, "wineprop after override = " + wineprop); + + r = (delete window.wineprop); + ok(r === true, "delete window.wineprop returned " + r); + ok(!("wineprop" in window), "wineprop in window after delete"); +}); + sync_test("host this", function() { var tests = [ undefined, null, external.nullDisp, function() {}, [0], "foobar", true, 42, new Number(42), external.testHostContext(true), window, document ]; var i, obj = Object.create(Function.prototype);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/global.c | 42 +++++++++---------- dlls/jscript/set.c | 6 +-- dlls/mshtml/tests/es5.js | 91 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 114 insertions(+), 25 deletions(-)
diff --git a/dlls/jscript/global.c b/dlls/jscript/global.c index 2653d72cd2b..bb2fd26335b 100644 --- a/dlls/jscript/global.c +++ b/dlls/jscript/global.c @@ -943,7 +943,7 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype) if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"Function", PROPF_WRITABLE, + hres = jsdisp_define_data_property(ctx->global, L"Function", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(ctx->function_constr)); if(FAILED(hres)) return hres; @@ -952,7 +952,7 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype) if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"Object", PROPF_WRITABLE, + hres = jsdisp_define_data_property(ctx->global, L"Object", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(ctx->object_constr)); if(FAILED(hres)) return hres; @@ -961,7 +961,7 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype) if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"Array", PROPF_WRITABLE, + hres = jsdisp_define_data_property(ctx->global, L"Array", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(ctx->array_constr)); if(FAILED(hres)) return hres; @@ -970,7 +970,7 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype) if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"Boolean", PROPF_WRITABLE, + hres = jsdisp_define_data_property(ctx->global, L"Boolean", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(ctx->bool_constr)); if(FAILED(hres)) return hres; @@ -979,7 +979,7 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype) if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"Date", PROPF_WRITABLE, + hres = jsdisp_define_data_property(ctx->global, L"Date", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(ctx->date_constr)); if(FAILED(hres)) return hres; @@ -988,7 +988,7 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype) if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"Enumerator", PROPF_WRITABLE, + hres = jsdisp_define_data_property(ctx->global, L"Enumerator", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(ctx->enumerator_constr)); if(FAILED(hres)) return hres; @@ -997,42 +997,42 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype) if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"Error", PROPF_WRITABLE, + hres = jsdisp_define_data_property(ctx->global, L"Error", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(ctx->error_constr)); if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"EvalError", PROPF_WRITABLE, + hres = jsdisp_define_data_property(ctx->global, L"EvalError", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(ctx->eval_error_constr)); if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"RangeError", PROPF_WRITABLE, + hres = jsdisp_define_data_property(ctx->global, L"RangeError", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(ctx->range_error_constr)); if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"ReferenceError", PROPF_WRITABLE, + hres = jsdisp_define_data_property(ctx->global, L"ReferenceError", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(ctx->reference_error_constr)); if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"RegExpError", PROPF_WRITABLE, + hres = jsdisp_define_data_property(ctx->global, L"RegExpError", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(ctx->regexp_error_constr)); if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"SyntaxError", PROPF_WRITABLE, + hres = jsdisp_define_data_property(ctx->global, L"SyntaxError", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(ctx->syntax_error_constr)); if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"TypeError", PROPF_WRITABLE, + hres = jsdisp_define_data_property(ctx->global, L"TypeError", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(ctx->type_error_constr)); if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"URIError", PROPF_WRITABLE, + hres = jsdisp_define_data_property(ctx->global, L"URIError", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(ctx->uri_error_constr)); if(FAILED(hres)) return hres; @@ -1041,7 +1041,7 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype) if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"Number", PROPF_WRITABLE, + hres = jsdisp_define_data_property(ctx->global, L"Number", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(ctx->number_constr)); if(FAILED(hres)) return hres; @@ -1050,7 +1050,7 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype) if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"RegExp", PROPF_WRITABLE, + hres = jsdisp_define_data_property(ctx->global, L"RegExp", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(ctx->regexp_constr)); if(FAILED(hres)) return hres; @@ -1059,7 +1059,7 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype) if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"String", PROPF_WRITABLE, + hres = jsdisp_define_data_property(ctx->global, L"String", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(ctx->string_constr)); if(FAILED(hres)) return hres; @@ -1068,7 +1068,7 @@ static HRESULT init_constructors(script_ctx_t *ctx, jsdisp_t *object_prototype) if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"VBArray", PROPF_WRITABLE, + hres = jsdisp_define_data_property(ctx->global, L"VBArray", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(ctx->vbarray_constr)); if(FAILED(hres)) return hres; @@ -1105,7 +1105,7 @@ HRESULT init_global(script_ctx_t *ctx) if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"Math", PROPF_WRITABLE, jsval_obj(math)); + hres = jsdisp_define_data_property(ctx->global, L"Math", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(math)); jsdisp_release(math); if(FAILED(hres)) return hres; @@ -1117,7 +1117,7 @@ HRESULT init_global(script_ctx_t *ctx) if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"JSON", PROPF_WRITABLE, jsval_obj(json)); + hres = jsdisp_define_data_property(ctx->global, L"JSON", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(json)); jsdisp_release(json); if(FAILED(hres)) return hres; @@ -1127,7 +1127,7 @@ HRESULT init_global(script_ctx_t *ctx) if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"ActiveXObject", PROPF_WRITABLE, + hres = jsdisp_define_data_property(ctx->global, L"ActiveXObject", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(constr)); jsdisp_release(constr); if(FAILED(hres)) diff --git a/dlls/jscript/set.c b/dlls/jscript/set.c index 5a568607a43..c114e3fd6e2 100644 --- a/dlls/jscript/set.c +++ b/dlls/jscript/set.c @@ -903,7 +903,7 @@ HRESULT init_set_constructor(script_ctx_t *ctx) if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"Set", PROPF_WRITABLE, + hres = jsdisp_define_data_property(ctx->global, L"Set", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(constructor)); jsdisp_release(constructor); if(FAILED(hres)) @@ -918,7 +918,7 @@ HRESULT init_set_constructor(script_ctx_t *ctx) if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"Map", PROPF_WRITABLE, + hres = jsdisp_define_data_property(ctx->global, L"Map", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(constructor)); jsdisp_release(constructor); if(FAILED(hres)) @@ -933,7 +933,7 @@ HRESULT init_set_constructor(script_ctx_t *ctx) if(FAILED(hres)) return hres;
- hres = jsdisp_define_data_property(ctx->global, L"WeakMap", PROPF_WRITABLE, + hres = jsdisp_define_data_property(ctx->global, L"WeakMap", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(constructor)); jsdisp_release(constructor); return hres; diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index efc3bf0f8d1..9d6a4eb8418 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -23,6 +23,7 @@ var JS_E_NUMBER_EXPECTED = 0x800a1389; var JS_E_FUNCTION_EXPECTED = 0x800a138a; var JS_E_DATE_EXPECTED = 0x800a138e; var JS_E_OBJECT_EXPECTED = 0x800a138f; +var JS_E_UNDEFINED_VARIABLE = 0x800a1391; var JS_E_BOOLEAN_EXPECTED = 0x800a1392; var JS_E_VBARRAY_EXPECTED = 0x800a1395; var JS_E_ENUMERATOR_EXPECTED = 0x800a1397; @@ -2159,7 +2160,7 @@ sync_test("globals override", function() { ok(window.wineprop === 1337, "window.wineprop = " + window.wineprop); ok(wineprop === 1337, "wineprop = " + wineprop);
- var r = Object.defineProperty(window, "wineprop", { value: 42, configurable: true }); + var i, desc, r = Object.defineProperty(window, "wineprop", { value: 42, configurable: true }); ok(r === window, "defineProperty(window.wineprop) returned " + r); ok(window.hasOwnProperty("wineprop"), "wineprop not a prop of window after override"); ok(window.wineprop === 42, "window.wineprop after override = " + window.wineprop); @@ -2168,6 +2169,94 @@ sync_test("globals override", function() { r = (delete window.wineprop); ok(r === true, "delete window.wineprop returned " + r); ok(!("wineprop" in window), "wineprop in window after delete"); + + /* configurable */ + var builtins = [ + "ActiveXObject", + "Array", + "ArrayBuffer", + "Boolean", + "CollectGarbage", + "DataView", + "Date", + "decodeURI", + "decodeURIComponent", + "encodeURI", + "encodeURIComponent", + "Enumerator", + "Error", + "escape", + "EvalError", + "Function", + "isFinite", + "isNaN", + "JSON", + "Map", + "Math", + "Number", + "parseFloat", + "parseInt", + "RangeError", + "ReferenceError", + "RegExp", + "ScriptEngine", + "ScriptEngineBuildVersion", + "ScriptEngineMajorVersion", + "ScriptEngineMinorVersion", + "Set", + "String", + "SyntaxError", + "TypeError", + "unescape", + "URIError", + "VBArray", + "WeakMap" + ]; + for(i = 0; i < builtins.length; i++) { + desc = Object.getOwnPropertyDescriptor(window, builtins[i]); + ok(desc !== undefined, "getOwnPropertyDescriptor('" + builtins[i] + "' returned undefined"); + ok(desc.configurable === true, builtins[i] + " not configurable"); + ok(desc.enumerable === false, builtins[i] + " is enumerable"); + ok(desc.writable === true, builtins[i] + " not writable"); + + r = Object.defineProperty(window, builtins[i], { value: 12, configurable: true, writable: true }); + ok(r === window, "defineProperty('" + builtins[i] + "' returned " + r); + r = Object.getOwnPropertyDescriptor(window, builtins[i]); + ok(r !== undefined, "getOwnPropertyDescriptor('" + builtins[i] + "' after override returned undefined"); + ok(r.value === 12, builtins[i] + " value = " + r.value); + + r = eval(builtins[i]); + ok(r === window[builtins[i]], "Global " + builtins[i] + " does not match redefined window." + builtins[i]); + r = (delete window[builtins[i]]); + ok(r === true, "delete window." + builtins[i] + " returned " + r); + ok(!(builtins[i] in window), builtins[i] + " in window after delete"); + try { + eval(builtins[i]); + ok(false, "expected exception retrieving global " + builtins[i] + " after delete."); + }catch(ex) { + r = ex.number >>> 0; + ok(r === JS_E_UNDEFINED_VARIABLE, "retrieving global " + builtins[i] + " after delete threw " + r); + } + + r = Object.defineProperty(window, builtins[i], desc); + ok(r === window, "defineProperty('" + builtins[i] + "' to restore returned " + r); + } + + /* non-configurable */ + builtins = [ + "undefined", + "Infinity", + "NaN" + ]; + for(i = 0; i < builtins.length; i++) { + desc = Object.getOwnPropertyDescriptor(window, builtins[i]); + ok(desc !== undefined, "getOwnPropertyDescriptor('" + builtins[i] + "' returned undefined"); + todo_wine. + ok(desc.configurable === false, builtins[i] + " is configurable"); + ok(desc.enumerable === false, builtins[i] + " is enumerable"); + todo_wine. + ok(desc.writable === false, builtins[i] + " is writable"); + } });
sync_test("host this", function() {
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 12 +++++++++++- dlls/jscript/jsdisp.idl | 1 + dlls/mshtml/htmlwindow.c | 27 +++++++++++++++++++++++++-- dlls/mshtml/tests/es5.js | 2 -- 4 files changed, 37 insertions(+), 5 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 1dd18fcc2ee..8274862541c 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -2388,7 +2388,16 @@ static void WINAPI WineJSDispatch_Free(IWineJSDispatch *iface) { jsdisp_t *This = impl_from_IWineJSDispatch(iface); jsdisp_free(This); - } +} + +static DWORD WINAPI WineJSDispatch_GetPropFlags(IWineJSDispatch *iface, DISPID id) +{ + jsdisp_t *This = impl_from_IWineJSDispatch(iface); + dispex_prop_t *prop = get_prop(This, id); + + assert(prop != NULL); + return prop->flags & PROPF_PUBLIC_MASK; +}
static HRESULT WINAPI WineJSDispatch_GetScriptGlobal(IWineJSDispatch *iface, IWineJSDispatchHost **ret) { @@ -2422,6 +2431,7 @@ static IWineJSDispatchVtbl DispatchExVtbl = { DispatchEx_GetNextDispID, DispatchEx_GetNameSpaceParent, WineJSDispatch_Free, + WineJSDispatch_GetPropFlags, WineJSDispatch_GetScriptGlobal, };
diff --git a/dlls/jscript/jsdisp.idl b/dlls/jscript/jsdisp.idl index 051f819e817..eceb9886f77 100644 --- a/dlls/jscript/jsdisp.idl +++ b/dlls/jscript/jsdisp.idl @@ -51,6 +51,7 @@ interface IWineJSDispatchHost; interface IWineJSDispatch : IDispatchEx { void Free(); + DWORD GetPropFlags(DISPID id); HRESULT GetScriptGlobal(IWineJSDispatchHost **ret); }
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index b6f66627dd9..07c16074ea8 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -4030,6 +4030,7 @@ HRESULT HTMLWindow_get_prop_desc(DispatchEx *dispex, DISPID id, struct property_ { HTMLInnerWindow *This = impl_from_DispatchEx(dispex); global_prop_t *prop; + HRESULT hres;
if(id - MSHTML_DISPID_CUSTOM_MIN >= This->global_prop_cnt) return DISP_E_MEMBERNOTFOUND; @@ -4038,9 +4039,31 @@ HRESULT HTMLWindow_get_prop_desc(DispatchEx *dispex, DISPID id, struct property_ desc->name = prop->name; desc->id = id; desc->flags = PROPF_WRITABLE | PROPF_CONFIGURABLE; - if(prop->type == GLOBAL_DISPEXVAR) - desc->flags |= PROPF_ENUMERABLE; desc->iid = 0; + + switch(prop->type) { + case GLOBAL_SCRIPTVAR: { + IWineJSDispatch *jsdisp; + IDispatch *disp; + + if(!(disp = get_script_disp(prop->script_host))) + return E_UNEXPECTED; + + hres = IDispatch_QueryInterface(disp, &IID_IWineJSDispatch, (void**)&jsdisp); + IDispatch_Release(disp); + if(SUCCEEDED(hres)) { + desc->flags = IWineJSDispatch_GetPropFlags(jsdisp, prop->id); + IWineJSDispatch_Release(jsdisp); + } + break; + } + case GLOBAL_DISPEXVAR: + desc->flags |= PROPF_ENUMERABLE; + break; + default: + break; + } + return S_OK; }
diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 9d6a4eb8418..0033a06fa3c 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -2251,10 +2251,8 @@ sync_test("globals override", function() { for(i = 0; i < builtins.length; i++) { desc = Object.getOwnPropertyDescriptor(window, builtins[i]); ok(desc !== undefined, "getOwnPropertyDescriptor('" + builtins[i] + "' returned undefined"); - todo_wine. ok(desc.configurable === false, builtins[i] + " is configurable"); ok(desc.enumerable === false, builtins[i] + " is enumerable"); - todo_wine. ok(desc.writable === false, builtins[i] + " is writable"); } });
Ok redone this without replacing the global host, that should still fix it.
Jacek Caban (@jacek) commented about dlls/mshtml/htmlwindow.c:
desc->name = prop->name; desc->id = id; desc->flags = PROPF_WRITABLE | PROPF_CONFIGURABLE;
- if(prop->type == GLOBAL_DISPEXVAR)
desc->iid = 0;desc->flags |= PROPF_ENUMERABLE;
- switch(prop->type) {
- case GLOBAL_SCRIPTVAR: {
IWineJSDispatch *jsdisp;
IDispatch *disp;
if(!(disp = get_script_disp(prop->script_host)))
return E_UNEXPECTED;
hres = IDispatch_QueryInterface(disp, &IID_IWineJSDispatch, (void**)&jsdisp);
We have `script_dispex` now in the script host. You could store it as `IWineJSDispatch` and just use it here, without any QI.
Jacek Caban (@jacek) commented about dlls/jscript/dispex.c:
{ jsdisp_t *This = impl_from_IWineJSDispatch(iface); jsdisp_free(This);
- }
+}
+static DWORD WINAPI WineJSDispatch_GetPropFlags(IWineJSDispatch *iface, DISPID id) +{
- jsdisp_t *This = impl_from_IWineJSDispatch(iface);
- dispex_prop_t *prop = get_prop(This, id);
- assert(prop != NULL);
- return prop->flags & PROPF_PUBLIC_MASK;
This potentially returns flags of deleted properties, I think that instead of asserting here we should return an error for deleted properties.
More generally, it feels suboptimal that we need two separate calls to JS to check if the prop is deleted (!6721) and get its flags. I can see how a single call doesn't fit current MSHTML internals and that's fine for now, but this is also used by `dispex_prop_name`, for which returning an error here seems right.