Gabriel Ivăncescu : jscript: Fixup PROTREF props when looking them up.

Alexandre Julliard julliard at winehq.org
Wed Nov 24 15:17:18 CST 2021


Module: wine
Branch: master
Commit: 738894a47c7c7afa9e8464774e0ee1d0b9dbf196
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=738894a47c7c7afa9e8464774e0ee1d0b9dbf196

Author: Gabriel Ivăncescu <gabrielopcode at gmail.com>
Date:   Wed Nov 24 16:10:31 2021 +0200

jscript: Fixup PROTREF props when looking them up.

Convert them to PROP_DELETE if the referenced prop in the prototype chain
doesn't exist anymore.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/jscript/dispex.c      | 26 +++++++++++++++++++++++---
 dlls/jscript/tests/lang.js |  2 ++
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c
index df81e1a0d99..ad6623f2648 100644
--- a/dlls/jscript/dispex.c
+++ b/dlls/jscript/dispex.c
@@ -60,6 +60,24 @@ struct _dispex_prop_t {
     int bucket_next;
 };
 
+static void fix_protref_prop(jsdisp_t *jsdisp, dispex_prop_t *prop)
+{
+    DWORD ref;
+
+    if(prop->type != PROP_PROTREF)
+        return;
+    ref = prop->u.ref;
+
+    while((jsdisp = jsdisp->prototype)) {
+        if(ref >= jsdisp->prop_cnt || jsdisp->props[ref].type == PROP_DELETED)
+            break;
+        if(jsdisp->props[ref].type != PROP_PROTREF)
+            return;
+        ref = jsdisp->props[ref].u.ref;
+    }
+    prop->type = PROP_DELETED;
+}
+
 static inline DISPID prop_to_id(jsdisp_t *This, dispex_prop_t *prop)
 {
     return prop - This->props;
@@ -67,10 +85,11 @@ static inline DISPID prop_to_id(jsdisp_t *This, dispex_prop_t *prop)
 
 static inline dispex_prop_t *get_prop(jsdisp_t *This, DISPID id)
 {
-    if(id < 0 || id >= This->prop_cnt || This->props[id].type == PROP_DELETED)
+    if(id < 0 || id >= This->prop_cnt)
         return NULL;
+    fix_protref_prop(This, &This->props[id]);
 
-    return This->props+id;
+    return This->props[id].type == PROP_DELETED ? NULL : &This->props[id];
 }
 
 static inline BOOL is_function_prop(dispex_prop_t *prop)
@@ -284,6 +303,7 @@ static HRESULT find_prop_name_prot(jsdisp_t *This, unsigned hash, const WCHAR *n
     if(prop && prop->type==PROP_DELETED) {
         del = prop;
     } else if(prop) {
+        fix_protref_prop(This, prop);
         *ret = prop;
         return S_OK;
     }
@@ -292,7 +312,7 @@ static HRESULT find_prop_name_prot(jsdisp_t *This, unsigned hash, const WCHAR *n
         hres = find_prop_name_prot(This->prototype, hash, name, &prop);
         if(FAILED(hres))
             return hres;
-        if(prop) {
+        if(prop && prop->type != PROP_DELETED) {
             if(del) {
                 del->type = PROP_PROTREF;
                 del->u.ref = prop - This->prototype->props;
diff --git a/dlls/jscript/tests/lang.js b/dlls/jscript/tests/lang.js
index f259c70e92e..e4f5882246a 100644
--- a/dlls/jscript/tests/lang.js
+++ b/dlls/jscript/tests/lang.js
@@ -1569,6 +1569,8 @@ ok((delete inobj.test1) === true, "delete inobj.test1 returned false");
 ok(!("test1" in inobj), "test1 is still in inobj after delete");
 ok((delete inobj.test3) === true, "delete inobj.test3 returned false");
 ok("test3" in inobj, "test3 is not in inobj after delete");
+ok((delete forinTestObj.prototype.test3) === true, "delete forinTestObj.prototype.test3 returned false");
+ok(!("test3" in inobj), "test3 is still in inobj after delete on prototype");
 
 tmp = new Object();
 tmp.test = false;




More information about the wine-cvs mailing list