-- v3: jscript: Fix error value when passing non-string 'this' to String's toString. jscript: Fallback to Object's toString for Arrays when 'this' isn't an jscript: Return proper error when passing wrong type to Function.apply. jscript: Allow objects that expose "length" prop for Function.apply under
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Behavior depends on mode. Javascript used inside mshtml allows non-JS objects that expose "length" to be used in apply(). For ES5 and above, even JS objects that expose "length" are allowed. Javascript not in HTML mode does not, however.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 37 +++++++++++++++++ dlls/jscript/function.c | 41 ++++++++++--------- dlls/jscript/jscript.h | 2 + dlls/jscript/tests/api.js | 2 + dlls/mshtml/tests/documentmode.js | 66 +++++++++++++++++++++++++++++++ 5 files changed, 129 insertions(+), 19 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 3b475237970..c5e1fb7e8a9 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -2975,6 +2975,35 @@ HRESULT jsdisp_propget_name(jsdisp_t *obj, const WCHAR *name, jsval_t *val) return prop_get(obj, to_disp(obj), prop, val); }
+HRESULT disp_propget_name(script_ctx_t *ctx, IDispatch *disp, const WCHAR *name, jsval_t *val) +{ + IDispatchEx *dispex; + jsdisp_t *jsdisp; + DISPID dispid; + HRESULT hres; + BSTR str; + + jsdisp = to_jsdisp(disp); + if(jsdisp && jsdisp->ctx == ctx) + return jsdisp_propget_name(jsdisp, name, val); + + if(!(str = SysAllocString(name))) + return E_OUTOFMEMORY; + hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); + if(hres != S_OK) + hres = IDispatch_GetIDsOfNames(disp, &IID_NULL, &str, 1, 0, &dispid); + else { + hres = IDispatchEx_GetDispID(dispex, str, fdexNameCaseSensitive, &dispid); + IDispatchEx_Release(dispex); + } + SysFreeString(str); + + if(SUCCEEDED(hres)) + hres = disp_propget(ctx, disp, dispid, val); + + return hres; +} + HRESULT jsdisp_get_idx(jsdisp_t *obj, DWORD idx, jsval_t *r) { WCHAR name[12]; @@ -2995,6 +3024,14 @@ HRESULT jsdisp_get_idx(jsdisp_t *obj, DWORD idx, jsval_t *r) return prop_get(obj, to_disp(obj), prop, r); }
+HRESULT disp_propget_idx(script_ctx_t *ctx, IDispatch *disp, DWORD idx, jsval_t *r) +{ + WCHAR buf[12]; + + swprintf(buf, ARRAY_SIZE(buf), L"%u", idx); + return disp_propget_name(ctx, disp, buf, r); +} + HRESULT jsdisp_propget(jsdisp_t *jsdisp, DISPID id, jsval_t *val) { dispex_prop_t *prop; diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index ffb55af0922..59384d1f0a2 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -417,27 +417,30 @@ static HRESULT Function_toString(script_ctx_t *ctx, jsval_t vthis, WORD flags, u return S_OK; }
-static HRESULT array_to_args(script_ctx_t *ctx, jsdisp_t *arg_array, unsigned *argc, jsval_t **ret) +static HRESULT array_to_args(script_ctx_t *ctx, IDispatch *disp, unsigned *argc, jsval_t **ret) { jsval_t *argv, val; - UINT32 length, i; HRESULT hres; + INT32 length; + UINT32 i;
- hres = jsdisp_propget_name(arg_array, L"length", &val); + hres = disp_propget_name(ctx, disp, L"length", &val); if(FAILED(hres)) - return hres; + return (hres == DISP_E_UNKNOWNNAME) ? JS_E_JSCRIPT_EXPECTED : hres;
- hres = to_uint32(ctx, val, &length); + hres = to_int32(ctx, val, &length); jsval_release(val); if(FAILED(hres)) return hres; + if(length < 0) + return JS_E_JSCRIPT_EXPECTED;
argv = malloc(length * sizeof(*argv)); if(!argv) return E_OUTOFMEMORY;
for(i=0; i<length; i++) { - hres = jsdisp_get_idx(arg_array, i, argv+i); + hres = disp_propget_idx(ctx, disp, i, argv+i); if(hres == DISP_E_UNKNOWNNAME) { argv[i] = jsval_undefined(); }else if(FAILED(hres)) { @@ -483,24 +486,24 @@ static HRESULT Function_apply(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsi }
if(argc >= 2) { - jsdisp_t *arg_array = NULL; + IDispatch *obj = NULL; + jsdisp_t *arg_array;
if(is_object_instance(argv[1])) { - arg_array = iface_to_jsdisp(get_object(argv[1])); - if(arg_array && - (!is_class(arg_array, JSCLASS_ARRAY) && !is_class(arg_array, JSCLASS_ARGUMENTS) )) { - jsdisp_release(arg_array); - arg_array = NULL; + obj = get_object(argv[1]); + arg_array = to_jsdisp(obj); + + if(ctx->version < SCRIPTLANGUAGEVERSION_ES5) { + if(!arg_array) { + if(!ctx->html_mode) + obj = NULL; + }else if(!is_class(arg_array, JSCLASS_ARRAY) && !is_class(arg_array, JSCLASS_ARGUMENTS)) { + obj = NULL; + } } }
- if(arg_array) { - hres = array_to_args(ctx, arg_array, &cnt, &args); - jsdisp_release(arg_array); - }else { - FIXME("throw TypeError\n"); - hres = E_FAIL; - } + hres = obj ? array_to_args(ctx, obj, &cnt, &args) : JS_E_JSCRIPT_EXPECTED; }
if(SUCCEEDED(hres)) { diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index a3009239ba1..5660ee48435 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -253,7 +253,9 @@ HRESULT jsdisp_call(jsdisp_t*,DISPID,WORD,unsigned,jsval_t*,jsval_t*); HRESULT jsdisp_call_name(jsdisp_t*,const WCHAR*,WORD,unsigned,jsval_t*,jsval_t*); HRESULT disp_propget(script_ctx_t*,IDispatch*,DISPID,jsval_t*); HRESULT disp_propput(script_ctx_t*,IDispatch*,DISPID,jsval_t); +HRESULT disp_propget_name(script_ctx_t*,IDispatch*,const WCHAR*,jsval_t*); HRESULT disp_propput_name(script_ctx_t*,IDispatch*,const WCHAR*,jsval_t); +HRESULT disp_propget_idx(script_ctx_t*,IDispatch*,DWORD,jsval_t*); HRESULT jsdisp_propget(jsdisp_t*,DISPID,jsval_t*); HRESULT jsdisp_propput(jsdisp_t*,const WCHAR*,DWORD,BOOL,jsval_t); HRESULT jsdisp_propput_name(jsdisp_t*,const WCHAR*,jsval_t); diff --git a/dlls/jscript/tests/api.js b/dlls/jscript/tests/api.js index aea7cac63dc..8c054fff058 100644 --- a/dlls/jscript/tests/api.js +++ b/dlls/jscript/tests/api.js @@ -2918,6 +2918,8 @@ testFunctionThis("toString"); testFunctionThis("call"); testFunctionThis("apply");
+testException(function() {(function (a, b) {}).apply(null, testObj)}, "E_JSCRIPT_EXPECTED"); + function testArrayHostThis(func) { testException(function() { Array.prototype[func].call(testObj); }, "E_JSCRIPT_EXPECTED"); } diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 8e8b87d7e36..562761a022f 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -502,6 +502,72 @@ sync_test("builtin_obj", function() { f.call = function() { }; ok(f.apply === 0, "changed f.apply = ", f.apply); ok(f.call instanceof Function, "changed f.call not instance of Function"); + + e = Array.isArray(document.body.childNodes); + ok(e === false, "isArray(childNodes) returned " + e); + } + + (function(a, b, c) { + ok(a === document.body.childNodes[0], "a = " + a); + ok(b === document.body.childNodes[1], "b = " + b); + ok(c === document.body.childNodes[2], "c = " + c); + }).apply(null, document.body.childNodes); + + elem1[0] = "a"; + elem1[1] = "b"; + if(v < 9) { + try { + (function(a, b) {}).apply(null, elem1); + }catch(ex) { + e = ex.number; + } + todo_wine. + ok(e === 0xa13a4 - 0x80000000, "[function.apply with elem without length] e = " + e); + }else { + (function(a, b) { + ok(a === undefined, "a = " + a); + ok(b === undefined, "b = " + b); + }).apply(null, elem1); + } + + elem1.length = 2; + (function(a, b) { + ok(a === "a", "a = " + a); + ok(b === "b", "b = " + b); + }).apply(null, elem1); + + elem1 = new Object; + elem1[0] = "c"; + elem1[1] = "d"; + if(v < 9) { + try { + (function(c, d) {}).apply(null, elem1); + }catch(ex) { + e = ex.number; + } + todo_wine. + ok(e === 0xa13a4 - 0x80000000, "[function.apply with Object without length] e = " + e); + }else { + (function(c, d) { + ok(c === undefined, "c = " + c); + ok(d === undefined, "d = " + d); + }).apply(null, elem1); + } + + elem1.length = 2; + if(v < 9) { + try { + (function(c, d) {}).apply(null, elem1); + }catch(ex) { + e = ex.number; + } + todo_wine. + ok(e === 0xa13a4 - 0x80000000, "[function.apply with Object with length] e = " + e); + }else { + (function(c, d) { + ok(c === "c", "c = " + c); + ok(d === "d", "d = " + d); + }).apply(null, elem1); } });
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/error.c | 1 + dlls/jscript/function.c | 6 +++--- dlls/jscript/jscript.h | 1 + dlls/jscript/jscript.rc | 1 + dlls/jscript/resource.h | 1 + dlls/mshtml/tests/documentmode.js | 3 --- 6 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/dlls/jscript/error.c b/dlls/jscript/error.c index 3ff40a1e1e7..a7513981676 100644 --- a/dlls/jscript/error.c +++ b/dlls/jscript/error.c @@ -489,6 +489,7 @@ jsdisp_t *create_builtin_error(script_ctx_t *ctx) case JS_E_JSCRIPT_EXPECTED: case JS_E_ENUMERATOR_EXPECTED: case JS_E_REGEXP_EXPECTED: + case JS_E_ARRAY_OR_ARGS_EXPECTED: case JS_E_ARRAY_EXPECTED: case JS_E_CYCLIC_PROTO_VALUE: case JS_E_CANNOT_CREATE_FOR_NONEXTENSIBLE: diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 59384d1f0a2..f4f9dd57d3b 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -426,14 +426,14 @@ static HRESULT array_to_args(script_ctx_t *ctx, IDispatch *disp, unsigned *argc,
hres = disp_propget_name(ctx, disp, L"length", &val); if(FAILED(hres)) - return (hres == DISP_E_UNKNOWNNAME) ? JS_E_JSCRIPT_EXPECTED : hres; + return (hres == DISP_E_UNKNOWNNAME) ? JS_E_ARRAY_OR_ARGS_EXPECTED : hres;
hres = to_int32(ctx, val, &length); jsval_release(val); if(FAILED(hres)) return hres; if(length < 0) - return JS_E_JSCRIPT_EXPECTED; + return JS_E_ARRAY_OR_ARGS_EXPECTED;
argv = malloc(length * sizeof(*argv)); if(!argv) @@ -503,7 +503,7 @@ static HRESULT Function_apply(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsi } }
- hres = obj ? array_to_args(ctx, obj, &cnt, &args) : JS_E_JSCRIPT_EXPECTED; + hres = obj ? array_to_args(ctx, obj, &cnt, &args) : ctx->html_mode ? JS_E_ARRAY_OR_ARGS_EXPECTED : JS_E_JSCRIPT_EXPECTED; }
if(SUCCEEDED(hres)) { diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 5660ee48435..30f3d8d6bfa 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -567,6 +567,7 @@ static inline HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, jsval_ #define JS_E_INVALID_URI_CHAR MAKE_JSERROR(IDS_URI_INVALID_CHAR) #define JS_E_FRACTION_DIGITS_OUT_OF_RANGE MAKE_JSERROR(IDS_FRACTION_DIGITS_OUT_OF_RANGE) #define JS_E_PRECISION_OUT_OF_RANGE MAKE_JSERROR(IDS_PRECISION_OUT_OF_RANGE) +#define JS_E_ARRAY_OR_ARGS_EXPECTED MAKE_JSERROR(IDS_ARRAY_OR_ARGS_EXPECTED) #define JS_E_INVALID_LENGTH MAKE_JSERROR(IDS_INVALID_LENGTH) #define JS_E_ARRAY_EXPECTED MAKE_JSERROR(IDS_ARRAY_EXPECTED) #define JS_E_CYCLIC_PROTO_VALUE MAKE_JSERROR(IDS_CYCLIC_PROTO_VALUE) diff --git a/dlls/jscript/jscript.rc b/dlls/jscript/jscript.rc index 3e46023adc6..998082a1046 100644 --- a/dlls/jscript/jscript.rc +++ b/dlls/jscript/jscript.rc @@ -69,6 +69,7 @@ STRINGTABLE IDS_URI_INVALID_CHAR "URI to be encoded contains invalid characters" IDS_FRACTION_DIGITS_OUT_OF_RANGE "Number of fraction digits is out of range" IDS_PRECISION_OUT_OF_RANGE "Precision is out of range" + IDS_ARRAY_OR_ARGS_EXPECTED "Array or arguments object expected" IDS_INVALID_LENGTH "Array length must be a finite positive integer" IDS_ARRAY_EXPECTED "Array object expected" IDS_INVALID_WRITABLE_PROP_DESC "'writable' attribute on the property descriptor cannot be set to 'true' on this object" diff --git a/dlls/jscript/resource.h b/dlls/jscript/resource.h index 640cc01cff9..30147f683a0 100644 --- a/dlls/jscript/resource.h +++ b/dlls/jscript/resource.h @@ -67,6 +67,7 @@ #define IDS_URI_INVALID_CODING 0x13A1 #define IDS_FRACTION_DIGITS_OUT_OF_RANGE 0x13A2 #define IDS_PRECISION_OUT_OF_RANGE 0x13A3 +#define IDS_ARRAY_OR_ARGS_EXPECTED 0x13A4 #define IDS_INVALID_LENGTH 0x13A5 #define IDS_ARRAY_EXPECTED 0x13A7 #define IDS_INVALID_WRITABLE_PROP_DESC 0x13AC diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 562761a022f..3a9fb8319bb 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -521,7 +521,6 @@ sync_test("builtin_obj", function() { }catch(ex) { e = ex.number; } - todo_wine. ok(e === 0xa13a4 - 0x80000000, "[function.apply with elem without length] e = " + e); }else { (function(a, b) { @@ -545,7 +544,6 @@ sync_test("builtin_obj", function() { }catch(ex) { e = ex.number; } - todo_wine. ok(e === 0xa13a4 - 0x80000000, "[function.apply with Object without length] e = " + e); }else { (function(c, d) { @@ -561,7 +559,6 @@ sync_test("builtin_obj", function() { }catch(ex) { e = ex.number; } - todo_wine. ok(e === 0xa13a4 - 0x80000000, "[function.apply with Object with length] e = " + e); }else { (function(c, d) {
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/array.c | 8 +++++- dlls/jscript/jscript.h | 1 + dlls/jscript/object.c | 2 +- dlls/jscript/tests/api.js | 1 + dlls/mshtml/tests/documentmode.js | 46 +++++++++++++++++++++++++++++++ 5 files changed, 56 insertions(+), 2 deletions(-)
diff --git a/dlls/jscript/array.c b/dlls/jscript/array.c index dfd9eda75cc..80fb52f486f 100644 --- a/dlls/jscript/array.c +++ b/dlls/jscript/array.c @@ -948,8 +948,14 @@ static HRESULT Array_toString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsi TRACE("\n");
array = array_this(vthis); - if(!array) + if(!array) { + if(ctx->version >= SCRIPTLANGUAGEVERSION_ES5) { + if(is_undefined(vthis) || is_null(vthis)) + return JS_E_OBJECT_EXPECTED; + return Object_toString(ctx, vthis, flags, argc, argv, r); + } return JS_E_ARRAY_EXPECTED; + }
return array_join(ctx, &array->dispex, array->length, L",", 1, to_string, r); } diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 30f3d8d6bfa..6175dea9c49 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -496,6 +496,7 @@ HRESULT localize_number(script_ctx_t*,DOUBLE,BOOL,jsstr_t**); BOOL is_builtin_eval_func(jsdisp_t*); HRESULT builtin_eval(script_ctx_t*,struct _call_frame_t*,WORD,unsigned,jsval_t*,jsval_t*); HRESULT JSGlobal_eval(script_ctx_t*,jsval_t,WORD,unsigned,jsval_t*,jsval_t*); +HRESULT Object_toString(script_ctx_t*,jsval_t,WORD,unsigned,jsval_t*,jsval_t*); HRESULT Object_get_proto_(script_ctx_t*,jsval_t,WORD,unsigned,jsval_t*,jsval_t*); HRESULT Object_set_proto_(script_ctx_t*,jsval_t,WORD,unsigned,jsval_t*,jsval_t*);
diff --git a/dlls/jscript/object.c b/dlls/jscript/object.c index feeff5c294a..a1ba990695b 100644 --- a/dlls/jscript/object.c +++ b/dlls/jscript/object.c @@ -24,7 +24,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
-static HRESULT Object_toString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, +HRESULT Object_toString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { const WCHAR *str = NULL; diff --git a/dlls/jscript/tests/api.js b/dlls/jscript/tests/api.js index 8c054fff058..9158e31fd8a 100644 --- a/dlls/jscript/tests/api.js +++ b/dlls/jscript/tests/api.js @@ -2704,6 +2704,7 @@ 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() {var o = new Object(); o.length = 1; o[0] = "a"; Array.prototype.toString.call(o);}, "E_NOT_ARRAY"); testException(function() {var o = new Object(); o.length = 1; o[0] = "a"; Array.prototype.toLocaleString.call(o);}, "E_NOT_ARRAY"); testException(function() {Number.prototype.toString.call(arr);}, "E_NOT_NUM"); testException(function() {Number.prototype.toFixed.call(arr);}, "E_NOT_NUM"); diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 3a9fb8319bb..59801936ecd 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -505,6 +505,52 @@ sync_test("builtin_obj", function() {
e = Array.isArray(document.body.childNodes); ok(e === false, "isArray(childNodes) returned " + e); + e = Array.prototype.toString.call(Number); + ok(e === "[object Function]", "Array.toString(Number) = " + e); + } + + function test_toString(msg, constr, err) { + var e = 0; + if(typeof(err) === "string") { + e = constr.prototype.toString.call(document.body); + ok(e === err, msg + ".toString(body) = " + e); + return; + } + try { + constr.prototype.toString.call(document.body); + }catch(ex) { + e = ex.number; + } + ok(e === err - 0x80000000, "[" + msg + ".toString(body)] e = " + e); + } + + test_toString("Array", Array, v < 9 ? 0xa13a7 : "[object HTMLBodyElement]"); + test_toString("Boolean", Boolean, 0xa1392); + test_toString("Date", Date, 0xa138e); + test_toString("RegExp", RegExp, 0xa1398); + test_toString("Number", Number, 0xa1389); + + if(v >= 9) { + var obj = { length: 2 }; + obj[0] = "foo"; + obj[1] = "bar"; + e = Array.prototype.toString.call(obj); + ok(e === "[object Object]", "Array.toString(array-like object) = " + e); + + obj = Object.create(null); + obj.length = 2; + obj[0] = "foo"; + obj[1] = "bar"; + e = Array.prototype.toString.call(obj); + ok(e === "[object Object]", "Array.toString(array-like object with no prototype) = " + e); + + e = 0; + try { + Array.prototype.toString.call(null); + }catch(ex) { + e = ex.number; + } + ok(e === 0xa138f - 0x80000000, "Array.toString(null) e = " + e); }
(function(a, b, c) {
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/error.c | 1 + dlls/jscript/jscript.h | 1 + dlls/jscript/jscript.rc | 1 + dlls/jscript/resource.h | 1 + dlls/jscript/string.c | 2 +- dlls/jscript/tests/api.js | 3 +++ dlls/mshtml/tests/documentmode.js | 1 + 7 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/dlls/jscript/error.c b/dlls/jscript/error.c index a7513981676..9f22b7feefa 100644 --- a/dlls/jscript/error.c +++ b/dlls/jscript/error.c @@ -479,6 +479,7 @@ jsdisp_t *create_builtin_error(script_ctx_t *ctx) case JS_E_MISSING_ARG: case JS_E_OBJECT_NOT_COLLECTION: case JS_E_FUNCTION_EXPECTED: + case JS_E_STRING_EXPECTED: case JS_E_DATE_EXPECTED: case JS_E_NUMBER_EXPECTED: case JS_E_OBJECT_EXPECTED: diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 6175dea9c49..0540bce380d 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -550,6 +550,7 @@ static inline HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, jsval_ #define JS_E_DISABLED_CC MAKE_JSERROR(IDS_DISABLED_CC) #define JS_E_EXPECTED_AT MAKE_JSERROR(IDS_EXPECTED_AT) #define JS_E_FUNCTION_EXPECTED MAKE_JSERROR(IDS_NOT_FUNC) +#define JS_E_STRING_EXPECTED MAKE_JSERROR(IDS_NOT_STRING) #define JS_E_DATE_EXPECTED MAKE_JSERROR(IDS_NOT_DATE) #define JS_E_NUMBER_EXPECTED MAKE_JSERROR(IDS_NOT_NUM) #define JS_E_OBJECT_EXPECTED MAKE_JSERROR(IDS_OBJECT_EXPECTED) diff --git a/dlls/jscript/jscript.rc b/dlls/jscript/jscript.rc index 998082a1046..189f6fe19a3 100644 --- a/dlls/jscript/jscript.rc +++ b/dlls/jscript/jscript.rc @@ -51,6 +51,7 @@ STRINGTABLE IDS_DISABLED_CC "Conditional compilation is turned off" IDS_EXPECTED_AT "Expected '@'" IDS_NOT_FUNC "Function expected" + IDS_NOT_STRING "'[object]' is not a string object" IDS_NOT_DATE "'[object]' is not a date object" IDS_NOT_NUM "Number expected" IDS_OBJECT_EXPECTED "Object expected" diff --git a/dlls/jscript/resource.h b/dlls/jscript/resource.h index 30147f683a0..7b37a7ae8ea 100644 --- a/dlls/jscript/resource.h +++ b/dlls/jscript/resource.h @@ -49,6 +49,7 @@ #define IDS_DISABLED_CC 0x0406 #define IDS_EXPECTED_AT 0x0408 #define IDS_NOT_FUNC 0x138A +#define IDS_NOT_STRING 0x138D #define IDS_NOT_DATE 0x138E #define IDS_NOT_NUM 0x1389 #define IDS_OBJECT_EXPECTED 0x138F diff --git a/dlls/jscript/string.c b/dlls/jscript/string.c index 42a2c697fbc..607dd7c0b65 100644 --- a/dlls/jscript/string.c +++ b/dlls/jscript/string.c @@ -89,7 +89,7 @@ static HRESULT stringobj_to_string(jsval_t vthis, jsval_t *r)
if(!(string = string_this(vthis))) { WARN("this is not a string object\n"); - return E_FAIL; + return JS_E_STRING_EXPECTED; }
if(r) diff --git a/dlls/jscript/tests/api.js b/dlls/jscript/tests/api.js index 9158e31fd8a..a6ac3c7ed33 100644 --- a/dlls/jscript/tests/api.js +++ b/dlls/jscript/tests/api.js @@ -2634,6 +2634,7 @@ var exception_array = { E_INVALID_LENGTH: { type: "RangeError", number: -2146823259 },
E_NOT_DATE: { type: "TypeError", number: -2146823282 }, + E_NOT_STRING: { type: "TypeError", number: -2146823283 }, E_NOT_BOOL: { type: "TypeError", number: -2146823278 }, E_ARG_NOT_OPT: { type: "TypeError", number: -2146827839 }, E_NO_PROPERTY: { type: "TypeError", number: -2146827850 }, @@ -2727,6 +2728,8 @@ 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() {String.prototype.toString.call(null);}, "E_NOT_STRING"); +testException(function() {String.prototype.toString.call([]);}, "E_NOT_STRING"); 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/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 59801936ecd..d671f43a1f5 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -529,6 +529,7 @@ sync_test("builtin_obj", function() { test_toString("Date", Date, 0xa138e); test_toString("RegExp", RegExp, 0xa1398); test_toString("Number", Number, 0xa1389); + test_toString("String", String, 0xa138d);
if(v >= 9) { var obj = { length: 2 };
This merge request was approved by Jacek Caban.