This makes sure that object instances are always non-NULL and gets rid of
all such checks.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)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'");
--
2.34.1