Commit 451169fb authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

jscript: Return double instead of VARIANT from to_number.

parent f1c9bd44
......@@ -127,20 +127,15 @@ static HRESULT Array_length(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISP
V_I4(retv) = This->length;
break;
case DISPATCH_PROPERTYPUT: {
VARIANT num;
DOUBLE len = -1;
DWORD i;
HRESULT hres;
hres = to_number(ctx, get_arg(dp, 0), ei, &num);
hres = to_number(ctx, get_arg(dp, 0), ei, &len);
if(FAILED(hres))
return hres;
if(V_VT(&num) == VT_I4)
len = V_I4(&num);
else
len = floor(V_R8(&num));
len = floor(len);
if(len!=(DWORD)len)
return throw_range_error(ctx, ei, JS_E_INVALID_LENGTH, NULL);
......@@ -573,7 +568,6 @@ static HRESULT Array_slice(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPA
VARIANT *retv, jsexcept_t *ei)
{
jsdisp_t *arr, *jsthis;
VARIANT v;
DOUBLE range;
DWORD length, start, end, idx;
HRESULT hres;
......@@ -585,15 +579,11 @@ static HRESULT Array_slice(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPA
return hres;
if(arg_cnt(dp)) {
hres = to_number(ctx, get_arg(dp, 0), ei, &v);
hres = to_number(ctx, get_arg(dp, 0), ei, &range);
if(FAILED(hres))
return hres;
if(V_VT(&v) == VT_I4)
range = V_I4(&v);
else
range = floor(V_R8(&v));
range = floor(range);
if(-range>length || isnan(range)) start = 0;
else if(range < 0) start = range+length;
else if(range <= length) start = range;
......@@ -602,15 +592,11 @@ static HRESULT Array_slice(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPA
else start = 0;
if(arg_cnt(dp)>1) {
hres = to_number(ctx, get_arg(dp, 1), ei, &v);
hres = to_number(ctx, get_arg(dp, 1), ei, &range);
if(FAILED(hres))
return hres;
if(V_VT(&v) == VT_I4)
range = V_I4(&v);
else
range = floor(V_R8(&v));
range = floor(range);
if(-range>length) end = 0;
else if(range < 0) end = range+length;
else if(range <= length) end = range;
......@@ -623,6 +609,8 @@ static HRESULT Array_slice(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, DISPPA
return hres;
for(idx=start; idx<end; idx++) {
VARIANT v;
hres = jsdisp_get_idx(jsthis, idx, &v, ei);
if(hres == DISP_E_UNKNOWNNAME)
continue;
......@@ -653,7 +641,7 @@ static HRESULT sort_cmp(script_ctx_t *ctx, jsdisp_t *cmp_func, VARIANT *v1, VARI
if(cmp_func) {
VARIANTARG args[2];
DISPPARAMS dp = {args, NULL, 2, 0};
VARIANT tmp;
double n;
VARIANT res;
args[0] = *v2;
......@@ -663,15 +651,14 @@ static HRESULT sort_cmp(script_ctx_t *ctx, jsdisp_t *cmp_func, VARIANT *v1, VARI
if(FAILED(hres))
return hres;
hres = to_number(ctx, &res, ei, &tmp);
hres = to_number(ctx, &res, ei, &n);
VariantClear(&res);
if(FAILED(hres))
return hres;
if(V_VT(&tmp) == VT_I4)
*cmp = V_I4(&tmp);
else
*cmp = V_R8(&tmp) > 0.0 ? 1 : -1;
if(n == 0)
*cmp = 0;
*cmp = n > 0.0 ? 1 : -1;
}else if(V_VT(v1) == VT_EMPTY) {
*cmp = V_VT(v2) == VT_EMPTY ? 0 : 1;
}else if(V_VT(v2) == VT_EMPTY) {
......
......@@ -148,12 +148,17 @@ static void stack_popn(exec_ctx_t *ctx, unsigned n)
static HRESULT stack_pop_number(exec_ctx_t *ctx, VARIANT *r)
{
VARIANT *v;
double n;
HRESULT hres;
v = stack_pop(ctx);
hres = to_number(ctx->script, v, ctx->ei, r);
hres = to_number(ctx->script, v, ctx->ei, &n);
VariantClear(v);
return hres;
if(FAILED(hres))
return hres;
num_set_val(r, n);
return S_OK;
}
static HRESULT stack_pop_object(exec_ctx_t *ctx, IDispatch **r)
......@@ -1526,13 +1531,13 @@ static HRESULT add_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jsexcep
if(V_VT(&r) != VT_BSTR)
SysFreeString(rstr);
}else {
VARIANT nl, nr;
double nl, nr;
hres = to_number(ctx, &l, ei, &nl);
if(SUCCEEDED(hres)) {
hres = to_number(ctx, &r, ei, &nr);
if(SUCCEEDED(hres))
num_set_val(retv, num_val(&nl) + num_val(&nr));
num_set_val(retv, nl + nr);
}
}
......@@ -1872,18 +1877,19 @@ static HRESULT interp_minus(exec_ctx_t *ctx)
/* ECMA-262 3rd Edition 11.4.6 */
static HRESULT interp_tonum(exec_ctx_t *ctx)
{
VARIANT *v, num;
VARIANT *v;
double n;
HRESULT hres;
TRACE("\n");
v = stack_pop(ctx);
hres = to_number(ctx->script, v, ctx->ei, &num);
hres = to_number(ctx->script, v, ctx->ei, &n);
VariantClear(v);
if(FAILED(hres))
return hres;
return stack_push(ctx, &num);
return stack_push_number(ctx, n);
}
/* ECMA-262 3rd Edition 11.3.1 */
......@@ -1903,11 +1909,12 @@ static HRESULT interp_postinc(exec_ctx_t *ctx)
hres = disp_propget(ctx->script, obj, id, &v, ctx->ei);
if(SUCCEEDED(hres)) {
VARIANT n, inc;
VARIANT inc;
double n;
hres = to_number(ctx->script, &v, ctx->ei, &n);
if(SUCCEEDED(hres)) {
num_set_val(&inc, num_val(&n)+(double)arg);
num_set_val(&inc, n+(double)arg);
hres = disp_propput(ctx->script, obj, id, &inc, ctx->ei);
}
if(FAILED(hres))
......@@ -1937,12 +1944,12 @@ static HRESULT interp_preinc(exec_ctx_t *ctx)
hres = disp_propget(ctx->script, obj, id, &v, ctx->ei);
if(SUCCEEDED(hres)) {
VARIANT n;
double n;
hres = to_number(ctx->script, &v, ctx->ei, &n);
VariantClear(&v);
if(SUCCEEDED(hres)) {
num_set_val(&v, num_val(&n)+(double)arg);
num_set_val(&v, n+(double)arg);
hres = disp_propput(ctx->script, obj, id, &v, ctx->ei);
}
}
......@@ -1980,23 +1987,31 @@ static HRESULT equal_values(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, jse
if(V_VT(lval) == VT_BSTR && is_num_vt(V_VT(rval))) {
VARIANT v;
double n;
HRESULT hres;
hres = to_number(ctx, lval, ei, &v);
hres = to_number(ctx, lval, ei, &n);
if(FAILED(hres))
return hres;
/* FIXME: optimize */
num_set_val(&v, n);
return equal_values(ctx, &v, rval, ei, ret);
}
if(V_VT(rval) == VT_BSTR && is_num_vt(V_VT(lval))) {
VARIANT v;
double n;
HRESULT hres;
hres = to_number(ctx, rval, ei, &v);
hres = to_number(ctx, rval, ei, &n);
if(FAILED(hres))
return hres;
/* FIXME: optimize */
num_set_val(&v, n);
return equal_values(ctx, lval, &v, ei, ret);
}
......@@ -2138,7 +2153,8 @@ static HRESULT interp_neq2(exec_ctx_t *ctx)
/* ECMA-262 3rd Edition 11.8.5 */
static HRESULT less_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, BOOL greater, jsexcept_t *ei, BOOL *ret)
{
VARIANT l, r, ln, rn;
double ln, rn;
VARIANT l, r;
HRESULT hres;
hres = to_primitive(ctx, lval, ei, &l, NO_HINT);
......@@ -2166,15 +2182,7 @@ static HRESULT less_eval(script_ctx_t *ctx, VARIANT *lval, VARIANT *rval, BOOL g
if(FAILED(hres))
return hres;
if(V_VT(&ln) == VT_I4 && V_VT(&rn) == VT_I4) {
*ret = (V_I4(&ln) < V_I4(&rn)) ^ greater;
}else {
DOUBLE ld = num_val(&ln);
DOUBLE rd = num_val(&rn);
*ret = !isnan(ld) && !isnan(rd) && ((ld < rd) ^ greater);
}
*ret = !isnan(ln) && !isnan(rn) && ((ln < rn) ^ greater);
return S_OK;
}
......
......@@ -234,18 +234,16 @@ static HRESULT error_constr(script_ctx_t *ctx, WORD flags, DISPPARAMS *dp,
HRESULT hres;
if(arg_cnt(dp)) {
VARIANT numv;
double n;
hres = to_number(ctx, get_arg(dp, 0), ei, &numv);
if(FAILED(hres) || (V_VT(&numv)==VT_R8 && isnan(V_R8(&numv))))
hres = to_number(ctx, get_arg(dp, 0), ei, &n);
if(FAILED(hres)) /* FIXME: really? */
n = ret_nan();
if(isnan(n))
hres = to_string(ctx, get_arg(dp, 0), ei, &msg);
else if(V_VT(&numv) == VT_I4)
num = V_I4(&numv);
else
num = V_R8(&numv);
if(FAILED(hres))
return hres;
num = n;
}
if(arg_cnt(dp)>1 && !msg) {
......
......@@ -386,21 +386,19 @@ static HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DIS
static HRESULT JSGlobal_isNaN(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei)
{
VARIANT_BOOL ret = VARIANT_FALSE;
VARIANT num;
VARIANT_BOOL ret = VARIANT_TRUE;
double n;
HRESULT hres;
TRACE("\n");
if(arg_cnt(dp)) {
hres = to_number(ctx, get_arg(dp,0), ei, &num);
hres = to_number(ctx, get_arg(dp,0), ei, &n);
if(FAILED(hres))
return hres;
if(V_VT(&num) == VT_R8 && isnan(V_R8(&num)))
ret = VARIANT_TRUE;
}else {
ret = VARIANT_TRUE;
if(!isnan(n))
ret = VARIANT_FALSE;
}
if(retv) {
......@@ -419,13 +417,13 @@ static HRESULT JSGlobal_isFinite(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
TRACE("\n");
if(arg_cnt(dp)) {
VARIANT num;
double n;
hres = to_number(ctx, get_arg(dp,0), ei, &num);
hres = to_number(ctx, get_arg(dp,0), ei, &n);
if(FAILED(hres))
return hres;
if(V_VT(&num) != VT_R8 || (!isinf(V_R8(&num)) && !isnan(V_R8(&num))))
if(!isinf(n) && !isnan(n))
ret = VARIANT_TRUE;
}
......
......@@ -253,7 +253,7 @@ typedef enum {
HRESULT to_primitive(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*, hint_t) DECLSPEC_HIDDEN;
HRESULT to_boolean(VARIANT*,VARIANT_BOOL*) DECLSPEC_HIDDEN;
HRESULT to_number(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*) DECLSPEC_HIDDEN;
HRESULT to_number(script_ctx_t*,VARIANT*,jsexcept_t*,double*) DECLSPEC_HIDDEN;
HRESULT to_integer(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*) DECLSPEC_HIDDEN;
HRESULT to_int32(script_ctx_t*,VARIANT*,jsexcept_t*,INT*) DECLSPEC_HIDDEN;
HRESULT to_uint32(script_ctx_t*,VARIANT*,jsexcept_t*,DWORD*) DECLSPEC_HIDDEN;
......@@ -451,6 +451,13 @@ static inline void num_set_inf(VARIANT *v, BOOL positive)
#endif
}
static inline DOUBLE ret_inf(void)
{
VARIANT v;
num_set_inf(&v, TRUE);
return V_R8(&v);
}
static inline void var_set_jsdisp(VARIANT *v, jsdisp_t *jsdisp)
{
V_VT(v) = VT_DISPATCH;
......
......@@ -312,7 +312,7 @@ static int hex_to_int(WCHAR c)
}
/* ECMA-262 3rd Edition 9.3.1 */
static HRESULT str_to_number(BSTR str, VARIANT *ret)
static HRESULT str_to_number(BSTR str, double *ret)
{
const WCHAR *ptr = str;
BOOL neg = FALSE;
......@@ -336,9 +336,9 @@ static HRESULT str_to_number(BSTR str, VARIANT *ret)
ptr++;
if(*ptr)
num_set_nan(ret);
*ret = ret_nan();
else
num_set_inf(ret, !neg);
*ret = neg ? -ret_inf() : ret_inf();
return S_OK;
}
......@@ -351,7 +351,7 @@ static HRESULT str_to_number(BSTR str, VARIANT *ret)
ptr++;
}
num_set_val(ret, d);
*ret = d;
return S_OK;
}
......@@ -390,31 +390,32 @@ static HRESULT str_to_number(BSTR str, VARIANT *ret)
ptr++;
if(*ptr) {
num_set_nan(ret);
*ret = ret_nan();
return S_OK;
}
if(neg)
d = -d;
num_set_val(ret, d);
*ret = d;
return S_OK;
}
/* ECMA-262 3rd Edition 9.3 */
HRESULT to_number(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
HRESULT to_number(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, double *ret)
{
switch(V_VT(v)) {
case VT_EMPTY:
num_set_nan(ret);
*ret = ret_nan();
break;
case VT_NULL:
V_VT(ret) = VT_I4;
V_I4(ret) = 0;
*ret = 0;
break;
case VT_I4:
*ret = V_I4(v);
break;
case VT_R8:
*ret = *v;
*ret = V_R8(v);
break;
case VT_BSTR:
return str_to_number(V_BSTR(v), ret);
......@@ -431,8 +432,7 @@ HRESULT to_number(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
return hres;
}
case VT_BOOL:
V_VT(ret) = VT_I4;
V_I4(ret) = V_BOOL(v) ? 1 : 0;
*ret = V_BOOL(v) ? 1 : 0;
break;
default:
FIXME("unimplemented for vt %d\n", V_VT(v));
......@@ -445,20 +445,23 @@ HRESULT to_number(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
/* ECMA-262 3rd Edition 9.4 */
HRESULT to_integer(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
{
VARIANT num;
double n;
HRESULT hres;
hres = to_number(ctx, v, ei, &num);
if(V_VT(v) == VT_I4) {
*ret = *v;
return S_OK;
}
hres = to_number(ctx, v, ei, &n);
if(FAILED(hres))
return hres;
if(V_VT(&num) == VT_I4) {
*ret = num;
}else if(isnan(V_R8(&num))) {
if(isnan(n)) {
V_VT(ret) = VT_I4;
V_I4(ret) = 0;
}else {
num_set_val(ret, V_R8(&num) >= 0.0 ? floor(V_R8(&num)) : -floor(-V_R8(&num)));
num_set_val(ret, n >= 0.0 ? floor(n) : -floor(-n));
}
return S_OK;
......@@ -467,34 +470,38 @@ HRESULT to_integer(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret)
/* ECMA-262 3rd Edition 9.5 */
HRESULT to_int32(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, INT *ret)
{
VARIANT num;
double n;
HRESULT hres;
hres = to_number(ctx, v, ei, &num);
if(V_VT(v) == VT_I4) {
*ret = V_I4(v);
return S_OK;
}
hres = to_number(ctx, v, ei, &n);
if(FAILED(hres))
return hres;
if(V_VT(&num) == VT_I4)
*ret = V_I4(&num);
else
*ret = isnan(V_R8(&num)) || isinf(V_R8(&num)) ? 0 : (INT)V_R8(&num);
*ret = isnan(n) || isinf(n) ? 0 : n;
return S_OK;
}
/* ECMA-262 3rd Edition 9.6 */
HRESULT to_uint32(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, DWORD *ret)
{
VARIANT num;
double n;
HRESULT hres;
hres = to_number(ctx, v, ei, &num);
if(V_VT(v) == VT_I4) {
*ret = V_I4(v);
return S_OK;
}
hres = to_number(ctx, v, ei, &n);
if(FAILED(hres))
return hres;
if(V_VT(&num) == VT_I4)
*ret = V_I4(&num);
else
*ret = isnan(V_R8(&num)) || isinf(V_R8(&num)) ? 0 : (DWORD)V_R8(&num);
*ret = isnan(n) || isinf(n) ? 0 : n;
return S_OK;
}
......@@ -679,17 +686,19 @@ HRESULT variant_change_type(script_ctx_t *ctx, VARIANT *dst, VARIANT *src, VARTY
}
break;
}
case VT_R8:
hres = to_number(ctx, src, &ei, dst);
if(SUCCEEDED(hres) && V_VT(dst) == VT_I4)
V_R8(dst) = V_I4(dst);
case VT_R8: {
double n;
hres = to_number(ctx, src, &ei, &n);
if(SUCCEEDED(hres))
V_R8(dst) = n;
break;
}
case VT_R4: {
VARIANT n;
double n;
hres = to_number(ctx, src, &ei, &n);
if(SUCCEEDED(hres))
V_R4(dst) = num_val(&n);
V_R4(dst) = n;
break;
}
case VT_BOOL: {
......
......@@ -263,7 +263,7 @@ static const builtin_info_t Number_info = {
static HRESULT NumberConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei)
{
VARIANT num;
double n;
HRESULT hres;
TRACE("\n");
......@@ -278,27 +278,30 @@ static HRESULT NumberConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
return S_OK;
}
hres = to_number(ctx, get_arg(dp, 0), ei, &num);
hres = to_number(ctx, get_arg(dp, 0), ei, &n);
if(FAILED(hres))
return hres;
if(retv)
*retv = num;
num_set_val(retv, n);
break;
case DISPATCH_CONSTRUCT: {
jsdisp_t *obj;
VARIANT v;
if(arg_cnt(dp)) {
hres = to_number(ctx, get_arg(dp, 0), ei, &num);
hres = to_number(ctx, get_arg(dp, 0), ei, &n);
if(FAILED(hres))
return hres;
num_set_val(&v, n);
}else {
V_VT(&num) = VT_I4;
V_I4(&num) = 0;
V_VT(&v) = VT_I4;
V_I4(&v) = 0;
}
hres = create_number(ctx, &num, &obj);
hres = create_number(ctx, &v, &obj);
if(FAILED(hres))
return hres;
......
......@@ -3522,22 +3522,18 @@ static HRESULT RegExp_multiline(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
static INT index_from_var(script_ctx_t *ctx, VARIANT *v)
{
jsexcept_t ei;
VARIANT num;
double n;
HRESULT hres;
memset(&ei, 0, sizeof(ei));
hres = to_number(ctx, v, &ei, &num);
hres = to_number(ctx, v, &ei, &n);
if(FAILED(hres)) { /* FIXME: Move ignoring exceptions to to_primitive */
VariantClear(&ei.var);
return 0;
}
if(V_VT(&num) == VT_R8) {
DOUBLE d = floor(V_R8(&num));
return (DOUBLE)(INT)d == d ? d : 0;
}
return V_I4(&num);
n = floor(n);
return (double)(INT)n == n ? n : 0;
}
static HRESULT RegExp_lastIndex(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment