jscript: Properly handle elisions in array literals.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2018-03-01 23:58:38 +01:00 committed by Alexandre Julliard
parent 89da4559ee
commit d72acebd6c
4 changed files with 37 additions and 27 deletions

View file

@ -861,29 +861,29 @@ static HRESULT literal_as_bstr(compiler_ctx_t *ctx, literal_t *literal, BSTR *st
static HRESULT compile_array_literal(compiler_ctx_t *ctx, array_literal_expression_t *expr)
{
unsigned i, elem_cnt = expr->length;
unsigned length = 0;
array_element_t *iter;
unsigned array_instr;
HRESULT hres;
for(iter = expr->element_list; iter; iter = iter->next) {
elem_cnt += iter->elision+1;
array_instr = push_instr(ctx, OP_carray);
for(i=0; i < iter->elision; i++) {
if(!push_instr(ctx, OP_undefined))
return E_OUTOFMEMORY;
}
for(iter = expr->element_list; iter; iter = iter->next) {
length += iter->elision;
hres = compile_expression(ctx, iter->expr, TRUE);
if(FAILED(hres))
return hres;
hres = push_instr_uint(ctx, OP_carray_set, length);
if(FAILED(hres))
return hres;
length++;
}
for(i=0; i < expr->length; i++) {
if(!push_instr(ctx, OP_undefined))
return E_OUTOFMEMORY;
}
return push_instr_uint(ctx, OP_carray, elem_cnt);
instr_ptr(ctx, array_instr)->u.arg[0].uint = length + expr->length;
return S_OK;
}
static HRESULT compile_object_literal(compiler_ctx_t *ctx, property_value_expression_t *expr)

View file

@ -1399,8 +1399,6 @@ static HRESULT interp_carray(script_ctx_t *ctx)
{
const unsigned arg = get_op_uint(ctx, 0);
jsdisp_t *array;
jsval_t val;
unsigned i;
HRESULT hres;
TRACE("%u\n", arg);
@ -1409,20 +1407,27 @@ static HRESULT interp_carray(script_ctx_t *ctx)
if(FAILED(hres))
return hres;
i = arg;
while(i--) {
val = stack_pop(ctx);
hres = jsdisp_propput_idx(array, i, val);
jsval_release(val);
if(FAILED(hres)) {
jsdisp_release(array);
return hres;
}
}
return stack_push(ctx, jsval_obj(array));
}
static HRESULT interp_carray_set(script_ctx_t *ctx)
{
const unsigned index = get_op_uint(ctx, 0);
jsval_t value, array;
HRESULT hres;
value = stack_pop(ctx);
TRACE("[%u] = %s\n", index, debugstr_jsval(value));
array = stack_top(ctx);
assert(is_object_instance(array));
hres = jsdisp_propput_idx(iface_to_jsdisp(get_object(array)), index, value);
jsval_release(value);
return hres;
}
/* ECMA-262 3rd Edition 11.1.5 */
static HRESULT interp_new_obj(script_ctx_t *ctx)
{

View file

@ -21,12 +21,13 @@
X(and, 1, 0,0) \
X(array, 1, 0,0) \
X(assign, 1, 0,0) \
X(assign_call,1, ARG_UINT, 0) \
X(assign_call,1, ARG_UINT, 0) \
X(bool, 1, ARG_INT, 0) \
X(bneg, 1, 0,0) \
X(call, 1, ARG_UINT, ARG_UINT) \
X(call_member,1, ARG_UINT, ARG_UINT) \
X(carray, 1, ARG_UINT, 0) \
X(carray_set, 1, ARG_UINT, 0) \
X(case, 0, ARG_ADDR, 0) \
X(cnd_nz, 0, ARG_ADDR, 0) \
X(cnd_z, 0, ARG_ADDR, 0) \

View file

@ -1171,6 +1171,10 @@ ok(tmp["0"] === undefined, "tmp[0] is not undefined");
ok(tmp["3"] === 2, "tmp[3] !== 2");
ok(tmp["6"] === true, "tmp[6] !== true");
ok(tmp[2] === 1, "tmp[2] !== 1");
ok(!("0" in tmp), "0 found in array");
ok(!("1" in tmp), "1 found in array");
ok("2" in tmp, "2 not found in array");
ok(!("2" in [1,,,,]), "2 found in [1,,,,]");
ok([1,].length === 2, "[1,].length !== 2");
ok([,,].length === 3, "[,,].length !== 3");