diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index f9f9cd63cac..8f66b3dac08 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -194,6 +194,97 @@ static HRESULT put_value(script_ctx_t *ctx, exprval_t *ref, VARIANT *v, jsexcept return disp_propput(ref->u.idref.disp, ref->u.idref.id, ctx->lcid, v, ei, NULL/*FIXME*/); } +static HRESULT disp_cmp(IDispatch *disp1, IDispatch *disp2, BOOL *ret) +{ + IObjectIdentity *identity; + IUnknown *unk1, *unk2; + HRESULT hres; + + if(disp1 == disp2) { + *ret = TRUE; + return S_OK; + } + + hres = IDispatch_QueryInterface(disp1, &IID_IUnknown, (void**)&unk1); + if(FAILED(hres)) + return hres; + + hres = IDispatch_QueryInterface(disp2, &IID_IUnknown, (void**)&unk2); + if(FAILED(hres)) { + IUnknown_Release(unk1); + return hres; + } + + if(unk1 == unk2) { + *ret = TRUE; + }else { + hres = IUnknown_QueryInterface(unk1, &IID_IObjectIdentity, (void**)&identity); + if(SUCCEEDED(hres)) { + hres = IObjectIdentity_IsEqualObject(identity, unk2); + IObjectIdentity_Release(identity); + *ret = hres == S_OK; + }else { + *ret = FALSE; + } + } + + IUnknown_Release(unk1); + IUnknown_Release(unk2); + return S_OK; +} + +static inline BOOL is_num_vt(enum VARENUM vt) +{ + return vt == VT_I4 || vt == VT_R8; +} + +static inline DOUBLE num_val(const VARIANT *v) +{ + return V_VT(v) == VT_I4 ? V_I4(v) : V_R8(v); +} + +/* ECMA-262 3rd Edition 11.9.6 */ +HRESULT equal2_values(VARIANT *lval, VARIANT *rval, BOOL *ret) +{ + TRACE("\n"); + + if(V_VT(lval) != V_VT(rval)) { + if(is_num_vt(V_VT(lval)) && is_num_vt(V_VT(rval))) { + *ret = num_val(lval) == num_val(rval); + return S_OK; + } + + *ret = FALSE; + return S_OK; + } + + switch(V_VT(lval)) { + case VT_EMPTY: + case VT_NULL: + *ret = VARIANT_TRUE; + break; + case VT_I4: + *ret = V_I4(lval) == V_I4(rval); + break; + case VT_R8: + *ret = V_R8(lval) == V_R8(rval); + break; + case VT_BSTR: + *ret = !strcmpW(V_BSTR(lval), V_BSTR(rval)); + break; + case VT_DISPATCH: + return disp_cmp(V_DISPATCH(lval), V_DISPATCH(rval), ret); + case VT_BOOL: + *ret = !V_BOOL(lval) == !V_BOOL(rval); + break; + default: + FIXME("unimplemented vt %d\n", V_VT(lval)); + return E_NOTIMPL; + } + + return S_OK; +} + static HRESULT literal_to_var(literal_t *literal, VARIANT *v) { V_VT(v) = literal->vt; @@ -510,6 +601,34 @@ static HRESULT return_bool(exprval_t *ret, DWORD b) return S_OK; } +static HRESULT get_binary_expr_values(exec_ctx_t *ctx, binary_expression_t *expr, jsexcept_t *ei, VARIANT *lval, VARIANT *rval) +{ + exprval_t exprval; + HRESULT hres; + + hres = expr_eval(ctx, expr->expression1, 0, ei, &exprval); + if(FAILED(hres)) + return hres; + + hres = exprval_to_value(ctx->parser->script, &exprval, ei, lval); + exprval_release(&exprval); + if(FAILED(hres)) + return hres; + + hres = expr_eval(ctx, expr->expression2, 0, ei, &exprval); + if(SUCCEEDED(hres)) { + hres = exprval_to_value(ctx->parser->script, &exprval, ei, rval); + exprval_release(&exprval); + } + + if(FAILED(hres)) { + VariantClear(lval); + return hres; + } + + return S_OK; +} + HRESULT function_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) { FIXME("\n"); @@ -829,10 +948,25 @@ HRESULT equal_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, return E_NOTIMPL; } -HRESULT equal2_expression_eval(exec_ctx_t *ctx, expression_t *expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +/* ECMA-262 3rd Edition 11.9.4 */ +HRESULT equal2_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) { - FIXME("\n"); - return E_NOTIMPL; + binary_expression_t *expr = (binary_expression_t*)_expr; + VARIANT rval, lval; + BOOL b; + HRESULT hres; + + TRACE("\n"); + + hres = get_binary_expr_values(ctx, expr, ei, &rval, &lval); + if(FAILED(hres)) + return hres; + + hres = equal2_values(&rval, &lval, &b); + if(FAILED(hres)) + return hres; + + return return_bool(ret, b); } HRESULT not_equal_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) diff --git a/dlls/jscript/tests/lang.js b/dlls/jscript/tests/lang.js index 3ea49333c5d..61d108f7ea3 100644 --- a/dlls/jscript/tests/lang.js +++ b/dlls/jscript/tests/lang.js @@ -23,6 +23,15 @@ ok(!null, "!null is not true"); ok(!0, "!0 is not true"); ok(!0.0, "!0.0 is not true"); +ok(1 === 1, "1 === 1 is false"); +ok(!(1 === 2), "!(1 === 2) is false"); +ok(1.0 === 1, "1.0 === 1 is false"); +ok("abc" === "abc", "\"abc\" === \"abc\" is false"); +ok(true === true, "true === true is false"); +ok(null === null, "null === null is false"); +ok(undefined === undefined, "undefined === undefined is false"); +ok(!(undefined === null), "!(undefined === null) is false"); + var trueVar = true; ok(trueVar, "trueVar is not true");