jscript: Store NULL disps as a different type of jsval_null.

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>
Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Gabriel Ivăncescu 2022-03-24 17:31:06 +02:00 committed by Alexandre Julliard
parent 2b86208f8c
commit f6dc431af5
11 changed files with 93 additions and 82 deletions

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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);

View file

@ -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)) {

View file

@ -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:

View file

@ -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)

View file

@ -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);

View file

@ -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;
}

View file

@ -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");

View file

@ -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'");