Piotr Caban : jscript: Changed to_primitive implementation.

Alexandre Julliard julliard at winehq.org
Thu Jul 9 10:57:10 CDT 2009


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

Author: Piotr Caban <piotr.caban at gmail.com>
Date:   Wed Jul  8 10:52:56 2009 +0200

jscript: Changed to_primitive implementation.

---

 dlls/jscript/date.c        |    2 +-
 dlls/jscript/dispex.c      |    2 +-
 dlls/jscript/engine.c      |   12 ++++----
 dlls/jscript/jscript.h     |    9 +++++-
 dlls/jscript/jsutils.c     |   63 ++++++++++++++++++++++++++++++++++++++++---
 dlls/jscript/tests/api.js  |    2 +
 dlls/jscript/tests/lang.js |   12 ++++++++
 7 files changed, 88 insertions(+), 14 deletions(-)

diff --git a/dlls/jscript/date.c b/dlls/jscript/date.c
index 3a681b9..642c9ec 100644
--- a/dlls/jscript/date.c
+++ b/dlls/jscript/date.c
@@ -2634,7 +2634,7 @@ static HRESULT DateConstr_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPP
         case 1: {
             VARIANT prim, num;
 
-            hres = to_primitive(dispex->ctx, get_arg(dp,0), ei, &prim);
+            hres = to_primitive(dispex->ctx, get_arg(dp,0), ei, &prim, NO_HINT);
             if(FAILED(hres))
                 return hres;
 
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c
index a387ecd..01f4d49 100644
--- a/dlls/jscript/dispex.c
+++ b/dlls/jscript/dispex.c
@@ -828,7 +828,7 @@ HRESULT jsdisp_call_value(DispatchEx *disp, LCID lcid, WORD flags, DISPPARAMS *d
     return disp->builtin_info->value_prop.invoke(disp, lcid, flags, dp, retv, ei, caller);
 }
 
-static HRESULT jsdisp_call(DispatchEx *disp, DISPID id, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv,
+HRESULT jsdisp_call(DispatchEx *disp, DISPID id, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv,
         jsexcept_t *ei, IServiceProvider *caller)
 {
     dispex_prop_t *prop;
diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c
index 05c6225..00eb087 100644
--- a/dlls/jscript/engine.c
+++ b/dlls/jscript/engine.c
@@ -1931,11 +1931,11 @@ static HRESULT add_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_
     VARIANT r, l;
     HRESULT hres;
 
-    hres = to_primitive(ctx->parser->script, lval, ei, &l);
+    hres = to_primitive(ctx->parser->script, lval, ei, &l, NO_HINT);
     if(FAILED(hres))
         return hres;
 
-    hres = to_primitive(ctx->parser->script, rval, ei, &r);
+    hres = to_primitive(ctx->parser->script, rval, ei, &r, NO_HINT);
     if(FAILED(hres)) {
         VariantClear(&l);
         return hres;
@@ -2518,7 +2518,7 @@ static HRESULT equal_values(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexc
         VARIANT v;
         HRESULT hres;
 
-        hres = to_primitive(ctx->parser->script, rval, ei, &v);
+        hres = to_primitive(ctx->parser->script, rval, ei, &v, NO_HINT);
         if(FAILED(hres))
             return hres;
 
@@ -2533,7 +2533,7 @@ static HRESULT equal_values(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexc
         VARIANT v;
         HRESULT hres;
 
-        hres = to_primitive(ctx->parser->script, lval, ei, &v);
+        hres = to_primitive(ctx->parser->script, lval, ei, &v, NO_HINT);
         if(FAILED(hres))
             return hres;
 
@@ -2638,11 +2638,11 @@ static HRESULT less_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, BOOL gre
     VARIANT l, r, ln, rn;
     HRESULT hres;
 
-    hres = to_primitive(ctx->parser->script, lval, ei, &l);
+    hres = to_primitive(ctx->parser->script, lval, ei, &l, NO_HINT);
     if(FAILED(hres))
         return hres;
 
-    hres = to_primitive(ctx->parser->script, rval, ei, &r);
+    hres = to_primitive(ctx->parser->script, rval, ei, &r, NO_HINT);
     if(FAILED(hres)) {
         VariantClear(&l);
         return hres;
diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h
index 7a4158c..8d7d61f 100644
--- a/dlls/jscript/jscript.h
+++ b/dlls/jscript/jscript.h
@@ -123,6 +123,7 @@ DispatchEx *iface_to_jsdisp(IUnknown*);
 
 HRESULT disp_call(IDispatch*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*);
 HRESULT jsdisp_call_value(DispatchEx*,LCID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*);
+HRESULT jsdisp_call(DispatchEx*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*);
 HRESULT disp_propget(IDispatch*,DISPID,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
 HRESULT disp_propput(IDispatch*,DISPID,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
 HRESULT jsdisp_propget(DispatchEx*,DISPID,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
@@ -145,7 +146,13 @@ HRESULT create_string(script_ctx_t*,const WCHAR*,DWORD,DispatchEx**);
 HRESULT create_bool(script_ctx_t*,VARIANT_BOOL,DispatchEx**);
 HRESULT create_number(script_ctx_t*,VARIANT*,DispatchEx**);
 
-HRESULT to_primitive(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*);
+typedef enum {
+    NO_HINT,
+    HINT_STRING,
+    HINT_NUMBER
+} hint_t;
+
+HRESULT to_primitive(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*, hint_t);
 HRESULT to_boolean(VARIANT*,VARIANT_BOOL*);
 HRESULT to_number(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*);
 HRESULT to_integer(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*);
diff --git a/dlls/jscript/jsutils.c b/dlls/jscript/jsutils.c
index eab850b..4a885a5 100644
--- a/dlls/jscript/jsutils.c
+++ b/dlls/jscript/jsutils.c
@@ -175,7 +175,7 @@ jsheap_t *jsheap_mark(jsheap_t *heap)
 }
 
 /* ECMA-262 3rd Edition    9.1 */
-HRESULT to_primitive(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
+HRESULT to_primitive(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret, hint_t hint)
 {
     switch(V_VT(v)) {
     case VT_EMPTY:
@@ -189,8 +189,61 @@ HRESULT to_primitive(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret
         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*/);
+    case VT_DISPATCH: {
+        DispatchEx *jsdisp;
+        DISPID id;
+        DISPPARAMS dp = {NULL, NULL, 0, 0};
+        HRESULT hres;
+
+        static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
+        static const WCHAR valueOfW[] = {'v','a','l','u','e','O','f',0};
+
+        jsdisp = iface_to_jsdisp((IUnknown*)V_DISPATCH(v));
+        if(!jsdisp)
+            return disp_propget(V_DISPATCH(v), DISPID_VALUE, ctx->lcid, ret, ei, NULL /*FIXME*/);
+
+        if(hint == NO_HINT)
+            hint = is_class(jsdisp, JSCLASS_DATE) ? HINT_STRING : HINT_NUMBER;
+
+        /* Native implementation doesn't throw TypeErrors, returns strange values */
+
+        hres = jsdisp_get_id(jsdisp, hint == HINT_STRING ? toStringW : valueOfW, 0, &id);
+        if(SUCCEEDED(hres)) {
+            hres = jsdisp_call(jsdisp, id, ctx->lcid, DISPATCH_METHOD, &dp, ret, ei, NULL /*FIXME*/);
+            if(FAILED(hres)) {
+                FIXME("throw TypeError\n");
+                jsdisp_release(jsdisp);
+                return hres;
+            }
+            else if(V_VT(ret) != VT_DISPATCH) {
+                jsdisp_release(jsdisp);
+                return S_OK;
+            }
+            else
+                IDispatch_Release(V_DISPATCH(ret));
+        }
+
+        hres = jsdisp_get_id(jsdisp, hint == HINT_STRING ? valueOfW : toStringW, 0, &id);
+        if(SUCCEEDED(hres)) {
+            hres = jsdisp_call(jsdisp, id, ctx->lcid, DISPATCH_METHOD, &dp, ret, ei, NULL /*FIXME*/);
+            if(FAILED(hres)) {
+                FIXME("throw TypeError\n");
+                jsdisp_release(jsdisp);
+                return hres;
+            }
+            else if(V_VT(ret) != VT_DISPATCH) {
+                jsdisp_release(jsdisp);
+                return S_OK;
+            }
+            else
+                IDispatch_Release(V_DISPATCH(ret));
+        }
+
+        jsdisp_release(jsdisp);
+
+        FIXME("throw TypeError\n");
+        return E_FAIL;
+    }
     default:
         FIXME("Unimplemented for vt %d\n", V_VT(v));
         return E_NOTIMPL;
@@ -356,7 +409,7 @@ HRESULT to_number(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
         VARIANT prim;
         HRESULT hres;
 
-        hres = to_primitive(ctx, v, ei, &prim);
+        hres = to_primitive(ctx, v, ei, &prim, HINT_NUMBER);
         if(FAILED(hres))
             return hres;
 
@@ -489,7 +542,7 @@ HRESULT to_string(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, BSTR *str)
         VARIANT prim;
         HRESULT hres;
 
-        hres = to_primitive(ctx, v, ei, &prim);
+        hres = to_primitive(ctx, v, ei, &prim, HINT_STRING);
         if(FAILED(hres))
             return hres;
 
diff --git a/dlls/jscript/tests/api.js b/dlls/jscript/tests/api.js
index 7075aec..79b255b 100644
--- a/dlls/jscript/tests/api.js
+++ b/dlls/jscript/tests/api.js
@@ -1026,6 +1026,8 @@ date.setUTCMonth(22, 37);
 ok(date.getTime() === 60987050010, "date.getTime() = " + date.getTime());
 date.setUTCFullYear(83, 21, 321);
 ok(date.getTime() === -59464984149990, "date.getTime() = " + date.getTime());
+ok(Math.abs(date) === 59464984149990, "Math.abs(date) = " + Math.abs(date));
+ok(getVT(date+1) === "VT_BSTR", "getVT(date+1) = " + getVT(date+1));
 
 ok(isNaN(Date.parse()), "Date.parse() is not NaN");
 ok(isNaN(Date.parse("")), "Date.parse(\"\") is not NaN");
diff --git a/dlls/jscript/tests/lang.js b/dlls/jscript/tests/lang.js
index cf04f9e..fcd6ec3 100644
--- a/dlls/jscript/tests/lang.js
+++ b/dlls/jscript/tests/lang.js
@@ -882,4 +882,16 @@ function testEmbededFunctions() {
 
 testEmbededFunctions();
 
+date = new Date();
+date.toString = function() { return "toString"; }
+ok(""+date === "toString", "''+date = " + date);
+date.toString = function() { return this; }
+ok(""+date === ""+date.valueOf(), "''+date = " + date);
+
+str = new String("test");
+str.valueOf = function() { return "valueOf"; }
+ok(""+str === "valueOf", "''+str = " + str);
+str.valueOf = function() { return new Date(); }
+ok(""+str === "test", "''+str = " + str);
+
 reportSuccess();




More information about the wine-cvs mailing list