Module: wine Branch: master Commit: 93a62e8f70be1eeb208799ea0217f97823baa250 URL: http://source.winehq.org/git/wine.git/?a=commit;h=93a62e8f70be1eeb208799ea02...
Author: Jacek Caban jacek@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();