From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/arraybuf.c | 49 ++++++++++++++++++++++++++++++++++++++-- dlls/jscript/error.c | 1 + dlls/jscript/jscript.h | 1 + dlls/jscript/jscript.rc | 1 + dlls/jscript/resource.h | 1 + dlls/mshtml/tests/es5.js | 46 ++++++++++++++++++++++++++++++++++++- 6 files changed, 96 insertions(+), 3 deletions(-)
diff --git a/dlls/jscript/arraybuf.c b/dlls/jscript/arraybuf.c index afcf3229773..300893d2034 100644 --- a/dlls/jscript/arraybuf.c +++ b/dlls/jscript/arraybuf.c @@ -55,6 +55,8 @@ static inline ArrayBufferInstance *arraybuf_this(jsval_t vthis) return (jsdisp && is_class(jsdisp, JSCLASS_ARRAYBUFFER)) ? arraybuf_from_jsdisp(jsdisp) : NULL; }
+static HRESULT create_arraybuf(script_ctx_t*,DWORD,jsdisp_t**); + static HRESULT ArrayBuffer_get_byteLength(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) { TRACE("%p\n", jsthis); @@ -66,9 +68,52 @@ static HRESULT ArrayBuffer_get_byteLength(script_ctx_t *ctx, jsdisp_t *jsthis, j static HRESULT ArrayBuffer_slice(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - FIXME("not implemented\n"); + ArrayBufferInstance *arraybuf; + DWORD begin = 0, end, size; + jsdisp_t *obj; + HRESULT hres; + double n;
- return E_NOTIMPL; + TRACE("\n"); + + if(!(arraybuf = arraybuf_this(vthis))) + return JS_E_ARRAYBUFFER_EXPECTED; + end = arraybuf->size; + if(!r) + return S_OK; + + if(argc) { + hres = to_integer(ctx, argv[0], &n); + if(FAILED(hres)) + return hres; + if(n < 0.0) + n += arraybuf->size; + if(n >= 0.0 && n < arraybuf->size) { + begin = n; + if(argc > 1 && !is_undefined(argv[1])) { + hres = to_integer(ctx, argv[1], &n); + if(FAILED(hres)) + return hres; + if(n < 0.0) + n += arraybuf->size; + if(n >= 0.0) { + end = n < arraybuf->size ? n : arraybuf->size; + end = end < begin ? begin : end; + }else + end = begin; + } + }else + end = 0; + } + + size = end - begin; + hres = create_arraybuf(ctx, size, &obj); + if(FAILED(hres)) + return hres; + memcpy(arraybuf_from_jsdisp(obj)->buf, arraybuf->buf + begin, size); + + *r = jsval_obj(obj); + return S_OK; }
static const builtin_prop_t ArrayBuffer_props[] = { diff --git a/dlls/jscript/error.c b/dlls/jscript/error.c index 60d090ec76e..81e3a3a9739 100644 --- a/dlls/jscript/error.c +++ b/dlls/jscript/error.c @@ -487,6 +487,7 @@ jsdisp_t *create_builtin_error(script_ctx_t *ctx) case JS_E_DATAVIEW_NO_ARGUMENT: case JS_E_WRONG_THIS: case JS_E_KEY_NOT_OBJECT: + case JS_E_ARRAYBUFFER_EXPECTED: case JS_E_PROP_DESC_MISMATCH: case JS_E_INVALID_WRITABLE_PROP_DESC: constr = ctx->type_error_constr; diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 07e0c4693be..2453cba4939 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -587,6 +587,7 @@ static inline HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, jsval_ #define JS_E_DATAVIEW_INVALID_OFFSET MAKE_JSERROR(IDS_DATAVIEW_INVALID_OFFSET) #define JS_E_WRONG_THIS MAKE_JSERROR(IDS_WRONG_THIS) #define JS_E_KEY_NOT_OBJECT MAKE_JSERROR(IDS_KEY_NOT_OBJECT) +#define JS_E_ARRAYBUFFER_EXPECTED MAKE_JSERROR(IDS_ARRAYBUFFER_EXPECTED) #define JS_E_PROP_DESC_MISMATCH MAKE_JSERROR(IDS_PROP_DESC_MISMATCH) #define JS_E_INVALID_WRITABLE_PROP_DESC MAKE_JSERROR(IDS_INVALID_WRITABLE_PROP_DESC)
diff --git a/dlls/jscript/jscript.rc b/dlls/jscript/jscript.rc index 1cfc9040f51..cbdfde507b7 100644 --- a/dlls/jscript/jscript.rc +++ b/dlls/jscript/jscript.rc @@ -82,6 +82,7 @@ STRINGTABLE IDS_DATAVIEW_INVALID_OFFSET "DataView constructor argument offset is invalid" IDS_WRONG_THIS "'this' is not a | object" IDS_KEY_NOT_OBJECT "'key' is not an object" + IDS_ARRAYBUFFER_EXPECTED "ArrayBuffer object expected" IDS_PROP_DESC_MISMATCH "Property cannot have both accessors and a value"
IDS_COMPILATION_ERROR "Microsoft JScript compilation error" diff --git a/dlls/jscript/resource.h b/dlls/jscript/resource.h index e2b60b98bd5..801e940b95e 100644 --- a/dlls/jscript/resource.h +++ b/dlls/jscript/resource.h @@ -80,6 +80,7 @@ #define IDS_DATAVIEW_INVALID_OFFSET 0x13E2 #define IDS_WRONG_THIS 0x13FC #define IDS_KEY_NOT_OBJECT 0x13FD +#define IDS_ARRAYBUFFER_EXPECTED 0x15E4 /* FIXME: This is not compatible with native, but we would * conflict with IDS_UNSUPPORTED_ACTION otherwise */ #define IDS_PROP_DESC_MISMATCH 0x1F00 diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index a18fea6476a..353d0b0b5c0 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -37,6 +37,7 @@ var JS_E_DATAVIEW_NO_ARGUMENT = 0x800a13e0; var JS_E_DATAVIEW_INVALID_ACCESS = 0x800a13e1; var JS_E_DATAVIEW_INVALID_OFFSET = 0x800a13e2; var JS_E_WRONG_THIS = 0x800a13fc; +var JS_E_ARRAYBUFFER_EXPECTED = 0x800a15e4;
var tests = [];
@@ -1687,7 +1688,7 @@ sync_test("RegExp", function() { });
sync_test("ArrayBuffers & Views", function() { - var i, r, buf, view, view2, arr; + var i, r, buf, buf2, view, view2, arr;
var types = [ [ "Int8", 1 ], @@ -1732,6 +1733,20 @@ sync_test("ArrayBuffers & Views", function() { r = ArrayBuffer.prototype.slice.length; ok(r === 2, "ArrayBuffer.prototype.slice.length = " + r);
+ try { + ArrayBuffer.prototype.slice.call(null); + ok(false, "ArrayBuffer: calling slice with null context did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_ARRAYBUFFER_EXPECTED, "ArrayBuffer: calling slice with null context threw " + n); + } + try { + ArrayBuffer.prototype.slice.call({}); + ok(false, "ArrayBuffer: calling slice with an object context did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_ARRAYBUFFER_EXPECTED, "ArrayBuffer: calling slice with an object context threw " + n); + } try { new ArrayBuffer(-1); ok(false, "new ArrayBuffer(-1) did not throw exception"); @@ -1983,10 +1998,39 @@ sync_test("ArrayBuffers & Views", function() { r = view2.getFloat32(0, true); ok(r === 1234.5, "view2.getFloat32(0) returned " + r);
+ r = buf.slice(-9, 1); + ok(r instanceof ArrayBuffer, "buf.slice did not return an ArrayBuffer"); + ok(r.byteLength === 0, "buf.slice(-9, 1).byteLength = " + r.byteLength); + r = buf.slice(); + ok(r.byteLength === 10, "buf.slice().byteLength = " + r.byteLength); + r = buf.slice(9, 16); + ok(r.byteLength === 1, "buf.slice(9, 16).byteLength = " + r.byteLength); + r = buf.slice(-9, -1); + ok(r.byteLength === 8, "buf.slice(-9, -1).byteLength = " + r.byteLength); + /* setters differing only in signedness have identical behavior, but they're not the same methods */ ok(view.setInt8 !== view.setUint8, "setInt8 and setUint8 are the same method"); ok(view.setInt16 !== view.setUint16, "setInt16 and setUint16 are the same method"); ok(view.setInt32 !== view.setUint32, "setInt32 and setUint32 are the same method"); + + /* slice makes a copy */ + buf2 = buf.slice(-9); + ok(buf2.byteLength === 9, "buf.slice(-9).byteLength = " + buf2.byteLength); + view2 = DataView(buf2, 1); + ok(view2.byteLength === 8, "buf.slice(-9) view(1).byteLength = " + view2.byteLength); + + r = view2.getUint32(0); + ok(r === 4294967040, "buf.slice(-9) view(1).getUint32(0) returned " + r); + view2.setInt16(0, -5); + r = view2.getUint16(1); + ok(r === 64511, "buf.slice(-9) view(1).getUint16(1) returned " + r); + r = view.getInt32(1); + ok(r === -1, "view.getInt32(1) after slice changed returned " + r); + + r = view2.setFloat64(0, 11.875); + ok(r === undefined, "buf.slice(-9) view(1).setFloat64(0, 11.875) returned " + r); + r = view2.getFloat64(0); + ok(r === 11.875, "buf.slice(-9) view(1).getFloat64(0) returned " + r); });
sync_test("builtin_context", function() {