diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index 2a37d058b8e..36286da5b3e 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -641,16 +641,58 @@ HRESULT if_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt return hres; } -HRESULT dowhile_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret) +/* ECMA-262 3rd Edition 12.6.2 */ +HRESULT while_statement_eval(exec_ctx_t *ctx, statement_t *_stat, return_type_t *rt, VARIANT *ret) { - FIXME("\n"); - return E_NOTIMPL; -} + while_statement_t *stat = (while_statement_t*)_stat; + exprval_t exprval; + VARIANT val, tmp; + VARIANT_BOOL b; + BOOL test_expr; + HRESULT hres; -HRESULT while_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret) -{ - FIXME("\n"); - return E_NOTIMPL; + TRACE("\n"); + + V_VT(&val) = VT_EMPTY; + test_expr = !stat->do_while; + + while(1) { + if(test_expr) { + hres = expr_eval(ctx, stat->expr, 0, &rt->ei, &exprval); + if(FAILED(hres)) + break; + + hres = exprval_to_boolean(ctx->parser->script, &exprval, &rt->ei, &b); + exprval_release(&exprval); + if(FAILED(hres) || !b) + break; + }else { + test_expr = TRUE; + } + + hres = stat_eval(ctx, stat->statement, rt, &tmp); + if(FAILED(hres)) + break; + + VariantClear(&val); + val = tmp; + + if(rt->type == RT_CONTINUE) + rt->type = RT_NORMAL; + if(rt->type != RT_NORMAL) + break; + } + + if(FAILED(hres)) { + VariantClear(&val); + return hres; + } + + if(rt->type == RT_BREAK) + rt->type = RT_NORMAL; + + *ret = val; + return S_OK; } HRESULT for_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret) diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h index 5c64853c99a..3f7fda86c9a 100644 --- a/dlls/jscript/engine.h +++ b/dlls/jscript/engine.h @@ -161,6 +161,7 @@ typedef struct { typedef struct { statement_t stat; + BOOL do_while; expression_t *expr; statement_t *statement; } while_statement_t; @@ -229,7 +230,6 @@ HRESULT var_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); HRESULT empty_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); HRESULT expression_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); HRESULT if_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); -HRESULT dowhile_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); HRESULT while_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); HRESULT for_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); HRESULT forin_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y index d8b876edfde..a6cb5ebf32c 100644 --- a/dlls/jscript/parser.y +++ b/dlls/jscript/parser.y @@ -1086,8 +1086,9 @@ static statement_t *new_while_statement(parser_ctx_t *ctx, BOOL dowhile, express { while_statement_t *ret = parser_alloc(ctx, sizeof(while_statement_t)); - ret->stat.eval = dowhile ? dowhile_statement_eval : while_statement_eval; + ret->stat.eval = while_statement_eval; ret->stat.next = NULL; + ret->do_while = dowhile; ret->expr = expr; ret->statement = stat; diff --git a/dlls/jscript/tests/lang.js b/dlls/jscript/tests/lang.js index e2b5800ef61..6acc82c5e55 100644 --- a/dlls/jscript/tests/lang.js +++ b/dlls/jscript/tests/lang.js @@ -550,4 +550,36 @@ ok(tmp["3"] === 2, "tmp[3] !== 2"); ok(tmp["6"] === true, "tmp[6] !== true"); ok(tmp[2] === 1, "tmp[2] !== 1"); +tmp = 0; +while(tmp < 4) { + ok(tmp < 4, "tmp >= 4"); + tmp++; +} +ok(tmp === 4, "tmp !== 4"); + +tmp = 0; +while(true) { + ok(tmp < 4, "tmp >= 4"); + tmp++; + if(tmp === 4) { + break; + ok(false, "break did not break"); + } +} +ok(tmp === 4, "tmp !== 4"); + +tmp = 0; +do { + ok(tmp < 4, "tmp >= 4"); + tmp++; +} while(tmp < 4); +ok(tmp === 4, "tmp !== 4"); + +tmp = 0; +do { + ok(tmp === 0, "tmp !=== 0"); + tmp++; +} while(false); +ok(tmp === 1, "tmp !== 4"); + reportSuccess();