Jacek Caban : jscript: Added add expression implementation.

Alexandre Julliard julliard at winehq.org
Thu Sep 11 08:00:58 CDT 2008


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Wed Sep 10 21:12:45 2008 +0200

jscript: Added add expression implementation.

---

 dlls/jscript/engine.c      |  107 ++++++++++++++++++++++++++++++++++++++++++-
 dlls/jscript/jscript.h     |    2 +
 dlls/jscript/jsutils.c     |   41 +++++++++++++++++
 dlls/jscript/tests/lang.js |   15 ++++++
 4 files changed, 162 insertions(+), 3 deletions(-)

diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c
index ba3f9b0..a952ecb 100644
--- a/dlls/jscript/engine.c
+++ b/dlls/jscript/engine.c
@@ -278,6 +278,17 @@ static inline DOUBLE num_val(const VARIANT *v)
     return V_VT(v) == VT_I4 ? V_I4(v) : V_R8(v);
 }
 
+static inline void num_set_val(VARIANT *v, DOUBLE d)
+{
+    if(d == (DOUBLE)(INT)d) {
+        V_VT(v) = VT_I4;
+        V_I4(v) = d;
+    }else {
+        V_VT(v) = VT_R8;
+        V_R8(v) = d;
+    }
+}
+
 /* ECMA-262 3rd Edition    11.9.6 */
 HRESULT equal2_values(VARIANT *lval, VARIANT *rval, BOOL *ret)
 {
@@ -751,6 +762,29 @@ static HRESULT get_binary_expr_values(exec_ctx_t *ctx, binary_expression_t *expr
     return S_OK;
 }
 
+typedef HRESULT (*oper_t)(exec_ctx_t*,VARIANT*,VARIANT*,jsexcept_t*,VARIANT*);
+
+static HRESULT binary_expr_eval(exec_ctx_t *ctx, binary_expression_t *expr, oper_t oper, jsexcept_t *ei,
+        exprval_t *ret)
+{
+    VARIANT lval, rval, retv;
+    HRESULT hres;
+
+    hres = get_binary_expr_values(ctx, expr, ei, &lval, &rval);
+    if(FAILED(hres))
+        return hres;
+
+    hres = oper(ctx, &lval, &rval, ei, &retv);
+    VariantClear(&lval);
+    VariantClear(&rval);
+    if(FAILED(hres))
+        return hres;
+
+    ret->type = EXPRVAL_VARIANT;
+    ret->u.var = retv;
+    return S_OK;
+}
+
 /* ECMA-262 3rd Edition    13 */
 HRESULT function_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
 {
@@ -1192,10 +1226,77 @@ HRESULT in_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jse
     return E_NOTIMPL;
 }
 
-HRESULT add_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+/* ECMA-262 3rd Edition    11.6.1 */
+static HRESULT add_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_t *ei, VARIANT *retv)
 {
-    FIXME("\n");
-    return E_NOTIMPL;
+    VARIANT r, l;
+    HRESULT hres;
+
+    hres = to_primitive(ctx->parser->script, lval, ei, &l);
+    if(FAILED(hres))
+        return hres;
+
+    hres = to_primitive(ctx->parser->script, rval, ei, &r);
+    if(FAILED(hres)) {
+        VariantClear(&l);
+        return hres;
+    }
+
+    if(V_VT(&l) == VT_BSTR || V_VT(&r) == VT_BSTR) {
+        BSTR lstr = NULL, rstr = NULL;
+
+        if(V_VT(&l) == VT_BSTR)
+            lstr = V_BSTR(&l);
+        else
+            hres = to_string(ctx->parser->script, &l, ei, &lstr);
+
+        if(SUCCEEDED(hres)) {
+            if(V_VT(&r) == VT_BSTR)
+                rstr = V_BSTR(&r);
+            else
+                hres = to_string(ctx->parser->script, &r, ei, &rstr);
+        }
+
+        if(SUCCEEDED(hres)) {
+            int len1, len2;
+
+            len1 = SysStringLen(lstr);
+            len2 = SysStringLen(rstr);
+
+            V_VT(retv) = VT_BSTR;
+            V_BSTR(retv) = SysAllocStringLen(NULL, len1+len2);
+            memcpy(V_BSTR(retv), lstr, len1*sizeof(WCHAR));
+            memcpy(V_BSTR(retv)+len1, rstr, (len2+1)*sizeof(WCHAR));
+        }
+
+        if(lstr && V_VT(&l) != VT_BSTR)
+            SysFreeString(lstr);
+        if(rstr && V_VT(&r) != VT_BSTR)
+            SysFreeString(rstr);
+    }else {
+        VARIANT nl, nr;
+
+        hres = to_number(ctx->parser->script, &l, ei, &nl);
+        if(SUCCEEDED(hres)) {
+            hres = to_number(ctx->parser->script, &r, ei, &nr);
+            if(SUCCEEDED(hres))
+                num_set_val(retv, num_val(&nl) + num_val(&nr));
+        }
+    }
+
+    VariantClear(&r);
+    VariantClear(&l);
+    return hres;
+}
+
+/* ECMA-262 3rd Edition    11.6.1 */
+HRESULT add_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
+{
+    binary_expression_t *expr = (binary_expression_t*)_expr;
+
+    TRACE("\n");
+
+    return binary_expr_eval(ctx, expr, add_eval, ei, ret);
 }
 
 HRESULT sub_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h
index 5f15695..ee1215e 100644
--- a/dlls/jscript/jscript.h
+++ b/dlls/jscript/jscript.h
@@ -116,7 +116,9 @@ HRESULT create_builtin_function(script_ctx_t*,builtin_invoke_t,DWORD,DispatchEx*
 HRESULT create_object(script_ctx_t*,DispatchEx*,DispatchEx**);
 HRESULT create_math(script_ctx_t*,DispatchEx**);
 
+HRESULT to_primitive(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*);
 HRESULT to_boolean(VARIANT*,VARIANT_BOOL*);
+HRESULT to_number(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*);
 HRESULT to_string(script_ctx_t*,VARIANT*,jsexcept_t*,BSTR*);
 HRESULT to_object(exec_ctx_t*,VARIANT*,IDispatch**);
 
diff --git a/dlls/jscript/jsutils.c b/dlls/jscript/jsutils.c
index 919bcca..a193b9e 100644
--- a/dlls/jscript/jsutils.c
+++ b/dlls/jscript/jsutils.c
@@ -133,6 +133,31 @@ void jsheap_free(jsheap_t *heap)
     jsheap_init(heap);
 }
 
+/* ECMA-262 3rd Edition    9.1 */
+HRESULT to_primitive(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
+{
+    switch(V_VT(v)) {
+    case VT_EMPTY:
+    case VT_NULL:
+    case VT_BOOL:
+    case VT_I4:
+    case VT_R8:
+        *ret = *v;
+        break;
+    case VT_BSTR:
+        V_VT(ret) = VT_BSTR;
+        V_BSTR(ret) = SysAllocString(V_BSTR(v));
+        break;
+    case VT_DISPATCH:
+        return disp_propget(V_DISPATCH(v), DISPID_VALUE, ctx->lcid, ret, ei, NULL /*FIXME*/);
+    default:
+        FIXME("Unimplemented for vt %d\n", V_VT(v));
+        return E_NOTIMPL;
+    }
+
+    return S_OK;
+}
+
 /* ECMA-262 3rd Edition    9.2 */
 HRESULT to_boolean(VARIANT *v, VARIANT_BOOL *b)
 {
@@ -164,6 +189,22 @@ HRESULT to_boolean(VARIANT *v, VARIANT_BOOL *b)
     return S_OK;
 }
 
+/* ECMA-262 3rd Edition    9.3 */
+HRESULT to_number(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
+{
+    switch(V_VT(v)) {
+    case VT_I4:
+    case VT_R8:
+        *ret = *v;
+        break;
+    default:
+        FIXME("unimplemented for vt %d\n", V_VT(v));
+        return E_NOTIMPL;
+    }
+
+    return S_OK;
+}
+
 /* ECMA-262 3rd Edition    9.8 */
 HRESULT to_string(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, BSTR *str)
 {
diff --git a/dlls/jscript/tests/lang.js b/dlls/jscript/tests/lang.js
index b58e0f8..302de8d 100644
--- a/dlls/jscript/tests/lang.js
+++ b/dlls/jscript/tests/lang.js
@@ -161,4 +161,19 @@ ok(getVT("test") === "VT_BSTR", "getVT(\"test\") is not VT_BSTR");
 ok(getVT(Math) === "VT_DISPATCH", "getVT(Math) is not VT_DISPATCH");
 ok(getVT(false) === "VT_BOOL", "getVT(false) is not VT_BOOL");
 
+tmp = 2+2;
+ok(tmp === 4, "2+2 !== 4");
+ok(getVT(tmp) === "VT_I4", "getVT(2+2) !== VT_I4");
+
+tmp = 2+2.5;
+ok(tmp === 4.5, "2+2.5 !== 4.5");
+ok(getVT(tmp) === "VT_R8", "getVT(2+2.5) !== VT_R8");
+
+tmp = 1.5+2.5;
+ok(tmp === 4, "1.4+2.5 !== 4");
+ok(getVT(tmp) === "VT_I4", "getVT(1.5+2.5) !== VT_I4");
+
+tmp = "ab" + "cd";
+ok(tmp === "abcd", "\"ab\" + \"cd\" !== \"abcd\"");
+
 reportSuccess();




More information about the wine-cvs mailing list