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