[PATCH 2/2] jscript: Implement Object.prototype.__proto__ property.

Jeff Smith whydoubt at gmail.com
Mon Mar 23 15:30:10 CDT 2020


Signed-off-by: Jeff Smith <whydoubt at gmail.com>
---
 dlls/jscript/object.c    | 59 +++++++++++++++++++++++++++++++++++++++-
 dlls/mshtml/tests/es5.js | 33 +++++++++++++++++++++-
 2 files changed, 90 insertions(+), 2 deletions(-)

diff --git a/dlls/jscript/object.c b/dlls/jscript/object.c
index ef249e91a9..8fdbd8cad7 100644
--- a/dlls/jscript/object.c
+++ b/dlls/jscript/object.c
@@ -198,6 +198,57 @@ static HRESULT Object_isPrototypeOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD fla
     return E_NOTIMPL;
 }
 
+static HRESULT Object_get_null(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r)
+{
+    TRACE("%p \n", jsthis);
+
+    *r = jsval_null();
+    return S_OK;
+}
+
+static HRESULT Object_get_proto(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r)
+{
+    TRACE("%p \n", jsthis);
+
+    *r = jsthis->prototype
+        ? jsval_obj(jsdisp_addref(jsthis->prototype))
+        : jsval_undefined();
+    return S_OK;
+}
+
+static HRESULT Object_set_proto(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t value)
+{
+    IDispatch *proto_disp;
+    jsdisp_t *proto_obj = NULL;
+    HRESULT hres;
+
+    TRACE("%p %s\n", jsthis, debugstr_jsval(value));
+
+    if (!jsthis->prototype)
+        return S_OK;
+
+    if (!is_object_instance(value) && !is_null(value))
+        return S_OK;
+
+    if (!is_null_instance(value))
+    {
+        hres = to_object(ctx, value, &proto_disp);
+        if(FAILED(hres))
+            return hres;
+
+        proto_obj = to_jsdisp(proto_disp);
+        if(!proto_obj) {
+            FIXME("non-JS list obj\n");
+            IDispatch_Release(proto_disp);
+            return E_NOTIMPL;
+        }
+    }
+
+    jsdisp_release(jsthis->prototype);
+    jsthis->prototype = proto_obj;
+    return S_OK;
+}
+
 static HRESULT Object_get_value(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r)
 {
     jsstr_t *ret;
@@ -221,6 +272,7 @@ static const builtin_prop_t Object_props[] = {
     {L"hasOwnProperty",        Object_hasOwnProperty,        PROPF_METHOD|1},
     {L"isPrototypeOf",         Object_isPrototypeOf,         PROPF_METHOD|1},
     {L"propertyIsEnumerable",  Object_propertyIsEnumerable,  PROPF_METHOD|1},
+    {L"__proto__",             NULL, 0,                      Object_get_null},
     {L"toLocaleString",        Object_toLocaleString,        PROPF_METHOD},
     {L"toString",              Object_toString,              PROPF_METHOD},
     {L"valueOf",               Object_valueOf,               PROPF_METHOD}
@@ -235,10 +287,15 @@ static const builtin_info_t Object_info = {
     NULL
 };
 
+static const builtin_prop_t ObjectInst_props[] = {
+    {L"__proto__",             NULL, 0,                      Object_get_proto, Object_set_proto}
+};
+
 static const builtin_info_t ObjectInst_info = {
     JSCLASS_OBJECT,
     {NULL, NULL,0, Object_get_value},
-    0, NULL,
+    ARRAY_SIZE(ObjectInst_props),
+    ObjectInst_props,
     Object_destructor,
     NULL
 };
diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js
index 6b5d04a959..c3c889ae2d 100644
--- a/dlls/mshtml/tests/es5.js
+++ b/dlls/mshtml/tests/es5.js
@@ -734,35 +734,66 @@ function test_getPrototypeOf() {
 
     ok(Object.getPrototypeOf(new Object()) === Object.prototype,
        "Object.getPrototypeOf(new Object()) !== Object.prototype");
+    ok((new Object()).__proto__ === Object.prototype,
+       "(new Object()).__proto__ !== Object.prototype");
 
     function Constr() {}
     var obj = new Constr();
     ok(Object.getPrototypeOf(Constr.prototype) === Object.prototype,
        "Object.getPrototypeOf(Constr.prototype) !== Object.prototype");
+    ok(Constr.prototype.__proto__ === Object.prototype,
+       "Constr.prototype.__proto__ !== Object.prototype");
     ok(Object.getPrototypeOf(obj) === Constr.prototype,
        "Object.getPrototypeOf(obj) !== Constr.prototype");
+    ok(obj.__proto__ === Constr.prototype,
+       "obj.__proto__ !== Constr.prototype");
 
     var proto = new Object();
     Constr.prototype = proto;
     ok(Object.getPrototypeOf(obj) != proto,
        "Object.getPrototypeOf(obj) == proto");
+    ok(obj.__proto__ !== proto, "obj.__proto__ === proto");
     obj = new Constr();
     ok(Object.getPrototypeOf(obj) === proto,
        "Object.getPrototypeOf(obj) !== proto");
     ok(Object.getPrototypeOf(obj, 2, 3, 4) === proto,
        "Object.getPrototypeOf(obj) !== proto");
+    ok(obj.__proto__ === proto, "obj.__proto__ !== proto");
 
     ok(Object.getPrototypeOf(Object.prototype) === null,
        "Object.getPrototypeOf(Object.prototype) !== null");
+    ok(Object.prototype.__proto__ === null,
+       "Object.prototype.__proto__ !== null");
 
     obj = Object.create(proto = { test: 1 });
     ok(Object.getPrototypeOf(obj) === proto,
        "Object.getPrototypeOf(obj) !== proto");
+    ok(obj.__proto__ === proto, "obj.__proto__ !== proto");
     ok(obj.test === 1, "obj.test = " + obj.test);
 
+    obj.__proto__ = Number.prototype;
+    ok(Object.getPrototypeOf(obj) === Number.prototype,
+       "Object.getPrototypeOf(obj) !== Number.prototype");
+    obj.__proto__ = "won't change";
+    ok(Object.getPrototypeOf(obj) === Number.prototype,
+       "Object.getPrototypeOf(obj) !== Number.prototype");
+    obj.__proto__ = null;
+    ok(Object.getPrototypeOf(obj) === null,
+       "Object.getPrototypeOf(obj) !== null");
+    ok(obj.__proto__ === undefined, "obj.__proto__ !== undefined");
+    obj.__proto__ = Number.prototype;
+    ok(Object.getPrototypeOf(obj) === null,
+       "Object.getPrototypeOf(obj) !== null");
+
     obj = Object.create(null);
     ok(!("toString" in obj), "toString is in obj");
-    ok(Object.getPrototypeOf(obj) === null, "Object.getPrototypeOf(obj) = " + Object.getPrototypeOf(obj));
+    ok(Object.getPrototypeOf(obj) === null,
+       "Object.getPrototypeOf(obj) = " + Object.getPrototypeOf(obj));
+    ok(obj.__proto__ === undefined, "obj.__proto__ !== undefined");
+
+    obj.__proto__ = Number.prototype;
+    ok(Object.getPrototypeOf(obj) === null,
+       "Object.getPrototypeOf(obj) !== null");
 
     next_test();
 }
-- 
2.23.0




More information about the wine-devel mailing list