[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