From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/arraybuf.c | 273 ++++++++++++++++++++++++++++-- dlls/jscript/error.c | 3 + dlls/jscript/jscript.h | 4 + dlls/jscript/jscript.rc | 3 + dlls/jscript/jsutils.c | 2 +- dlls/jscript/resource.h | 3 + dlls/mshtml/tests/documentmode.js | 2 +- dlls/mshtml/tests/es5.js | 172 ++++++++++++++++++- 8 files changed, 445 insertions(+), 17 deletions(-)
diff --git a/dlls/jscript/arraybuf.c b/dlls/jscript/arraybuf.c index 82df57243eb..847cabe92b6 100644 --- a/dlls/jscript/arraybuf.c +++ b/dlls/jscript/arraybuf.c @@ -39,6 +39,14 @@ typedef struct { DWORD size; } DataViewInstance;
+typedef struct { + jsdisp_t dispex; + + ArrayBufferInstance *buffer; + DWORD offset; + DWORD length; +} TypedArrayInstance; + static inline ArrayBufferInstance *arraybuf_from_jsdisp(jsdisp_t *jsdisp) { return CONTAINING_RECORD(jsdisp, ArrayBufferInstance, dispex); @@ -49,6 +57,11 @@ static inline DataViewInstance *dataview_from_jsdisp(jsdisp_t *jsdisp) return CONTAINING_RECORD(jsdisp, DataViewInstance, dispex); }
+static inline TypedArrayInstance *typedarr_from_jsdisp(jsdisp_t *jsdisp) +{ + return CONTAINING_RECORD(jsdisp, TypedArrayInstance, dispex); +} + static inline ArrayBufferInstance *arraybuf_this(jsval_t vthis) { jsdisp_t *jsdisp = is_object_instance(vthis) ? to_jsdisp(get_object(vthis)) : NULL; @@ -701,28 +714,213 @@ ALL_TYPED_ARRAYS #undef X };
+struct typed_array_desc { + unsigned size; + double (*get)(const void*); + void (*set)(void*,double); +}; + +static double get_s8(const void *p) { return *(const INT8 *)p; } +static double get_u8(const void *p) { return *(const UINT8 *)p; } +static void set_u8(void *p, double v) { *(UINT8 *)p = double_to_int32(v); } +static double get_s16(const void *p) { return *(const INT16 *)p; } +static double get_u16(const void *p) { return *(const UINT16 *)p; } +static void set_u16(void *p, double v) { *(UINT16 *)p = double_to_int32(v); } +static double get_s32(const void *p) { return *(const INT32 *)p; } +static double get_u32(const void *p) { return *(const UINT32 *)p; } +static void set_u32(void *p, double v) { *(UINT32 *)p = double_to_int32(v); } +static double get_f32(const void *p) { return *(const float *)p; } +static void set_f32(void *p, double v) { *(float *)p = v; } +static double get_f64(const void *p) { return *(const double *)p; } +static void set_f64(void *p, double v) { *(double *)p = v; } + +static const struct typed_array_desc typed_array_descs[NUM_TYPEDARRAY_TYPES] = { + [Int8Array_desc_idx] = { 1, get_s8, set_u8 }, + [Int16Array_desc_idx] = { 2, get_s16, set_u16 }, + [Int32Array_desc_idx] = { 4, get_s32, set_u32 }, + [Uint8Array_desc_idx] = { 1, get_u8, set_u8 }, + [Uint16Array_desc_idx] = { 2, get_u16, set_u16 }, + [Uint32Array_desc_idx] = { 4, get_u32, set_u32 }, + [Float32Array_desc_idx] = { 4, get_f32, set_f32 }, + [Float64Array_desc_idx] = { 8, get_f64, set_f64 } +}; + static HRESULT TypedArray_get_buffer(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) { - FIXME("%p\n", jsthis); - return E_NOTIMPL; + TRACE("%p\n", jsthis); + + *r = jsval_obj(jsdisp_addref(&typedarr_from_jsdisp(jsthis)->buffer->dispex)); + return S_OK; }
static HRESULT TypedArray_get_byteLength(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) { - FIXME("%p\n", jsthis); - return E_NOTIMPL; + TRACE("%p\n", jsthis); + + *r = jsval_number(typedarr_from_jsdisp(jsthis)->length * typed_array_descs[jsthis->builtin_info->class - FIRST_TYPEDARRAY_JSCLASS].size); + return S_OK; }
static HRESULT TypedArray_get_byteOffset(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) { - FIXME("%p\n", jsthis); - return E_NOTIMPL; + TRACE("%p\n", jsthis); + + *r = jsval_number(typedarr_from_jsdisp(jsthis)->offset); + return S_OK; }
static HRESULT TypedArray_get_length(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) { - FIXME("%p\n", jsthis); - return E_NOTIMPL; + TRACE("%p\n", jsthis); + + *r = jsval_number(typedarr_from_jsdisp(jsthis)->length); + return S_OK; +} + +static void TypedArray_destructor(jsdisp_t *dispex) +{ + TypedArrayInstance *typedarr = typedarr_from_jsdisp(dispex); + if(typedarr->buffer) + jsdisp_release(&typedarr->buffer->dispex); +} + +static HRESULT TypedArray_lookup_prop(jsdisp_t *dispex, const WCHAR *name, unsigned flags, struct property_info *desc) +{ + TypedArrayInstance *typedarr = typedarr_from_jsdisp(dispex); + + /* Typed Arrays override every positive index */ + return jsdisp_index_lookup(&typedarr->dispex, name, INT_MAX, desc); +} + +static inline HRESULT TypedArray_prop_get(unsigned desc_idx, jsdisp_t *dispex, unsigned idx, jsval_t *r) +{ + TypedArrayInstance *typedarr = typedarr_from_jsdisp(dispex); + + if(idx >= typedarr->length) + *r = jsval_undefined(); + else + *r = jsval_number(typed_array_descs[desc_idx].get(&typedarr->buffer->buf[typedarr->offset + idx * typed_array_descs[desc_idx].size])); + return S_OK; +} + +static inline HRESULT TypedArray_prop_put(unsigned desc_idx, jsdisp_t *dispex, unsigned idx, jsval_t val) +{ + TypedArrayInstance *typedarr = typedarr_from_jsdisp(dispex); + HRESULT hres; + double n; + + if(idx >= typedarr->length) + return S_OK; + + hres = to_number(typedarr->dispex.ctx, val, &n); + if(SUCCEEDED(hres)) + typed_array_descs[desc_idx].set(&typedarr->buffer->buf[typedarr->offset + idx * typed_array_descs[desc_idx].size], n); + return hres; +} + +static HRESULT TypedArray_fill_props(jsdisp_t *dispex) +{ + TypedArrayInstance *typedarr = typedarr_from_jsdisp(dispex); + + return jsdisp_fill_indices(&typedarr->dispex, typedarr->length); +} + +static HRESULT TypedArray_gc_traverse(struct gc_ctx *gc_ctx, enum gc_traverse_op op, jsdisp_t *dispex) +{ + TypedArrayInstance *typedarr = typedarr_from_jsdisp(dispex); + return typedarr->buffer ? gc_process_linked_obj(gc_ctx, op, dispex, &typedarr->buffer->dispex, (void**)&typedarr->buffer) : S_OK; +} + +static const builtin_prop_t TypedArrayInst_props[] = { + {L"buffer", NULL, 0, TypedArray_get_buffer}, + {L"byteLength", NULL, 0, TypedArray_get_byteLength}, + {L"byteOffset", NULL, 0, TypedArray_get_byteOffset}, + {L"length", NULL, 0, TypedArray_get_length}, +}; + +static HRESULT create_typedarr(const builtin_info_t *info, script_ctx_t *ctx, ArrayBufferInstance *buffer, + DWORD offset, DWORD length, jsdisp_t **ret) +{ + TypedArrayInstance *typedarr; + HRESULT hres; + + if(!(typedarr = calloc(1, sizeof(TypedArrayInstance)))) + return E_OUTOFMEMORY; + + hres = init_dispex_from_constr(&typedarr->dispex, ctx, info, ctx->typedarr_constr[info->class - FIRST_TYPEDARRAY_JSCLASS]); + if(FAILED(hres)) { + free(typedarr); + return hres; + } + + jsdisp_addref(&buffer->dispex); + typedarr->buffer = buffer; + typedarr->offset = offset; + typedarr->length = length; + + *ret = &typedarr->dispex; + return S_OK; +} + +static HRESULT TypedArrayConstr_value(const builtin_info_t *info, script_ctx_t *ctx, jsval_t vthis, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r) +{ + const unsigned desc_idx = info->class - FIRST_TYPEDARRAY_JSCLASS; + const unsigned elem_size = typed_array_descs[desc_idx].size; + ArrayBufferInstance *buffer = NULL; + DWORD offset = 0, length = 0; + jsdisp_t *typedarr; + HRESULT hres; + double n; + + switch(flags) { + case DISPATCH_METHOD: + case DISPATCH_CONSTRUCT: { + if(argc) { + if(is_object_instance(argv[0])) { + jsdisp_t *obj = to_jsdisp(get_object(argv[0])); + + if(!obj) + return JS_E_TYPEDARRAY_BAD_CTOR_ARG; + + FIXME("Construction from object not implemented\n"); + return E_NOTIMPL; + }else if(is_number(argv[0])) { + hres = to_integer(ctx, argv[0], &n); + if(FAILED(hres)) + return hres; + if(n < 0.0) + return JS_E_TYPEDARRAY_INVALID_OFFSLEN; + if(n * elem_size > (UINT_MAX - FIELD_OFFSET(ArrayBufferInstance, buf[0]))) + return E_OUTOFMEMORY; + length = n; + }else + return JS_E_TYPEDARRAY_BAD_CTOR_ARG; + } + + if(!r) + return S_OK; + + if(!buffer) { + hres = create_arraybuf(ctx, length * elem_size, &buffer); + if(FAILED(hres)) + return hres; + } + + hres = create_typedarr(info, ctx, buffer, offset, length, &typedarr); + jsdisp_release(&buffer->dispex); + if(FAILED(hres)) + return hres; + + *r = jsval_obj(typedarr); + break; + } + default: + FIXME("unimplemented flags: %x\n", flags); + return E_NOTIMPL; + } + + return S_OK; }
#define X(name) \ @@ -738,6 +936,18 @@ static HRESULT name##_subarray(script_ctx_t *ctx, jsval_t vthis, WORD flags, uns return E_NOTIMPL; \ } \ \ +static HRESULT name##_prop_get(jsdisp_t *dispex, unsigned idx, jsval_t *r) \ +{ \ + TRACE("%p[%u]\n", dispex, idx); \ + return TypedArray_prop_get(name##_desc_idx, dispex, idx, r); \ +} \ + \ +static HRESULT name##_prop_put(jsdisp_t *dispex, unsigned idx, jsval_t val) \ +{ \ + TRACE("%p[%u] = %s\n", dispex, idx, debugstr_jsval(val)); \ + return TypedArray_prop_put(name##_desc_idx, dispex, idx, val); \ +} \ + \ static const builtin_prop_t name##_props[] = { \ {L"buffer", NULL, 0, TypedArray_get_buffer}, \ {L"byteLength", NULL, 0, TypedArray_get_byteLength}, \ @@ -752,12 +962,30 @@ static const builtin_info_t name##_info = .class = FIRST_TYPEDARRAY_JSCLASS + name ##_desc_idx, \ .props_cnt = ARRAY_SIZE(name##_props), \ .props = name##_props, \ + .destructor = TypedArray_destructor, \ + .lookup_prop = TypedArray_lookup_prop, \ + .prop_get = name##_prop_get, \ + .prop_put = name##_prop_put, \ + .fill_props = TypedArray_fill_props, \ + .gc_traverse = TypedArray_gc_traverse, \ }; \ \ +static const builtin_info_t name##Inst_info = \ +{ \ + .class = FIRST_TYPEDARRAY_JSCLASS + name##_desc_idx, \ + .props_cnt = ARRAY_SIZE(TypedArrayInst_props), \ + .props = TypedArrayInst_props, \ + .destructor = TypedArray_destructor, \ + .lookup_prop = TypedArray_lookup_prop, \ + .prop_get = name##_prop_get, \ + .prop_put = name##_prop_put, \ + .fill_props = TypedArray_fill_props, \ + .gc_traverse = TypedArray_gc_traverse, \ +}; \ static HRESULT name ## Constr_value(script_ctx_t *ctx, jsval_t jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) \ { \ - FIXME("\n"); \ - return E_NOTIMPL; \ + TRACE("\n"); \ + return TypedArrayConstr_value(&name##Inst_info, ctx, jsthis, flags, argc, argv, r); \ } ALL_TYPED_ARRAYS #undef X @@ -770,15 +998,32 @@ static const builtin_info_t TypedArrayConstr_info = { static HRESULT init_typed_array_constructor(script_ctx_t *ctx, builtin_invoke_t func, const WCHAR *name, const builtin_info_t *info, unsigned int type_idx) { - jsdisp_t *prototype; + TypedArrayInstance *prototype; HRESULT hres;
- hres = create_dispex(ctx, info, ctx->object_prototype, &prototype); + if(!(prototype = calloc(1, sizeof(*prototype)))) + return E_OUTOFMEMORY; + + hres = create_arraybuf(ctx, 0, &prototype->buffer); + if(FAILED(hres)) { + free(prototype); + return hres; + } + + hres = init_dispex(&prototype->dispex, ctx, info, ctx->object_prototype); + if(FAILED(hres)) { + jsdisp_release(&prototype->buffer->dispex); + free(prototype); + return hres; + } + + hres = create_builtin_constructor(ctx, func, name, &TypedArrayConstr_info, PROPF_CONSTR|1, &prototype->dispex, &ctx->typedarr_constr[type_idx]); + jsdisp_release(&prototype->dispex); if(FAILED(hres)) return hres;
- hres = create_builtin_constructor(ctx, func, name, &TypedArrayConstr_info, PROPF_CONSTR|1, prototype, &ctx->typedarr_constr[type_idx]); - jsdisp_release(prototype); + hres = jsdisp_define_data_property(ctx->typedarr_constr[type_idx], L"BYTES_PER_ELEMENT", 0, + jsval_number(typed_array_descs[type_idx].size)); if(FAILED(hres)) return hres;
diff --git a/dlls/jscript/error.c b/dlls/jscript/error.c index 9f22b7feefa..48e9826040c 100644 --- a/dlls/jscript/error.c +++ b/dlls/jscript/error.c @@ -497,6 +497,8 @@ jsdisp_t *create_builtin_error(script_ctx_t *ctx) case JS_E_OBJECT_NONEXTENSIBLE: case JS_E_NONCONFIGURABLE_REDEFINED: case JS_E_NONWRITABLE_MODIFIED: + case JS_E_TYPEDARRAY_BAD_CTOR_ARG: + case JS_E_NOT_TYPEDARRAY: case JS_E_NOT_DATAVIEW: case JS_E_DATAVIEW_NO_ARGUMENT: case JS_E_WRONG_THIS: @@ -511,6 +513,7 @@ jsdisp_t *create_builtin_error(script_ctx_t *ctx) case JS_E_FRACTION_DIGITS_OUT_OF_RANGE: case JS_E_PRECISION_OUT_OF_RANGE: case JS_E_INVALID_LENGTH: + case JS_E_TYPEDARRAY_INVALID_OFFSLEN: case JS_E_DATAVIEW_INVALID_ACCESS: case JS_E_DATAVIEW_INVALID_OFFSET: constr = ctx->range_error_constr; diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 5a8910565b3..db0f2e3d6a7 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -320,6 +320,7 @@ HRESULT to_uint32(script_ctx_t*,jsval_t,UINT32*); HRESULT to_string(script_ctx_t*,jsval_t,jsstr_t**); HRESULT to_flat_string(script_ctx_t*,jsval_t,jsstr_t**,const WCHAR**); HRESULT to_object(script_ctx_t*,jsval_t,IDispatch**); +INT32 double_to_int32(double);
HRESULT jsval_strict_equal(jsval_t,jsval_t,BOOL*);
@@ -578,6 +579,9 @@ static inline HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, jsval_ #define JS_E_OBJECT_NONEXTENSIBLE MAKE_JSERROR(IDS_OBJECT_NONEXTENSIBLE) #define JS_E_NONCONFIGURABLE_REDEFINED MAKE_JSERROR(IDS_NONCONFIGURABLE_REDEFINED) #define JS_E_NONWRITABLE_MODIFIED MAKE_JSERROR(IDS_NONWRITABLE_MODIFIED) +#define JS_E_TYPEDARRAY_BAD_CTOR_ARG MAKE_JSERROR(IDS_TYPEDARRAY_BAD_CTOR_ARG) +#define JS_E_NOT_TYPEDARRAY MAKE_JSERROR(IDS_NOT_TYPEDARRAY) +#define JS_E_TYPEDARRAY_INVALID_OFFSLEN MAKE_JSERROR(IDS_TYPEDARRAY_INVALID_OFFSLEN) #define JS_E_NOT_DATAVIEW MAKE_JSERROR(IDS_NOT_DATAVIEW) #define JS_E_DATAVIEW_NO_ARGUMENT MAKE_JSERROR(IDS_DATAVIEW_NO_ARGUMENT) #define JS_E_DATAVIEW_INVALID_ACCESS MAKE_JSERROR(IDS_DATAVIEW_INVALID_ACCESS) diff --git a/dlls/jscript/jscript.rc b/dlls/jscript/jscript.rc index 189f6fe19a3..91bbf09d034 100644 --- a/dlls/jscript/jscript.rc +++ b/dlls/jscript/jscript.rc @@ -79,6 +79,9 @@ STRINGTABLE IDS_OBJECT_NONEXTENSIBLE "Cannot define property '|': object is not extensible" IDS_NONCONFIGURABLE_REDEFINED "Cannot redefine non-configurable property '|'" IDS_NONWRITABLE_MODIFIED "Cannot modify non-writable property '|'" + IDS_NOT_TYPEDARRAY "'this' is not a typed array object" + IDS_TYPEDARRAY_BAD_CTOR_ARG "Typed array constructor argument is invalid" + IDS_TYPEDARRAY_INVALID_OFFSLEN "Invalid offset/length when creating typed array" IDS_NOT_DATAVIEW "'this' is not a DataView object" IDS_DATAVIEW_NO_ARGUMENT "Required argument offset or value in DataView method is not specified" IDS_DATAVIEW_INVALID_ACCESS "DataView operation access beyond specified buffer length" diff --git a/dlls/jscript/jsutils.c b/dlls/jscript/jsutils.c index 1d6fa06a993..190c97d08ec 100644 --- a/dlls/jscript/jsutils.c +++ b/dlls/jscript/jsutils.c @@ -676,7 +676,7 @@ HRESULT to_integer(script_ctx_t *ctx, jsval_t v, double *ret) return S_OK; }
-static INT32 double_to_int32(double number) +INT32 double_to_int32(double number) { INT32 exp, result; union { diff --git a/dlls/jscript/resource.h b/dlls/jscript/resource.h index 7b37a7ae8ea..0f8e6f2dc7f 100644 --- a/dlls/jscript/resource.h +++ b/dlls/jscript/resource.h @@ -77,6 +77,9 @@ #define IDS_OBJECT_NONEXTENSIBLE 0x13D5 #define IDS_NONCONFIGURABLE_REDEFINED 0x13D6 #define IDS_NONWRITABLE_MODIFIED 0x13D7 +#define IDS_TYPEDARRAY_BAD_CTOR_ARG 0x13DA +#define IDS_NOT_TYPEDARRAY 0x13DB +#define IDS_TYPEDARRAY_INVALID_OFFSLEN 0x13DC #define IDS_NOT_DATAVIEW 0x13DF #define IDS_DATAVIEW_NO_ARGUMENT 0x13E0 #define IDS_DATAVIEW_INVALID_ACCESS 0x13E1 diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index be141928453..dcd8fa77663 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -4566,7 +4566,7 @@ sync_test("typed arrays", function() { "unexpected " + constr + " porototype's prototype " + Object.getPrototypeOf(constr.prototype)); test_own_props(constr, constr, ["BYTES_PER_ELEMENT", "arguments", "caller", "length", "prototype"], - ["BYTES_PER_ELEMENT", "arguments", "caller"]); + ["arguments", "caller"]); test_own_props(constr.prototype, constr + ".prototype", ["BYTES_PER_ELEMENT", "buffer", "byteLength", "byteOffset", "constructor", "length", "set", "subarray"], ["BYTES_PER_ELEMENT"]); diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index ef2c80a2c07..c929eaae0fa 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -33,6 +33,9 @@ var JS_E_INVALID_LENGTH = 0x800a13a5; var JS_E_INVALID_WRITABLE_PROP_DESC = 0x800a13ac; var JS_E_NONCONFIGURABLE_REDEFINED = 0x800a13d6; var JS_E_NONWRITABLE_MODIFIED = 0x800a13d7; +var JS_E_TYPEDARRAY_BAD_CTOR_ARG = 0x800a13da; +var JS_E_NOT_TYPEDARRAY = 0x800a13db; +var JS_E_TYPEDARRAY_INVALID_OFFSLEN = 0x800a13dc; var JS_E_NOT_DATAVIEW = 0x800a13df; var JS_E_DATAVIEW_NO_ARGUMENT = 0x800a13e0; var JS_E_DATAVIEW_INVALID_ACCESS = 0x800a13e1; @@ -1747,7 +1750,7 @@ sync_test("RegExp", function() { });
sync_test("ArrayBuffers & Views", function() { - var i, r, buf, buf2, view, view2, arr; + var i, r, buf, buf2, view, view2, arr, arr2;
var types = [ [ "Int8", 1 ], @@ -2090,6 +2093,173 @@ sync_test("ArrayBuffers & Views", function() { 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); + + for(i = 0; i < types.length; i++) { + var name = types[i][0] + "Array", arrType = window[name], typeSz = types[i][1]; + + arr = arrType; + test_own_data_prop_desc(arr, "BYTES_PER_ELEMENT", false, false, false); + ok(arr.BYTES_PER_ELEMENT === typeSz, name + ".BYTES_PER_ELEMENT = " + arr.BYTES_PER_ELEMENT); + r = arr.length; + ok(r === 1, name + ".length = " + r); + r = arr.prototype.set.length; + ok(r === 2, name + ".prototype.set.length = " + r); + r = arr.prototype.subarray.length; + ok(r === 2, name + ".prototype.subarray.length = " + r); + + r = Object.getPrototypeOf(arrType); + ok(r === Function.prototype, name + "'s prototype is not Function.prototype: " + r); + r = Object.getPrototypeOf(arrType.prototype); + ok(r === Object.prototype, name + ".prototype's prototype is not Object.prototype: " + r); + r = Object.prototype.toString.call(new arrType(3)); + ok(r === "[object " + name + "]", "Object toString(new " + name + "(3)) = " + r); + r = arrType.prototype; + test_own_data_prop_desc(r, "byteLength", false, false, false); + test_own_data_prop_desc(r, "byteOffset", false, false, false); + test_own_data_prop_desc(r, "length", false, false, false); + test_own_data_prop_desc(r, "buffer", false, false, false); + + try { + new arrType(-1); + ok(false, "new " + name + "(-1) did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_TYPEDARRAY_INVALID_OFFSLEN, "new " + name + "(-1) threw " + n); + } + try { + new arrType('9'); + ok(false, "new " + name + "('9') did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_TYPEDARRAY_BAD_CTOR_ARG, "new " + name + "('9') threw " + n); + } + try { + new arrType(null); + ok(false, "new " + name + "(null) did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_TYPEDARRAY_BAD_CTOR_ARG, "new " + name + "(null) threw " + n); + } + + arr = new arrType(); + ok(arr.byteLength === 0, name + "().byteLength = " + arr.byteLength); + ok(arr.byteOffset === 0, name + "().byteOffset = " + arr.byteOffset); + ok(arr.length === 0, name + "().length = " + arr.length); + ok(arr.buffer.byteLength === 0, name + "().buffer.byteLength = " + arr.buffer.byteLength); + test_readonly(arr, "byteLength", 0); + test_readonly(arr, "byteOffset", 0); + test_readonly(arr, "length", 0); + test_own_data_prop_desc(arr, "byteLength", false, false, false); + test_own_data_prop_desc(arr, "byteOffset", false, false, false); + test_own_data_prop_desc(arr, "length", false, false, false); + test_own_data_prop_desc(arr, "buffer", false, false, false); + + Object.freeze(arr); + ok(Object.isFrozen(arr) === true, name + "() not frozen"); + + arr = arrType(9.1); + ok(arr.byteLength === 9 * typeSz, name + "(9.1).byteLength = " + arr.byteLength); + ok(arr.byteOffset === 0, name + "(9.1).byteOffset = " + arr.byteOffset); + ok(arr.length === 9, name + "(9.1).length = " + arr.length); + ok(arr.buffer.byteLength === arr.byteLength, name + "(9.1).buffer.byteLength = " + arr.buffer.byteLength); + for(var j = 0; j < 9; j++) + ok(arr[j] === 0, "arr[" + j + "] = " + arr[j]); + arr[5] = 42; + ok(arr[5] === 42, name + "(9.1)[5] = " + arr[5]); + arr[9] = 50; + ok(arr[9] === undefined, name + "(9.1)[9] = " + arr[9]); + + arrType.prototype[6] = "foo"; + r = arrType.prototype[6]; + ok(r === undefined, name + ".prototype[6] = " + r); + ok(arr[6] === 0, name + "(9.1)[6] after set in prototype = " + arr[6]); + arr[6] = 0; + ok(arr.hasOwnProperty("6"), "'6' not a property of " + name + "(9.1)[6]"); + test_own_data_prop_desc(arr, "6", true, true, false); + r = (delete arr[6]); + ok(r === false, "delete " + name + "(9.1)[6] returned " + r); + try { + Object.defineProperty(arr, "6", {writable: false, enumerable: false, configurable: true, value: 10}); + ok(false, "redefining " + name + "(9.1)[6] with different flags did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_NONCONFIGURABLE_REDEFINED, "redefining " + name + "(9.1)[6] with different flags threw " + n); + } + Object.defineProperty(arr, "6", {writable: true, enumerable: true, configurable: false, value: 10}); + ok(arr[6] === 10, name + "(9.1)[6] after definition = " + arr[6]); + Object.defineProperty(arr, "6", {writable: true, enumerable: true, configurable: false, value: "foo"}); + if(name.substr(0, 5) === "Float") + todo_wine. + ok(arr[6] !== arr[6] /* NaN */, name + "(9.1)[6] after definition to string = " + arr[6]); + else + todo_wine. + ok(arr[6] === 0, name + "(9.1)[6] after definition to string = " + arr[6]); + + arrType.prototype[100] = "foobar"; + r = arrType.prototype[100]; + ok(r === undefined, name + ".prototype[100] = " + r); + ok(arr[100] === undefined, name + "(9.1)[100] after set in prototype = " + arr[100]); + arr[100] = 0; + ok(arr[100] === undefined, name + "(9.1)[100] after set to zero = " + arr[100]); + todo_wine. + ok(!arr.hasOwnProperty("100"), "'100' is a property of " + name + "(9.1)[100]"); + r = (delete arr[100]); + ok(r === false, "delete " + name + "(9.1)[100] returned " + r); + try { + Object.defineProperty(arr, "100", {writable: false, enumerable: false, configurable: true, value: 10}); + ok(false, "redefining " + name + "(9.1)[100] with different flags did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_NONCONFIGURABLE_REDEFINED, "redefining " + name + "(9.1)[100] with different flags threw " + n); + } + Object.defineProperty(arr, "100", {writable: true, enumerable: true, configurable: false, value: 10}); + todo_wine. + ok(arr[100] === undefined, name + "(9.1)[100] after defined to 10 = " + arr[100]); + todo_wine. + ok(!arr.hasOwnProperty("100"), "'100' is a property of " + name + "(9.1)[100] after definition"); + todo_wine. + ok(arr[100] === undefined, name + "(9.1)[100] after definition = " + arr[100]); + + r = 0; + for(var idx in arr) { + todo_wine_if(r == 10). + ok(idx === ""+r, name + "(9.1) enum idx " + r + " = " + idx); + r++; + } + todo_wine. + ok(r === 9, name + "(9.1) enum did " + r + " iterations"); + + arrType.prototype[-1] = "barfoo"; + r = arrType.prototype[-1]; + ok(r === "barfoo", name + ".prototype[-1] = " + r); + ok(arr[-1] === "barfoo", name + "(9.1)[-1] after set in prototype = " + arr[-1]); + + arrType.prototype.foo = "bar"; + r = arrType.prototype.foo; + ok(r === "bar", name + ".prototype.foo = " + r); + ok(arr.foo === "bar", name + "(9.1).foo after set in prototype = " + arr.foo); + Object.freeze(arr); + todo_wine. + ok(Object.isFrozen(arr) === true, name + "(9.1) not frozen"); + arr = arrType.prototype; + delete arr[-1]; + delete arr.foo; + } + + arr = new Int16Array(2); + arr[0] = 65535; + arr[1] = -65535; + ok(arr[0] == -1, "16-bit arr[0] after overflow = " + arr[0]); + ok(arr[1] == 1, "16-bit arr[1] after overflow = " + arr[1]); + + arr = new Uint8Array(2); + arr[0] = -2; + arr[1] = 258; + ok(arr[0] == 254, "8-bit arr[0] after overflow = " + arr[0]); + ok(arr[1] == 2, "8-bit arr[1] after overflow = " + arr[1]); + + arr = new Int8Array(); + arr2 = new Int32Array(); });
sync_test("builtin_context", function() {