Jacek Caban : jscript: Use bytecode for post-increment expression.

Alexandre Julliard julliard at winehq.org
Wed Dec 7 13:57:13 CST 2011


Module: wine
Branch: master
Commit: a508149fad4602793df0cd893f42f7b48c7ee0cc
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a508149fad4602793df0cd893f42f7b48c7ee0cc

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Wed Dec  7 11:01:53 2011 +0100

jscript: Use bytecode for post-increment expression.

---

 dlls/jscript/compile.c     |   21 +++++++++++++++++++++
 dlls/jscript/engine.c      |   39 ++++++++++++++++++---------------------
 dlls/jscript/engine.h      |    2 +-
 dlls/jscript/parser.y      |    2 +-
 dlls/jscript/tests/api.js  |    7 +++++++
 dlls/jscript/tests/lang.js |    4 ++++
 6 files changed, 52 insertions(+), 23 deletions(-)

diff --git a/dlls/jscript/compile.c b/dlls/jscript/compile.c
index 3e5800e..b274a0e 100644
--- a/dlls/jscript/compile.c
+++ b/dlls/jscript/compile.c
@@ -292,6 +292,25 @@ static HRESULT compile_memberid_expression(compiler_ctx_t *ctx, expression_t *ex
     return hres;
 }
 
+static HRESULT compile_increment_expression(compiler_ctx_t *ctx, unary_expression_t *expr)
+{
+    HRESULT hres;
+
+    if(!is_memberid_expr(expr->expression->type)) {
+        hres = compile_expression(ctx, expr->expression);
+        if(FAILED(hres))
+            return hres;
+
+        return push_instr_uint(ctx, OP_throw, JS_E_ILLEGAL_ASSIGN);
+    }
+
+    hres = compile_memberid_expression(ctx, expr->expression, fdexNameEnsure);
+    if(FAILED(hres))
+        return hres;
+
+    return push_instr_int(ctx, OP_postinc, 1);
+}
+
 /* ECMA-262 3rd Edition    11.14 */
 static HRESULT compile_comma_expression(compiler_ctx_t *ctx, binary_expression_t *expr)
 {
@@ -628,6 +647,8 @@ static HRESULT compile_expression_noret(compiler_ctx_t *ctx, expression_t *expr,
         return compile_logical_expression(ctx, (binary_expression_t*)expr, OP_jmp_nz);
     case EXPR_PLUS:
         return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_tonum);
+    case EXPR_POSTINC:
+        return compile_increment_expression(ctx, (unary_expression_t*)expr);
     case EXPR_SUB:
         return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub);
     case EXPR_THIS:
diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c
index e98e98a..8bf0a0a 100644
--- a/dlls/jscript/engine.c
+++ b/dlls/jscript/engine.c
@@ -2704,38 +2704,35 @@ static HRESULT interp_tonum(exec_ctx_t *ctx)
 }
 
 /* ECMA-262 3rd Edition    11.3.1 */
-HRESULT post_increment_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+static HRESULT interp_postinc(exec_ctx_t *ctx)
 {
-    unary_expression_t *expr = (unary_expression_t*)_expr;
-    VARIANT val, num;
-    exprval_t exprval;
+    const int arg = ctx->parser->code->instrs[ctx->ip].arg1.lng;
+    IDispatch *obj;
+    DISPID id;
+    VARIANT v;
     HRESULT hres;
 
-    TRACE("\n");
+    TRACE("%d\n", arg);
 
-    hres = expr_eval(ctx, expr->expression, EXPR_NEWREF, ei, &exprval);
-    if(FAILED(hres))
-        return hres;
+    obj = stack_pop_objid(ctx, &id);
+    if(!obj)
+        return throw_type_error(ctx->parser->script, &ctx->ei, JS_E_OBJECT_EXPECTED, NULL);
 
-    hres = exprval_value(ctx, &exprval, ei, &val);
+    hres = disp_propget(ctx->parser->script, obj, id, &v, &ctx->ei, NULL/*FIXME*/);
     if(SUCCEEDED(hres)) {
-        hres = to_number(ctx, &val, ei, &num);
-        VariantClear(&val);
-    }
+        VARIANT n, inc;
 
-    if(SUCCEEDED(hres)) {
-        VARIANT inc;
-        num_set_val(&inc, num_val(&num)+1.0);
-        hres = put_value(ctx, &exprval, &inc, ei);
+        hres = to_number(ctx->parser->script, &v, &ctx->ei, &n);
+        if(SUCCEEDED(hres)) {
+            num_set_val(&inc, num_val(&n)+(double)arg);
+            hres = disp_propput(ctx->parser->script, obj, id, &inc, &ctx->ei, NULL/*FIXME*/);
+        }
     }
-
-    exprval_release(&exprval);
+    IDispatch_Release(obj);
     if(FAILED(hres))
         return hres;
 
-    ret->type = EXPRVAL_VARIANT;
-    ret->u.var = num;
-    return S_OK;
+    return stack_push(ctx, &v);
 }
 
 /* ECMA-262 3rd Edition    11.3.2 */
diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h
index 8b2c0a7..21d599b 100644
--- a/dlls/jscript/engine.h
+++ b/dlls/jscript/engine.h
@@ -77,6 +77,7 @@ typedef struct _func_stack {
     X(null,       1, 0,0)                  \
     X(or,         1, 0,0)                  \
     X(pop,        1, 0,0)                  \
+    X(postinc,    1, ARG_INT,    0)        \
     X(regexp,     1, ARG_STR,    ARG_INT)  \
     X(str,        1, ARG_STR,    0)        \
     X(this,       1, 0,0)                  \
@@ -562,7 +563,6 @@ HRESULT binary_and_expression_eval(script_ctx_t*,expression_t*,DWORD,jsexcept_t*
 HRESULT instanceof_expression_eval(script_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*) DECLSPEC_HIDDEN;
 HRESULT delete_expression_eval(script_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*) DECLSPEC_HIDDEN;
 HRESULT typeof_expression_eval(script_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*) DECLSPEC_HIDDEN;
-HRESULT post_increment_expression_eval(script_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*) DECLSPEC_HIDDEN;
 HRESULT post_decrement_expression_eval(script_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*) DECLSPEC_HIDDEN;
 HRESULT pre_increment_expression_eval(script_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*) DECLSPEC_HIDDEN;
 HRESULT pre_decrement_expression_eval(script_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*) DECLSPEC_HIDDEN;
diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y
index 25d1fcb..f32788e 100644
--- a/dlls/jscript/parser.y
+++ b/dlls/jscript/parser.y
@@ -1322,7 +1322,7 @@ static const expression_eval_t expression_eval_table[] = {
    typeof_expression_eval,
    compiled_expression_eval,
    compiled_expression_eval,
-   post_increment_expression_eval,
+   compiled_expression_eval,
    post_decrement_expression_eval,
    pre_increment_expression_eval,
    pre_decrement_expression_eval,
diff --git a/dlls/jscript/tests/api.js b/dlls/jscript/tests/api.js
index 0118743..7291979 100644
--- a/dlls/jscript/tests/api.js
+++ b/dlls/jscript/tests/api.js
@@ -2031,6 +2031,9 @@ testException(function() {new nullDisp;}, "E_NO_PROPERTY");
 testException(function() {new VBArray();}, "E_NOT_VBARRAY");
 testException(function() {new VBArray(new VBArray(createArray()));}, "E_NOT_VBARRAY");
 testException(function() {VBArray.prototype.lbound.call(new Object());}, "E_NOT_VBARRAY");
+//FIXME: testException(function() {nonexistent++;}, "E_OBJECT_EXPECTED");
+//FIXME: testException(function() {undefined.nonexistent++;}, "E_OBJECT_EXPECTED");
+
 
 // SyntaxError tests
 function testSyntaxError(code, id) {
@@ -2088,6 +2091,10 @@ tmp = "";
 testException(function() {(tmp = tmp+"1") = (tmp = tmp+"2");}, "E_ILLEGAL_ASSIGN");
 ok(tmp === "12", "assign evaluated in unexpected order");
 
+tmp = false;
+testException(function() { ((tmp = true) && false)++; }, "E_ILLEGAL_ASSIGN")
+ok(tmp, "incremented expression not evaluated");
+
 // RegExpError tests
 testException(function() {RegExp(/a/, "g");}, "E_REGEXP_SYNTAX_ERROR");
 
diff --git a/dlls/jscript/tests/lang.js b/dlls/jscript/tests/lang.js
index 1dd0c02..3710ae7 100644
--- a/dlls/jscript/tests/lang.js
+++ b/dlls/jscript/tests/lang.js
@@ -521,6 +521,10 @@ ok(tmp === 2, "incremented tmp(1) is not 2");
 ok(tmp-- === 2, "tmp-- (2) is not 2");
 ok(tmp === 1, "decremented tmp is not 1");
 
+tmp = new Object();
+tmp.iii++;
+ok(isNaN(tmp.iii), "tmp.iii = " + tmp.iii);
+
 String.prototype.test = true;
 ok("".test === true, "\"\".test is not true");
 




More information about the wine-cvs mailing list