Signed-off-by: Jeff Smith whydoubt@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(); }