This makes sure that object instances are always non-NULL and gets rid of all such checks.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
Hopefully, I handled all cases and objects now can never be NULL. I tested this with a bunch of test apps (some also needing the mshtml proxy object patches), no difference in behavior or crashes were observed, so I think it should cover all cases.
dlls/jscript/array.c | 13 +++++----- dlls/jscript/dispex.c | 8 +++---- dlls/jscript/engine.c | 31 ++++++++---------------- dlls/jscript/function.c | 13 ++++++---- dlls/jscript/json.c | 11 +++++---- dlls/jscript/jsutils.c | 49 ++++++++++++++++---------------------- dlls/jscript/jsval.h | 13 ++++++++-- dlls/jscript/object.c | 25 +++++++++++-------- dlls/jscript/set.c | 2 +- dlls/jscript/tests/api.js | 8 +++++++ dlls/jscript/tests/lang.js | 2 ++ 11 files changed, 93 insertions(+), 82 deletions(-)
diff --git a/dlls/jscript/array.c b/dlls/jscript/array.c index 9b97ef2..dcabc0d 100644 --- a/dlls/jscript/array.c +++ b/dlls/jscript/array.c @@ -704,7 +704,8 @@ static HRESULT Array_sort(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned hres = JS_E_JSCRIPT_EXPECTED; goto done; } - }else if(ctx->version >= SCRIPTLANGUAGEVERSION_ES5 ? !is_undefined(argv[0]) : !is_null(argv[0])) { + }else if(ctx->version >= SCRIPTLANGUAGEVERSION_ES5 ? !is_undefined(argv[0]) : + (!is_null(argv[0]) || is_null_disp(argv[0]))) { WARN("invalid arg %s\n", debugstr_jsval(argv[0])); hres = JS_E_JSCRIPT_EXPECTED; goto done; @@ -972,7 +973,7 @@ static HRESULT Array_forEach(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsig return hres;
/* Fixme check IsCallable */ - if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) { + if(!argc || !is_object_instance(argv[0])) { FIXME("Invalid arg %s\n", debugstr_jsval(argc ? argv[0] : jsval_undefined())); hres = E_INVALIDARG; goto done; @@ -980,7 +981,7 @@ static HRESULT Array_forEach(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsig callback = get_object(argv[0]);
if(argc > 1 && !is_undefined(argv[1])) { - if(!is_object_instance(argv[1]) || !get_object(argv[1])) { + if(!is_object_instance(argv[1])) { FIXME("Unsupported context this %s\n", debugstr_jsval(argv[1])); hres = E_NOTIMPL; goto done; @@ -1087,7 +1088,7 @@ static HRESULT Array_map(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned }
/* FIXME: check IsCallable */ - if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) { + if(!argc || !is_object_instance(argv[0])) { FIXME("Invalid arg %s\n", debugstr_jsval(argc ? argv[0] : jsval_undefined())); hres = E_INVALIDARG; goto done; @@ -1095,7 +1096,7 @@ static HRESULT Array_map(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned callback = get_object(argv[0]);
if(argc > 1) { - if(is_object_instance(argv[1]) && get_object(argv[1])) { + if(is_object_instance(argv[1])) { context_this = get_object(argv[1]); }else if(!is_undefined(argv[1])) { FIXME("Unsupported context this %s\n", debugstr_jsval(argv[1])); @@ -1154,7 +1155,7 @@ static HRESULT Array_reduce(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsign }
/* Fixme check IsCallable */ - if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) { + if(!argc || !is_object_instance(argv[0])) { FIXME("Invalid arg %s\n", debugstr_jsval(argc ? argv[0] : jsval_undefined())); hres = E_INVALIDARG; goto done; diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index df2f65f..ef13e29 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -574,7 +574,7 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t return invoke_prop_func(This->prototype, jsthis ? jsthis : (IDispatch *)&This->IDispatchEx_iface, This->prototype->props+prop->u.ref, flags, argc, argv, r, caller); case PROP_JSVAL: { - if(!is_object_instance(prop->u.val) || !get_object(prop->u.val)) { + if(!is_object_instance(prop->u.val)) { FIXME("invoke %s\n", debugstr_jsval(prop->u.val)); return E_FAIL; } @@ -593,7 +593,7 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t if(FAILED(hres)) return hres;
- if(is_object_instance(val) && get_object(val)) { + if(is_object_instance(val)) { hres = disp_call_value(This->ctx, get_object(val), jsthis ? jsthis : (IDispatch*)&This->IDispatchEx_iface, flags, argc, argv, r); @@ -1927,7 +1927,7 @@ HRESULT init_dispex_from_constr(jsdisp_t *dispex, script_ctx_t *ctx, const built return hres; }
- if(is_object_instance(val) && get_object(val)) + if(is_object_instance(val)) prot = iface_to_jsdisp(get_object(val)); else prot = jsdisp_addref(ctx->object_prototype); @@ -1987,7 +1987,7 @@ HRESULT jsdisp_call_value(jsdisp_t *jsfunc, IDispatch *jsthis, WORD flags, unsig }
flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK; - hres = jsfunc->builtin_info->call(jsfunc->ctx, jsval_disp(jsthis), flags, argc, argv, r); + hres = jsfunc->builtin_info->call(jsfunc->ctx, jsthis ? jsval_disp(jsthis) : jsval_null(), flags, argc, argv, r); } return hres; } diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index d894fbc..c483f2a 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -131,8 +131,6 @@ static HRESULT stack_pop_object(script_ctx_t *ctx, IDispatch **r)
v = stack_pop(ctx); if(is_object_instance(v)) { - if(!get_object(v)) - return JS_E_OBJECT_REQUIRED; *r = get_object(v); return S_OK; } @@ -539,10 +537,7 @@ HRESULT jsval_strict_equal(jsval_t lval, jsval_t rval, BOOL *ret) TRACE("\n");
if(type != jsval_type(rval)) { - if(is_null_instance(lval)) - *ret = is_null_instance(rval); - else - *ret = FALSE; + *ret = FALSE; return S_OK; }
@@ -1034,7 +1029,7 @@ static void set_error_value(script_ctx_t *ctx, jsval_t value) ei->valid_value = TRUE; ei->value = value;
- if(is_object_instance(value) && get_object(value) && (obj = to_jsdisp(get_object(value)))) { + if(is_object_instance(value) && (obj = to_jsdisp(get_object(value)))) { UINT32 number; jsstr_t *str; jsval_t v; @@ -1360,11 +1355,9 @@ static HRESULT interp_new(script_ctx_t *ctx) /* NOTE: Should use to_object here */
if(is_null(constr)) - return JS_E_OBJECT_EXPECTED; - else if(!is_object_instance(constr)) + return is_null_disp(constr) ? JS_E_INVALID_PROPERTY : JS_E_OBJECT_EXPECTED; + if(!is_object_instance(constr)) return JS_E_INVALID_ACTION; - else if(!get_object(constr)) - return JS_E_INVALID_PROPERTY;
clear_acc(ctx); return disp_call_value(ctx, get_object(constr), NULL, DISPATCH_CONSTRUCT | DISPATCH_JSCRIPT_CALLEREXECSSOURCE, @@ -1807,7 +1800,7 @@ static HRESULT interp_instanceof(script_ctx_t *ctx) HRESULT hres;
v = stack_pop(ctx); - if(!is_object_instance(v) || !get_object(v)) { + if(!is_object_instance(v)) { jsval_release(v); return JS_E_FUNCTION_EXPECTED; } @@ -1830,7 +1823,9 @@ static HRESULT interp_instanceof(script_ctx_t *ctx)
v = stack_pop(ctx);
- if(is_object_instance(prot)) { + if(is_null_disp(v)) + hres = JS_E_OBJECT_EXPECTED; + else if(is_object_instance(prot)) { if(is_object_instance(v)) tmp = iface_to_jsdisp(get_object(v)); for(iter = tmp; !ret && iter; iter = iter->prototype) { @@ -1867,7 +1862,7 @@ static HRESULT interp_in(script_ctx_t *ctx) TRACE("\n");
obj = stack_pop(ctx); - if(!is_object_instance(obj) || !get_object(obj)) { + if(!is_object_instance(obj)) { jsval_release(obj); return JS_E_OBJECT_EXPECTED; } @@ -2126,7 +2121,7 @@ static HRESULT typeof_string(jsval_t v, const WCHAR **ret) case JSV_OBJECT: { jsdisp_t *dispex;
- if(get_object(v) && (dispex = iface_to_jsdisp(get_object(v)))) { + if((dispex = iface_to_jsdisp(get_object(v)))) { *ret = is_class(dispex, JSCLASS_FUNCTION) ? L"function" : L"object"; jsdisp_release(dispex); }else { @@ -2326,12 +2321,6 @@ static HRESULT equal_values(script_ctx_t *ctx, jsval_t lval, jsval_t rval, BOOL if(jsval_type(lval) == jsval_type(rval) || (is_number(lval) && is_number(rval))) return jsval_strict_equal(lval, rval, ret);
- /* FIXME: NULL disps should be handled in more general way */ - if(is_object_instance(lval) && !get_object(lval)) - return equal_values(ctx, jsval_null(), rval, ret); - if(is_object_instance(rval) && !get_object(rval)) - return equal_values(ctx, lval, jsval_null(), ret); - if((is_null(lval) && is_undefined(rval)) || (is_undefined(lval) && is_null(rval))) { *ret = TRUE; return S_OK; diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index fc8a85c..03c541c 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -256,7 +256,7 @@ HRESULT Function_invoke(jsdisp_t *func_this, IDispatch *jsthis, WORD flags, unsi assert(is_class(func_this, JSCLASS_FUNCTION)); function = function_from_jsdisp(func_this);
- return function->vtbl->call(function->dispex.ctx, function, jsval_disp(jsthis), flags, argc, argv, r); + return function->vtbl->call(function->dispex.ctx, function, jsthis ? jsval_disp(jsthis) : jsval_null(), flags, argc, argv, r); }
static HRESULT Function_get_length(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) @@ -336,6 +336,8 @@ static HRESULT Function_apply(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsi
TRACE("\n");
+ if(is_null_disp(vthis)) + return JS_E_OBJECT_REQUIRED; if(!is_object_instance(vthis) || (!(function = function_this(vthis)) && to_jsdisp(get_object(vthis)))) return JS_E_FUNCTION_EXPECTED;
@@ -407,6 +409,8 @@ static HRESULT Function_call(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsig
TRACE("\n");
+ if(is_null_disp(vthis)) + return JS_E_OBJECT_REQUIRED; if(!(function = function_this(vthis))) return JS_E_FUNCTION_EXPECTED;
@@ -663,7 +667,7 @@ HRESULT create_builtin_function(script_ctx_t *ctx, builtin_invoke_t value_proc, hres = jsdisp_define_data_property(&function->function.dispex, L"length", 0, jsval_number(function->function.length)); if(SUCCEEDED(hres)) - hres = jsdisp_define_data_property(&function->function.dispex, L"prototype", 0, jsval_obj(prototype)); + hres = jsdisp_define_data_property(&function->function.dispex, L"prototype", 0, prototype ? jsval_obj(prototype) : jsval_null()); if(FAILED(hres)) { jsdisp_release(&function->function.dispex); return hres; @@ -725,8 +729,7 @@ static HRESULT InterpretedFunction_call(script_ctx_t *ctx, FunctionInstance *fun this_obj = to_disp(new_obj); }else if(is_object_instance(vthis)) { this_obj = get_object(vthis); - if(this_obj) - IDispatch_AddRef(this_obj); + IDispatch_AddRef(this_obj); }else if(ctx->version >= SCRIPTLANGUAGEVERSION_ES5 && !is_undefined(vthis) && !is_null(vthis)) { hres = to_object(ctx, vthis, &this_obj); if(FAILED(hres)) @@ -836,7 +839,7 @@ static HRESULT BindFunction_call(script_ctx_t *ctx, FunctionInstance *func, jsva memcpy(call_args + function->argc, argv, argc * sizeof(*call_args)); }
- hres = function->target->vtbl->call(ctx, function->target, jsval_disp(function->this), + hres = function->target->vtbl->call(ctx, function->target, function->this ? jsval_disp(function->this) : jsval_null(), flags, call_argc, call_args, r);
heap_free(call_args); diff --git a/dlls/jscript/json.c b/dlls/jscript/json.c index e0867eb..dfcc39d 100644 --- a/dlls/jscript/json.c +++ b/dlls/jscript/json.c @@ -404,7 +404,7 @@ static HRESULT maybe_to_primitive(script_ctx_t *ctx, jsval_t val, jsval_t *r) jsdisp_t *obj; HRESULT hres;
- if(!is_object_instance(val) || !get_object(val) || !(obj = iface_to_jsdisp(get_object(val)))) + if(!is_object_instance(val) || !(obj = iface_to_jsdisp(get_object(val)))) return jsval_copy(val, r);
if(is_class(obj, JSCLASS_NUMBER)) { @@ -640,7 +640,7 @@ static HRESULT stringify(stringify_ctx_t *ctx, jsdisp_t *object, const WCHAR *na if(FAILED(hres)) return hres == DISP_E_UNKNOWNNAME ? S_FALSE : hres;
- if(is_object_instance(value) && get_object(value)) { + if(is_object_instance(value)) { jsdisp_t *obj; DISPID id;
@@ -681,7 +681,9 @@ static HRESULT stringify(stringify_ctx_t *ctx, jsdisp_t *object, const WCHAR *na
switch(jsval_type(value)) { case JSV_NULL: - if(!append_string(ctx, L"null")) + if(is_null_disp(value)) + hres = S_FALSE; + else if(!append_string(ctx, L"null")) hres = E_OUTOFMEMORY; break; case JSV_BOOL: @@ -763,8 +765,7 @@ static HRESULT JSON_stringify(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsi return S_OK; }
- if(argc >= 2 && is_object_instance(argv[1]) && get_object(argv[1]) && - (replacer = to_jsdisp(get_object(argv[1])))) { + if(argc >= 2 && is_object_instance(argv[1]) && (replacer = to_jsdisp(get_object(argv[1])))) { if(is_callable(replacer)) { stringify_ctx.replacer = jsdisp_addref(replacer); }else if(is_class(replacer, JSCLASS_ARRAY)) { diff --git a/dlls/jscript/jsutils.c b/dlls/jscript/jsutils.c index 6bc34da..7debf07 100644 --- a/dlls/jscript/jsutils.c +++ b/dlls/jscript/jsutils.c @@ -183,8 +183,7 @@ void jsval_release(jsval_t val) { switch(jsval_type(val)) { case JSV_OBJECT: - if(get_object(val)) - IDispatch_Release(get_object(val)); + IDispatch_Release(get_object(val)); break; case JSV_STRING: jsstr_release(get_string(val)); @@ -229,8 +228,7 @@ HRESULT jsval_copy(jsval_t v, jsval_t *r) *r = v; return S_OK; case JSV_OBJECT: - if(get_object(v)) - IDispatch_AddRef(get_object(v)); + IDispatch_AddRef(get_object(v)); *r = v; return S_OK; case JSV_STRING: { @@ -282,8 +280,11 @@ HRESULT variant_to_jsval(VARIANT *var, jsval_t *r) return S_OK; } case VT_DISPATCH: { - if(V_DISPATCH(var)) - IDispatch_AddRef(V_DISPATCH(var)); + if(!V_DISPATCH(var)) { + *r = jsval_null_disp(); + return S_OK; + } + IDispatch_AddRef(V_DISPATCH(var)); *r = jsval_disp(V_DISPATCH(var)); return S_OK; } @@ -332,7 +333,7 @@ HRESULT variant_to_jsval(VARIANT *var, jsval_t *r) return S_OK; } }else { - *r = jsval_disp(NULL); + *r = jsval_null_disp(); return S_OK; } /* fall through */ @@ -348,13 +349,17 @@ HRESULT jsval_to_variant(jsval_t val, VARIANT *retv) V_VT(retv) = VT_EMPTY; return S_OK; case JSV_NULL: + if(get_bool(val)) { + V_VT(retv) = VT_DISPATCH; + V_DISPATCH(retv) = NULL; + return S_OK; + } V_VT(retv) = VT_NULL; return S_OK; case JSV_OBJECT: V_VT(retv) = VT_DISPATCH; - if(get_object(val)) - IDispatch_AddRef(get_object(val)); V_DISPATCH(retv) = get_object(val); + IDispatch_AddRef(get_object(val)); return S_OK; case JSV_STRING: V_VT(retv) = VT_BSTR; @@ -394,11 +399,6 @@ HRESULT to_primitive(script_ctx_t *ctx, jsval_t val, jsval_t *ret, hint_t hint) DISPID id; HRESULT hres;
- if(!get_object(val)) { - *ret = jsval_null(); - return S_OK; - } - jsdisp = iface_to_jsdisp(get_object(val)); if(!jsdisp) return disp_propget(ctx, get_object(val), DISPID_VALUE, ret); @@ -459,7 +459,7 @@ HRESULT to_boolean(jsval_t val, BOOL *ret) *ret = FALSE; return S_OK; case JSV_OBJECT: - *ret = get_object(val) != NULL; + *ret = TRUE; return S_OK; case JSV_STRING: *ret = jsstr_length(get_string(val)) != 0; @@ -839,18 +839,8 @@ HRESULT to_object(script_ctx_t *ctx, jsval_t val, IDispatch **disp) *disp = to_disp(dispex); break; case JSV_OBJECT: - if(get_object(val)) { - *disp = get_object(val); - IDispatch_AddRef(*disp); - }else { - jsdisp_t *obj; - - hres = create_object(ctx, NULL, &obj); - if(FAILED(hres)) - return hres; - - *disp = to_disp(obj); - } + *disp = get_object(val); + IDispatch_AddRef(*disp); break; case JSV_BOOL: hres = create_bool(ctx, get_bool(val), &dispex); @@ -859,8 +849,11 @@ HRESULT to_object(script_ctx_t *ctx, jsval_t val, IDispatch **disp)
*disp = to_disp(dispex); break; - case JSV_UNDEFINED: case JSV_NULL: + if(is_null_disp(val)) + return JS_E_OBJECT_REQUIRED; + /* fall through */ + case JSV_UNDEFINED: WARN("object expected\n"); return JS_E_OBJECT_EXPECTED; case JSV_VARIANT: diff --git a/dlls/jscript/jsval.h b/dlls/jscript/jsval.h index 9f451b1..4e00d08 100644 --- a/dlls/jscript/jsval.h +++ b/dlls/jscript/jsval.h @@ -131,6 +131,15 @@ static inline jsval_t jsval_null(void) { jsval_t ret; __JSVAL_TYPE(ret) = JSV_NULL; + __JSVAL_BOOL(ret) = FALSE; + return ret; +} + +static inline jsval_t jsval_null_disp(void) +{ + jsval_t ret; + __JSVAL_TYPE(ret) = JSV_NULL; + __JSVAL_BOOL(ret) = TRUE; return ret; }
@@ -178,9 +187,9 @@ static inline BOOL is_null(jsval_t v) return __JSVAL_TYPE(v) == JSV_NULL; }
-static inline BOOL is_null_instance(jsval_t v) +static inline BOOL is_null_disp(jsval_t v) { - return is_null(v) || (is_object_instance(v) && !__JSVAL_OBJ(v)); + return is_null(v) && __JSVAL_BOOL(v); }
static inline BOOL is_string(jsval_t v) diff --git a/dlls/jscript/object.c b/dlls/jscript/object.c index f8f1407..9d4a747 100644 --- a/dlls/jscript/object.c +++ b/dlls/jscript/object.c @@ -127,6 +127,11 @@ static HRESULT Object_valueOf(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsi
TRACE("\n");
+ if(is_null_disp(vthis)) { + if(r) *r = jsval_null_disp(); + return S_OK; + } + hres = to_object(ctx, vthis, &disp); if(FAILED(hres)) return hres; @@ -554,7 +559,7 @@ static HRESULT jsdisp_define_properties(script_ctx_t *ctx, jsdisp_t *obj, jsval_ if(FAILED(hres)) break;
- if(!is_object_instance(desc_val) || !get_object(desc_val) || !(desc_obj = to_jsdisp(get_object(desc_val)))) { + if(!is_object_instance(desc_val) || !(desc_obj = to_jsdisp(get_object(desc_val)))) { jsval_release(desc_val); break; } @@ -631,7 +636,7 @@ static HRESULT Object_defineProperties(script_ctx_t *ctx, jsval_t vthis, WORD fl jsdisp_t *obj; HRESULT hres;
- if(argc < 1 || !is_object_instance(argv[0]) || !get_object(argv[0]) || !(obj = to_jsdisp(get_object(argv[0])))) { + if(argc < 1 || !is_object_instance(argv[0]) || !(obj = to_jsdisp(get_object(argv[0])))) { FIXME("not an object\n"); return E_NOTIMPL; } @@ -779,7 +784,7 @@ static HRESULT object_keys(script_ctx_t *ctx, jsval_t arg, enum jsdisp_enum_type jsstr_t *key; HRESULT hres;
- if(!is_object_instance(arg) || !get_object(arg)) { + if(!is_object_instance(arg)) { FIXME("invalid arguments %s\n", debugstr_jsval(arg)); return E_NOTIMPL; } @@ -838,7 +843,7 @@ static HRESULT Object_preventExtensions(script_ctx_t *ctx, jsval_t vthis, WORD f { jsdisp_t *obj;
- if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) { + if(!argc || !is_object_instance(argv[0])) { FIXME("invalid arguments\n"); return E_NOTIMPL; } @@ -861,7 +866,7 @@ static HRESULT Object_freeze(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsig { jsdisp_t *obj;
- if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) { + if(!argc || !is_object_instance(argv[0])) { WARN("argument is not an object\n"); return JS_E_OBJECT_EXPECTED; } @@ -884,7 +889,7 @@ static HRESULT Object_seal(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigne { jsdisp_t *obj;
- if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) { + if(!argc || !is_object_instance(argv[0])) { WARN("argument is not an object\n"); return JS_E_OBJECT_EXPECTED; } @@ -906,7 +911,7 @@ static HRESULT Object_isExtensible(script_ctx_t *ctx, jsval_t vthis, WORD flags, { jsdisp_t *obj;
- if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) { + if(!argc || !is_object_instance(argv[0])) { WARN("argument is not an object\n"); return JS_E_OBJECT_EXPECTED; } @@ -928,7 +933,7 @@ static HRESULT Object_isFrozen(script_ctx_t *ctx, jsval_t vthis, WORD flags, uns { jsdisp_t *obj;
- if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) { + if(!argc || !is_object_instance(argv[0])) { WARN("argument is not an object\n"); return JS_E_OBJECT_EXPECTED; } @@ -950,7 +955,7 @@ static HRESULT Object_isSealed(script_ctx_t *ctx, jsval_t vthis, WORD flags, uns { jsdisp_t *obj;
- if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) { + if(!argc || !is_object_instance(argv[0])) { WARN("argument is not an object\n"); return JS_E_OBJECT_EXPECTED; } @@ -1005,7 +1010,7 @@ static HRESULT ObjectConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, jsdisp_t *obj;
if(argc) { - if(!is_undefined(argv[0]) && !is_null(argv[0]) && (!is_object_instance(argv[0]) || get_object(argv[0]))) { + if(!is_undefined(argv[0]) && !is_null(argv[0])) { IDispatch *disp;
hres = to_object(ctx, argv[0], &disp); diff --git a/dlls/jscript/set.c b/dlls/jscript/set.c index 35edcf8..7973d42 100644 --- a/dlls/jscript/set.c +++ b/dlls/jscript/set.c @@ -274,7 +274,7 @@ static HRESULT Map_forEach(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigne
TRACE("%p (%s)\n", map, debugstr_jsval(argc >= 1 ? argv[0] : jsval_undefined()));
- if(!is_object_instance(callback) || !get_object(callback)) { + if(!is_object_instance(callback)) { FIXME("invalid callback %s\n", debugstr_jsval(callback)); return E_FAIL; } diff --git a/dlls/jscript/tests/api.js b/dlls/jscript/tests/api.js index 8e2b0d6..9eaeddd 100644 --- a/dlls/jscript/tests/api.js +++ b/dlls/jscript/tests/api.js @@ -1926,6 +1926,7 @@ ok(isNaN(tmp), "Math.tan(-Infinity) is not NaN"); [[true], "true"], [[false], "false"], [[null], "null"], + [[nullDisp], undefined], [[1], "1"], [["test"], ""test""], [["test"\\b\f\n\r\t\u0002 !"], ""test\"\\\b\f\n\r\t\u0002 !""], @@ -2367,6 +2368,9 @@ ok(bool.toString() === "true", "bool.toString() = " + bool.toString()); ok(bool.valueOf() === Boolean(1), "bool.valueOf() = " + bool.valueOf()); ok(bool.toLocaleString() === bool.toString(), "bool.toLocaleString() = " + bool.toLocaleString());
+tmp = Object.prototype.valueOf.call(nullDisp); +ok(tmp === nullDisp, "nullDisp.valueOf != nullDisp"); + ok(ActiveXObject instanceof Function, "ActiveXObject is not instance of Function"); ok(ActiveXObject.prototype instanceof Object, "ActiveXObject.prototype is not instance of Object");
@@ -2574,6 +2578,7 @@ testException(function() {createArray().getItem(3);}, "E_SUBSCRIPT_OUT_OF_RANGE" testException(function() {date.setTime();}, "E_ARG_NOT_OPT"); testException(function() {date.setYear();}, "E_ARG_NOT_OPT"); testException(function() {arr.test();}, "E_NO_PROPERTY"); +testException(function() {[1,2,3].sort(nullDisp);}, "E_JSCRIPT_EXPECTED"); testException(function() {Number.prototype.toString.call(arr);}, "E_NOT_NUM"); testException(function() {Number.prototype.toFixed.call(arr);}, "E_NOT_NUM"); testException(function() {(new Number(3)).toString(1);}, "E_INVALID_CALL_ARG"); @@ -2587,6 +2592,9 @@ testException(function() {eval("nonexistingfunc()")}, "E_OBJECT_EXPECTED"); testException(function() {(new Object()) instanceof 3;}, "E_NOT_FUNC"); testException(function() {(new Object()) instanceof null;}, "E_NOT_FUNC"); testException(function() {(new Object()) instanceof nullDisp;}, "E_NOT_FUNC"); +testException(function() {nullDisp instanceof Object;}, "E_OBJECT_EXPECTED"); +testException(function() {Function.prototype.apply.call(nullDisp, Object, []);}, "E_OBJECT_REQUIRED"); +testException(function() {Function.prototype.call.call(nullDisp, Object);}, "E_OBJECT_REQUIRED"); testException(function() {"test" in 3;}, "E_OBJECT_EXPECTED"); testException(function() {"test" in null;}, "E_OBJECT_EXPECTED"); testException(function() {"test" in nullDisp;}, "E_OBJECT_EXPECTED"); diff --git a/dlls/jscript/tests/lang.js b/dlls/jscript/tests/lang.js index 23c9c79..cf08423 100644 --- a/dlls/jscript/tests/lang.js +++ b/dlls/jscript/tests/lang.js @@ -1906,6 +1906,8 @@ ok(getVT(true && nullDisp) === "VT_DISPATCH", "getVT(0 && nullDisp) = " + getVT(true && nullDisp)); ok(!nullDisp === true, "!nullDisp = " + !nullDisp); ok(String(nullDisp) === "null", "String(nullDisp) = " + String(nullDisp)); +ok(+nullDisp === 0, "+nullDisp !== 0"); +ok(''+nullDisp === "null", "''+nullDisp !== null"); ok(nullDisp != new Object(), "nullDisp == new Object()"); ok(new Object() != nullDisp, "new Object() == nullDisp"); ok((typeof Object(nullDisp)) === "object", "typeof Object(nullDisp) !== 'object'");