From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
fill_typedarr_data_from_object will also be used for 'set'. --- dlls/jscript/arraybuf.c | 66 ++++++++++++++++++++++++++++++++++++++-- dlls/mshtml/tests/es5.js | 47 +++++++++++++++++++++++++++- 2 files changed, 110 insertions(+), 3 deletions(-)
diff --git a/dlls/jscript/arraybuf.c b/dlls/jscript/arraybuf.c index a4d11e1763f..1478b4affef 100644 --- a/dlls/jscript/arraybuf.c +++ b/dlls/jscript/arraybuf.c @@ -18,6 +18,7 @@
#include <limits.h> +#include <assert.h>
#include "jscript.h"
@@ -791,6 +792,40 @@ static HRESULT TypedArray_get_length(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_ return S_OK; }
+static HRESULT fill_typedarr_data_from_object(script_ctx_t *ctx, BYTE *data, jsdisp_t *obj, DWORD length, jsclass_t jsclass) +{ + HRESULT hres = S_OK; + jsval_t val; + UINT32 i; + + switch(jsclass) { +#define X(NAME, JSCLASS, TYPE, CONVERT, NUM_TYPE) \ + case JSCLASS: \ + for(i = 0; i < length; i++) { \ + NUM_TYPE n; \ + \ + hres = jsdisp_get_idx(obj, i, &val); \ + if(FAILED(hres)) { \ + if(hres != DISP_E_UNKNOWNNAME) \ + break; \ + val = jsval_undefined(); \ + } \ + \ + hres = CONVERT(ctx, val, &n); \ + jsval_release(val); \ + if(FAILED(hres)) \ + break; \ + *(TYPE*)&data[i * sizeof(TYPE)] = n; \ + } \ + break; + TYPEDARRAY_LIST + DEFAULT_UNREACHABLE; +#undef X + } + + return hres; +} + static HRESULT TypedArray_set(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r, jsclass_t jsclass) { @@ -998,8 +1033,35 @@ static HRESULT TypedArrayConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD fla } jsdisp_addref(&buffer->dispex); }else { - FIXME("Construction from object not implemented\n"); - return E_NOTIMPL; + jsval_t val; + UINT32 len; + DWORD size; + + hres = jsdisp_propget_name(obj, L"length", &val); + if(FAILED(hres)) + return hres; + if(is_undefined(val)) + return JS_E_TYPEDARRAY_BAD_CTOR_ARG; + + hres = to_uint32(ctx, val, &len); + jsval_release(val); + if(FAILED(hres)) + return hres; + + length = len; + size = length * elem_size; + if(size < length || size > (UINT_MAX - FIELD_OFFSET(ArrayBufferInstance, buf[0]))) + return E_OUTOFMEMORY; + + hres = create_arraybuf(ctx, size, &buffer); + if(FAILED(hres)) + return hres; + + hres = fill_typedarr_data_from_object(ctx, buffer->buf, obj, length, jsclass); + if(FAILED(hres)) { + jsdisp_release(&buffer->dispex); + return hres; + } } }else if(is_number(argv[0])) { hres = to_integer(ctx, argv[0], &n); diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 63bc8e1700e..bc6acaee70e 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -2133,6 +2133,13 @@ sync_test("ArrayBuffers & Views", function() { var n = ex.number >>> 0; ok(n === JS_E_TYPEDARRAY_BAD_CTOR_ARG, "new " + arrType + "(null) threw " + n); } + try { + eval("new " + arrType + "({})"); + ok(false, "new " + arrType + "({}) did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_TYPEDARRAY_BAD_CTOR_ARG, "new " + arrType + "({}) threw " + n); + } if(typeSz > 1) { /* test misalignment */ var a = typeSz >>> 1; @@ -2250,6 +2257,23 @@ sync_test("ArrayBuffers & Views", function() { delete arr[-1]; delete arr.foo;
+ arr2 = { length: 4 }; + arr2[0] = 1.5; + arr2[1] = '3'; + arr2[3] = 12; + var name = arrType + "(array-like object)"; + arr = eval(arrType + "(arr2)"); + ok(arr.byteLength === 4 * typeSz, name + ".byteLength = " + arr.byteLength); + ok(arr.byteOffset === 0, name + ".byteOffset = " + arr.byteOffset); + ok(arr.length === 4, name + ".length = " + arr.length); + if(isNaN(arr[2])) { + ok(arr[0] === 1.5, name + "[0] = " + arr[0]); + ok(arr[1] === 3, name + "[1] = " + arr[1]); + ok(arr[3] === 12, name + "[3] = " + arr[3]); + }else + for(var j = 0; j < 4; j++) + ok(arr[j] === [1, 3, 0, 12][j], name + "[" + j + "] = " + arr[j]); + name = arrType + "(buf, " + typeSz + ", 2)"; arr = eval(name); ok(arr.byteLength === 2 * typeSz, name + ".byteLength = " + arr.byteLength); @@ -2264,7 +2288,28 @@ sync_test("ArrayBuffers & Views", function() { ok(r === 12, "DataView(buf).get" + types[i][0] + " after arr[0] set = " + r); Object.freeze(arr); ok(Object.isFrozen(arr) === true, name + " not frozen"); - } + + arr2 = eval(arrType + "(arr)"); + ok(arr2.byteLength === arr.byteLength, name + " copy.byteLength = " + arr2.byteLength); + ok(arr2.byteOffset === 0, name + " copy.byteOffset = " + arr2.byteOffset); + ok(arr2.length === arr.length, name + " copy.length = " + arr2.length); + ok(arr2.buffer !== arr.buffer, name + " copy.buffer = " + arr2.buffer); + } + + arr = new Float32Array(3); + arr[0] = 1.125; + arr[1] = 2.25; + arr[2] = 3.375; + arr2 = new Uint16Array(arr); + ok(arr[0] === 1.125, "arr[0] = " + arr[0]); + ok(arr[1] === 2.25, "arr[1] = " + arr[1]); + ok(arr[2] === 3.375, "arr[2] = " + arr[2]); + ok(arr2[0] === 1, "arr2[0] = " + arr2[0]); + ok(arr2[1] === 2, "arr2[1] = " + arr2[1]); + ok(arr2[2] === 3, "arr2[2] = " + arr2[2]); + arr2[0] = 100; + ok(arr[0] === 1.125, "arr[0] after arr2[0] changed = " + arr[0]); + ok(arr2[0] === 100, "arr2[0] after change = " + arr2[0]);
arr = new Int16Array(2); arr[0] = 65535;