From d72acebd6c8176f4e00c79c0f199082221caf4e3 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Thu, 1 Mar 2018 23:58:38 +0100 Subject: [PATCH] jscript: Properly handle elisions in array literals. Signed-off-by: Jacek Caban Signed-off-by: Alexandre Julliard --- dlls/jscript/compile.c | 26 +++++++++++++------------- dlls/jscript/engine.c | 31 ++++++++++++++++++------------- dlls/jscript/engine.h | 3 ++- dlls/jscript/tests/lang.js | 4 ++++ 4 files changed, 37 insertions(+), 27 deletions(-) diff --git a/dlls/jscript/compile.c b/dlls/jscript/compile.c index 86915954d6c..6e6be9135fb 100644 --- a/dlls/jscript/compile.c +++ b/dlls/jscript/compile.c @@ -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) diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index 8092159354c..6b4aae3f76e 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -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) { diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h index 121a2c21150..31f6b1cfba6 100644 --- a/dlls/jscript/engine.h +++ b/dlls/jscript/engine.h @@ -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) \ diff --git a/dlls/jscript/tests/lang.js b/dlls/jscript/tests/lang.js index aba6ddac6b9..ef4c3165b17 100644 --- a/dlls/jscript/tests/lang.js +++ b/dlls/jscript/tests/lang.js @@ -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");