jscript: Add interpreter support for getters and setters in object initializer.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2018-11-30 22:44:40 +01:00 committed by Alexandre Julliard
parent 56be97fd5d
commit 0cc68cf82a
4 changed files with 95 additions and 9 deletions

View file

@ -889,7 +889,6 @@ static HRESULT compile_array_literal(compiler_ctx_t *ctx, array_literal_expressi
static HRESULT compile_object_literal(compiler_ctx_t *ctx, property_value_expression_t *expr)
{
property_definition_t *iter;
unsigned instr;
BSTR name;
HRESULT hres;
@ -905,11 +904,9 @@ static HRESULT compile_object_literal(compiler_ctx_t *ctx, property_value_expres
if(FAILED(hres))
return hres;
instr = push_instr(ctx, OP_obj_prop);
if(!instr)
return E_OUTOFMEMORY;
instr_ptr(ctx, instr)->u.arg->bstr = name;
hres = push_instr_bstr_uint(ctx, OP_obj_prop, name, iter->type);
if(FAILED(hres))
return hres;
}
return S_OK;

View file

@ -1445,6 +1445,7 @@ static HRESULT interp_new_obj(script_ctx_t *ctx)
static HRESULT interp_obj_prop(script_ctx_t *ctx)
{
const BSTR name = get_op_bstr(ctx, 0);
unsigned type = get_op_uint(ctx, 1);
jsdisp_t *obj;
jsval_t val;
HRESULT hres;
@ -1456,7 +1457,28 @@ static HRESULT interp_obj_prop(script_ctx_t *ctx)
assert(is_object_instance(stack_top(ctx)));
obj = as_jsdisp(get_object(stack_top(ctx)));
hres = jsdisp_propput_name(obj, name, val);
if(type == PROPERTY_DEFINITION_VALUE) {
hres = jsdisp_propput_name(obj, name, val);
}else {
property_desc_t desc = {PROPF_ENUMERABLE | PROPF_CONFIGURABLE};
jsdisp_t *func;
assert(is_object_instance(val));
func = iface_to_jsdisp(get_object(val));
desc.mask = desc.flags;
if(type == PROPERTY_DEFINITION_GETTER) {
desc.explicit_getter = TRUE;
desc.getter = func;
}else {
desc.explicit_setter = TRUE;
desc.setter = func;
}
hres = jsdisp_define_property(obj, name, &desc);
jsdisp_release(func);
}
jsval_release(val);
return hres;
}

View file

@ -66,7 +66,7 @@
X(new, 1, ARG_UINT, 0) \
X(new_obj, 1, 0,0) \
X(null, 1, 0,0) \
X(obj_prop, 1, ARG_BSTR, 0) \
X(obj_prop, 1, ARG_BSTR, ARG_UINT) \
X(or, 1, 0,0) \
X(pop, 1, ARG_UINT, 0) \
X(pop_except, 0, ARG_ADDR, 0) \

View file

@ -149,7 +149,7 @@ function test_identifier_keywords() {
}
function test_own_data_prop_desc(obj, prop, expected_writable, expected_enumerable,
expected_configurable) {
expected_configurable) {
var desc = Object.getOwnPropertyDescriptor(obj, prop);
ok("value" in desc, "value is not in desc");
ok(desc.value === obj[prop], "desc.value = " + desc.value + " expected " + obj[prop]);
@ -427,6 +427,72 @@ function test_defineProperty() {
next_test();
}
function test_property_definitions() {
var obj, val, i, arr;
function test_accessor_prop_desc(obj, prop, have_getter, have_setter) {
var desc = Object.getOwnPropertyDescriptor(obj, prop);
ok(desc.enumerable === true, "desc.enumerable = " + desc.enumerable);
ok(desc.configurable === true, "desc.configurable = " + desc.configurable);
if(have_getter) {
ok(typeof(desc.get) === "function", "desc.get = " + desc.get);
ok(typeof(desc.get.prototype) === "object", "desc.get.prototype = " + desc.get.prototype);
trace("" + desc.get);
}else {
ok(!("get" in obj), "desc.get = " + desc.get);
}
if(have_setter) {
ok(typeof(desc.set) === "function", "desc.set = " + desc.set);
ok(typeof(desc.set.prototype) === "object", "desc.set.prototype = " + desc.set.prototype);
}else {
ok(!("set" in obj), "desc.get = " + desc.get);
}
}
obj = {
get prop() { return val + 1; },
set prop(v) { val = v; }
};
test_accessor_prop_desc(obj, "prop", true, true);
val = 0;
ok(obj.prop === 1, "obj.prop = " + obj.prop);
obj.prop = 3;
ok(val === 3, "val = " + val);
ok(obj.prop === 4, "obj.prop = " + obj.prop);
arr = [];
for(i in obj)
arr.push(i);
ok(arr.join() === "prop", "prop of obj = " + arr.join());
obj = {
set prop(v) { val = v; }
};
test_accessor_prop_desc(obj, "prop", false, true);
val = 1;
ok(obj.prop === undefined, "obj.prop = " + obj.prop);
obj.prop = 2;
ok(val === 2, "val = " + val);
ok(obj.prop === undefined, "obj.prop = " + obj.prop);
obj = {
get prop() { return val + 1; },
get 0() { return val + 2; }
};
test_accessor_prop_desc(obj, "prop", true, false);
val = 5;
ok(obj.prop === 6, "obj.prop = " + obj.prop);
obj.prop = 10;
ok(val === 5, "val = " + val);
ok(obj.prop === 6, "obj.prop = " + obj.prop);
test_accessor_prop_desc(obj, "0", true, false);
ok(obj[0] === 7, "obj.prop = " + obj[0]);
next_test();
}
function test_string_trim() {
function test_trim(value, expected) {
var r = String.prototype.trim.call(value);
@ -513,6 +579,7 @@ var tests = [
test_identifier_keywords,
test_getOwnPropertyDescriptor,
test_defineProperty,
test_property_definitions,
test_string_trim,
test_global_properties,
test_string_split