jscript: Changed to_primitive implementation.

This commit is contained in:
Piotr Caban 2009-07-08 10:52:56 +02:00 committed by Alexandre Julliard
parent 3f18e98413
commit b9be3bd766
7 changed files with 88 additions and 14 deletions

View File

@ -2634,7 +2634,7 @@ static HRESULT DateConstr_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPP
case 1: { case 1: {
VARIANT prim, num; 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)) if(FAILED(hres))
return hres; return hres;

View File

@ -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); 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) jsexcept_t *ei, IServiceProvider *caller)
{ {
dispex_prop_t *prop; dispex_prop_t *prop;

View File

@ -1931,11 +1931,11 @@ static HRESULT add_eval(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcept_
VARIANT r, l; VARIANT r, l;
HRESULT hres; 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)) if(FAILED(hres))
return 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)) { if(FAILED(hres)) {
VariantClear(&l); VariantClear(&l);
return hres; return hres;
@ -2518,7 +2518,7 @@ static HRESULT equal_values(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexc
VARIANT v; VARIANT v;
HRESULT hres; 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)) if(FAILED(hres))
return hres; return hres;
@ -2533,7 +2533,7 @@ static HRESULT equal_values(exec_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexc
VARIANT v; VARIANT v;
HRESULT hres; 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)) if(FAILED(hres))
return 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; VARIANT l, r, ln, rn;
HRESULT hres; 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)) if(FAILED(hres))
return 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)) { if(FAILED(hres)) {
VariantClear(&l); VariantClear(&l);
return hres; return hres;

View File

@ -123,6 +123,7 @@ DispatchEx *iface_to_jsdisp(IUnknown*);
HRESULT disp_call(IDispatch*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*); 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_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_propget(IDispatch*,DISPID,LCID,VARIANT*,jsexcept_t*,IServiceProvider*);
HRESULT disp_propput(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*); 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_bool(script_ctx_t*,VARIANT_BOOL,DispatchEx**);
HRESULT create_number(script_ctx_t*,VARIANT*,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_boolean(VARIANT*,VARIANT_BOOL*);
HRESULT to_number(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*); HRESULT to_number(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*);
HRESULT to_integer(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*); HRESULT to_integer(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*);

View File

@ -175,7 +175,7 @@ jsheap_t *jsheap_mark(jsheap_t *heap)
} }
/* ECMA-262 3rd Edition 9.1 */ /* 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)) { switch(V_VT(v)) {
case VT_EMPTY: 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_VT(ret) = VT_BSTR;
V_BSTR(ret) = SysAllocString(V_BSTR(v)); V_BSTR(ret) = SysAllocString(V_BSTR(v));
break; break;
case VT_DISPATCH: case VT_DISPATCH: {
return disp_propget(V_DISPATCH(v), DISPID_VALUE, ctx->lcid, ret, ei, NULL /*FIXME*/); 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: default:
FIXME("Unimplemented for vt %d\n", V_VT(v)); FIXME("Unimplemented for vt %d\n", V_VT(v));
return E_NOTIMPL; return E_NOTIMPL;
@ -356,7 +409,7 @@ HRESULT to_number(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
VARIANT prim; VARIANT prim;
HRESULT hres; HRESULT hres;
hres = to_primitive(ctx, v, ei, &prim); hres = to_primitive(ctx, v, ei, &prim, HINT_NUMBER);
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
@ -489,7 +542,7 @@ HRESULT to_string(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, BSTR *str)
VARIANT prim; VARIANT prim;
HRESULT hres; HRESULT hres;
hres = to_primitive(ctx, v, ei, &prim); hres = to_primitive(ctx, v, ei, &prim, HINT_STRING);
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;

View File

@ -1026,6 +1026,8 @@ date.setUTCMonth(22, 37);
ok(date.getTime() === 60987050010, "date.getTime() = " + date.getTime()); ok(date.getTime() === 60987050010, "date.getTime() = " + date.getTime());
date.setUTCFullYear(83, 21, 321); date.setUTCFullYear(83, 21, 321);
ok(date.getTime() === -59464984149990, "date.getTime() = " + date.getTime()); 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");
ok(isNaN(Date.parse("")), "Date.parse(\"\") is not NaN"); ok(isNaN(Date.parse("")), "Date.parse(\"\") is not NaN");

View File

@ -882,4 +882,16 @@ function testEmbededFunctions() {
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(); reportSuccess();