jscript: Implement Object.prototype.__defineSetter__.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com> Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
8eac0fc60a
commit
9785781fbc
|
@ -337,6 +337,49 @@ done:
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT Object_defineSetter(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
|
||||
{
|
||||
property_desc_t desc;
|
||||
const WCHAR *name;
|
||||
jsstr_t *name_str;
|
||||
jsdisp_t *jsthis;
|
||||
HRESULT hres;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
if(!is_object_instance(vthis) || !(jsthis = to_jsdisp(get_object(vthis))))
|
||||
goto done;
|
||||
|
||||
if(argc < 2 || !is_object_instance(argv[1]))
|
||||
return JS_E_FUNCTION_EXPECTED;
|
||||
|
||||
desc.setter = to_jsdisp(get_object(argv[1]));
|
||||
if(!desc.setter) {
|
||||
FIXME("setter is not JS object\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
/* FIXME: Check IsCallable */
|
||||
|
||||
hres = to_flat_string(ctx, argv[0], &name_str, &name);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
desc.flags = desc.mask = PROPF_CONFIGURABLE | PROPF_ENUMERABLE;
|
||||
desc.explicit_getter = FALSE;
|
||||
desc.explicit_setter = TRUE;
|
||||
desc.explicit_value = FALSE;
|
||||
desc.getter = NULL;
|
||||
hres = jsdisp_define_property(jsthis, name, &desc);
|
||||
|
||||
jsstr_release(name_str);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
done:
|
||||
if(r)
|
||||
*r = jsval_undefined();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT Object_get_proto_(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
|
||||
{
|
||||
jsdisp_t *jsthis;
|
||||
|
@ -409,6 +452,7 @@ static void Object_destructor(jsdisp_t *dispex)
|
|||
|
||||
static const builtin_prop_t Object_props[] = {
|
||||
{L"__defineGetter__", Object_defineGetter, PROPF_METHOD|PROPF_ES6|2},
|
||||
{L"__defineSetter__", Object_defineSetter, PROPF_METHOD|PROPF_ES6|2},
|
||||
{L"hasOwnProperty", Object_hasOwnProperty, PROPF_METHOD|1},
|
||||
{L"isPrototypeOf", Object_isPrototypeOf, PROPF_METHOD|1},
|
||||
{L"propertyIsEnumerable", Object_propertyIsEnumerable, PROPF_METHOD|1},
|
||||
|
|
|
@ -1503,6 +1503,101 @@ sync_test("__defineGetter__", function() {
|
|||
ok(x.bar === "wine", "x.bar with getter = " + x.bar);
|
||||
});
|
||||
|
||||
sync_test("__defineSetter__", function() {
|
||||
var v = document.documentMode;
|
||||
var r, x = 42;
|
||||
|
||||
if(v < 11) {
|
||||
ok(x.__defineSetter__ === undefined, "x.__defineSetter__ = " + x.__defineSetter__);
|
||||
ok(!("__defineSetter__" in Object), "Object.__defineSetter__ = " + Object.__defineSetter__);
|
||||
return;
|
||||
}
|
||||
ok(Object.prototype.hasOwnProperty("__defineSetter__"), "__defineSetter__ is not a property of Object.prototype");
|
||||
ok(Object.prototype.__defineSetter__.length === 2, "__defineSetter__.length = " + Object.prototype.__defineSetter__.length);
|
||||
|
||||
function getter() { return "wine"; }
|
||||
function setter(val) { this.setterVal = val - 1; }
|
||||
|
||||
r = x.__defineSetter__("foo", setter);
|
||||
ok(r === undefined, "__defineSetter__ on 42 returned " + r);
|
||||
ok(x.foo === undefined, "42.foo = " + x.foo);
|
||||
|
||||
x = {};
|
||||
r = x.__defineSetter__("foo", setter);
|
||||
ok(r === undefined, "__defineSetter__ returned " + r);
|
||||
ok(x.setterVal === undefined, "x.setterVal = " + x.setterVal);
|
||||
x.foo = 13;
|
||||
ok(x.setterVal === 12, "x.setterVal = " + x.setterVal);
|
||||
r = Object.getOwnPropertyDescriptor(x, "foo");
|
||||
ok(r.value === undefined, "x.foo value = " + r.value);
|
||||
ok(r.get === undefined, "x.foo get = " + r.get);
|
||||
ok(r.set === setter, "x.foo set = " + r.set);
|
||||
ok(r.writable === undefined, "x.foo writable = " + r.writable);
|
||||
ok(r.enumerable === true, "x.foo enumerable = " + r.enumerable);
|
||||
ok(r.configurable === true, "x.foo configurable = " + r.configurable);
|
||||
|
||||
Object.defineProperty(x, "foo", { get: getter, set: undefined, configurable: false });
|
||||
r = Object.getOwnPropertyDescriptor(x, "foo");
|
||||
ok(r.value === undefined, "x.foo getter value = " + r.value);
|
||||
ok(r.get === getter, "x.foo getter get = " + r.get);
|
||||
ok(r.set === undefined, "x.foo getter set = " + r.set);
|
||||
ok(r.writable === undefined, "x.foo getter writable = " + r.writable);
|
||||
ok(r.enumerable === true, "x.foo getter enumerable = " + r.enumerable);
|
||||
ok(r.configurable === false, "x.foo getter configurable = " + r.configurable);
|
||||
try {
|
||||
x.__defineSetter__("foo", setter);
|
||||
ok(false, "expected exception calling __defineSetter__ on non-configurable property");
|
||||
}catch(e) {
|
||||
ok(e.number === 0xa13d6 - 0x80000000, "__defineSetter__ on non-configurable property threw exception " + e.number);
|
||||
}
|
||||
|
||||
r = Object.prototype.__defineSetter__.call(undefined, "bar", setter);
|
||||
ok(r === undefined, "__defineSetter__ on undefined returned " + r);
|
||||
r = Object.prototype.__defineSetter__.call(null, "bar", setter);
|
||||
ok(r === undefined, "__defineSetter__ on null returned " + r);
|
||||
r = x.__defineSetter__(null, setter);
|
||||
ok(r === undefined, "__defineSetter__ null prop returned " + r);
|
||||
x["null"] = 100;
|
||||
ok(x.setterVal === 99, "x.setterVal after setting x.null = " + x.setterVal);
|
||||
r = x.__defineSetter__(50, setter);
|
||||
ok(r === undefined, "__defineSetter__ 50 prop returned " + r);
|
||||
x["50"] = 33;
|
||||
ok(x.setterVal === 32, "x.setterVal after setting x.50 = " + x.setterVal);
|
||||
|
||||
try {
|
||||
x.__defineSetter__("bar", true);
|
||||
ok(false, "expected exception calling __defineSetter__ with bool");
|
||||
}catch(e) {
|
||||
ok(e.number === 0xa138a - 0x80000000, "__defineSetter__ with bool threw exception " + e.number);
|
||||
}
|
||||
try {
|
||||
x.__defineSetter__("bar", undefined);
|
||||
ok(false, "expected exception calling __defineSetter__ with undefined");
|
||||
}catch(e) {
|
||||
ok(e.number === 0xa138a - 0x80000000, "__defineSetter__ with undefined threw exception " + e.number);
|
||||
}
|
||||
try {
|
||||
x.__defineSetter__("bar", null);
|
||||
ok(false, "expected exception calling __defineSetter__ with null");
|
||||
}catch(e) {
|
||||
ok(e.number === 0xa138a - 0x80000000, "__defineSetter__ with null threw exception " + e.number);
|
||||
}
|
||||
try {
|
||||
Object.prototype.__defineSetter__.call(x, "bar");
|
||||
ok(false, "expected exception calling __defineSetter__ with only one arg");
|
||||
}catch(e) {
|
||||
ok(e.number === 0xa138a - 0x80000000, "__defineSetter__ with only one arg threw exception " + e.number);
|
||||
}
|
||||
|
||||
x.bar = "test";
|
||||
ok(x.bar === "test", "x.bar = " + x.bar);
|
||||
x.__defineSetter__("bar", setter);
|
||||
ok(x.bar === undefined, "x.bar with setter = " + x.bar);
|
||||
x.bar = 10;
|
||||
ok(x.bar === undefined, "x.bar with setter = " + x.bar);
|
||||
ok(x.setterVal === 9, "x.setterVal after setting bar = " + x.setterVal);
|
||||
});
|
||||
|
||||
async_test("postMessage", function() {
|
||||
var v = document.documentMode;
|
||||
var onmessage_called = false;
|
||||
|
|
Loading…
Reference in New Issue