-- v2: jscript: Implement Uint8ClampedArray. jscript: Implement 'set' for Typed Arrays. jscript: Implement 'subarray' for Typed Arrays. jscript: Implement Typed Array construction from objects. jscript: Implement ArrayBuffer.isView. jscript: Implement Typed Array construction on ArrayBuffers. jscript: Add initial implementation of Typed Arrays. jscript: Simplify get_flags to only check whether it's enumerable.
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
It's the only thing it was used for anyway. --- dlls/jscript/dispex.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index c5e1fb7e8a9..897df1a0773 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -108,7 +108,7 @@ static inline BOOL is_function_prop(dispex_prop_t *prop) return ret; }
-static DWORD get_flags(jsdisp_t *This, dispex_prop_t *prop) +static BOOL is_enumerable(jsdisp_t *This, dispex_prop_t *prop) { if(prop->type == PROP_PROTREF) { dispex_prop_t *parent = NULL; @@ -118,13 +118,13 @@ static DWORD get_flags(jsdisp_t *This, dispex_prop_t *prop)
if(!parent || parent->type == PROP_DELETED) { prop->type = PROP_DELETED; - return 0; + return FALSE; }
- return get_flags(This->prototype, parent); + return is_enumerable(This->prototype, parent); }
- return prop->flags; + return !!(prop->flags & PROPF_ENUMERABLE); }
static const builtin_prop_t *find_builtin_prop(jsdisp_t *This, const WCHAR *name, BOOL case_insens) @@ -3170,7 +3170,7 @@ HRESULT jsdisp_next_prop(jsdisp_t *obj, DISPID id, enum jsdisp_enum_type enum_ty continue; if(enum_type != JSDISP_ENUM_ALL && iter->type == PROP_PROTREF) continue; - if(enum_type != JSDISP_ENUM_OWN && !(get_flags(obj, iter) & PROPF_ENUMERABLE)) + if(enum_type != JSDISP_ENUM_OWN && !is_enumerable(obj, iter)) continue; *ret = prop_to_id(obj, iter); return S_OK;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/arraybuf.c | 397 ++++++++++++++++++++++++++++++ dlls/jscript/error.c | 3 + dlls/jscript/jscript.h | 20 +- dlls/jscript/jscript.rc | 3 + dlls/jscript/jsutils.c | 2 +- dlls/jscript/object.c | 8 + dlls/jscript/resource.h | 3 + dlls/mshtml/tests/documentmode.js | 8 +- dlls/mshtml/tests/es5.js | 206 +++++++++++++++- 9 files changed, 643 insertions(+), 7 deletions(-)
diff --git a/dlls/jscript/arraybuf.c b/dlls/jscript/arraybuf.c index fc01773338f..bd530ec9cfd 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; @@ -684,6 +697,353 @@ static const builtin_info_t DataViewConstr_info = { .call = Function_value, };
+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 void set_s8(void *p, double v) { *(INT8 *)p = double_to_int32(v); } +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 void set_s16(void *p, double v) { *(INT16 *)p = double_to_int32(v); } +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 void set_s32(void *p, double v) { *(INT32 *)p = double_to_int32(v); } +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; } + +/* NOTE: Keep in sync with the JSCLASS ordering of typed arrays */ +#define ALL_TYPED_ARRAYS \ +X(Int8Array) \ +X(Int16Array) \ +X(Int32Array) \ +X(Uint8Array) \ +X(Uint16Array) \ +X(Uint32Array) \ +X(Float32Array) \ +X(Float64Array) + +enum { +#define X(NAME) NAME ##_desc_idx, +ALL_TYPED_ARRAYS +#undef X +}; + +static const struct typed_array_desc typed_array_descs[NUM_TYPEDARRAY_TYPES] = { + [Int8Array_desc_idx] = { 1, get_s8, set_s8 }, + [Int16Array_desc_idx] = { 2, get_s16, set_s16 }, + [Int32Array_desc_idx] = { 4, get_s32, set_s32 }, + [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 inline TypedArrayInstance *typedarr_this(jsval_t vthis, unsigned desc_idx) +{ + jsdisp_t *jsdisp = is_object_instance(vthis) ? to_jsdisp(get_object(vthis)) : NULL; + return (jsdisp && is_class(jsdisp, FIRST_TYPEDARRAY_JSCLASS + desc_idx)) ? typedarr_from_jsdisp(jsdisp) : NULL; +} + +static HRESULT TypedArray_get_buffer(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) +{ + 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) +{ + 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) +{ + 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) +{ + TRACE("%p\n", jsthis); + + *r = jsval_number(typedarr_from_jsdisp(jsthis)->length); + return S_OK; +} + +static HRESULT TypedArray_set(unsigned desc_idx, script_ctx_t *ctx, jsval_t vthis, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r) +{ + TypedArrayInstance *typedarr; + + FIXME("not implemented\n"); + + if(!(typedarr = typedarr_this(vthis, desc_idx))) + return JS_E_NOT_TYPEDARRAY; + return E_NOTIMPL; +} + +static HRESULT TypedArray_subarray(unsigned desc_idx, script_ctx_t *ctx, jsval_t vthis, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r) +{ + TypedArrayInstance *typedarr; + + FIXME("not implemented\n"); + + if(!(typedarr = typedarr_this(vthis, desc_idx))) + return JS_E_NOT_TYPEDARRAY; + return E_NOTIMPL; +} + +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); + + TRACE("%p[%u]\n", typedarr, idx); + + 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; + + TRACE("%p[%u] = %s\n", typedarr, idx, debugstr_jsval(val)); + + 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 gc_process_linked_obj(gc_ctx, op, dispex, &typedarr->buffer->dispex, (void**)&typedarr->buffer); +} + +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}, +}; + +#define X(NAME) \ +static HRESULT NAME ##_set(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) \ +{ \ + return TypedArray_set(NAME ##_desc_idx, ctx, vthis, flags, argc, argv, r); \ +} \ + \ +static HRESULT NAME ##_subarray(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) \ +{ \ + return TypedArray_subarray(NAME ##_desc_idx, ctx, vthis, flags, argc, argv, r); \ +} \ + \ +static HRESULT NAME ##_prop_get(jsdisp_t *dispex, unsigned idx, jsval_t *r) \ +{ \ + return TypedArray_prop_get(NAME ##_desc_idx, dispex, idx, r); \ +} \ + \ +static HRESULT NAME ##_prop_put(jsdisp_t *dispex, unsigned idx, jsval_t 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}, \ + {L"byteOffset", NULL, 0, TypedArray_get_byteOffset}, \ + {L"length", NULL, 0, TypedArray_get_length}, \ + {L"set", NAME ##_set, PROPF_METHOD|2}, \ + {L"subarray", NAME ##_subarray, PROPF_METHOD|2}, \ +}; +ALL_TYPED_ARRAYS +#undef X + +#define X(NAME) \ +{ \ + .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 TypedArray_info[] = { ALL_TYPED_ARRAYS }; +#undef X + +#define X(NAME) \ +{ \ + .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 const builtin_info_t TypedArrayInst_info[] = { ALL_TYPED_ARRAYS }; +#undef X + +static HRESULT create_typedarr(unsigned desc_idx, 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, &TypedArrayInst_info[desc_idx], ctx->typedarr_constr[desc_idx]); + 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(unsigned desc_idx, script_ctx_t *ctx, jsval_t vthis, WORD flags, + unsigned argc, jsval_t *argv, jsval_t *r) +{ + 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; + + TRACE("\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(desc_idx, 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) \ +static HRESULT NAME ## Constr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) \ +{ \ + return TypedArrayConstr_value(NAME ##_desc_idx, ctx, vthis, flags, argc, argv, r); \ +} +ALL_TYPED_ARRAYS +#undef X + +#define X(NAME) NAME ## Constr_value, +static const builtin_invoke_t TypedArray_constr[] = { ALL_TYPED_ARRAYS }; +#undef X + +#define X(NAME) L"" #NAME, +static const WCHAR *const TypedArray_name[] = { ALL_TYPED_ARRAYS }; +#undef X + +static const builtin_info_t TypedArrayConstr_info = { + .class = JSCLASS_FUNCTION, + .call = Function_value, +}; + HRESULT init_arraybuf_constructors(script_ctx_t *ctx) { static const struct { @@ -695,6 +1055,7 @@ HRESULT init_arraybuf_constructors(script_ctx_t *ctx) { L"byteOffset", DataView_get_byteOffset }, }; ArrayBufferInstance *arraybuf; + TypedArrayInstance *typedarr; DataViewInstance *view; property_desc_t desc; HRESULT hres; @@ -766,6 +1127,42 @@ HRESULT init_arraybuf_constructors(script_ctx_t *ctx)
hres = jsdisp_define_data_property(ctx->global, L"DataView", PROPF_CONFIGURABLE | PROPF_WRITABLE, jsval_obj(ctx->dataview_constr)); + if(FAILED(hres)) + return hres; + + for(i = 0; i < ARRAY_SIZE(typed_array_descs); i++) { + if(!(typedarr = calloc(1, sizeof(TypedArrayInstance)))) + return E_OUTOFMEMORY; + + hres = create_arraybuf(ctx, 0, &typedarr->buffer); + if(FAILED(hres)) { + free(typedarr); + return hres; + } + + hres = init_dispex(&typedarr->dispex, ctx, &TypedArray_info[i], ctx->object_prototype); + if(FAILED(hres)) { + jsdisp_release(&typedarr->buffer->dispex); + free(typedarr); + return hres; + } + + hres = create_builtin_constructor(ctx, TypedArray_constr[i], TypedArray_name[i], &TypedArrayConstr_info, + PROPF_CONSTR|1, &typedarr->dispex, &ctx->typedarr_constr[i]); + jsdisp_release(&typedarr->dispex); + if(FAILED(hres)) + return hres; + + hres = jsdisp_define_data_property(ctx->typedarr_constr[i], L"BYTES_PER_ELEMENT", 0, + jsval_number(typed_array_descs[i].size)); + if(FAILED(hres)) + return hres; + + hres = jsdisp_define_data_property(ctx->global, TypedArray_name[i], PROPF_CONFIGURABLE | PROPF_WRITABLE, + jsval_obj(ctx->typedarr_constr[i])); + if(FAILED(hres)) + return 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 0540bce380d..99271e74b83 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -113,12 +113,25 @@ typedef enum { JSCLASS_JSON, JSCLASS_ARRAYBUFFER, JSCLASS_DATAVIEW, + JSCLASS_INT8ARRAY, + JSCLASS_INT16ARRAY, + JSCLASS_INT32ARRAY, + JSCLASS_UINT8ARRAY, + JSCLASS_UINT16ARRAY, + JSCLASS_UINT32ARRAY, + JSCLASS_FLOAT32ARRAY, + JSCLASS_FLOAT64ARRAY, JSCLASS_MAP, JSCLASS_SET, JSCLASS_WEAKMAP, JSCLASS_HOST, + + FIRST_TYPEDARRAY_JSCLASS = JSCLASS_INT8ARRAY, + LAST_TYPEDARRAY_JSCLASS = JSCLASS_FLOAT64ARRAY, } jsclass_t;
+enum { NUM_TYPEDARRAY_TYPES = LAST_TYPEDARRAY_JSCLASS - FIRST_TYPEDARRAY_JSCLASS + 1 }; + jsdisp_t *iface_to_jsdisp(IDispatch*);
typedef HRESULT (*builtin_invoke_t)(script_ctx_t*,jsval_t,WORD,unsigned,jsval_t*,jsval_t*); @@ -320,6 +333,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*);
@@ -433,11 +447,12 @@ struct _script_ctx_t { jsdisp_t *vbarray_constr; jsdisp_t *arraybuf_constr; jsdisp_t *dataview_constr; + jsdisp_t *typedarr_constr[NUM_TYPEDARRAY_TYPES]; jsdisp_t *map_prototype; jsdisp_t *set_prototype; jsdisp_t *weakmap_prototype; }; - jsdisp_t *global_objects[25]; + jsdisp_t *global_objects[25 + NUM_TYPEDARRAY_TYPES]; }; }; C_ASSERT(RTL_SIZEOF_THROUGH_FIELD(script_ctx_t, weakmap_prototype) == RTL_SIZEOF_THROUGH_FIELD(script_ctx_t, global_objects)); @@ -577,6 +592,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/object.c b/dlls/jscript/object.c index a1ba990695b..bda4d28ecef 100644 --- a/dlls/jscript/object.c +++ b/dlls/jscript/object.c @@ -53,6 +53,14 @@ HRESULT Object_toString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned a L"[object Object]", L"[object ArrayBuffer]", L"[object Object]", + L"[object Int8Array]", + L"[object Int16Array]", + L"[object Int32Array]", + L"[object Uint8Array]", + L"[object Uint16Array]", + L"[object Uint32Array]", + L"[object Float32Array]", + L"[object Float64Array]", L"[object Object]", L"[object Object]", L"[object Object]", 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 6cacb0f2303..d8dc6763167 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -4631,7 +4631,7 @@ async_test("window own props", function() { "CompositionEvent", "ControlRangeCollection", "Coordinates", ["Crypto",11], ["CryptoOperation",11], "CSSFontFaceRule", "CSSImportRule", ["CSSKeyframeRule",10], ["CSSKeyframesRule",10], "CSSMediaRule", "CSSNamespaceRule", "CSSPageRule", "CSSRuleList", "DataTransfer", ["DataView",9,9], "Debug", ["DeviceAcceleration",11], ["DeviceMotionEvent",11], ["DeviceOrientationEvent",11], ["DeviceRotationRate",11], ["DOMError",10], "DOMException", ["DOMSettableTokenList",10], ["DOMStringList",10], ["DOMStringMap",11], - "DragEvent", ["ErrorEvent",10], "EventException", ["EXT_texture_filter_anisotropic",11], ["File",10], ["FileList",10], ["FileReader",10], ["Float32Array",10], ["Float64Array",10], + "DragEvent", ["ErrorEvent",10], "EventException", ["EXT_texture_filter_anisotropic",11], ["File",10], ["FileList",10], ["FileReader",10], ["Float32Array",9,9], ["Float64Array",9,9], "FocusEvent", ["FormData",10], "Geolocation", "GetObject", ["HTMLAllCollection",11], "HTMLAppletElement", "HTMLAreasCollection", "HTMLAudioElement", "HTMLBaseElement", "HTMLBaseFontElement", "HTMLBGSoundElement", "HTMLBlockElement", "HTMLBRElement", "HTMLCanvasElement", ["HTMLDataListElement",10], "HTMLDDElement", "HTMLDirectoryElement", "HTMLDivElement", "HTMLDListElement", "HTMLDTElement", "HTMLFieldSetElement", "HTMLFontElement", "HTMLFrameSetElement", "HTMLHeadingElement", "HTMLHRElement", "HTMLIsIndexElement", @@ -4639,7 +4639,7 @@ async_test("window own props", function() { "HTMLOptGroupElement", "HTMLParagraphElement", "HTMLParamElement", "HTMLPhraseElement", "HTMLPreElement", ["HTMLProgressElement",10], "HTMLQuoteElement", "HTMLSourceElement", "HTMLSpanElement", "HTMLTableCaptionElement", "HTMLTableColElement", "HTMLTableHeaderCellElement", "HTMLTableSectionElement", ["HTMLTrackElement",10], "HTMLUListElement", "HTMLVideoElement", ["IDBCursor",10], ["IDBCursorWithValue",10], ["IDBDatabase",10], ["IDBFactory",10], ["IDBIndex",10], ["IDBKeyRange",10], ["IDBObjectStore",10], ["IDBOpenDBRequest",10], - ["IDBRequest",10], ["IDBTransaction",10], ["IDBVersionChangeEvent",10], "ImageData", ["Int16Array",10], ["Int32Array",10], ["Int8Array",10], ["Intl",11], ["Key",11], ["KeyOperation",11], + ["IDBRequest",10], ["IDBTransaction",10], ["IDBVersionChangeEvent",10], "ImageData", ["Int16Array",9,9], ["Int32Array",9,9], ["Int8Array",9,9], ["Intl",11], ["Key",11], ["KeyOperation",11], ["KeyPair",11], "Location", "MediaError", "MediaList", ["MediaSource",11], ["MessageChannel",10], ["MessagePort",10], ["MimeType",11], ["MimeTypeArray",9,10], "MouseWheelEvent", "MSBehaviorUrnsCollection", ["MSBlobBuilder",10], "MSCompatibleInfo", "MSCompatibleInfoCollection", ["MSCSSMatrix",10], ["MSGesture",10], ["MSGestureEvent",10], ["MSGraphicsTrust",11], ["MSInputMethodContext",11], ["MSManipulationEvent",10], ["MSMediaKeyError",11], ["MSMediaKeyMessageEvent",11], ["MSMediaKeyNeededEvent",11], ["MSMediaKeys",11], ["MSMediaKeySession",11], @@ -4662,8 +4662,8 @@ async_test("window own props", function() { "SVGPatternElement", "SVGPoint", "SVGPointList", "SVGPolygonElement", "SVGPolylineElement", "SVGPreserveAspectRatio", "SVGRadialGradientElement", "SVGRect", "SVGRectElement", "SVGScriptElement", "SVGStopElement", "SVGStringList", "SVGStyleElement", "SVGSwitchElement", "SVGSymbolElement", "SVGTextElement", "SVGTextPathElement", "SVGTitleElement", "SVGTransform", "SVGTransformList", "SVGUnitTypes", "SVGUseElement", "SVGViewElement", "SVGZoomAndPan", "SVGZoomEvent", "TextEvent", "TextMetrics", "TextRangeCollection", ["TextTrack",10], - ["TextTrackCue",10], ["TextTrackCueList",10], ["TextTrackList",10], "TimeRanges", ["TrackEvent",10], ["TransitionEvent",10], "TreeWalker", ["Uint16Array",10], ["Uint32Array",10], - ["Uint8Array",10], ["Uint8ClampedArray",11], ["URL",10], ["ValidityState",10], ["VideoPlaybackQuality",11], ["WebGLActiveInfo",11], ["WebGLBuffer",11], ["WebGLContextEvent",11], + ["TextTrackCue",10], ["TextTrackCueList",10], ["TextTrackList",10], "TimeRanges", ["TrackEvent",10], ["TransitionEvent",10], "TreeWalker", ["Uint16Array",9,9], ["Uint32Array",9,9], + ["Uint8Array",9,9], ["Uint8ClampedArray",11], ["URL",10], ["ValidityState",10], ["VideoPlaybackQuality",11], ["WebGLActiveInfo",11], ["WebGLBuffer",11], ["WebGLContextEvent",11], ["WebGLFramebuffer",11], ["WebGLObject",11], ["WebGLProgram",11], ["WebGLRenderbuffer",11], ["WebGLRenderingContext",11], ["WebGLShader",11], ["WebGLShaderPrecisionFormat",11], ["WebGLTexture",11], ["WebGLUniformLocation",11], ["WEBGL_compressed_texture_s3tc",11], ["WEBGL_debug_renderer_info",11], ["WebSocket",10], "WheelEvent", ["Worker",10], ["XMLHttpRequestEventTarget",10], "XMLSerializer" diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 402be2f9d9a..87df5f86cbd 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,199 @@ 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]; + test_own_props(name, [ "BYTES_PER_ELEMENT" ]); + test_not_own_props(name, [ "from", "of" ]); + test_own_props(name + ".prototype", [ "buffer", "byteLength", "byteOffset", "length", "set", "subarray" ]); + test_not_own_props(name + ".prototype", [ + "at", "copyWithin", "entries", "every", "fill", "filter", "find", "findIndex", "forEach", + "includes", "indexOf", "join", "keys", "lastIndexOf", "map", "reduce", "reduceRight", + "reverse", "slice", "some", "sort", "toLocaleString", "toString", "values" + ]); + + 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(); + + /* methods are incompatible, even though thrown error is not explicit */ + ok(Uint16Array.prototype.subarray !== Int32Array.prototype.subarray, "Uint16Array and Int32Array have same subarray methods"); + ok(Int8Array.prototype.set !== Float32Array.prototype.set, "Int8Array and Float32Array have same set methods"); + try { + Uint8Array.prototype.set.call(arr, [12, 50]); + ok(false, "calling Uint8Array's set with Int8Array context did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_NOT_TYPEDARRAY, "calling Uint8Array's set with Int8Array context threw " + n); + } + try { + Uint32Array.prototype.subarray.call(arr2, 0); + ok(false, "calling Uint32Array's subarray with Int32Array context did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_NOT_TYPEDARRAY, "calling Uint32Array's subarray with Int32Array context threw " + n); + } });
sync_test("builtin_context", function() { @@ -2186,7 +2382,12 @@ sync_test("globals override", function() { "Error", "escape", "EvalError", + "Float32Array", + "Float64Array", "Function", + "Int8Array", + "Int16Array", + "Int32Array", "isFinite", "isNaN", "JSON", @@ -2206,6 +2407,9 @@ sync_test("globals override", function() { "String", "SyntaxError", "TypeError", + "Uint8Array", + "Uint16Array", + "Uint32Array", "unescape", "URIError", "VBArray",
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/arraybuf.c | 34 +++++++++++++++++++++-- dlls/mshtml/tests/es5.js | 58 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 2 deletions(-)
diff --git a/dlls/jscript/arraybuf.c b/dlls/jscript/arraybuf.c index bd530ec9cfd..4eb9787de7e 100644 --- a/dlls/jscript/arraybuf.c +++ b/dlls/jscript/arraybuf.c @@ -983,8 +983,38 @@ static HRESULT TypedArrayConstr_value(unsigned desc_idx, script_ctx_t *ctx, jsva if(!obj) return JS_E_TYPEDARRAY_BAD_CTOR_ARG;
- FIXME("Construction from object not implemented\n"); - return E_NOTIMPL; + if(obj->builtin_info->class == JSCLASS_ARRAYBUFFER) { + buffer = arraybuf_from_jsdisp(obj); + if(argc > 1) { + hres = to_integer(ctx, argv[1], &n); + if(FAILED(hres)) + return hres; + if(n < 0.0 || n > buffer->size) + return JS_E_TYPEDARRAY_INVALID_OFFSLEN; + offset = n; + if(offset % elem_size) + return JS_E_TYPEDARRAY_INVALID_OFFSLEN; + } + if(argc > 2 && !is_undefined(argv[2])) { + hres = to_integer(ctx, argv[2], &n); + if(FAILED(hres)) + return hres; + if(n < 0.0 || n > UINT_MAX) + return JS_E_TYPEDARRAY_INVALID_OFFSLEN; + length = n; + if(offset + length * elem_size > buffer->size) + return JS_E_TYPEDARRAY_INVALID_OFFSLEN; + }else { + length = buffer->size - offset; + if(length % elem_size) + return JS_E_TYPEDARRAY_INVALID_OFFSLEN; + length /= elem_size; + } + jsdisp_addref(&buffer->dispex); + }else { + 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)) diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 87df5f86cbd..8d807e29976 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -2127,6 +2127,7 @@ sync_test("ArrayBuffers & Views", function() { test_own_data_prop_desc(r, "length", false, false, false); test_own_data_prop_desc(r, "buffer", false, false, false);
+ buf = ArrayBuffer(34); try { new arrType(-1); ok(false, "new " + name + "(-1) did not throw exception"); @@ -2134,6 +2135,27 @@ sync_test("ArrayBuffers & Views", function() { var n = ex.number >>> 0; ok(n === JS_E_TYPEDARRAY_INVALID_OFFSLEN, "new " + name + "(-1) threw " + n); } + try { + new arrType(buf, -1); + ok(false, "new " + name + "(buf, -1) did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_TYPEDARRAY_INVALID_OFFSLEN, "new " + name + "(buf, -1) threw " + n); + } + try { + new arrType(buf, 36); + ok(false, "new " + name + "(buf, 36) did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_TYPEDARRAY_INVALID_OFFSLEN, "new " + name + "(buf, 36) threw " + n); + } + try { + new arrType(buf, 32, 4); + ok(false, "new " + name + "(buf, 32, 4) did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_TYPEDARRAY_INVALID_OFFSLEN, "new " + name + "(buf, 32, 4) threw " + n); + } try { new arrType('9'); ok(false, "new " + name + "('9') did not throw exception"); @@ -2148,6 +2170,26 @@ sync_test("ArrayBuffers & Views", function() { var n = ex.number >>> 0; ok(n === JS_E_TYPEDARRAY_BAD_CTOR_ARG, "new " + name + "(null) threw " + n); } + if(typeSz > 1) { + /* test misalignment */ + var a = typeSz >>> 1; + try { + new arrType(buf, a, 1); + ok(false, "new " + name + "(buf, " + a + ", 1) did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_TYPEDARRAY_INVALID_OFFSLEN, "new " + name + "(buf, " + a + ", 1) threw " + n); + } + a += typeSz; + var b = new ArrayBuffer(a); + try { + new arrType(b); + ok(false, "new " + name + "(new ArrayBuffer(" + a + ")) did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_TYPEDARRAY_INVALID_OFFSLEN, "new " + name + "(new ArrayBuffer(" + a + ")) threw " + n); + } + }
arr = new arrType(); ok(arr.byteLength === 0, name + "().byteLength = " + arr.byteLength); @@ -2252,6 +2294,22 @@ sync_test("ArrayBuffers & Views", function() { arr = arrType.prototype; delete arr[-1]; delete arr.foo; + + arr = arrType(buf, typeSz, 2); + name = name + "(buf, " + typeSz + ", 2)"; + ok(arr.byteLength === 2 * typeSz, name + ".byteLength = " + arr.byteLength); + ok(arr.byteOffset === typeSz, name + ".byteOffset = " + arr.byteOffset); + ok(arr.length === 2, name + ".length = " + arr.length); + ok(arr.buffer === buf, name + ".buffer = " + arr.buffer); + view = DataView(buf); + view["set" + types[i][0]](typeSz, 10, true); + ok(arr[0] === 10, "arr[0] after DataView(buf).set" + types[i][0] + " = " + arr[0]); + arr[0] = 12; + r = view["get" + types[i][0]](typeSz, true); + ok(r === 12, "DataView(buf).get" + types[i][0] + " after arr[0] set = " + r); + Object.freeze(arr); + todo_wine. + ok(Object.isFrozen(arr) === true, name + " not frozen"); }
arr = new Int16Array(2);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/arraybuf.c | 15 +++++++++++++-- dlls/jscript/jscript.h | 2 ++ dlls/mshtml/tests/es5.js | 13 +++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/dlls/jscript/arraybuf.c b/dlls/jscript/arraybuf.c index 4eb9787de7e..d36c262db91 100644 --- a/dlls/jscript/arraybuf.c +++ b/dlls/jscript/arraybuf.c @@ -171,9 +171,20 @@ static HRESULT create_arraybuf(script_ctx_t *ctx, DWORD size, ArrayBufferInstanc static HRESULT ArrayBufferConstr_isView(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { - FIXME("not implemented\n"); + BOOL ret = FALSE; + jsdisp_t *obj;
- return E_NOTIMPL; + TRACE("\n"); + + if(!r) + return S_OK; + + if(argc && is_object_instance(argv[0]) && (obj = to_jsdisp(get_object(argv[0]))) && + obj->builtin_info->class >= FIRST_VIEW_JSCLASS && obj->builtin_info->class <= LAST_VIEW_JSCLASS) + ret = TRUE; + + *r = jsval_bool(ret); + return S_OK; }
static HRESULT ArrayBufferConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 99271e74b83..b6cb22cd1f5 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -128,6 +128,8 @@ typedef enum {
FIRST_TYPEDARRAY_JSCLASS = JSCLASS_INT8ARRAY, LAST_TYPEDARRAY_JSCLASS = JSCLASS_FLOAT64ARRAY, + FIRST_VIEW_JSCLASS = JSCLASS_DATAVIEW, + LAST_VIEW_JSCLASS = JSCLASS_FLOAT64ARRAY, } jsclass_t;
enum { NUM_TYPEDARRAY_TYPES = LAST_TYPEDARRAY_JSCLASS - FIRST_TYPEDARRAY_JSCLASS + 1 }; diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 8d807e29976..76eaf455f23 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -1826,6 +1826,13 @@ sync_test("ArrayBuffers & Views", function() { test_readonly(buf, "byteLength", 10); test_own_data_prop_desc(buf, "byteLength", false, false, false);
+ ok(ArrayBuffer.isView() === false, "ArrayBuffer.isView() returned true"); + ok(ArrayBuffer.isView([]) === false, "ArrayBuffer.isView([]) returned true"); + ok(ArrayBuffer.isView({}) === false, "ArrayBuffer.isView({}) returned true"); + ok(ArrayBuffer.isView(undefined) === false, "ArrayBuffer.isView(undefined) returned true"); + ok(ArrayBuffer.isView(null) === false, "ArrayBuffer.isView(null) returned true"); + ok(ArrayBuffer.isView(buf) === false, "ArrayBuffer.isView(ArrayBuffer) returned true"); + test_own_props("DataView.prototype", [ "buffer", "byteLength", "byteOffset", "getInt8", "setInt8", "getUint8", "setUint8", @@ -1946,6 +1953,9 @@ sync_test("ArrayBuffers & Views", function() { ok(view.byteLength === 10, "DataView(buf).byteLength = " + view.byteLength); ok(view.byteOffset === 0, "DataView(buf).byteOffset = " + view.byteOffset);
+ ok(ArrayBuffer.isView(DataView) === false, "ArrayBuffer.isView(DataView) returned true"); + ok(ArrayBuffer.isView(view) === true, "ArrayBuffer.isView(DataView(buf)) returned false"); + for(i = 0; i < 10; i++) { r = view.getInt8(i); ok(r === 0, "view byte " + i + " = " + r); @@ -2080,6 +2090,8 @@ sync_test("ArrayBuffers & Views", function() { 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); + ok(ArrayBuffer.isView(buf2) === false, "ArrayBuffer.isView(buf.slice(-9)) returned true"); + ok(ArrayBuffer.isView(view2) === true, "ArrayBuffer.isView(DataView(buf.slice(-9))) returned false");
r = view2.getUint32(0); ok(r === 4294967040, "buf.slice(-9) view(1).getUint32(0) returned " + r); @@ -2204,6 +2216,7 @@ sync_test("ArrayBuffers & Views", function() { test_own_data_prop_desc(arr, "length", false, false, false); test_own_data_prop_desc(arr, "buffer", false, false, false);
+ ok(ArrayBuffer.isView(arr) === true, "ArrayBuffer.isView(" + name + "()) returned false"); Object.freeze(arr); ok(Object.isFrozen(arr) === true, name + "() not frozen");
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 | 58 ++++++++++++++++++++++++++++++++++++++-- dlls/mshtml/tests/es5.js | 47 +++++++++++++++++++++++++++++++- 2 files changed, 102 insertions(+), 3 deletions(-)
diff --git a/dlls/jscript/arraybuf.c b/dlls/jscript/arraybuf.c index d36c262db91..58c075fdfac 100644 --- a/dlls/jscript/arraybuf.c +++ b/dlls/jscript/arraybuf.c @@ -18,6 +18,7 @@
#include <limits.h> +#include <assert.h>
#include "jscript.h"
@@ -797,6 +798,32 @@ static HRESULT TypedArray_get_length(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_ return S_OK; }
+static HRESULT fill_typedarr_data_from_object(unsigned desc_idx, script_ctx_t *ctx, BYTE *data, jsdisp_t *obj, DWORD length) +{ + HRESULT hres; + jsval_t val; + UINT32 i; + + for(i = 0; i < length; i++) { + double n; + + hres = jsdisp_get_idx(obj, i, &val); + if(FAILED(hres)) { + if(hres != DISP_E_UNKNOWNNAME) + return hres; + val = jsval_undefined(); + } + + hres = to_number(ctx, val, &n); + jsval_release(val); + if(FAILED(hres)) + return hres; + typed_array_descs[desc_idx].set(&data[i * typed_array_descs[desc_idx].size], n); + } + + return S_OK; +} + static HRESULT TypedArray_set(unsigned desc_idx, script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) { @@ -1023,8 +1050,35 @@ static HRESULT TypedArrayConstr_value(unsigned desc_idx, script_ctx_t *ctx, jsva } 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(desc_idx, ctx, buffer->buf, obj, length); + 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 76eaf455f23..b7b787b9a05 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -2182,6 +2182,13 @@ sync_test("ArrayBuffers & Views", function() { var n = ex.number >>> 0; ok(n === JS_E_TYPEDARRAY_BAD_CTOR_ARG, "new " + name + "(null) threw " + n); } + try { + new arrType({}); + ok(false, "new " + name + "({}) did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_TYPEDARRAY_BAD_CTOR_ARG, "new " + name + "({}) threw " + n); + } if(typeSz > 1) { /* test misalignment */ var a = typeSz >>> 1; @@ -2308,6 +2315,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; + arr = arrType(arr2); + r = name + "(array-like object)"; + ok(arr.byteLength === 4 * typeSz, r + ".byteLength = " + arr.byteLength); + ok(arr.byteOffset === 0, r + ".byteOffset = " + arr.byteOffset); + ok(arr.length === 4, r + ".length = " + arr.length); + if(isNaN(arr[2])) { + ok(arr[0] === 1.5, r + "[0] = " + arr[0]); + ok(arr[1] === 3, r + "[1] = " + arr[1]); + ok(arr[3] === 12, r + "[3] = " + arr[3]); + }else + for(var j = 0; j < 4; j++) + ok(arr[j] === [1, 3, 0, 12][j], r + "[" + j + "] = " + arr[j]); + arr = arrType(buf, typeSz, 2); name = name + "(buf, " + typeSz + ", 2)"; ok(arr.byteLength === 2 * typeSz, name + ".byteLength = " + arr.byteLength); @@ -2323,7 +2347,28 @@ sync_test("ArrayBuffers & Views", function() { Object.freeze(arr); todo_wine. ok(Object.isFrozen(arr) === true, name + " not frozen"); - } + + arr2 = 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;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/arraybuf.c | 44 ++++++++++++++++++++++++++++++-- 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 | 55 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 101 insertions(+), 2 deletions(-)
diff --git a/dlls/jscript/arraybuf.c b/dlls/jscript/arraybuf.c index 58c075fdfac..bfd9c9e8e45 100644 --- a/dlls/jscript/arraybuf.c +++ b/dlls/jscript/arraybuf.c @@ -766,6 +766,8 @@ static inline TypedArrayInstance *typedarr_this(jsval_t vthis, unsigned desc_idx return (jsdisp && is_class(jsdisp, FIRST_TYPEDARRAY_JSCLASS + desc_idx)) ? typedarr_from_jsdisp(jsdisp) : NULL; }
+static HRESULT create_typedarr(unsigned,script_ctx_t*,ArrayBufferInstance*,DWORD,DWORD,jsdisp_t**); + static HRESULT TypedArray_get_buffer(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) { TRACE("%p\n", jsthis); @@ -840,12 +842,50 @@ static HRESULT TypedArray_subarray(unsigned desc_idx, script_ctx_t *ctx, jsval_t unsigned argc, jsval_t *argv, jsval_t *r) { TypedArrayInstance *typedarr; + DWORD begin = 0, end; + jsdisp_t *obj; + HRESULT hres; + double n;
- FIXME("not implemented\n"); + TRACE("\n");
if(!(typedarr = typedarr_this(vthis, desc_idx))) return JS_E_NOT_TYPEDARRAY; - return E_NOTIMPL; + if(!argc) + return JS_E_TYPEDARRAY_INVALID_SUBARRAY; + if(!r) + return S_OK; + + hres = to_integer(ctx, argv[0], &n); + if(FAILED(hres)) + return hres; + end = typedarr->length; + if(n < 0.0) + n += typedarr->length; + if(n >= 0.0) + begin = n < typedarr->length ? n : typedarr->length; + + if(argc > 1 && !is_undefined(argv[1])) { + hres = to_integer(ctx, argv[1], &n); + if(FAILED(hres)) + return hres; + if(n < 0.0) + n += typedarr->length; + if(n >= 0.0) { + end = n < typedarr->length ? n : typedarr->length; + end = end < begin ? begin : end; + }else + end = begin; + } + + hres = create_typedarr(desc_idx, ctx, typedarr->buffer, + typedarr->offset + begin * typed_array_descs[desc_idx].size, + end - begin, &obj); + if(FAILED(hres)) + return hres; + + *r = jsval_obj(obj); + return S_OK; }
static void TypedArray_destructor(jsdisp_t *dispex) diff --git a/dlls/jscript/error.c b/dlls/jscript/error.c index 48e9826040c..d85cb811214 100644 --- a/dlls/jscript/error.c +++ b/dlls/jscript/error.c @@ -514,6 +514,7 @@ jsdisp_t *create_builtin_error(script_ctx_t *ctx) case JS_E_PRECISION_OUT_OF_RANGE: case JS_E_INVALID_LENGTH: case JS_E_TYPEDARRAY_INVALID_OFFSLEN: + case JS_E_TYPEDARRAY_INVALID_SUBARRAY: 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 b6cb22cd1f5..4f924cd13bc 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -597,6 +597,7 @@ static inline HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, jsval_ #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_TYPEDARRAY_INVALID_SUBARRAY MAKE_JSERROR(IDS_TYPEDARRAY_INVALID_SUBARRAY) #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 91bbf09d034..6c73f045b5d 100644 --- a/dlls/jscript/jscript.rc +++ b/dlls/jscript/jscript.rc @@ -82,6 +82,7 @@ STRINGTABLE 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_TYPEDARRAY_INVALID_SUBARRAY "Invalid begin/end value in typed array subarray method" 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/resource.h b/dlls/jscript/resource.h index 0f8e6f2dc7f..416c608eb0b 100644 --- a/dlls/jscript/resource.h +++ b/dlls/jscript/resource.h @@ -80,6 +80,7 @@ #define IDS_TYPEDARRAY_BAD_CTOR_ARG 0x13DA #define IDS_NOT_TYPEDARRAY 0x13DB #define IDS_TYPEDARRAY_INVALID_OFFSLEN 0x13DC +#define IDS_TYPEDARRAY_INVALID_SUBARRAY 0x13DD #define IDS_NOT_DATAVIEW 0x13DF #define IDS_DATAVIEW_NO_ARGUMENT 0x13E0 #define IDS_DATAVIEW_INVALID_ACCESS 0x13E1 diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index b7b787b9a05..cdca63090b5 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -36,6 +36,7 @@ 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_TYPEDARRAY_INVALID_SUBARRAY = 0x800a13dd; var JS_E_NOT_DATAVIEW = 0x800a13df; var JS_E_DATAVIEW_NO_ARGUMENT = 0x800a13e0; var JS_E_DATAVIEW_INVALID_ACCESS = 0x800a13e1; @@ -2332,6 +2333,55 @@ sync_test("ArrayBuffers & Views", function() { for(var j = 0; j < 4; j++) ok(arr[j] === [1, 3, 0, 12][j], r + "[" + j + "] = " + arr[j]);
+ arr = arrType(10); + r = name + "(10)"; + try { + arr.subarray.call(null, 0); + ok(false, r + ": calling subarray with null context did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_NOT_TYPEDARRAY, r + ": calling subarray with null context threw " + n); + } + try { + arr.subarray.call({}, 0); + ok(false, r + ": calling subarray with an object context did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_NOT_TYPEDARRAY, r + ": calling subarray with an object context threw " + n); + } + try { + arr.subarray(); + ok(false, r + " subarray() did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_TYPEDARRAY_INVALID_SUBARRAY, r + " subarray() threw " + n); + } + arr2 = arr.subarray(4); + ok(arr2.byteLength === 6 * typeSz, r + ".subarray(4).byteLength = " + arr2.byteLength); + ok(arr2.byteOffset === 4 * typeSz, r + ".subarray(4).byteOffset = " + arr2.byteOffset); + ok(arr2.length === 6, r + ".subarray(4).length = " + arr2.length); + ok(arr2.buffer === arr.buffer, r + ".subarray(4).buffer = " + arr2.buffer); + arr2 = arr.subarray(4, 2); + ok(arr2.byteLength === 0, r + ".subarray(4, 2).byteLength = " + arr2.byteLength); + ok(arr2.byteOffset === 4 * typeSz, r + ".subarray(4, 2).byteOffset = " + arr2.byteOffset); + ok(arr2.length === 0, r + ".subarray(4, 2).length = " + arr2.length); + ok(arr2.buffer === arr.buffer, r + ".subarray(4, 2).buffer = " + arr2.buffer); + arr2 = arr.subarray(-3, 100); + ok(arr2.byteLength === 3 * typeSz, r + ".subarray(-3, 100).byteLength = " + arr2.byteLength); + ok(arr2.byteOffset === 7 * typeSz, r + ".subarray(-3, 100).byteOffset = " + arr2.byteOffset); + ok(arr2.length === 3, r + ".subarray(-3, 100).length = " + arr2.length); + ok(arr2.buffer === arr.buffer, r + ".subarray(-3, 100).buffer = " + arr2.buffer); + arr2 = arr.subarray(42, -1); + ok(arr2.byteLength === 0, r + ".subarray(42, -1).byteLength = " + arr2.byteLength); + ok(arr2.byteOffset === 10 * typeSz, r + ".subarray(42, -1).byteOffset = " + arr2.byteOffset); + ok(arr2.length === 0, r + ".subarray(42, -1).length = " + arr2.length); + ok(arr2.buffer === arr.buffer, r + ".subarray(42, -1).buffer = " + arr2.buffer); + arr2 = arr.subarray(2, -3); + ok(arr2.byteLength === 5 * typeSz, r + ".subarray(2, -3).byteLength = " + arr2.byteLength); + ok(arr2.byteOffset === 2 * typeSz, r + ".subarray(2, -3).byteOffset = " + arr2.byteOffset); + ok(arr2.length === 5, r + ".subarray(2, -3).length = " + arr2.length); + ok(arr2.buffer === arr.buffer, r + ".subarray(2, -3).buffer = " + arr2.buffer); + arr = arrType(buf, typeSz, 2); name = name + "(buf, " + typeSz + ", 2)"; ok(arr.byteLength === 2 * typeSz, name + ".byteLength = " + arr.byteLength); @@ -2353,6 +2403,11 @@ sync_test("ArrayBuffers & Views", function() { 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); + arr2 = arr.subarray(undefined, "1"); + ok(arr2.byteLength === typeSz, name + " subarray(undefined, '1').byteLength = " + arr2.byteLength); + ok(arr2.byteOffset === arr.byteOffset, name + " subarray(undefined, '1').byteOffset = " + arr2.byteOffset); + ok(arr2.length === 1, name + " subarray(undefined, '1').length = " + arr2.length); + ok(arr2.buffer === arr.buffer, name + " subarray(undefined, '1').buffer = " + arr2.buffer); }
arr = new Float32Array(3);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/arraybuf.c | 74 +++++++++++++++++++++++++++++- 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 | 97 +++++++++++++++++++++++++++++++++++++++- 6 files changed, 171 insertions(+), 4 deletions(-)
diff --git a/dlls/jscript/arraybuf.c b/dlls/jscript/arraybuf.c index bfd9c9e8e45..560cb46ed5d 100644 --- a/dlls/jscript/arraybuf.c +++ b/dlls/jscript/arraybuf.c @@ -830,12 +830,82 @@ static HRESULT TypedArray_set(unsigned desc_idx, script_ctx_t *ctx, jsval_t vthi unsigned argc, jsval_t *argv, jsval_t *r) { TypedArrayInstance *typedarr; + DWORD begin = 0, size; + BYTE *dest, *data; + IDispatch *disp; + jsdisp_t *obj; + HRESULT hres; + jsval_t val; + UINT32 len; + double n;
- FIXME("not implemented\n"); + TRACE("\n");
if(!(typedarr = typedarr_this(vthis, desc_idx))) return JS_E_NOT_TYPEDARRAY; - return E_NOTIMPL; + if(!argc) + return JS_E_TYPEDARRAY_INVALID_SOURCE; + + hres = to_object(ctx, argv[0], &disp); + if(FAILED(hres)) + return JS_E_TYPEDARRAY_INVALID_SOURCE; + + if(!(obj = to_jsdisp(disp))) { + FIXME("Non-JS array object\n"); + hres = JS_E_TYPEDARRAY_INVALID_SOURCE; + goto done; + } + + hres = jsdisp_propget_name(obj, L"length", &val); + if(FAILED(hres)) + goto done; + + hres = to_uint32(ctx, val, &len); + jsval_release(val); + if(FAILED(hres)) + goto done; + + if(argc > 1) { + hres = to_integer(ctx, argv[1], &n); + if(FAILED(hres)) + goto done; + if(n < 0.0 || n > typedarr->length) { + hres = JS_E_TYPEDARRAY_INVALID_OFFSLEN; + goto done; + } + begin = n; + } + + if(len > typedarr->length - begin) { + hres = JS_E_TYPEDARRAY_INVALID_OFFSLEN; + goto done; + } + size = len * typed_array_descs[desc_idx].size; + dest = data = &typedarr->buffer->buf[typedarr->offset + begin * typed_array_descs[desc_idx].size]; + + /* If they overlap, make a temporary copy */ + if(obj->builtin_info->class >= FIRST_TYPEDARRAY_JSCLASS && obj->builtin_info->class <= LAST_TYPEDARRAY_JSCLASS) { + TypedArrayInstance *src_arr = typedarr_from_jsdisp(obj); + const BYTE *src = src_arr->buffer->buf + src_arr->offset; + + if(dest < src + len * typed_array_descs[obj->builtin_info->class - FIRST_TYPEDARRAY_JSCLASS].size && + dest + size > src) { + if(!(data = malloc(size))) { + hres = E_OUTOFMEMORY; + goto done; + } + } + } + + hres = fill_typedarr_data_from_object(desc_idx, ctx, data, obj, len); + if(SUCCEEDED(hres) && dest != data) { + memcpy(dest, data, size); + free(data); + } + +done: + IDispatch_Release(disp); + return hres; }
static HRESULT TypedArray_subarray(unsigned desc_idx, script_ctx_t *ctx, jsval_t vthis, WORD flags, diff --git a/dlls/jscript/error.c b/dlls/jscript/error.c index d85cb811214..b387972a5f4 100644 --- a/dlls/jscript/error.c +++ b/dlls/jscript/error.c @@ -499,6 +499,7 @@ jsdisp_t *create_builtin_error(script_ctx_t *ctx) case JS_E_NONWRITABLE_MODIFIED: case JS_E_TYPEDARRAY_BAD_CTOR_ARG: case JS_E_NOT_TYPEDARRAY: + case JS_E_TYPEDARRAY_INVALID_SOURCE: case JS_E_NOT_DATAVIEW: case JS_E_DATAVIEW_NO_ARGUMENT: case JS_E_WRONG_THIS: diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 4f924cd13bc..5c3478f1295 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -598,6 +598,7 @@ static inline HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, jsval_ #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_TYPEDARRAY_INVALID_SUBARRAY MAKE_JSERROR(IDS_TYPEDARRAY_INVALID_SUBARRAY) +#define JS_E_TYPEDARRAY_INVALID_SOURCE MAKE_JSERROR(IDS_TYPEDARRAY_INVALID_SOURCE) #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 6c73f045b5d..cbddcb90058 100644 --- a/dlls/jscript/jscript.rc +++ b/dlls/jscript/jscript.rc @@ -83,6 +83,7 @@ STRINGTABLE IDS_TYPEDARRAY_BAD_CTOR_ARG "Typed array constructor argument is invalid" IDS_TYPEDARRAY_INVALID_OFFSLEN "Invalid offset/length when creating typed array" IDS_TYPEDARRAY_INVALID_SUBARRAY "Invalid begin/end value in typed array subarray method" + IDS_TYPEDARRAY_INVALID_SOURCE "Invalid source in typed array set" 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/resource.h b/dlls/jscript/resource.h index 416c608eb0b..22bc3a551e3 100644 --- a/dlls/jscript/resource.h +++ b/dlls/jscript/resource.h @@ -81,6 +81,7 @@ #define IDS_NOT_TYPEDARRAY 0x13DB #define IDS_TYPEDARRAY_INVALID_OFFSLEN 0x13DC #define IDS_TYPEDARRAY_INVALID_SUBARRAY 0x13DD +#define IDS_TYPEDARRAY_INVALID_SOURCE 0x13DE #define IDS_NOT_DATAVIEW 0x13DF #define IDS_DATAVIEW_NO_ARGUMENT 0x13E0 #define IDS_DATAVIEW_INVALID_ACCESS 0x13E1 diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index cdca63090b5..5be512671e5 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -37,6 +37,7 @@ var JS_E_TYPEDARRAY_BAD_CTOR_ARG = 0x800a13da; var JS_E_NOT_TYPEDARRAY = 0x800a13db; var JS_E_TYPEDARRAY_INVALID_OFFSLEN = 0x800a13dc; var JS_E_TYPEDARRAY_INVALID_SUBARRAY = 0x800a13dd; +var JS_E_TYPEDARRAY_INVALID_SOURCE = 0x800a13de; var JS_E_NOT_DATAVIEW = 0x800a13df; var JS_E_DATAVIEW_NO_ARGUMENT = 0x800a13e0; var JS_E_DATAVIEW_INVALID_ACCESS = 0x800a13e1; @@ -2382,6 +2383,87 @@ sync_test("ArrayBuffers & Views", function() { ok(arr2.length === 5, r + ".subarray(2, -3).length = " + arr2.length); ok(arr2.buffer === arr.buffer, r + ".subarray(2, -3).buffer = " + arr2.buffer);
+ try { + arr.set.call(null, [1]); + ok(false, name + ": calling set with null context did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_NOT_TYPEDARRAY, name + ": calling set with null context threw " + n); + } + try { + arr.set.call({}, [1]); + ok(false, name + ": calling set with an object context did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_NOT_TYPEDARRAY, name + ": calling set with an object context threw " + n); + } + try { + arr.set(); + ok(false, name + ".set() did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_TYPEDARRAY_INVALID_SOURCE, name + ".set() threw " + n); + } + try { + arr.set(null); + ok(false, name + ".set(null) did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_TYPEDARRAY_INVALID_SOURCE, name + ".set(null) threw " + n); + } + try { + arr.set([1,2,3], 8); + ok(false, name + ".set([1,2,3], 8) did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_TYPEDARRAY_INVALID_OFFSLEN, name + ".set([1,2,3], 8) threw " + n); + } + try { + arr.set([99], -3); + ok(false, name + ".set([99], -3) did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + ok(n === JS_E_TYPEDARRAY_INVALID_OFFSLEN, name + ".set([99], -3) threw " + n); + } + + r = arr.set(5); + ok(r === undefined, name + ".set(5) returned " + r); + for(var j = 0; j < 10; j++) + ok(arr[j] === 0, name + ".set(5): arr[" + j + "] = " + arr[j]); + + r = arr.set({}); + ok(r === undefined, name + ".set({}) returned " + r); + for(var j = 0; j < 10; j++) + ok(arr[j] === 0, name + ".set({}): arr[" + j + "] = " + arr[j]); + + r = arr.set("12"); + ok(r === undefined, name + ".set('12') returned " + r); + for(var j = 0; j < 10; j++) + ok(arr[j] === [ 1, 2, 0, 0, 0, 0, 0, 0, 0, 0 ][j], name + ".set('12'): arr[" + j + "] = " + arr[j]); + + arr2 = { length: 2 }; + arr2[0] = 9; + arr2[1] = 7; + r = arr.set(arr2); + ok(r === undefined, name + ".set(array-like obj) returned " + r); + for(var j = 0; j < 10; j++) + ok(arr[j] === [ 9, 7, 0, 0, 0, 0, 0, 0, 0, 0 ][j], name + ".set(array-like obj): arr[" + j + "] = " + arr[j]); + + r = arr.set([12, 10, 11], 3); + ok(r === undefined, name + ".set([12, 10, 11], 3) returned " + r); + for(var j = 0; j < 10; j++) + ok(arr[j] === [ 9, 7, 0, 12, 10, 11, 0, 0, 0, 0 ][j], name + ".set([12, 10, 11], 3): arr[" + j + "] = " + arr[j]); + + r = arr.set(arr.subarray(4, 6), 5); + ok(r === undefined, name + ".set(arr.subarray(4, 2), 5) returned " + r); + for(var j = 0; j < 10; j++) + ok(arr[j] === [ 9, 7, 0, 12, 10, 10, 11, 0, 0, 0 ][j], name + ".set(arr.subarray(4, 2), 5): arr[" + j + "] = " + arr[j]); + + r = arr.set(arr.subarray(3, 7), 2); + ok(r === undefined, name + ".set(arr.subarray(3, 7), 2) returned " + r); + for(var j = 0; j < 10; j++) + ok(arr[j] === [ 9, 7, 12, 10, 10, 11, 11, 0, 0, 0 ][j], name + ".set(arr.subarray(3, 7), 2): arr[" + j + "] = " + arr[j]); + arr = arrType(buf, typeSz, 2); name = name + "(buf, " + typeSz + ", 2)"; ok(arr.byteLength === 2 * typeSz, name + ".byteLength = " + arr.byteLength); @@ -2437,8 +2519,19 @@ sync_test("ArrayBuffers & Views", function() { 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(); + arr = new Int8Array(12); + arr.set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]); + for(var j = 0; j < 12; j++) + ok(arr[j] === j + 1, "sequential arr[" + j + "] = " + arr[j]); + arr2 = new Int32Array(arr.buffer); + ok(arr2.buffer === arr.buffer, "arr2.buffer = " + arr2.buffer); + for(var j = 0; j < 3; j++) + ok(arr2[j] === [ 0x04030201, 0x08070605, 0x0c0b0a09 ][j], "sequential 32-bit arr[" + j + "] = " + arr2[j]); + + /* test overlap */ + arr2.set(arr.subarray(1, 4)); + for(var j = 0; j < 3; j++) + ok(arr2[j] === j + 2, "arr with overlap[" + j + "] = " + arr[j]);
/* methods are incompatible, even though thrown error is not explicit */ ok(Uint16Array.prototype.subarray !== Int32Array.prototype.subarray, "Uint16Array and Int32Array have same subarray methods");
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/arraybuf.c | 11 +++++++++++ dlls/jscript/jscript.h | 1 + dlls/jscript/object.c | 1 + dlls/mshtml/tests/documentmode.js | 2 +- dlls/mshtml/tests/es5.js | 13 +++++++++++++ 5 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/dlls/jscript/arraybuf.c b/dlls/jscript/arraybuf.c index 560cb46ed5d..0ee3e79516c 100644 --- a/dlls/jscript/arraybuf.c +++ b/dlls/jscript/arraybuf.c @@ -17,6 +17,7 @@ */
+#include <math.h> #include <limits.h> #include <assert.h>
@@ -732,12 +733,21 @@ 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 void set_clamped_u8(void *p, double v) +{ + if(!isfinite(v)) + *(UINT8 *)p = (v == INFINITY ? 255 : 0); + else + *(UINT8 *)p = (v >= 255.0 ? 255 : v <= 0 ? 0 : lround(v)); +} + /* NOTE: Keep in sync with the JSCLASS ordering of typed arrays */ #define ALL_TYPED_ARRAYS \ X(Int8Array) \ X(Int16Array) \ X(Int32Array) \ X(Uint8Array) \ +X(Uint8ClampedArray) \ X(Uint16Array) \ X(Uint32Array) \ X(Float32Array) \ @@ -754,6 +764,7 @@ static const struct typed_array_desc typed_array_descs[NUM_TYPEDARRAY_TYPES] = { [Int16Array_desc_idx] = { 2, get_s16, set_s16 }, [Int32Array_desc_idx] = { 4, get_s32, set_s32 }, [Uint8Array_desc_idx] = { 1, get_u8, set_u8 }, + [Uint8ClampedArray_desc_idx] = { 1, get_u8, set_clamped_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 }, diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 5c3478f1295..a1f2f80205a 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -117,6 +117,7 @@ typedef enum { JSCLASS_INT16ARRAY, JSCLASS_INT32ARRAY, JSCLASS_UINT8ARRAY, + JSCLASS_UINT8CLAMPEDARRAY, JSCLASS_UINT16ARRAY, JSCLASS_UINT32ARRAY, JSCLASS_FLOAT32ARRAY, diff --git a/dlls/jscript/object.c b/dlls/jscript/object.c index bda4d28ecef..836b49e684c 100644 --- a/dlls/jscript/object.c +++ b/dlls/jscript/object.c @@ -57,6 +57,7 @@ HRESULT Object_toString(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned a L"[object Int16Array]", L"[object Int32Array]", L"[object Uint8Array]", + L"[object Uint8ClampedArray]", L"[object Uint16Array]", L"[object Uint32Array]", L"[object Float32Array]", diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index d8dc6763167..19baab64076 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -4663,7 +4663,7 @@ async_test("window own props", function() { "SVGScriptElement", "SVGStopElement", "SVGStringList", "SVGStyleElement", "SVGSwitchElement", "SVGSymbolElement", "SVGTextElement", "SVGTextPathElement", "SVGTitleElement", "SVGTransform", "SVGTransformList", "SVGUnitTypes", "SVGUseElement", "SVGViewElement", "SVGZoomAndPan", "SVGZoomEvent", "TextEvent", "TextMetrics", "TextRangeCollection", ["TextTrack",10], ["TextTrackCue",10], ["TextTrackCueList",10], ["TextTrackList",10], "TimeRanges", ["TrackEvent",10], ["TransitionEvent",10], "TreeWalker", ["Uint16Array",9,9], ["Uint32Array",9,9], - ["Uint8Array",9,9], ["Uint8ClampedArray",11], ["URL",10], ["ValidityState",10], ["VideoPlaybackQuality",11], ["WebGLActiveInfo",11], ["WebGLBuffer",11], ["WebGLContextEvent",11], + ["Uint8Array",9,9], ["Uint8ClampedArray",9,10], ["URL",10], ["ValidityState",10], ["VideoPlaybackQuality",11], ["WebGLActiveInfo",11], ["WebGLBuffer",11], ["WebGLContextEvent",11], ["WebGLFramebuffer",11], ["WebGLObject",11], ["WebGLProgram",11], ["WebGLRenderbuffer",11], ["WebGLRenderingContext",11], ["WebGLShader",11], ["WebGLShaderPrecisionFormat",11], ["WebGLTexture",11], ["WebGLUniformLocation",11], ["WEBGL_compressed_texture_s3tc",11], ["WEBGL_debug_renderer_info",11], ["WebSocket",10], "WheelEvent", ["Worker",10], ["XMLHttpRequestEventTarget",10], "XMLSerializer" diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 5be512671e5..b426ab347c4 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -2550,6 +2550,18 @@ sync_test("ArrayBuffers & Views", function() { var n = ex.number >>> 0; ok(n === JS_E_NOT_TYPEDARRAY, "calling Uint32Array's subarray with Int32Array context threw " + n); } + + /* clamped array */ + arr = new Uint8ClampedArray(7); + arr2 = new Uint8Array(7); + arr.set ([42, -1, 999, 0.9, NaN, Infinity, -Infinity]); + arr2.set([42, -1, 999, 0.9, NaN, Infinity, -Infinity]); + for(var j = 0; j < 7; j++) { + ok(arr[j] === [42, 0, 255, 1, 0, 255, 0][j], "clamped arr[" + j + "] = " + arr[j]); + ok(arr2[j] === [42, 255, 231, 0, 0, 0, 0][j], "non-clamped arr[" + j + "] = " + arr2[j]); + } + r = Object.prototype.toString.call(arr); + ok(r === "[object Uint8ClampedArray]", "Object toString for Uint8ClampedArray = " + r); });
sync_test("builtin_context", function() { @@ -2672,6 +2684,7 @@ sync_test("globals override", function() { "SyntaxError", "TypeError", "Uint8Array", + "Uint8ClampedArray", "Uint16Array", "Uint32Array", "unescape",
On Wed Oct 29 20:40:30 2025 +0000, Gabriel Ivăncescu wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/9275/diffs?diff_id=219575&start_sha=69d8336f45e87b038001e8429536b1761033b0bc#f985ae8bae507385ac1ba05103ba3974f1ca0875_730_744)
It’s better, thanks, but I think we can still avoid some more indirection. I also think the commit adding the initial stubs is larger than it needs to be, it could use more splitting. It would also be nice to have `test_own_props` tests in documentmode.js instead of its ad-hoc version in es5.js.
I gave it a try and will create a separate MR for it. The core part is mostly a stripped-down version of your big commit, so I hope it won’t be too bad to rebase and build on incrementally from there.